Advertisement
Kitomas

code for 2025-06-26 (2/4)

Jun 27th, 2025
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 26.02 KB | None | 0 0
  1. /******************************************************************************/
  2. /******************************************************************************/
  3. //"opengl_metaballs_2025-06-26\src\win32\fileio.cpp":
  4. #include <windows.h>
  5.  
  6. #include <public_stuff.hpp>
  7.  
  8.  
  9.  
  10.  
  11.  
  12. BinaryData::BinaryData(const char* file_path)
  13.   : size( fileio_size(file_path) )
  14. {
  15.   data_void = nullptr;
  16.   if(size == FILEIO_SIZE_ERR) return;
  17.  
  18.   size_t _size;
  19.   data_void = fileio_read(file_path, &_size);
  20.  
  21.   if(_size != size){ // Just in case
  22.     mem_free(&data_void);
  23.   }
  24.  
  25. }
  26.  
  27.  
  28.  
  29.  
  30.  
  31. BinaryData::BinaryData(const void* src, size_t _size)
  32.   : size( _size )
  33. {
  34.   data_void = mem_alloc(size+1);
  35.   if(data_void == nullptr) return; // Failed to allocate memory for data
  36.  
  37.   // Adding +1 to the Alloc size makes it so that I can always
  38.   // make sure that the file's data is null-terminated, like so:
  39.   data_char[size] = 0;
  40.  
  41.   if(src != nullptr) mem_copy(data_char, src, size);
  42.  
  43. }
  44.  
  45.  
  46.  
  47.  
  48.  
  49. BinaryData::~BinaryData(){
  50.   mem_free(&data_void);
  51.  
  52. }
  53.  
  54.  
  55.  
  56.  
  57.  
  58. /******************************************************************************/
  59.  
  60.  
  61.  
  62.  
  63.  
  64. void* fileio_read(const char* file_path, size_t* dataSize_p){
  65.   size_t size = fileio_size(file_path);
  66.   if(size == FILEIO_SIZE_ERR) return nullptr;
  67.  
  68.  
  69.  
  70.   // Open the file
  71.   HANDLE fileHandle = CreateFileA(file_path, GENERIC_READ, FILE_SHARE_READ,
  72.                                   nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  73.  
  74.   if(fileHandle == INVALID_HANDLE_VALUE) return nullptr; // Failed to open file
  75.  
  76.  
  77.  
  78.   // Allocate memory for file data
  79.   void* data = mem_alloc(size+1);
  80.  
  81.   if(data == nullptr){  CloseHandle(fileHandle);  return nullptr;  }
  82.  
  83.   ((char*)data)[size] = 0;
  84.  
  85.  
  86.  
  87.   DWORD bytesRead;
  88.   BOOL success = ReadFile(fileHandle, data, (DWORD)size, &bytesRead, nullptr);
  89.   CloseHandle(fileHandle);
  90.  
  91.   if(!success  ||  bytesRead < size)
  92.   {
  93.     mem_free(&data);
  94.     return nullptr;
  95.   }
  96.  
  97.  
  98.  
  99.   if(dataSize_p != nullptr) *dataSize_p = size;
  100.  
  101.   return data;
  102.  
  103. }
  104.  
  105.  
  106.  
  107.  
  108.  
  109. bool fileio_write(const char* file_path, const void* data,
  110.                   size_t data_size, bool append)
  111. {
  112.   if(file_path == nullptr  ||  data == nullptr) return false;
  113.  
  114.   // Writing files >=4GiB is currently unsupported!
  115.   // (If you really wanted to, I guess you could write files larger than 4 gigs
  116.   // with an overwrite and a series of appends, so that's always an option?)
  117.   if(data_size >= 0xFFFFFFFF) return false;
  118.  
  119.  
  120.  
  121.   DWORD accessMode, creationDisposition;
  122.  
  123.   if(append){ // Create or append to existing
  124.     accessMode          = FILE_APPEND_DATA;
  125.     creationDisposition = OPEN_ALWAYS;
  126.  
  127.   } else { // Create or overwrite existing
  128.     accessMode          = GENERIC_WRITE;
  129.     creationDisposition = CREATE_ALWAYS;
  130.  
  131.   }
  132.  
  133.  
  134.  
  135.   HANDLE fileHandle = CreateFileA(file_path, accessMode, 0, nullptr,
  136.                                   creationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
  137.  
  138.   if(fileHandle == INVALID_HANDLE_VALUE) return false; // Failed to open file
  139.  
  140.  
  141.  
  142.   // If data_size *is* 0, then just create/open the file without writing to it
  143.  
  144.   if(data_size > 0){
  145.     DWORD bytesWritten;
  146.     BOOL success = WriteFile(fileHandle, data, (DWORD)data_size, &bytesWritten, nullptr);
  147.     CloseHandle(fileHandle);
  148.     if(!success) return false; // Failed to write to file
  149.     if(bytesWritten < data_size) return false; // Bytes read was less than data_size
  150.  
  151.   } else {
  152.     CloseHandle(fileHandle);
  153.  
  154.   }
  155.  
  156.  
  157.  
  158.   return true;
  159.  
  160. }
  161.  
  162.  
  163.  
  164.  
  165.  
  166. /******************************************************************************/
  167.  
  168.  
  169.  
  170.  
  171.  
  172. size_t fileio_size(const char* file_path){
  173.   if(file_path == nullptr) return FILEIO_SIZE_ERR;
  174.  
  175.   HANDLE fileHandle = CreateFileA(file_path, 0, FILE_SHARE_READ, nullptr,
  176.                                   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,nullptr);
  177.  
  178.  
  179.  
  180.   if(fileHandle == INVALID_HANDLE_VALUE){
  181.     if(GetLastError() == ERROR_FILE_NOT_FOUND) return FILEIO_SIZE_ERR; // File not found
  182.     else                                       return FILEIO_SIZE_ERR; // Failed to open file
  183.   }
  184.  
  185.  
  186.  
  187.   LARGE_INTEGER fileSize;
  188.   BOOL success = GetFileSizeEx(fileHandle, &fileSize);
  189.   CloseHandle(fileHandle); // Close the file whether or not the query succeeds
  190.   if(!success) return FILEIO_SIZE_ERR;
  191.  
  192.   return (size_t)fileSize.QuadPart;
  193.  
  194. }
  195.  
  196.  
  197.  
  198.  
  199.  
  200. #define IS_READONLY(_attributes) \
  201.   ( (_attributes)&FILE_ATTRIBUTE_READONLY )
  202.  
  203. #define IS_DIRECTORY(_attributes) \
  204.   ( (_attributes)&FILE_ATTRIBUTE_DIRECTORY )
  205.  
  206. #define IS_READONLY_FILE(_attributes) \
  207.   ( IS_READONLY(_attributes) && !IS_DIRECTORY(_attributes) )
  208.  
  209. bool fileio_isreadonly(const char* file_path){
  210.   if(file_path == nullptr) return false; // file_path is not a real string
  211.  
  212.   DWORD fileAttributes = GetFileAttributesA(file_path);
  213.  
  214.   if(fileAttributes == INVALID_FILE_ATTRIBUTES){
  215.     if(GetLastError() != ERROR_FILE_NOT_FOUND) return false; // Failed to get file attributes
  216.     else                                       return false; // File doesn't exist
  217.  
  218.   } else if(IS_READONLY_FILE(fileAttributes)){
  219.     return true; // File is read-only
  220.  
  221.   } else {
  222.     return false; // File is not read-only
  223.  
  224.   }
  225.  
  226. }
  227.  
  228.  
  229.  
  230.  
  231.  
  232. #define IS_NORMAL_FILE(_attributes) \
  233.   ( !( IS_READONLY(_attributes) || IS_DIRECTORY(_attributes) ) )
  234.  
  235. bool fileio_exists(const char* file_path){
  236.   if(file_path == nullptr) return false; // file_path is not a real string
  237.  
  238.   DWORD fileAttributes = GetFileAttributesA(file_path);
  239.  
  240.   if(fileAttributes == INVALID_FILE_ATTRIBUTES){
  241.     if(GetLastError() != ERROR_FILE_NOT_FOUND) return false; // Failed to get file attributes
  242.     else                                       return false;
  243.  
  244.   } else if(IS_NORMAL_FILE(fileAttributes)){
  245.     return true;
  246.  
  247.   } else {
  248.     return false; // Path exists, but is not associated with a normal file
  249.  
  250.   }
  251.  
  252. }
  253.  
  254.  
  255.  
  256.  
  257.  
  258. bool fileio_delete(const char* file_path){
  259.   if(!fileio_exists(file_path)) return false; // File does not exist
  260.   if(!DeleteFileA(file_path)  ) return false; // Failed to delete file
  261.  
  262.   return true;
  263.  
  264. }
  265. /******************************************************************************/
  266. /******************************************************************************/
  267. //"opengl_metaballs_2025-06-26\src\win32\functions.cpp":
  268. #include <win32/audio.hpp>
  269. #include <win32/video.hpp>
  270.  
  271.  
  272.  
  273.  
  274.  
  275. _Winmm_func_t _Winmm_func;
  276.  
  277. char _Winmm_names_a[] = // prefix = "time"
  278.   "GetDevCaps\0"
  279.   "BeginPeriod\0"
  280.   "\0";
  281.  
  282. char _Winmm_names_b[] = // prefix = "waveOut"
  283. //"GetNumDevs\0"
  284.   "GetDevCapsA\0"
  285. //"GetVolume\0"
  286.   "SetVolume\0"
  287. //"GetErrorTextA\0"
  288.   "Open\0"
  289. //"Close\0"
  290.   "PrepareHeader\0"
  291. //"UnprepareHeader\0"
  292.   "Write\0"
  293.   "Pause\0"
  294. //"Restart\0"
  295. //"Reset\0"
  296. //"BreakLoop\0"
  297. //"GetPosition\0"
  298. //"GetPitch\0"
  299. //"SetPitch\0"
  300. //"GetPlaybackRate\0"
  301. //"SetPlaybackRate\0"
  302. //"GetID\0"
  303. //"Message\0"
  304.   "\0";
  305.  
  306.  
  307.  
  308.  
  309.  
  310. _User32_func_t _User32_func;
  311.  
  312. char _User32_names_a[] = // prefix = ""
  313.   "RegisterClassA\0"
  314.   "CreateWindowExA\0"
  315.   "DefWindowProcA\0"
  316.   "InvalidateRect\0"
  317.   "UpdateWindow\0"
  318.   "BeginPaint\0"
  319.   "EndPaint\0"
  320.   "PeekMessageA\0"
  321.   "DispatchMessageA\0"
  322.   "DestroyWindow\0"
  323.   "ReleaseDC\0"
  324.   "GetDC\0"
  325.   "PostQuitMessage\0"
  326.   "MessageBoxA\0"
  327.   "TranslateMessage\0"
  328.   "GetWindowLongA\0"
  329.   "AdjustWindowRectEx\0"
  330.   "LoadCursorA\0"
  331.   "MapVirtualKeyA\0"
  332. //"GetCursorPos\0"
  333.   "ScreenToClient\0"
  334.   "ShowCursor\0"
  335.   "ClipCursor\0"
  336.   "GetClientRect\0"
  337.   "ClientToScreen\0"
  338.   "SetCapture\0"
  339.   "ReleaseCapture\0"
  340.   "SetCursorPos\0"
  341.   "RegisterRawInputDevices\0"
  342.   "GetRawInputData\0"
  343.   "FillRect\0"
  344.   "ShowWindow\0"
  345.   "\0";
  346.  
  347.  
  348.  
  349.  
  350.  
  351. _Gdi32_func_t _Gdi32_func;
  352.  
  353. char _Gdi32_names_a[] = // prefix = ""
  354.   "CreateCompatibleDC\0"
  355.   "CreateDIBSection\0"
  356.   "SelectObject\0"
  357.   "DeleteObject\0"
  358.   "BitBlt\0"
  359.   "DeleteDC\0"
  360.   "StretchBlt\0"
  361.   "CreateCompatibleBitmap\0"
  362.   "SetStretchBltMode\0"
  363.   "SetDIBColorTable\0"
  364.   "CreateSolidBrush\0"
  365.   "SetPixelFormat\0"
  366.   "ChoosePixelFormat\0"
  367.   "SwapBuffers\0"
  368.   "\0";
  369. /******************************************************************************/
  370. /******************************************************************************/
  371. //"opengl_metaballs_2025-06-26\src\win32\input.cpp":
  372. #include <win32/input.hpp>
  373.  
  374. #include <public_stuff.hpp>
  375.  
  376.  
  377.  
  378. CRITICAL_SECTION events_lock;
  379. Event            events_queue[65536];
  380. u16              events_next = 0;
  381. u16              events_end  = 0;
  382.  
  383. Event_Key_Mod key_mods;
  384. bool          key_states[256] = {0};
  385.  
  386. Point2d mouse_position = {0};
  387. bool    mouse_was_moved_before = false;
  388.  
  389. bool cursor_trapped = false;
  390. bool cursor_hidden = false;
  391.  
  392.  
  393.  
  394.  
  395.  
  396. extern HWND win;
  397.  
  398. int InputInit(){
  399.   // This function has no failure condition
  400.   InitializeCriticalSectionAndSpinCount(&events_lock, 2048);
  401.  
  402.   return 0;
  403.  
  404. }
  405.  
  406.  
  407.  
  408. void InputQuit(){}
  409.  
  410.  
  411.  
  412.  
  413.  
  414. // Returns false if queue is full
  415. bool AddToEventQueue(Event& event){
  416.   EnterCriticalSection(&events_lock);
  417.  
  418.   bool success = false;
  419.  
  420.   if((events_end+1) != events_next){
  421.     events_queue[events_end++] = event;
  422.     success = true;
  423.  
  424.   }
  425.  
  426.   LeaveCriticalSection(&events_lock);
  427.  
  428.   return success;
  429.  
  430. }
  431.  
  432.  
  433.  
  434. // Returns a EVENT_NULL event if queue is empty
  435. Event RemoveFromEventQueue(){
  436.   EnterCriticalSection(&events_lock);
  437.  
  438.   Event event;
  439.   event.type = EVENT_NULL;
  440.  
  441.   if(events_next != events_end)
  442.     event = events_queue[events_next++];
  443.  
  444.   LeaveCriticalSection(&events_lock);
  445.  
  446.   return event;
  447.  
  448. }
  449.  
  450.  
  451.  
  452.  
  453.  
  454. // Calling this exclusively in the main thread is recommended
  455. bool pollEvent(Event* event_p){
  456.   // Take one event off the current event queue and set it to *event_p
  457.   EnterCriticalSection(&events_lock);
  458.  
  459.   Event event = RemoveFromEventQueue();
  460.  
  461.   LeaveCriticalSection(&events_lock);
  462.  
  463.  
  464.  
  465.   // If previous event queue is now empty, process any pending window messages,
  466.   // while adding any events generated by WindowProc to the event queue
  467.   if(events_next == events_end){
  468.     MSG message;
  469.  
  470.     while(PeekMessageA(&message, nullptr, 0, 0, PM_REMOVE)){
  471.       TranslateMessage(&message);
  472.       DispatchMessageA(&message);
  473.  
  474.     }
  475.  
  476.   }
  477.  
  478.  
  479.  
  480.   if(event_p != nullptr) *event_p = event;
  481.  
  482.   return event.type != EVENT_NULL;
  483.  
  484. }
  485.  
  486.  
  487.  
  488.  
  489.  
  490. bool is_cursor_trapped(){
  491.   return cursor_trapped; // Yep, that's all it does
  492.  
  493. }
  494. /******************************************************************************/
  495. /******************************************************************************/
  496. //"opengl_metaballs_2025-06-26\src\win32\main.cpp":
  497. #include <win32/audio.hpp>
  498. #include <win32/video.hpp>
  499. #include <win32/input.hpp>
  500. #include <win32/opengl.hpp>
  501.  
  502. #include <public_stuff.hpp>
  503.  
  504. extern HWND win; // from video.cpp
  505.  
  506.  
  507.  
  508.  
  509.  
  510. static HMODULE _Ole32_dll;
  511. static HMODULE _Winmm_dll;
  512. static HMODULE _User32_dll;
  513. static HMODULE _Gdi32_dll;
  514. static HMODULE _Opengl32_dll;
  515.  
  516.  
  517.  
  518.  
  519.  
  520. int user_main(int argc, char** argv);
  521.  
  522.  
  523.  
  524.  
  525.  
  526. // Doing "*((FARPROC*)&_name)" to work around not
  527. // being able to directly cast an lvalue.
  528. // (This is only really useful for isolated function pointers.)
  529. #define LOAD_FUNC(_pre, _post, _name, _dll) \
  530.   *((FARPROC*)&_name) = loadFunction(_pre, _post, _dll)
  531.  
  532.  
  533.  
  534. static char _functionNameBuffer[256];
  535.  
  536.  
  537.  
  538. FARPROC loadFunction(const char* prefix, const char* postfix, HMODULE dll){
  539.   strnCpy(_functionNameBuffer, prefix, 255);
  540.   strCat(_functionNameBuffer, postfix);
  541.  
  542.   _functionNameBuffer[255] = 0; // Just in case
  543.  
  544.   return GetProcAddress(dll, _functionNameBuffer);
  545.  
  546. }
  547.  
  548. // Postfixes string should look like: "nameA\0nameB\0nameC\0\0"
  549. bool loadFunctions(const char* prefix, const char* postfixes, HMODULE dll,
  550.                    FARPROC* funcs, int from)
  551. {
  552.   while(*postfixes != '\0'){
  553.     if(!( funcs[from++] = loadFunction(prefix, postfixes, dll) ))
  554.       return false;
  555.  
  556.     // +1 to get past null-terminator
  557.     postfixes += strnLen(postfixes, 256)+1;
  558.  
  559.   }
  560.  
  561.   return true;
  562.  
  563. }
  564.  
  565.  
  566.  
  567.  
  568.  
  569. //
  570.  
  571.  
  572.  
  573.  
  574.  
  575. #ifdef _DEBUG
  576. #define MAIN_ASSERT(_success, _code, _msg) \
  577.   if(!(_success)){ \
  578.     returnCode = (_code); \
  579.     _printf("ERROR: %s\n", _msg); \
  580.     goto _main_return; \
  581.   }
  582.  
  583. #else
  584. #define MAIN_ASSERT(_success, _code, _msg) \
  585.   if(!(_success)){ \
  586.     returnCode = (_code); \
  587.     showMessageBox(_msg, "A fatal error occurred!", \
  588.                    MSGBOX_BTN_OK | MSGBOX_ICN_ERROR, 0); \
  589.     goto _main_return; \
  590.   }
  591.  
  592. #endif
  593.  
  594.  
  595.  
  596. int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,
  597.                    LPSTR     lpszArg,   int       nCmdShow)
  598. {
  599.   int err, returnCode = 0;
  600.  
  601.   // g++ doesn't seem to allow gotos that might maybe possibly step
  602.   // over declarations, so the exit is near the top as a workaround
  603.   if(0){ _main_return:
  604.     // Seemingly due to WinMM being janky and old, in some environments the
  605.     // program hangs indefinitely unless I explicitly exit the process like
  606.     // this for some reason!
  607.     ExitProcess((UINT)returnCode);
  608.     return returnCode;
  609.   }
  610.  
  611.   #ifdef _DEBUG
  612.     u64 timeStart = timeGetPerfCounter();
  613.   #endif /* _DEBUG */
  614.  
  615.  
  616.  
  617.  
  618.  
  619.   _Ole32_dll = LoadLibrary("Ole32.dll");
  620.   MAIN_ASSERT(_Ole32_dll, -1, "failed to load \"Ole32.dll\"");
  621.  
  622.   _Winmm_dll = LoadLibrary("Winmm.dll");
  623.   MAIN_ASSERT(_Winmm_dll, -2, "failed to load \"Winmm.dll\"");
  624.  
  625.   _User32_dll = LoadLibrary("User32.dll");
  626.   MAIN_ASSERT(_User32_dll, -3, "failed to load \"User32.dll\"");
  627.  
  628.   _Gdi32_dll = LoadLibrary("Gdi32.dll");
  629.   MAIN_ASSERT(_Gdi32_dll, -4, "failed to load \"Gdi32.dll\"");
  630.  
  631.   _Opengl32_dll = LoadLibrary("Opengl32.dll");
  632.   MAIN_ASSERT(_Opengl32_dll, -5, "failed to load \"Opengl32.dll\"");
  633.  
  634.  
  635.  
  636.  
  637.  
  638.   MAIN_ASSERT(loadFunctions("time", _Winmm_names_a, _Winmm_dll,
  639.                             _Winmm_func.ptrs, 0), -11,
  640.                             "failed to load \"time\" functions from WinMM");
  641.  
  642.   MAIN_ASSERT(loadFunctions("waveOut", _Winmm_names_b, _Winmm_dll,
  643.                             _Winmm_func.ptrs, 2), -12,
  644.                             "failed to load \"waveOut\" functions from WinMM");
  645.  
  646.  
  647.  
  648.   #define LOAD_USER32_FUNCS(_prefix, _namegroup, _from, _errcode, _msg)        \
  649.     MAIN_ASSERT(loadFunctions(_prefix, _User32_names_##_namegroup, _User32_dll,\
  650.                               _User32_func.ptrs, (_from)), (_errcode), _msg)
  651.  
  652.   LOAD_USER32_FUNCS("", a, 0,  -13, "failed to load functions from User32");
  653.  
  654.  
  655.  
  656.   #define LOAD_GDI32_FUNCS(_prefix, _namegroup, _from, _errcode, _msg)       \
  657.     MAIN_ASSERT(loadFunctions(_prefix, _Gdi32_names_##_namegroup, _Gdi32_dll,\
  658.                               _Gdi32_func.ptrs, (_from)), (_errcode), _msg)
  659.  
  660.   LOAD_GDI32_FUNCS("", a, 0,  -14, "failed to load functions from Gdi32");
  661.  
  662.  
  663.  
  664.   #define LOAD_OPENGL32_FUNCS(_prefix, _namegroup, _from, _errcode, _msg)\
  665.     MAIN_ASSERT(loadFunctions(_prefix, _Opengl32_names_##_namegroup,     \
  666.                               _Opengl32_dll, _Opengl32_func.ptrs_wgl_1_1,\
  667.                               (_from)), (_errcode), _msg)
  668.  
  669.   LOAD_OPENGL32_FUNCS("wgl", wgl_1_1, 0,
  670.                       -15, "failed to load \"wgl\" functions from Opengl32");
  671.  
  672.   LOAD_OPENGL32_FUNCS("gl", gl_1_1, WGL_1_1_LEN,
  673.                       -16, "failed to load \"gl\" functions from Opengl32");
  674.  
  675.  
  676.  
  677.  
  678.  
  679.   // Request 1ms minimum delay, to make timeSleep(16) reliably take 15 to 17 ms
  680.   MAIN_ASSERT(!timeBeginPeriod(1), -50, "failed to set timer resolution");
  681.  
  682.  
  683.  
  684.  
  685.  
  686.   err = WaveOutInit(); // Also starts audio automatically
  687.   MAIN_ASSERT(err == 0, err-100, "failed to initialize waveOut device");
  688.  
  689.   err = WindowInit(hThisInst);
  690.   MAIN_ASSERT(err == 0, err-200, "failed to initialize window");
  691.  
  692.   err = InputInit();
  693.   MAIN_ASSERT(err == 0, err-300, "failed to initialize event system");
  694.  
  695.   err = OpenGLInit();
  696.   MAIN_ASSERT(err == 0, err-400, "failed to initialize OpenGL context");
  697.  
  698.  
  699.  
  700.   #if defined(STDLIB_USED)
  701.     srand(timeGetPerfCounter()&0xFFFFFFFF);
  702.   #endif
  703.  
  704.   #ifdef _DEBUG
  705.     s64 timeDeltaTicks = (s64)(timeGetPerfCounter()-timeStart);
  706.     f64 timeDeltaSecs  = (f64)timeDeltaTicks/timeGetPerfFreq();
  707.     _printf("Initialized in: %.4f seconds!\n", timeDeltaSecs);
  708.   #endif
  709.  
  710.   ShowWindow(win, SW_SHOW);
  711.  
  712.  
  713.  
  714.   try {
  715.     returnCode = user_main(0, nullptr); // TBD: provide main's arguments
  716.  
  717.   } catch(const char* errorText) {
  718.     MAIN_ASSERT(false, returnCode-1000, errorText);
  719.  
  720.   } catch(...){
  721.     MAIN_ASSERT(false, returnCode-1000, "(UNKNOWN EXCEPTION TYPE)");
  722.  
  723.   }
  724.  
  725.  
  726.  
  727.   ShowWindow(win, SW_HIDE);
  728.  
  729.  
  730.  
  731.   OpenGLQuit();
  732.  
  733.   InputQuit();
  734.  
  735.   WindowQuit();
  736.  
  737.   WaveOutQuit();
  738.  
  739.  
  740.  
  741.   // A nonzero value means there was a memory leak!
  742.   if(mem_getNumAllocations() > 0){
  743.     _printf("# OF ALLOCATIONS (THIS NUMBER SHOULD BE 0!): %llu\n",
  744.             mem_getNumAllocations());
  745.   }
  746.  
  747.  
  748.  
  749.   // Make sure no unused parameter warnings occur for these,
  750.   // regardless of whether or not they end up being used
  751.   (void)hThisInst;
  752.   (void)hPrevInst;
  753.   (void)lpszArg;
  754.   (void)nCmdShow;
  755.  
  756.   goto _main_return;
  757.  
  758. }
  759. /******************************************************************************/
  760. /******************************************************************************/
  761. //"opengl_metaballs_2025-06-26\src\win32\memory.cpp":
  762. #include <public_stuff.hpp>
  763.  
  764.  
  765. //turns something into a void**
  766.  //(this makes some code here easier for me to read)
  767. #define VPP(_ptr_p) ((void**)(_ptr_p))
  768.  
  769.  
  770. size_t numAllocations = 0;
  771.  
  772.  
  773.  
  774.  
  775.  
  776. void* mem_alloc(size_t size){
  777.   void* newHeapMemory = malloc(size);
  778.   if(newHeapMemory != nullptr) ++numAllocations;
  779.   return newHeapMemory;
  780.  
  781. }
  782.  
  783.  
  784.  
  785.  
  786.  
  787. void mem_free(void* ptr_p){
  788.   if(VPP(ptr_p) != nullptr  &&  *VPP(ptr_p) != nullptr){
  789.     --numAllocations;
  790.     free(*VPP(ptr_p));
  791.     *VPP(ptr_p) = nullptr;
  792.  
  793.   }
  794.  
  795. }
  796.  
  797.  
  798.  
  799.  
  800. void* mem_realloc(void* ptr_p, size_t newSize){
  801.   void* ptr_new = nullptr;
  802.  
  803.   if(VPP(ptr_p) != nullptr){
  804.     ptr_new = realloc(*VPP(ptr_p), newSize);
  805.  
  806.     if(ptr_new != nullptr){
  807.       if(*VPP(ptr_p) == nullptr) ++numAllocations;
  808.       *VPP(ptr_p) = ptr_new;
  809.  
  810.     }
  811.  
  812.   }
  813.  
  814.   return ptr_new;
  815.  
  816. }
  817.  
  818.  
  819.  
  820.  
  821.  
  822. size_t mem_getNumAllocations(){ return numAllocations; }
  823.  
  824. size_t mem_setNumAllocations(size_t value){ return numAllocations = value; }
  825.  
  826. size_t mem_addNumAllocations(s32 amount){
  827.   size_t originalState = numAllocations;
  828.  
  829.   numAllocations += amount;
  830.  
  831.   if(amount < 0  &&  numAllocations > originalState)
  832.     numAllocations = 0; // Integer underflow protection
  833.  
  834.   return numAllocations;
  835.  
  836. }
  837.  
  838.  
  839.  
  840.  
  841.  
  842. // Currently just a wrapper, but now I can make my own implementation
  843. // whenever I want, without replacing every call to memset with it
  844. void* mem_set(void* ptr, s32 value, size_t size){
  845.   if(ptr == nullptr) return nullptr; //now it's safe to pass nullptr :D
  846.   return memSet(ptr, value, size);
  847.  
  848. }
  849.  
  850.  
  851.  
  852.  
  853.  
  854. void* mem_copy(void* destination, const void* source, size_t size){
  855.   if(destination == nullptr  ||  source == nullptr) return destination;
  856.   return memCpy(destination, source, size);
  857.  
  858. }
  859. /******************************************************************************/
  860. /******************************************************************************/
  861. //"opengl_metaballs_2025-06-26\src\win32\misc.cpp":
  862. #include <windows.h>
  863.  
  864. #include <public_stuff.hpp>
  865.  
  866.  
  867.  
  868.  
  869.  
  870. extern HWND win;
  871. extern bool win_closed;
  872.  
  873. u32 showMessageBox(const char* text, const char* title,
  874.                    u32 type, u32 defaultButton)
  875. {
  876.   if(!text ) text  = "";
  877.   if(!title) title = "";
  878.  
  879.   defaultButton = (defaultButton&3)<<8; //0x000 -> 0x300
  880.  
  881.   HWND win_handle = (!win_closed) ? win : nullptr;
  882.   return MessageBoxA(win_handle, text, title, type|defaultButton);
  883.  
  884. }
  885.  
  886.  
  887.  
  888.  
  889.  
  890. u64 timeGetPerfCounter(){
  891.   u64 result;
  892.   QueryPerformanceCounter((LARGE_INTEGER*)&result);
  893.   return result;
  894.  
  895. }
  896.  
  897.  
  898.  
  899. static u64 perfFreq = 0;
  900.  
  901. u64 timeGetPerfFreq(){
  902.   if(!perfFreq)
  903.     QueryPerformanceFrequency((LARGE_INTEGER*)&perfFreq);
  904.  
  905.   return perfFreq;
  906.  
  907. }
  908.  
  909.  
  910.  
  911. f64 timeGetSeconds(){
  912.   return (f64)timeGetPerfCounter()/timeGetPerfFreq();
  913.  
  914. }
  915.  
  916.  
  917.  
  918. void timeSleep(u32 milliseconds){
  919.   Sleep((DWORD)milliseconds);
  920.  
  921. }
  922. /******************************************************************************/
  923. /******************************************************************************/
  924. //"opengl_metaballs_2025-06-26\src\win32\opengl.cpp":
  925. #include <win32/video.hpp>
  926. #include <win32/opengl.hpp>
  927.  
  928. #include <public_stuff.hpp>
  929.  
  930.  
  931.  
  932.  
  933.  
  934. /******************************************************************************/
  935.  
  936. _Opengl32_func_t _Opengl32_func;
  937.  
  938. // Use loadFunction() (NOT loadOpenGLFunction; this is done in "src/main.cpp"!)
  939. char _Opengl32_names_wgl_1_1[] = // prefix = "wgl"
  940.   "CopyContext\0"
  941.   "CreateContext\0"
  942.   "CreateLayerContext\0"
  943.   "DeleteContext\0"
  944.   "DescribeLayerPlane\0"
  945.   "GetCurrentContext\0"
  946.   "GetCurrentDC\0"
  947.   "GetLayerPaletteEntries\0"
  948.   "GetProcAddress\0"
  949.   "MakeCurrent\0"
  950.   "RealizeLayerPalette\0"
  951.   "SetLayerPaletteEntries\0"
  952.   "ShareLists\0"
  953.   "SwapLayerBuffers\0"
  954.   "UseFontBitmapsA\0"
  955.   "UseFontOutlinesA\0"
  956.   "\0";
  957.  
  958. // Use loadFunction() (NOT loadOpenGLFunction; this is done in "src/main.cpp"!)
  959. char _Opengl32_names_gl_1_1[] = // prefix = "gl"
  960.   "ClearColor\0"
  961.   "Clear\0"
  962.   "PolygonMode\0"
  963.   "Viewport\0"
  964.   "GetBooleanv\0"
  965.   "GetDoublev\0"
  966.   "GetFloatv\0"
  967.   "GetIntegerv\0"
  968.   "GetError\0"
  969.   "\0";
  970.  
  971. // Use loadOpenGLFunction()
  972. char _Opengl32_names_wgl[] = // prefix = "wgl"
  973.   "\0";
  974.  
  975. // Use loadOpenGLFunction()
  976. char _Opengl32_names_gl[] = // prefix = "gl"
  977.   "CreateShader\0"
  978.   "ShaderSource\0"
  979.   "CompileShader\0"
  980.   "GetShaderiv\0"
  981.   "GetShaderInfoLog\0"
  982.   "CreateProgram\0"
  983.   "AttachShader\0"
  984.   "LinkProgram\0"
  985.   "GetProgramInfoLog\0"
  986.   "DeleteShader\0"
  987.   "GenVertexArrays\0"
  988.   "GenBuffers\0"
  989.   "BindVertexArray\0"
  990.   "BindBuffer\0"
  991.   "BufferData\0"
  992.   "VertexAttribPointer\0"
  993.   "VertexAttribIPointer\0"
  994.   "EnableVertexAttribArray\0"
  995.   "DisableVertexAttribArray\0"
  996.   "UseProgram\0"
  997.   "DrawArrays\0"
  998.   "DeleteVertexArrays\0"
  999.   "DeleteBuffers\0"
  1000.   "DeleteProgram\0"
  1001.   "GetInteger64v\0"
  1002.   "GetBooleani_v\0"
  1003.   "GetIntegeri_v\0"
  1004.   "GetInteger64i_v\0"
  1005.   "GetProgramiv\0"
  1006.   "BufferSubData\0"
  1007.   "MapBufferRange\0"
  1008.   "GenTextures\0"
  1009.   "BindTexture\0"
  1010.   "TexBuffer\0"
  1011.   "GetUniformLocation\0"
  1012.  
  1013.   "Uniform1f\0"
  1014.   "Uniform2f\0"
  1015.   "Uniform3f\0"
  1016.   "Uniform4f\0"
  1017.  
  1018.   "Uniform1i\0"
  1019.   "Uniform2i\0"
  1020.   "Uniform3i\0"
  1021.   "Uniform4i\0"
  1022.  
  1023. //"Uniform1ui\0"
  1024. //"Uniform2ui\0"
  1025. //"Uniform3ui\0"
  1026. //"Uniform4ui\0"
  1027. //
  1028. //"Uniform1fv\0"
  1029. //"Uniform2fv\0"
  1030. //"Uniform3fv\0"
  1031. //"Uniform4fv\0"
  1032. //
  1033. //"Uniform1iv\0"
  1034. //"Uniform2iv\0"
  1035. //"Uniform3iv\0"
  1036. //"Uniform4iv\0"
  1037. //
  1038. //"Uniform1uiv\0"
  1039. //"Uniform2uiv\0"
  1040. //"Uniform3uiv\0"
  1041. //"Uniform4uiv\0"
  1042. //
  1043. //"UniformMatrix2fv\0"
  1044. //"UniformMatrix3fv\0"
  1045. //"UniformMatrix4fv\0"
  1046. //"UniformMatrix2x3fv\0"
  1047. //"UniformMatrix3x2fv\0"
  1048. //"UniformMatrix2x4fv\0"
  1049. //"UniformMatrix4x2fv\0"
  1050. //"UniformMatrix3x4fv\0"
  1051. //"UniformMatrix4x3fv\0"
  1052.  
  1053.   "DeleteTextures\0"
  1054.   "\0";
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060. /******************************************************************************/
  1061.  
  1062. static char _funcNameBufferOpenGL[256];
  1063.  
  1064.  
  1065.  
  1066. // Only works after wglGetProcAddress() has actually been loaded during init
  1067. PROC loadOpenGLFunction(const char* prefix, const char* postfix){
  1068.   strnCpy(_funcNameBufferOpenGL, prefix, 255);
  1069.   strCat(_funcNameBufferOpenGL, postfix);
  1070.  
  1071.   _funcNameBufferOpenGL[255] = 0; // Just in case
  1072.  
  1073.   return wglGetProcAddress(_funcNameBufferOpenGL);
  1074.  
  1075. }
  1076.  
  1077.  
  1078.  
  1079. // postfixes string should look like: "nameA\0nameB\0nameC\0\0"
  1080. bool loadOpenGLFunctions(const char* prefix, const char* postfixes,
  1081.                          PROC* funcs, int from = 0)
  1082. {
  1083.   while(*postfixes != '\0'){
  1084.     if(!( funcs[from++] = loadOpenGLFunction(prefix, postfixes) ))
  1085.       return false;
  1086.  
  1087.     // +1 to get past null-terminator
  1088.     postfixes += strnLen(postfixes, 256)+1;
  1089.  
  1090.   }
  1091.  
  1092.   return true;
  1093.  
  1094. }
  1095.  
  1096.  
  1097.  
  1098.  
  1099.  
  1100. /******************************************************************************/
  1101.  
  1102. static inline bool SetupDummyPixelFormat(HDC hDC){
  1103.     PIXELFORMATDESCRIPTOR pfd = {
  1104.         sizeof(PIXELFORMATDESCRIPTOR), 1, // nSize, nVersion
  1105.         PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // dwFlags
  1106.         PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, // iPixelType, cColorBits, empty*6
  1107.         0, 0, 0, 0, 0, 0, 0,
  1108.         24, 8, 0, PFD_MAIN_PLANE,
  1109.         0, 0, 0, 0
  1110.     };
  1111.  
  1112.     int pf = ChoosePixelFormat(hDC, &pfd);
  1113.     if(!pf) return false;
  1114.  
  1115.     return SetPixelFormat(hDC, pf, &pfd) == TRUE;
  1116.  
  1117. }
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123. extern HDC win_dc;
  1124.  
  1125. HGLRC renderCtx; // Rendering context
  1126.  
  1127. PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB_;
  1128.  
  1129.  
  1130.  
  1131.  
  1132.  
  1133. int OpenGLInit(){
  1134.   if(!SetupDummyPixelFormat(win_dc)) return -1;
  1135.  
  1136.  
  1137.  
  1138.   // Make a temporary, dummy context
  1139.  
  1140.   renderCtx = wglCreateContext(win_dc);
  1141.   if(renderCtx == nullptr) return -2;
  1142.  
  1143.   if(!wglMakeCurrent(win_dc, renderCtx)) return -3;
  1144.  
  1145.  
  1146.  
  1147.   // Get a pointer to wglCreateContextAttribsARB()
  1148.  
  1149.   #define WGL_CCA_ARB_t PFNWGLCREATECONTEXTATTRIBSARBPROC // Lol
  1150.  
  1151.   wglCreateContextAttribsARB_ = (WGL_CCA_ARB_t)loadOpenGLFunction(
  1152.                                   "wgl","CreateContextAttribsARB");
  1153.  
  1154.   if(wglCreateContextAttribsARB_ == nullptr) return -4;
  1155.  
  1156.  
  1157.  
  1158.   // Create the actual 'OpenGL v3.3 core' context (then delete the dummy one)
  1159.  
  1160.   #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
  1161.   #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
  1162.   #define WGL_CONTEXT_PROFILE_MASK_ARB  0x9126
  1163.  
  1164.   #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
  1165.  
  1166.   const int context_attributes[] = {
  1167.     WGL_CONTEXT_MAJOR_VERSION_ARB, 3, // ver X._
  1168.     WGL_CONTEXT_MINOR_VERSION_ARB, 3, // ver _.X
  1169.     WGL_CONTEXT_PROFILE_MASK_ARB , WGL_CONTEXT_CORE_PROFILE_BIT_ARB, // core
  1170.     0 // (null-terminator)
  1171.   };
  1172.  
  1173.   HGLRC renderCtx_old = renderCtx;
  1174.  
  1175.   renderCtx = wglCreateContextAttribsARB(win_dc, 0, context_attributes);
  1176.   if(renderCtx == nullptr) return -5;
  1177.  
  1178.   wglMakeCurrent(NULL, NULL);
  1179.   wglDeleteContext(renderCtx_old);
  1180.   wglMakeCurrent(win_dc, renderCtx);
  1181.  
  1182.  
  1183.  
  1184.   // Load the relevant OpenGL extensions
  1185.  
  1186.   if(!loadOpenGLFunctions("wgl", _Opengl32_names_wgl, _Opengl32_func.ptrs_wgl))
  1187.   {
  1188.     return -6;
  1189.   }
  1190.  
  1191.   if(!loadOpenGLFunctions("gl", _Opengl32_names_gl, _Opengl32_func.ptrs_gl))
  1192.   {
  1193.     return -7;
  1194.   }
  1195.  
  1196.  
  1197.  
  1198.   return 0;
  1199.  
  1200. }
  1201.  
  1202.  
  1203.  
  1204.  
  1205.  
  1206. void OpenGLQuit(){
  1207.   wglMakeCurrent(NULL, NULL);
  1208.   if(renderCtx != nullptr)
  1209.     wglDeleteContext(renderCtx);
  1210.  
  1211. }
  1212.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement