From c9c6976344a5302968fbc36a7cd9c9d0f716b9f1 Mon Sep 17 00:00:00 2001 From: elasota Date: Thu, 12 Dec 2019 23:37:40 -0500 Subject: [PATCH] Working up to start of menu loading --- GpApp/Environ.cpp | 9 +- GpApp/GliderProtos.h | 4 +- GpApp/GliderStructs.h | 70 ++-- GpApp/GpApp.vcxproj | 30 ++ GpApp/GpApp.vcxproj.filters | 86 +++++ GpApp/HouseIO.cpp | 306 +++++++++++++++++- GpApp/SelectHouse.cpp | 52 +-- GpApp/Sound.cpp | 163 ++++------ GpApp/SoundSync.h | 15 + GpApp/SoundSync_Win32.cpp | 31 ++ GpD3D/GpFileSystem_Win32.cpp | 109 ++++++- GpD3D/GpFileSystem_Win32.h | 1 + PictChecker/PictChecker.cpp | 220 ++++++------- PortabilityLayer/FileManager.cpp | 34 +- PortabilityLayer/FileManager.h | 8 +- PortabilityLayer/FilePos.h | 9 + PortabilityLayer/HostDirectoryCursor.h | 11 + PortabilityLayer/HostFileSystem.h | 4 +- PortabilityLayer/IOStream.h | 6 +- PortabilityLayer/MacLatin.h | 14 + PortabilityLayer/MacLatin1.cpp | 95 ++++++ PortabilityLayer/PLAliases.cpp | 5 +- PortabilityLayer/PLCore.cpp | 149 ++++++++- PortabilityLayer/PLCore.h | 14 +- PortabilityLayer/PLMenus.cpp | 3 +- PortabilityLayer/PLMovies.cpp | 4 +- PortabilityLayer/PLQuickdraw.cpp | 9 +- PortabilityLayer/PLQuickdraw.h | 40 +-- PortabilityLayer/PLResourceManager.cpp | 70 ++-- PortabilityLayer/PLResources.cpp | 17 +- PortabilityLayer/PLStringCompare.cpp | 73 ++++- PortabilityLayer/PortabilityLayer.vcxproj | 4 + .../PortabilityLayer.vcxproj.filters | 12 + PortabilityLayer/ResTypeIDCodec.h | 8 +- PortabilityLayer/VirtualDirectory.h | 29 +- 35 files changed, 1316 insertions(+), 398 deletions(-) create mode 100644 GpApp/SoundSync.h create mode 100644 GpApp/SoundSync_Win32.cpp create mode 100644 PortabilityLayer/FilePos.h create mode 100644 PortabilityLayer/HostDirectoryCursor.h create mode 100644 PortabilityLayer/MacLatin.h create mode 100644 PortabilityLayer/MacLatin1.cpp diff --git a/GpApp/Environ.cpp b/GpApp/Environ.cpp index eb03bb6..e744e8f 100644 --- a/GpApp/Environ.cpp +++ b/GpApp/Environ.cpp @@ -191,7 +191,8 @@ Boolean DoWeHaveSoundManager3 (void) Boolean DoWeHaveQuickTime (void) { - return true; + PL_NotYetImplemented_TODO(); + return false; } //-------------------------------------------------------------- DoWeHaveDragManager @@ -214,14 +215,14 @@ short WhatsOurDepth (void) { case PortabilityLayer::PixelFormat_8BitCustom: case PortabilityLayer::PixelFormat_8BitStandard: - return 8; + return 8; case PortabilityLayer::PixelFormat_RGB555: - return 16; + return 16; case PortabilityLayer::PixelFormat_RGB24: case PortabilityLayer::PixelFormat_RGB32: return 32; default: - return 0; + return 0; } } diff --git a/GpApp/GliderProtos.h b/GpApp/GliderProtos.h index 45bfdc5..de12d8d 100644 --- a/GpApp/GliderProtos.h +++ b/GpApp/GliderProtos.h @@ -446,9 +446,7 @@ void DoSettingsMain (void); // --- Settings.c void PlayPrioritySound (SInt16, SInt16); // --- Sound.c void FlushAnyTriggerPlaying (void); -void PlaySound0 (SInt16, SInt16); -void PlaySound1 (SInt16, SInt16); -void PlaySound2 (SInt16, SInt16); +void PlayExclusiveSoundChannel (SInt16, SInt16, SInt16, SInt16); OSErr LoadTriggerSound (SInt16); void DumpTriggerSound (void); void InitSound (void); diff --git a/GpApp/GliderStructs.h b/GpApp/GliderStructs.h index 3c569ba..e3f69a2 100644 --- a/GpApp/GliderStructs.h +++ b/GpApp/GliderStructs.h @@ -11,7 +11,7 @@ typedef struct { Point topLeft; // 4 - short distance; // 2 + int16_t distance; // 2 Boolean initial; // 1 Boolean state; // 1 F. lf. dn. rt. up Byte vector; // 1 | x | x | x | x | 8 | 4 | 2 | 1 | @@ -21,14 +21,14 @@ typedef struct typedef struct { Rect bounds; // 8 - short pict; // 2 + int16_t pict; // 2 } furnitureType; // total = 10 typedef struct { Point topLeft; // 4 - short length; // 2 grease spill - short points; // 2 invis bonus + int16_t length; // 2 grease spill + int16_t points; // 2 invis bonus Boolean state; // 1 Boolean initial; // 1 } bonusType; // total = 10 @@ -36,8 +36,8 @@ typedef struct typedef struct { Point topLeft; // 4 - short tall; // 2 invis transport - short where; // 2 + int16_t tall; // 2 invis transport + int16_t where; // 2 Byte who; // 1 Byte wide; // 1 } transportType; // total = 10 @@ -45,8 +45,8 @@ typedef struct typedef struct { Point topLeft; // 4 - short delay; // 2 - short where; // 2 + int16_t delay; // 2 + int16_t where; // 2 Byte who; // 1 Byte type; // 1 } switchType; // total = 10 @@ -54,7 +54,7 @@ typedef struct typedef struct { Point topLeft; // 4 - short length; // 2 + int16_t length; // 2 Byte byte0; // 1 Byte byte1; // 1 Boolean initial; // 1 @@ -64,7 +64,7 @@ typedef struct typedef struct { Point topLeft; // 4 - short height; // 2 toaster, pict ID + int16_t height; // 2 toaster, pict ID Byte byte0; // 1 Byte delay; // 1 Boolean initial; // 1 @@ -74,7 +74,7 @@ typedef struct typedef struct { Point topLeft; // 4 - short length; // 2 + int16_t length; // 2 Byte delay; // 1 Byte byte0; // 1 Boolean initial; // 1 @@ -84,12 +84,12 @@ typedef struct typedef struct { Rect bounds; // 8 - short pict; // 2 + int16_t pict; // 2 } clutterType; // total = 10 typedef struct { - short what; // 2 + int16_t what; // 2 union { blowerType a; @@ -110,25 +110,25 @@ typedef struct Str15 names[kMaxScores]; // 16 * 10 = 160 Int32 scores[kMaxScores]; // 4 * 10 = 40 UInt32 timeStamps[kMaxScores]; // 4 * 10 = 40 - short levels[kMaxScores]; // 2 * 10 = 20 + int16_t levels[kMaxScores]; // 2 * 10 = 20 } scoresType; // total = 292 typedef struct { - short version; // 2 - short wasStarsLeft; // 2 + int16_t version; // 2 + int16_t wasStarsLeft; // 2 UInt32 timeStamp; // 4 Point where; // 4 Int32 score; // 4 Int32 unusedLong; // 4 Int32 unusedLong2; // 4 - short energy; // 2 - short bands; // 2 - short roomNumber; // 2 - short gliderState; // 2 - short numGliders; // 2 - short foil; // 2 - short unusedShort; // 2 + int16_t energy; // 2 + int16_t bands; // 2 + int16_t roomNumber; // 2 + int16_t gliderState; // 2 + int16_t numGliders; // 2 + int16_t foil; // 2 + int16_t unusedShort; // 2 Boolean facing; // 1 Boolean showFoil; // 1 } gameType; // total = 40 @@ -166,25 +166,25 @@ typedef struct typedef struct { Str27 name; // 28 - short bounds; // 2 + int16_t bounds; // 2 Byte leftStart; // 1 Byte rightStart; // 1 Byte unusedByte; // 1 Boolean visited; // 1 - short background; // 2 - short tiles[kNumTiles]; // 2 * 8 - short floor, suite; // 2 + 2 - short openings; // 2 - short numObjects; // 2 + int16_t background; // 2 + int16_t tiles[kNumTiles]; // 2 * 8 + int16_t floor, suite; // 2 + 2 + int16_t openings; // 2 + int16_t numObjects; // 2 objectType objects[kMaxRoomObs]; // 24 * 12 } roomType, *roomPtr; // total = 348 typedef struct { - short version; // 2 - short unusedShort; // 2 - long timeStamp; // 4 - long flags; // 4 (bit 0 = wardBit) + int16_t version; // 2 + int16_t unusedShort; // 2 + int32_t timeStamp; // 4 + int32_t flags; // 4 (bit 0 = wardBit) Point initial; // 4 Str255 banner; // 256 Str255 trailer; // 256 @@ -192,8 +192,8 @@ typedef struct gameType savedGame; // 40 Boolean hasGame; // 1 Boolean unusedBoolean; // 1 - short firstRoom; // 2 - short nRooms; // 2 + int16_t firstRoom; // 2 + int16_t nRooms; // 2 roomType rooms[1]; // 348 * nRooms } houseType, *housePtr, **houseHand; // total = 866 + diff --git a/GpApp/GpApp.vcxproj b/GpApp/GpApp.vcxproj index b492b47..c7a91c9 100644 --- a/GpApp/GpApp.vcxproj +++ b/GpApp/GpApp.vcxproj @@ -182,6 +182,7 @@ + @@ -198,6 +199,35 @@ {6ec62b0f-9353-40a4-a510-3788f1368b33} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GpApp/GpApp.vcxproj.filters b/GpApp/GpApp.vcxproj.filters index 10d281f..161a4c3 100644 --- a/GpApp/GpApp.vcxproj.filters +++ b/GpApp/GpApp.vcxproj.filters @@ -210,5 +210,91 @@ Source Files + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/GpApp/HouseIO.cpp b/GpApp/HouseIO.cpp index 9114376..ddc9821 100644 --- a/GpApp/HouseIO.cpp +++ b/GpApp/HouseIO.cpp @@ -313,6 +313,302 @@ Boolean SaveHouseAs (void) // With a house open, this function reads in the actual bits of dataÉ // into memory. +void ByteSwapPoint(Point *point) +{ + PortabilityLayer::ByteSwap::BigInt16(point->h); + PortabilityLayer::ByteSwap::BigInt16(point->v); +} + +void ByteSwapRect(Rect *rect) +{ + PortabilityLayer::ByteSwap::BigInt16(rect->top); + PortabilityLayer::ByteSwap::BigInt16(rect->left); + PortabilityLayer::ByteSwap::BigInt16(rect->bottom); + PortabilityLayer::ByteSwap::BigInt16(rect->right); +} + +void ByteSwapScores(scoresType *scores) +{ + for (int i = 0; i < kMaxScores; i++) + PortabilityLayer::ByteSwap::BigInt32(scores->scores[i]); + + for (int i = 0; i < kMaxScores; i++) + PortabilityLayer::ByteSwap::BigUInt32(scores->timeStamps[i]); + + for (int i = 0; i < kMaxScores; i++) + PortabilityLayer::ByteSwap::BigInt16(scores->levels[i]); +} + +void ByteSwapSavedGame(gameType *game) +{ + PortabilityLayer::ByteSwap::BigInt16(game->version); + PortabilityLayer::ByteSwap::BigInt16(game->wasStarsLeft); + PortabilityLayer::ByteSwap::BigUInt32(game->timeStamp); + ByteSwapPoint(&game->where); + PortabilityLayer::ByteSwap::BigInt32(game->score); + PortabilityLayer::ByteSwap::BigInt32(game->unusedLong); + PortabilityLayer::ByteSwap::BigInt32(game->unusedLong2); + PortabilityLayer::ByteSwap::BigInt16(game->energy); + PortabilityLayer::ByteSwap::BigInt16(game->bands); + + PortabilityLayer::ByteSwap::BigInt16(game->roomNumber); + PortabilityLayer::ByteSwap::BigInt16(game->gliderState); + PortabilityLayer::ByteSwap::BigInt16(game->numGliders); + PortabilityLayer::ByteSwap::BigInt16(game->foil); + PortabilityLayer::ByteSwap::BigInt16(game->unusedShort); +} + +void ByteSwapBlower(blowerType *blower) +{ + ByteSwapPoint(&blower->topLeft); + PortabilityLayer::ByteSwap::BigInt16(blower->distance); +} + +void ByteSwapFurniture(furnitureType *furniture) +{ + ByteSwapRect(&furniture->bounds); + PortabilityLayer::ByteSwap::BigInt16(furniture->pict); +} + +void ByteSwapBonus(bonusType *bonus) +{ + ByteSwapPoint(&bonus->topLeft); + PortabilityLayer::ByteSwap::BigInt16(bonus->length); + PortabilityLayer::ByteSwap::BigInt16(bonus->points); +} + +void ByteSwapTransport(transportType *transport) +{ + ByteSwapPoint(&transport->topLeft); + PortabilityLayer::ByteSwap::BigInt16(transport->tall); + PortabilityLayer::ByteSwap::BigInt16(transport->where); +} + +void ByteSwapSwitch(switchType *sw) +{ + ByteSwapPoint(&sw->topLeft); + PortabilityLayer::ByteSwap::BigInt16(sw->delay); + PortabilityLayer::ByteSwap::BigInt16(sw->where); +} + +void ByteSwapLight(lightType *light) +{ + ByteSwapPoint(&light->topLeft); + PortabilityLayer::ByteSwap::BigInt16(light->length); +} + +void ByteSwapAppliance(applianceType *appliance) +{ + ByteSwapPoint(&appliance->topLeft); + PortabilityLayer::ByteSwap::BigInt16(appliance->height); +} + +void ByteSwapEnemy(enemyType *enemy) +{ + ByteSwapPoint(&enemy->topLeft); + PortabilityLayer::ByteSwap::BigInt16(enemy->length); +} + +void ByteSwapClutter(clutterType *clutter) +{ + ByteSwapRect(&clutter->bounds); + PortabilityLayer::ByteSwap::BigInt16(clutter->pict); +} + +void ByteSwapObject(objectType *obj) +{ + PortabilityLayer::ByteSwap::BigInt16(obj->what); + + switch (obj->what) + { + case kFloorVent: + case kCeilingVent: + case kFloorBlower: + case kCeilingBlower: + case kSewerGrate: + case kLeftFan: + case kRightFan: + case kTaper: + case kCandle: + case kStubby: + case kTiki: + case kBBQ: + case kInvisBlower: + case kGrecoVent: + case kSewerBlower: + case kLiftArea: + ByteSwapBlower(&obj->data.a); + break; + + case kTable: + case kShelf: + case kCabinet: + case kFilingCabinet: + case kWasteBasket: + case kMilkCrate: + case kCounter: + case kDresser: + case kDeckTable: + case kStool: + case kTrunk: + case kInvisObstacle: + case kManhole: + case kBooks: + case kInvisBounce: + ByteSwapFurniture(&obj->data.b); + break; + + case kRedClock: + case kBlueClock: + case kYellowClock: + case kCuckoo: + case kPaper: + case kBattery: + case kBands: + case kGreaseRt: + case kGreaseLf: + case kFoil: + case kInvisBonus: + case kStar: + case kSparkle: + case kHelium: + case kSlider: + ByteSwapBonus(&obj->data.c); + break; + + case kUpStairs: + case kDownStairs: + case kMailboxLf: + case kMailboxRt: + case kFloorTrans: + case kCeilingTrans: + case kDoorInLf: + case kDoorInRt: + case kDoorExRt: + case kDoorExLf: + case kWindowInLf: + case kWindowInRt: + case kWindowExRt: + case kWindowExLf: + case kInvisTrans: + case kDeluxeTrans: + ByteSwapTransport(&obj->data.d); + break; + + case kLightSwitch: + case kMachineSwitch: + case kThermostat: + case kPowerSwitch: + case kKnifeSwitch: + case kInvisSwitch: + case kTrigger: + case kLgTrigger: + case kSoundTrigger: + ByteSwapSwitch(&obj->data.e); + break; + + case kCeilingLight: + case kLightBulb: + case kTableLamp: + case kHipLamp: + case kDecoLamp: + case kFlourescent: + case kTrackLight: + case kInvisLight: + ByteSwapLight(&obj->data.f); + break; + + case kShredder: + case kToaster: + case kMacPlus: + case kGuitar: + case kTV: + case kCoffee: + case kOutlet: + case kVCR: + case kStereo: + case kMicrowave: + case kCinderBlock: + case kFlowerBox: + case kCDs: + case kCustomPict: + ByteSwapAppliance(&obj->data.g); + break; + + case kBalloon: + case kCopterLf: + case kCopterRt: + case kDartLf: + case kDartRt: + case kBall: + case kDrip: + case kFish: + case kCobweb: + ByteSwapEnemy(&obj->data.h); + break; + + case kOzma: + case kMirror: + case kMousehole: + case kFireplace: + case kFlower: + case kWallWindow: + case kBear: + case kCalendar: + case kVase1: + case kVase2: + case kBulletin: + case kCloud: + case kFaucet: + case kRug: + case kChimes: + ByteSwapClutter(&obj->data.i); + break; + default: + break; + }; +} + +void ByteSwapRoom(roomType *room) +{ + PortabilityLayer::ByteSwap::BigInt16(room->bounds); + + PortabilityLayer::ByteSwap::BigInt16(room->background); + + for (int i = 0; i < kNumTiles; i++) + PortabilityLayer::ByteSwap::BigInt16(room->tiles[i]); + + PortabilityLayer::ByteSwap::BigInt16(room->floor); + PortabilityLayer::ByteSwap::BigInt16(room->suite); + PortabilityLayer::ByteSwap::BigInt16(room->openings); + PortabilityLayer::ByteSwap::BigInt16(room->numObjects); + for (int i = 0; i < kMaxRoomObs; i++) + ByteSwapObject(room->objects + i); +} + +bool ByteSwapHouse(housePtr house, size_t sizeInBytes) +{ + PortabilityLayer::ByteSwap::BigInt16(house->version); + PortabilityLayer::ByteSwap::BigInt16(house->unusedShort); + PortabilityLayer::ByteSwap::BigInt32(house->timeStamp); + PortabilityLayer::ByteSwap::BigInt32(house->flags); + ByteSwapPoint(&house->initial); + ByteSwapScores(&house->highScores); + ByteSwapSavedGame(&house->savedGame); + PortabilityLayer::ByteSwap::BigInt16(house->firstRoom); + PortabilityLayer::ByteSwap::BigInt16(house->nRooms); + + const size_t roomDataSize = sizeInBytes + sizeof(roomType) - sizeof(houseType); + if (house->nRooms < 1 || roomDataSize / sizeof(roomType) < static_cast(house->nRooms)) + return false; + + const size_t nRooms = static_cast(house->nRooms); + for (size_t i = 0; i < nRooms; i++) + ByteSwapRoom(house->rooms + i); + + return true; +} + Boolean ReadHouse (void) { long byteCount; @@ -377,6 +673,8 @@ Boolean ReadHouse (void) HUnlock((Handle)thisHouse); return(false); } + + ByteSwapHouse(*thisHouse, static_cast(byteCount)); numberRooms = (*thisHouse)->nRooms; #ifdef COMPILEDEMO @@ -451,6 +749,8 @@ Boolean WriteHouse (Boolean checkIt) UInt32 timeStamp; long byteCount; OSErr theErr; + + PL_NotYetImplemented(); if (!houseOpen) { @@ -488,7 +788,9 @@ Boolean WriteHouse (Boolean checkIt) (*thisHouse)->timeStamp = (long)timeStamp; (*thisHouse)->version = wasHouseVersion; } - + + ByteSwapHouse(*thisHouse, static_cast(byteCount)); + theErr = FSWrite(houseRefNum, &byteCount, *thisHouse); if (theErr != noErr) { @@ -497,6 +799,8 @@ Boolean WriteHouse (Boolean checkIt) return(false); } + ByteSwapHouse(*thisHouse, static_cast(byteCount)); + theErr = SetEOF(houseRefNum, byteCount); if (theErr != noErr) { diff --git a/GpApp/SelectHouse.cpp b/GpApp/SelectHouse.cpp index c3e0a77..741114d 100644 --- a/GpApp/SelectHouse.cpp +++ b/GpApp/SelectHouse.cpp @@ -15,6 +15,7 @@ #include "Environ.h" #include "House.h" #include "RectUtils.h" +#include "VirtualDirectory.h" #define kLoadHouseDialogID 1000 @@ -557,8 +558,6 @@ void SortHouseList (void) void DoDirSearch (void) { #define kMaxDirectories 32 - CInfoPBRec theBlock; - Str255 nameString; long theDirs[kMaxDirectories]; OSErr theErr, notherErr; short count, i, currentDir, numDirs; @@ -566,51 +565,32 @@ void DoDirSearch (void) for (i = 0; i < kMaxDirectories; i++) theDirs[i] = 0L; currentDir = 0; - theDirs[currentDir] = thisMac.dirID; + theDirs[currentDir] = PortabilityLayer::EVirtualDirectory_GameData; numDirs = 1; - theBlock.hFileInfo.ioCompletion = nil; - theBlock.hFileInfo.ioVRefNum = thisMac.vRefNum; - theBlock.hFileInfo.ioNamePtr = nameString; - while ((currentDir < numDirs) && (currentDir < kMaxDirectories)) { count = 1; theErr = noErr; - - while (theErr == noErr) + + long dirID = theDirs[currentDir]; + + DirectoryFileListEntry *firstFile = GetDirectoryFiles(theDirs[currentDir]); + + for (DirectoryFileListEntry *f = firstFile; f; f = f->nextEntry) { SpinCursor(1); - theBlock.hFileInfo.ioFDirIndex = count; - theBlock.hFileInfo.ioDirID = theDirs[currentDir]; - theErr = PBGetCatInfo(&theBlock, false); - - if (theErr == noErr) + + if ((f->finderInfo.fdType == 'gliH') && (f->finderInfo.fdCreator == 'ozm5') && (housesFound < maxFiles)) { - if ((theBlock.hFileInfo.ioFlAttrib & 0x10) == 0x00) - { - if ((theBlock.hFileInfo.ioFlFndrInfo.fdType == 'gliH') && - (theBlock.hFileInfo.ioFlFndrInfo.fdCreator == 'ozm5') && - (housesFound < maxFiles)) - { - notherErr = FSMakeFSSpec(thisMac.vRefNum, - theBlock.hFileInfo.ioFlParID, nameString, - &theHousesSpecs[housesFound]); - if (notherErr == noErr) - housesFound++; - } - } - else if ((theBlock.hFileInfo.ioFlAttrib & 0x10) == 0x10) - { - if (numDirs < kMaxDirectories) - { - theDirs[numDirs] = theBlock.hFileInfo.ioDirID; - numDirs++; - } - } - count++; + notherErr = FSMakeFSSpec(thisMac.vRefNum, theDirs[currentDir], f->name, &theHousesSpecs[housesFound]); + if (notherErr == noErr) + housesFound++; } } + + DisposeDirectoryFiles(firstFile); + currentDir++; } diff --git a/GpApp/Sound.cpp b/GpApp/Sound.cpp index 778a62f..ddb966c 100644 --- a/GpApp/Sound.cpp +++ b/GpApp/Sound.cpp @@ -9,11 +9,11 @@ #include "PLResources.h" #include "PLSound.h" #include "Externs.h" +#include "SoundSync.h" #define kBaseBufferSoundID 1000 #define kMaxSounds 64 -#define kNoSoundPlaying -1 void CallBack0 (SndChannelPtr, SndCommand *); @@ -28,12 +28,10 @@ OSErr CloseSoundChannels (void); SndCallBackUPP callBack0UPP, callBack1UPP, callBack2UPP; SndChannelPtr channel0, channel1, channel2; Ptr theSoundData[kMaxSounds]; -short numSoundsLoaded, priority0, priority1, priority2; -short soundPlaying0, soundPlaying1, soundPlaying2; +short numSoundsLoaded; Boolean soundLoaded[kMaxSounds], dontLoadSounds; Boolean channelOpen, isSoundOn, failedSound; - //============================================================== Functions //-------------------------------------------------------------- PlayPrioritySound @@ -43,44 +41,33 @@ void PlayPrioritySound (short which, short priority) if (failedSound || dontLoadSounds) return; + + SoundSyncState ss = SoundSync_ReadAll(); if ((priority == kTriggerPriority) && - ((priority0 == kTriggerPriority) || - ((priority1 == kTriggerPriority)) || - ((priority2 == kTriggerPriority)))) + ((ss.priority0 == kTriggerPriority) || + ((ss.priority1 == kTriggerPriority)) || + ((ss.priority2 == kTriggerPriority)))) return; whosLowest = 0; - lowestPriority = priority0; + lowestPriority = ss.priority0; - if (priority1 < lowestPriority) + if (ss.priority1 < lowestPriority) { - lowestPriority = priority1; + lowestPriority = ss.priority1; whosLowest = 1; } - if (priority2 < lowestPriority) + if (ss.priority2 < lowestPriority) { - lowestPriority = priority2; + lowestPriority = ss.priority2; whosLowest = 2; } if (priority >= lowestPriority) { - switch (whosLowest) - { - case 0: - PlaySound0(which, priority); - break; - - case 1: - PlaySound1(which, priority); - break; - - case 2: - PlaySound2(which, priority); - break; - } + PlayExclusiveSoundChannel(whosLowest, which, lowestPriority, priority); } } @@ -90,8 +77,10 @@ void FlushAnyTriggerPlaying (void) { SndCommand theCommand; OSErr theErr; + + SoundSyncState ss = SoundSync_ReadAll(); - if (priority0 == kTriggerPriority) + if (ss.priority0 == kTriggerPriority) { theCommand.cmd = quietCmd; theCommand.param1 = 0; @@ -103,7 +92,7 @@ void FlushAnyTriggerPlaying (void) theErr = SndDoImmediate(channel0, &theCommand); } - if (priority1 == kTriggerPriority) + if (ss.priority1 == kTriggerPriority) { theCommand.cmd = quietCmd; theCommand.param1 = 0; @@ -115,7 +104,7 @@ void FlushAnyTriggerPlaying (void) theErr = SndDoImmediate(channel1, &theCommand); } - if (priority2 == kTriggerPriority) + if (ss.priority2 == kTriggerPriority) { theCommand.cmd = quietCmd; theCommand.param1 = 0; @@ -130,85 +119,63 @@ void FlushAnyTriggerPlaying (void) //-------------------------------------------------------------- PlaySound0 -void PlaySound0 (short soundID, short priority) +void PlayExclusiveSoundChannel(short channelIndex, short soundID, short oldPriority, short newPriority) { SndCommand theCommand; OSErr theErr; if (failedSound || dontLoadSounds) return; - - theErr = noErr; - if (isSoundOn) + + SndChannelPtr channel = nil; + switch (channelIndex) { - priority0 = priority; - soundPlaying0 = soundID; - - theCommand.cmd = bufferCmd; - theCommand.param1 = 0; - theCommand.param2 = (intptr_t)(theSoundData[soundID]); - theErr = SndDoImmediate(channel0, &theCommand); - - theCommand.cmd = callBackCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoCommand(channel0, &theCommand, true); + case 0: + channel = channel0; + break; + case 1: + channel = channel2; + break; + case 2: + channel = channel2; + break; + default: + return; } -} -//-------------------------------------------------------------- PlaySound1 - -void PlaySound1 (short soundID, short priority) -{ - SndCommand theCommand; - OSErr theErr; - - if (failedSound || dontLoadSounds) - return; - theErr = noErr; if (isSoundOn) { - priority1 = priority; - soundPlaying1 = soundID; - + if (oldPriority != 0) + { + // Flush the queue and stop the channel, which will remove the pending callback + theCommand.cmd = flushCmd; + theCommand.param1 = 0; + theCommand.param2 = 0; + theErr = SndDoImmediate(channel, &theCommand); + + theCommand.cmd = quietCmd; + theCommand.param1 = 0; + theCommand.param2 = 0; + theErr = SndDoImmediate(channel, &theCommand); + + SoundSync_ClearPriority(channelIndex); + } + + SoundSync_PutPriority(channelIndex, newPriority); + theCommand.cmd = bufferCmd; theCommand.param1 = 0; theCommand.param2 = (intptr_t)(theSoundData[soundID]); - theErr = SndDoImmediate(channel1, &theCommand); + theErr = SndDoCommand(channel, &theCommand, true); theCommand.cmd = callBackCmd; theCommand.param1 = 0; theCommand.param2 = 0; - theErr = SndDoCommand(channel1, &theCommand, true); - } -} + theErr = SndDoCommand(channel, &theCommand, true); -//-------------------------------------------------------------- PlaySound2 - -void PlaySound2 (short soundID, short priority) -{ - SndCommand theCommand; - OSErr theErr; - - if (failedSound || dontLoadSounds) - return; - - theErr = noErr; - if (isSoundOn) - { - theCommand.cmd = bufferCmd; - theCommand.param1 = 0; - theCommand.param2 = (intptr_t)(theSoundData[soundID]); - theErr = SndDoImmediate(channel2, &theCommand); - - theCommand.cmd = callBackCmd; - theCommand.param1 = 0; - theCommand.param2 = 0; - theErr = SndDoCommand(channel2, &theCommand, true); - - priority2 = priority; - soundPlaying2 = soundID; + if (theErr != noErr) + SoundSync_ClearPriority(channelIndex); } } @@ -216,24 +183,21 @@ void PlaySound2 (short soundID, short priority) void CallBack0 (SndChannelPtr theChannel, SndCommand *theCommand) { - priority0 = 0; - soundPlaying0 = kNoSoundPlaying; + SoundSync_ClearPriority(0); } //-------------------------------------------------------------- CallBack1 void CallBack1 (SndChannelPtr theChannel, SndCommand *theCommand) { - priority1 = 0; - soundPlaying1 = kNoSoundPlaying; + SoundSync_ClearPriority(1); } //-------------------------------------------------------------- CallBack2 void CallBack2 (SndChannelPtr theChannel, SndCommand *theCommand) { - priority2 = 0; - soundPlaying2 = kNoSoundPlaying; + SoundSync_ClearPriority(2); } //-------------------------------------------------------------- LoadTriggerSound @@ -423,13 +387,10 @@ void InitSound (void) channel0 = nil; channel1 = nil; channel2 = nil; - - priority0 = 0; - priority1 = 0; - priority2 = 0; - soundPlaying0 = kNoSoundPlaying; - soundPlaying1 = kNoSoundPlaying; - soundPlaying2 = kNoSoundPlaying; + + SoundSync_ClearPriority(0); + SoundSync_ClearPriority(1); + SoundSync_ClearPriority(2); theErr = LoadBufferSounds(); if (theErr != noErr) diff --git a/GpApp/SoundSync.h b/GpApp/SoundSync.h new file mode 100644 index 0000000..64de962 --- /dev/null +++ b/GpApp/SoundSync.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +struct SoundSyncState +{ + int16_t priority0; + int16_t priority1; + int16_t priority2; + int16_t priority3; +}; + +SoundSyncState SoundSync_ReadAll(); +void SoundSync_ClearPriority(int index); +void SoundSync_PutPriority(int index, int16_t priority); diff --git a/GpApp/SoundSync_Win32.cpp b/GpApp/SoundSync_Win32.cpp new file mode 100644 index 0000000..c3db567 --- /dev/null +++ b/GpApp/SoundSync_Win32.cpp @@ -0,0 +1,31 @@ +#include "SoundSync.h" +#include + +#include + +static volatile uint64_t gs_prioritiesBlob = 0; + +SoundSyncState SoundSync_ReadAll() +{ + const uint16_t priorities = gs_prioritiesBlob; + + SoundSyncState state; + state.priority0 = static_cast((priorities >> 0) & 0xffff); + state.priority1 = static_cast((priorities >> 16) & 0xffff); + state.priority2 = static_cast((priorities >> 32) & 0xffff); + state.priority3 = static_cast((priorities >> 48) & 0xffff); + + return state; +} + +void SoundSync_ClearPriority(int index) +{ + const uint64_t clearMask = ~(static_cast(0xffff) << (index * 16)); + InterlockedAnd(&gs_prioritiesBlob, clearMask); +} + +void SoundSync_PutPriority(int index, int16_t priority) +{ + const uint64_t insertMask = static_cast(priority) << (index * 16); + InterlockedOr(&gs_prioritiesBlob, insertMask); +} diff --git a/GpD3D/GpFileSystem_Win32.cpp b/GpD3D/GpFileSystem_Win32.cpp index 6959281..83d346d 100644 --- a/GpD3D/GpFileSystem_Win32.cpp +++ b/GpD3D/GpFileSystem_Win32.cpp @@ -1,11 +1,97 @@ #include "GpFileSystem_Win32.h" #include "GpFileStream_Win32.h" #include "GpWindows.h" -#include "GpMemoryBuffer.h" +#include "GpMemoryBuffer.h" +#include "HostDirectoryCursor.h" #include #include -#include +#include +#include + +class GpDirectoryCursor_Win32 final : public PortabilityLayer::HostDirectoryCursor +{ +public: + static GpDirectoryCursor_Win32 *Create(const HANDLE &handle, const WIN32_FIND_DATAW &findData); + + bool GetNext(const char *&outFileName) override; + void Destroy() override; + +private: + GpDirectoryCursor_Win32(const HANDLE &handle, const WIN32_FIND_DATAW &findData); + ~GpDirectoryCursor_Win32(); + + HANDLE m_handle; + WIN32_FIND_DATAW m_findData; + char m_chars[MAX_PATH + 1]; + bool m_haveNext; +}; + +GpDirectoryCursor_Win32 *GpDirectoryCursor_Win32::Create(const HANDLE &handle, const WIN32_FIND_DATAW &findData) +{ + void *storage = malloc(sizeof(GpDirectoryCursor_Win32)); + if (!storage) + return nullptr; + + return new (storage) GpDirectoryCursor_Win32(handle, findData); +} + +bool GpDirectoryCursor_Win32::GetNext(const char *&outFileName) +{ + while (m_haveNext) + { + bool haveResult = false; + + bool hasInvalidChars = false; + for (const wchar_t *fnameScan = m_findData.cFileName; *fnameScan; fnameScan++) + { + const int32_t asInt = static_cast(*fnameScan); + if (asInt < 1 || asInt >= 128) + { + hasInvalidChars = true; + break; + } + } + + if (!hasInvalidChars && wcscmp(m_findData.cFileName, L".") && wcscmp(m_findData.cFileName, L"..")) + { + const size_t len = wcslen(m_findData.cFileName); + + haveResult = true; + + for (size_t i = 0; i <= len; i++) + m_chars[i] = static_cast(m_findData.cFileName[i]); + } + + m_haveNext = (FindNextFileW(m_handle, &m_findData) != FALSE); + + if (haveResult) + { + outFileName = m_chars; + return true; + } + } + + return false; +} + +void GpDirectoryCursor_Win32::Destroy() +{ + this->~GpDirectoryCursor_Win32(); + free(this); +} + +GpDirectoryCursor_Win32::GpDirectoryCursor_Win32(const HANDLE &handle, const WIN32_FIND_DATAW &findData) + : m_handle(handle) + , m_findData(findData) + , m_haveNext(true) +{ +} + +GpDirectoryCursor_Win32::~GpDirectoryCursor_Win32() +{ + FindClose(m_handle); +} GpFileSystem_Win32::GpFileSystem_Win32() { @@ -52,6 +138,22 @@ PortabilityLayer::IOStream *GpFileSystem_Win32::OpenFile(PortabilityLayer::EVirt HANDLE h = CreateFileW(winPath, desiredAccess, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); return new GpFileStream_Win32(h, true, writeAccess, true); +} + +PortabilityLayer::HostDirectoryCursor *GpFileSystem_Win32::ScanDirectory(PortabilityLayer::EVirtualDirectory virtualDirectory) +{ + wchar_t winPath[MAX_PATH + 2]; + + if (!ResolvePath(virtualDirectory, "*", winPath)) + return nullptr; + + WIN32_FIND_DATAW findData; + HANDLE ff = FindFirstFileW(winPath, &findData); + + if (ff == INVALID_HANDLE_VALUE) + return nullptr; + + return GpDirectoryCursor_Win32::Create(ff, findData); } GpFileSystem_Win32 *GpFileSystem_Win32::GetInstance() @@ -68,6 +170,9 @@ bool GpFileSystem_Win32::ResolvePath(PortabilityLayer::EVirtualDirectory virtual case PortabilityLayer::EVirtualDirectory_ApplicationData: baseDir = L"D:\\Source Code\\GlidePort\\Packaged\\"; break; + case PortabilityLayer::EVirtualDirectory_GameData: + baseDir = L"D:\\Source Code\\GlidePort\\Packaged\\Houses\\"; + break; case PortabilityLayer::EVirtualDirectory_Prefs: baseDir = m_prefsDir.c_str(); break; diff --git a/GpD3D/GpFileSystem_Win32.h b/GpD3D/GpFileSystem_Win32.h index 1a91e16..0a1d2db 100644 --- a/GpD3D/GpFileSystem_Win32.h +++ b/GpD3D/GpFileSystem_Win32.h @@ -13,6 +13,7 @@ public: bool FileExists(PortabilityLayer::EVirtualDirectory virtualDirectory, const char *path) override; PortabilityLayer::IOStream *OpenFile(PortabilityLayer::EVirtualDirectory virtualDirectory, const char *path, bool writeAccess, bool create) override; + PortabilityLayer::HostDirectoryCursor *ScanDirectory(PortabilityLayer::EVirtualDirectory virtualDirectory) override; static GpFileSystem_Win32 *GetInstance(); diff --git a/PictChecker/PictChecker.cpp b/PictChecker/PictChecker.cpp index 048f84c..964f6dc 100644 --- a/PictChecker/PictChecker.cpp +++ b/PictChecker/PictChecker.cpp @@ -992,103 +992,103 @@ void AuditPackBitsRect(MemReaderStream &stream, int pictVersion, bool isPackedFl class PictDumpEmitContext final : public QDPictEmitContext { public: - bool SpecifyFrame(const Rect &rect) override - { - m_rect = rect; - m_width = rect.right - rect.left; - m_height = rect.bottom - rect.top; - m_image.resize(m_width * m_height); - return true; - } - - Rect ConstrainRegion(const Rect &rect) const override - { - return rect.Intersect(m_rect); - } - - void Start(QDPictBlitSourceType sourceType, const QDPictEmitScanlineParameters ¶ms) override - { - m_blitType = sourceType; - m_params = params; - m_constraintRegionWidth = params.m_constrainedRegionRight - params.m_constrainedRegionLeft; - m_constraintRegionStartIndex = params.m_constrainedRegionLeft - params.m_scanlineOriginX; - m_constraintRegionEndIndex = params.m_constrainedRegionRight - params.m_scanlineOriginX; - - const size_t firstCol = params.m_constrainedRegionLeft - m_rect.left; - const size_t firstRow = params.m_firstY - m_rect.top; - - m_outputIndexStart = firstRow * m_width + firstCol; - } - - void BlitScanlineAndAdvance(const void *data) override - { - const int32_t crRight = m_params.m_constrainedRegionRight; - const int32_t crLeft = m_params.m_constrainedRegionLeft; - const size_t constraintRegionStartIndex = m_constraintRegionStartIndex; - const uint8_t *dataBytes = static_cast(data); - const size_t outputIndexStart = m_outputIndexStart; - const RGBAColor *palette = m_params.m_colors; - const size_t planarSeparation = m_params.m_planarSeparation; - - static const RGBAColor bwColors[] = - { - { 255, 255, 255, 255 }, - { 0, 0, 0, 255 } - }; - - switch (m_blitType) - { - case QDPictBlitSourceType_Indexed1Bit: - for (size_t i = 0; i < m_constraintRegionWidth; i++) - { + bool SpecifyFrame(const Rect &rect) override + { + m_rect = rect; + m_width = rect.right - rect.left; + m_height = rect.bottom - rect.top; + m_image.resize(m_width * m_height); + return true; + } + + Rect ConstrainRegion(const Rect &rect) const override + { + return rect.Intersect(m_rect); + } + + void Start(QDPictBlitSourceType sourceType, const QDPictEmitScanlineParameters ¶ms) override + { + m_blitType = sourceType; + m_params = params; + m_constraintRegionWidth = params.m_constrainedRegionRight - params.m_constrainedRegionLeft; + m_constraintRegionStartIndex = params.m_constrainedRegionLeft - params.m_scanlineOriginX; + m_constraintRegionEndIndex = params.m_constrainedRegionRight - params.m_scanlineOriginX; + + const size_t firstCol = params.m_constrainedRegionLeft - m_rect.left; + const size_t firstRow = params.m_firstY - m_rect.top; + + m_outputIndexStart = firstRow * m_width + firstCol; + } + + void BlitScanlineAndAdvance(const void *data) override + { + const int32_t crRight = m_params.m_constrainedRegionRight; + const int32_t crLeft = m_params.m_constrainedRegionLeft; + const size_t constraintRegionStartIndex = m_constraintRegionStartIndex; + const uint8_t *dataBytes = static_cast(data); + const size_t outputIndexStart = m_outputIndexStart; + const RGBAColor *palette = m_params.m_colors; + const size_t planarSeparation = m_params.m_planarSeparation; + + static const RGBAColor bwColors[] = + { + { 255, 255, 255, 255 }, + { 0, 0, 0, 255 } + }; + + switch (m_blitType) + { + case QDPictBlitSourceType_Indexed1Bit: + for (size_t i = 0; i < m_constraintRegionWidth; i++) + { const size_t itemIndex = i + constraintRegionStartIndex; const int bitShift = 7 - (itemIndex & 7); const int colorIndex = (dataBytes[itemIndex / 8] >> bitShift) & 0x1; - m_image[i + outputIndexStart] = palette[colorIndex]; - } - break; - case QDPictBlitSourceType_Indexed2Bit: - for (size_t i = 0; i < m_constraintRegionWidth; i++) - { + m_image[i + outputIndexStart] = palette[colorIndex]; + } + break; + case QDPictBlitSourceType_Indexed2Bit: + for (size_t i = 0; i < m_constraintRegionWidth; i++) + { const size_t itemIndex = i + constraintRegionStartIndex; const int bitShift = 6 - (2 * (itemIndex & 1)); const int colorIndex = (dataBytes[itemIndex / 4] >> bitShift) & 0x3; - m_image[i + outputIndexStart] = palette[colorIndex]; - } - break; - case QDPictBlitSourceType_Indexed4Bit: - for (size_t i = 0; i < m_constraintRegionWidth; i++) - { + m_image[i + outputIndexStart] = palette[colorIndex]; + } + break; + case QDPictBlitSourceType_Indexed4Bit: + for (size_t i = 0; i < m_constraintRegionWidth; i++) + { const size_t itemIndex = i + constraintRegionStartIndex; const int bitShift = 4 - (4 * (itemIndex & 1)); const int colorIndex = (dataBytes[itemIndex / 2] >> bitShift) & 0xf; - m_image[i + outputIndexStart] = palette[colorIndex]; - } - break; - case QDPictBlitSourceType_Indexed8Bit: - for (size_t i = 0; i < m_constraintRegionWidth; i++) - { - const size_t itemIndex = i + constraintRegionStartIndex; - const uint8_t colorIndex = dataBytes[itemIndex]; - m_image[i + outputIndexStart] = palette[colorIndex]; - } - break; - case QDPictBlitSourceType_1Bit: - for (size_t i = 0; i < m_constraintRegionWidth; i++) - { + m_image[i + outputIndexStart] = palette[colorIndex]; + } + break; + case QDPictBlitSourceType_Indexed8Bit: + for (size_t i = 0; i < m_constraintRegionWidth; i++) + { + const size_t itemIndex = i + constraintRegionStartIndex; + const uint8_t colorIndex = dataBytes[itemIndex]; + m_image[i + outputIndexStart] = palette[colorIndex]; + } + break; + case QDPictBlitSourceType_1Bit: + for (size_t i = 0; i < m_constraintRegionWidth; i++) + { const size_t itemIndex = i + constraintRegionStartIndex; const int bitShift = 7 - (itemIndex & 7); const int colorIndex = (dataBytes[itemIndex / 8] >> bitShift) & 0x1; - m_image[i + outputIndexStart] = bwColors[colorIndex]; - } - break; - case QDPictBlitSourceType_RGB15: - for (size_t i = 0; i < m_constraintRegionWidth; i++) - { + m_image[i + outputIndexStart] = bwColors[colorIndex]; + } + break; + case QDPictBlitSourceType_RGB15: + for (size_t i = 0; i < m_constraintRegionWidth; i++) + { const size_t itemIndex = i + constraintRegionStartIndex; const uint16_t item = *reinterpret_cast(dataBytes + itemIndex * 2); @@ -1098,11 +1098,11 @@ public: outputItem.g = FiveToEight((item >> 5) & 0x1f); outputItem.r = FiveToEight((item >> 10) & 0x1f); outputItem.a = 255; - } - break; - case QDPictBlitSourceType_RGB24_Multiplane: - for (size_t i = 0; i < m_constraintRegionWidth; i++) - { + } + break; + case QDPictBlitSourceType_RGB24_Multiplane: + for (size_t i = 0; i < m_constraintRegionWidth; i++) + { const size_t itemIndex = i + constraintRegionStartIndex; RGBAColor &outputItem = m_image[i + outputIndexStart]; @@ -1111,30 +1111,30 @@ public: outputItem.g = dataBytes[itemIndex + planarSeparation]; outputItem.b = dataBytes[itemIndex + planarSeparation * 2]; outputItem.a = 255; - } - break; - default: - assert(false); - } - - m_outputIndexStart += m_width; - } - - bool AllocTempBuffers(uint8_t *&buffer1, size_t buffer1Size, uint8_t *&buffer2, size_t buffer2Size) override - { - m_buffer1.resize(buffer1Size); - m_buffer2.resize(buffer2Size); - - buffer1 = &m_buffer1[0]; - buffer2 = &m_buffer2[0]; - - return true; - } - - void DumpImageToFile(const char *path) - { - stbi_write_png(path, static_cast(m_width), static_cast(m_height), 4, &m_image[0], static_cast(m_width * 4)); - } + } + break; + default: + assert(false); + } + + m_outputIndexStart += m_width; + } + + bool AllocTempBuffers(uint8_t *&buffer1, size_t buffer1Size, uint8_t *&buffer2, size_t buffer2Size) override + { + m_buffer1.resize(buffer1Size); + m_buffer2.resize(buffer2Size); + + buffer1 = &m_buffer1[0]; + buffer2 = &m_buffer2[0]; + + return true; + } + + void DumpImageToFile(const char *path) + { + stbi_write_png(path, static_cast(m_width), static_cast(m_height), 4, &m_image[0], static_cast(m_width * 4)); + } private: Rect m_rect; diff --git a/PortabilityLayer/FileManager.cpp b/PortabilityLayer/FileManager.cpp index bafc946..0a0b7c9 100644 --- a/PortabilityLayer/FileManager.cpp +++ b/PortabilityLayer/FileManager.cpp @@ -20,6 +20,8 @@ namespace PortabilityLayer int OpenFileDF(uint32_t dirID, const PLPasStr &filename, EFilePermission filePermission, short *outRefNum) override; int OpenFileRF(uint32_t dirID, const PLPasStr &filename, EFilePermission filePermission, short *outRefNum) override; + bool ReadFileProperties(uint32_t dirID, const PLPasStr &filename, MacFileProperties &properties) override; + IOStream *GetFileStream(int fileID) override; int RawOpenFileDF(uint32_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, IOStream **outStream) override; int RawOpenFileRF(uint32_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, IOStream **outStream) override; @@ -64,6 +66,28 @@ namespace PortabilityLayer int FileManagerImpl::OpenFileRF(uint32_t dirID, const PLPasStr &filename, EFilePermission permission, short *outRefNum) { return OpenFileFork(dirID, filename, ".gpr", permission, outRefNum); + } + + bool FileManagerImpl::ReadFileProperties(uint32_t dirID, const PLPasStr &filename, MacFileProperties &properties) + { + IOStream *stream = nullptr; + int err = RawOpenFileFork(dirID, filename, ".gpf", EFilePermission_Read, true, &stream); + if (err) + return false; + + MacFilePropertiesSerialized serialized; + bool readOk = (stream->Read(serialized.m_data, MacFilePropertiesSerialized::kSize) == MacFilePropertiesSerialized::kSize); + stream->Close(); + + if (readOk) + serialized.Deserialize(properties); + + return readOk; + } + + IOStream *FileManagerImpl::GetFileStream(int fileID) + { + return m_refs[fileID].m_stream; } int FileManagerImpl::RawOpenFileDF(uint32_t dirID, const PLPasStr &filename, EFilePermission permission, bool ignoreMeta, IOStream **outStream) @@ -94,7 +118,7 @@ namespace PortabilityLayer } } - if (refIndex == 0x7fff) + if (refIndex == 0x8000) return tmfoErr; IOStream *stream = nullptr; @@ -110,7 +134,7 @@ namespace PortabilityLayer of.m_dirID = static_cast(dirID); of.m_fileName.Set(filename.Length(), filename.Chars()); - *outRefNum = static_cast(refIndex + 1); + *outRefNum = static_cast(refIndex); return noErr; } @@ -132,11 +156,11 @@ namespace PortabilityLayer return fnfErr; } - const bool needToCreate = !(ignoreMeta || HostFileSystem::GetInstance()->FileExists(static_cast(dirID), extFN)); - if (!ConstructFilename(extFN, filename, ext)) return bdNamErr; + const bool needToCreate = !(ignoreMeta || HostFileSystem::GetInstance()->FileExists(static_cast(dirID), extFN)); + IOStream *fstream = nullptr; switch (permission) { @@ -180,7 +204,7 @@ namespace PortabilityLayer if (c >= '0' && c <= '9') continue; - if (c == '_') + if (c == '_' || c == '.' || c == '\'') continue; if (c == ' ' && i != 0 && i != fnameSize - 1) diff --git a/PortabilityLayer/FileManager.h b/PortabilityLayer/FileManager.h index 7e628f5..0886c6b 100644 --- a/PortabilityLayer/FileManager.h +++ b/PortabilityLayer/FileManager.h @@ -3,7 +3,8 @@ #define __PL_FILE_MANAGER_H__ #include "FilePermission.h" -#include "CoreDefs.h" +#include "CoreDefs.h" +#include "FilePos.h" #include @@ -11,7 +12,8 @@ class PLPasStr; namespace PortabilityLayer { - class IOStream; + class IOStream; + struct MacFileProperties; class FileManager { @@ -20,6 +22,8 @@ namespace PortabilityLayer virtual int OpenFileDF(uint32_t dirID, const PLPasStr &filename, EFilePermission filePermission, short *outRefNum) = 0; virtual int OpenFileRF(uint32_t dirID, const PLPasStr &filename, EFilePermission filePermission, short *outRefNum) = 0; + virtual bool ReadFileProperties(uint32_t dirID, const PLPasStr &filename, MacFileProperties &properties) = 0; + virtual IOStream *GetFileStream(int fileID) = 0; virtual int RawOpenFileDF(uint32_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, IOStream **outStream) = 0; virtual int RawOpenFileRF(uint32_t dirID, const PLPasStr &filename, EFilePermission filePermission, bool ignoreMeta, IOStream **outStream) = 0; diff --git a/PortabilityLayer/FilePos.h b/PortabilityLayer/FilePos.h new file mode 100644 index 0000000..f11ee61 --- /dev/null +++ b/PortabilityLayer/FilePos.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace PortabilityLayer +{ + typedef int64_t FilePos_t; + typedef uint64_t UFilePos_t; +} diff --git a/PortabilityLayer/HostDirectoryCursor.h b/PortabilityLayer/HostDirectoryCursor.h new file mode 100644 index 0000000..d2681ca --- /dev/null +++ b/PortabilityLayer/HostDirectoryCursor.h @@ -0,0 +1,11 @@ +#pragma once + +namespace PortabilityLayer +{ + class HostDirectoryCursor + { + public: + virtual bool GetNext(const char *&outFileName) = 0; + virtual void Destroy() = 0; + }; +} diff --git a/PortabilityLayer/HostFileSystem.h b/PortabilityLayer/HostFileSystem.h index 443822b..99f2352 100644 --- a/PortabilityLayer/HostFileSystem.h +++ b/PortabilityLayer/HostFileSystem.h @@ -6,13 +6,15 @@ namespace PortabilityLayer { - class IOStream; + class IOStream; + class HostDirectoryCursor; class HostFileSystem { public: virtual bool FileExists(EVirtualDirectory virtualDirectory, const char *path) = 0; virtual IOStream *OpenFile(EVirtualDirectory virtualDirectory, const char *path, bool writeAccess, bool create) = 0; + virtual HostDirectoryCursor *ScanDirectory(EVirtualDirectory virtualDirectory) = 0; static HostFileSystem *GetInstance(); static void SetInstance(HostFileSystem *instance); diff --git a/PortabilityLayer/IOStream.h b/PortabilityLayer/IOStream.h index 7167373..5f1ae50 100644 --- a/PortabilityLayer/IOStream.h +++ b/PortabilityLayer/IOStream.h @@ -3,13 +3,11 @@ #ifndef __PL_IOTREAM_H__ #define __PL_IOTREAM_H__ -#include "DataTypes.h" +#include "DataTypes.h" +#include "FilePos.h" namespace PortabilityLayer { - typedef int64_t FilePos_t; - typedef uint64_t UFilePos_t; - class IOStream { public: diff --git a/PortabilityLayer/MacLatin.h b/PortabilityLayer/MacLatin.h new file mode 100644 index 0000000..d350511 --- /dev/null +++ b/PortabilityLayer/MacLatin.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace PortabilityLayer +{ + namespace MacLatin + { + extern const uint16_t g_toUnicode[256]; + extern const uint8_t g_stripDiacritic[256]; + extern const uint8_t g_toLower[256]; + extern const uint8_t g_toUpper[256]; + } +} diff --git a/PortabilityLayer/MacLatin1.cpp b/PortabilityLayer/MacLatin1.cpp new file mode 100644 index 0000000..3b3a6c1 --- /dev/null +++ b/PortabilityLayer/MacLatin1.cpp @@ -0,0 +1,95 @@ +#include "MacLatin.h" + +namespace PortabilityLayer +{ + namespace MacLatin + { + const uint16_t g_toUnicode[256] = + { + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5 + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 6 + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, // 7 + + 0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1, 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8, // 8 + 0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3, 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc, // 9 + 0x00dd, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x00d7, 0x00b6, 0x00df, 0x00ae, 0x00a9, 0x00b2, 0x00b4, 0x00a8, 0x00b3, 0x00c6, 0x00d8, // 10 + 0x00b9, 0x00b1, 0x00bc, 0x00bd, 0x00a5, 0x00b5, 0xffff, 0xffff, 0xffff, 0xffff, 0x00be, 0x00aa, 0x00ba, 0xffff, 0x00e6, 0x00f8, // 11 + 0x00bf, 0x00a1, 0x00ac, 0x0141, 0x0192, 0x02cb, 0xffff, 0x00ab, 0x00bb, 0x00a6, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153, // 12 + 0x00ad, 0xffff, 0xffff, 0xffff, 0x0142, 0xffff, 0x00f7, 0xffff, 0x00ff, 0x0178, 0xffff, 0x00a4, 0x00d0, 0x00f0, 0x00de, 0x00fe, // 13 + 0x00fd, 0x00b7, 0xffff, 0xffff, 0xffff, 0x00c2, 0x00ca, 0x00c1, 0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4, // 14 + 0xffff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc, 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7, // 15 + }; + + const uint8_t g_stripDiacritic[256] = + { + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5 + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 6 + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, // 7 + + 'A', 'A', 'C', 'E', 'N', 'O', 'U', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', // 8 + 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', // 9 + 'Y', 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 'O', // a + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 'o', // b + 192, 193, 194, 'L', 196, 197, 198, 199, 200, 201, 202, 'A', 'A', 'O', 206, 207, // c + 208, 209, 210, 211, 'l', 213, 214, 215, 'y', 'Y', 218, 219, 220, 221, 222, 223, // d + 224, 225, 226, 227, 228, 'A', 'E', 'A', 'E', 'E', 'I', 'I', 'I', 'I', 'O', 'O', // e + 240, 'O', 'U', 'U', 'U', 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, // f + }; + + const uint8_t g_toUpper[256] = + { + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5 + 96, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', // 6 + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 123, 124, 125, 126, 127, // 7 + + 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 143, // 8 + 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, // 9 + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, // a + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 174, 175, // b + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 206, // c + 208, 209, 210, 211, 195, 213, 214, 215, 217, 217, 218, 219, 220, 220, 222, 222, // d + 160, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // e + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, // f + }; + + const uint8_t g_toLower[256] = + { + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 + 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', // 4 + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 91, 92, 93, 94, 95, // 5 + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 6 + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, // 7 + + 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, // 8 + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 9 + 224, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, // a + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, // b + 192, 193, 194, 212, 196, 197, 198, 199, 200, 201, 202, 136, 139, 155, 207, 207, // c + 208, 209, 210, 211, 212, 213, 214, 215, 216, 216, 218, 219, 221, 221, 223, 223, // d + 224, 225, 226, 227, 228, 137, 144, 135, 145, 143, 146, 148, 149, 147, 151, 153, // e + 240, 152, 156, 158, 157, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, // f + }; + } +} diff --git a/PortabilityLayer/PLAliases.cpp b/PortabilityLayer/PLAliases.cpp index 2133817..64a0ced 100644 --- a/PortabilityLayer/PLAliases.cpp +++ b/PortabilityLayer/PLAliases.cpp @@ -1,7 +1,8 @@ #include "PLAliases.h" OSErr ResolveAliasFile(FSSpecPtr fsSpec, Boolean recursive, Boolean *outIsFolder, Boolean *outWasAliased) -{ - PL_NotYetImplemented(); +{ + *outIsFolder = PL_FALSE; + *outWasAliased = PL_FALSE; return noErr; } diff --git a/PortabilityLayer/PLCore.cpp b/PortabilityLayer/PLCore.cpp index b103cf4..b94fb87 100644 --- a/PortabilityLayer/PLCore.cpp +++ b/PortabilityLayer/PLCore.cpp @@ -6,11 +6,14 @@ #include "DisplayDeviceManager.h" #include "FileManager.h" #include "FilePermission.h" +#include "HostDirectoryCursor.h" +#include "HostFileSystem.h" #include "HostSuspendCallArgument.h" #include "HostSuspendHook.h" #include "HostDisplayDriver.h" #include "HostSystemServices.h" #include "ResourceManager.h" +#include "MacFileInfo.h" #include "MemoryManager.h" #include "MemReaderStream.h" #include "MMHandleBlock.h" @@ -23,6 +26,29 @@ #include +static bool ConvertFilenameToSafePStr(const char *str, uint8_t *pstr) +{ + const char *strBase = str; + while (*str) + { + const char c = *str++; + + if (c == '.' || c == ' ' || c == '_' || c == '\'' || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) + continue; + else + return false; + } + + ptrdiff_t len = str - strBase; + if (len > 31) + return false; + + memcpy(pstr + 1, strBase, static_cast(len)); + pstr[0] = static_cast(len); + + return true; +} + void InitCursor() { } @@ -414,7 +440,11 @@ OSErr FSWrite(short refNum, long *byteCount, const void *data) OSErr FSRead(short refNum, long *byteCount, void *data) { - PL_NotYetImplemented(); + PortabilityLayer::IOStream *stream = PortabilityLayer::FileManager::GetInstance()->GetFileStream(refNum); + + const size_t bytesRead = stream->Read(data, static_cast(*byteCount)); + *byteCount = static_cast(bytesRead); + return noErr; } @@ -426,19 +456,35 @@ OSErr FSpDelete(const FSSpec *spec) OSErr FSpGetFInfo(const FSSpec *spec, FInfo *finfo) { - PL_NotYetImplemented(); + PortabilityLayer::MacFileProperties mfp; + if (!PortabilityLayer::FileManager::GetInstance()->ReadFileProperties(static_cast(spec->parID), spec->name, mfp)) + return fnfErr; + + finfo->fdType = PortabilityLayer::ResTypeIDCodec::Decode(mfp.m_fileType); + return noErr; } OSErr SetFPos(short refNum, SetFPosWhere where, long offset) { - PL_NotYetImplemented(); + switch (where) + { + case fsFromStart: + if (!PortabilityLayer::FileManager::GetInstance()->GetFileStream(refNum)->SeekStart(static_cast(offset))) + return ioErr; + break; + default: + return genericErr; + } + return noErr; } OSErr GetEOF(short refNum, long *byteCount) { - PL_NotYetImplemented(); + const PortabilityLayer::UFilePos_t fileSize = PortabilityLayer::FileManager::GetInstance()->GetFileStream(refNum)->Size(); + + *byteCount = static_cast(fileSize); return noErr; } @@ -454,6 +500,95 @@ OSErr PBGetCatInfo(CInfoPBPtr paramBlock, Boolean async) return noErr; } +DirectoryFileListEntry *GetDirectoryFiles(long dirID) +{ + PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance(); + PortabilityLayer::HostFileSystem *fs = PortabilityLayer::HostFileSystem::GetInstance(); + PortabilityLayer::HostDirectoryCursor *dirCursor = fs->ScanDirectory(static_cast(dirID)); + + DirectoryFileListEntry *firstDFL = nullptr; + DirectoryFileListEntry *lastDFL = nullptr; + + if (!dirCursor) + return nullptr; + + const char *filename; + char fnCopy[256]; + while (dirCursor->GetNext(filename)) + { + const size_t fnLen = strlen(filename); + if (fnLen < 5 || fnLen > 255) + continue; + + memcpy(fnCopy, filename, fnLen + 1); + + if (!strcmp(&filename[fnLen - 4], ".gpf")) + { + const size_t dotPos = fnLen - 4; + PortabilityLayer::IOStream *stream = fs->OpenFile(static_cast(dirID), filename, false, false); + if (!stream) + continue; + + PortabilityLayer::MacFileProperties mfp; + PortabilityLayer::MacFilePropertiesSerialized mfs; + + const size_t gpfSize = stream->Read(mfs.m_data, PortabilityLayer::MacFilePropertiesSerialized::kSize); + stream->Close(); + + if (gpfSize != PortabilityLayer::MacFilePropertiesSerialized::kSize) + continue; + + mfs.Deserialize(mfp); + + fnCopy[dotPos] = '\0'; + + DirectoryFileListEntry tempDFL; + tempDFL.finderInfo.fdType = PortabilityLayer::ResTypeIDCodec::Decode(mfp.m_fileType); + tempDFL.finderInfo.fdCreator = PortabilityLayer::ResTypeIDCodec::Decode(mfp.m_fileCreator); + tempDFL.nextEntry = nullptr; + if (!ConvertFilenameToSafePStr(fnCopy, tempDFL.name)) + continue; + + DirectoryFileListEntry *dfl = static_cast(mm->Alloc(sizeof(DirectoryFileListEntry))); + if (!dfl) + { + if (firstDFL) + DisposeDirectoryFiles(firstDFL); + + return nullptr; + } + + new (dfl) DirectoryFileListEntry(tempDFL); + + dfl->nextEntry = nullptr; + + if (lastDFL) + lastDFL->nextEntry = dfl; + else + firstDFL = dfl; + + lastDFL = dfl; + } + } + + dirCursor->Destroy(); + + return firstDFL; +} + +void DisposeDirectoryFiles(DirectoryFileListEntry *firstDFL) +{ + PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance(); + + DirectoryFileListEntry *dfl = firstDFL; + while (dfl) + { + DirectoryFileListEntry *nextDFL = dfl->nextEntry; + mm->Release(dfl); + dfl = nextDFL; + } +} + short StringWidth(const PLPasStr &str) { PL_NotYetImplemented(); @@ -621,12 +756,10 @@ void PurgeSpace(long *totalFree, long *contiguousFree) void HSetState(Handle handle, char state) { - PL_NotYetImplemented(); } char HGetState(Handle handle) { - PL_NotYetImplemented(); return 0; } @@ -671,6 +804,10 @@ void PL_NotYetImplemented_Minor() { } +void PL_NotYetImplemented_TODO() +{ +} + void PL_Init() { PortabilityLayer::MemoryManager::GetInstance()->Init(); diff --git a/PortabilityLayer/PLCore.h b/PortabilityLayer/PLCore.h index 4b9d649..5edc493 100644 --- a/PortabilityLayer/PLCore.h +++ b/PortabilityLayer/PLCore.h @@ -51,7 +51,7 @@ struct FileInfoBlock void *ioCompletion; short ioVRefNum; // Volume ref num StringPtr ioNamePtr; - int ioFDirIndex; // Index (1-based!) + int ioFDirIndex; // Index: If >0, Nth directory in ioVRefNum. If 0, lookup by name. If <0, do behavior that we don't support. long ioDirID; // Input: Directory ID Output: File ID int ioFlAttrib; // File attributes FinderInfoBlock ioFlFndrInfo; @@ -74,6 +74,13 @@ struct CInfoPBRec DirInfoBlock dirInfo; }; +struct DirectoryFileListEntry +{ + FinderInfoBlock finderInfo; + Str32 name; + DirectoryFileListEntry *nextEntry; +}; + struct Cursor { }; @@ -324,6 +331,7 @@ OSErr FSMakeFSSpec(int refNum, long dirID, const PLPasStr &fileName, FSSpec *spe OSErr FSpCreate(const FSSpec *spec, UInt32 creator, UInt32 fileType, ScriptCode scriptTag); OSErr FSpDirCreate(const FSSpec *spec, ScriptCode script, long *outDirID); OSErr FSpOpenDF(const FSSpec *spec, int permission, short *refNum); +OSErr FSpOpenRF(const FSSpec *spec, int permission, short *refNum); OSErr FSWrite(short refNum, long *byteCount, const void *data); OSErr FSRead(short refNum, long *byteCount, void *data); OSErr FSpDelete(const FSSpec *spec); @@ -334,6 +342,9 @@ OSErr SetEOF(short refNum, long byteCount); OSErr PBGetCatInfo(CInfoPBPtr paramBlock, Boolean async); +DirectoryFileListEntry *GetDirectoryFiles(long dirID); +void DisposeDirectoryFiles(DirectoryFileListEntry *firstDFL); + short StringWidth(const PLPasStr &str); void GetMouse(Point *point); @@ -393,6 +404,7 @@ WindowPtr PL_GetPutInFrontWindowPtr(); void PL_NotYetImplemented(); void PL_NotYetImplemented_Minor(); +void PL_NotYetImplemented_TODO(); void PL_Init(); diff --git a/PortabilityLayer/PLMenus.cpp b/PortabilityLayer/PLMenus.cpp index 9a842a3..7f98dde 100644 --- a/PortabilityLayer/PLMenus.cpp +++ b/PortabilityLayer/PLMenus.cpp @@ -1,5 +1,4 @@ -#include "PLMenus.h" - +#include "PLMenus.h" MenuHandle GetMenu(int resID) { diff --git a/PortabilityLayer/PLMovies.cpp b/PortabilityLayer/PLMovies.cpp index 499148f..db18a46 100644 --- a/PortabilityLayer/PLMovies.cpp +++ b/PortabilityLayer/PLMovies.cpp @@ -31,13 +31,13 @@ OSErr AddUserData(UserData userData, Handle data, UInt32 type) OSErr OpenMovieFile(const FSSpec *fsSpec, short *outRefNum, int permissions) { - PL_NotYetImplemented(); + PL_NotYetImplemented_TODO(); return noErr; } OSErr NewMovieFromFile(Movie *movie, short refNum, const short *optResId, StringPtr resName, int flags, Boolean *unused) { - PL_NotYetImplemented(); + PL_NotYetImplemented_TODO(); return noErr; } diff --git a/PortabilityLayer/PLQuickdraw.cpp b/PortabilityLayer/PLQuickdraw.cpp index 308857a..06edd69 100644 --- a/PortabilityLayer/PLQuickdraw.cpp +++ b/PortabilityLayer/PLQuickdraw.cpp @@ -265,7 +265,7 @@ void PaintRect(const Rect *rect) break; default: PL_NotYetImplemented(); - return; + return; } } @@ -306,7 +306,7 @@ void FrameRoundRect(const Rect *rect, int w, int h) PL_NotYetImplemented(); } -void PenMode(int mode) +void PenMode(CopyBitsMode copyBitsMode) { PL_NotYetImplemented(); } @@ -316,11 +316,6 @@ void PenMode(PenModeID penMode) PL_NotYetImplemented(); } -void PenMode(CopyBitsMode copyBitsMode) -{ - PL_NotYetImplemented(); -} - void PenPat(const Pattern *pattern) { PL_NotYetImplemented(); diff --git a/PortabilityLayer/PLQuickdraw.h b/PortabilityLayer/PLQuickdraw.h index 98ef837..e658e03 100644 --- a/PortabilityLayer/PLQuickdraw.h +++ b/PortabilityLayer/PLQuickdraw.h @@ -55,17 +55,16 @@ enum SystemFontID mobile = 24, }; -// wtf? enum SystemColorID { - whiteColor = 30, - blackColor = 33, - yellowColor = 69, - magentaColor = 137, - redColor = 205, - cyanColor = 273, - greenColor = 341, - blueColor = 409, + whiteColor = 1, + blackColor, + yellowColor, + magentaColor, + redColor, + cyanColor, + greenColor, + blueColor, }; enum CopyBitsMode @@ -73,29 +72,13 @@ enum CopyBitsMode srcCopy, srcOr, srcXor, - srcBic, - notSrcCopy, - notSrcOr, - notSrcXor, - notSrcBic, - transparent + transparent, }; enum PenModeID { - patCopy = 8, - patOr, + patOr = transparent + 1, patXor, - patBic, - notPatCopy, - notPatOr, - notPatXor, - notPatBic, -}; - -enum HiliteMode -{ - hilite = 50, }; struct CIcon @@ -165,7 +148,8 @@ void ClipRect(const Rect *rect); // Sets the clipping area void FrameRect(const Rect *rect); void FrameOval(const Rect *rect); void FrameRoundRect(const Rect *rect, int w, int h); -void PenMode(int mode); // Can be CopyBitsMode, PenModeID, and possibly add "50" to hilite +void PenMode(CopyBitsMode copyBitsMode); +void PenMode(PenModeID mode); void PenPat(const Pattern *pattern); void PenSize(int w, int h); void PenNormal(); diff --git a/PortabilityLayer/PLResourceManager.cpp b/PortabilityLayer/PLResourceManager.cpp index af3cdc6..4f72ed4 100644 --- a/PortabilityLayer/PLResourceManager.cpp +++ b/PortabilityLayer/PLResourceManager.cpp @@ -34,7 +34,16 @@ namespace PortabilityLayer static ResourceManagerImpl *GetInstance(); private: - std::vector m_resFiles; + struct ResFileSlot + { + short m_prevFile; + short m_nextFile; + ResourceFile* m_resourceFile; + }; + + std::vector m_resFiles; + short m_firstResFile; + short m_lastResFile; short m_currentResFile; bool m_load; @@ -42,7 +51,9 @@ namespace PortabilityLayer }; ResourceManagerImpl::ResourceManagerImpl() - : m_currentResFile(0) + : m_currentResFile(-1) + , m_firstResFile(-1) + , m_lastResFile(-1) , m_load(true) { } @@ -54,8 +65,8 @@ namespace PortabilityLayer void ResourceManagerImpl::Shutdown() { - for (std::vector::iterator it = m_resFiles.begin(), itEnd = m_resFiles.end(); it != itEnd; ++it) - delete (*it); + for (std::vector::iterator it = m_resFiles.begin(), itEnd = m_resFiles.end(); it != itEnd; ++it) + delete it->m_resourceFile; m_resFiles.clear(); } @@ -87,7 +98,7 @@ namespace PortabilityLayer for (size_t i = 0; i < numSlots; i++) { - if (m_resFiles[i] == nullptr) + if (m_resFiles[i].m_resourceFile == nullptr) { resFileIndex = i; break; @@ -95,11 +106,11 @@ namespace PortabilityLayer } if (resFileIndex == 0x7fff) - return 0; + return -1; IOStream *fStream = nullptr; if (FileManager::GetInstance()->RawOpenFileRF(virtualDir, filename, EFilePermission_Read, true, &fStream) != noErr) - return 0; + return -1; ResourceFile *resFile = new ResourceFile(); bool loaded = resFile->Load(fStream); @@ -108,27 +119,48 @@ namespace PortabilityLayer if (!loaded) { delete resFile; - return 0; + return -1; } - if (resFileIndex == numSlots) - m_resFiles.push_back(resFile); - else - m_resFiles[resFileIndex] = resFile; + ResFileSlot slot; + slot.m_resourceFile = resFile; + slot.m_prevFile = m_lastResFile; + slot.m_nextFile = -1; - return static_cast(resFileIndex + 1); + if (resFileIndex == numSlots) + m_resFiles.push_back(slot); + else + m_resFiles[resFileIndex] = slot; + + const short rfid = static_cast(resFileIndex); + + if (m_firstResFile < 0) + m_firstResFile = rfid; + + if (m_lastResFile >= 0) + m_resFiles[m_lastResFile].m_nextFile = rfid; + + m_lastResFile = rfid; + m_currentResFile = rfid; // Resource Manager is supposed to reset the search stack on new file open + + return rfid; } MMHandleBlock *ResourceManagerImpl::GetResource(const ResTypeID &resType, int id) { - if (!m_currentResFile) - return nullptr; + short searchIndex = m_currentResFile; + while (searchIndex >= 0) + { + const ResFileSlot& slot = m_resFiles[searchIndex]; + assert(slot.m_resourceFile); - ResourceFile *resFile = m_resFiles[m_currentResFile - 1]; - if (!resFile) - return nullptr; + if (MMHandleBlock *block = slot.m_resourceFile->GetResource(resType, id, m_load)) + return block; - return resFile->GetResource(resType, id, m_load); + searchIndex = slot.m_prevFile; + } + + return nullptr; } diff --git a/PortabilityLayer/PLResources.cpp b/PortabilityLayer/PLResources.cpp index 199bc47..2335470 100644 --- a/PortabilityLayer/PLResources.cpp +++ b/PortabilityLayer/PLResources.cpp @@ -1,12 +1,22 @@ #include "PLResources.h" +#include "HostFileSystem.h" #include "MemoryManager.h" #include "MMHandleBlock.h" +#include "PLPasStr.h" #include "ResourceManager.h" #include "ResourceCompiledRef.h" #include +struct PLOpenedResFile +{ + bool m_isOpen; +}; + +static const unsigned int kPLMaxOpenedResFiles = 64; +static PLOpenedResFile gs_resFiles[kPLMaxOpenedResFiles]; + void DetachResource(Handle hdl) { if (!hdl) @@ -32,7 +42,7 @@ short CurResFile() void UseResFile(short fid) { - PL_NotYetImplemented(); + PortabilityLayer::ResourceManager::GetInstance()->SetCurrentResFile(fid); } Handle Get1Resource(UInt32 resID, int index) @@ -66,8 +76,9 @@ OSErr ResError() short FSpOpenResFile(const FSSpec *spec, int permission) { - PL_NotYetImplemented(); - return 0; + PortabilityLayer::ResourceManager *rm = PortabilityLayer::ResourceManager::GetInstance(); + + return rm->OpenResFork(static_cast(spec->parID), PLPasStr(spec->name)); } void CloseResFile(short refNum) diff --git a/PortabilityLayer/PLStringCompare.cpp b/PortabilityLayer/PLStringCompare.cpp index b277464..6b9614a 100644 --- a/PortabilityLayer/PLStringCompare.cpp +++ b/PortabilityLayer/PLStringCompare.cpp @@ -1,7 +1,70 @@ -#include "PLStringCompare.h" +#include "PLStringCompare.h" +#include "MacLatin.h" + +#include Boolean EqualString(const PLPasStr &string1, const PLPasStr &string2, Boolean caseSensitive, Boolean diacriticSensitive) -{ - PL_NotYetImplemented(); - return false; -} \ No newline at end of file +{ + const size_t len = string1.Length(); + if (len != string2.Length()) + return PL_FALSE; + + const uint8_t *chars1 = string1.UChars(); + const uint8_t *chars2 = string2.UChars(); + + if (caseSensitive) + { + // Case sensitive + if (diacriticSensitive) + { + // Diacritic sensitive + return memcmp(chars1, chars2, len) ? PL_FALSE : PL_TRUE; + } + else + { + // Diacritic insensitive + for (size_t i = 0; i < len; i++) + { + const uint8_t c1 = chars1[i]; + const uint8_t c2 = chars2[i]; + + if (PortabilityLayer::MacLatin::g_stripDiacritic[c1] != PortabilityLayer::MacLatin::g_stripDiacritic[c2]) + return PL_FALSE; + } + + return PL_TRUE; + } + } + else + { + // Case insensitive + if (diacriticSensitive) + { + // Diacritic sensitive + for (size_t i = 0; i < len; i++) + { + const uint8_t c1 = chars1[i]; + const uint8_t c2 = chars2[i]; + + if (PortabilityLayer::MacLatin::g_toLower[c1] != PortabilityLayer::MacLatin::g_toLower[c2]) + return PL_FALSE; + } + + return PL_TRUE; + } + else + { + // Diacritic insensitive + for (size_t i = 0; i < len; i++) + { + const uint8_t c1 = PortabilityLayer::MacLatin::g_stripDiacritic[chars1[i]]; + const uint8_t c2 = PortabilityLayer::MacLatin::g_stripDiacritic[chars2[i]]; + + if (PortabilityLayer::MacLatin::g_toLower[c1] != PortabilityLayer::MacLatin::g_toLower[c2]) + return PL_FALSE; + } + + return PL_TRUE; + } + } +} diff --git a/PortabilityLayer/PortabilityLayer.vcxproj b/PortabilityLayer/PortabilityLayer.vcxproj index 83b1e4e..51193d1 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj +++ b/PortabilityLayer/PortabilityLayer.vcxproj @@ -132,9 +132,11 @@ + + @@ -147,6 +149,7 @@ + @@ -235,6 +238,7 @@ + diff --git a/PortabilityLayer/PortabilityLayer.vcxproj.filters b/PortabilityLayer/PortabilityLayer.vcxproj.filters index 1117a0a..6ddc454 100644 --- a/PortabilityLayer/PortabilityLayer.vcxproj.filters +++ b/PortabilityLayer/PortabilityLayer.vcxproj.filters @@ -315,6 +315,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + @@ -467,5 +476,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/PortabilityLayer/ResTypeIDCodec.h b/PortabilityLayer/ResTypeIDCodec.h index 4cda1c3..94e1b4e 100644 --- a/PortabilityLayer/ResTypeIDCodec.h +++ b/PortabilityLayer/ResTypeIDCodec.h @@ -16,7 +16,7 @@ namespace PortabilityLayer { public: static void Encode(int32_t id, char *chars); - static int32_t Decode(char *chars); + static int32_t Decode(const char *chars); }; template<> @@ -24,7 +24,7 @@ namespace PortabilityLayer { public: static void Encode(int32_t id, char *chars); - static int32_t Decode(char *chars); + static int32_t Decode(const char *chars); }; typedef ResTypeIDCodecResolver<'abcd'> ResTypeIDCodec; @@ -40,7 +40,7 @@ namespace PortabilityLayer chars[3] = static_cast((id >> 24) & 0xff); } - inline int32_t ResTypeIDCodecResolver<0x64636261>::Decode(char *chars) + inline int32_t ResTypeIDCodecResolver<0x64636261>::Decode(const char *chars) { return static_cast( ((chars[0] & 0xff) << 0) @@ -57,7 +57,7 @@ namespace PortabilityLayer chars[3] = static_cast((id >> 0) & 0xff); } - inline int32_t ResTypeIDCodecResolver<0x61626364>::Decode(char *chars) + inline int32_t ResTypeIDCodecResolver<0x61626364>::Decode(const char *chars) { return static_cast( ((chars[0] & 0xff) << 24) diff --git a/PortabilityLayer/VirtualDirectory.h b/PortabilityLayer/VirtualDirectory.h index ec7f156..0ccff67 100644 --- a/PortabilityLayer/VirtualDirectory.h +++ b/PortabilityLayer/VirtualDirectory.h @@ -1,15 +1,14 @@ -#pragma once -#ifndef __PL_VIRTUALDIRECTORY_H__ -#define __PL_VIRTUALDIRECTORY_H__ - -namespace PortabilityLayer -{ - enum EVirtualDirectory - { - EVirtualDirectory_ApplicationData = 1, - EVirtualDirectory_GameData, - EVirtualDirectory_Prefs, - }; -} - -#endif +#pragma once + +namespace PortabilityLayer +{ + enum EVirtualDirectory + { + EVirtualDirectory_Unspecified = 0, + + EVirtualDirectory_ApplicationData = 1, + EVirtualDirectory_GameData, + EVirtualDirectory_UserData, + EVirtualDirectory_Prefs, + }; +}