Various improvements toward getting high scores working again.

This commit is contained in:
elasota
2020-02-02 01:38:38 -05:00
parent 7cb6994f90
commit 265db139c8
48 changed files with 729 additions and 488 deletions

View File

@@ -85,7 +85,7 @@ namespace PortabilityLayer
int16_t ExecuteModal(DialogFilterFunc_t filterFunc) override;
bool Populate(DialogTemplate *tmpl);
bool Populate(DialogTemplate *tmpl, const DialogTextSubstitutions *substitutions);
void DrawControls(bool redraw);
@@ -97,6 +97,8 @@ namespace PortabilityLayer
explicit DialogImpl(Window *window, DialogItem *items, size_t numItems);
~DialogImpl();
static void MakeStringSubstitutions(uint8_t *outStr, const uint8_t *inStr, const DialogTextSubstitutions *substitutions);
Window *m_window;
DialogItem *m_items;
size_t m_numItems;
@@ -268,7 +270,7 @@ namespace PortabilityLayer
}
}
bool DialogImpl::Populate(DialogTemplate *tmpl)
bool DialogImpl::Populate(DialogTemplate *tmpl, const DialogTextSubstitutions *substitutions)
{
Window *window = this->GetWindow();
@@ -282,10 +284,13 @@ namespace PortabilityLayer
Widget *widget = nullptr;
Str255 substitutedStr;
MakeStringSubstitutions(substitutedStr, templateItem.m_name, substitutions);
WidgetBasicState basicState;
basicState.m_enabled = templateItem.m_enabled;
basicState.m_resID = templateItem.m_id;
basicState.m_text = PascalStr<255>(PLPasStr(templateItem.m_name));
basicState.m_text = PascalStr<255>(PLPasStr(substitutedStr));
basicState.m_rect = templateItem.m_rect;
basicState.m_window = window;
@@ -304,8 +309,8 @@ namespace PortabilityLayer
widget = ImageWidget::Create(basicState);
break;
case SerializedDialogItemTypeCodes::kCheckBox:
//widget = CheckboxWidget::Create(basicState);
//break;
widget = CheckboxWidget::Create(basicState);
break;
case SerializedDialogItemTypeCodes::kRadioButton:
widget = RadioButtonWidget::Create(basicState);
break;
@@ -338,6 +343,49 @@ namespace PortabilityLayer
return Point::Create(x, y);
}
void DialogImpl::MakeStringSubstitutions(uint8_t *outStr, const uint8_t *inStr, const DialogTextSubstitutions *substitutions)
{
if (substitutions == nullptr)
{
memcpy(outStr, inStr, inStr[0] + 1);
return;
}
const uint8_t inStrLen = inStr[0];
const uint8_t *inStrChar = inStr + 1;
uint8_t *outStrChar = outStr + 1;
uint8_t outStrRemaining = 255;
uint8_t inStrRemaining = inStr[0];
while (outStrRemaining > 0 && inStrRemaining > 0)
{
if ((*inStrChar) != '^' || inStrRemaining < 2 || inStrChar[1] < static_cast<uint8_t>('0') || inStrChar[1] > static_cast<uint8_t>('3'))
{
*outStrChar++ = *inStrChar++;
inStrRemaining--;
outStrRemaining--;
}
else
{
const int subIndex = inStrChar[1] - '0';
inStrChar += 2;
inStrRemaining -= 2;
const uint8_t *substitution = substitutions->m_strings[subIndex];
const uint8_t substitutionLength = substitution[0];
const uint8_t *substitutionChars = substitution + 1;
const uint8_t copyLength = (substitutionLength < outStrRemaining) ? substitutionLength : outStrRemaining;
memcpy(outStrChar, substitutionChars, copyLength);
outStrChar += copyLength;
outStrRemaining -= copyLength;
}
}
outStr[0] = static_cast<uint8_t>(outStrChar - (outStr + 1));
}
DialogImpl *DialogImpl::Create(Window *window, size_t numItems)
{
size_t alignedSize = sizeof(DialogImpl) + GP_SYSTEM_MEMORY_ALIGNMENT + 1;
@@ -391,8 +439,8 @@ namespace PortabilityLayer
class DialogManagerImpl final : public DialogManager
{
public:
Dialog *LoadDialog(int16_t resID, Window *behindWindow) override;
int16_t DisplayAlert(int16_t alertResID) override;
Dialog *LoadDialog(int16_t resID, Window *behindWindow, const DialogTextSubstitutions *substitutions) override;
int16_t DisplayAlert(int16_t alertResID, const DialogTextSubstitutions *substitutions) override;
DialogTemplate *LoadDialogTemplate(int16_t resID);
@@ -404,7 +452,7 @@ namespace PortabilityLayer
static DialogManagerImpl ms_instance;
};
Dialog *DialogManagerImpl::LoadDialog(int16_t resID, Window *behindWindow)
Dialog *DialogManagerImpl::LoadDialog(int16_t resID, Window *behindWindow, const DialogTextSubstitutions *substitutions)
{
ResourceManager *rm = ResourceManager::GetInstance();
@@ -459,7 +507,7 @@ namespace PortabilityLayer
return nullptr;
}
if (!dialog->Populate(dtemplate))
if (!dialog->Populate(dtemplate, substitutions))
{
dialog->Destroy();
dtemplate->Destroy();
@@ -473,12 +521,8 @@ namespace PortabilityLayer
return dialog;
}
int16_t DialogManagerImpl::DisplayAlert(int16_t alertResID)
int16_t DialogManagerImpl::DisplayAlert(int16_t alertResID, const DialogTextSubstitutions *substitutions)
{
enum AlertStageBits
{
};
struct AlertResourceData
{
BERect m_rect;

View File

@@ -3,6 +3,7 @@
#include <stdint.h>
struct Dialog;
struct DialogTextSubstitutions;
struct Window;
struct TimeTaggedVOSEvent;
@@ -13,8 +14,8 @@ namespace PortabilityLayer
class DialogManager
{
public:
virtual Dialog *LoadDialog(int16_t resID, Window *behindWindow) = 0;
virtual int16_t DisplayAlert(int16_t alertResID) = 0;
virtual Dialog *LoadDialog(int16_t resID, Window *behindWindow, const DialogTextSubstitutions *substitutions) = 0;
virtual int16_t DisplayAlert(int16_t alertResID, const DialogTextSubstitutions *substitutions) = 0;
static DialogManager *GetInstance();
};

View File

@@ -1,9 +1,14 @@
#include "PLCheckboxWidget.h"
#include "PLStandardColors.h"
#include "FontFamily.h"
#include <algorithm>
namespace PortabilityLayer
{
CheckboxWidget::CheckboxWidget(const WidgetBasicState &state)
: WidgetSpec<CheckboxWidget>(state)
, m_text(state.m_text)
{
}
@@ -17,4 +22,51 @@ namespace PortabilityLayer
return true;
}
void CheckboxWidget::DrawControl(DrawSurface *surface)
{
if (!m_rect.IsValid())
return;
surface->SetForeColor(StdColors::White());
surface->FillRect(m_rect);
uint16_t checkFrameSize = std::min<uint16_t>(12, std::min(m_rect.Width(), m_rect.Height()));
int16_t top = (m_rect.top + m_rect.bottom - static_cast<int16_t>(checkFrameSize)) / 2;
surface->SetForeColor(StdColors::Black());
const Rect checkRect = Rect::Create(top, m_rect.left, top + static_cast<int16_t>(checkFrameSize), m_rect.left + static_cast<int16_t>(checkFrameSize));
surface->FillRect(checkRect);
surface->SetForeColor(StdColors::White());
surface->FillRect(checkRect.Inset(1, 1));
if (m_state)
{
surface->SetForeColor(StdColors::Black());
surface->DrawLine(Point::Create(checkRect.left + 1, checkRect.top + 1), Point::Create(checkRect.right - 2, checkRect.bottom - 2));
surface->DrawLine(Point::Create(checkRect.right - 2, checkRect.top + 1), Point::Create(checkRect.left + 1, checkRect.bottom - 2));
}
surface->SetForeColor(StdColors::Black());
surface->SetSystemFont(12, FontFamilyFlag_Bold);
int32_t textV = (m_rect.top + m_rect.bottom + surface->MeasureFontAscender()) / 2;
surface->DrawString(Point::Create(m_rect.left + checkFrameSize + 2, textV), m_text.ToShortStr(), true);
}
void CheckboxWidget::SetString(const PLPasStr &str)
{
m_text = PascalStr<255>(str);
}
PLPasStr CheckboxWidget::GetString() const
{
return m_text.ToShortStr();
}
void CheckboxWidget::OnStateChanged()
{
if (m_window)
DrawControl(&m_window->m_surface);
}
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "PascalStr.h"
#include "PLWidgets.h"
namespace PortabilityLayer
@@ -11,5 +12,14 @@ namespace PortabilityLayer
~CheckboxWidget();
bool Init(const WidgetBasicState &state) override;
void DrawControl(DrawSurface *surface) override;
void SetString(const PLPasStr &str) override;
PLPasStr GetString() const override;
void OnStateChanged() override;
private:
PascalStr<255> m_text;
};
}

View File

@@ -328,11 +328,6 @@ void NumToString(long number, unsigned char *str)
str[0] = static_cast<uint8_t>(strLength);
}
void ParamText(const PLPasStr &title, const PLPasStr &a, const PLPasStr &b, const PLPasStr &c)
{
PL_NotYetImplemented();
}
PLError_t AEProcessAppleEvent(EventRecord *evt)
{
PL_NotYetImplemented();
@@ -553,11 +548,6 @@ short Random()
return static_cast<short>(static_cast<int32_t>(rWord) - 0x8000);
}
void GetDateTime(UInt32 *dateTime)
{
PL_NotYetImplemented();
}
void GetTime(DateTimeRec *dateTime)
{
unsigned int year;

View File

@@ -57,34 +57,6 @@ struct FinderInfoBlock
Int32 fdCreator;
};
struct FileInfoBlock
{
void *ioCompletion;
short ioVRefNum; // Volume ref num
StringPtr ioNamePtr;
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;
long ioFlParID;
};
struct DirInfoBlock
{
void *ioCompletion;
short ioVRefNum;
long ioDrDirID;
unsigned char *ioNamePtr;
short ioFDirIndex;
int ioFlAttrib;
};
struct CInfoPBRec
{
FileInfoBlock hFileInfo;
DirInfoBlock dirInfo;
};
struct DirectoryFileListEntry
{
FinderInfoBlock finderInfo;
@@ -182,7 +154,6 @@ struct EventRecord
typedef Window *WindowPtr;
typedef Cursor *CursPtr;
typedef Menu *MenuPtr;
typedef CInfoPBRec *CInfoPBPtr;
typedef VersionRecord *VersRecPtr;
typedef THandle<Cursor> CursHandle;
@@ -274,7 +245,6 @@ short LoWord(Int32 v);
short HiWord(Int32 v);
void NumToString(long number, unsigned char *str);
void ParamText(const PLPasStr &title, const PLPasStr &a, const PLPasStr &b, const PLPasStr &c);
PLError_t AEProcessAppleEvent(EventRecord *evt);
@@ -293,7 +263,6 @@ Boolean StillDown();
Boolean WaitMouseUp();
short Random();
void GetDateTime(UInt32 *dateTime);
void GetTime(DateTimeRec *dateTime);
UInt32 GetDblTime();

View File

@@ -1,4 +1,48 @@
#include "PLDialogs.h"
#include "PLPasStr.h"
DialogTextSubstitutions::DialogTextSubstitutions()
{
Init(0, nullptr);
}
DialogTextSubstitutions::DialogTextSubstitutions(const PLPasStr& str0)
{
Init(1, &str0);
}
DialogTextSubstitutions::DialogTextSubstitutions(const PLPasStr& str0, const PLPasStr& str1)
{
PLPasStr strs[] = { str0, str1 };
Init(2, strs);
}
DialogTextSubstitutions::DialogTextSubstitutions(const PLPasStr& str0, const PLPasStr& str1, const PLPasStr& str2)
{
PLPasStr strs[] = { str0, str1, str2 };
Init(3, strs);
}
DialogTextSubstitutions::DialogTextSubstitutions(const PLPasStr& str0, const PLPasStr& str1, const PLPasStr& str2, const PLPasStr& str3)
{
PLPasStr strs[] = { str0, str1, str2, str3 };
Init(4, strs);
}
void DialogTextSubstitutions::Init(size_t numItems, const PLPasStr *items)
{
for (int i = 0; i < numItems; i++)
{
const uint8_t len = items[i].Length();
m_strings[i][0] = len;
if (len)
memcpy(m_strings[i] + 1, items[i].UChars(), len);
}
for (size_t i = numItems; i < 4; i++)
m_strings[i][0] = 0;
}
void DrawDialog(Dialog *dialog)
{
@@ -17,11 +61,6 @@ DrawSurface *GetDialogPort(Dialog *dialog)
return nullptr;
}
void GetDialogItem(Dialog *dialog, int index, short *itemType, THandle<Control> *itemHandle, Rect *itemRect)
{
PL_NotYetImplemented();
}
void GetDialogItemText(THandle<Control> handle, StringPtr str)
{
PL_NotYetImplemented();
@@ -39,7 +78,7 @@ void SetDialogItemText(THandle<Control> handle, const PLPasStr &str)
void SelectDialogItemText(Dialog *dialog, int item, int firstSelChar, int lastSelCharExclusive)
{
PL_NotYetImplemented();
PL_NotYetImplemented_TODO("TextBox_Critical");
}
ModalFilterUPP NewModalFilterUPP(ModalFilterUPP func)

View File

@@ -16,6 +16,20 @@ struct Dialog;
typedef int16_t(*DialogFilterFunc_t)(Dialog *dialog, const TimeTaggedVOSEvent &evt);
struct DialogTextSubstitutions
{
Str255 m_strings[4];
DialogTextSubstitutions();
explicit DialogTextSubstitutions(const PLPasStr& str0);
DialogTextSubstitutions(const PLPasStr& str0, const PLPasStr& str1);
DialogTextSubstitutions(const PLPasStr& str0, const PLPasStr& str1, const PLPasStr& str2);
DialogTextSubstitutions(const PLPasStr& str0, const PLPasStr& str1, const PLPasStr& str2, const PLPasStr& str3);
private:
void Init(size_t numItems, const PLPasStr *items);
};
struct Dialog
{
virtual void Destroy() = 0;
@@ -33,7 +47,6 @@ typedef Boolean(*ModalFilterUPP)(Dialog *dial, EventRecord *event, short *item);
void DrawDialog(Dialog *dialog);
DrawSurface *GetDialogPort(Dialog *dialog);
void GetDialogItem(Dialog *dialog, int index, short *itemType, THandle<Control> *itemHandle, Rect *itemRect);
void GetDialogItemText(THandle<Control> handle, StringPtr str);
void SetDialogItem(Dialog *dialog, int index, short itemType, THandle<Control> itemHandle, const Rect *itemRect);

View File

@@ -13,5 +13,5 @@ bool IsMacPlusSoundBanned()
// High scores disabled until dialogs work
bool IsHighScoreDisabled()
{
return true;
return false;
}

View File

@@ -52,13 +52,13 @@ namespace KeyEventEitherSpecialCategories
intptr_t PackVOSKeyCode(const GpKeyboardInputEvent &evt);
struct KeyDownStates
{
GpBitfield<GpKeySpecials::kCount> m_special;
GpBitfield<128> m_ascii;
GpBitfield<128> m_macRoman;
GpBitfield<10> m_numPadNumber;
{
GpBitfield<GpKeySpecials::kCount> m_special;
GpBitfield<128> m_ascii;
GpBitfield<128> m_macRoman;
GpBitfield<10> m_numPadNumber;
GpBitfield<GpNumPadSpecials::kCount> m_numPadSpecial;
GpBitfield<GpFKeyMaximumInclusive> m_fKey;
GpBitfield<GpFKeyMaximumInclusive> m_fKey;
GpBitfield<GpGamepadButtons::kCount> m_gamepadButtons[PL_INPUT_MAX_PLAYERS];
bool IsSet(intptr_t packedVOSCode) const;

View File

@@ -19,8 +19,22 @@ namespace PortabilityLayer
return true;
}
void LabelWidget::SetString(const PLPasStr &str)
{
m_text.Set(str.Length(), str.Chars());
}
PLPasStr LabelWidget::GetString() const
{
return m_text.ToShortStr();
}
void LabelWidget::DrawControl(DrawSurface *surface)
{
// FIXME: This is kind of bad
surface->SetForeColor(StdColors::White());
surface->FillRect(m_rect);
surface->SetSystemFont(12, PortabilityLayer::FontFamilyFlag_Bold);
surface->SetForeColor(StdColors::Black());

View File

@@ -12,6 +12,9 @@ namespace PortabilityLayer
bool Init(const WidgetBasicState &state) override;
void SetString(const PLPasStr &str) override;
PLPasStr GetString() const override;
void DrawControl(DrawSurface *surface) override;
private:

View File

@@ -820,9 +820,9 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds)
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
const unsigned int combinedValue = srcLow | (srcHigh << 8);
const unsigned int b = (srcLow & 0x1f);
const unsigned int g = ((srcLow >> 5) & 0x1f);
const unsigned int r = ((srcLow >> 10) & 0x1f);
const unsigned int b = (combinedValue & 0x1f);
const unsigned int g = ((combinedValue >> 5) & 0x1f);
const unsigned int r = ((combinedValue >> 10) & 0x1f);
if (r + g + b > 46)
currentDestRow[destColIndex] = 0;
@@ -866,9 +866,9 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds)
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
const unsigned int combinedValue = srcLow | (srcHigh << 8);
const unsigned int b = (srcLow & 0x1f);
const unsigned int g = ((srcLow >> 5) & 0x1f);
const unsigned int r = ((srcLow >> 10) & 0x1f);
const unsigned int b = (combinedValue & 0x1f);
const unsigned int g = ((combinedValue >> 5) & 0x1f);
const unsigned int r = ((combinedValue >> 10) & 0x1f);
if (r + g + b > 46)
currentDestRow[destColIndex] = 0;

View File

@@ -28,16 +28,23 @@ namespace PortabilityLayer
if (!m_rect.IsValid())
return;
surface->SetForeColor(StdColors::White());
surface->FillRect(m_rect);
uint16_t radioFrameSize = std::min<uint16_t>(12, std::min(m_rect.Width(), m_rect.Height()));
int16_t top = (m_rect.top + m_rect.bottom - static_cast<int16_t>(radioFrameSize)) / 2;
surface->SetForeColor(StdColors::Black());
const Rect radioRect = Rect::Create(top, m_rect.left, top + static_cast<int16_t>(radioFrameSize), m_rect.left + static_cast<int16_t>(radioFrameSize));
surface->FillEllipse(radioRect);
if (!m_state)
surface->SetForeColor(StdColors::White());
surface->FillEllipse(radioRect.Inset(1, 1));
if (m_state)
{
surface->SetForeColor(StdColors::White());
surface->FillEllipse(radioRect.Inset(1, 1));
surface->SetForeColor(StdColors::Black());
surface->FillEllipse(radioRect.Inset(3, 3));
}
surface->SetForeColor(StdColors::Black());
@@ -51,4 +58,14 @@ namespace PortabilityLayer
m_text = PascalStr<255>(str);
}
PLPasStr RadioButtonWidget::GetString() const
{
return m_text.ToShortStr();
}
void RadioButtonWidget::OnStateChanged()
{
if (m_window)
DrawControl(&m_window->m_surface);
}
}

View File

@@ -15,6 +15,9 @@ namespace PortabilityLayer
void DrawControl(DrawSurface *surface) override;
void SetString(const PLPasStr &str) override;
PLPasStr GetString() const override;
void OnStateChanged() override;
private:
PascalStr<255> m_text;

View File

@@ -10,7 +10,7 @@ struct TimeTaggedVOSEvent
static TimeTaggedVOSEvent Create(const GpVOSEvent &vosEvent, uint32_t timestamp);
// Helpers for common cases
bool IsKeyDownEvent() const;
bool IsKeyDownEvent() const; // Only returns true for untranslated keydown events
bool IsLMouseDownEvent() const;
bool IsLMouseUpEvent() const;
};

View File

@@ -89,6 +89,11 @@ namespace PortabilityLayer
(void)str;
}
PLPasStr Widget::GetString() const
{
return PSTR("");
}
const Rect &Widget::GetRect() const
{
return m_rect;

View File

@@ -60,6 +60,8 @@ namespace PortabilityLayer
bool IsVisible() const;
virtual void SetString(const PLPasStr &str);
virtual PLPasStr GetString() const;
virtual void SetHighlightStyle(int16_t style);
const Rect &GetRect() const;