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,
+ };
+}