diff --git a/SpaceCadetPinball/TTextBox.cpp b/SpaceCadetPinball/TTextBox.cpp index fe4abe9..0106c9a 100644 --- a/SpaceCadetPinball/TTextBox.cpp +++ b/SpaceCadetPinball/TTextBox.cpp @@ -25,7 +25,7 @@ TTextBox::TTextBox(TPinballTable* table, int groupIndex) : TPinballComponent(tab if (groupIndex > 0) { /*Full tilt: text box dimensions index is offset by resolution*/ - int arrLength; + int arrLength; auto dimensions = loader::query_iattribute(groupIndex + fullscrn::GetResolution(), 1500, &arrLength); OffsetX = dimensions[0]; OffsetY = dimensions[1]; @@ -155,8 +155,6 @@ void TTextBox::Display(char* text, float time) void TTextBox::Draw() { - TTextBoxMessage* nextMessage = nullptr; - auto bmp = BgBmp; if (bmp) gdrv::copy_bitmap( @@ -171,119 +169,112 @@ void TTextBox::Draw() else gdrv::fill_bitmap(&render::vscreen, Width, Height, OffsetX, OffsetY, 0); + bool display = false; while (Message1) { - auto message = Message1; - if (message->Time == -1.0) + if (Message1->Time == -1.0) { - nextMessage = message->NextMessage; - if (!message->NextMessage) + if (!Message1->NextMessage) { Timer = -1; - LABEL_18: - auto font = Font; - if (!font) - { - gdrv::blit( - &render::vscreen, - OffsetX, - OffsetY, - OffsetX + render::vscreen.XPosition, - OffsetY + render::vscreen.YPosition, - Width, - Height); - gdrv::grtext_draw_ttext_in_box( - Message1->Text, - render::vscreen.XPosition + OffsetX, - render::vscreen.YPosition + OffsetY, - Width, - Height, - 255); - return; - } - auto text = Message1->Text; - for (auto y = OffsetY; ; y += font->Height) - { - auto curChar = *text; - if (!curChar || y + font->Height > OffsetY + Height) - break; - - auto totalWidth = 0; - char* textEndSpace = nullptr; - auto textEnd = text; - while (true) - { - auto maskedChar = curChar & 0x7F; - if (!maskedChar || maskedChar == '\n') - break; - auto charBmp = font->Chars[maskedChar]; - if (charBmp) - { - auto width = charBmp->Width + font->GapWidth + totalWidth; - if (width > Width) - { - if (textEndSpace) - textEnd = textEndSpace; - break; - } - if (*textEnd == ' ') - textEndSpace = textEnd; - curChar = *(textEnd + 1); - totalWidth = width; - ++textEnd; - } - else - { - curChar = *textEnd; - } - } - - auto offX = OffsetX; - while (text < textEnd) - { - auto charBmp = font->Chars[*text++ & 0x7F]; - if (charBmp) - { - auto height = charBmp->Height; - auto width = charBmp->Width; - if (render::background_bitmap) - gdrv::copy_bitmap_w_transparency(&render::vscreen, width, height, offX, y, charBmp, 0, - 0); - else - gdrv::copy_bitmap(&render::vscreen, width, height, offX, y, charBmp, 0, 0); - font = Font; - offX += charBmp->Width + font->GapWidth; - } - } - while ((*text & 0x7F) == ' ') - ++text; - if ((*text & 0x7F) == '\n') - ++text; - } + display = true; break; } } - else + else if (Message1->TimeLeft() >= -2.0f) { - auto timeLeft = Message1->TimeLeft(); - if (timeLeft >= -2.0f) + Timer = timer::set(max(Message1->TimeLeft(), 0.25f), this, TimerExpired); + display = true; + break; + } + + auto tmp = Message1; + Message1 = Message1->NextMessage; + delete tmp; + } + + if (display) + { + auto font = Font; + if (!font) + { + gdrv::blit( + &render::vscreen, + OffsetX, + OffsetY, + OffsetX + render::vscreen.XPosition, + OffsetY + render::vscreen.YPosition, + Width, + Height); + gdrv::grtext_draw_ttext_in_box( + Message1->Text, + render::vscreen.XPosition + OffsetX, + render::vscreen.YPosition + OffsetY, + Width, + Height, + 255); + return; + } + + auto text = Message1->Text; + for (auto y = OffsetY; ; y += font->Height) + { + auto curChar = *text; + if (!curChar || y + font->Height > OffsetY + Height) + break; + + auto totalWidth = 0; + char* textEndSpace = nullptr; + auto textEnd = text; + while (true) { - int timer; - if (timeLeft >= 0.25f) + auto maskedChar = curChar & 0x7F; + if (!maskedChar || maskedChar == '\n') + break; + auto charBmp = font->Chars[maskedChar]; + if (charBmp) { - timer = timer::set(timeLeft, this, TimerExpired); + auto width = charBmp->Width + font->GapWidth + totalWidth; + if (width > Width) + { + if (textEndSpace) + textEnd = textEndSpace; + break; + } + if (*textEnd == ' ') + textEndSpace = textEnd; + curChar = *(textEnd + 1); + totalWidth = width; + ++textEnd; } else { - timer = timer::set(0.25, this, TimerExpired); + curChar = *textEnd; } - Timer = timer; - goto LABEL_18; } - nextMessage = message->NextMessage; + + auto offX = OffsetX; + while (text < textEnd) + { + auto charBmp = font->Chars[*text++ & 0x7F]; + if (charBmp) + { + auto height = charBmp->Height; + auto width = charBmp->Width; + if (render::background_bitmap) + gdrv::copy_bitmap_w_transparency(&render::vscreen, width, height, offX, y, charBmp, 0, + 0); + else + gdrv::copy_bitmap(&render::vscreen, width, height, offX, y, charBmp, 0, 0); + font = Font; + offX += charBmp->Width + font->GapWidth; + } + } + while ((*text & 0x7F) == ' ') + ++text; + if ((*text & 0x7F) == '\n') + ++text; } - delete message; - Message1 = nextMessage; } gdrv::blit( diff --git a/SpaceCadetPinball/fullscrn.cpp b/SpaceCadetPinball/fullscrn.cpp index 6d4aa6f..788955e 100644 --- a/SpaceCadetPinball/fullscrn.cpp +++ b/SpaceCadetPinball/fullscrn.cpp @@ -14,7 +14,7 @@ tagRECT fullscrn::WindowRect1, fullscrn::WindowRect2; rectangle_type fullscrn::WHRect; int fullscrn::fullscrn_flag1; int fullscrn::display_changed; -int fullscrn::ChangeDisplay, fullscrn::SmthFullScrnFlag2; +int fullscrn::ChangeDisplay, fullscrn::ignoreNextDisplayChangeFg; int fullscrn::trick = 1; int fullscrn::MenuEnabled; HMENU fullscrn::MenuHandle; @@ -122,8 +122,8 @@ int fullscrn::enableFullscreen() if (ChangeDisplay && !display_changed) { - DevMode.dmSize = 156; - DevMode.dmFields = 1835008; + DevMode.dmSize = sizeof DevMode; + DevMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; DevMode.dmPelsWidth = resolution_array[resolution].ScreenWidth; DevMode.dmPelsHeight = resolution_array[resolution].ScreenHeight; DevMode.dmBitsPerPel = 32; @@ -131,24 +131,24 @@ int fullscrn::enableFullscreen() if (trick) { GetWindowRect(GetDesktopWindow(), &Rect); - SetWindowPos(hWnd, (HWND)-1, 0, 0, Rect.right - Rect.left + 1, - Rect.bottom - Rect.top + 1, 8u); + SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, Rect.right - Rect.left + 1, + Rect.bottom - Rect.top + 1, SWP_NOREDRAW); } - SmthFullScrnFlag2 = 1; - LONG changeDispResult = ChangeDisplaySettingsA(&DevMode, 4u); - if (changeDispResult == 1) + ignoreNextDisplayChangeFg = 1; + LONG changeDispResult = ChangeDisplaySettingsA(&DevMode, CDS_FULLSCREEN); + if (changeDispResult == DISP_CHANGE_RESTART) { - BYTE2(DevMode.dmFields) &= 0xFBu; - SmthFullScrnFlag2 = 1; - changeDispResult = ChangeDisplaySettingsA(&DevMode, 4u); + DevMode.dmFields &= ~DM_BITSPERPEL; + ignoreNextDisplayChangeFg = 1; + changeDispResult = ChangeDisplaySettingsA(&DevMode, CDS_FULLSCREEN); } - display_changed = changeDispResult == 0; - if (changeDispResult == 0) + display_changed = changeDispResult == DISP_CHANGE_SUCCESSFUL; + if (display_changed) return 1; } GetWindowRect(GetDesktopWindow(), &Rect); disableWindowFlagsDisDlg(); - SetWindowPos(hWnd, (HWND)-1, 0, 0, Rect.right - Rect.left + 1, Rect.bottom - Rect.top + 1, 8u); + SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, Rect.right - Rect.left + 1, Rect.bottom - Rect.top + 1, SWP_NOREDRAW); return 0; } @@ -157,20 +157,20 @@ int fullscrn::disableFullscreen() if (display_changed) { display_changed = 0; - SmthFullScrnFlag2 = 1; - ChangeDisplaySettingsA(nullptr, 4u); + ignoreNextDisplayChangeFg = 1; + ChangeDisplaySettingsA(nullptr, CDS_FULLSCREEN); if (trick) - SetWindowPos(hWnd, (HWND)-1, 0, 0, 0, 0, 0x13u); + SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); } setWindowFlagsDisDlg(); SetWindowPos( hWnd, - nullptr, + HWND_TOP, WindowRect2.left, WindowRect2.top, WindowRect2.right - WindowRect2.left, WindowRect2.bottom - WindowRect2.top, - 0x14u); + SWP_NOZORDER | SWP_NOACTIVATE); return 0; } @@ -264,9 +264,9 @@ void fullscrn::center_in(HWND parent, HWND child) int fullscrn::displaychange() { int result = 0; - if (SmthFullScrnFlag2) + if (ignoreNextDisplayChangeFg) { - SmthFullScrnFlag2 = 0; + ignoreNextDisplayChangeFg = 0; } else { @@ -280,24 +280,24 @@ int fullscrn::displaychange() set_menu_mode(1); SetWindowPos( hWnd, - nullptr, + HWND_TOP, WindowRect2.left, WindowRect2.top, WindowRect2.right - WindowRect2.left, WindowRect2.bottom - WindowRect2.top, - 0x1Cu); + SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE); result = 1; } else { SetWindowPos( hWnd, - nullptr, + HWND_TOP, WindowRect2.left, WindowRect2.top, WindowRect2.right - WindowRect2.left, WindowRect2.bottom - WindowRect2.top, - 0x14u); + SWP_NOZORDER | SWP_NOACTIVATE); } center_in(GetDesktopWindow(), hWnd); } @@ -311,7 +311,7 @@ void fullscrn::activate(int flag) if (!flag) { set_screen_mode(0); - SetWindowPos(hWnd, (HWND)1, 0, 0, 0, 0, 0x13u); + SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); } } } diff --git a/SpaceCadetPinball/fullscrn.h b/SpaceCadetPinball/fullscrn.h index 4f924a7..78dd36c 100644 --- a/SpaceCadetPinball/fullscrn.h +++ b/SpaceCadetPinball/fullscrn.h @@ -25,7 +25,7 @@ public: static rectangle_type WHRect; static int fullscrn_flag1; static int display_changed; - static int ChangeDisplay, SmthFullScrnFlag2; + static int ChangeDisplay, ignoreNextDisplayChangeFg; static int trick; static const resolution_info resolution_array[3]; static float ScaleX; diff --git a/SpaceCadetPinball/midi.cpp b/SpaceCadetPinball/midi.cpp index 89f8031..2f32050 100644 --- a/SpaceCadetPinball/midi.cpp +++ b/SpaceCadetPinball/midi.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "midi.h" + +#include "pb.h" #include "pinball.h" tagMCI_OPEN_PARMSA midi::mci_open_info; @@ -10,6 +12,11 @@ int midi::midi_seq1_open, midi::midi_seq1_playing; MCIERROR midi::play_pb_theme(int flag) { + if (pb::FullTiltMode) + { + return play_ft(track1); + } + MCI_PLAY_PARMS playParams; MCIERROR result = 0; @@ -26,6 +33,11 @@ MCIERROR midi::play_pb_theme(int flag) MCIERROR midi::music_stop() { + if (pb::FullTiltMode) + { + return stop_ft(); + } + MCIERROR result = 0; if (midi_seq1_playing) result = mciSendCommandA(mci_open_info.wDeviceID, MCI_STOP, 0, 0); @@ -34,6 +46,11 @@ MCIERROR midi::music_stop() int midi::music_init(HWND hwnd) { + if (pb::FullTiltMode) + { + return music_init_ft(hwnd); + } + mci_open_info.wDeviceID = 0; midi_notify_hwnd = hwnd; lstrcpyA(midi_device_type, pinball::get_rc_string(156, 0)); @@ -46,6 +63,11 @@ int midi::music_init(HWND hwnd) MCIERROR midi::restart_midi_seq(int param) { + if (pb::FullTiltMode) + { + return play_ft(active_track); + } + MCI_PLAY_PARMS playParams; MCIERROR result = 0; @@ -58,7 +80,433 @@ MCIERROR midi::restart_midi_seq(int param) void midi::music_shutdown() { + if (pb::FullTiltMode) + { + music_shutdown_ft(); + return; + } + if (midi_seq1_open) mciSendCommandA(mci_open_info.wDeviceID, MCI_CLOSE, 0, 0); midi_seq1_open = 0; } + + +objlist_class* midi::TrackList; +midi_struct *midi::track1, *midi::track2, *midi::track3, *midi::active_track, *midi::active_track2; +int midi::some_flag1; + +int midi::music_init_ft(HWND hwnd) +{ + midi_notify_hwnd = hwnd; + active_track = nullptr; + TrackList = new objlist_class(0, 1); + + track1 = load_track("taba1"); + track2 = load_track("taba2"); + track3 = load_track("taba3"); + if (!track2) + track2 = track1; + if (!track3) + track3 = track1; + return 1; +} + +void midi::music_shutdown_ft() +{ + if (active_track) + stream_close(active_track); + while (TrackList->GetCount()) + { + midi_struct* midi = TrackList->Get(0); + unload_track(midi); + TrackList->Delete(midi); + } + active_track = nullptr; + delete TrackList; +} + +midi_struct* midi::load_track(LPCSTR fileName) +{ + midi_struct* midi; + char filePath[256]; + char fileName2[256]; + + lstrcpyA(fileName2, "sound\\"); + lstrcatA(fileName2, fileName); + pinball::make_path_name(filePath, fileName2, 254u); + lstrcatA(filePath, ".MDS"); + if (load_file(&midi, filePath, 0, 1)) + return nullptr; + + if (midi) + TrackList->Add(midi); + return midi; +} + +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 = 'ISDM'; + 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 != 'FFIR') + { + returnCode = 3; + break; + } + if (filePtr->Mids != 'SDIM') + { + returnCode = 3; + break; + } + if (filePtr->FileSize > fileSize - 8) + { + returnCode = 3; + break; + } + if (fileSize - 12 < 8) + { + returnCode = 3; + break; + } + if (filePtr->Fmt != ' tmf') + { + 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 != 'atad') + { + returnCode = 3; + break; + } + if (dataChunk->DataSize > blocksSize || dataChunk->DataSize < 4) + { + returnCode = 3; + break; + } + + midi->BlockCount = dataChunk->BlocksPerChunk; + midi->DataPtr1 = static_cast(GlobalLock(GlobalAlloc( + GMEM_DDESHARE | GMEM_MOVEABLE, 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) + { + GlobalUnlock(GlobalHandle(midi->DataPtr1)); + GlobalFree(GlobalHandle(midi->DataPtr1)); + } + return returnCode; +} + +int midi::play_ft(midi_struct* midi) +{ + int result; + + stop_ft(); + if (!midi) + return 0; + if (some_flag1) + { + active_track2 = midi; + return 0; + } + if (stream_open(midi, 1)) + { + active_track = nullptr; + result = 0; + } + else + { + active_track = midi; + result = 1; + } + return result; +} + +int midi::stop_ft() +{ + int returnCode = 0; + if (active_track) + returnCode = stream_close(active_track); + active_track = nullptr; + return returnCode; +} + +int midi::unload_track(midi_struct* midi) +{ + if (midi->Magic != 'ISDM') + return 6; + if (midi->StreamHandle) + stream_close(midi); + if (midi->DataPtr1) + { + GlobalUnlock(GlobalHandle(midi->DataPtr1)); + GlobalFree(GlobalHandle(midi->DataPtr1)); + } + midi->Magic = 'atad'; + LocalFree(midi); + return 0; +} + +int midi::stream_open(midi_struct* midi, char flags) +{ + auto returnCode = 0; + if (midi->Magic != 'ISDM') + return 6; + + 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)) + { + midihdr_tag* blockPtr = midi->DataPtr1; + for (auto blockIndex = midi->BlockCount; blockIndex; blockIndex--) + { + if (midiOutPrepareHeader(reinterpret_cast(midi->StreamHandle), blockPtr, sizeof(MIDIHDR)) || + midiStreamOut(midi->StreamHandle, blockPtr, sizeof(MIDIHDR))) + { + returnCode = 5; + break; + } + + ++midi->PreparedBlocksCount; + blockPtr = reinterpret_cast(reinterpret_cast(&blockPtr[1]) + blockPtr->dwBufferLength); + } + } + + 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; + + if (midi->Magic != 'ISDM') + 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) + { + 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; +} + +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; + } +} diff --git a/SpaceCadetPinball/midi.h b/SpaceCadetPinball/midi.h index a569593..8d4e430 100644 --- a/SpaceCadetPinball/midi.h +++ b/SpaceCadetPinball/midi.h @@ -1,4 +1,54 @@ #pragma once +#include "objlist_class.h" + +struct midi_struct +{ + DWORD Magic; + DWORD DwTimeFormat; + DWORD CbMaxBuffer; + DWORD DwFlagsFormat; + midihdr_tag* DataPtr1; + HMIDISTRM StreamHandle; + int SomeFlag2; + int BlockCount; + int PreparedBlocksCount; +}; + +#pragma pack(push) +#pragma pack(1) +struct riff_block +{ + DWORD TkStart; + DWORD CbBuffer; + char AData[4]; +}; + +struct riff_data +{ + DWORD Data; + DWORD DataSize; + DWORD BlocksPerChunk; + riff_block Blocks[1]; +}; + +struct riff_header +{ + DWORD Riff; + DWORD FileSize; + DWORD Mids; + DWORD Fmt; + DWORD FmtSize; + DWORD dwTimeFormat; + DWORD cbMaxBuffer; + DWORD dwFlags; + riff_data Data; +}; + +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"); +#pragma pack(pop) + class midi { public: @@ -7,10 +57,25 @@ public: static int music_init(HWND hwnd); static MCIERROR restart_midi_seq(int param); static void music_shutdown(); - private: static tagMCI_OPEN_PARMSA mci_open_info; static char midi_device_type[28]; static HWND midi_notify_hwnd; static int midi_seq1_open, midi_seq1_playing; + + static objlist_class* TrackList; + static midi_struct *track1, *track2, *track3, *active_track, *active_track2; + static int some_flag1; + static int music_init_ft(HWND hwnd); + 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 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); }; diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index 1c15267..93494fa 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -165,7 +165,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi options::init_resolution(); char windowName[40]; - lstrcpyA(windowName, pinball::get_rc_string(38, 0)); + lstrcpyA(windowName, pinball::get_rc_string(38, 0)); windowHandle = CreateWindowExA(0, windowClass, windowName, WndStyle, 0, 0, 640, 480, nullptr, nullptr, hInstance, nullptr); hwnd_frame = windowHandle; @@ -268,10 +268,14 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi now = timeGetTime(); if (now - then >= 2) { + /*last_mouse_n is in client coordinates*/ POINT Point; GetCursorPos(&Point); + ScreenToClient(hwnd_frame, &Point); pb::ballset(last_mouse_x - Point.x, Point.y - last_mouse_y); - SetCursorPos(last_mouse_x, last_mouse_y); + Point = POINT{last_mouse_x, last_mouse_y}; + ClientToScreen(hwnd_frame, &Point); + SetCursorPos(Point.x, Point.y); } } if (!single_step) @@ -705,7 +709,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP case WM_PALETTECHANGED: InvalidateRect(hWnd, nullptr, 0); return DefWindowProcA(hWnd, Msg, wParam, lParam); - case WM_POINTERDEVICEINRANGE | LB_ADDSTRING: + case MM_MCINOTIFY: if (wParam == 1) midi::restart_midi_seq(lParam); return DefWindowProcA(hWnd, Msg, wParam, lParam);