1
0
Fork 0
mirror of https://github.com/k4zmu2a/SpaceCadetPinball.git synced 2024-11-22 17:00:18 +01:00

Added FT music loader.

Fixed mouse lock.
Some cleanup.
This commit is contained in:
Muzychenko Andrey 2021-02-15 18:55:54 +03:00
parent debe52c1e0
commit 5c3e9fea4c
6 changed files with 638 additions and 130 deletions

View file

@ -155,8 +155,6 @@ void TTextBox::Display(char* text, float time)
void TTextBox::Draw() void TTextBox::Draw()
{ {
TTextBoxMessage* nextMessage = nullptr;
auto bmp = BgBmp; auto bmp = BgBmp;
if (bmp) if (bmp)
gdrv::copy_bitmap( gdrv::copy_bitmap(
@ -171,119 +169,112 @@ void TTextBox::Draw()
else else
gdrv::fill_bitmap(&render::vscreen, Width, Height, OffsetX, OffsetY, 0); gdrv::fill_bitmap(&render::vscreen, Width, Height, OffsetX, OffsetY, 0);
bool display = false;
while (Message1) while (Message1)
{ {
auto message = Message1; if (Message1->Time == -1.0)
if (message->Time == -1.0)
{ {
nextMessage = message->NextMessage; if (!Message1->NextMessage)
if (!message->NextMessage)
{ {
Timer = -1; Timer = -1;
LABEL_18: display = true;
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;
}
break; break;
} }
} }
else else if (Message1->TimeLeft() >= -2.0f)
{ {
auto timeLeft = Message1->TimeLeft(); Timer = timer::set(max(Message1->TimeLeft(), 0.25f), this, TimerExpired);
if (timeLeft >= -2.0f) 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; auto maskedChar = curChar & 0x7F;
if (timeLeft >= 0.25f) 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 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( gdrv::blit(

View file

@ -14,7 +14,7 @@ tagRECT fullscrn::WindowRect1, fullscrn::WindowRect2;
rectangle_type fullscrn::WHRect; rectangle_type fullscrn::WHRect;
int fullscrn::fullscrn_flag1; int fullscrn::fullscrn_flag1;
int fullscrn::display_changed; int fullscrn::display_changed;
int fullscrn::ChangeDisplay, fullscrn::SmthFullScrnFlag2; int fullscrn::ChangeDisplay, fullscrn::ignoreNextDisplayChangeFg;
int fullscrn::trick = 1; int fullscrn::trick = 1;
int fullscrn::MenuEnabled; int fullscrn::MenuEnabled;
HMENU fullscrn::MenuHandle; HMENU fullscrn::MenuHandle;
@ -122,8 +122,8 @@ int fullscrn::enableFullscreen()
if (ChangeDisplay && !display_changed) if (ChangeDisplay && !display_changed)
{ {
DevMode.dmSize = 156; DevMode.dmSize = sizeof DevMode;
DevMode.dmFields = 1835008; DevMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
DevMode.dmPelsWidth = resolution_array[resolution].ScreenWidth; DevMode.dmPelsWidth = resolution_array[resolution].ScreenWidth;
DevMode.dmPelsHeight = resolution_array[resolution].ScreenHeight; DevMode.dmPelsHeight = resolution_array[resolution].ScreenHeight;
DevMode.dmBitsPerPel = 32; DevMode.dmBitsPerPel = 32;
@ -131,24 +131,24 @@ int fullscrn::enableFullscreen()
if (trick) if (trick)
{ {
GetWindowRect(GetDesktopWindow(), &Rect); GetWindowRect(GetDesktopWindow(), &Rect);
SetWindowPos(hWnd, (HWND)-1, 0, 0, Rect.right - Rect.left + 1, SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, Rect.right - Rect.left + 1,
Rect.bottom - Rect.top + 1, 8u); Rect.bottom - Rect.top + 1, SWP_NOREDRAW);
} }
SmthFullScrnFlag2 = 1; ignoreNextDisplayChangeFg = 1;
LONG changeDispResult = ChangeDisplaySettingsA(&DevMode, 4u); LONG changeDispResult = ChangeDisplaySettingsA(&DevMode, CDS_FULLSCREEN);
if (changeDispResult == 1) if (changeDispResult == DISP_CHANGE_RESTART)
{ {
BYTE2(DevMode.dmFields) &= 0xFBu; DevMode.dmFields &= ~DM_BITSPERPEL;
SmthFullScrnFlag2 = 1; ignoreNextDisplayChangeFg = 1;
changeDispResult = ChangeDisplaySettingsA(&DevMode, 4u); changeDispResult = ChangeDisplaySettingsA(&DevMode, CDS_FULLSCREEN);
} }
display_changed = changeDispResult == 0; display_changed = changeDispResult == DISP_CHANGE_SUCCESSFUL;
if (changeDispResult == 0) if (display_changed)
return 1; return 1;
} }
GetWindowRect(GetDesktopWindow(), &Rect); GetWindowRect(GetDesktopWindow(), &Rect);
disableWindowFlagsDisDlg(); 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; return 0;
} }
@ -157,20 +157,20 @@ int fullscrn::disableFullscreen()
if (display_changed) if (display_changed)
{ {
display_changed = 0; display_changed = 0;
SmthFullScrnFlag2 = 1; ignoreNextDisplayChangeFg = 1;
ChangeDisplaySettingsA(nullptr, 4u); ChangeDisplaySettingsA(nullptr, CDS_FULLSCREEN);
if (trick) 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(); setWindowFlagsDisDlg();
SetWindowPos( SetWindowPos(
hWnd, hWnd,
nullptr, HWND_TOP,
WindowRect2.left, WindowRect2.left,
WindowRect2.top, WindowRect2.top,
WindowRect2.right - WindowRect2.left, WindowRect2.right - WindowRect2.left,
WindowRect2.bottom - WindowRect2.top, WindowRect2.bottom - WindowRect2.top,
0x14u); SWP_NOZORDER | SWP_NOACTIVATE);
return 0; return 0;
} }
@ -264,9 +264,9 @@ void fullscrn::center_in(HWND parent, HWND child)
int fullscrn::displaychange() int fullscrn::displaychange()
{ {
int result = 0; int result = 0;
if (SmthFullScrnFlag2) if (ignoreNextDisplayChangeFg)
{ {
SmthFullScrnFlag2 = 0; ignoreNextDisplayChangeFg = 0;
} }
else else
{ {
@ -280,24 +280,24 @@ int fullscrn::displaychange()
set_menu_mode(1); set_menu_mode(1);
SetWindowPos( SetWindowPos(
hWnd, hWnd,
nullptr, HWND_TOP,
WindowRect2.left, WindowRect2.left,
WindowRect2.top, WindowRect2.top,
WindowRect2.right - WindowRect2.left, WindowRect2.right - WindowRect2.left,
WindowRect2.bottom - WindowRect2.top, WindowRect2.bottom - WindowRect2.top,
0x1Cu); SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
result = 1; result = 1;
} }
else else
{ {
SetWindowPos( SetWindowPos(
hWnd, hWnd,
nullptr, HWND_TOP,
WindowRect2.left, WindowRect2.left,
WindowRect2.top, WindowRect2.top,
WindowRect2.right - WindowRect2.left, WindowRect2.right - WindowRect2.left,
WindowRect2.bottom - WindowRect2.top, WindowRect2.bottom - WindowRect2.top,
0x14u); SWP_NOZORDER | SWP_NOACTIVATE);
} }
center_in(GetDesktopWindow(), hWnd); center_in(GetDesktopWindow(), hWnd);
} }
@ -311,7 +311,7 @@ void fullscrn::activate(int flag)
if (!flag) if (!flag)
{ {
set_screen_mode(0); 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);
} }
} }
} }

View file

@ -25,7 +25,7 @@ public:
static rectangle_type WHRect; static rectangle_type WHRect;
static int fullscrn_flag1; static int fullscrn_flag1;
static int display_changed; static int display_changed;
static int ChangeDisplay, SmthFullScrnFlag2; static int ChangeDisplay, ignoreNextDisplayChangeFg;
static int trick; static int trick;
static const resolution_info resolution_array[3]; static const resolution_info resolution_array[3];
static float ScaleX; static float ScaleX;

View file

@ -1,6 +1,8 @@
#include "pch.h" #include "pch.h"
#include "midi.h" #include "midi.h"
#include "pb.h"
#include "pinball.h" #include "pinball.h"
tagMCI_OPEN_PARMSA midi::mci_open_info; 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) MCIERROR midi::play_pb_theme(int flag)
{ {
if (pb::FullTiltMode)
{
return play_ft(track1);
}
MCI_PLAY_PARMS playParams; MCI_PLAY_PARMS playParams;
MCIERROR result = 0; MCIERROR result = 0;
@ -26,6 +33,11 @@ MCIERROR midi::play_pb_theme(int flag)
MCIERROR midi::music_stop() MCIERROR midi::music_stop()
{ {
if (pb::FullTiltMode)
{
return stop_ft();
}
MCIERROR result = 0; MCIERROR result = 0;
if (midi_seq1_playing) if (midi_seq1_playing)
result = mciSendCommandA(mci_open_info.wDeviceID, MCI_STOP, 0, 0); result = mciSendCommandA(mci_open_info.wDeviceID, MCI_STOP, 0, 0);
@ -34,6 +46,11 @@ MCIERROR midi::music_stop()
int midi::music_init(HWND hwnd) int midi::music_init(HWND hwnd)
{ {
if (pb::FullTiltMode)
{
return music_init_ft(hwnd);
}
mci_open_info.wDeviceID = 0; mci_open_info.wDeviceID = 0;
midi_notify_hwnd = hwnd; midi_notify_hwnd = hwnd;
lstrcpyA(midi_device_type, pinball::get_rc_string(156, 0)); 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) MCIERROR midi::restart_midi_seq(int param)
{ {
if (pb::FullTiltMode)
{
return play_ft(active_track);
}
MCI_PLAY_PARMS playParams; MCI_PLAY_PARMS playParams;
MCIERROR result = 0; MCIERROR result = 0;
@ -58,7 +80,433 @@ MCIERROR midi::restart_midi_seq(int param)
void midi::music_shutdown() void midi::music_shutdown()
{ {
if (pb::FullTiltMode)
{
music_shutdown_ft();
return;
}
if (midi_seq1_open) if (midi_seq1_open)
mciSendCommandA(mci_open_info.wDeviceID, MCI_CLOSE, 0, 0); mciSendCommandA(mci_open_info.wDeviceID, MCI_CLOSE, 0, 0);
midi_seq1_open = 0; midi_seq1_open = 0;
} }
objlist_class<midi_struct>* 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<midi_struct>(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<midi_struct*>(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<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 != '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<riff_data*>(reinterpret_cast<char*>(&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<midihdr_tag*>(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<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)
{
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<DWORD_PTR>(midi_callback), 0,
CALLBACK_FUNCTION) &&
!midiStreamProperty(midi->StreamHandle, reinterpret_cast<LPBYTE>(&propdata),MIDIPROP_TIMEDIV | MIDIPROP_SET))
{
midihdr_tag* blockPtr = midi->DataPtr1;
for (auto blockIndex = midi->BlockCount; blockIndex; blockIndex--)
{
if (midiOutPrepareHeader(reinterpret_cast<HMIDIOUT>(midi->StreamHandle), blockPtr, sizeof(MIDIHDR)) ||
midiStreamOut(midi->StreamHandle, blockPtr, sizeof(MIDIHDR)))
{
returnCode = 5;
break;
}
++midi->PreparedBlocksCount;
blockPtr = reinterpret_cast<midihdr_tag*>(reinterpret_cast<char*>(&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<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));
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)
{
if (wMsg == 969)
{
auto mhdr = reinterpret_cast<LPMIDIHDR>(dwParam1);
auto midi = reinterpret_cast<midi_struct*>(mhdr->dwUser);
if ((midi->SomeFlag2 & 2) == 0 || (midi->SomeFlag2 & 1) != 0 || midiStreamOut(
midi->StreamHandle, mhdr, sizeof(MIDIHDR)))
--midi->PreparedBlocksCount;
}
}

View file

@ -1,4 +1,54 @@
#pragma once #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 class midi
{ {
public: public:
@ -7,10 +57,25 @@ public:
static int music_init(HWND hwnd); static int music_init(HWND hwnd);
static MCIERROR restart_midi_seq(int param); static MCIERROR restart_midi_seq(int param);
static void music_shutdown(); static void music_shutdown();
private: private:
static tagMCI_OPEN_PARMSA mci_open_info; static tagMCI_OPEN_PARMSA mci_open_info;
static char midi_device_type[28]; static char midi_device_type[28];
static HWND midi_notify_hwnd; static HWND midi_notify_hwnd;
static int midi_seq1_open, midi_seq1_playing; static int midi_seq1_open, midi_seq1_playing;
static objlist_class<midi_struct>* 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);
}; };

View file

@ -268,10 +268,14 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
now = timeGetTime(); now = timeGetTime();
if (now - then >= 2) if (now - then >= 2)
{ {
/*last_mouse_n is in client coordinates*/
POINT Point; POINT Point;
GetCursorPos(&Point); GetCursorPos(&Point);
ScreenToClient(hwnd_frame, &Point);
pb::ballset(last_mouse_x - Point.x, Point.y - last_mouse_y); 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) if (!single_step)
@ -705,7 +709,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP
case WM_PALETTECHANGED: case WM_PALETTECHANGED:
InvalidateRect(hWnd, nullptr, 0); InvalidateRect(hWnd, nullptr, 0);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcA(hWnd, Msg, wParam, lParam);
case WM_POINTERDEVICEINRANGE | LB_ADDSTRING: case MM_MCINOTIFY:
if (wParam == 1) if (wParam == 1)
midi::restart_midi_seq(lParam); midi::restart_midi_seq(lParam);
return DefWindowProcA(hWnd, Msg, wParam, lParam); return DefWindowProcA(hWnd, Msg, wParam, lParam);