Removed windows.h dependency.

Added support for music in MDS format.
This commit is contained in:
Muzychenko Andrey 2021-09-06 16:27:58 +03:00
parent e0638c598d
commit 2fe6d6d33a
20 changed files with 386 additions and 910 deletions

View File

@ -15,7 +15,7 @@ int Sound::Init(int voices)
num_channels = channelCount; num_channels = channelCount;
enabled_flag = -1; enabled_flag = -1;
return Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024) == -1; return Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024);
} }
void Sound::Enable(int channelFrom, int channelTo, int enableFlag) void Sound::Enable(int channelFrom, int channelTo, int enableFlag)

View File

@ -38,7 +38,7 @@ int main(int argc, char* argv[])
auto xx = sizeof(datFileHeader); auto xx = sizeof(datFileHeader);
lstrcpyA(winmain::DatFileName, "PINBALL.DAT"); strcpy_s(winmain::DatFileName, "PINBALL.DAT");
pb::init(); pb::init();
auto datFile = pb::record_table; auto datFile = pb::record_table;

View File

@ -229,14 +229,14 @@ TPinballComponent* TPinballTable::find_component(LPCSTR componentName)
for (int index = 0; index < objCount; ++index) for (int index = 0; index < objCount; ++index)
{ {
TPinballComponent* obj = ComponentList->Get(index); TPinballComponent* obj = ComponentList->Get(index);
const CHAR* groupName = obj->GroupName; const char* groupName = obj->GroupName;
if (groupName && !lstrcmpA(groupName, componentName)) if (groupName && !strcmp(groupName, componentName))
{ {
return obj; return obj;
} }
} }
} }
MessageBoxA(nullptr, "Table cant find:", componentName, 0x2000u); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Table cant find:", componentName, nullptr);
return nullptr; return nullptr;
} }
@ -254,7 +254,7 @@ TPinballComponent* TPinballTable::find_component(int groupIndex)
} }
} }
_itoa_s(groupIndex, Buffer, 10); _itoa_s(groupIndex, Buffer, 10);
MessageBoxA(nullptr, "Table cant find (lh):", Buffer, 0x2000u); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Table cant find (lh):", Buffer, nullptr);
return nullptr; return nullptr;
} }

View File

@ -117,9 +117,8 @@ int fullscrn::get_max_supported_resolution()
if (!pb::FullTiltMode) if (!pb::FullTiltMode)
return 0; return 0;
auto resolutionWH = get_screen_resolution(); int width = 0, height = 0;
auto width = LOWORD(resolutionWH); get_screen_resolution(&width, &height);
auto height = HIWORD(resolutionWH);
auto result = 0; auto result = 0;
for (auto index = 1; index < 3; ++index) for (auto index = 1; index < 3; ++index)
@ -131,10 +130,16 @@ int fullscrn::get_max_supported_resolution()
return result; return result;
} }
int fullscrn::get_screen_resolution() int fullscrn::get_screen_resolution(int* width, int* height)
{ {
auto height = static_cast<uint16_t>(GetSystemMetrics(SM_CYSCREEN)); SDL_DisplayMode dm;
return static_cast<uint16_t>(GetSystemMetrics(SM_CXSCREEN)) | (height << 16); if (SDL_GetDesktopDisplayMode(0, &dm) == 0)
{
*width = dm.w;
*height = dm.h;
return 0;
}
return 1;
} }
void fullscrn::window_size_changed() void fullscrn::window_size_changed()

View File

@ -29,7 +29,7 @@ public:
static int GetMaxResolution(); static int GetMaxResolution();
static void SetMaxResolution(int resolution); static void SetMaxResolution(int resolution);
static int get_max_supported_resolution(); static int get_max_supported_resolution();
static int get_screen_resolution(); static int get_screen_resolution(int* width, int* height);
static void window_size_changed(); static void window_size_changed();
private : private :
static int resolution; static int resolution;

View File

@ -33,17 +33,6 @@ union ColorRgba
}; };
static_assert(sizeof(ColorRgba) == 4, "Wrong size of RGBA color"); static_assert(sizeof(ColorRgba) == 4, "Wrong size of RGBA color");
struct LOGPALETTEx256 : LOGPALETTE
{
PALETTEENTRY palPalEntry2[256 - 1];
LOGPALETTEx256() : palPalEntry2{}
{
palVersion = 0x300;
palNumEntries = 256;
}
};
class gdrv class gdrv
{ {

View File

@ -54,15 +54,15 @@ int high_score::read(high_score_struct* table, int* ptrToSmth)
{ {
auto tablePtr = &table[position]; auto tablePtr = &table[position];
_itoa_s(position, Buffer, 10); _itoa_s(position, Buffer, 10);
lstrcatA(Buffer, ".Name"); strcat_s(Buffer, ".Name");
options::get_string(optPath, Buffer, buf1, "", 32); options::get_string(optPath, Buffer, buf1, "", 32);
buf1[32] = 0; buf1[32] = 0;
lstrcpyA(tablePtr->Name, buf1); strcpy_s(tablePtr->Name, buf1);
_itoa_s(position, Buffer, 10); _itoa_s(position, Buffer, 10);
lstrcatA(Buffer, ".Score"); strcat_s(Buffer, ".Score");
options::get_string(optPath, Buffer, buf1, "", 300); options::get_string(optPath, Buffer, buf1, "", 300);
tablePtr->Score = atol(buf1); tablePtr->Score = atol(buf1);
for (int i = lstrlenA(tablePtr->Name); --i >= 0; scoreSum += tablePtr->Name[i]) for (int i = (int)strlen(tablePtr->Name); --i >= 0; scoreSum += tablePtr->Name[i])
{ {
} }
scoreSum += tablePtr->Score; scoreSum += tablePtr->Score;
@ -70,7 +70,7 @@ int high_score::read(high_score_struct* table, int* ptrToSmth)
scramble_number_string(scoreSum, buf1); scramble_number_string(scoreSum, buf1);
options::get_string(optPath, "Verification", buf2, "", 300); options::get_string(optPath, "Verification", buf2, "", 300);
if (lstrcmpA(buf1, buf2)) if (strcmp(buf1, buf2) != 0)
clear_table(table); clear_table(table);
memory::free(buf1); memory::free(buf1);
memory::free(buf2); memory::free(buf2);
@ -83,20 +83,20 @@ int high_score::write(high_score_struct* table, int* ptrToSmth)
high_score_struct* tablePtr = table; high_score_struct* tablePtr = table;
int scoreSum = 0; int scoreSum = 0;
CHAR* buf = memory::allocate(300u); char* buf = memory::allocate(300u);
if (!buf) if (!buf)
return 1; return 1;
const CHAR* optPath = pinball::get_rc_string(166, 0); const char* optPath = pinball::get_rc_string(166, 0);
for (auto position = 0; position < 5; ++position) for (auto position = 0; position < 5; ++position)
{ {
_itoa_s(position, Buffer, 10); _itoa_s(position, Buffer, 10);
lstrcatA(Buffer, ".Name"); strcat_s(Buffer, ".Name");
options::set_string(optPath, Buffer, tablePtr->Name); options::set_string(optPath, Buffer, tablePtr->Name);
_itoa_s(position, Buffer, 10); _itoa_s(position, Buffer, 10);
lstrcatA(Buffer, ".Score"); strcat_s(Buffer, ".Score");
_ltoa_s(tablePtr->Score, buf, 300, 10); _ltoa_s(tablePtr->Score, buf, 300, 10);
options::set_string(optPath, Buffer, buf); options::set_string(optPath, Buffer, buf);
for (int i = lstrlenA(tablePtr->Name); --i >= 0; scoreSum += tablePtr->Name[i]) for (int i = (int)strlen(tablePtr->Name); --i >= 0; scoreSum += tablePtr->Name[i])
{ {
} }
scoreSum += tablePtr->Score; scoreSum += tablePtr->Score;
@ -150,9 +150,9 @@ int high_score::place_new_score_into(high_score_struct* table, int score, LPSTR
} }
high_score_struct* posTable = &table[position]; high_score_struct* posTable = &table[position];
posTable->Score = score; posTable->Score = score;
if (lstrlenA(scoreStr) >= 31) if (strlen(scoreStr) >= 31)
scoreStr[31] = 0; scoreStr[31] = 0;
lstrcpyA(posTable->Name, scoreStr); strcpy_s(posTable->Name, scoreStr);
posTable->Name[31] = 0; posTable->Name[31] = 0;
} }
return position; return position;

View File

@ -13,7 +13,6 @@ errorMsg loader::loader_errors[] =
errorMsg{0, "Bad Handle"}, errorMsg{0, "Bad Handle"},
errorMsg{1, "No Type Field"}, errorMsg{1, "No Type Field"},
errorMsg{2, "No Attributes Field"}, errorMsg{2, "No Attributes Field"},
errorMsg{0x0B, "No float Attributes Field"},
errorMsg{3, "Wrong Type: MATERIAL Expected"}, errorMsg{3, "Wrong Type: MATERIAL Expected"},
errorMsg{4, "Wrong Type: KICKER Expected"}, errorMsg{4, "Wrong Type: KICKER Expected"},
errorMsg{5, "Wrong Type: AN_OBJECT Expected"}, errorMsg{5, "Wrong Type: AN_OBJECT Expected"},
@ -21,6 +20,7 @@ errorMsg loader::loader_errors[] =
errorMsg{7, "STATES (re)defined in a state"}, errorMsg{7, "STATES (re)defined in a state"},
errorMsg{9, "Unrecognized Attribute"}, errorMsg{9, "Unrecognized Attribute"},
errorMsg{0x0A, "Unrecognized float Attribute"}, errorMsg{0x0A, "Unrecognized float Attribute"},
errorMsg{0x0B, "No float Attributes Field"},
errorMsg{0x0D, "float Attribute not found"}, errorMsg{0x0D, "float Attribute not found"},
errorMsg{0x0C, "state_index out of range"}, errorMsg{0x0C, "state_index out of range"},
errorMsg{0x0F, "loader_material() reports failure"}, errorMsg{0x0F, "loader_material() reports failure"},
@ -63,7 +63,7 @@ int loader::error(int errorCode, int captionCode)
if (!errorText) if (!errorText)
errorText = loader_errors[index].Message; errorText = loader_errors[index].Message;
MessageBoxA(nullptr, errorText, errorCaption, 0x2000u); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, errorCaption, errorText, nullptr);
return -1; return -1;
} }

View File

@ -7,14 +7,31 @@
Mix_Music* midi::currentMidi; Mix_Music* midi::currentMidi;
MCIERROR midi::play_pb_theme(int flag) #define FOURCC(a,b,c,d) ( (uint32_t) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a)) )
int ToVariableLen(uint32_t value, uint32_t& dst)
{
auto count = 1;
dst = value & 0x7F;
while ((value >>= 7))
{
dst <<= 8;
dst |= ((value & 0x7F) | 0x80);
count++;
}
return count;
}
int midi::play_pb_theme(int flag)
{ {
if (pb::FullTiltMode) if (pb::FullTiltMode)
{ {
return play_ft(track1); return play_ft(track1);
} }
MCIERROR result = 0; int result = 0;
music_stop(); music_stop();
if (currentMidi) if (currentMidi)
result = Mix_PlayMusic(currentMidi, -1); result = Mix_PlayMusic(currentMidi, -1);
@ -22,7 +39,7 @@ MCIERROR midi::play_pb_theme(int flag)
return result; return result;
} }
MCIERROR midi::music_stop() int midi::music_stop()
{ {
if (pb::FullTiltMode) if (pb::FullTiltMode)
{ {
@ -43,21 +60,6 @@ int midi::music_init()
return currentMidi != nullptr; return currentMidi != nullptr;
} }
MCIERROR midi::restart_midi_seq(LPARAM param)
{
if (pb::FullTiltMode)
{
return play_ft(active_track);
}
MCIERROR result = 0;
music_stop();
if (currentMidi)
result = Mix_PlayMusic(currentMidi, -1);
return result;
}
void midi::music_shutdown() void midi::music_shutdown()
{ {
if (pb::FullTiltMode) if (pb::FullTiltMode)
@ -70,14 +72,14 @@ void midi::music_shutdown()
} }
objlist_class<midi_struct>* midi::TrackList; objlist_class<Mix_Music>* midi::TrackList;
midi_struct *midi::track1, *midi::track2, *midi::track3, *midi::active_track, *midi::active_track2; Mix_Music *midi::track1, *midi::track2, *midi::track3, *midi::active_track, *midi::active_track2;
int midi::some_flag1; int midi::some_flag1;
int midi::music_init_ft() int midi::music_init_ft()
{ {
active_track = nullptr; active_track = nullptr;
TrackList = new objlist_class<midi_struct>(0, 1); TrackList = new objlist_class<Mix_Music>(0, 1);
track1 = load_track("taba1"); track1 = load_track("taba1");
track2 = load_track("taba2"); track2 = load_track("taba2");
@ -92,260 +94,50 @@ int midi::music_init_ft()
void midi::music_shutdown_ft() void midi::music_shutdown_ft()
{ {
if (active_track) if (active_track)
stream_close(active_track); Mix_HaltMusic();
while (TrackList->GetCount()) while (TrackList->GetCount())
{ {
midi_struct* midi = TrackList->Get(0); auto midi = TrackList->Get(0);
unload_track(midi); Mix_FreeMusic(midi);
TrackList->Delete(midi); TrackList->Delete(midi);
} }
active_track = nullptr; active_track = nullptr;
delete TrackList; delete TrackList;
} }
midi_struct* midi::load_track(LPCSTR fileName) Mix_Music* midi::load_track(LPCSTR fileName)
{ {
midi_struct* midi;
char filePath[256]; char filePath[256];
char fileName2[256]; char fileName2[256];
lstrcpyA(fileName2, "sound\\"); strcpy_s(fileName2, "sound\\");
lstrcatA(fileName2, fileName); strcat_s(fileName2, fileName);
pinball::make_path_name(filePath, fileName2, 254u); pinball::make_path_name(filePath, fileName2, 254u);
lstrcatA(filePath, ".MDS"); strcat_s(filePath, ".MDS");
if (load_file(&midi, filePath, 0, 1)) auto midi = MdsToMidi(filePath);
if (!midi)
return nullptr; return nullptr;
if (midi) auto rw = SDL_RWFromMem(midi->data(), static_cast<int>(midi->size()));
TrackList->Add(midi); auto audio = Mix_LoadMUS_RW(rw, 0);
return midi; SDL_FreeRW(rw);
delete midi;
if (!audio)
return nullptr;
// Dump converted MIDI file
/*FILE* fileHandle;
strcpy_s(fileName2, fileName);
strcat_s(fileName2, ".midi");
fopen_s(&fileHandle, fileName2, "wb");
fwrite(midi->data(), 1, midi->size(), fileHandle);
fclose(fileHandle);*/
TrackList->Add(audio);
return audio;
} }
int midi::load_file(midi_struct** midi_res, void* filePtrOrPath, int fileSizeP, int flags) int midi::play_ft(Mix_Music* midi)
{
int returnCode;
unsigned int fileSize;
HANDLE mapHandle = nullptr;
midi_struct* midi = nullptr;
HANDLE fileHandle = INVALID_HANDLE_VALUE;
int fileFlag = 0;
do
{
if ((flags & 3) == 0 || (flags & 3) == 3)
{
returnCode = 4;
break;
}
midi = static_cast<midi_struct*>(LocalAlloc(0x40u, sizeof(midi_struct)));
if (!midi)
{
returnCode = 1;
break;
}
midi->Magic = mmioFOURCC('M', 'D', 'S', 'I');
midi->StreamHandle = nullptr;
midi->PreparedBlocksCount = 0;
if ((flags & 2) != 0)
{
fileSize = fileSizeP;
}
else
{
fileFlag = 1;
fileHandle = CreateFileA(static_cast<LPCSTR>(filePtrOrPath), GENERIC_READ, 1u, nullptr, OPEN_EXISTING,
0x80u, nullptr);
if (fileHandle == INVALID_HANDLE_VALUE)
{
returnCode = 2;
break;
}
fileSize = GetFileSize(fileHandle, nullptr);
mapHandle = CreateFileMappingA(fileHandle, nullptr, 2u, 0, 0, nullptr);
if (!mapHandle)
{
returnCode = 2;
break;
}
filePtrOrPath = MapViewOfFile(mapHandle, 4u, 0, 0, 0);
if (!filePtrOrPath)
{
returnCode = 2;
break;
}
}
returnCode = read_file(midi, static_cast<riff_header*>(filePtrOrPath), fileSize);
}
while (false);
if (returnCode)
{
if (midi)
LocalFree(midi);
}
else
{
*midi_res = midi;
}
if (fileFlag)
{
if (filePtrOrPath)
UnmapViewOfFile(filePtrOrPath);
if (mapHandle)
CloseHandle(mapHandle);
if (fileHandle != INVALID_HANDLE_VALUE)
CloseHandle(fileHandle);
}
return returnCode;
}
int midi::read_file(midi_struct* midi, riff_header* filePtr, unsigned fileSize)
{
auto returnCode = 0;
do
{
midi->DataPtr1 = nullptr;
if (fileSize < 12)
{
returnCode = 3;
break;
}
if (filePtr->Riff != mmioFOURCC('R', 'I', 'F', 'F'))
{
returnCode = 3;
break;
}
if (filePtr->Mids != mmioFOURCC('M', 'I', 'D', 'S'))
{
returnCode = 3;
break;
}
if (filePtr->FileSize > fileSize - 8)
{
returnCode = 3;
break;
}
if (fileSize - 12 < 8)
{
returnCode = 3;
break;
}
if (filePtr->Fmt != mmioFOURCC('f', 'm', 't', ' '))
{
returnCode = 3;
break;
}
if (filePtr->FmtSize > fileSize - 12)
{
returnCode = 3;
break;
}
if (filePtr->FmtSize < 12)
{
returnCode = 3;
break;
}
midi->DwTimeFormat = filePtr->dwTimeFormat;
midi->CbMaxBuffer = filePtr->cbMaxBuffer;
midi->DwFlagsFormat = filePtr->dwFlags;
auto blocksSize = fileSize - 20 - filePtr->FmtSize;
if (blocksSize < 8)
{
returnCode = 3;
break;
}
auto dataChunk = reinterpret_cast<riff_data*>(reinterpret_cast<char*>(&filePtr->dwTimeFormat) + filePtr->FmtSize
);
if (dataChunk->Data != mmioFOURCC('d','a','t','a'))
{
returnCode = 3;
break;
}
if (dataChunk->DataSize > blocksSize || dataChunk->DataSize < 4)
{
returnCode = 3;
break;
}
midi->BlockCount = dataChunk->BlocksPerChunk;
midi->DataPtr1 = reinterpret_cast<midihdr_tag*>(memory::allocate(
dataChunk->BlocksPerChunk * (midi->CbMaxBuffer + sizeof(midihdr_tag))));
if (!midi->DataPtr1)
{
returnCode = 1;
break;
}
if (!midi->BlockCount)
{
returnCode = 3;
break;
}
auto blocksSizeIndex = blocksSize - 12;
auto srcPtr = dataChunk->Blocks;
auto* dstPtr = midi->DataPtr1;
for (auto blockIndex = midi->BlockCount; blockIndex; blockIndex--)
{
dstPtr->lpData = reinterpret_cast<LPSTR>(&dstPtr[1]);
dstPtr->dwBufferLength = midi->CbMaxBuffer;
dstPtr->dwFlags = 0;
dstPtr->dwUser = reinterpret_cast<DWORD_PTR>(midi);
dstPtr->lpNext = nullptr;
if (blocksSizeIndex < 8)
{
returnCode = 3;
break;
}
auto blockSize = srcPtr->CbBuffer;
if (blockSize > midi->CbMaxBuffer || blockSize > blocksSizeIndex - 8)
{
returnCode = 3;
break;
}
if ((midi->DwFlagsFormat & 1) != 0)
{
/*Not used in FT, some kind of compression*/
assertm(false, "Unimplemented code reached");
/*int a1[16];
a1[0] = (int)blockDataPtr;
a1[2] = blockSize;
a1[1] = blockSize;
if (!sub_4031A0(a1, dataPtr))
{
returnCode = 3; break;
}*/
}
else
{
dstPtr->dwBytesRecorded = blockSize;
memcpy(dstPtr->lpData, srcPtr->AData, blockSize);
}
blocksSizeIndex -= blockSize + 8;
srcPtr = reinterpret_cast<riff_block*>(&srcPtr->AData[blockSize]);
dstPtr = reinterpret_cast<midihdr_tag*>(reinterpret_cast<char*>(&dstPtr[1]) + midi->CbMaxBuffer);
}
}
while (false);
if (returnCode && midi->DataPtr1)
{
memory::free(midi->DataPtr1);
}
return returnCode;
}
int midi::play_ft(midi_struct* midi)
{ {
int result; int result;
@ -357,7 +149,7 @@ int midi::play_ft(midi_struct* midi)
active_track2 = midi; active_track2 = midi;
return 0; return 0;
} }
if (stream_open(midi, 1)) if (Mix_PlayMusic(midi, -1))
{ {
active_track = nullptr; active_track = nullptr;
result = 0; result = 0;
@ -374,114 +166,170 @@ int midi::stop_ft()
{ {
int returnCode = 0; int returnCode = 0;
if (active_track) if (active_track)
returnCode = stream_close(active_track); returnCode = Mix_HaltMusic();
active_track = nullptr; active_track = nullptr;
return returnCode; return returnCode;
} }
int midi::unload_track(midi_struct* midi) /// <summary>
/// SDL_mixed does not support MIDS. To support FT music, a conversion to MIDI is required.
/// </summary>
/// <param name="file">Path to .MDS file</param>
/// <returns>Vector that contains MIDI file</returns>
std::vector<uint8_t>* midi::MdsToMidi(char* file)
{ {
if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I')) FILE* fileHandle;
return 6; if (fopen_s(&fileHandle, file, "rb"))
if (midi->StreamHandle) return nullptr;
stream_close(midi);
if (midi->DataPtr1)
{
memory::free(midi->DataPtr1);
}
midi->Magic = mmioFOURCC('d','a','t','a');
LocalFree(midi);
return 0;
}
int midi::stream_open(midi_struct* midi, char flags) fseek(fileHandle, 0, SEEK_END);
{ auto fileSize = static_cast<uint32_t>(ftell(fileHandle));
auto returnCode = 0; auto filePtr = reinterpret_cast<riff_header*>(memory::allocate(fileSize));
if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I')) fseek(fileHandle, 0, SEEK_SET);
return 6; fread(filePtr, 1, fileSize, fileHandle);
fclose(fileHandle);
/*UINT puDeviceID = -1; int returnCode = 0;
auto steamOpenedFg = !midi->StreamHandle; std::vector<uint8_t>* midiOut = nullptr;
MIDIPROPTIMEDIV propdata{8, midi->DwTimeFormat}; do
if (steamOpenedFg &&
!midiStreamOpen(&midi->StreamHandle, &puDeviceID, 1u, reinterpret_cast<DWORD_PTR>(midi_callback), 0,
CALLBACK_FUNCTION) &&
!midiStreamProperty(midi->StreamHandle, reinterpret_cast<LPBYTE>(&propdata),MIDIPROP_TIMEDIV | MIDIPROP_SET))
{ {
midihdr_tag* blockPtr = midi->DataPtr1; if (fileSize < 12)
for (auto blockIndex = midi->BlockCount; blockIndex; blockIndex--)
{ {
if (midiOutPrepareHeader(reinterpret_cast<HMIDIOUT>(midi->StreamHandle), blockPtr, sizeof(MIDIHDR)) || returnCode = 3;
midiStreamOut(midi->StreamHandle, blockPtr, sizeof(MIDIHDR))) break;
}
if (filePtr->Riff != FOURCC('R', 'I', 'F', 'F') ||
filePtr->Mids != FOURCC('M', 'I', 'D', 'S') ||
filePtr->Fmt != FOURCC('f', 'm', 't', ' '))
{
returnCode = 3;
break;
}
if (filePtr->FileSize > fileSize - 8)
{
returnCode = 3;
break;
}
if (fileSize - 12 < 8)
{
returnCode = 3;
break;
}
if (filePtr->FmtSize < 12 || filePtr->FmtSize > fileSize - 12)
{
returnCode = 3;
break;
}
auto streamIdUsed = filePtr->dwFlags == 0;
auto dataChunk = reinterpret_cast<riff_data*>(reinterpret_cast<char*>(&filePtr->dwTimeFormat) + filePtr->
FmtSize);
if (dataChunk->Data != FOURCC('d', 'a', 't', 'a'))
{
returnCode = 3;
break;
}
if (dataChunk->DataSize < 4)
{
returnCode = 3;
break;
}
auto srcPtr = dataChunk->Blocks;
std::vector<midi_event_x2> midiEvents{};
for (auto blockIndex = dataChunk->BlocksPerChunk; blockIndex; blockIndex--)
{
auto eventSizeInt = streamIdUsed ? 3 : 2;
auto eventCount = srcPtr->CbBuffer / (4 * eventSizeInt);
auto currentTicks = srcPtr->TkStart;
auto srcPtr2 = reinterpret_cast<uint32_t*>(srcPtr->AData);
for (auto i = 0u; i < eventCount; i++)
{ {
returnCode = 5; currentTicks += srcPtr2[0];
break; auto event = streamIdUsed ? srcPtr2[2] : srcPtr2[1];
midiEvents.push_back({currentTicks, event});
srcPtr2 += eventSizeInt;
} }
++midi->PreparedBlocksCount; srcPtr = reinterpret_cast<riff_block*>(&srcPtr->AData[srcPtr->CbBuffer]);
blockPtr = reinterpret_cast<midihdr_tag*>(reinterpret_cast<char*>(&blockPtr[1]) + blockPtr->dwBufferLength);
} }
}
if (!returnCode) // MIDS events can be out of order in the file
{ std::sort(midiEvents.begin(), midiEvents.end(), [](const auto& lhs, const auto& rhs)
if (!steamOpenedFg && (midi->SomeFlag2 & 4) == 0)
return 7;
midi->SomeFlag2 &= ~2;
if ((flags & 1) != 0)
midi->SomeFlag2 |= 2;
midi->SomeFlag2 &= ~4;
if (midiStreamRestart(midi->StreamHandle))
returnCode = 5;
}
if (returnCode && steamOpenedFg)
{
if (midi->StreamHandle)
stream_close(midi);
}*/
return returnCode;
}
int midi::stream_close(midi_struct* midi)
{
int returnCode = 0;
/*if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I'))
return 6;
if (!midi->StreamHandle)
return 7;
midi->SomeFlag2 |= 1u;
if (midiOutReset(reinterpret_cast<HMIDIOUT>(midi->StreamHandle)))
{
returnCode = 5;
midi->SomeFlag2 &= ~1;
}
else
{
midihdr_tag* blockPtr = midi->DataPtr1;
for (int i = midi->BlockCount; i; --i)
{ {
midiOutUnprepareHeader(reinterpret_cast<HMIDIOUT>(midi->StreamHandle), blockPtr, sizeof(MIDIHDR)); return lhs.iTicks < rhs.iTicks;
blockPtr = reinterpret_cast<midihdr_tag*>(reinterpret_cast<char*>(&blockPtr[1]) + blockPtr->dwBufferLength); });
}
midiStreamClose(midi->StreamHandle);
returnCode = 0;
midi->StreamHandle = nullptr;
midi->SomeFlag2 = 0;
}*/
return returnCode;
}
void midi::midi_callback(HMIDIOUT hmo, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) // MThd chunk
{ std::vector<uint8_t>& midiBytes = *new std::vector<uint8_t>();
if (wMsg == 969) midiOut = &midiBytes;
{ midi_header header(SwapByteOrderShort(static_cast<uint16_t>(filePtr->dwTimeFormat)));
auto mhdr = reinterpret_cast<LPMIDIHDR>(dwParam1); auto headerData = reinterpret_cast<const uint8_t*>(&header);
auto midi = reinterpret_cast<midi_struct*>(mhdr->dwUser); midiBytes.insert(midiBytes.end(), headerData, headerData + sizeof header);
/*if ((midi->SomeFlag2 & 2) == 0 || (midi->SomeFlag2 & 1) != 0 || midiStreamOut(
midi->StreamHandle, mhdr, sizeof(MIDIHDR))) // MTrk chunk
--midi->PreparedBlocksCount;*/ midi_track track(7);
auto trackData = reinterpret_cast<const uint8_t*>(&track);
midiBytes.insert(midiBytes.end(), trackData, trackData + sizeof track);
auto lengthPos = midiBytes.size() - 4;
auto prevTime = 0u;
for (const auto& event : midiEvents)
{
assertm(event.iTicks >= prevTime, "MIDS events: negative delta-time");
uint32_t delta = event.iTicks - prevTime;
prevTime = event.iTicks;
// Delta time is in variable quantity, Big Endian
uint32_t deltaVarLen;
auto count = ToVariableLen(delta, deltaVarLen);
deltaVarLen = SwapByteOrderInt(deltaVarLen);
auto deltaData = reinterpret_cast<const uint8_t*>(&deltaVarLen) + 4 - count;
midiBytes.insert(midiBytes.end(), deltaData, deltaData + count);
switch (event.iEvent >> 24)
{
case 0:
{
// Type 0 - MIDI short message. 3 bytes: xx p1 p2 00, where xx - message, p* - parameters
// Some of the messages have only one parameter
auto msgMask = (event.iEvent) & 0xF0;
auto shortMsg = (msgMask == 0xC0 || msgMask == 0xD0);
auto eventData = reinterpret_cast<const uint8_t*>(&event.iEvent);
midiBytes.insert(midiBytes.end(), eventData, eventData + (shortMsg ? 2 : 3));
break;
}
case 1:
{
// Type 1 - tempo change, 3 bytes: xx xx xx 01
// Meta message, set tempo, 3 bytes payload
const uint8_t metaSetTempo[] = {0xFF, 0x51, 0x03};
midiBytes.insert(midiBytes.end(), metaSetTempo, metaSetTempo + 3);
auto eventBE = SwapByteOrderInt(event.iEvent);
auto eventData = reinterpret_cast<const uint8_t*>(&eventBE) + 1;
midiBytes.insert(midiBytes.end(), eventData, eventData + 3);
break;
}
default:
assertm(0, "MIDS events: uknown event");
break;
}
}
// Meta message, end of track, 0 bytes payload
const uint8_t metaEndTrack[] = {0x00, 0xFF, 0x2f, 0x00};
midiBytes.insert(midiBytes.end(), metaEndTrack, metaEndTrack + 4);
// Set final MTrk size
*(uint32_t*)&midiBytes[lengthPos] = SwapByteOrderInt((uint32_t)midiBytes.size() - sizeof header - sizeof track);
} }
while (false);
if (filePtr)
memory::free(filePtr);
if (returnCode && midiOut)
delete midiOut;
return midiOut;
} }

View File

@ -1,18 +1,18 @@
#pragma once #pragma once
#include "objlist_class.h" #include "objlist_class.h"
struct midi_struct constexpr uint32_t SwapByteOrderInt(uint32_t val)
{ {
DWORD Magic; return (val >> 24) |
DWORD DwTimeFormat; ((val << 8) & 0x00FF0000) |
DWORD CbMaxBuffer; ((val >> 8) & 0x0000FF00) |
DWORD DwFlagsFormat; (val << 24);
midihdr_tag* DataPtr1; }
HMIDISTRM StreamHandle;
int SomeFlag2; constexpr uint16_t SwapByteOrderShort(uint16_t val)
int BlockCount; {
int PreparedBlocksCount; return static_cast<uint16_t>((val >> 8) | (val << 8));
}; }
#pragma pack(push) #pragma pack(push)
#pragma pack(1) #pragma pack(1)
@ -44,35 +44,71 @@ struct riff_header
riff_data Data; riff_data Data;
}; };
struct midi_event_x2
{
DWORD iTicks;
DWORD iEvent;
};
struct midi_event_x3
{
DWORD iTicks;
DWORD iStreamID;
DWORD iEvent;
};
struct midi_header
{
explicit midi_header(uint16_t tickdiv)
: tickdiv(tickdiv)
{
}
const char MThd[4]{ 'M','T','h','d' };
const uint32_t chunklen = SwapByteOrderInt(6);
const int16_t format = SwapByteOrderShort(0);
const uint16_t ntracks = SwapByteOrderShort(1);
uint16_t tickdiv;
};
struct midi_track
{
explicit midi_track(uint32_t chunklen)
: chunklen(chunklen)
{
}
const char MTrk[4]{ 'M','T','r','k' };
uint32_t chunklen;
};
static_assert(sizeof(riff_block) == 0xC, "Wrong size of riff_block"); static_assert(sizeof(riff_block) == 0xC, "Wrong size of riff_block");
static_assert(sizeof(riff_data) == 0x18, "Wrong size of riff_data"); static_assert(sizeof(riff_data) == 0x18, "Wrong size of riff_data");
static_assert(sizeof(riff_header) == 0x38, "Wrong size of riff_header"); static_assert(sizeof(riff_header) == 0x38, "Wrong size of riff_header");
static_assert(sizeof(midi_event_x3) == 12, "Wrong size of midi_event3");
static_assert(sizeof(midi_event_x2) == 8, "Wrong size of midi_event2");
static_assert(sizeof(midi_header) == 14, "Wrong size of midi_header");
static_assert(sizeof(midi_track) == 8, "Wrong size of midi_track");
#pragma pack(pop) #pragma pack(pop)
class midi class midi
{ {
public: public:
static MCIERROR play_pb_theme(int flag); static int play_pb_theme(int flag);
static MCIERROR music_stop(); static int music_stop();
static int music_init(); static int music_init();
static MCIERROR restart_midi_seq(LPARAM param);
static void music_shutdown(); static void music_shutdown();
private: private:
static Mix_Music* currentMidi; static Mix_Music* currentMidi;
static objlist_class<midi_struct>* TrackList; static objlist_class<Mix_Music>* TrackList;
static midi_struct *track1, *track2, *track3, *active_track, *active_track2; static Mix_Music *track1, *track2, *track3, *active_track, *active_track2;
static int some_flag1; static int some_flag1;
static int music_init_ft(); static int music_init_ft();
static void music_shutdown_ft(); static void music_shutdown_ft();
static midi_struct* load_track(LPCSTR fileName); static Mix_Music* load_track(LPCSTR fileName);
static int load_file(midi_struct** midi_res, void* filePtrOrPath, int fileSizeP, int flags); static int play_ft(Mix_Music* midi);
static int read_file(midi_struct* midi, riff_header* filePtr, unsigned int fileSize);
static int play_ft(midi_struct* midi);
static int stop_ft(); static int stop_ft();
static int unload_track(midi_struct* midi); static std::vector<uint8_t>* MdsToMidi(char* file);
static int stream_open(midi_struct* midi, char flags);
static int stream_close(midi_struct* midi);
static void CALLBACK midi_callback(HMIDIOUT hmo, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,
DWORD_PTR dwParam2);
}; };

View File

@ -11,7 +11,6 @@
LPCSTR options::OptionsRegPath; LPCSTR options::OptionsRegPath;
LPSTR options::OptionsRegPathCur; LPSTR options::OptionsRegPathCur;
HMENU options::MenuHandle;
optionsStruct options::Options{}; optionsStruct options::Options{};
winhelp_entry options::keymap_help[18] winhelp_entry options::keymap_help[18]
@ -68,14 +67,12 @@ short options::vk_list[28]
-1 -1
}; };
void options::init(HMENU menuHandle) void options::init()
{ {
MenuHandle = menuHandle;
Options.Sounds = 1; Options.Sounds = 1;
Options.Music = 0; Options.Music = 0;
Options.FullScreen = 0; Options.FullScreen = 0;
Options.Average = 5; Options.Average = 5;
Options.PriorityAdj = 2;
Options.LeftFlipperKeyDft = SDLK_z; Options.LeftFlipperKeyDft = SDLK_z;
Options.RightFlipperKeyDft = SDLK_SLASH; Options.RightFlipperKeyDft = SDLK_SLASH;
Options.PlungerKeyDft = SDLK_SPACE; Options.PlungerKeyDft = SDLK_SPACE;
@ -109,29 +106,7 @@ void options::init(HMENU menuHandle)
Options.RightTableBumpKey = get_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey); Options.RightTableBumpKey = get_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey);
Options.BottomTableBumpKey = get_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey); Options.BottomTableBumpKey = get_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey);
Options.UniformScaling = get_int(nullptr, "Uniform scaling", true);*/ Options.UniformScaling = get_int(nullptr, "Uniform scaling", true);*/
menu_check(Menu1_Sounds, Options.Sounds);
Sound::Enable(0, 7, Options.Sounds); Sound::Enable(0, 7, Options.Sounds);
menu_check(Menu1_Music, Options.Music);
menu_check(Menu1_Full_Screen, Options.FullScreen);
menu_check(Menu1_1Player, Options.Players == 1);
menu_check(Menu1_2Players, Options.Players == 2);
menu_check(Menu1_3Players, Options.Players == 3);
menu_check(Menu1_4Players, Options.Players == 4);
menu_check(Menu1_WindowUniformScale, Options.UniformScaling);
auto tmpBuf = memory::allocate(0x1F4u);
if (tmpBuf)
{
get_string(nullptr, "Shell Exe", tmpBuf, "", 500);
if (!*tmpBuf)
{
if (MenuHandle)
{
DeleteMenu(MenuHandle, Menu1_Select_Table, 0);
DrawMenuBar(nullptr);
}
}
memory::free(tmpBuf);
}
update_resolution_menu(); update_resolution_menu();
} }
@ -154,10 +129,10 @@ void options::uninit()
void options::path_init(LPCSTR regPath) void options::path_init(LPCSTR regPath)
{ {
char* buf = memory::allocate(lstrlenA(regPath) + 1); char* buf = memory::allocate(strlen(regPath) + 1);
OptionsRegPath = buf; OptionsRegPath = buf;
if (buf) if (buf)
lstrcpyA(buf, regPath); strcpy_s(buf, strlen(regPath) + 1, regPath);
} }
void options::path_uninit() void options::path_uninit()
@ -172,16 +147,16 @@ LPCSTR options::path(LPCSTR regPath)
char* buf = OptionsRegPathCur; char* buf = OptionsRegPathCur;
if (!OptionsRegPathCur) if (!OptionsRegPathCur)
{ {
buf = memory::allocate(0x7D0u); buf = memory::allocate(2000);
OptionsRegPathCur = buf; OptionsRegPathCur = buf;
if (!buf) if (!buf)
return OptionsRegPath; return OptionsRegPath;
} }
lstrcpyA(buf, OptionsRegPath); strcpy_s(buf, 2000, OptionsRegPath);
if (!regPath) if (!regPath)
return OptionsRegPathCur; return OptionsRegPathCur;
lstrcatA(OptionsRegPathCur, "\\"); strcat_s(OptionsRegPathCur, 2000, "\\");
lstrcatA(OptionsRegPathCur, regPath); strcat_s(OptionsRegPathCur, 2000, regPath);
return OptionsRegPathCur; return OptionsRegPathCur;
} }
@ -195,92 +170,45 @@ void options::path_free()
int options::get_int(LPCSTR optPath, LPCSTR lpValueName, int defaultValue) int options::get_int(LPCSTR optPath, LPCSTR lpValueName, int defaultValue)
{ {
DWORD dwDisposition;
HKEY hKey;
auto result = defaultValue; auto result = defaultValue;
if (!OptionsRegPath) if (!OptionsRegPath)
return result; return result;
auto regPath = path(optPath); auto regPath = path(optPath);
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, &dwDisposition))
{
DWORD bufferSize = 4;
RegQueryValueExA(hKey, lpValueName, nullptr, nullptr, reinterpret_cast<LPBYTE>(&result), &bufferSize);
RegCloseKey(hKey);
}
path_free(); path_free();
return result; return result;
} }
void options::set_int(LPCSTR optPath, LPCSTR lpValueName, int data) void options::set_int(LPCSTR optPath, LPCSTR lpValueName, int data)
{ {
DWORD dwDisposition;
HKEY hKey;
if (!OptionsRegPath) if (!OptionsRegPath)
return; return;
auto regPath = path(optPath); auto regPath = path(optPath);
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, &dwDisposition))
{
RegSetValueExA(hKey, lpValueName, 0, 4u, reinterpret_cast<LPBYTE>(&data), 4u);
RegCloseKey(hKey);
}
path_free(); path_free();
} }
void options::get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR dst, LPCSTR defaultValue, int iMaxLength) void options::get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR dst, LPCSTR defaultValue, int iMaxLength)
{ {
DWORD dwDisposition; strncpy_s(dst, iMaxLength, defaultValue, iMaxLength);
HKEY hKey;
lstrcpynA(dst, defaultValue, iMaxLength);
if (!OptionsRegPath) if (!OptionsRegPath)
return; return;
auto regPath = path(optPath); auto regPath = path(optPath);
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, &dwDisposition))
{
DWORD bufferSize = iMaxLength;
RegQueryValueExA(hKey, lpValueName, nullptr, nullptr, reinterpret_cast<LPBYTE>(dst), &bufferSize);
RegCloseKey(hKey);
}
path_free(); path_free();
} }
void options::set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value) void options::set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value)
{ {
DWORD dwDisposition;
HKEY hKey;
if (!OptionsRegPath) if (!OptionsRegPath)
return; return;
auto regPath = path(optPath); auto regPath = path(optPath);
if (!RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, &dwDisposition))
{
RegSetValueExA(hKey, lpValueName, 0, 1u, LPBYTE(value), lstrlenA(value) + 1);
RegCloseKey(hKey);
}
path_free(); path_free();
} }
void options::menu_check(UINT uIDCheckItem, int check) void options::toggle(uint32_t uIDCheckItem)
{
if (MenuHandle)
CheckMenuItem(MenuHandle, uIDCheckItem, check != 0 ? 8 : 0);
}
void options::menu_set(UINT uIDEnableItem, int enable)
{
if (MenuHandle)
EnableMenuItem(MenuHandle, uIDEnableItem, enable == 0);
}
void options::toggle(UINT uIDCheckItem)
{ {
int newValue; int newValue;
switch (uIDCheckItem) switch (uIDCheckItem)
@ -289,7 +217,6 @@ void options::toggle(UINT uIDCheckItem)
newValue = Options.Sounds == 0; newValue = Options.Sounds == 0;
Options.Sounds = Options.Sounds == 0; Options.Sounds = Options.Sounds == 0;
Sound::Enable(0, 7, newValue); Sound::Enable(0, 7, newValue);
menu_check(uIDCheckItem, newValue);
return; return;
case Menu1_Music: case Menu1_Music:
newValue = Options.Music == 0; newValue = Options.Music == 0;
@ -298,31 +225,25 @@ void options::toggle(UINT uIDCheckItem)
midi::music_stop(); midi::music_stop();
else else
midi::play_pb_theme(0); midi::play_pb_theme(0);
menu_check(uIDCheckItem, newValue);
return; return;
case Menu1_Full_Screen: case Menu1_Full_Screen:
newValue = Options.FullScreen == 0; newValue = Options.FullScreen == 0;
Options.FullScreen = Options.FullScreen == 0; Options.FullScreen = Options.FullScreen == 0;
fullscrn::set_screen_mode(newValue); fullscrn::set_screen_mode(newValue);
menu_check(uIDCheckItem, newValue);
return; return;
case Menu1_1Player: case Menu1_1Player:
case Menu1_2Players: case Menu1_2Players:
case Menu1_3Players: case Menu1_3Players:
case Menu1_4Players: case Menu1_4Players:
Options.Players = uIDCheckItem - Menu1_1Player + 1; Options.Players = uIDCheckItem - Menu1_1Player + 1;
menu_check(Menu1_1Player, Options.Players == 1);
menu_check(Menu1_2Players, Options.Players == 2);
menu_check(Menu1_3Players, Options.Players == 3);
menu_check(Menu1_4Players, Options.Players == 4);
break; break;
case Menu1_MaximumResolution: case Menu1_MaximumResolution:
case Menu1_640x480: case Menu1_640x480:
case Menu1_800x600: case Menu1_800x600:
case Menu1_1024x768: case Menu1_1024x768:
{ {
for (unsigned i = Menu1_MaximumResolution; i <= Menu1_1024x768; ++i) /*for (unsigned i = Menu1_MaximumResolution; i <= Menu1_1024x768; ++i)
menu_check(i, i == uIDCheckItem); menu_check(i, i == uIDCheckItem);*/
int newResolution = uIDCheckItem - Menu1_640x480; int newResolution = uIDCheckItem - Menu1_640x480;
if (uIDCheckItem == Menu1_MaximumResolution) if (uIDCheckItem == Menu1_MaximumResolution)
@ -340,7 +261,6 @@ void options::toggle(UINT uIDCheckItem)
} }
case Menu1_WindowUniformScale: case Menu1_WindowUniformScale:
Options.UniformScaling ^= true; Options.UniformScaling ^= true;
menu_check(Menu1_WindowUniformScale, Options.UniformScaling);
fullscrn::window_size_changed(); fullscrn::window_size_changed();
pb::paint(); pb::paint();
break; break;
@ -353,8 +273,8 @@ void options::update_resolution_menu()
{ {
auto maxResolution = fullscrn::get_max_supported_resolution(); auto maxResolution = fullscrn::get_max_supported_resolution();
fullscrn::SetMaxResolution(maxResolution); fullscrn::SetMaxResolution(maxResolution);
const CHAR* maxResText = pinball::get_rc_string(maxResolution + 2030, 0); const char* maxResText = pinball::get_rc_string(maxResolution + 2030, 0);
if (MenuHandle) /*if (MenuHandle)
ModifyMenuA(MenuHandle, Menu1_MaximumResolution, 0, Menu1_MaximumResolution, maxResText); ModifyMenuA(MenuHandle, Menu1_MaximumResolution, 0, Menu1_MaximumResolution, maxResText);
for (auto resIndex = 0; resIndex < 3; resIndex++) for (auto resIndex = 0; resIndex < 3; resIndex++)
@ -368,7 +288,7 @@ void options::update_resolution_menu()
if (Options.Resolution >= 0) if (Options.Resolution >= 0)
menu_check(fullscrn::resolution_array[fullscrn::GetResolution()].ResolutionMenuId, 1); menu_check(fullscrn::resolution_array[fullscrn::GetResolution()].ResolutionMenuId, 1);
else else
menu_check(Menu1_MaximumResolution, 1); menu_check(Menu1_MaximumResolution, 1);*/
} }
void options::init_resolution() void options::init_resolution()
@ -390,192 +310,3 @@ void options::keyboard()
{ {
//DialogBoxParamA(nullptr, "KEYMAPPER", nullptr, KeyMapDlgProc, 0); //DialogBoxParamA(nullptr, "KEYMAPPER", nullptr, KeyMapDlgProc, 0);
} }
INT_PTR _stdcall options::KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
char keyName[20];
int keyBindings[6];
char rcString[256];
switch (msg)
{
case WM_HELP:
WinHelpA(static_cast<HWND>(reinterpret_cast<HELPINFO*>(lParam)->hItemHandle), "pinball.hlp", HELP_WM_HELP,
(ULONG_PTR)keymap_help);
return 1;
case WM_CONTEXTMENU:
WinHelpA((HWND)wParam, "pinball.hlp", HELP_CONTEXTMENU, (ULONG_PTR)keymap_help);
return 1;
case WM_INITDIALOG:
for (auto vkPtr = vk_list; *vkPtr != -1; vkPtr++)
{
short vk = *vkPtr;
auto vk2And = vk & 0x4000;
auto vkChar = static_cast<uint8_t>(vk);
unsigned short maxVk;
if (vk2And)
{
auto index = 128;
do
{
if (vkChar == MapVirtualKeyA(index, MAPVK_VK_TO_CHAR))
break;
++index;
}
while (index < 256);
if (index == 256)
{
continue;
}
keyName[0] = static_cast<char>(vkChar);
keyName[1] = 0;
vkChar = index;
maxVk = index;
}
else
{
if (vk >= 0)
{
maxVk = vkChar;
}
else
{
++vkPtr;
maxVk = *vkPtr;
}
if (vkChar > maxVk)
{
continue;
}
}
for (int curVK = vkChar; curVK <= maxVk; curVK++)
{
if (vk2And || get_vk_key_name(curVK, keyName))
{
auto ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL,CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.LeftFlipperKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.RightFlipperKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.PlungerKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.LeftTableBumpKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.RightTableBumpKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_SETCURSEL, ind, 0);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_INSERTSTRING, -1, (LPARAM)keyName);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_SETITEMDATA, ind, curVK);
if (curVK == Options.BottomTableBumpKey)
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_SETCURSEL, ind, 0);
}
}
}
return 1;
case WM_COMMAND:
switch (wParam)
{
case KEYMAPPER_Ok:
{
auto ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_GETCURSEL, 0, 0);
keyBindings[0] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_GETCURSEL, 0, 0);
keyBindings[1] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_GETCURSEL, 0, 0);
keyBindings[2] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_GETCURSEL, 0, 0);
keyBindings[3] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_GETCURSEL, 0, 0);
keyBindings[4] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_GETITEMDATA, ind, 0));
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_GETCURSEL, 0, 0);
keyBindings[5] = static_cast<int>(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_GETITEMDATA, ind, 0));
auto sameKeyBound = 0;
auto index = 1;
auto optPtr = keyBindings;
while (!sameKeyBound)
{
for (auto keyInd = index; keyInd < 6; keyInd++)
{
if (sameKeyBound)
break;
if (*optPtr == keyBindings[keyInd])
{
lstrcpyA(rcString, pinball::get_rc_string(43, 0));
MessageBoxA(hDlg, pinball::get_rc_string(39, 0), rcString, 0x2000u);
sameKeyBound = 1;
}
}
++index;
++optPtr;
if (index - 1 >= 5)
{
if (sameKeyBound)
return 1;
Options.LeftFlipperKey = keyBindings[0];
Options.RightFlipperKey = keyBindings[1];
Options.PlungerKey = keyBindings[2];
Options.LeftTableBumpKey = keyBindings[3];
Options.RightTableBumpKey = keyBindings[4];
Options.BottomTableBumpKey = keyBindings[5];
EndDialog(hDlg, wParam);
return 1;
}
}
return 1;
}
case KEYMAPPER_Cancel:
EndDialog(hDlg, wParam);
return 1;
case KEYMAPPER_Default:
{
auto name = (LPARAM)get_vk_key_name(Options.LeftFlipperKeyDft, keyName);
auto ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.RightFlipperKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.PlungerKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.LeftTableBumpKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.RightTableBumpKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_SETCURSEL, ind, 0);
name = (LPARAM)get_vk_key_name(Options.BottomTableBumpKeyDft, keyName);
ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_FINDSTRINGEXACT, 0, name);
SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_SETCURSEL, ind, 0);
return 0;
}
default:
return 0;
}
default:
break;
}
return 0;
}
LPSTR options::get_vk_key_name(uint16_t vk, LPSTR keyName)
{
LONG scanCode = MapVirtualKeyA(vk, MAPVK_VK_TO_VSC) << 16;
if (vk >= 0x21u && vk <= 0x2Eu)
scanCode |= 0x1000000u;
return GetKeyNameTextA(scanCode, keyName, 19) != 0 ? keyName : nullptr;
}

View File

@ -7,7 +7,6 @@ struct optionsStruct
int Music; int Music;
int Average; int Average;
int FullScreen; int FullScreen;
int PriorityAdj;
int Players; int Players;
int LeftFlipperKey; int LeftFlipperKey;
int RightFlipperKey; int RightFlipperKey;
@ -29,7 +28,7 @@ struct optionsStruct
class options class options
{ {
public: public:
static void init(HMENU menuHandle); static void init();
static void uninit(); static void uninit();
static void path_init(LPCSTR regPath); static void path_init(LPCSTR regPath);
static void path_uninit(); static void path_uninit();
@ -37,15 +36,11 @@ public:
static void set_int(LPCSTR optPath, LPCSTR lpValueName, int data); static void set_int(LPCSTR optPath, LPCSTR lpValueName, int data);
static void get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR dst, LPCSTR defaultValue, int iMaxLength); static void get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR dst, LPCSTR defaultValue, int iMaxLength);
static void set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value); static void set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value);
static void menu_check(UINT uIDCheckItem, int check); static void toggle(uint32_t uIDCheckItem);
static void menu_set(UINT uIDEnableItem, int enable);
static void toggle(UINT uIDCheckItem);
static void update_resolution_menu(); static void update_resolution_menu();
static void init_resolution(); static void init_resolution();
static void keyboard(); static void keyboard();
static INT_PTR _stdcall KeyMapDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
static LPSTR get_vk_key_name(uint16_t vk, LPSTR keyName);
static optionsStruct Options; static optionsStruct Options;
private: private:
@ -53,7 +48,6 @@ private:
static LPSTR OptionsRegPathCur; static LPSTR OptionsRegPathCur;
static LPCSTR path(LPCSTR regPath); static LPCSTR path(LPCSTR regPath);
static void path_free(); static void path_free();
static HMENU MenuHandle;
static winhelp_entry keymap_help[18]; static winhelp_entry keymap_help[18];
static short vk_list[28]; static short vk_list[28];
}; };

View File

@ -20,7 +20,7 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful
if (fileHandle == nullptr) if (fileHandle == nullptr)
return nullptr; return nullptr;
fread(&header, 1, sizeof datFileHeader, fileHandle); fread(&header, 1, sizeof datFileHeader, fileHandle);
if (lstrcmpA("PARTOUT(4.0)RESOURCE", header.FileSignature)) if (strcmp("PARTOUT(4.0)RESOURCE", header.FileSignature) != 0)
{ {
fclose(fileHandle); fclose(fileHandle);
return nullptr; return nullptr;
@ -31,13 +31,13 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful
fclose(fileHandle); fclose(fileHandle);
return nullptr; return nullptr;
} }
if (lstrlenA(header.Description) <= 0) if (strlen(header.Description) <= 0)
{ {
datFile->Description = nullptr; datFile->Description = nullptr;
} }
else else
{ {
int lenOfStr = lstrlenA(header.Description); auto lenOfStr = strlen(header.Description);
auto descriptionBuf = memory::allocate(lenOfStr + 1); auto descriptionBuf = memory::allocate(lenOfStr + 1);
datFile->Description = descriptionBuf; datFile->Description = descriptionBuf;
if (!descriptionBuf) if (!descriptionBuf)
@ -46,7 +46,7 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful
memory::free(datFile); memory::free(datFile);
return nullptr; return nullptr;
} }
lstrcpyA(descriptionBuf, header.Description); strcpy_s(descriptionBuf, lenOfStr + 1, header.Description);
} }
if (header.Unknown) if (header.Unknown)
@ -256,7 +256,7 @@ int partman::field_size(datFileStruct* datFile, int groupIndex, datFieldTypes ta
int partman::record_labeled(datFileStruct* datFile, LPCSTR targetGroupName) int partman::record_labeled(datFileStruct* datFile, LPCSTR targetGroupName)
{ {
auto targetLength = lstrlenA(targetGroupName); auto targetLength = strlen(targetGroupName);
for (int groupIndex = datFile->NumberOfGroups - 1; groupIndex >= 0; --groupIndex) for (int groupIndex = datFile->NumberOfGroups - 1; groupIndex >= 0; --groupIndex)
{ {
auto groupName = field(datFile, groupIndex, datFieldTypes::GroupName); auto groupName = field(datFile, groupIndex, datFieldTypes::GroupName);

View File

@ -36,11 +36,11 @@ bool pb::FullTiltMode = false;
int pb::init() int pb::init()
{ {
float projMat[12], zMin = 0, zScaler = 0; float projMat[12], zMin = 0, zScaler = 0;
CHAR datFileName[300]; char datFileName[300];
CHAR dataFilePath[300]; char dataFilePath[300];
++memory::critical_allocation; ++memory::critical_allocation;
lstrcpyA(datFileName, winmain::DatFileName); strcpy_s(datFileName, winmain::DatFileName);
pinball::make_path_name(dataFilePath, datFileName, 300); pinball::make_path_name(dataFilePath, datFileName, 300);
record_table = partman::load_records(dataFilePath, fullscrn::GetResolution(), FullTiltMode); record_table = partman::load_records(dataFilePath, fullscrn::GetResolution(), FullTiltMode);
@ -148,9 +148,9 @@ void pb::mode_change(int mode)
case 1: case 1:
if (demo_mode) if (demo_mode)
{ {
options::menu_set(Menu1_Launch_Ball, 0); winmain::LaunchBallEnabled = false;
options::menu_set(Menu1_High_Scores, 0); winmain::HighScoresEnabled = false;
options::menu_check(Menu1_Demo, 1); winmain::DemoActive = true;
if (MainTable) if (MainTable)
{ {
if (MainTable->Demo) if (MainTable->Demo)
@ -159,9 +159,9 @@ void pb::mode_change(int mode)
} }
else else
{ {
options::menu_set(Menu1_High_Scores, 1); winmain::LaunchBallEnabled = true;
options::menu_set(Menu1_Launch_Ball, 1); winmain::HighScoresEnabled = true;
options::menu_check(Menu1_Demo, 0); winmain::DemoActive = false;
if (MainTable) if (MainTable)
{ {
if (MainTable->Demo) if (MainTable->Demo)
@ -170,19 +170,19 @@ void pb::mode_change(int mode)
} }
break; break;
case 2: case 2:
options::menu_set(Menu1_Launch_Ball, 0); winmain::LaunchBallEnabled = false;
if (!demo_mode) if (!demo_mode)
{ {
options::menu_set(Menu1_High_Scores, 1); winmain::HighScoresEnabled = true;
options::menu_check(Menu1_Demo, 0); winmain::DemoActive = false;
} }
if (MainTable && MainTable->LightGroup) if (MainTable && MainTable->LightGroup)
MainTable->LightGroup->Message(29, 1.4f); MainTable->LightGroup->Message(29, 1.4f);
break; break;
case 3: case 3:
case 4: case 4:
options::menu_set(Menu1_Launch_Ball, 0); winmain::LaunchBallEnabled = false;
options::menu_set(Menu1_High_Scores, 0); winmain::HighScoresEnabled = false;
mode_countdown_ = 5000; mode_countdown_ = 5000;
break; break;
} }
@ -479,7 +479,7 @@ void pb::keydown(int key)
break; break;
case 'h': case 'h':
char String1[200]; char String1[200];
lstrcpyA(String1, pinball::get_rc_string(26, 0)); strcpy_s(String1, pinball::get_rc_string(26, 0));
high_score::show_and_set_high_score_dialog(highscore_table, 1000000000, 1, String1); high_score::show_and_set_high_score_dialog(highscore_table, 1000000000, 1, String1);
break; break;
case 'm': case 'm':
@ -490,10 +490,10 @@ void pb::keydown(int key)
case 'r': case 'r':
control::cheat_bump_rank(); control::cheat_bump_rank();
break; break;
case VK_F11: case SDLK_F11:
gdrv::get_focus(); gdrv::get_focus();
break; break;
case VK_F12: case SDLK_F12:
MainTable->port_draw(); MainTable->port_draw();
break; break;
} }
@ -569,7 +569,7 @@ void pb::end_game()
int position = high_score::get_score_position(highscore_table, scores[i]); int position = high_score::get_score_position(highscore_table, scores[i]);
if (position >= 0) if (position >= 0)
{ {
lstrcpyA(String1, pinball::get_rc_string(scoreIndex[i] + 26, 0)); strcpy_s(String1, pinball::get_rc_string(scoreIndex[i] + 26, 0));
high_score::show_and_set_high_score_dialog(highscore_table, scores[i], position, String1); high_score::show_and_set_high_score_dialog(highscore_table, scores[i], position, String1);
} }
} }

View File

@ -10,18 +10,17 @@
#define PCH_H #define PCH_H
// TODO: add headers that you want to pre-compile here // TODO: add headers that you want to pre-compile here
#include <Windows.h>
#include <cstdio> #include <cstdio>
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
#include <CommCtrl.h>
#include <htmlhelp.h>
#include <cstdint> #include <cstdint>
#include <type_traits> /*For control template*/ #include <type_traits> /*For control template*/
#include <chrono> #include <chrono>
//#include <iostream> //#include <iostream>
#include <iomanip> //#include <iomanip>
//#include <cstdlib> //#include <cstdlib>
#include <vector>
#include <algorithm>
#define SDL_MAIN_HANDLED #define SDL_MAIN_HANDLED
#include "SDL.h" #include "SDL.h"
@ -33,9 +32,12 @@
//https://github.com/Tyyppi77/imgui_sdl 01deb04b102b6a1c15c7fdec1977a2c96a885e6f //https://github.com/Tyyppi77/imgui_sdl 01deb04b102b6a1c15c7fdec1977a2c96a885e6f
#include "imgui_sdl.h" #include "imgui_sdl.h"
//typedef const char* LPCSTR; typedef unsigned long DWORD;
//typedef int HINSTANCE; typedef char* LPSTR;
//typedef int HWND; typedef const char* LPCSTR;
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
/*Use (void) to silent unused warnings.*/ /*Use (void) to silent unused warnings.*/
#define assertm(exp, msg) assert(((void)msg, exp)) #define assertm(exp, msg) assert(((void)msg, exp))

View File

@ -206,7 +206,7 @@ std::map<uint32_t, LPCSTR> rc_strings
{2032, "Use &Maximum Resolution (1024 x 768)"} {2032, "Use &Maximum Resolution (1024 x 768)"}
}; };
int LoadStringAlt(UINT uID, LPSTR lpBuffer, int cchBufferMax) int LoadStringAlt(uint32_t uID, LPSTR lpBuffer, int cchBufferMax)
{ {
auto str = rc_strings.find(uID); auto str = rc_strings.find(uID);
if (str == rc_strings.end()) if (str == rc_strings.end())
@ -246,100 +246,15 @@ int pinball::get_rc_int(int uID, int* dst)
return 1; return 1;
} }
void pinball::FindShiftKeys()
{
signed int i;
int rightShift;
CHAR stringBuf[20];
RightShift = -1;
LeftShift = -1;
for (i = 0; i < 256; ++i)
{
if (MapVirtualKeyA(i, 1u) == 16)
{
LeftShift = i;
break;
}
}
while (++i < 256)
{
if (MapVirtualKeyA(i, 1u) == 16)
{
RightShift = i;
break;
}
}
if (!GetKeyNameTextA(LeftShift << 16, stringBuf, 19) || !_strnicmp(stringBuf, "right", 5u))
{
rightShift = RightShift;
}
else
{
rightShift = LeftShift;
LeftShift = RightShift;
RightShift = rightShift;
}
if (GetKeyNameTextA(rightShift << 16, stringBuf, 19))
{
if (_strnicmp(stringBuf, "left", 4u) != 0)
{
auto tmp = LeftShift;
LeftShift = RightShift;
RightShift = tmp;
}
}
}
void pinball::adjust_priority(int priority)
{
auto thread = GetCurrentThread();
switch (priority)
{
case -2:
SetThreadPriority(thread, -2);
break;
case -1:
SetThreadPriority(thread, -1);
break;
case 0:
SetThreadPriority(thread, 0);
break;
case 1:
SetThreadPriority(thread, 1);
break;
case 2:
SetThreadPriority(thread, 2);
break;
case 3:
SetThreadPriority(thread, 15);
break;
default:
break;
}
}
int pinball::make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize) int pinball::make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize)
{ {
int nameSize = GetModuleFileNameA(nullptr, lpFilename, nSize); auto base_path = SDL_GetBasePath();
if (!nameSize || nameSize == nSize) if (!base_path)
{
strcat_s(lpFilename, nSize, "?");
return 1; return 1;
for (CHAR* i = &lpFilename[nameSize]; i > lpFilename; --i)
{
if (*i == '\\' || *i == ':')
{
i[1] = 0;
break;
}
--nameSize;
} }
if (nameSize + 13 < nSize) strcpy_s(lpFilename, nSize, base_path);
{ strcat_s(lpFilename, nSize, lpString2);
lstrcatA(lpFilename, lpString2); return 0;
return 0;
}
lstrcatA(lpFilename, "?");
return 1;
} }

View File

@ -18,8 +18,6 @@ public:
static char* get_rc_string(int uID, int a2); static char* get_rc_string(int uID, int a2);
static int get_rc_int(int uID, int* dst); static int get_rc_int(int uID, int* dst);
static void FindShiftKeys();
static void adjust_priority(int priority);
static int make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize = 0x12Cu); static int make_path_name(LPSTR lpFilename, LPCSTR lpString2, int nSize = 0x12Cu);
private: private:
static char getRcBuffer[256 * 6]; static char getRcBuffer[256 * 6];

View File

@ -273,7 +273,7 @@ void score::update(scoreStruct* score)
void score::string_format(int score, char* str) void score::string_format(int score, char* str)
{ {
CHAR separator[12]; char separator[12];
if (score == -999) if (score == -999)
{ {
@ -281,25 +281,7 @@ void score::string_format(int score, char* str)
} }
else else
{ {
lstrcpyA(separator, ","); strcpy_s(separator, ",");
HKEY phkResult;
DWORD dwDisposition;
if (!RegCreateKeyExA(
HKEY_CURRENT_USER,
"Control Panel\\International",
0,
nullptr,
0,
KEY_ALL_ACCESS,
nullptr,
&phkResult,
&dwDisposition))
{
DWORD cbData = 10;
RegQueryValueExA(phkResult, "sThousand", nullptr, nullptr, (LPBYTE)separator, &cbData);
RegCloseKey(phkResult);
}
int scoreMillions = score % 1000000000 / 1000000; int scoreMillions = score % 1000000000 / 1000000;
if (score / 1000000000 <= 0) if (score / 1000000000 <= 0)
{ {

View File

@ -12,7 +12,6 @@
const double TargetFps = 60, TargetFrameTime = 1000 / TargetFps; const double TargetFps = 60, TargetFrameTime = 1000 / TargetFps;
HCURSOR winmain::mouse_hsave;
SDL_Window* winmain::MainWindow = nullptr; SDL_Window* winmain::MainWindow = nullptr;
SDL_Renderer* winmain::Renderer = nullptr; SDL_Renderer* winmain::Renderer = nullptr;
ImGuiIO* winmain::ImIO = nullptr; ImGuiIO* winmain::ImIO = nullptr;
@ -31,13 +30,15 @@ int winmain::no_time_loss;
DWORD winmain::then; DWORD winmain::then;
DWORD winmain::now; DWORD winmain::now;
UINT winmain::iFrostUniqueMsg;
bool winmain::restart = false; bool winmain::restart = false;
gdrv_bitmap8 winmain::gfr_display{}; gdrv_bitmap8 winmain::gfr_display{};
char winmain::DatFileName[300]{}; char winmain::DatFileName[300]{};
bool winmain::ShowAboutDialog = false; bool winmain::ShowAboutDialog = false;
bool winmain::ShowImGuiDemo = false; bool winmain::ShowImGuiDemo = false;
bool winmain::LaunchBallEnabled = true;
bool winmain::HighScoresEnabled = true;
bool winmain::DemoActive = false;
uint32_t timeGetTimeAlt() uint32_t timeGetTimeAlt()
@ -80,7 +81,6 @@ int winmain::WinMain(LPCSTR lpCmdLine)
pb::FullTiltMode = true; pb::FullTiltMode = true;
} }
pinball::FindShiftKeys();
options::init_resolution(); options::init_resolution();
// SDL window // SDL window
@ -125,18 +125,19 @@ int winmain::WinMain(LPCSTR lpCmdLine)
{ {
++memory::critical_allocation; ++memory::critical_allocation;
options::init(nullptr); options::init();
auto voiceCount = options::get_int(nullptr, "Voices", 8); auto voiceCount = options::get_int(nullptr, "Voices", 8);
if (!Sound::Init(voiceCount)) if (Sound::Init(voiceCount))
options::menu_set(Menu1_Sounds, 0); options::Options.Sounds = 0;
Sound::Activate(); Sound::Activate();
if (!pinball::quickFlag && !midi::music_init()) if (!pinball::quickFlag && !midi::music_init())
options::menu_set(Menu1_Music, 0); options::Options.Music = 0;
if (pb::init()) if (pb::init())
{ {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not load game data", "The .dat file is missing", window); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not load game data",
"The .dat file is missing", window);
return 1; return 1;
} }
@ -151,14 +152,11 @@ int winmain::WinMain(LPCSTR lpCmdLine)
if (strstr(lpCmdLine, "-fullscreen")) if (strstr(lpCmdLine, "-fullscreen"))
{ {
options::Options.FullScreen = 1; options::Options.FullScreen = 1;
options::menu_check(Menu1_Full_Screen, 1);
} }
SDL_ShowWindow(window); SDL_ShowWindow(window);
fullscrn::set_screen_mode(options::Options.FullScreen); fullscrn::set_screen_mode(options::Options.FullScreen);
pinball::adjust_priority(options::Options.PriorityAdj);
if (strstr(lpCmdLine, "-demo")) if (strstr(lpCmdLine, "-demo"))
pb::toggle_demo(); pb::toggle_demo();
else else
@ -249,7 +247,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
if (curTime == then) if (curTime == then)
{ {
Sleep(8u); SDL_Delay(8);
} }
else if (pb::frame(curTime - then)) else if (pb::frame(curTime - then))
{ {
@ -308,7 +306,8 @@ int winmain::WinMain(LPCSTR lpCmdLine)
if (restart) if (restart)
{ {
char restartPath[300]{}; // Todo: get rid of restart to change resolution.
/*char restartPath[300]{};
if (GetModuleFileNameA(nullptr, restartPath, 300)) if (GetModuleFileNameA(nullptr, restartPath, 300))
{ {
STARTUPINFO si{}; STARTUPINFO si{};
@ -320,7 +319,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
} }
} }*/
} }
return return_value; return return_value;
@ -342,7 +341,7 @@ void winmain::RenderUi()
{ {
new_game(); new_game();
} }
if (ImGui::MenuItem("Launch Ball")) if (ImGui::MenuItem("Launch Ball", nullptr, false, LaunchBallEnabled))
{ {
end_pause(); end_pause();
pb::launch_ball(); pb::launch_ball();
@ -353,13 +352,13 @@ void winmain::RenderUi()
} }
ImGui::Separator(); ImGui::Separator();
if (ImGui::MenuItem("High Scores...")) if (ImGui::MenuItem("High Scores...", nullptr, false, HighScoresEnabled))
{ {
if (!single_step) if (!single_step)
pause(); pause();
pb::high_scores(); pb::high_scores();
} }
if (ImGui::MenuItem("Demo")) if (ImGui::MenuItem("Demo", nullptr, DemoActive))
{ {
end_pause(); end_pause();
pb::toggle_demo(); pb::toggle_demo();
@ -450,7 +449,7 @@ void winmain::RenderUi()
{ {
if (!single_step) if (!single_step)
pause(); pause();
help_introduction(nullptr, (HWND)MainWindow); help_introduction();
} }
ImGui::Separator(); ImGui::Separator();
@ -507,7 +506,6 @@ int winmain::event_handler(const SDL_Event* event)
case SDL_QUIT: case SDL_QUIT:
end_pause(); end_pause();
bQuit = 1; bQuit = 1;
PostQuitMessage(0);
fullscrn::shutdown(); fullscrn::shutdown();
return_value = 0; return_value = 0;
return 0; return 0;
@ -525,7 +523,7 @@ int winmain::event_handler(const SDL_Event* event)
SDL_MinimizeWindow(MainWindow); SDL_MinimizeWindow(MainWindow);
break; break;
case SDLK_F1: case SDLK_F1:
help_introduction(nullptr, (HWND)MainWindow); help_introduction();
break; break;
case SDLK_F2: case SDLK_F2:
new_game(); new_game();
@ -637,7 +635,6 @@ int winmain::event_handler(const SDL_Event* event)
if (options::Options.Music && !single_step) if (options::Options.Music && !single_step)
midi::play_pb_theme(0); midi::play_pb_theme(0);
no_time_loss = 1; no_time_loss = 1;
pinball::adjust_priority(options::Options.PriorityAdj);
has_focus = 1; has_focus = 1;
gdrv::get_focus(); gdrv::get_focus();
pb::paint(); pb::paint();
@ -646,9 +643,7 @@ int winmain::event_handler(const SDL_Event* event)
case SDL_WINDOWEVENT_HIDDEN: case SDL_WINDOWEVENT_HIDDEN:
activated = 0; activated = 0;
fullscrn::activate(0); fullscrn::activate(0);
options::menu_check(Menu1_Full_Screen, 0);
options::Options.FullScreen = 0; options::Options.FullScreen = 0;
SetThreadPriority(GetCurrentThread(), 0);
Sound::Deactivate(); Sound::Deactivate();
midi::music_stop(); midi::music_stop();
has_focus = 0; has_focus = 0;
@ -693,7 +688,7 @@ void winmain::memalloc_failure()
gdrv::uninit(); gdrv::uninit();
char* caption = pinball::get_rc_string(170, 0); char* caption = pinball::get_rc_string(170, 0);
char* text = pinball::get_rc_string(179, 0); char* text = pinball::get_rc_string(179, 0);
MessageBoxA(nullptr, text, caption, 0x2030u); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, caption, text, MainWindow);
_exit(1); _exit(1);
} }
@ -732,9 +727,7 @@ void winmain::end_pause()
void winmain::new_game() void winmain::new_game()
{ {
end_pause(); end_pause();
HCURSOR prevCursor = SetCursor(LoadCursorA(nullptr, IDC_WAIT));
pb::replay_level(0); pb::replay_level(0);
SetCursor(prevCursor);
} }
void winmain::pause() void winmain::pause()
@ -743,26 +736,8 @@ void winmain::pause()
no_time_loss = 1; no_time_loss = 1;
} }
void winmain::help_introduction(HINSTANCE a1, HWND a2) void winmain::help_introduction()
{ {
char* buf1 = memory::allocate(0x1F4u);
if (buf1)
{
char* buf2 = memory::allocate(0x1F4u);
if (buf2)
{
options::get_string(nullptr, "HelpFile", buf1, pinball::get_rc_string(178, 0), 500);
options::get_string(pinball::get_rc_string(166, 0), "HelpFile", buf1, buf1, 500);
lstrcpyA(buf2, buf1);
memory::free(buf1);
//HtmlHelpA(GetDesktopWindow(), buf2, 0, 0);
memory::free(buf2);
}
else
{
memory::free(buf1);
}
}
} }
void winmain::Restart() void winmain::Restart()

View File

@ -9,6 +9,9 @@ public:
static SDL_Window* MainWindow; static SDL_Window* MainWindow;
static SDL_Renderer* Renderer; static SDL_Renderer* Renderer;
static ImGuiIO* ImIO; static ImGuiIO* ImIO;
static bool LaunchBallEnabled;
static bool HighScoresEnabled;
static bool DemoActive;
static int WinMain(LPCSTR lpCmdLine); static int WinMain(LPCSTR lpCmdLine);
static int event_handler(const SDL_Event* event); static int event_handler(const SDL_Event* event);
@ -18,15 +21,13 @@ public:
static void end_pause(); static void end_pause();
static void new_game(); static void new_game();
static void pause(); static void pause();
static void help_introduction(HINSTANCE a1, HWND a2); static void help_introduction();
static void Restart(); static void Restart();
private: private:
static int return_value, bQuit, DispFrameRate, DispGRhistory, activated; static int return_value, bQuit, DispFrameRate, DispGRhistory, activated;
static int has_focus, mouse_down, last_mouse_x, last_mouse_y, no_time_loss; static int has_focus, mouse_down, last_mouse_x, last_mouse_y, no_time_loss;
static DWORD then, now; static DWORD then, now;
static UINT iFrostUniqueMsg;
static gdrv_bitmap8 gfr_display; static gdrv_bitmap8 gfr_display;
static HCURSOR mouse_hsave;
static bool restart; static bool restart;
static bool ShowAboutDialog; static bool ShowAboutDialog;
static bool ShowImGuiDemo; static bool ShowImGuiDemo;