diff --git a/Doc/FuncStats.xlsx b/Doc/FuncStats.xlsx index 91b9aa8..05242d5 100644 Binary files a/Doc/FuncStats.xlsx and b/Doc/FuncStats.xlsx differ diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj b/SpaceCadetPinball/SpaceCadetPinball.vcxproj index 80735c1..b9c8cc9 100644 --- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj +++ b/SpaceCadetPinball/SpaceCadetPinball.vcxproj @@ -158,6 +158,7 @@ + @@ -219,6 +220,7 @@ + diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters index 146dbad..ab37c36 100644 --- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters +++ b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters @@ -210,6 +210,9 @@ Header Files\TPinballComponent + + Header Files + @@ -386,6 +389,9 @@ Source Files\TPinballComponent + + Source Files + diff --git a/SpaceCadetPinball/high_score.cpp b/SpaceCadetPinball/high_score.cpp new file mode 100644 index 0000000..e00ab80 --- /dev/null +++ b/SpaceCadetPinball/high_score.cpp @@ -0,0 +1,16 @@ +#include "pch.h" +#include "high_score.h" + +int high_score::read(CHAR* table, int* ptrToSmth) +{ + return 0; +} + +int high_score::write(CHAR* table, int* ptrToSmth) +{ + return 0; +} + +void high_score::show_high_score_dialog(CHAR* table) +{ +} diff --git a/SpaceCadetPinball/high_score.h b/SpaceCadetPinball/high_score.h new file mode 100644 index 0000000..667905a --- /dev/null +++ b/SpaceCadetPinball/high_score.h @@ -0,0 +1,8 @@ +#pragma once +class high_score +{ +public: + static int read(CHAR* table, int* ptrToSmth); + static int write(CHAR* table, int* ptrToSmth); + static void show_high_score_dialog(CHAR* table); +}; diff --git a/SpaceCadetPinball/options.cpp b/SpaceCadetPinball/options.cpp index 5fe9486..cc5ff64 100644 --- a/SpaceCadetPinball/options.cpp +++ b/SpaceCadetPinball/options.cpp @@ -53,14 +53,14 @@ void options::init(HMENU menuHandle) Options.LeftTableBumpKey = get_int(nullptr, "Left Table Bump key", Options.LeftTableBumpKey); Options.RightTableBumpKey = get_int(nullptr, "Right Table Bump key", Options.RightTableBumpKey); Options.BottomTableBumpKey = get_int(nullptr, "Bottom Table Bump key", Options.BottomTableBumpKey); - menu_check(0xC9u, Options.Sounds); + menu_check(Menu1_Sounds, Options.Sounds); Sound::Enable(0, 7, Options.Sounds); - menu_check(0xCAu, Options.Music); - menu_check(0x193u, Options.FullScreen); - menu_check(0x198u, Options.Players == 1); - menu_check(0x199u, Options.Players == 2); - menu_check(0x19Au, Options.Players == 3); - menu_check(0x19Bu, Options.Players == 4); + 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); auto tmpBuf = memory::allocate(0x1F4u); if (tmpBuf) { @@ -247,10 +247,10 @@ void options::toggle(UINT uIDCheckItem) if (uIDCheckItem > 407 && uIDCheckItem <= 411) { Options.Players = uIDCheckItem - 407; - menu_check(0x198u, Options.Players == 1); - menu_check(0x199u, Options.Players == 2); - menu_check(0x19Au, Options.Players == 3); - menu_check(0x19Bu, Options.Players == 4); + 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); } } diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index 5d161d4..047d077 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "pb.h" +#include "high_score.h" #include "memory.h" #include "pinball.h" #include "proj.h" @@ -11,12 +12,14 @@ #include "options.h" #include "timer.h" #include "winmain.h" +#include "resource.h" TPinballTable* pb::MainTable = nullptr; datFileStruct* pb::record_table = nullptr; int pb::time_ticks = 0, pb::demo_mode = 0, pb::cheat_mode = 0, pb::game_mode = 2, pb::mode_countdown_, pb:: - ball_speed_limit; + ball_speed_limit, pb::state; float pb::time_now, pb::time_next; +char pb::highscore_table[32]; int pb::init() { @@ -58,8 +61,7 @@ int pb::init() } render::init(nullptr, zMin, zScaler, tableSize[0], tableSize[1]); - gdrv::fill_bitmap(&render::vscreen, render::vscreen.Width, render::vscreen.Height, 0, 0, - static_cast(0xff)); // temp + gdrv::fill_bitmap(&render::vscreen, render::vscreen.Width, render::vscreen.Height, 0, 0, '\xFF'); // temp gdrv::copy_bitmap( &render::vscreen, backgroundBmp->Width, @@ -84,7 +86,7 @@ int pb::init() MainTable = new TPinballTable(); - //high_score_read(highscore_table, (int)&pb_state); + high_score::read(highscore_table, &state); //v11 = *(float*)((char*)MainTable->ListP2.ListPtr->Array[0] + 154); //ball_speed_limit = v11 * 200.0; @@ -97,7 +99,7 @@ int pb::uninit() score::unload_msg_font(); loader::unload(); partman::unload_records(record_table); - //high_score_write(highscore_table, (int)&pb_state); + high_score::write(highscore_table, &state); if (MainTable) delete MainTable; MainTable = nullptr; @@ -128,6 +130,52 @@ void pb::paint() void pb::mode_change(int mode) { + switch (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); + if (MainTable) + { + /*v2 = MainTable->UnknownP48; + if (v2) + *(_BYTE*)(v2 + 5) = 1;*/ + } + } + else + { + options::menu_set(Menu1_High_Scores, 1); + options::menu_set(Menu1_Launch_Ball, 1); + options::menu_check(Menu1_Demo, 0); + if (MainTable) + { + /*v1 = MainTable->UnknownP48; + if (v1) + *(_BYTE*)(v1 + 5) = 0;*/ + } + } + break; + case 2: + options::menu_set(Menu1_Launch_Ball, 0); + if (!demo_mode) + { + options::menu_set(Menu1_High_Scores, 1); + options::menu_check(Menu1_Demo, 0); + } + 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); + mode_countdown_ = 5000; + break; + } + game_mode = mode; } void pb::toggle_demo() @@ -151,8 +199,8 @@ void pb::replay_level(int demoMode) { demo_mode = demoMode; mode_change(1); - //if (options::Options.Music) - midi::play_pb_theme(0); + if (options::Options.Music) + midi::play_pb_theme(0); MainTable->Message(1014, static_cast(options::Options.Players)); } @@ -388,6 +436,7 @@ int pb::cheat_bump_rank() void pb::launch_ball() { + MainTable->Plunger->Message(1017, 0.0f); } int pb::end_game() @@ -397,4 +446,5 @@ int pb::end_game() void pb::high_scores() { + high_score::show_high_score_dialog(highscore_table); } diff --git a/SpaceCadetPinball/pb.h b/SpaceCadetPinball/pb.h index f103533..18bc3f2 100644 --- a/SpaceCadetPinball/pb.h +++ b/SpaceCadetPinball/pb.h @@ -35,4 +35,6 @@ public: private : static int demo_mode, mode_countdown_; static float time_now, time_next; + static char highscore_table[32]; + static int state; }; diff --git a/SpaceCadetPinball/timer.cpp b/SpaceCadetPinball/timer.cpp index 2280e70..2420868 100644 --- a/SpaceCadetPinball/timer.cpp +++ b/SpaceCadetPinball/timer.cpp @@ -4,128 +4,124 @@ #include "memory.h" #include "pb.h" -timer_struct timer::timerStruct{}; -int timer::set_count; +int timer::SetCount; +timer_struct* timer::ActiveList; +int timer::MaxCount; +int timer::Count; +timer_struct* timer::FreeList; +timer_struct* timer::TimerBuffer; int timer::init(int count) { - auto buf = (timer_sub_struct*)memory::allocate(sizeof(timer_sub_struct) * count); - timerStruct.TimerMem = buf; + auto buf = (timer_struct*)memory::allocate(sizeof(timer_struct) * count); + TimerBuffer = buf; if (!buf) return 1; - timerStruct.Count = 0; - timerStruct.MaxCount = count; - set_count = 1; + Count = 0; + MaxCount = count; + SetCount = 1; for (int index = 0; index < count - 1; index++) buf[index].NextTimer = &buf[index + 1]; buf[count - 1].NextTimer = nullptr; - timerStruct.NextTimer = nullptr; - timerStruct.LastTimer = buf; + ActiveList = nullptr; + FreeList = buf; return 0; } void timer::uninit() { - if (timerStruct.TimerMem) - memory::free(timerStruct.TimerMem); - timerStruct.TimerMem = nullptr; + if (TimerBuffer) + memory::free(TimerBuffer); + TimerBuffer = nullptr; } int timer::kill(int timerId) { - timer_sub_struct* next = timerStruct.NextTimer; + timer_struct* current = ActiveList; int index = 0; - timer_sub_struct* current = nullptr; - if (timerStruct.Count <= 0) + timer_struct* prev = nullptr; + if (Count <= 0) return 0; - while (timerId != next->TimerId) + while (timerId != current->TimerId) { ++index; - current = next; - next = next->NextTimer; - if (index >= timerStruct.Count) + prev = current; + current = current->NextTimer; + if (index >= Count) return 0; } - if (current) - current->NextTimer = next->NextTimer; + if (prev) + prev->NextTimer = current->NextTimer; else - timerStruct.NextTimer = next->NextTimer; + ActiveList = current->NextTimer; - --timerStruct.Count; - next->NextTimer = timerStruct.LastTimer; - timerStruct.LastTimer = next; + --Count; + current->NextTimer = FreeList; + FreeList = current; return timerId; } int timer::set(float time, void* caller, void (* callback)(int, void*)) { - if (timerStruct.Count >= timerStruct.MaxCount) + if (Count >= MaxCount) return 0; - /*timerStruct.LastTimer->NextTimer = nullptr; - timerStruct.LastTimer = timerStruct.LastTimer->NextTimer;*/ + auto timer = FreeList; + FreeList = timer->NextTimer; + timer->NextTimer = nullptr; - auto lastNext = timerStruct.LastTimer->NextTimer; - timerStruct.LastTimer->NextTimer = nullptr; - timerStruct.LastTimer = lastNext; - - auto prev = timerStruct.NextTimer; - auto current = timerStruct.NextTimer; + auto prev = ActiveList; + auto current = ActiveList; auto targetTime = pb::time_ticks + static_cast(time * 1000.0f); - for (int index = 0; index < timerStruct.Count && targetTime >= current->TargetTime; ++index) + for (int index = 0; index < Count && targetTime >= current->TargetTime; ++index) { prev = current; current = current->NextTimer; } - auto last = timerStruct.LastTimer; if (current != prev) { - timerStruct.LastTimer->NextTimer = prev->NextTimer; - prev->NextTimer = last; + timer->NextTimer = prev->NextTimer; + prev->NextTimer = timer; } else { - timerStruct.LastTimer->NextTimer = timerStruct.NextTimer; - timerStruct.NextTimer = last; + timer->NextTimer = ActiveList; + ActiveList = timer; } - last->Caller = caller; - last->Callback = callback; - last->TimerId = set_count; - last->TargetTime = targetTime; - timerStruct.Count++; + timer->Caller = caller; + timer->Callback = callback; + timer->TimerId = SetCount; + timer->TargetTime = targetTime; + Count++; - set_count++; - if (set_count <= 0) - set_count = 1; - return last->TimerId; + SetCount++; + if (SetCount <= 0) + SetCount = 1; + return timer->TimerId; } int timer::check() { - timer_sub_struct curCopy{}; - timer_sub_struct* current = timerStruct.NextTimer; + timer_struct* current = ActiveList; int index = 0; - if (timerStruct.NextTimer) + if (ActiveList) { while (pb::time_ticks >= current->TargetTime) { - --timerStruct.Count; - memcpy(&curCopy, current, sizeof curCopy); - timer_sub_struct** nextPtr = ¤t->NextTimer; - current = current->NextTimer; - timerStruct.NextTimer = current; - *nextPtr = timerStruct.LastTimer; - timerStruct.LastTimer = current; - if (curCopy.Callback != nullptr) - { - curCopy.Callback(curCopy.TimerId, curCopy.Caller); - current = timerStruct.NextTimer; - } + --Count; + // Advance active list, move current to free + ActiveList = current->NextTimer; + current->NextTimer = FreeList; + FreeList = current; + if (current->Callback != nullptr) + current->Callback(current->TimerId, current->Caller); + + current = ActiveList; ++index; if (index > 1) break; @@ -134,18 +130,14 @@ int timer::check() } while (current && pb::time_ticks >= current->TargetTime + 100) { - --timerStruct.Count; - memcpy(&curCopy, current, sizeof curCopy); - timer_sub_struct** nextPtr = ¤t->NextTimer; - current = current->NextTimer; - timerStruct.NextTimer = current; - *nextPtr = timerStruct.LastTimer; - timerStruct.LastTimer = current; - if (curCopy.Callback != nullptr) - { - curCopy.Callback(curCopy.TimerId, curCopy.Caller); - current = timerStruct.NextTimer; - } + --Count; + ActiveList = current->NextTimer; + current->NextTimer = FreeList; + FreeList = current; + if (current->Callback != nullptr) + current->Callback(current->TimerId, current->Caller); + + current = ActiveList; ++index; } } diff --git a/SpaceCadetPinball/timer.h b/SpaceCadetPinball/timer.h index 2834896..d06b34b 100644 --- a/SpaceCadetPinball/timer.h +++ b/SpaceCadetPinball/timer.h @@ -1,24 +1,14 @@ #pragma once -struct __declspec(align(4)) timer_sub_struct +struct __declspec(align(4)) timer_struct { int TargetTime; void* Caller; void (* Callback)(int, void*); - timer_sub_struct* NextTimer; + timer_struct* NextTimer; int TimerId; }; -struct __declspec(align(4)) timer_struct -{ - timer_sub_struct* NextTimer; - int MaxCount; - int Count; - timer_sub_struct* LastTimer; - timer_sub_struct* TimerMem; -}; - - class timer { public: @@ -29,6 +19,10 @@ public: static int check(); private: - static timer_struct timerStruct; - static int set_count; + static int SetCount; + static timer_struct* ActiveList; + static int MaxCount; + static int Count; + static timer_struct* FreeList; + static timer_struct* TimerBuffer; }; diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index ec8631d..16c7a5d 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -131,7 +131,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi picce.dwSize = 8; picce.dwICC = 5885; InitCommonControlsEx(&picce); - + WNDCLASSA WndClass{}; WndClass.style = 4104; WndClass.lpfnWndProc = message_handler; @@ -167,7 +167,7 @@ int winmain::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi if (strstr(lpCmdLine, "-fullscreen")) { options::Options.FullScreen = 1; - options::menu_check(0x193u, 1); + options::menu_check(Menu1_Full_Screen, 1); } ShowWindow(hwnd_frame, nShowCmd); @@ -331,7 +331,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP { activated = 0; fullscrn::activate(0); - options::menu_check(0x193u, 0); + options::menu_check(Menu1_Full_Screen, 0); options::Options.FullScreen = 0; SetThreadPriority(GetCurrentThread(), 0); Sound::Deactivate(); @@ -359,11 +359,11 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP auto voiceCount = options::get_int(nullptr, "Voices", 8); if (!Sound::Init(hinst, voiceCount, nullptr)) - options::menu_set(0xC9u, 0); + options::menu_set(Menu1_Sounds, 0); Sound::Activate(); if (!pinball::quickFlag && !midi::music_init(hWnd)) - options::menu_set(0xCAu, 0); + options::menu_set(Menu1_Music, 0); if (pb::init()) _exit(0); @@ -432,7 +432,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP if (fullscrn::displaychange()) { options::Options.FullScreen = 0; - options::menu_check(0x193u, 0); + options::menu_check(Menu1_Full_Screen, 0); } return DefWindowProcA(hWnd, Msg, wParam, lParam); case WM_KEYUP: @@ -640,7 +640,7 @@ LRESULT CALLBACK winmain::message_handler(HWND hWnd, UINT Msg, WPARAM wParam, LP if (wParam == 4 && options::Options.FullScreen) { options::Options.FullScreen = 0; - options::menu_check(0x193u, 0); + options::menu_check(Menu1_Full_Screen, 0); fullscrn::set_screen_mode(options::Options.FullScreen); } return DefWindowProcA(hWnd, Msg, wParam, lParam);