diff --git a/SpaceCadetPinball/Sound.cpp b/SpaceCadetPinball/Sound.cpp index a1b0993..ecd4965 100644 --- a/SpaceCadetPinball/Sound.cpp +++ b/SpaceCadetPinball/Sound.cpp @@ -15,7 +15,7 @@ int Sound::Init(int voices) num_channels = channelCount; 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) diff --git a/SpaceCadetPinball/SpaceCadetPinball.cpp b/SpaceCadetPinball/SpaceCadetPinball.cpp index 6b0ef20..fb53717 100644 --- a/SpaceCadetPinball/SpaceCadetPinball.cpp +++ b/SpaceCadetPinball/SpaceCadetPinball.cpp @@ -38,7 +38,7 @@ int main(int argc, char* argv[]) auto xx = sizeof(datFileHeader); - lstrcpyA(winmain::DatFileName, "PINBALL.DAT"); + strcpy_s(winmain::DatFileName, "PINBALL.DAT"); pb::init(); auto datFile = pb::record_table; diff --git a/SpaceCadetPinball/TPinballTable.cpp b/SpaceCadetPinball/TPinballTable.cpp index 367ef7a..50d392c 100644 --- a/SpaceCadetPinball/TPinballTable.cpp +++ b/SpaceCadetPinball/TPinballTable.cpp @@ -229,14 +229,14 @@ TPinballComponent* TPinballTable::find_component(LPCSTR componentName) for (int index = 0; index < objCount; ++index) { TPinballComponent* obj = ComponentList->Get(index); - const CHAR* groupName = obj->GroupName; - if (groupName && !lstrcmpA(groupName, componentName)) + const char* groupName = obj->GroupName; + if (groupName && !strcmp(groupName, componentName)) { return obj; } } } - MessageBoxA(nullptr, "Table cant find:", componentName, 0x2000u); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Table cant find:", componentName, nullptr); return nullptr; } @@ -254,7 +254,7 @@ TPinballComponent* TPinballTable::find_component(int groupIndex) } } _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; } diff --git a/SpaceCadetPinball/fullscrn.cpp b/SpaceCadetPinball/fullscrn.cpp index 2f35a0d..3cdb5aa 100644 --- a/SpaceCadetPinball/fullscrn.cpp +++ b/SpaceCadetPinball/fullscrn.cpp @@ -117,9 +117,8 @@ int fullscrn::get_max_supported_resolution() if (!pb::FullTiltMode) return 0; - auto resolutionWH = get_screen_resolution(); - auto width = LOWORD(resolutionWH); - auto height = HIWORD(resolutionWH); + int width = 0, height = 0; + get_screen_resolution(&width, &height); auto result = 0; for (auto index = 1; index < 3; ++index) @@ -131,10 +130,16 @@ int fullscrn::get_max_supported_resolution() return result; } -int fullscrn::get_screen_resolution() +int fullscrn::get_screen_resolution(int* width, int* height) { - auto height = static_cast(GetSystemMetrics(SM_CYSCREEN)); - return static_cast(GetSystemMetrics(SM_CXSCREEN)) | (height << 16); + SDL_DisplayMode dm; + if (SDL_GetDesktopDisplayMode(0, &dm) == 0) + { + *width = dm.w; + *height = dm.h; + return 0; + } + return 1; } void fullscrn::window_size_changed() diff --git a/SpaceCadetPinball/fullscrn.h b/SpaceCadetPinball/fullscrn.h index 851652a..4fc2ba5 100644 --- a/SpaceCadetPinball/fullscrn.h +++ b/SpaceCadetPinball/fullscrn.h @@ -29,7 +29,7 @@ public: static int GetMaxResolution(); static void SetMaxResolution(int 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(); private : static int resolution; diff --git a/SpaceCadetPinball/gdrv.h b/SpaceCadetPinball/gdrv.h index 7ab961a..bdd2506 100644 --- a/SpaceCadetPinball/gdrv.h +++ b/SpaceCadetPinball/gdrv.h @@ -33,17 +33,6 @@ union ColorRgba }; 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 { diff --git a/SpaceCadetPinball/high_score.cpp b/SpaceCadetPinball/high_score.cpp index ab3b7c6..2d30bf5 100644 --- a/SpaceCadetPinball/high_score.cpp +++ b/SpaceCadetPinball/high_score.cpp @@ -54,15 +54,15 @@ int high_score::read(high_score_struct* table, int* ptrToSmth) { auto tablePtr = &table[position]; _itoa_s(position, Buffer, 10); - lstrcatA(Buffer, ".Name"); + strcat_s(Buffer, ".Name"); options::get_string(optPath, Buffer, buf1, "", 32); buf1[32] = 0; - lstrcpyA(tablePtr->Name, buf1); + strcpy_s(tablePtr->Name, buf1); _itoa_s(position, Buffer, 10); - lstrcatA(Buffer, ".Score"); + strcat_s(Buffer, ".Score"); options::get_string(optPath, Buffer, buf1, "", 300); 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; @@ -70,7 +70,7 @@ int high_score::read(high_score_struct* table, int* ptrToSmth) scramble_number_string(scoreSum, buf1); options::get_string(optPath, "Verification", buf2, "", 300); - if (lstrcmpA(buf1, buf2)) + if (strcmp(buf1, buf2) != 0) clear_table(table); memory::free(buf1); memory::free(buf2); @@ -83,20 +83,20 @@ int high_score::write(high_score_struct* table, int* ptrToSmth) high_score_struct* tablePtr = table; int scoreSum = 0; - CHAR* buf = memory::allocate(300u); + char* buf = memory::allocate(300u); if (!buf) 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) { _itoa_s(position, Buffer, 10); - lstrcatA(Buffer, ".Name"); + strcat_s(Buffer, ".Name"); options::set_string(optPath, Buffer, tablePtr->Name); _itoa_s(position, Buffer, 10); - lstrcatA(Buffer, ".Score"); + strcat_s(Buffer, ".Score"); _ltoa_s(tablePtr->Score, buf, 300, 10); 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; @@ -150,9 +150,9 @@ int high_score::place_new_score_into(high_score_struct* table, int score, LPSTR } high_score_struct* posTable = &table[position]; posTable->Score = score; - if (lstrlenA(scoreStr) >= 31) + if (strlen(scoreStr) >= 31) scoreStr[31] = 0; - lstrcpyA(posTable->Name, scoreStr); + strcpy_s(posTable->Name, scoreStr); posTable->Name[31] = 0; } return position; diff --git a/SpaceCadetPinball/loader.cpp b/SpaceCadetPinball/loader.cpp index d8ee65b..cddebae 100644 --- a/SpaceCadetPinball/loader.cpp +++ b/SpaceCadetPinball/loader.cpp @@ -12,8 +12,7 @@ errorMsg loader::loader_errors[] = { errorMsg{0, "Bad Handle"}, errorMsg{1, "No Type Field"}, - errorMsg{2, "No Attributes Field"}, - errorMsg{0x0B, "No float Attributes Field"}, + errorMsg{2, "No Attributes Field"}, errorMsg{3, "Wrong Type: MATERIAL Expected"}, errorMsg{4, "Wrong Type: KICKER 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{9, "Unrecognized Attribute"}, errorMsg{0x0A, "Unrecognized float Attribute"}, + errorMsg{0x0B, "No float Attributes Field"}, errorMsg{0x0D, "float Attribute not found"}, errorMsg{0x0C, "state_index out of range"}, errorMsg{0x0F, "loader_material() reports failure"}, @@ -63,7 +63,7 @@ int loader::error(int errorCode, int captionCode) if (!errorText) errorText = loader_errors[index].Message; - MessageBoxA(nullptr, errorText, errorCaption, 0x2000u); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, errorCaption, errorText, nullptr); return -1; } diff --git a/SpaceCadetPinball/midi.cpp b/SpaceCadetPinball/midi.cpp index 9c5aff0..76cbaf6 100644 --- a/SpaceCadetPinball/midi.cpp +++ b/SpaceCadetPinball/midi.cpp @@ -7,14 +7,31 @@ 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) { return play_ft(track1); } - MCIERROR result = 0; + int result = 0; music_stop(); if (currentMidi) result = Mix_PlayMusic(currentMidi, -1); @@ -22,13 +39,13 @@ MCIERROR midi::play_pb_theme(int flag) return result; } -MCIERROR midi::music_stop() +int midi::music_stop() { if (pb::FullTiltMode) { return stop_ft(); } - + return Mix_HaltMusic(); } @@ -38,26 +55,11 @@ int midi::music_init() { return music_init_ft(); } - + currentMidi = Mix_LoadMUS(pinball::get_rc_string(156, 0)); 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() { if (pb::FullTiltMode) @@ -70,14 +72,14 @@ void midi::music_shutdown() } -objlist_class* midi::TrackList; -midi_struct *midi::track1, *midi::track2, *midi::track3, *midi::active_track, *midi::active_track2; +objlist_class* midi::TrackList; +Mix_Music *midi::track1, *midi::track2, *midi::track3, *midi::active_track, *midi::active_track2; int midi::some_flag1; int midi::music_init_ft() { active_track = nullptr; - TrackList = new objlist_class(0, 1); + TrackList = new objlist_class(0, 1); track1 = load_track("taba1"); track2 = load_track("taba2"); @@ -92,260 +94,50 @@ int midi::music_init_ft() void midi::music_shutdown_ft() { if (active_track) - stream_close(active_track); + Mix_HaltMusic(); while (TrackList->GetCount()) { - midi_struct* midi = TrackList->Get(0); - unload_track(midi); + auto midi = TrackList->Get(0); + Mix_FreeMusic(midi); TrackList->Delete(midi); } active_track = nullptr; delete TrackList; } -midi_struct* midi::load_track(LPCSTR fileName) +Mix_Music* midi::load_track(LPCSTR fileName) { - midi_struct* midi; char filePath[256]; char fileName2[256]; - lstrcpyA(fileName2, "sound\\"); - lstrcatA(fileName2, fileName); + strcpy_s(fileName2, "sound\\"); + strcat_s(fileName2, fileName); pinball::make_path_name(filePath, fileName2, 254u); - lstrcatA(filePath, ".MDS"); - if (load_file(&midi, filePath, 0, 1)) + strcat_s(filePath, ".MDS"); + auto midi = MdsToMidi(filePath); + if (!midi) return nullptr; - if (midi) - TrackList->Add(midi); - return midi; + auto rw = SDL_RWFromMem(midi->data(), static_cast(midi->size())); + auto audio = Mix_LoadMUS_RW(rw, 0); + 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 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(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(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(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(reinterpret_cast(&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(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(&dstPtr[1]); - dstPtr->dwBufferLength = midi->CbMaxBuffer; - dstPtr->dwFlags = 0; - dstPtr->dwUser = reinterpret_cast(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(&srcPtr->AData[blockSize]); - dstPtr = reinterpret_cast(reinterpret_cast(&dstPtr[1]) + midi->CbMaxBuffer); - } - } - while (false); - - if (returnCode && midi->DataPtr1) - { - memory::free(midi->DataPtr1); - } - return returnCode; -} - -int midi::play_ft(midi_struct* midi) +int midi::play_ft(Mix_Music* midi) { int result; @@ -357,7 +149,7 @@ int midi::play_ft(midi_struct* midi) active_track2 = midi; return 0; } - if (stream_open(midi, 1)) + if (Mix_PlayMusic(midi, -1)) { active_track = nullptr; result = 0; @@ -374,114 +166,170 @@ int midi::stop_ft() { int returnCode = 0; if (active_track) - returnCode = stream_close(active_track); + returnCode = Mix_HaltMusic(); active_track = nullptr; return returnCode; } -int midi::unload_track(midi_struct* midi) +/// +/// SDL_mixed does not support MIDS. To support FT music, a conversion to MIDI is required. +/// +/// Path to .MDS file +/// Vector that contains MIDI file +std::vector* midi::MdsToMidi(char* file) { - if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I')) - return 6; - if (midi->StreamHandle) - stream_close(midi); - if (midi->DataPtr1) - { - memory::free(midi->DataPtr1); - } - midi->Magic = mmioFOURCC('d','a','t','a'); - LocalFree(midi); - return 0; -} + FILE* fileHandle; + if (fopen_s(&fileHandle, file, "rb")) + return nullptr; -int midi::stream_open(midi_struct* midi, char flags) -{ - auto returnCode = 0; - if (midi->Magic != mmioFOURCC('M', 'D', 'S', 'I')) - return 6; + fseek(fileHandle, 0, SEEK_END); + auto fileSize = static_cast(ftell(fileHandle)); + auto filePtr = reinterpret_cast(memory::allocate(fileSize)); + fseek(fileHandle, 0, SEEK_SET); + fread(filePtr, 1, fileSize, fileHandle); + fclose(fileHandle); - /*UINT puDeviceID = -1; - auto steamOpenedFg = !midi->StreamHandle; - MIDIPROPTIMEDIV propdata{8, midi->DwTimeFormat}; - if (steamOpenedFg && - !midiStreamOpen(&midi->StreamHandle, &puDeviceID, 1u, reinterpret_cast(midi_callback), 0, - CALLBACK_FUNCTION) && - !midiStreamProperty(midi->StreamHandle, reinterpret_cast(&propdata),MIDIPROP_TIMEDIV | MIDIPROP_SET)) + int returnCode = 0; + std::vector* midiOut = nullptr; + do { - midihdr_tag* blockPtr = midi->DataPtr1; - for (auto blockIndex = midi->BlockCount; blockIndex; blockIndex--) + if (fileSize < 12) { - if (midiOutPrepareHeader(reinterpret_cast(midi->StreamHandle), blockPtr, sizeof(MIDIHDR)) || - midiStreamOut(midi->StreamHandle, blockPtr, sizeof(MIDIHDR))) + returnCode = 3; + 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(reinterpret_cast(&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 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(srcPtr->AData); + for (auto i = 0u; i < eventCount; i++) { - returnCode = 5; - break; + currentTicks += srcPtr2[0]; + auto event = streamIdUsed ? srcPtr2[2] : srcPtr2[1]; + midiEvents.push_back({currentTicks, event}); + srcPtr2 += eventSizeInt; } - ++midi->PreparedBlocksCount; - blockPtr = reinterpret_cast(reinterpret_cast(&blockPtr[1]) + blockPtr->dwBufferLength); + srcPtr = reinterpret_cast(&srcPtr->AData[srcPtr->CbBuffer]); } - } - if (!returnCode) - { - 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(midi->StreamHandle))) - { - returnCode = 5; - midi->SomeFlag2 &= ~1; - } - else - { - midihdr_tag* blockPtr = midi->DataPtr1; - for (int i = midi->BlockCount; i; --i) + // MIDS events can be out of order in the file + std::sort(midiEvents.begin(), midiEvents.end(), [](const auto& lhs, const auto& rhs) { - midiOutUnprepareHeader(reinterpret_cast(midi->StreamHandle), blockPtr, sizeof(MIDIHDR)); - blockPtr = reinterpret_cast(reinterpret_cast(&blockPtr[1]) + blockPtr->dwBufferLength); - } - midiStreamClose(midi->StreamHandle); - returnCode = 0; - midi->StreamHandle = nullptr; - midi->SomeFlag2 = 0; - }*/ - return returnCode; -} + return lhs.iTicks < rhs.iTicks; + }); -void midi::midi_callback(HMIDIOUT hmo, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) -{ - if (wMsg == 969) - { - auto mhdr = reinterpret_cast(dwParam1); - auto midi = reinterpret_cast(mhdr->dwUser); - /*if ((midi->SomeFlag2 & 2) == 0 || (midi->SomeFlag2 & 1) != 0 || midiStreamOut( - midi->StreamHandle, mhdr, sizeof(MIDIHDR))) - --midi->PreparedBlocksCount;*/ + // MThd chunk + std::vector& midiBytes = *new std::vector(); + midiOut = &midiBytes; + midi_header header(SwapByteOrderShort(static_cast(filePtr->dwTimeFormat))); + auto headerData = reinterpret_cast(&header); + midiBytes.insert(midiBytes.end(), headerData, headerData + sizeof header); + + // MTrk chunk + midi_track track(7); + auto trackData = reinterpret_cast(&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(&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(&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(&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; } diff --git a/SpaceCadetPinball/midi.h b/SpaceCadetPinball/midi.h index a42540d..bec2d2e 100644 --- a/SpaceCadetPinball/midi.h +++ b/SpaceCadetPinball/midi.h @@ -1,18 +1,18 @@ #pragma once #include "objlist_class.h" -struct midi_struct +constexpr uint32_t SwapByteOrderInt(uint32_t val) { - DWORD Magic; - DWORD DwTimeFormat; - DWORD CbMaxBuffer; - DWORD DwFlagsFormat; - midihdr_tag* DataPtr1; - HMIDISTRM StreamHandle; - int SomeFlag2; - int BlockCount; - int PreparedBlocksCount; -}; + return (val >> 24) | + ((val << 8) & 0x00FF0000) | + ((val >> 8) & 0x0000FF00) | + (val << 24); +} + +constexpr uint16_t SwapByteOrderShort(uint16_t val) +{ + return static_cast((val >> 8) | (val << 8)); +} #pragma pack(push) #pragma pack(1) @@ -44,35 +44,71 @@ struct riff_header 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_data) == 0x18, "Wrong size of riff_data"); 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) class midi { public: - static MCIERROR play_pb_theme(int flag); - static MCIERROR music_stop(); + static int play_pb_theme(int flag); + static int music_stop(); static int music_init(); - static MCIERROR restart_midi_seq(LPARAM param); static void music_shutdown(); -private: +private: static Mix_Music* currentMidi; - static objlist_class* TrackList; - static midi_struct *track1, *track2, *track3, *active_track, *active_track2; + static objlist_class* TrackList; + static Mix_Music *track1, *track2, *track3, *active_track, *active_track2; static int some_flag1; static int music_init_ft(); static void music_shutdown_ft(); - static midi_struct* load_track(LPCSTR fileName); - static int load_file(midi_struct** midi_res, void* filePtrOrPath, int fileSizeP, int flags); - static int read_file(midi_struct* midi, riff_header* filePtr, unsigned int fileSize); - static int play_ft(midi_struct* midi); + static Mix_Music* load_track(LPCSTR fileName); + static int play_ft(Mix_Music* midi); static int stop_ft(); - static int unload_track(midi_struct* midi); - 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); + static std::vector* MdsToMidi(char* file); }; diff --git a/SpaceCadetPinball/options.cpp b/SpaceCadetPinball/options.cpp index 45be91b..699c910 100644 --- a/SpaceCadetPinball/options.cpp +++ b/SpaceCadetPinball/options.cpp @@ -11,7 +11,6 @@ LPCSTR options::OptionsRegPath; LPSTR options::OptionsRegPathCur; -HMENU options::MenuHandle; optionsStruct options::Options{}; winhelp_entry options::keymap_help[18] @@ -68,14 +67,12 @@ short options::vk_list[28] -1 }; -void options::init(HMENU menuHandle) +void options::init() { - MenuHandle = menuHandle; Options.Sounds = 1; Options.Music = 0; Options.FullScreen = 0; Options.Average = 5; - Options.PriorityAdj = 2; Options.LeftFlipperKeyDft = SDLK_z; Options.RightFlipperKeyDft = SDLK_SLASH; 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.BottomTableBumpKey = get_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey); Options.UniformScaling = get_int(nullptr, "Uniform scaling", true);*/ - menu_check(Menu1_Sounds, 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(); } @@ -154,10 +129,10 @@ void options::uninit() void options::path_init(LPCSTR regPath) { - char* buf = memory::allocate(lstrlenA(regPath) + 1); + char* buf = memory::allocate(strlen(regPath) + 1); OptionsRegPath = buf; if (buf) - lstrcpyA(buf, regPath); + strcpy_s(buf, strlen(regPath) + 1, regPath); } void options::path_uninit() @@ -172,16 +147,16 @@ LPCSTR options::path(LPCSTR regPath) char* buf = OptionsRegPathCur; if (!OptionsRegPathCur) { - buf = memory::allocate(0x7D0u); + buf = memory::allocate(2000); OptionsRegPathCur = buf; if (!buf) return OptionsRegPath; } - lstrcpyA(buf, OptionsRegPath); + strcpy_s(buf, 2000, OptionsRegPath); if (!regPath) return OptionsRegPathCur; - lstrcatA(OptionsRegPathCur, "\\"); - lstrcatA(OptionsRegPathCur, regPath); + strcat_s(OptionsRegPathCur, 2000, "\\"); + strcat_s(OptionsRegPathCur, 2000, regPath); return OptionsRegPathCur; } @@ -195,92 +170,45 @@ void options::path_free() int options::get_int(LPCSTR optPath, LPCSTR lpValueName, int defaultValue) { - DWORD dwDisposition; - HKEY hKey; - auto result = defaultValue; if (!OptionsRegPath) return result; 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(&result), &bufferSize); - RegCloseKey(hKey); - } path_free(); return result; } void options::set_int(LPCSTR optPath, LPCSTR lpValueName, int data) { - DWORD dwDisposition; - HKEY hKey; - if (!OptionsRegPath) return; - 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(&data), 4u); - RegCloseKey(hKey); - } + auto regPath = path(optPath); path_free(); } void options::get_string(LPCSTR optPath, LPCSTR lpValueName, LPSTR dst, LPCSTR defaultValue, int iMaxLength) { - DWORD dwDisposition; - HKEY hKey; - - lstrcpynA(dst, defaultValue, iMaxLength); + strncpy_s(dst, iMaxLength, defaultValue, iMaxLength); if (!OptionsRegPath) return; - 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(dst), &bufferSize); - RegCloseKey(hKey); - } + auto regPath = path(optPath); path_free(); } void options::set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value) { - DWORD dwDisposition; - HKEY hKey; - if (!OptionsRegPath) return; - 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); - } + auto regPath = path(optPath); path_free(); } -void options::menu_check(UINT uIDCheckItem, int check) -{ - 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) +void options::toggle(uint32_t uIDCheckItem) { int newValue; switch (uIDCheckItem) @@ -289,7 +217,6 @@ void options::toggle(UINT uIDCheckItem) newValue = Options.Sounds == 0; Options.Sounds = Options.Sounds == 0; Sound::Enable(0, 7, newValue); - menu_check(uIDCheckItem, newValue); return; case Menu1_Music: newValue = Options.Music == 0; @@ -298,31 +225,25 @@ void options::toggle(UINT uIDCheckItem) midi::music_stop(); else midi::play_pb_theme(0); - menu_check(uIDCheckItem, newValue); return; case Menu1_Full_Screen: newValue = Options.FullScreen == 0; Options.FullScreen = Options.FullScreen == 0; fullscrn::set_screen_mode(newValue); - menu_check(uIDCheckItem, newValue); return; case Menu1_1Player: case Menu1_2Players: case Menu1_3Players: case Menu1_4Players: 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; case Menu1_MaximumResolution: case Menu1_640x480: case Menu1_800x600: case Menu1_1024x768: { - for (unsigned i = Menu1_MaximumResolution; i <= Menu1_1024x768; ++i) - menu_check(i, i == uIDCheckItem); + /*for (unsigned i = Menu1_MaximumResolution; i <= Menu1_1024x768; ++i) + menu_check(i, i == uIDCheckItem);*/ int newResolution = uIDCheckItem - Menu1_640x480; if (uIDCheckItem == Menu1_MaximumResolution) @@ -340,7 +261,6 @@ void options::toggle(UINT uIDCheckItem) } case Menu1_WindowUniformScale: Options.UniformScaling ^= true; - menu_check(Menu1_WindowUniformScale, Options.UniformScaling); fullscrn::window_size_changed(); pb::paint(); break; @@ -353,8 +273,8 @@ void options::update_resolution_menu() { auto maxResolution = fullscrn::get_max_supported_resolution(); fullscrn::SetMaxResolution(maxResolution); - const CHAR* maxResText = pinball::get_rc_string(maxResolution + 2030, 0); - if (MenuHandle) + const char* maxResText = pinball::get_rc_string(maxResolution + 2030, 0); + /*if (MenuHandle) ModifyMenuA(MenuHandle, Menu1_MaximumResolution, 0, Menu1_MaximumResolution, maxResText); for (auto resIndex = 0; resIndex < 3; resIndex++) @@ -368,7 +288,7 @@ void options::update_resolution_menu() if (Options.Resolution >= 0) menu_check(fullscrn::resolution_array[fullscrn::GetResolution()].ResolutionMenuId, 1); else - menu_check(Menu1_MaximumResolution, 1); + menu_check(Menu1_MaximumResolution, 1);*/ } void options::init_resolution() @@ -390,192 +310,3 @@ void options::keyboard() { //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(reinterpret_cast(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(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(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(SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperL, CB_GETITEMDATA, ind, 0)); - ind = SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_GETCURSEL, 0, 0); - keyBindings[1] = static_cast(SendDlgItemMessageA(hDlg, KEYMAPPER_FlipperR, CB_GETITEMDATA, ind, 0)); - ind = SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_GETCURSEL, 0, 0); - keyBindings[2] = static_cast(SendDlgItemMessageA(hDlg, KEYMAPPER_Plunger, CB_GETITEMDATA, ind, 0)); - ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_GETCURSEL, 0, 0); - keyBindings[3] = static_cast(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpLeft, CB_GETITEMDATA, ind, 0)); - ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_GETCURSEL, 0, 0); - keyBindings[4] = static_cast(SendDlgItemMessageA(hDlg, KEYMAPPER_BumpRight, CB_GETITEMDATA, ind, 0)); - ind = SendDlgItemMessageA(hDlg, KEYMAPPER_BumpBottom, CB_GETCURSEL, 0, 0); - keyBindings[5] = static_cast(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; -} diff --git a/SpaceCadetPinball/options.h b/SpaceCadetPinball/options.h index 73b4353..66de9a9 100644 --- a/SpaceCadetPinball/options.h +++ b/SpaceCadetPinball/options.h @@ -7,7 +7,6 @@ struct optionsStruct int Music; int Average; int FullScreen; - int PriorityAdj; int Players; int LeftFlipperKey; int RightFlipperKey; @@ -29,7 +28,7 @@ struct optionsStruct class options { public: - static void init(HMENU menuHandle); + static void init(); static void uninit(); static void path_init(LPCSTR regPath); static void path_uninit(); @@ -37,15 +36,11 @@ public: 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 set_string(LPCSTR optPath, LPCSTR lpValueName, LPCSTR value); - static void menu_check(UINT uIDCheckItem, int check); - static void menu_set(UINT uIDEnableItem, int enable); - static void toggle(UINT uIDCheckItem); + static void toggle(uint32_t uIDCheckItem); static void update_resolution_menu(); static void init_resolution(); 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; private: @@ -53,7 +48,6 @@ private: static LPSTR OptionsRegPathCur; static LPCSTR path(LPCSTR regPath); static void path_free(); - static HMENU MenuHandle; static winhelp_entry keymap_help[18]; static short vk_list[28]; }; diff --git a/SpaceCadetPinball/partman.cpp b/SpaceCadetPinball/partman.cpp index 7d0950d..da9db0b 100644 --- a/SpaceCadetPinball/partman.cpp +++ b/SpaceCadetPinball/partman.cpp @@ -20,7 +20,7 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful if (fileHandle == nullptr) return nullptr; 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); return nullptr; @@ -31,13 +31,13 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful fclose(fileHandle); return nullptr; } - if (lstrlenA(header.Description) <= 0) + if (strlen(header.Description) <= 0) { datFile->Description = nullptr; } else { - int lenOfStr = lstrlenA(header.Description); + auto lenOfStr = strlen(header.Description); auto descriptionBuf = memory::allocate(lenOfStr + 1); datFile->Description = descriptionBuf; if (!descriptionBuf) @@ -46,7 +46,7 @@ datFileStruct* partman::load_records(LPCSTR lpFileName, int resolution, bool ful memory::free(datFile); return nullptr; } - lstrcpyA(descriptionBuf, header.Description); + strcpy_s(descriptionBuf, lenOfStr + 1, header.Description); } 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) { - auto targetLength = lstrlenA(targetGroupName); + auto targetLength = strlen(targetGroupName); for (int groupIndex = datFile->NumberOfGroups - 1; groupIndex >= 0; --groupIndex) { auto groupName = field(datFile, groupIndex, datFieldTypes::GroupName); diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index 4b41024..ccc1b66 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -36,11 +36,11 @@ bool pb::FullTiltMode = false; int pb::init() { float projMat[12], zMin = 0, zScaler = 0; - CHAR datFileName[300]; - CHAR dataFilePath[300]; + char datFileName[300]; + char dataFilePath[300]; ++memory::critical_allocation; - lstrcpyA(datFileName, winmain::DatFileName); + strcpy_s(datFileName, winmain::DatFileName); pinball::make_path_name(dataFilePath, datFileName, 300); record_table = partman::load_records(dataFilePath, fullscrn::GetResolution(), FullTiltMode); @@ -148,9 +148,9 @@ void pb::mode_change(int mode) case 1: if (demo_mode) { - options::menu_set(Menu1_Launch_Ball, 0); - options::menu_set(Menu1_High_Scores, 0); - options::menu_check(Menu1_Demo, 1); + winmain::LaunchBallEnabled = false; + winmain::HighScoresEnabled = false; + winmain::DemoActive = true; if (MainTable) { if (MainTable->Demo) @@ -159,9 +159,9 @@ void pb::mode_change(int mode) } else { - options::menu_set(Menu1_High_Scores, 1); - options::menu_set(Menu1_Launch_Ball, 1); - options::menu_check(Menu1_Demo, 0); + winmain::LaunchBallEnabled = true; + winmain::HighScoresEnabled = true; + winmain::DemoActive = false; if (MainTable) { if (MainTable->Demo) @@ -170,19 +170,19 @@ void pb::mode_change(int mode) } break; case 2: - options::menu_set(Menu1_Launch_Ball, 0); + winmain::LaunchBallEnabled = false; if (!demo_mode) { - options::menu_set(Menu1_High_Scores, 1); - options::menu_check(Menu1_Demo, 0); + winmain::HighScoresEnabled = true; + winmain::DemoActive = false; } if (MainTable && MainTable->LightGroup) MainTable->LightGroup->Message(29, 1.4f); break; case 3: case 4: - options::menu_set(Menu1_Launch_Ball, 0); - options::menu_set(Menu1_High_Scores, 0); + winmain::LaunchBallEnabled = false; + winmain::HighScoresEnabled = false; mode_countdown_ = 5000; break; } @@ -479,7 +479,7 @@ void pb::keydown(int key) break; case 'h': 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); break; case 'm': @@ -490,10 +490,10 @@ void pb::keydown(int key) case 'r': control::cheat_bump_rank(); break; - case VK_F11: + case SDLK_F11: gdrv::get_focus(); break; - case VK_F12: + case SDLK_F12: MainTable->port_draw(); break; } @@ -569,7 +569,7 @@ void pb::end_game() int position = high_score::get_score_position(highscore_table, scores[i]); 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); } } diff --git a/SpaceCadetPinball/pch.h b/SpaceCadetPinball/pch.h index 03e48f9..f28fffd 100644 --- a/SpaceCadetPinball/pch.h +++ b/SpaceCadetPinball/pch.h @@ -10,18 +10,17 @@ #define PCH_H // TODO: add headers that you want to pre-compile here -#include #include #include #include -#include -#include #include #include /*For control template*/ #include //#include -#include +//#include //#include +#include +#include #define SDL_MAIN_HANDLED #include "SDL.h" @@ -33,9 +32,12 @@ //https://github.com/Tyyppi77/imgui_sdl 01deb04b102b6a1c15c7fdec1977a2c96a885e6f #include "imgui_sdl.h" -//typedef const char* LPCSTR; -//typedef int HINSTANCE; -//typedef int HWND; +typedef unsigned long DWORD; +typedef char* LPSTR; +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.*/ #define assertm(exp, msg) assert(((void)msg, exp)) diff --git a/SpaceCadetPinball/pinball.cpp b/SpaceCadetPinball/pinball.cpp index fa983df..8dd7299 100644 --- a/SpaceCadetPinball/pinball.cpp +++ b/SpaceCadetPinball/pinball.cpp @@ -206,7 +206,7 @@ std::map rc_strings {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); if (str == rc_strings.end()) @@ -246,100 +246,15 @@ int pinball::get_rc_int(int uID, int* dst) 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 nameSize = GetModuleFileNameA(nullptr, lpFilename, nSize); - if (!nameSize || nameSize == nSize) + auto base_path = SDL_GetBasePath(); + if (!base_path) + { + strcat_s(lpFilename, nSize, "?"); return 1; - for (CHAR* i = &lpFilename[nameSize]; i > lpFilename; --i) - { - if (*i == '\\' || *i == ':') - { - i[1] = 0; - break; - } - --nameSize; } - if (nameSize + 13 < nSize) - { - lstrcatA(lpFilename, lpString2); - return 0; - } - lstrcatA(lpFilename, "?"); - return 1; + strcpy_s(lpFilename, nSize, base_path); + strcat_s(lpFilename, nSize, lpString2); + return 0; } diff --git a/SpaceCadetPinball/pinball.h b/SpaceCadetPinball/pinball.h index 9c48ffd..6f99ced 100644 --- a/SpaceCadetPinball/pinball.h +++ b/SpaceCadetPinball/pinball.h @@ -18,8 +18,6 @@ public: static char* get_rc_string(int uID, int a2); 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); private: static char getRcBuffer[256 * 6]; diff --git a/SpaceCadetPinball/score.cpp b/SpaceCadetPinball/score.cpp index 6bfddaa..e7f7201 100644 --- a/SpaceCadetPinball/score.cpp +++ b/SpaceCadetPinball/score.cpp @@ -273,7 +273,7 @@ void score::update(scoreStruct* score) void score::string_format(int score, char* str) { - CHAR separator[12]; + char separator[12]; if (score == -999) { @@ -281,25 +281,7 @@ void score::string_format(int score, char* str) } else { - lstrcpyA(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); - } + strcpy_s(separator, ","); int scoreMillions = score % 1000000000 / 1000000; if (score / 1000000000 <= 0) { diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index acf2356..e187b71 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -12,7 +12,6 @@ const double TargetFps = 60, TargetFrameTime = 1000 / TargetFps; -HCURSOR winmain::mouse_hsave; SDL_Window* winmain::MainWindow = nullptr; SDL_Renderer* winmain::Renderer = nullptr; ImGuiIO* winmain::ImIO = nullptr; @@ -31,13 +30,15 @@ int winmain::no_time_loss; DWORD winmain::then; DWORD winmain::now; -UINT winmain::iFrostUniqueMsg; bool winmain::restart = false; gdrv_bitmap8 winmain::gfr_display{}; char winmain::DatFileName[300]{}; bool winmain::ShowAboutDialog = false; bool winmain::ShowImGuiDemo = false; +bool winmain::LaunchBallEnabled = true; +bool winmain::HighScoresEnabled = true; +bool winmain::DemoActive = false; uint32_t timeGetTimeAlt() @@ -79,8 +80,7 @@ int winmain::WinMain(LPCSTR lpCmdLine) strcpy_s(DatFileName, "CADET.DAT"); pb::FullTiltMode = true; } - - pinball::FindShiftKeys(); + options::init_resolution(); // SDL window @@ -125,21 +125,22 @@ int winmain::WinMain(LPCSTR lpCmdLine) { ++memory::critical_allocation; - options::init(nullptr); + options::init(); auto voiceCount = options::get_int(nullptr, "Voices", 8); - if (!Sound::Init(voiceCount)) - options::menu_set(Menu1_Sounds, 0); + if (Sound::Init(voiceCount)) + options::Options.Sounds = 0; Sound::Activate(); 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; } - + fullscrn::init(); --memory::critical_allocation; @@ -151,13 +152,10 @@ int winmain::WinMain(LPCSTR lpCmdLine) if (strstr(lpCmdLine, "-fullscreen")) { options::Options.FullScreen = 1; - options::menu_check(Menu1_Full_Screen, 1); } SDL_ShowWindow(window); - fullscrn::set_screen_mode(options::Options.FullScreen); - - pinball::adjust_priority(options::Options.PriorityAdj); + fullscrn::set_screen_mode(options::Options.FullScreen); if (strstr(lpCmdLine, "-demo")) pb::toggle_demo(); @@ -249,7 +247,7 @@ int winmain::WinMain(LPCSTR lpCmdLine) if (curTime == then) { - Sleep(8u); + SDL_Delay(8); } else if (pb::frame(curTime - then)) { @@ -308,7 +306,8 @@ int winmain::WinMain(LPCSTR lpCmdLine) if (restart) { - char restartPath[300]{}; + // Todo: get rid of restart to change resolution. + /*char restartPath[300]{}; if (GetModuleFileNameA(nullptr, restartPath, 300)) { STARTUPINFO si{}; @@ -320,7 +319,7 @@ int winmain::WinMain(LPCSTR lpCmdLine) CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } - } + }*/ } return return_value; @@ -342,7 +341,7 @@ void winmain::RenderUi() { new_game(); } - if (ImGui::MenuItem("Launch Ball")) + if (ImGui::MenuItem("Launch Ball", nullptr, false, LaunchBallEnabled)) { end_pause(); pb::launch_ball(); @@ -353,13 +352,13 @@ void winmain::RenderUi() } ImGui::Separator(); - if (ImGui::MenuItem("High Scores...")) + if (ImGui::MenuItem("High Scores...", nullptr, false, HighScoresEnabled)) { if (!single_step) pause(); pb::high_scores(); } - if (ImGui::MenuItem("Demo")) + if (ImGui::MenuItem("Demo", nullptr, DemoActive)) { end_pause(); pb::toggle_demo(); @@ -450,7 +449,7 @@ void winmain::RenderUi() { if (!single_step) pause(); - help_introduction(nullptr, (HWND)MainWindow); + help_introduction(); } ImGui::Separator(); @@ -507,7 +506,6 @@ int winmain::event_handler(const SDL_Event* event) case SDL_QUIT: end_pause(); bQuit = 1; - PostQuitMessage(0); fullscrn::shutdown(); return_value = 0; return 0; @@ -525,7 +523,7 @@ int winmain::event_handler(const SDL_Event* event) SDL_MinimizeWindow(MainWindow); break; case SDLK_F1: - help_introduction(nullptr, (HWND)MainWindow); + help_introduction(); break; case SDLK_F2: new_game(); @@ -637,7 +635,6 @@ int winmain::event_handler(const SDL_Event* event) if (options::Options.Music && !single_step) midi::play_pb_theme(0); no_time_loss = 1; - pinball::adjust_priority(options::Options.PriorityAdj); has_focus = 1; gdrv::get_focus(); pb::paint(); @@ -646,9 +643,7 @@ int winmain::event_handler(const SDL_Event* event) case SDL_WINDOWEVENT_HIDDEN: activated = 0; fullscrn::activate(0); - options::menu_check(Menu1_Full_Screen, 0); options::Options.FullScreen = 0; - SetThreadPriority(GetCurrentThread(), 0); Sound::Deactivate(); midi::music_stop(); has_focus = 0; @@ -693,7 +688,7 @@ void winmain::memalloc_failure() gdrv::uninit(); char* caption = pinball::get_rc_string(170, 0); char* text = pinball::get_rc_string(179, 0); - MessageBoxA(nullptr, text, caption, 0x2030u); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, caption, text, MainWindow); _exit(1); } @@ -732,9 +727,7 @@ void winmain::end_pause() void winmain::new_game() { end_pause(); - HCURSOR prevCursor = SetCursor(LoadCursorA(nullptr, IDC_WAIT)); pb::replay_level(0); - SetCursor(prevCursor); } void winmain::pause() @@ -743,26 +736,8 @@ void winmain::pause() 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() diff --git a/SpaceCadetPinball/winmain.h b/SpaceCadetPinball/winmain.h index 957adc7..bfda4f4 100644 --- a/SpaceCadetPinball/winmain.h +++ b/SpaceCadetPinball/winmain.h @@ -9,6 +9,9 @@ public: static SDL_Window* MainWindow; static SDL_Renderer* Renderer; static ImGuiIO* ImIO; + static bool LaunchBallEnabled; + static bool HighScoresEnabled; + static bool DemoActive; static int WinMain(LPCSTR lpCmdLine); static int event_handler(const SDL_Event* event); @@ -18,15 +21,13 @@ public: static void end_pause(); static void new_game(); static void pause(); - static void help_introduction(HINSTANCE a1, HWND a2); + static void help_introduction(); static void Restart(); private: static int return_value, bQuit, DispFrameRate, DispGRhistory, activated; static int has_focus, mouse_down, last_mouse_x, last_mouse_y, no_time_loss; static DWORD then, now; - static UINT iFrostUniqueMsg; static gdrv_bitmap8 gfr_display; - static HCURSOR mouse_hsave; static bool restart; static bool ShowAboutDialog; static bool ShowImGuiDemo;