forked from KolibriOS/kolibrios
update demo life2,
fix rev 8179 git-svn-id: svn://kolibrios.org@8184 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
f708b1dae5
commit
9582ac80f6
Binary file not shown.
@ -34,6 +34,7 @@ endp
|
|||||||
proc @MemoryHeap@mem_Free$qpv uses ebx
|
proc @MemoryHeap@mem_Free$qpv uses ebx
|
||||||
mov eax,SF_SYS_MISC
|
mov eax,SF_SYS_MISC
|
||||||
mov ebx,SSF_MEM_FREE
|
mov ebx,SSF_MEM_FREE
|
||||||
|
mov ecx,[esp+8]
|
||||||
int 0x40
|
int 0x40
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef __KOLIBRI_H_INCLUDED_
|
#ifndef __KOLIBRI_H_INCLUDED_
|
||||||
#define __KOLIBRI_H_INCLUDED_
|
#define __KOLIBRI_H_INCLUDED_
|
||||||
|
|
||||||
#include <kos_lib.h>
|
#include "kos_lib.h"
|
||||||
|
|
||||||
// Kolibri interface.
|
// Kolibri interface.
|
||||||
|
|
||||||
@ -37,6 +37,7 @@ namespace Kolibri // All kolibri functions, types and data are nested in the (
|
|||||||
// Note: pass only thread data of current thread as (thread_data) parameter to these functions.
|
// Note: pass only thread data of current thread as (thread_data) parameter to these functions.
|
||||||
|
|
||||||
void Main(); // Main function is called at program startup.
|
void Main(); // Main function is called at program startup.
|
||||||
|
void DrawButton(long id, long color, long x, long y, long c_x, long c_y); // Draw Standard button
|
||||||
void* ThreadMain(void *user = 0, void *stack_begin = 0);
|
void* ThreadMain(void *user = 0, void *stack_begin = 0);
|
||||||
// Called at thread startup, (user) is placed in thread data as a user dword,
|
// Called at thread startup, (user) is placed in thread data as a user dword,
|
||||||
//_ (stack_begin) is placed in thread data as a stack beginning.
|
//_ (stack_begin) is placed in thread data as a stack beginning.
|
||||||
@ -54,8 +55,8 @@ namespace Kolibri // All kolibri functions, types and data are nested in the (
|
|||||||
//_ if (frame) is negative do nothing.
|
//_ if (frame) is negative do nothing.
|
||||||
void MoveWindow(const int window_rect[/* 4 */]); // Move and resize current window.
|
void MoveWindow(const int window_rect[/* 4 */]); // Move and resize current window.
|
||||||
|
|
||||||
void Abort(); // Abnormally terminate a program.
|
void ExitDebug(); // Abnormally terminate a program.
|
||||||
void ExitProcess(); // Exit from the process, don't call any destructors of global varyables
|
void ExitProcess(); // Exit from the process, don't call any destructors of global varyables
|
||||||
void ExitThread(); // Exit from the current thread
|
void ExitThread(); // Exit from the current thread
|
||||||
void ExitThread(TThreadData thread_data);
|
void ExitThread(TThreadData thread_data);
|
||||||
void ReturnMessageLoop(); // Return to the message loop of the thread. Exit from the thread
|
void ReturnMessageLoop(); // Return to the message loop of the thread. Exit from the thread
|
||||||
@ -134,6 +135,7 @@ namespace Kolibri // All kolibri functions, types and data are nested in the (
|
|||||||
//_ of the stack if (stack_end) is zero or (stack_size) is not zero, in this case stack
|
//_ of the stack if (stack_end) is zero or (stack_size) is not zero, in this case stack
|
||||||
//_ will be deleted automaticaly from dynamic memory at the finish of the thread.
|
//_ will be deleted automaticaly from dynamic memory at the finish of the thread.
|
||||||
void DrawText(short x, short y, int color, const char* string);
|
void DrawText(short x, short y, int color, const char* string);
|
||||||
|
void SetWindowCaption(const char* caption);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function, defined outside.
|
// Function, defined outside.
|
||||||
@ -145,6 +147,7 @@ int KolibriOnIdle(Kolibri::TThreadData thread_data); // Return the time to
|
|||||||
void KolibriOnSize(int window_rect[/* 4 */], Kolibri::TThreadData thread_data); // When the window is resized.
|
void KolibriOnSize(int window_rect[/* 4 */], Kolibri::TThreadData thread_data); // When the window is resized.
|
||||||
void KolibriOnKeyPress(Kolibri::TThreadData thread_data); // When user press a key.
|
void KolibriOnKeyPress(Kolibri::TThreadData thread_data); // When user press a key.
|
||||||
void KolibriOnMouse(Kolibri::TThreadData thread_data); // When user move a mouse.
|
void KolibriOnMouse(Kolibri::TThreadData thread_data); // When user move a mouse.
|
||||||
|
void KolibriOnButton(long id, Kolibri::TThreadData th);
|
||||||
|
|
||||||
#ifdef __KOLIBRI__
|
#ifdef __KOLIBRI__
|
||||||
|
|
||||||
@ -249,7 +252,7 @@ namespace Kolibri
|
|||||||
|
|
||||||
// Constants from fasm.
|
// Constants from fasm.
|
||||||
|
|
||||||
#include <kos_func.inc>
|
#include "kos_func.inc"
|
||||||
|
|
||||||
// Functions.
|
// Functions.
|
||||||
|
|
||||||
|
@ -1,920 +0,0 @@
|
|||||||
#include <string.h>
|
|
||||||
#include <process.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <deque.h>
|
|
||||||
|
|
||||||
#include <kolibri.h>
|
|
||||||
#include <kos_heap.h>
|
|
||||||
#include <kos_file.h>
|
|
||||||
|
|
||||||
using namespace Kolibri;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
const char file_prefix[] = "";
|
|
||||||
bool WasThreadCreatedBool = false;
|
|
||||||
|
|
||||||
struct TExceptToMessageLoop
|
|
||||||
{
|
|
||||||
TExceptToMessageLoop() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TThreadDataStruct
|
|
||||||
{
|
|
||||||
void *user;
|
|
||||||
void *stack_begin;
|
|
||||||
TWindowData *win_data;
|
|
||||||
HWND hwnd;
|
|
||||||
int flag;
|
|
||||||
unsigned int win_time, me_time;
|
|
||||||
void *picture;
|
|
||||||
unsigned int picture_width, picture_height;
|
|
||||||
deque<unsigned char> *keys;
|
|
||||||
unsigned int bmp_data_length;
|
|
||||||
unsigned int *bmp_data;
|
|
||||||
unsigned int mouse_state;
|
|
||||||
};
|
|
||||||
|
|
||||||
TThreadDataStruct /*__thread*/ ThreadDataStruct;
|
|
||||||
int nCmdShow;
|
|
||||||
HINSTANCE hInstance;
|
|
||||||
const char szWindowClass[] = "Kolibri window";
|
|
||||||
|
|
||||||
void FinalizeThreadData()
|
|
||||||
{
|
|
||||||
if (ThreadDataStruct.keys)
|
|
||||||
{
|
|
||||||
delete ThreadDataStruct.keys;
|
|
||||||
ThreadDataStruct.keys = 0;
|
|
||||||
}
|
|
||||||
if (ThreadDataStruct.bmp_data)
|
|
||||||
{
|
|
||||||
delete[] ThreadDataStruct.bmp_data;
|
|
||||||
ThreadDataStruct.bmp_data = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CalculateNewTime()
|
|
||||||
{
|
|
||||||
unsigned int t = GetTickCount();
|
|
||||||
unsigned int dt = (unsigned int)(t - ThreadDataStruct.win_time) / 10U;
|
|
||||||
ThreadDataStruct.me_time += dt;
|
|
||||||
ThreadDataStruct.win_time += dt * 10;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawPicture(HDC hdc)
|
|
||||||
{
|
|
||||||
TRecMutex xm;
|
|
||||||
InitRecMutex(&xm);
|
|
||||||
Lock(&xm);
|
|
||||||
UnLock(&xm);
|
|
||||||
|
|
||||||
int w = ThreadDataStruct.picture_width, h = ThreadDataStruct.picture_height;
|
|
||||||
RECT rect;
|
|
||||||
if (!ThreadDataStruct.picture || !ThreadDataStruct.hwnd || w <= 0 || h <= 0) return;
|
|
||||||
if (GetClientRect(ThreadDataStruct.hwnd, &rect))
|
|
||||||
{
|
|
||||||
rect.right -= rect.left; rect.left = 0;
|
|
||||||
rect.bottom -= rect.top; rect.top = 0;
|
|
||||||
if (rect.right <= 0 || rect.bottom <= 0) return;
|
|
||||||
if (w > rect.right) w = rect.right;
|
|
||||||
if (h > rect.bottom) h = rect.bottom;
|
|
||||||
}
|
|
||||||
if (!ThreadDataStruct.bmp_data || ThreadDataStruct.bmp_data_length < w * h)
|
|
||||||
{
|
|
||||||
if (ThreadDataStruct.bmp_data) delete[] ThreadDataStruct.bmp_data;
|
|
||||||
ThreadDataStruct.bmp_data_length = w * h;
|
|
||||||
ThreadDataStruct.bmp_data = new unsigned int[ThreadDataStruct.bmp_data_length];
|
|
||||||
}
|
|
||||||
int i;
|
|
||||||
unsigned char *p = (unsigned char*)ThreadDataStruct.picture;
|
|
||||||
for (i = 0; i < w * h; i++)
|
|
||||||
{
|
|
||||||
ThreadDataStruct.bmp_data[i] = ((unsigned int)p[0]) +
|
|
||||||
((unsigned int)p[1] << 8) + ((unsigned int)p[2] << 16);
|
|
||||||
p += 3;
|
|
||||||
}
|
|
||||||
HBITMAP bitmap = CreateBitmap(w, h, 1, 32, ThreadDataStruct.bmp_data);
|
|
||||||
if (bitmap)
|
|
||||||
{
|
|
||||||
HDC memdc = CreateCompatibleDC(hdc);
|
|
||||||
if (memdc)
|
|
||||||
{
|
|
||||||
SelectObject(memdc, bitmap);
|
|
||||||
BitBlt(hdc, 0, 0, w, h, memdc, 0, 0, SRCCOPY);
|
|
||||||
DeleteObject(memdc);
|
|
||||||
}
|
|
||||||
DeleteObject(bitmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
const int timeout = 20;
|
|
||||||
unsigned int t;
|
|
||||||
PAINTSTRUCT ps;
|
|
||||||
HDC hdc;
|
|
||||||
if (hWnd == ThreadDataStruct.hwnd && ThreadDataStruct.flag != -1)
|
|
||||||
{
|
|
||||||
int window_rect[4];
|
|
||||||
switch (message)
|
|
||||||
{
|
|
||||||
case WM_CREATE:
|
|
||||||
SetTimer(hWnd, 0, timeout, NULL);
|
|
||||||
SendMessage(hWnd, WM_SIZE, SIZE_RESTORED, 0);
|
|
||||||
return 0;
|
|
||||||
case WM_TIMER:
|
|
||||||
t = CalculateNewTime();
|
|
||||||
while (KolibriOnIdle((TThreadData)(&ThreadDataStruct)) == 0 &&
|
|
||||||
GetTickCount() - t + 2 < timeout);
|
|
||||||
return 0;
|
|
||||||
case WM_MOUSEMOVE:
|
|
||||||
KolibriOnMouse((TThreadData)(&ThreadDataStruct));
|
|
||||||
return 0;
|
|
||||||
case WM_LBUTTONDOWN:
|
|
||||||
if (!ThreadDataStruct.mouse_state) SetCapture(hWnd);
|
|
||||||
ThreadDataStruct.mouse_state |= 1;
|
|
||||||
KolibriOnMouse((TThreadData)(&ThreadDataStruct));
|
|
||||||
return 0;
|
|
||||||
case WM_LBUTTONUP:
|
|
||||||
if (ThreadDataStruct.mouse_state & 1)
|
|
||||||
{
|
|
||||||
ThreadDataStruct.mouse_state &= ~1;
|
|
||||||
if (!ThreadDataStruct.mouse_state) ReleaseCapture();
|
|
||||||
KolibriOnMouse((TThreadData)(&ThreadDataStruct));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
case WM_RBUTTONDOWN:
|
|
||||||
if (!ThreadDataStruct.mouse_state) SetCapture(hWnd);
|
|
||||||
ThreadDataStruct.mouse_state |= 2;
|
|
||||||
KolibriOnMouse((TThreadData)(&ThreadDataStruct));
|
|
||||||
return 0;
|
|
||||||
case WM_RBUTTONUP:
|
|
||||||
if (ThreadDataStruct.mouse_state & 2)
|
|
||||||
{
|
|
||||||
ThreadDataStruct.mouse_state &= ~2;
|
|
||||||
if (!ThreadDataStruct.mouse_state) ReleaseCapture();
|
|
||||||
KolibriOnMouse((TThreadData)(&ThreadDataStruct));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
case WM_CAPTURECHANGED:
|
|
||||||
if (ThreadDataStruct.mouse_state)
|
|
||||||
{
|
|
||||||
ThreadDataStruct.mouse_state = 0;
|
|
||||||
KolibriOnMouse((TThreadData)(&ThreadDataStruct));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
//case WM_SYSKEYDOWN: case WM_KEYDOWN:
|
|
||||||
case WM_CHAR:
|
|
||||||
ThreadDataStruct.keys->push_back((unsigned char)wParam);
|
|
||||||
KolibriOnKeyPress((TThreadData)(&ThreadDataStruct));
|
|
||||||
return 0;
|
|
||||||
case WM_SIZE:
|
|
||||||
GetProcessInfo(0, 0, 0, 0, window_rect);
|
|
||||||
KolibriOnSize(window_rect, (TThreadData)(&ThreadDataStruct));
|
|
||||||
InvalidateRect(hWnd, 0, 0);
|
|
||||||
return 0;
|
|
||||||
case WM_PAINT:
|
|
||||||
hdc = BeginPaint(hWnd, &ps);
|
|
||||||
if (ThreadDataStruct.picture) DrawPicture(hdc);
|
|
||||||
EndPaint(hWnd, &ps);
|
|
||||||
return 0;
|
|
||||||
case WM_CLOSE:
|
|
||||||
if (KolibriOnClose((TThreadData)(&ThreadDataStruct)))
|
|
||||||
{
|
|
||||||
ThreadDataStruct.flag = -1;
|
|
||||||
}
|
|
||||||
else return 0;
|
|
||||||
case WM_DESTROY:
|
|
||||||
PostQuitMessage(0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
ATOM MyRegisterClass()
|
|
||||||
{
|
|
||||||
HBRUSH background = CreateSolidBrush(RGB(0, 0, 0));
|
|
||||||
WNDCLASSEX wcex;
|
|
||||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
|
||||||
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
|
||||||
wcex.lpfnWndProc = (WNDPROC)WndProc;
|
|
||||||
wcex.cbClsExtra = 0;
|
|
||||||
wcex.cbWndExtra = 0;
|
|
||||||
wcex.hInstance = hInstance;
|
|
||||||
wcex.hIcon = 0;
|
|
||||||
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
||||||
wcex.hbrBackground = background;
|
|
||||||
wcex.lpszMenuName = NULL;
|
|
||||||
wcex.lpszClassName = szWindowClass;
|
|
||||||
wcex.hIconSm = 0;
|
|
||||||
ATOM ret = RegisterClassEx(&wcex);
|
|
||||||
DeleteObject(background);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
HWND InitInstance(int x, int y, int w, int h)
|
|
||||||
{
|
|
||||||
HWND hWnd;
|
|
||||||
MyRegisterClass();
|
|
||||||
DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, exstyle = 0;
|
|
||||||
hWnd = CreateWindowEx(exstyle, szWindowClass, ThreadDataStruct.win_data->Title, style,
|
|
||||||
x, y, w, h, NULL, NULL, hInstance, NULL);
|
|
||||||
if (!hWnd) return NULL;
|
|
||||||
ShowWindow(hWnd, nCmdShow);
|
|
||||||
UpdateWindow(hWnd);
|
|
||||||
return hWnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ThreadMainProc(void *user)
|
|
||||||
{
|
|
||||||
ThreadMain(user, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Kolibri
|
|
||||||
{
|
|
||||||
void Main() {ThreadMain();}
|
|
||||||
|
|
||||||
void* ThreadMain(void *user, void *stack_begin)
|
|
||||||
{
|
|
||||||
TStartData start_data;
|
|
||||||
ThreadDataStruct.user = user;
|
|
||||||
ThreadDataStruct.stack_begin = stack_begin;
|
|
||||||
ThreadDataStruct.win_data = &start_data.WinData;
|
|
||||||
ThreadDataStruct.hwnd = 0;
|
|
||||||
ThreadDataStruct.flag = 0;
|
|
||||||
ThreadDataStruct.win_time = GetTickCount();
|
|
||||||
ThreadDataStruct.me_time = ThreadDataStruct.win_time / 10;
|
|
||||||
ThreadDataStruct.keys = new deque<unsigned char>;
|
|
||||||
ThreadDataStruct.bmp_data_length = 0;
|
|
||||||
ThreadDataStruct.bmp_data = 0;
|
|
||||||
ThreadDataStruct.mouse_state = 0;
|
|
||||||
start_data.Left = 50; start_data.Width = 256;
|
|
||||||
start_data.Top = 50; start_data.Height = 256;
|
|
||||||
start_data.WinData.WindowType = 0x03;
|
|
||||||
start_data.WinData.HeaderType = 0x80;
|
|
||||||
start_data.WinData.WindowColor = 0xFFFFFF;
|
|
||||||
start_data.WinData.HeaderColor = 0x6060FF;
|
|
||||||
start_data.WinData.BorderColor = 0x000000;
|
|
||||||
start_data.WinData.TitleColor = 0xFFFF40;
|
|
||||||
start_data.WinData.Title = 0;
|
|
||||||
if (KolibriOnStart(start_data, (TThreadData)(&ThreadDataStruct)))
|
|
||||||
{
|
|
||||||
while (ThreadDataStruct.flag < 0)
|
|
||||||
{
|
|
||||||
ThreadDataStruct.flag &= ~0x80000000;
|
|
||||||
if (KolibriOnClose((TThreadData)(&ThreadDataStruct)))
|
|
||||||
{
|
|
||||||
ThreadDataStruct.flag = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ThreadDataStruct.flag >= 0)
|
|
||||||
{
|
|
||||||
assert((ThreadDataStruct.hwnd = InitInstance(start_data.Left,
|
|
||||||
start_data.Top, start_data.Width, start_data.Height)) != NULL);
|
|
||||||
assert(SendMessage(ThreadDataStruct.hwnd, WM_CREATE, 0, 0) == 0);
|
|
||||||
MSG msg;
|
|
||||||
HACCEL hAccelTable = 0;
|
|
||||||
while (GetMessage(&msg, NULL, 0, 0))
|
|
||||||
{
|
|
||||||
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
|
|
||||||
{
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(ThreadDataStruct.flag == -1);
|
|
||||||
}
|
|
||||||
FinalizeThreadData();
|
|
||||||
return ThreadDataStruct.stack_begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetWindowData(TWindowData &win_data)
|
|
||||||
{
|
|
||||||
win_data = *ThreadDataStruct.win_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetWindowData(TWindowData &win_data, TThreadData thread_data)
|
|
||||||
{
|
|
||||||
win_data = *((TThreadDataStruct*)thread_data)->win_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetWindowData(const TWindowData &win_data)
|
|
||||||
{
|
|
||||||
*ThreadDataStruct.win_data = win_data;
|
|
||||||
if (ThreadDataStruct.hwnd)
|
|
||||||
{
|
|
||||||
SetWindowText(ThreadDataStruct.hwnd, ThreadDataStruct.win_data->Title);
|
|
||||||
InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetWindowData(const TWindowData &win_data, TThreadData thread_data)
|
|
||||||
{
|
|
||||||
*((TThreadDataStruct*)thread_data)->win_data = win_data;
|
|
||||||
if (((TThreadDataStruct*)thread_data)->hwnd)
|
|
||||||
{
|
|
||||||
SetWindowText(((TThreadDataStruct*)thread_data)->hwnd,
|
|
||||||
((TThreadDataStruct*)thread_data)->win_data->Title);
|
|
||||||
InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CloseWindow()
|
|
||||||
{
|
|
||||||
if (ThreadDataStruct.hwnd)
|
|
||||||
{
|
|
||||||
SendMessage(ThreadDataStruct.hwnd, WM_CLOSE, 0, 0);
|
|
||||||
}
|
|
||||||
else ThreadDataStruct.flag |= 0x80000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CloseWindow(TThreadData thread_data)
|
|
||||||
{
|
|
||||||
if (((TThreadDataStruct*)thread_data)->hwnd)
|
|
||||||
{
|
|
||||||
SendMessage(((TThreadDataStruct*)thread_data)->hwnd, WM_CLOSE, 0, 0);
|
|
||||||
}
|
|
||||||
else ((TThreadDataStruct*)thread_data)->flag |= 0x80000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Redraw(int /*frame*/)
|
|
||||||
{
|
|
||||||
if (ThreadDataStruct.hwnd)
|
|
||||||
{
|
|
||||||
InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
|
|
||||||
SendMessage(ThreadDataStruct.hwnd, WM_PAINT, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Redraw(int /*frame*/, TThreadData thread_data)
|
|
||||||
{
|
|
||||||
if (((TThreadDataStruct*)thread_data)->hwnd)
|
|
||||||
{
|
|
||||||
InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
|
|
||||||
SendMessage(((TThreadDataStruct*)thread_data)->hwnd, WM_PAINT, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Invalidate(int /*frame*/)
|
|
||||||
{
|
|
||||||
if (ThreadDataStruct.hwnd)
|
|
||||||
{
|
|
||||||
InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Invalidate(int /*frame*/, TThreadData thread_data)
|
|
||||||
{
|
|
||||||
if (((TThreadDataStruct*)thread_data)->hwnd)
|
|
||||||
{
|
|
||||||
InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveWindow(const int window_rect[/* 4 */])
|
|
||||||
{
|
|
||||||
if (!ThreadDataStruct.hwnd) return;
|
|
||||||
RECT rect;
|
|
||||||
if (window_rect[0] == -1 || window_rect[1] == -1 ||
|
|
||||||
window_rect[2] == -1 || window_rect[3] == -1)
|
|
||||||
{
|
|
||||||
if (!GetWindowRect(ThreadDataStruct.hwnd, &rect)) return;
|
|
||||||
::MoveWindow(ThreadDataStruct.hwnd,
|
|
||||||
(window_rect[0] == -1) ? rect.left : window_rect[0],
|
|
||||||
(window_rect[1] == -1) ? rect.top : window_rect[1],
|
|
||||||
(window_rect[2] == -1) ? (rect.right - rect.left) : window_rect[2],
|
|
||||||
(window_rect[3] == -1) ? (rect.bottom - rect.top) : window_rect[3], TRUE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
::MoveWindow(ThreadDataStruct.hwnd, window_rect[0],
|
|
||||||
window_rect[1], window_rect[2], window_rect[3], TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Abort()
|
|
||||||
{
|
|
||||||
if (ThreadDataStruct.hwnd) KillTimer(ThreadDataStruct.hwnd, 0);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExitProcess() {::ExitProcess(0);}
|
|
||||||
|
|
||||||
void ExitThread() {FinalizeThreadData(); ::ExitThread(0);}
|
|
||||||
|
|
||||||
void ExitThread(TThreadData) {FinalizeThreadData(); ::ExitThread(0);}
|
|
||||||
|
|
||||||
void ReturnMessageLoop()
|
|
||||||
{
|
|
||||||
TExceptToMessageLoop ex;
|
|
||||||
throw(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReturnMessageLoop(TThreadData)
|
|
||||||
{
|
|
||||||
TExceptToMessageLoop ex;
|
|
||||||
throw(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Delay(unsigned int time) {Sleep(time * 10);}
|
|
||||||
|
|
||||||
unsigned int Clock() {CalculateNewTime(); return ThreadDataStruct.me_time;}
|
|
||||||
|
|
||||||
int GetPackedTime()
|
|
||||||
{
|
|
||||||
SYSTEMTIME time;
|
|
||||||
GetSystemTime(&time);
|
|
||||||
int t;
|
|
||||||
t = (time.wSecond / 10) * 16 + (time.wSecond % 10);
|
|
||||||
t = (time.wMinute / 10) * 16 + (time.wMinute % 10) + (t << 8);
|
|
||||||
t = (time.wHour / 10) * 16 + (time.wHour % 10) + (t << 8);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetTime(int t[/* 3 */])
|
|
||||||
{
|
|
||||||
SYSTEMTIME time;
|
|
||||||
GetSystemTime(&time);
|
|
||||||
t[0] = time.wSecond;
|
|
||||||
t[1] = time.wMinute;
|
|
||||||
t[2] = time.wHour;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetPackedDate()
|
|
||||||
{
|
|
||||||
SYSTEMTIME time;
|
|
||||||
GetSystemTime(&time);
|
|
||||||
int t;
|
|
||||||
t = ((time.wYear / 10) % 10) * 16 + (time.wYear % 10);
|
|
||||||
t = (time.wDay / 10) * 16 + (time.wDay % 10) + (t << 8);
|
|
||||||
t = (time.wMonth / 10) * 16 + (time.wMonth % 10) + (t << 8);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetDate(int d[/* 3 */])
|
|
||||||
{
|
|
||||||
SYSTEMTIME time;
|
|
||||||
GetSystemTime(&time);
|
|
||||||
d[0] = time.wDay;
|
|
||||||
d[1] = time.wMonth;
|
|
||||||
d[2] = time.wYear;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetTimeDate(int t[/* 6 */])
|
|
||||||
{
|
|
||||||
SYSTEMTIME time;
|
|
||||||
GetSystemTime(&time);
|
|
||||||
t[0] = time.wSecond;
|
|
||||||
t[1] = time.wMinute;
|
|
||||||
t[2] = time.wHour;
|
|
||||||
t[3] = time.wDay;
|
|
||||||
t[4] = time.wMonth;
|
|
||||||
t[5] = time.wYear;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadCommonColors(unsigned int colors[/* 10 */])
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 10; i++) colors[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int GetProcessInfo(unsigned int *use_cpu, char process_name[/* 13 */], unsigned int *use_memory,
|
|
||||||
unsigned int *pid, int window_rect[/* 4 */], unsigned int pid_for)
|
|
||||||
{
|
|
||||||
if (use_cpu) *use_cpu = 0;
|
|
||||||
if (process_name) strcpy(process_name, "noname");
|
|
||||||
if (use_memory) *use_memory = 0;
|
|
||||||
if (pid)
|
|
||||||
{
|
|
||||||
if ((pid_for | 15) == -1) pid_for = getpid();
|
|
||||||
*pid = pid_for;
|
|
||||||
}
|
|
||||||
if (window_rect)
|
|
||||||
{
|
|
||||||
RECT rect;
|
|
||||||
if (ThreadDataStruct.hwnd && GetWindowRect(ThreadDataStruct.hwnd, &rect))
|
|
||||||
{
|
|
||||||
window_rect[0] = rect.left;
|
|
||||||
window_rect[1] = rect.top;
|
|
||||||
window_rect[2] = rect.right - rect.left;
|
|
||||||
window_rect[3] = rect.bottom - rect.top;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
window_rect[0] = 0; window_rect[1] = 0;
|
|
||||||
window_rect[2] = 0; window_rect[3] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int GetPid() {return GetCurrentThreadId();}
|
|
||||||
|
|
||||||
unsigned int GetPid(TThreadData /*thread_data*/) {return GetCurrentThreadId();}
|
|
||||||
|
|
||||||
TThreadData GetThreadData() {return (TThreadData)(&ThreadDataStruct);}
|
|
||||||
|
|
||||||
TThreadData GetThreadData(unsigned int /*pid*/) {return (TThreadData)(&ThreadDataStruct);}
|
|
||||||
|
|
||||||
void* GetPicture(unsigned short &width, unsigned short &height)
|
|
||||||
{
|
|
||||||
width = (unsigned short)ThreadDataStruct.picture_width;
|
|
||||||
height = (unsigned short)ThreadDataStruct.picture_height;
|
|
||||||
return ThreadDataStruct.picture;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* GetPicture(unsigned short &width, unsigned short &height, TThreadData thread_data)
|
|
||||||
{
|
|
||||||
width = (unsigned short)((TThreadDataStruct*)thread_data)->picture_width;
|
|
||||||
height = (unsigned short)((TThreadDataStruct*)thread_data)->picture_height;
|
|
||||||
return ((TThreadDataStruct*)thread_data)->picture;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPicture(void *picture, unsigned short width, unsigned short height)
|
|
||||||
{
|
|
||||||
ThreadDataStruct.picture_width = width;
|
|
||||||
ThreadDataStruct.picture_height = height;
|
|
||||||
ThreadDataStruct.picture = picture;
|
|
||||||
if (ThreadDataStruct.hwnd)
|
|
||||||
{
|
|
||||||
InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPicture(void *picture, unsigned short width, unsigned short height, TThreadData thread_data)
|
|
||||||
{
|
|
||||||
((TThreadDataStruct*)thread_data)->picture_width = width;
|
|
||||||
((TThreadDataStruct*)thread_data)->picture_height = height;
|
|
||||||
((TThreadDataStruct*)thread_data)->picture = picture;
|
|
||||||
if (((TThreadDataStruct*)thread_data)->hwnd)
|
|
||||||
{
|
|
||||||
InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetBorderHeader(unsigned short &border_size, unsigned short &header_size)
|
|
||||||
{
|
|
||||||
border_size = (unsigned short)GetSystemMetrics(SM_CXFRAME);
|
|
||||||
header_size = (unsigned short)(GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetBorderHeader(unsigned short &border_size, unsigned short &header_size, TThreadData /*thread_data*/)
|
|
||||||
{
|
|
||||||
border_size = (unsigned short)GetSystemMetrics(SM_CXFRAME);
|
|
||||||
header_size = (unsigned short)(GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetClientSize(unsigned short &width, unsigned short &height)
|
|
||||||
{
|
|
||||||
if (!ThreadDataStruct.hwnd) {width = 0; height = 0; return;}
|
|
||||||
RECT rect;
|
|
||||||
GetClientRect(ThreadDataStruct.hwnd, &rect);
|
|
||||||
width = (unsigned short)(rect.right - rect.left);
|
|
||||||
height = (unsigned short)(rect.bottom - rect.top);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetClientSize(unsigned short &width, unsigned short &height, TThreadData thread_data)
|
|
||||||
{
|
|
||||||
if (!((TThreadDataStruct*)thread_data)->hwnd) {width = 0; height = 0; return;}
|
|
||||||
RECT rect;
|
|
||||||
GetClientRect(((TThreadDataStruct*)thread_data)->hwnd, &rect);
|
|
||||||
width = (unsigned short)(rect.right - rect.left);
|
|
||||||
height = (unsigned short)(rect.bottom - rect.top);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height)
|
|
||||||
{
|
|
||||||
win_width -= 2*GetSystemMetrics(SM_CXFRAME);
|
|
||||||
win_height -= 2*GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
|
|
||||||
if (win_width < 0) win_width = 0;
|
|
||||||
if (win_height < 0) win_height = 0;
|
|
||||||
width = (unsigned short)win_width; height = (unsigned short)win_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetClientSize(unsigned short &width, unsigned short &height,
|
|
||||||
int win_width, int win_height, TThreadData /*thread_data*/)
|
|
||||||
{
|
|
||||||
win_width -= 2*GetSystemMetrics(SM_CXFRAME);
|
|
||||||
win_height -= 2*GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
|
|
||||||
if (win_width < 0) win_width = 0;
|
|
||||||
if (win_height < 0) win_height = 0;
|
|
||||||
width = (unsigned short)win_width; height = (unsigned short)win_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetScreenSize(unsigned short &width, unsigned short &height)
|
|
||||||
{
|
|
||||||
width = (unsigned short)GetSystemMetrics(SM_CXFULLSCREEN);
|
|
||||||
height = (unsigned short)GetSystemMetrics(SM_CYFULLSCREEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
TMutex::TMutex() {mut = (unsigned int)CreateMutex(NULL, FALSE, NULL);}
|
|
||||||
|
|
||||||
TMutex::~TMutex() {if (mut) {CloseHandle((HANDLE)mut); mut = 0;}}
|
|
||||||
|
|
||||||
TRecMutex::TRecMutex() {mut = (unsigned int)CreateMutex(NULL, FALSE, NULL);}
|
|
||||||
|
|
||||||
TRecMutex::~TRecMutex() {if (mut) {CloseHandle((HANDLE)mut); mut = 0;}}
|
|
||||||
|
|
||||||
void InitMutex(TMutex *mutex) {if (!mutex->mut) *mutex = TMutex();}
|
|
||||||
|
|
||||||
void InitRecMutex(TRecMutex *mutex) {if (!mutex->mut) *mutex = TRecMutex();}
|
|
||||||
|
|
||||||
bool TryLock(TMutex *mutex)
|
|
||||||
{
|
|
||||||
DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
|
|
||||||
return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryLock(TRecMutex *mutex, unsigned int /*pid*/)
|
|
||||||
{
|
|
||||||
DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
|
|
||||||
return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryLock(TRecMutex *mutex)
|
|
||||||
{
|
|
||||||
DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
|
|
||||||
return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryLock(TRecMutex *mutex, TThreadData /*thread_data*/)
|
|
||||||
{
|
|
||||||
DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
|
|
||||||
return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lock(TMutex *mutex)
|
|
||||||
{
|
|
||||||
WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lock(TRecMutex *mutex, unsigned int /*pid*/)
|
|
||||||
{
|
|
||||||
WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lock(TRecMutex *mutex)
|
|
||||||
{
|
|
||||||
WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lock(TRecMutex *mutex, TThreadData /*thread_data*/)
|
|
||||||
{
|
|
||||||
WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LockTime(TMutex *mutex, unsigned int time)
|
|
||||||
{
|
|
||||||
DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
|
|
||||||
return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LockTime(TRecMutex *mutex, unsigned int time, unsigned int /*pid*/)
|
|
||||||
{
|
|
||||||
DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
|
|
||||||
return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LockTime(TRecMutex *mutex, unsigned int time)
|
|
||||||
{
|
|
||||||
DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
|
|
||||||
return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LockTime(TRecMutex *mutex, unsigned int time, TThreadData /*thread_data*/)
|
|
||||||
{
|
|
||||||
DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
|
|
||||||
return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnLock(TMutex *mutex)
|
|
||||||
{
|
|
||||||
ReleaseMutex((HANDLE)mutex->mut);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnLock(TRecMutex *mutex, unsigned int /*pid*/)
|
|
||||||
{
|
|
||||||
ReleaseMutex((HANDLE)mutex->mut);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnLock(TRecMutex *mutex)
|
|
||||||
{
|
|
||||||
ReleaseMutex((HANDLE)mutex->mut);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnLock(TRecMutex *mutex, TThreadData /*thread_data*/)
|
|
||||||
{
|
|
||||||
ReleaseMutex((HANDLE)mutex->mut);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugPutChar(char c)
|
|
||||||
{
|
|
||||||
DWORD num_written;
|
|
||||||
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), &c, 1, &num_written, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugPutString(const char *s)
|
|
||||||
{
|
|
||||||
DWORD num_written;
|
|
||||||
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), s, strlen(s), &num_written, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetKey()
|
|
||||||
{
|
|
||||||
if (ThreadDataStruct.keys->empty()) return -1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned char c = ThreadDataStruct.keys->front();
|
|
||||||
ThreadDataStruct.keys->pop_front();
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetMouseButton()
|
|
||||||
{
|
|
||||||
return ThreadDataStruct.mouse_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetMousePosition(short &x, short &y, bool absolute)
|
|
||||||
{
|
|
||||||
POINT point;
|
|
||||||
if (!GetCursorPos(&point)) {x = -1; y = -1;}
|
|
||||||
else if (absolute) {x = (short)point.x; y = (short)point.y;}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RECT rect;
|
|
||||||
if (!ThreadDataStruct.hwnd || !GetWindowRect(ThreadDataStruct.hwnd, &rect))
|
|
||||||
{
|
|
||||||
x = -1; y = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = (short)(point.x - rect.left);
|
|
||||||
y = (short)(point.y - rect.top);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetMousePosPicture(short &x, short &y)
|
|
||||||
{
|
|
||||||
POINT point;
|
|
||||||
if (!GetCursorPos(&point)) {x = -1; y = -1;}
|
|
||||||
else if (!ThreadDataStruct.hwnd || !ScreenToClient(ThreadDataStruct.hwnd, &point))
|
|
||||||
{
|
|
||||||
x = -1; y = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = (short)point.x;
|
|
||||||
y = (short)point.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WasThreadCreated() {return WasThreadCreatedBool;}
|
|
||||||
|
|
||||||
unsigned int CreateThread(void *user, unsigned int stack_size, void* /*stack_end*/)
|
|
||||||
{
|
|
||||||
unsigned long pid = -1;
|
|
||||||
WasThreadCreatedBool = true;
|
|
||||||
if (!::CreateThread(NULL, stack_size, (LPTHREAD_START_ROUTINE)ThreadMainProc, user, 0, &pid))
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int StrLen(const char *str) {return ::strlen(str);}
|
|
||||||
|
|
||||||
char *StrCopy(char *dest, const char *src) {return ::strcpy(dest, src);}
|
|
||||||
|
|
||||||
void *MemCopy(void *dest, const void *src, unsigned int n) {return ::memcpy(dest, src, n);}
|
|
||||||
|
|
||||||
void *MemSet(void *s, char c, unsigned int n) {return ::memset(s, c, n);}
|
|
||||||
|
|
||||||
double Floor(double x) {return floor(x);}
|
|
||||||
|
|
||||||
void *Alloc(unsigned int size) {return malloc(size);}
|
|
||||||
|
|
||||||
void *ReAlloc(void *mem, unsigned int size) {return realloc(mem, size);}
|
|
||||||
|
|
||||||
void Free(void *mem) {free(mem);}
|
|
||||||
|
|
||||||
TFileData FileOpen(const char *name, unsigned int /*buffer_length*/)
|
|
||||||
{
|
|
||||||
if (!name || !name[0]) return 0;
|
|
||||||
TFileData file_data = (TFileData)Alloc(sizeof(unsigned int) +
|
|
||||||
strlen(file_prefix) + strlen(name) + 1);
|
|
||||||
if (!file_data) return 0;
|
|
||||||
file_data->data = 0;
|
|
||||||
strcpy((char*)file_data + sizeof(unsigned int), file_prefix);
|
|
||||||
strcat((char*)file_data + sizeof(unsigned int), name);
|
|
||||||
return file_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileClose(TFileData file_data)
|
|
||||||
{
|
|
||||||
if (!file_data) return -1;
|
|
||||||
if (file_data->data) CloseHandle((HANDLE)file_data->data);
|
|
||||||
Free(file_data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileEof(TFileData file_data)
|
|
||||||
{
|
|
||||||
unsigned int pos;
|
|
||||||
if (FileTestRead(file_data) < 0) return false;
|
|
||||||
pos = SetFilePointer((HANDLE)file_data->data, 0, NULL, FILE_CURRENT);
|
|
||||||
if (pos == -1) return false;
|
|
||||||
return pos >= GetFileSize((HANDLE)file_data->data, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int FileGetPosition(TFileData file_data)
|
|
||||||
{
|
|
||||||
unsigned int pos;
|
|
||||||
if (FileTestRead(file_data) < 0) return 0;
|
|
||||||
pos = SetFilePointer((HANDLE)file_data->data, 0, NULL, FILE_CURRENT);
|
|
||||||
return (pos == -1) ? 0 : pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileSetPosition(TFileData file_data, unsigned int pos)
|
|
||||||
{
|
|
||||||
if (FileTestRead(file_data) < 0) return;
|
|
||||||
SetFilePointer((HANDLE)file_data->data, pos, NULL, FILE_BEGIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileReset(TFileData file_data)
|
|
||||||
{
|
|
||||||
if (!file_data || !file_data->data) return;
|
|
||||||
FlushFileBuffers((HANDLE)file_data->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int FileGetLength(TFileData file_data)
|
|
||||||
{
|
|
||||||
if (FileTestRead(file_data) < 0) return -1;
|
|
||||||
return GetFileSize((HANDLE)file_data->data, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileTestRead(TFileData file_data)
|
|
||||||
{
|
|
||||||
if (!file_data) return -1;
|
|
||||||
if (!file_data->data)
|
|
||||||
{
|
|
||||||
file_data->data = (unsigned int)CreateFile((char*)file_data + sizeof(unsigned int),
|
|
||||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 0);
|
|
||||||
if (!file_data->data) return -512;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileRead(TFileData file_data, void *mem, int size)
|
|
||||||
{
|
|
||||||
if (!file_data || !mem || size <= 0) return -1;
|
|
||||||
int res = FileTestRead(file_data);
|
|
||||||
if (res < 0) return res;
|
|
||||||
if (!ReadFile((HANDLE)file_data->data, mem, size, (unsigned long*)&res, NULL))
|
|
||||||
{
|
|
||||||
return -512;
|
|
||||||
}
|
|
||||||
return (res >= 0) ? res : (-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CheckAllocConsole(LPSTR lpCmdLine)
|
|
||||||
{
|
|
||||||
char Console[] = "-console";
|
|
||||||
int ConsoleL = ::strlen(Console);
|
|
||||||
char *s;
|
|
||||||
for (s = lpCmdLine; *s; s++)
|
|
||||||
{
|
|
||||||
if ((s == lpCmdLine || isspace(s[-1])) && memcmp(s, Console, ConsoleL) == 0 &&
|
|
||||||
(!s[ConsoleL] || isspace(s[ConsoleL])))
|
|
||||||
{
|
|
||||||
AllocConsole();
|
|
||||||
SetConsoleTitle("Debug Console");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int APIENTRY WinMain(HINSTANCE hInstance,
|
|
||||||
HINSTANCE /*hPrevInstance*/,
|
|
||||||
LPSTR lpCmdLine,
|
|
||||||
int nCmdShow)
|
|
||||||
{
|
|
||||||
::nCmdShow = nCmdShow;
|
|
||||||
::hInstance = hInstance;
|
|
||||||
CheckAllocConsole(lpCmdLine);
|
|
||||||
Main();
|
|
||||||
//::ExitThread(0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,278 +1,95 @@
|
|||||||
#ifndef __KOLIBRI_FILE_H_INCLUDED_
|
#ifndef __KOLIBRI_FILE_H_INCLUDED_
|
||||||
#define __KOLIBRI_FILE_H_INCLUDED_
|
#define __KOLIBRI_FILE_H_INCLUDED_
|
||||||
|
|
||||||
#include <kolibri.h>
|
#include "kolibri.h"
|
||||||
#include <kos_heap.h>
|
#include "kos_heap.h"
|
||||||
|
|
||||||
// Kolibri file interface.
|
// Kolibri file interface.
|
||||||
|
|
||||||
namespace Kolibri // All kolibri functions, types and data are nested in the (Kolibri) namespace.
|
namespace Kolibri // All kolibri functions, types and data are nested in the (Kolibri) namespace.
|
||||||
{
|
{
|
||||||
struct _FileDataStruct;
|
struct FileDateTime{
|
||||||
typedef _FileDataStruct *TFileData;
|
unsigned long int time;
|
||||||
|
unsigned long int date;
|
||||||
TFileData FileOpen(const char *name, unsigned int buffer_length = 1024);
|
|
||||||
int FileClose(TFileData file_data);
|
|
||||||
bool FileEof(TFileData file_data);
|
|
||||||
unsigned int FileGetPosition(TFileData file_data);
|
|
||||||
void FileSetPosition(TFileData file_data, unsigned int pos);
|
|
||||||
void FileReset(TFileData file_data);
|
|
||||||
unsigned int FileGetLength(TFileData file_data);
|
|
||||||
int FileTestRead(TFileData file_data);
|
|
||||||
int FileRead(TFileData file_data, void *mem, int size);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __KOLIBRI__
|
|
||||||
|
|
||||||
namespace Kolibri
|
|
||||||
{
|
|
||||||
// Define the file data structure.
|
|
||||||
|
|
||||||
struct _FileDataStruct
|
|
||||||
{
|
|
||||||
unsigned int length;
|
|
||||||
unsigned int position;
|
|
||||||
unsigned int *buffer;
|
|
||||||
unsigned int access_param[5];
|
|
||||||
|
|
||||||
enum {PosName = (unsigned int)(((_FileDataStruct*)0)->access_param + 5)};
|
|
||||||
};
|
};
|
||||||
|
struct FileInfoBlock
|
||||||
// Inline functions.
|
|
||||||
|
|
||||||
inline bool FileEof(TFileData file_data)
|
|
||||||
{
|
{
|
||||||
return file_data && file_data->position >= file_data->length;
|
unsigned long int Function;
|
||||||
}
|
unsigned long int Position;
|
||||||
|
unsigned long int Flags;
|
||||||
inline unsigned int FileGetPosition(TFileData file_data)
|
unsigned long int Count;
|
||||||
|
char *Buffer;
|
||||||
|
char *FileName1;
|
||||||
|
char *FileName2;
|
||||||
|
};
|
||||||
|
struct FileInfoA
|
||||||
{
|
{
|
||||||
return file_data ? file_data->position : 0;
|
unsigned long int Attributes;
|
||||||
}
|
unsigned long int Flags;
|
||||||
|
FileDateTime DateCreate;
|
||||||
inline void FileReset(TFileData file_data)
|
FileDateTime DateAccess;
|
||||||
{
|
FileDateTime DateModify;
|
||||||
if (!file_data) return;
|
unsigned long int FileSizeLow;
|
||||||
file_data->length = -1;
|
unsigned long int FileSizeHigh;
|
||||||
file_data->position = 0;
|
char FileName[520];
|
||||||
if (file_data->buffer) file_data->buffer[1] = 0;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Functions.
|
// Functions.
|
||||||
|
|
||||||
int _FileAccess(void *file_access_param);
|
int _FileAccess(FileInfoBlock *file_access);
|
||||||
|
|
||||||
TFileData FileOpen(const char *name, unsigned int buffer_length)
|
FileInfoBlock* FileOpen(const char *name)
|
||||||
{
|
{
|
||||||
if (!name || !name[0]) return 0;
|
if (!name || !name[0]){
|
||||||
unsigned int name_len = StrLen(name) + 1;
|
DebugPutString("name is 0");
|
||||||
unsigned int data_len = (_FileDataStruct::PosName + name_len + 3) & ~3;
|
return 0;
|
||||||
buffer_length = (buffer_length / KOLIBRI_FILE_BLOCK_SIZE) * KOLIBRI_FILE_BLOCK_SIZE;
|
|
||||||
if (buffer_length) data_len += buffer_length + 2*sizeof(unsigned int);
|
|
||||||
TFileData file = (TFileData)Alloc(_FileDataStruct::PosName + data_len);
|
|
||||||
if (!file) return 0;
|
|
||||||
file->length = -1;
|
|
||||||
file->position = 0;
|
|
||||||
if (buffer_length)
|
|
||||||
{
|
|
||||||
file->buffer = (unsigned int*)((char*)file + data_len) - 2;
|
|
||||||
file->buffer[0] = buffer_length;
|
|
||||||
file->buffer[1] = 0;
|
|
||||||
}
|
}
|
||||||
MemCopy(file->access_param + 5, name, name_len);
|
FileInfoBlock* file = (FileInfoBlock*)Alloc(sizeof(FileInfoBlock)+sizeof(FileInfoA));
|
||||||
unsigned int attr[40/4];
|
if (!file){
|
||||||
file->access_param[0] = 5;
|
DebugPutString("mem_Alloc -> 0");
|
||||||
file->access_param[1] = 0;
|
return 0;
|
||||||
file->access_param[2] = 0;
|
}
|
||||||
file->access_param[3] = 0;
|
file->Function = 5; //SSF_GET_INFO
|
||||||
file->access_param[4] = (int)attr;
|
file->Position = 0;
|
||||||
_FileAccess(file->access_param);
|
file->Flags = 0;
|
||||||
file->length = attr[32/4];
|
file->Count = 0;
|
||||||
|
file->Buffer = (char*)file+sizeof(FileInfoBlock);
|
||||||
|
file->FileName1 = (char*)name;
|
||||||
|
file->FileName2 = (char*)name;
|
||||||
|
file->FileName1 = (char*)((long)file->FileName1 << 8);
|
||||||
|
file->FileName2 = (char*)((long)file->FileName2 >> 24);
|
||||||
|
|
||||||
|
_FileAccess(file);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FileClose(TFileData file_data)
|
int FileClose(FileInfoBlock* file_data)
|
||||||
{
|
{
|
||||||
if (!file_data) return -1;
|
if (!file_data) return -1;
|
||||||
Free(file_data);
|
Free(file_data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSetPosition(TFileData file_data, unsigned int pos)
|
unsigned long int FileRead(FileInfoBlock* file_data, void *mem, int size)
|
||||||
{
|
{
|
||||||
if (!file_data) return;
|
file_data->Function = 0; //SSF_READ_FILE
|
||||||
if (file_data->buffer && file_data->buffer[1])
|
file_data->Position = 0;
|
||||||
{
|
file_data->Flags = 0;
|
||||||
if (pos >= file_data->position && pos < file_data->position + file_data->buffer[1])
|
file_data->Count = size;
|
||||||
{
|
file_data->Buffer = (char*)mem;
|
||||||
file_data->buffer[1] -= pos - file_data->position;
|
|
||||||
}
|
|
||||||
else file_data->buffer[1] = 0;
|
|
||||||
}
|
|
||||||
file_data->position = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _FileReadBuffer(TFileData file_data, void *mem, int size, void *temp_mem = 0)
|
if(!_FileAccess(file_data)) return file_data->Function;
|
||||||
{
|
|
||||||
unsigned int *buffer;
|
|
||||||
if (!file_data || !mem || size <= 0) return -1;
|
|
||||||
if (file_data->buffer) buffer = file_data->buffer;
|
|
||||||
else if (temp_mem)
|
|
||||||
{
|
|
||||||
buffer = (unsigned int*)((char*)temp_mem + KOLIBRI_FILE_BLOCK_SIZE);
|
|
||||||
}
|
|
||||||
else return 0;
|
else return 0;
|
||||||
if (!buffer[1]) return 0;
|
|
||||||
if (file_data->position >= file_data->length)
|
|
||||||
{
|
|
||||||
buffer[1] = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
unsigned int buf_size = file_data->length - file_data->position;
|
|
||||||
if (buf_size > buffer[1]) buf_size = buffer[1];
|
|
||||||
if ((unsigned int)size >= buf_size) size = buf_size;
|
|
||||||
MemCopy(mem, (char*)buffer - buffer[1], size);
|
|
||||||
file_data->position += size;
|
|
||||||
if ((unsigned int)size >= buf_size) buffer[1] = 0;
|
|
||||||
else buffer[1] -= size;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _FileReadSystem(TFileData file_data, void *mem, int size)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
unsigned int len0, len1;
|
|
||||||
size /= KOLIBRI_FILE_BLOCK_SIZE;
|
|
||||||
if (!file_data || !mem || size <= 0) return -1;
|
|
||||||
file_data->access_param[0] = 0;
|
|
||||||
file_data->access_param[1] = (file_data->position / KOLIBRI_FILE_BLOCK_SIZE) * KOLIBRI_FILE_BLOCK_SIZE;
|
|
||||||
file_data->access_param[2] = 0;
|
|
||||||
file_data->access_param[3] = size * KOLIBRI_FILE_BLOCK_SIZE;
|
|
||||||
file_data->access_param[4] = (unsigned int)mem;
|
|
||||||
res = _FileAccess(file_data->access_param);
|
|
||||||
if (res != 0 && res != 6) return (res & 255) - 1024;
|
|
||||||
if (file_data->length <= file_data->position) return 0;
|
|
||||||
len0 = file_data->length - file_data->position;
|
|
||||||
len1 = size * KOLIBRI_FILE_BLOCK_SIZE - (file_data->position % KOLIBRI_FILE_BLOCK_SIZE);
|
|
||||||
return (len0 <= len1) ? len0 : len1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _FileBufferSystem(TFileData file_data, void *&temp_mem)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
unsigned int *buffer;
|
|
||||||
if (!file_data) return -1;
|
|
||||||
if (file_data->buffer) buffer = file_data->buffer;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!temp_mem)
|
|
||||||
{
|
|
||||||
temp_mem = Alloc(KOLIBRI_FILE_BLOCK_SIZE + 2*sizeof(unsigned int));
|
|
||||||
if (!temp_mem) return -10;
|
|
||||||
}
|
|
||||||
buffer = (unsigned int*)((char*)temp_mem + KOLIBRI_FILE_BLOCK_SIZE);
|
|
||||||
buffer[0] = KOLIBRI_FILE_BLOCK_SIZE;
|
|
||||||
}
|
|
||||||
buffer[1] = buffer[0];
|
|
||||||
res = _FileReadSystem(file_data, (char*)buffer - buffer[1], buffer[1]);
|
|
||||||
if (res < 0) buffer[1] = 0;
|
|
||||||
else buffer[1] -= file_data->position % KOLIBRI_FILE_BLOCK_SIZE;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileTestRead(TFileData file_data)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
void *temp_mem = 0;
|
|
||||||
if (!file_data) return -1;
|
|
||||||
if (file_data->buffer && file_data->buffer[1]) return 0;
|
|
||||||
res = _FileBufferSystem(file_data, temp_mem);
|
|
||||||
if (temp_mem) Free(temp_mem);
|
|
||||||
return (res < 0) ? res : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileRead(TFileData file_data, void *mem, int size)
|
|
||||||
{
|
|
||||||
int tlen, res, read_len;
|
|
||||||
void *temp_mem = 0;
|
|
||||||
res = _FileReadBuffer(file_data, mem, size);
|
|
||||||
if (res < 0 || res >= size) return res;
|
|
||||||
read_len = res;
|
|
||||||
mem = (char*)mem + res;
|
|
||||||
size -= res;
|
|
||||||
tlen = file_data->position % KOLIBRI_FILE_BLOCK_SIZE;
|
|
||||||
if (tlen)
|
|
||||||
{
|
|
||||||
res = _FileBufferSystem(file_data, temp_mem);
|
|
||||||
if (res < 0)
|
|
||||||
{
|
|
||||||
if (temp_mem) Free(temp_mem);
|
|
||||||
return read_len ? read_len : res;
|
|
||||||
}
|
|
||||||
res = _FileReadBuffer(file_data, mem, size);
|
|
||||||
read_len += res;
|
|
||||||
if (res >= size || file_data->length <= file_data->position ||
|
|
||||||
file_data->length - file_data->position <= res)
|
|
||||||
{
|
|
||||||
if (temp_mem) Free(temp_mem);
|
|
||||||
return read_len;
|
|
||||||
}
|
|
||||||
mem = (char*)mem + res;
|
|
||||||
size -= res;
|
|
||||||
}
|
|
||||||
if (size >= (file_data->buffer ? file_data->buffer[0] : KOLIBRI_FILE_BLOCK_SIZE))
|
|
||||||
{
|
|
||||||
res = _FileReadSystem(file_data, mem, size);
|
|
||||||
if (res < 0)
|
|
||||||
{
|
|
||||||
if (temp_mem) Free(temp_mem);
|
|
||||||
return read_len ? read_len : res;
|
|
||||||
}
|
|
||||||
file_data->position += res;
|
|
||||||
read_len += res;
|
|
||||||
if (res < (size / KOLIBRI_FILE_BLOCK_SIZE) * KOLIBRI_FILE_BLOCK_SIZE)
|
|
||||||
{
|
|
||||||
if (temp_mem) Free(temp_mem);
|
|
||||||
return read_len;
|
|
||||||
}
|
|
||||||
mem = (char*)mem + res;
|
|
||||||
size -= res;
|
|
||||||
}
|
|
||||||
if (size)
|
|
||||||
{
|
|
||||||
res = _FileBufferSystem(file_data, temp_mem);
|
|
||||||
if (res < 0)
|
|
||||||
{
|
|
||||||
if (temp_mem) Free(temp_mem);
|
|
||||||
return read_len ? read_len : res;
|
|
||||||
}
|
|
||||||
read_len += _FileReadBuffer(file_data, mem, size, temp_mem);
|
|
||||||
}
|
|
||||||
if (temp_mem) Free(temp_mem);
|
|
||||||
return read_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inline functions.
|
// Inline functions.
|
||||||
|
|
||||||
inline unsigned int FileGetLength(TFileData file_data)
|
inline unsigned long int FileGetLength(FileInfoBlock* file_data)
|
||||||
{
|
{
|
||||||
if (!file_data) return -1;
|
if (!file_data) return -1;
|
||||||
if (file_data->length == -1) FileTestRead(file_data);
|
return (unsigned long int)*(long*)((char*)file_data+sizeof(FileInfoBlock)+32);
|
||||||
return file_data->length;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // def __KOLIBRI__
|
|
||||||
|
|
||||||
namespace Kolibri
|
|
||||||
{
|
|
||||||
struct _FileDataStruct
|
|
||||||
{
|
|
||||||
unsigned int data;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // else: def __KOLIBRI__
|
|
||||||
|
|
||||||
#endif // ndef __KOLIBRI_FILE_H_INCLUDED_
|
#endif // ndef __KOLIBRI_FILE_H_INCLUDED_
|
||||||
|
|
||||||
|
@ -41,12 +41,6 @@ KOLIBRI_THREAD_DATA_LEN = 16;
|
|||||||
;const int
|
;const int
|
||||||
KOLIBRI_MUTEX_MAX_TIME_WAIT = 20;
|
KOLIBRI_MUTEX_MAX_TIME_WAIT = 20;
|
||||||
|
|
||||||
;const int
|
|
||||||
KOLIBRI_FILE_BLOCK_SIZE = 512;
|
|
||||||
|
|
||||||
;const int
|
|
||||||
KOLIBRI_FILE_MEMORY_OS_NEED = 4096;
|
|
||||||
|
|
||||||
;/***
|
;/***
|
||||||
|
|
||||||
macro segment name
|
macro segment name
|
||||||
@ -1122,7 +1116,7 @@ end if
|
|||||||
jmp .create_thread_fill_stack
|
jmp .create_thread_fill_stack
|
||||||
endp
|
endp
|
||||||
|
|
||||||
proc @Kolibri@_FileAccess$qpv uses ebx
|
proc @Kolibri@_FileAccess$qp21Kolibri@FileInfoBlock uses ebx
|
||||||
mov eax,SF_FILE
|
mov eax,SF_FILE
|
||||||
mov ebx,[esp+8]
|
mov ebx,[esp+8]
|
||||||
int 0x40
|
int 0x40
|
||||||
|
@ -1,90 +1,32 @@
|
|||||||
#ifndef __KOLIBRI_HEAP_H_INCLUDED_
|
#ifndef __KOLIBRI_HEAP_H_INCLUDED_
|
||||||
#define __KOLIBRI_HEAP_H_INCLUDED_
|
#define __KOLIBRI_HEAP_H_INCLUDED_
|
||||||
|
|
||||||
#include <kolibri.h>
|
#include "kolibri.h"
|
||||||
#include <memheap.h>
|
#include "memheap.h"
|
||||||
|
|
||||||
// Kolibri memory heap interface.
|
// Kolibri memory heap interface.
|
||||||
|
|
||||||
namespace Kolibri // All kolibri functions, types and data are nested in the (Kolibri) namespace.
|
namespace Kolibri // All kolibri functions, types and data are nested in the (Kolibri) namespace.
|
||||||
{
|
{
|
||||||
void *Alloc(unsigned int size);
|
long _HeapInit()
|
||||||
void *ReAlloc(void *mem, unsigned int size);
|
|
||||||
void Free(void *mem);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __KOLIBRI__
|
|
||||||
|
|
||||||
namespace Kolibri
|
|
||||||
{
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
|
|
||||||
MemoryHeap::TFreeSpace _KolibriFreeSpace;
|
|
||||||
MemoryHeap::TMemBlock _KolibriMemBlock;
|
|
||||||
TMutex _MemHeapMutex = KOLIBRI_MUTEX_INIT;
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
|
|
||||||
void *_HeapInit(void *begin, void *use_end, void *end)
|
|
||||||
{
|
{
|
||||||
MemoryHeap::InitFreeSpace(_KolibriFreeSpace);
|
return MemoryHeap::mem_Init();
|
||||||
_KolibriMemBlock = MemoryHeap::CreateBlock(begin, end, _KolibriFreeSpace);
|
|
||||||
unsigned int use_beg = (unsigned int)MemoryHeap::BlockBegin(_KolibriMemBlock) +
|
|
||||||
MemoryHeap::BlockAddSize - MemoryHeap::BlockEndSize;
|
|
||||||
unsigned int use_size = (unsigned int)use_end;
|
|
||||||
if (use_size <= use_beg) return 0;
|
|
||||||
else use_size -= use_beg;
|
|
||||||
return MemoryHeap::Alloc(_KolibriFreeSpace, use_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _SetUseMemory(unsigned int use_mem);
|
|
||||||
|
|
||||||
int _RecalculateUseMemory(unsigned int use_mem);
|
|
||||||
|
|
||||||
void *Alloc(unsigned int size)
|
void *Alloc(unsigned int size)
|
||||||
{
|
{
|
||||||
if (!size) return 0;
|
return MemoryHeap::mem_Alloc(size);
|
||||||
Lock(&_MemHeapMutex);
|
|
||||||
void *res = MemoryHeap::Alloc(_KolibriFreeSpace, size);
|
|
||||||
if (!res)
|
|
||||||
{
|
|
||||||
unsigned use_mem = (unsigned int)MemoryHeap::BlockEndFor(_KolibriMemBlock, size);
|
|
||||||
if (_SetUseMemory(_RecalculateUseMemory(use_mem)))
|
|
||||||
{
|
|
||||||
res = MemoryHeap::Alloc(_KolibriFreeSpace, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UnLock(&_MemHeapMutex);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ReAlloc(void *mem, unsigned int size)
|
void *ReAlloc(void *mem, unsigned int size)
|
||||||
{
|
{
|
||||||
Lock(&_MemHeapMutex);
|
return MemoryHeap::mem_ReAlloc(size, mem);
|
||||||
void *res = MemoryHeap::ReAlloc(_KolibriFreeSpace, mem, size);
|
|
||||||
if (!res && size)
|
|
||||||
{
|
|
||||||
unsigned use_mem = (unsigned int)MemoryHeap::BlockEndFor(_KolibriMemBlock, size);
|
|
||||||
if (_SetUseMemory(_RecalculateUseMemory(use_mem)))
|
|
||||||
{
|
|
||||||
res = MemoryHeap::ReAlloc(_KolibriFreeSpace, mem, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UnLock(&_MemHeapMutex);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Free(void *mem)
|
void Free(void *mem)
|
||||||
{
|
{
|
||||||
Lock(&_MemHeapMutex);
|
MemoryHeap::mem_Free(mem);
|
||||||
MemoryHeap::Free(_KolibriFreeSpace, mem);
|
|
||||||
UnLock(&_MemHeapMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _FreeAndThreadFinish(void *mem, int *exit_proc_now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // def __KOLIBRI__
|
|
||||||
|
|
||||||
#endif // ndef __KOLIBRI_HEAP_H_INCLUDED_
|
#endif // ndef __KOLIBRI_HEAP_H_INCLUDED_
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
;/***
|
;/***
|
||||||
|
|
||||||
KolibriHeapInit = @@Kolibri@_HeapInit$qpvt1t1
|
KolibriHeapInit = @@Kolibri@_HeapInit$qv
|
||||||
|
|
||||||
KolibriHeapAlloc = @@Kolibri@Alloc$qui
|
KolibriHeapAlloc = @@Kolibri@Alloc$qui
|
||||||
|
|
||||||
@ -8,90 +8,35 @@ KolibriHeapReAlloc = @@Kolibri@ReAlloc$qpvui
|
|||||||
|
|
||||||
KolibriHeapFree = @@Kolibri@Free$qpv
|
KolibriHeapFree = @@Kolibri@Free$qpv
|
||||||
|
|
||||||
KolibriHeapFreeAndThreadFinish = @Kolibri@_FreeAndThreadFinish$qpvpi
|
proc @MemoryHeap@mem_Init$qv uses ebx
|
||||||
|
mov eax,SF_SYS_MISC
|
||||||
|
mov ebx,SSF_HEAP_INIT
|
||||||
|
int 0x40
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
proc @Kolibri@_SetUseMemory$qui
|
proc @MemoryHeap@mem_Alloc$qul uses ebx
|
||||||
push ebx
|
mov eax,SF_SYS_MISC
|
||||||
mov eax,64
|
mov ebx,SSF_MEM_ALLOC
|
||||||
mov ebx,1
|
int 0x40
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
|
proc @MemoryHeap@mem_ReAlloc$qulpv uses ebx
|
||||||
|
mov eax,SF_SYS_MISC
|
||||||
|
mov ebx,SSF_MEM_REALLOC
|
||||||
|
mov ecx,[esp+8]
|
||||||
|
mov edx,[esp+12]
|
||||||
|
int 0x40
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
|
proc @MemoryHeap@mem_Free$qpv uses ebx
|
||||||
|
mov eax,SF_SYS_MISC
|
||||||
|
mov ebx,SSF_MEM_FREE
|
||||||
mov ecx,[esp+8]
|
mov ecx,[esp+8]
|
||||||
int 0x40
|
int 0x40
|
||||||
pop ebx
|
|
||||||
test eax,eax
|
|
||||||
jnz .set_use_memory_nomem
|
|
||||||
push ecx
|
|
||||||
push dword [@Kolibri@_KolibriMemBlock]
|
|
||||||
call @@MemoryHeap@ResizeBlock$q20MemoryHeap@TMemBlockpv
|
|
||||||
add esp,8
|
|
||||||
mov al,1
|
|
||||||
ret
|
|
||||||
.set_use_memory_nomem:
|
|
||||||
xor al,al
|
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
proc @Kolibri@_RecalculateUseMemory$qui
|
|
||||||
mov eax,dword [esp+4]
|
|
||||||
mov ecx,(U_END + 3) and not 3
|
|
||||||
cmp eax,ecx
|
|
||||||
jna .recalculate_use_memory_min
|
|
||||||
push ebx
|
|
||||||
sub eax,ecx
|
|
||||||
mov ebx,6
|
|
||||||
mul ebx
|
|
||||||
dec ebx
|
|
||||||
div ebx
|
|
||||||
add eax,((U_END + 3) and not 3) + 3
|
|
||||||
and eax,not 3
|
|
||||||
pop ebx
|
|
||||||
ret
|
|
||||||
.recalculate_use_memory_min:
|
|
||||||
mov eax,ecx
|
|
||||||
ret
|
|
||||||
endp
|
|
||||||
|
|
||||||
proc @Kolibri@_FreeAndThreadFinish$qpvpi
|
|
||||||
mov ebx,1
|
|
||||||
mov ecx,[esp+8]
|
|
||||||
jmp .heap_free_tf_wait
|
|
||||||
.heap_free_tf_wait_loop:
|
|
||||||
mov eax,5
|
|
||||||
int 0x40
|
|
||||||
shl ebx,1
|
|
||||||
cmp ebx,KOLIBRI_MUTEX_MAX_TIME_WAIT
|
|
||||||
jna .heap_free_tf_wait
|
|
||||||
mov ebx,KOLIBRI_MUTEX_MAX_TIME_WAIT
|
|
||||||
.heap_free_tf_wait:
|
|
||||||
cmp dword [ecx],0
|
|
||||||
jnz @Kolibri@ExitProcess$qv
|
|
||||||
lock bts dword [@Kolibri@_MemHeapMutex],0
|
|
||||||
jc .heap_free_tf_wait_loop
|
|
||||||
push dword [esp+4]
|
|
||||||
push @Kolibri@_KolibriFreeSpace
|
|
||||||
call @@MemoryHeap@Free$qr21MemoryHeap@TFreeSpacepv
|
|
||||||
add esp,8
|
|
||||||
mov byte [@Kolibri@_MemHeapMutex],0x40
|
|
||||||
or eax,-1
|
|
||||||
int 0x40
|
|
||||||
endp
|
|
||||||
|
|
||||||
macro call func
|
|
||||||
{
|
|
||||||
if func eq @MemoryHeap@_FirstNotZeroBit$qui
|
|
||||||
bsf eax,[esp]
|
|
||||||
else if func eq @MemoryHeap@_CopyMemItemArray$quiuiui
|
|
||||||
xchg edi,[esp]
|
|
||||||
xchg esi,[esp+4]
|
|
||||||
mov ecx,[esp+8]
|
|
||||||
cld
|
|
||||||
sub ecx,esi
|
|
||||||
shr ecx,2
|
|
||||||
rep movs dword [edi],[esi]
|
|
||||||
xchg edi,[esp]
|
|
||||||
xchg esi,[esp+4]
|
|
||||||
else
|
|
||||||
call func
|
|
||||||
end if
|
|
||||||
}
|
|
||||||
|
|
||||||
;/**/
|
;/**/
|
||||||
|
@ -8,7 +8,7 @@ org 0
|
|||||||
dd U_END+STACKSIZE
|
dd U_END+STACKSIZE
|
||||||
dd @Kolibri@CommandLine,0
|
dd @Kolibri@CommandLine,0
|
||||||
|
|
||||||
include "..\..\..\KOSfuncs.inc"
|
include "..\..\KOSfuncs.inc"
|
||||||
include "..\..\proc32.inc"
|
include "..\..\proc32.inc"
|
||||||
|
|
||||||
ptr equ
|
ptr equ
|
||||||
|
@ -1,626 +1,13 @@
|
|||||||
#ifndef __MEMORY_HEAP_RBTREE_H_INCLUDED_
|
#ifndef __MEMORY_HEAP_H_INCLUDED_
|
||||||
#define __MEMORY_HEAP_RBTREE_H_INCLUDED_
|
#define __MEMORY_HEAP_H_INCLUDED_
|
||||||
|
|
||||||
namespace MemoryHeap
|
namespace MemoryHeap
|
||||||
{
|
{
|
||||||
typedef unsigned int TMemItem;
|
long mem_Init();
|
||||||
|
void *mem_Alloc(unsigned long size);
|
||||||
enum {NumTreeSmall = 8 * sizeof(TMemItem)};
|
void *mem_ReAlloc(unsigned long size, void *mem);
|
||||||
|
bool mem_Free(void *mem);
|
||||||
// Memory heap interface.
|
|
||||||
|
|
||||||
struct TFreeSpace
|
|
||||||
{
|
|
||||||
TMemItem Small[NumTreeSmall], Min, SmallMask;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TMemBlock
|
|
||||||
{
|
|
||||||
TMemItem *Begin;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool BlockValid(const TMemBlock &block); // Is the given memory block valid?
|
|
||||||
void *BlockBegin(const TMemBlock &block); // Return the beginning address of the block.
|
|
||||||
void *BlockEnd(const TMemBlock &block); // Return the ending address of the block.
|
|
||||||
TFreeSpace &BlockFreeSpace(const TMemBlock &block); // Return the free space of the block.
|
|
||||||
|
|
||||||
void InitFreeSpace(TFreeSpace &fs); // Initialize the free space.
|
|
||||||
TMemBlock NullBlock(); // Return null invalid block.
|
|
||||||
TMemBlock CreateBlock(void *begin, void *end, TFreeSpace &fs);
|
|
||||||
// Create a memory block with the given begin and end and add free space of it to (fs),
|
|
||||||
//_ give (BlockAddSize) bytes of the block for it's data.
|
|
||||||
//_ (Program can alloc (end - begin - BlockAddSize) bytes after it,
|
|
||||||
//_ that must be not less than (MemMinSize) ).
|
|
||||||
TMemBlock CreateBlock(void *begin, void *end);
|
|
||||||
// Create a memory block with the given begin and end and new free space for it,
|
|
||||||
//_ give (BlockAddSizeFS) bytes of the block for it's data.
|
|
||||||
//_ (Program can alloc (end - begin - BlockAddSizeFS) bytes after it,
|
|
||||||
//_ that must be not less than (MemMinSize) ).
|
|
||||||
void ResizeBlock(TMemBlock block, void *new_end); // Resize the memory block to the given new end.
|
|
||||||
void RemoveBlock(TMemBlock block); // Remove the given memory block.
|
|
||||||
|
|
||||||
void *BlockEndFor(TMemBlock block, unsigned int size);
|
|
||||||
// Return the new end of the block needed for (ResizeBlock) to alloc the given size of memory.
|
|
||||||
unsigned int BlockSize(TMemBlock block); // Return the size of the given block.
|
|
||||||
unsigned int MemSize(void *mem); // Return the size of the allocced memory.
|
|
||||||
|
|
||||||
void *Alloc(TFreeSpace &fs, unsigned int size);
|
|
||||||
// Alloc a memory in the given free space, give (MemAddSize) bytes for it's data.
|
|
||||||
void *ReAlloc(TFreeSpace &fs, unsigned int size, void *mem);
|
|
||||||
// ReAlloc the given memory, it must lie in the block with the given free space.
|
|
||||||
void Free(TFreeSpace &fs, void *mem);
|
|
||||||
// Free the given memory, it must lie in the block with the given free space.
|
|
||||||
|
|
||||||
// Macro definitions.
|
|
||||||
|
|
||||||
#define MEMORY_HEAP_ALIGN_DOWN(s) (MemoryHeap::TMemItem(s) & ~(MemoryHeap::MemAlign - 1))
|
|
||||||
#define MEMORY_HEAP_ALIGN_UP(s) ((MemoryHeap::TMemItem(s) + (MemoryHeap::MemAlign - 1)) & ~(MemoryHeap::MemAlign - 1))
|
|
||||||
#define MEMORY_HEAP_ITEM(s,k) ( ((MemoryHeap::TMemItem*)(s))[(k)] )
|
|
||||||
#define MEMORY_HEAP_NEXT(s) (MEMORY_HEAP_ITEM((s),-1))
|
|
||||||
#define MEMORY_HEAP_PREV(s) (MEMORY_HEAP_ITEM((s),-2))
|
|
||||||
#define MEMORY_HEAP_FREE(s) (MEMORY_HEAP_ITEM((s),-1) & 1)
|
|
||||||
|
|
||||||
// Constants.
|
|
||||||
|
|
||||||
enum {MemAlign = sizeof(TMemItem)};
|
|
||||||
enum {MemAddSize = MEMORY_HEAP_ALIGN_UP(2 * sizeof(TMemItem))};
|
|
||||||
enum {BlockEndSize = MemAddSize};
|
|
||||||
enum {BlockAddSize = MEMORY_HEAP_ALIGN_UP(4 * sizeof(TMemItem)) + BlockEndSize};
|
|
||||||
enum {BlockAddSizeFS = BlockAddSize + BlockEndSize + MEMORY_HEAP_ALIGN_UP(sizeof(TFreeSpace))};
|
|
||||||
enum {MemMinSize = MEMORY_HEAP_ALIGN_UP(2 * sizeof(TMemItem))};
|
|
||||||
|
|
||||||
// Inline functions.
|
|
||||||
|
|
||||||
inline bool BlockValid(const TMemBlock &block) {return block.Begin != 0;}
|
|
||||||
|
|
||||||
inline void *BlockBegin(const TMemBlock &block) {return (void*)block.Begin;}
|
|
||||||
|
|
||||||
inline void *BlockEnd(const TMemBlock &block) {return block.Begin ? (void*)block.Begin[1] : 0;}
|
|
||||||
|
|
||||||
inline TFreeSpace &BlockFreeSpace(const TMemBlock &block) {return *(TFreeSpace*)block.Begin[0];}
|
|
||||||
|
|
||||||
inline TMemBlock NullBlock() {TMemBlock block; block.Begin = 0; return block;}
|
|
||||||
|
|
||||||
inline void *BlockEndFor(TMemBlock block, unsigned int size)
|
|
||||||
{
|
|
||||||
TMemItem last = (TMemItem)block.Begin[1];
|
|
||||||
TMemItem prevlast = MEMORY_HEAP_PREV(last);
|
|
||||||
return (void*)( (MEMORY_HEAP_FREE(prevlast) ? prevlast : last) + MemAddSize +
|
|
||||||
((size <= MemMinSize) ? MemMinSize : MEMORY_HEAP_ALIGN_UP(size)) );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned int BlockSize(TMemBlock block)
|
|
||||||
{
|
|
||||||
if (!block.Begin) return 0;
|
|
||||||
return (unsigned int)(block.Begin[1] - (TMemItem)block.Begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned int MemSize(void *mem)
|
|
||||||
{
|
|
||||||
if (!mem) return 0;
|
|
||||||
TMemItem c = (TMemItem)mem;
|
|
||||||
return MEMORY_HEAP_NEXT(c) - c - MemAddSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free space item functions.
|
|
||||||
|
|
||||||
TMemItem _FirstNotZeroBit(TMemItem i)
|
|
||||||
{
|
|
||||||
TMemItem r = 0;
|
|
||||||
while ((i >>= 1) != 0) r++;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _RBTreeRotate(TMemItem parent, TMemItem item, int side)
|
|
||||||
{
|
|
||||||
TMemItem temp = MEMORY_HEAP_ITEM(parent,0);
|
|
||||||
MEMORY_HEAP_ITEM(item,0) = temp;
|
|
||||||
if (temp)
|
|
||||||
{
|
|
||||||
if (MEMORY_HEAP_ITEM(temp,2) == parent)
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_ITEM(temp,2) = item;
|
|
||||||
}
|
|
||||||
else MEMORY_HEAP_ITEM(temp,3) = item;
|
|
||||||
}
|
|
||||||
temp = MEMORY_HEAP_ITEM(item,side^1);
|
|
||||||
if (temp) MEMORY_HEAP_ITEM(temp,0) = parent;
|
|
||||||
MEMORY_HEAP_ITEM(parent,side) = temp;
|
|
||||||
MEMORY_HEAP_ITEM(parent,0) = item;
|
|
||||||
MEMORY_HEAP_ITEM(item,side^1) = parent;
|
|
||||||
temp = MEMORY_HEAP_ITEM(parent,1);
|
|
||||||
MEMORY_HEAP_ITEM(parent,1) = MEMORY_HEAP_ITEM(item,1);
|
|
||||||
MEMORY_HEAP_ITEM(item,1) = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitFreeSpace(TFreeSpace &fs)
|
|
||||||
{
|
|
||||||
TMemItem i;
|
|
||||||
for (i = 0; i <= NumTreeSmall; i++) fs.Small[i] = 0;
|
|
||||||
fs.Min = 0; fs.SmallMask = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _FreeAdd(TFreeSpace &fs, TMemItem item)
|
|
||||||
{
|
|
||||||
TMemItem size = MEMORY_HEAP_NEXT(item) - item;
|
|
||||||
if (size < MemAddSize + MemMinSize + MemAlign * NumTreeSmall)
|
|
||||||
{
|
|
||||||
TMemItem s = (size - (MemAddSize + MemMinSize)) / MemAlign;
|
|
||||||
TMemItem &addto = fs.Small[s];
|
|
||||||
MEMORY_HEAP_ITEM(item,1) = (TMemItem)(&addto);
|
|
||||||
MEMORY_HEAP_ITEM(item,0) = (TMemItem)addto;
|
|
||||||
if (addto) MEMORY_HEAP_ITEM(addto,1) = item;
|
|
||||||
addto = item;
|
|
||||||
fs.SmallMask |= TMemItem(1) << s;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TMemItem addto = fs.Min, parent, temp;
|
|
||||||
MEMORY_HEAP_ITEM(item,2) = 0;
|
|
||||||
MEMORY_HEAP_ITEM(item,3) = 0;
|
|
||||||
if (!addto)
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_ITEM(item,0) = 0;
|
|
||||||
MEMORY_HEAP_ITEM(item,1) = 1;
|
|
||||||
fs.Min = item;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MEMORY_HEAP_ITEM(item,1) = 0;
|
|
||||||
TMemItem side = 2;
|
|
||||||
if (MEMORY_HEAP_NEXT(addto) - addto >= size) fs.Min = item;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
parent = MEMORY_HEAP_ITEM(addto,0);
|
|
||||||
if (!parent) break;
|
|
||||||
if (MEMORY_HEAP_NEXT(parent) - parent < size) addto = parent;
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (MEMORY_HEAP_NEXT(addto) - addto < size)
|
|
||||||
{
|
|
||||||
temp = MEMORY_HEAP_ITEM(addto,3);
|
|
||||||
if (!temp) {side = 3; break;}
|
|
||||||
addto = temp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
temp = MEMORY_HEAP_ITEM(addto,2);
|
|
||||||
if (!temp) break;
|
|
||||||
addto = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MEMORY_HEAP_ITEM(item,0) = addto;
|
|
||||||
MEMORY_HEAP_ITEM(addto,side) = item;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (MEMORY_HEAP_ITEM(addto,1) != 0) return;
|
|
||||||
parent = MEMORY_HEAP_ITEM(addto,0);
|
|
||||||
temp = MEMORY_HEAP_ITEM(parent,2);
|
|
||||||
if (temp == addto)
|
|
||||||
{
|
|
||||||
temp = MEMORY_HEAP_ITEM(parent,3);
|
|
||||||
side = 2;
|
|
||||||
}
|
|
||||||
else side = 3;
|
|
||||||
if (!temp || MEMORY_HEAP_ITEM(temp,1) != 0) break;
|
|
||||||
MEMORY_HEAP_ITEM(addto,1) = 1;
|
|
||||||
MEMORY_HEAP_ITEM(temp,1) = 1;
|
|
||||||
item = parent;
|
|
||||||
addto = MEMORY_HEAP_ITEM(item,0);
|
|
||||||
if (!addto) return;
|
|
||||||
MEMORY_HEAP_ITEM(item,1) = 0;
|
|
||||||
}
|
|
||||||
if (MEMORY_HEAP_ITEM(addto,side) != item)
|
|
||||||
{
|
|
||||||
temp = MEMORY_HEAP_ITEM(item,side);
|
|
||||||
if (temp) MEMORY_HEAP_ITEM(temp,0) = addto;
|
|
||||||
MEMORY_HEAP_ITEM(addto,side^1) = temp;
|
|
||||||
MEMORY_HEAP_ITEM(addto,0) = item;
|
|
||||||
MEMORY_HEAP_ITEM(item,side) = addto;
|
|
||||||
MEMORY_HEAP_ITEM(item,0) = parent;
|
|
||||||
MEMORY_HEAP_ITEM(parent,side) = item;
|
|
||||||
}
|
|
||||||
else item = addto;
|
|
||||||
_RBTreeRotate(parent, item, side);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _FreeDel(TFreeSpace &fs, TMemItem item)
|
|
||||||
{
|
|
||||||
TMemItem size = MEMORY_HEAP_NEXT(item) - item;
|
|
||||||
if (size < MemAddSize + MemMinSize + MemAlign * NumTreeSmall)
|
|
||||||
{
|
|
||||||
TMemItem prev = MEMORY_HEAP_ITEM(item,1);
|
|
||||||
TMemItem next = MEMORY_HEAP_ITEM(item,0);
|
|
||||||
MEMORY_HEAP_ITEM(prev,0) = next;
|
|
||||||
if (next) MEMORY_HEAP_ITEM(next,1) = prev;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TMemItem s = (size - (MemAddSize + MemMinSize)) / MemAlign;
|
|
||||||
if (!fs.Small[s]) fs.SmallMask &= ~(TMemItem(1) << s);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TMemItem parent, temp, second, add;
|
|
||||||
TMemItem side = 2;
|
|
||||||
temp = MEMORY_HEAP_ITEM(item,3);
|
|
||||||
if (temp)
|
|
||||||
{
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
second = temp;
|
|
||||||
temp = MEMORY_HEAP_ITEM(temp,2);
|
|
||||||
if (!temp) break;
|
|
||||||
}
|
|
||||||
if (fs.Min == item) fs.Min = second;
|
|
||||||
add = MEMORY_HEAP_ITEM(second,3);
|
|
||||||
parent = MEMORY_HEAP_ITEM(second,0);
|
|
||||||
if (parent == item) {parent = second; side = 3;}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
temp = MEMORY_HEAP_ITEM(item,3);
|
|
||||||
MEMORY_HEAP_ITEM(second,3) = temp;
|
|
||||||
MEMORY_HEAP_ITEM(temp,0) = second;
|
|
||||||
}
|
|
||||||
temp = MEMORY_HEAP_ITEM(item,2);
|
|
||||||
MEMORY_HEAP_ITEM(second,2) = temp;
|
|
||||||
if (temp) MEMORY_HEAP_ITEM(temp,0) = second;
|
|
||||||
temp = MEMORY_HEAP_ITEM(item,0);
|
|
||||||
MEMORY_HEAP_ITEM(second,0) = temp;
|
|
||||||
if (temp)
|
|
||||||
{
|
|
||||||
if (MEMORY_HEAP_ITEM(temp,2) == item)
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_ITEM(temp,2) = second;
|
|
||||||
}
|
|
||||||
else MEMORY_HEAP_ITEM(temp,3) = second;
|
|
||||||
}
|
|
||||||
MEMORY_HEAP_ITEM(parent,side) = add;
|
|
||||||
if (add) MEMORY_HEAP_ITEM(add,0) = parent;
|
|
||||||
bool color = MEMORY_HEAP_ITEM(second,1);
|
|
||||||
MEMORY_HEAP_ITEM(second,1) = MEMORY_HEAP_ITEM(item,1);
|
|
||||||
if (!color) return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (fs.Min == item) fs.Min = MEMORY_HEAP_ITEM(item,0);
|
|
||||||
add = MEMORY_HEAP_ITEM(item,2);
|
|
||||||
parent = MEMORY_HEAP_ITEM(item,0);
|
|
||||||
if (add) MEMORY_HEAP_ITEM(add,0) = parent;
|
|
||||||
if (parent)
|
|
||||||
{
|
|
||||||
if (MEMORY_HEAP_ITEM(parent,2) == item)
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_ITEM(parent,2) = add;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_ITEM(parent,3) = add;
|
|
||||||
side = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (add) MEMORY_HEAP_ITEM(add,1) = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!MEMORY_HEAP_ITEM(item,1)) return;
|
|
||||||
}
|
|
||||||
if (add && !MEMORY_HEAP_ITEM(add,1))
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_ITEM(add,1) = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
second = MEMORY_HEAP_ITEM(parent,side^1);
|
|
||||||
if (!MEMORY_HEAP_ITEM(second,1))
|
|
||||||
{
|
|
||||||
_RBTreeRotate(parent, second, side^1);
|
|
||||||
second = MEMORY_HEAP_ITEM(parent,side^1);
|
|
||||||
}
|
|
||||||
temp = MEMORY_HEAP_ITEM(second,side^1);
|
|
||||||
if (temp && !MEMORY_HEAP_ITEM(temp,1))
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_ITEM(temp,1) = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
temp = MEMORY_HEAP_ITEM(second,side);
|
|
||||||
if (temp && !MEMORY_HEAP_ITEM(temp,1))
|
|
||||||
{
|
|
||||||
_RBTreeRotate(second, temp, side);
|
|
||||||
MEMORY_HEAP_ITEM(second,1) = 1;
|
|
||||||
second = temp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
MEMORY_HEAP_ITEM(second,1) = 0;
|
|
||||||
if (!MEMORY_HEAP_ITEM(parent,1))
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_ITEM(parent,1) = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
second = parent;
|
|
||||||
parent = MEMORY_HEAP_ITEM(second,0);
|
|
||||||
if (!parent) return;
|
|
||||||
if (MEMORY_HEAP_ITEM(parent,2) == second) side = 2;
|
|
||||||
else side = 3;
|
|
||||||
}
|
|
||||||
_RBTreeRotate(parent, second, side^1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TMemItem _FreeFindAfter(TMemItem item, TMemItem size)
|
|
||||||
{
|
|
||||||
if (!item) return 0;
|
|
||||||
TMemItem paritem, s;
|
|
||||||
if (MEMORY_HEAP_NEXT(item) - item >= size) return item;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
paritem = MEMORY_HEAP_ITEM(item,0);
|
|
||||||
if (!paritem) break;
|
|
||||||
s = MEMORY_HEAP_NEXT(paritem) - paritem;
|
|
||||||
if (s == size) return paritem;
|
|
||||||
if (s < size) item = paritem;
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
MEMORY_HEAP_ITEM(item,3);
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (!item) return paritem;
|
|
||||||
s = MEMORY_HEAP_NEXT(item) - item;
|
|
||||||
if (s == size) return item;
|
|
||||||
if (s < size) item = MEMORY_HEAP_ITEM(item,3);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
paritem = item;
|
|
||||||
item = MEMORY_HEAP_ITEM(item,2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TMemItem _FreeFind(TFreeSpace &fs, TMemItem size)
|
|
||||||
{
|
|
||||||
TMemItem item, nextitem, s;
|
|
||||||
if (size < MemAddSize + MemMinSize + MemAlign * NumTreeSmall)
|
|
||||||
{
|
|
||||||
TMemItem m, t;
|
|
||||||
s = (size - (MemAddSize + MemMinSize)) / MemAlign;
|
|
||||||
item = fs.Small[s];
|
|
||||||
if (item) return item;
|
|
||||||
if (size < MemAlign * NumTreeSmall)
|
|
||||||
{
|
|
||||||
t = size / MemAlign;
|
|
||||||
m = fs.SmallMask >> t;
|
|
||||||
if (m) return fs.Small[t + _FirstNotZeroBit(m)];
|
|
||||||
else if (fs.Min) return fs.Min;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item = _FreeFindAfter(fs.Min, size + 1 + MemAddSize + MemMinSize);
|
|
||||||
if (item) return item;
|
|
||||||
}
|
|
||||||
m = fs.SmallMask >> s;
|
|
||||||
if (m) return fs.Small[s + _FirstNotZeroBit(m)];
|
|
||||||
else return fs.Min;
|
|
||||||
}
|
|
||||||
item = _FreeFindAfter(fs.Min, ++size);
|
|
||||||
if (!item) return 0;
|
|
||||||
s = MEMORY_HEAP_NEXT(item) - item;
|
|
||||||
if (s == size) return item;
|
|
||||||
size += MemAddSize + MemMinSize;
|
|
||||||
if (s >= size) return item;
|
|
||||||
nextitem = _FreeFindAfter(item, size);
|
|
||||||
return nextitem ? nextitem : item;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block functions.
|
|
||||||
|
|
||||||
inline void _CreateBlockEnd(TMemBlock &block, TFreeSpace &fs, TMemItem c, TMemItem e)
|
|
||||||
{
|
|
||||||
block.Begin[0] = (TMemItem)(&fs);
|
|
||||||
if (e - c < TMemItem(MemAddSize + MemMinSize))
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_NEXT(c) = 0;
|
|
||||||
block.Begin[1] = c;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_NEXT(c) = e + 1;
|
|
||||||
_FreeAdd(fs, c);
|
|
||||||
MEMORY_HEAP_PREV(e) = c;
|
|
||||||
MEMORY_HEAP_NEXT(e) = 0;
|
|
||||||
block.Begin[1] = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TMemBlock CreateBlock(void *begin, void *end, TFreeSpace &fs)
|
|
||||||
{
|
|
||||||
TMemBlock block = {0};
|
|
||||||
TMemItem b = MEMORY_HEAP_ALIGN_UP(begin);
|
|
||||||
TMemItem e = MEMORY_HEAP_ALIGN_DOWN(end);
|
|
||||||
if (e <= b || e - b < TMemItem(BlockAddSize - MemAddSize)) return block;
|
|
||||||
block.Begin = (TMemItem*)b;
|
|
||||||
b += MEMORY_HEAP_ALIGN_UP(4 * sizeof(TMemItem));
|
|
||||||
MEMORY_HEAP_PREV(b) = 0;
|
|
||||||
_CreateBlockEnd(block, fs, b, e);
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
TMemBlock CreateBlock(void *begin, void *end)
|
|
||||||
{
|
|
||||||
TMemBlock block = {0};
|
|
||||||
TMemItem b = MEMORY_HEAP_ALIGN_UP(begin);
|
|
||||||
TMemItem e = MEMORY_HEAP_ALIGN_DOWN(end);
|
|
||||||
if (e <= b || e - b < TMemItem(BlockAddSizeFS - MemAddSize)) return block;
|
|
||||||
block.Begin = (TMemItem*)b;
|
|
||||||
b += MEMORY_HEAP_ALIGN_UP(4 * sizeof(TMemItem));
|
|
||||||
TMemItem c = b + MemAddSize + MEMORY_HEAP_ALIGN_UP(sizeof(TFreeSpace));
|
|
||||||
MEMORY_HEAP_PREV(b) = 0;
|
|
||||||
MEMORY_HEAP_NEXT(b) = c;
|
|
||||||
MEMORY_HEAP_PREV(c) = b;
|
|
||||||
InitFreeSpace(*(TFreeSpace*)b);
|
|
||||||
_CreateBlockEnd(block, *(TFreeSpace*)b, c, e);
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResizeBlock(TMemBlock block, void *new_end)
|
|
||||||
{
|
|
||||||
if (!BlockValid(block)) return;
|
|
||||||
TMemItem e = MEMORY_HEAP_ALIGN_DOWN(new_end);
|
|
||||||
TMemItem c = block.Begin[1];
|
|
||||||
TFreeSpace &fs = *(TFreeSpace*)block.Begin[0];
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (c == e) return;
|
|
||||||
else if (c > e)
|
|
||||||
{
|
|
||||||
while ((c = MEMORY_HEAP_PREV(c)) > e)
|
|
||||||
{
|
|
||||||
if (MEMORY_HEAP_FREE(c)) _FreeDel(fs, c);
|
|
||||||
}
|
|
||||||
if (!c) {block.Begin = 0; return;}
|
|
||||||
if (MEMORY_HEAP_FREE(c))
|
|
||||||
{
|
|
||||||
_FreeDel(fs, c);
|
|
||||||
if (e - c < TMemItem(MemAddSize + MemMinSize)) e = c;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_NEXT(c) = e + 1;
|
|
||||||
_FreeAdd(*(TFreeSpace*)block.Begin[0], c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (e - c >= TMemItem(MemAddSize + MemMinSize))
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_NEXT(c) = e; break;
|
|
||||||
}
|
|
||||||
MEMORY_HEAP_NEXT(c) = 0;
|
|
||||||
block.Begin[1] = c;
|
|
||||||
if (c == e) return;
|
|
||||||
}
|
|
||||||
TMemItem pc = MEMORY_HEAP_PREV(c);
|
|
||||||
if (pc && MEMORY_HEAP_FREE(pc)) _FreeDel(fs, c = pc);
|
|
||||||
else if (e - c < TMemItem(MemAddSize + MemMinSize)) return;
|
|
||||||
MEMORY_HEAP_NEXT(c) = e + 1;
|
|
||||||
_FreeAdd(fs, c);
|
|
||||||
} while(false);
|
|
||||||
MEMORY_HEAP_PREV(e) = c;
|
|
||||||
MEMORY_HEAP_NEXT(e) = 0;
|
|
||||||
block.Begin[1] = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveBlock(TMemBlock block)
|
|
||||||
{
|
|
||||||
if (!BlockValid(block)) return;
|
|
||||||
TMemItem e = block.Begin[1];
|
|
||||||
TFreeSpace &fs = *(TFreeSpace*)block.Begin[0];
|
|
||||||
while ((e = MEMORY_HEAP_PREV(e)) != 0)
|
|
||||||
{
|
|
||||||
if (MEMORY_HEAP_FREE(e)) _FreeDel(fs, e);
|
|
||||||
}
|
|
||||||
block.Begin = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free space functions.
|
|
||||||
|
|
||||||
void _CopyMemItemArray(TMemItem dest, TMemItem src, TMemItem end)
|
|
||||||
{
|
|
||||||
TMemItem k = (end - src) / sizeof(TMemItem);
|
|
||||||
TMemItem *d = (TMemItem*)dest;
|
|
||||||
TMemItem *s = (TMemItem*)src;
|
|
||||||
while (k--) *(d++) = *(s++);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *Alloc(TFreeSpace &fs, unsigned int size)
|
|
||||||
{
|
|
||||||
if (!size) return 0;
|
|
||||||
TMemItem s = MEMORY_HEAP_ALIGN_UP(size) + MemAddSize;
|
|
||||||
if (s < MemAddSize + MemMinSize) s = MemAddSize + MemMinSize;
|
|
||||||
TMemItem c = _FreeFind(fs, s);
|
|
||||||
if (!c) return 0;
|
|
||||||
_FreeDel(fs, c);
|
|
||||||
TMemItem nc = --MEMORY_HEAP_NEXT(c);
|
|
||||||
TMemItem mc = c + s;
|
|
||||||
if (nc - (MemAddSize + MemMinSize) >= mc)
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_NEXT(c) = mc;
|
|
||||||
MEMORY_HEAP_PREV(mc) = c;
|
|
||||||
MEMORY_HEAP_NEXT(mc) = nc + 1;
|
|
||||||
MEMORY_HEAP_PREV(nc) = mc;
|
|
||||||
_FreeAdd(fs, mc);
|
|
||||||
}
|
|
||||||
return (void*)c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ReAlloc(TFreeSpace &fs, void *mem, unsigned int size)
|
|
||||||
{
|
|
||||||
if (!mem) return Alloc(fs, size);
|
|
||||||
if (!size) {Free(fs, mem); return 0;}
|
|
||||||
TMemItem s = MEMORY_HEAP_ALIGN_UP(size) + MemAddSize;
|
|
||||||
TMemItem c = (TMemItem)mem;
|
|
||||||
TMemItem mc = MEMORY_HEAP_NEXT(c);
|
|
||||||
TMemItem nc = MEMORY_HEAP_NEXT(mc);
|
|
||||||
if (--nc & 1) nc = mc;
|
|
||||||
if (s < MemAddSize + MemMinSize) s = MemAddSize + MemMinSize;
|
|
||||||
if (nc - c < s)
|
|
||||||
{
|
|
||||||
mem = Alloc(fs, size);
|
|
||||||
if (mem)
|
|
||||||
{
|
|
||||||
_CopyMemItemArray((TMemItem)mem, c, mc - MemAddSize);
|
|
||||||
Free(fs, (void*)c);
|
|
||||||
return mem;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TMemItem pc = MEMORY_HEAP_PREV(c);
|
|
||||||
if (pc && MEMORY_HEAP_FREE(pc) && nc - pc >= s)
|
|
||||||
{
|
|
||||||
_FreeDel(fs, pc);
|
|
||||||
_CopyMemItemArray(pc, c, mc - MemAddSize);
|
|
||||||
c = pc;
|
|
||||||
}
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mc < nc) _FreeDel(fs, mc);
|
|
||||||
mc = c + s;
|
|
||||||
if (nc - (MemAddSize + MemMinSize) >= mc)
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_NEXT(c) = mc;
|
|
||||||
MEMORY_HEAP_PREV(mc) = c;
|
|
||||||
MEMORY_HEAP_NEXT(mc) = nc + 1;
|
|
||||||
MEMORY_HEAP_PREV(nc) = mc;
|
|
||||||
_FreeAdd(fs, mc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MEMORY_HEAP_NEXT(c) = nc;
|
|
||||||
MEMORY_HEAP_PREV(nc) = c;
|
|
||||||
}
|
|
||||||
return (void*)c;
|
|
||||||
}
|
|
||||||
|
|
||||||
int free_a = 0;
|
|
||||||
|
|
||||||
void Free(TFreeSpace &fs, void *mem)
|
|
||||||
{
|
|
||||||
TMemItem c = (TMemItem)mem;
|
|
||||||
if (!c) return;
|
|
||||||
TMemItem pc = MEMORY_HEAP_PREV(c);
|
|
||||||
TMemItem mc = MEMORY_HEAP_NEXT(c);
|
|
||||||
TMemItem nc = MEMORY_HEAP_NEXT(mc);
|
|
||||||
if (--nc & 1) nc = mc;
|
|
||||||
else _FreeDel(fs, mc);
|
|
||||||
if (free_a == 1) return;
|
|
||||||
if (pc && MEMORY_HEAP_FREE(pc)) _FreeDel(fs, c = pc);
|
|
||||||
MEMORY_HEAP_NEXT(c) = nc + 1;
|
|
||||||
MEMORY_HEAP_PREV(nc) = c;
|
|
||||||
if (free_a == 2) return;
|
|
||||||
_FreeAdd(fs, c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ndef __MEMORY_HEAP_RBTREE_H_INCLUDED_
|
#endif // ndef __MEMORY_HEAP_H_INCLUDED_
|
||||||
|
|
||||||
|
@ -1362,7 +1362,7 @@ void MenuOpenDialogEnd(TThreadData th)
|
|||||||
if (state != 2) return;
|
if (state != 2) return;
|
||||||
char *name = OpenFileGetName(open_file_str);
|
char *name = OpenFileGetName(open_file_str);
|
||||||
if (!name) return;
|
if (!name) return;
|
||||||
TFileData file = FileOpen(name);
|
FileInfoBlock* file = FileOpen(name);
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
int k = FileGetLength(file);
|
int k = FileGetLength(file);
|
||||||
unsigned char *pict = 0;
|
unsigned char *pict = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user