forked from KolibriOS/kolibrios
add 'Hello World' example
git-svn-id: svn://kolibrios.org@8140 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
dd55ceaa16
commit
cd50f4af3c
34
programs/bcc32/examples/hello.cpp
Normal file
34
programs/bcc32/examples/hello.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "../include/kolibri.h"
|
||||
#include "../include/kos_heap.h"
|
||||
#include "../include/kos_file.h"
|
||||
|
||||
using namespace Kolibri;
|
||||
|
||||
const char header[] = "Hello World test";
|
||||
const char string[] = "Hello, World!";
|
||||
|
||||
bool KolibriOnStart(TStartData &me_start, TThreadData /*th*/)
|
||||
{
|
||||
me_start.Left = 10;
|
||||
me_start.Top = 40;
|
||||
me_start.Width = 150;
|
||||
me_start.Height = 80;
|
||||
me_start.WinData.Title = header;
|
||||
return true;
|
||||
}
|
||||
|
||||
void KolibriOnPaint(void)
|
||||
{
|
||||
DrawText(30,10,0,string);
|
||||
}
|
||||
|
||||
bool KolibriOnClose(TThreadData /*th*/)
|
||||
{return true;}
|
||||
int KolibriOnIdle(TThreadData /*th*/)
|
||||
{return -1;}
|
||||
void KolibriOnSize(int /*window_rect*/[], TThreadData /*th*/)
|
||||
{}
|
||||
void KolibriOnKeyPress(TThreadData /*th*/)
|
||||
{GetKey();}
|
||||
void KolibriOnMouse(TThreadData /*th*/)
|
||||
{}
|
6
programs/bcc32/examples/hello_cpp.bat
Normal file
6
programs/bcc32/examples/hello_cpp.bat
Normal file
@ -0,0 +1,6 @@
|
||||
kos32-bcc -S -v- -R- -6 -a4 -O2 -Og -Oi -Ov -OS -k- -D__KOLIBRI__ -Iinclude hello.cpp
|
||||
echo include "kos_make.inc" > f_hello.asm
|
||||
t2fasm < hello.asm >> f_hello.asm
|
||||
fasm f_hello.asm hello.kex
|
||||
kpack hello.kex
|
||||
pause
|
7
programs/bcc32/examples/kos_make.inc
Normal file
7
programs/bcc32/examples/kos_make.inc
Normal file
@ -0,0 +1,7 @@
|
||||
STACKSIZE equ 102400
|
||||
HEAPSIZE equ 102400
|
||||
|
||||
include "..\..\proc32.inc"
|
||||
include "..\include\kos_start.inc"
|
||||
include "..\include\kos_func.inc"
|
||||
include "..\include\kos_heap.inc"
|
538
programs/bcc32/include/kolibri.h
Normal file
538
programs/bcc32/include/kolibri.h
Normal file
@ -0,0 +1,538 @@
|
||||
#ifndef __KOLIBRI_H_INCLUDED_
|
||||
#define __KOLIBRI_H_INCLUDED_
|
||||
|
||||
#include "kos_lib.h"
|
||||
|
||||
// Kolibri interface.
|
||||
|
||||
namespace Kolibri // All kolibri functions, types and data are nested in the (Kolibri) namespace.
|
||||
{
|
||||
const char *DebugPrefix = "User program: ";
|
||||
char CommandLine[257];
|
||||
|
||||
struct TWindowData // Data for drawing a window.
|
||||
{
|
||||
unsigned short WindowType, HeaderType;
|
||||
unsigned long WindowColor, HeaderColor, BorderColor, TitleColor;
|
||||
const char *Title;
|
||||
};
|
||||
|
||||
struct TStartData // This structure is used only for KolibriOnStart function.
|
||||
{
|
||||
unsigned short Left, Width, Top, Height; // Initial window rectangle.
|
||||
TWindowData WinData;
|
||||
};
|
||||
|
||||
typedef void **TThreadData; // Thread data are the fast identifier of thread, contains user dword in
|
||||
//_ the zero element and stack beginning (or zero if it is unknown) in the first element.
|
||||
//_ The stack will be deleted from dynamic memory at the finish of the thread if stack beginning is not zero.
|
||||
|
||||
struct TMutex; // Simple mutex can be locked only once at a time.
|
||||
#define KOLIBRI_MUTEX_INIT {} // Simple mutex initializer, cat be redefined in a realization of the library
|
||||
|
||||
struct TRecMutex; // Recursive mutex can be locked many times by a single thread at a time.
|
||||
#define KOLIBRI_REC_MUTEX_INIT {} // Recursive mutex initializer, cat be redefined in a realization of the library
|
||||
|
||||
// Some functions have two forms: the fast form with (thread_data) parameter and the form without it.
|
||||
// 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* ThreadMain(void *user = 0, void *stack_begin = 0);
|
||||
// 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.
|
||||
//_ Return new value of stack beginning that can be changed in the thread data.
|
||||
void GetWindowData(TWindowData &win_data); // Write current window data to (win_data).
|
||||
void GetWindowData(TWindowData &win_data, TThreadData thread_data);
|
||||
void SetWindowData(const TWindowData &win_data); // Replace current window data by (win_data).
|
||||
void SetWindowData(const TWindowData &win_data, TThreadData thread_data);
|
||||
void CloseWindow(); // Close current window when returning to message loop.
|
||||
void CloseWindow(TThreadData thread_data);
|
||||
void Redraw(int frame = 0); // Redraw current window immediately, if (frame) is positive redraw the frame too,
|
||||
void Redraw(int frame, TThreadData thread_data); //_ if (frame) is negative redraw only invalideted window.
|
||||
void Invalidate(int frame = 0); // Redraw current window when no message will be is the queue,
|
||||
void Invalidate(int frame, TThreadData thread_data); //_ if (frame) is positive redraw the frame too,
|
||||
//_ if (frame) is negative do nothing.
|
||||
void MoveWindow(const int window_rect[/* 4 */]); // Move and resize current window.
|
||||
|
||||
void Abort(); // Abnormally terminate a program.
|
||||
void ExitProcess(); // Exit from the process, don't call any destructors of global varyables
|
||||
void ExitThread(); // Exit from the current thread
|
||||
void ExitThread(TThreadData thread_data);
|
||||
void ReturnMessageLoop(); // Return to the message loop of the thread. Exit from the thread
|
||||
void ReturnMessageLoop(TThreadData thread_data); //_ if it is called from (KolibriOnStart).
|
||||
|
||||
void Delay(unsigned int time); // Delay the execution of the program during (time) hundredth seconds.
|
||||
unsigned int Clock(); // Return the time from starting of the system to this moment in hundredth of seconds.
|
||||
int GetPackedTime(); // Return the current time of day in binary-decimal format 0x00SSMMHH.
|
||||
void GetTime(int t[/* 3 */]); // Write the current time to (t): t[0] = second, t[1] = minute, t[2] = hour.
|
||||
int GetPackedDate(); // Return the current date in binary-decimal format 0x00YYDDMM.
|
||||
void GetDate(int d[/* 3 */]); // Write the current date to (d): d[0] = day, d[1] = month, d[2] = year.
|
||||
void GetTimeDate(int t[/* 6 */]); // Write the current time and date to (t): t[0] = second,
|
||||
//_ t[1] = minute, t[2] = hour, t[3] = day, t[4] = month, t[5] = year.
|
||||
void ReadCommonColors(unsigned int colors[/* 10 */]); // Writes standart window colors to (colors).
|
||||
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 = -1);
|
||||
// Write (pid_for) process information to variables parameters points, return
|
||||
//_ the number of processes. (pid_for) equal to (-1) means current process.
|
||||
unsigned int GetPid(); // Return the current thread identifier (pid).
|
||||
unsigned int GetPid(TThreadData thread_data);
|
||||
TThreadData GetThreadData(); // Return the thread data of the current thread.
|
||||
TThreadData GetThreadData(unsigned int pid); // Return the thread data of the thread with the given pid.
|
||||
|
||||
void* GetPicture(unsigned short &width, unsigned short &height);
|
||||
void* GetPicture(unsigned short &width, unsigned short &height, TThreadData thread_data);
|
||||
// Return the picture on the window and write its width and height to (width) and (height).
|
||||
void SetPicture(void *picture, unsigned short width, unsigned short height);
|
||||
void SetPicture(void *picture, unsigned short width, unsigned short height, TThreadData thread_data);
|
||||
// Replace the picture on the window by the given picture with the given width and height.
|
||||
void GetBorderHeader(unsigned short &border_size, unsigned short &header_size);
|
||||
void GetBorderHeader(unsigned short &border_size, unsigned short &header_size, TThreadData thread_data);
|
||||
// Write the border thickness to (border_size) and header height to (header_size).
|
||||
void GetClientSize(unsigned short &width, unsigned short &height);
|
||||
void GetClientSize(unsigned short &width, unsigned short &height, TThreadData thread_data);
|
||||
// Write the client area width and height to (width) and (height) parameters.
|
||||
void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height);
|
||||
void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height, TThreadData thread_data);
|
||||
// Write the client area size of window with the width (win_width)
|
||||
//_ and height (win_height) to (width) and (height) parameters.
|
||||
void GetScreenSize(unsigned short &width, unsigned short &height);
|
||||
// Write the screen width and height to (width) and (height) parameters.
|
||||
|
||||
void InitMutex(TMutex *mutex); // Initialize the simple mutex.
|
||||
void InitRecMutex(TRecMutex *mutex); // Initialize the recursive mutex.
|
||||
bool TryLock(TMutex *mutex); // Try to lock the mutex without waitting, return true if lock.
|
||||
bool TryLock(TRecMutex *mutex);
|
||||
bool TryLock(TRecMutex *mutex, TThreadData thread_data);
|
||||
bool TryLock(TRecMutex *mutex, unsigned int pid);
|
||||
void Lock(TMutex *mutex); // Lock mutex and wait for it if this necessary.
|
||||
void Lock(TRecMutex *mutex);
|
||||
void Lock(TRecMutex *mutex, TThreadData thread_data);
|
||||
void Lock(TRecMutex *mutex, unsigned int pid);
|
||||
bool LockTime(TMutex *mutex, int time);
|
||||
bool LockTime(TRecMutex *mutex, int time); // Lock mutex and wait for it during (time) hundredth seconds.
|
||||
bool LockTime(TRecMutex *mutex, int time, TThreadData thread_data);
|
||||
bool LockTime(TRecMutex *mutex, int time, unsigned int pid);
|
||||
void UnLock(TMutex *mutex); // Unlock mutex
|
||||
void UnLock(TRecMutex *mutex);
|
||||
void UnLock(TRecMutex *mutex, TThreadData thread_data);
|
||||
void UnLock(TRecMutex *mutex, unsigned int pid);
|
||||
|
||||
void DebugPutChar(char c); // Put the character to the debug board.
|
||||
void DebugPutString(const char *s); // Put the string to the debug board.
|
||||
int GetKey(); // Return key pressed by user or -1 if no key was pressed.
|
||||
int GetMouseButton(); // Return buttons pressed: 0 - no buttons, 1 - left button, 2 - right button, 3 - both buttons.
|
||||
void GetMousePosition(short &x, short &y, bool absolute = false);
|
||||
// Write mouse position to (x) and (y): absolute if (absolute) is true and relative the window otherwise.
|
||||
void GetMousePosPicture(short &x, short &y);
|
||||
|
||||
int GetThreadNumber(); // Return the number of threads currently executing.
|
||||
bool WasThreadCreated(); // Return true if there was created at least one thread except the main thred.
|
||||
unsigned int CreateThread(void *user = 0, unsigned int stack_size = 0, void *stack_end = 0);
|
||||
// Create a new thread with the user dword (user) and stack pointer (stack_end).
|
||||
//_ If (stack_end) is zero, create stack in dynamic memory of size (stack_size) or
|
||||
//_ the same size as the main thread if (stack_size) less that 4096. Set the beginning
|
||||
//_ 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.
|
||||
void DrawText(short x, short y, int color, const char* string);
|
||||
}
|
||||
|
||||
// Function, defined outside.
|
||||
|
||||
bool KolibriOnStart(Kolibri::TStartData &me_start, Kolibri::TThreadData thread_data);
|
||||
// Window will be created iff return value is true.
|
||||
bool KolibriOnClose(Kolibri::TThreadData thread_data); // Window will be closed iff return value is true.
|
||||
int KolibriOnIdle(Kolibri::TThreadData thread_data); // Return the time to wait next message.
|
||||
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 KolibriOnMouse(Kolibri::TThreadData thread_data); // When user move a mouse.
|
||||
|
||||
#ifdef __KOLIBRI__
|
||||
|
||||
namespace Kolibri
|
||||
{
|
||||
// Structures.
|
||||
|
||||
struct TMutex // Simple mutex can be locked only once at a time.
|
||||
{
|
||||
unsigned int mut;
|
||||
};
|
||||
#undef KOLIBRI_MUTEX_INIT
|
||||
#define KOLIBRI_MUTEX_INIT {0x40} // Simple mutex initializer, cat be redefined in a realization of the library
|
||||
|
||||
struct TRecMutex // Recursive mutex can be locked many times by a single thread at a time.
|
||||
{
|
||||
unsigned int mut, pid;
|
||||
};
|
||||
#undef KOLIBRI_REC_MUTEX_INIT
|
||||
#define KOLIBRI_REC_MUTEX_INIT {0x20,-1} // Recursive mutex initializer, cat be redefined in a realization of the library
|
||||
|
||||
// Global variables.
|
||||
|
||||
volatile TThreadData _ThreadTable[256];
|
||||
volatile unsigned int _ThreadScanCount[2] = {0, 0};
|
||||
volatile int _ThreadNumber = 1;
|
||||
volatile int _ExitProcessNow = 0;
|
||||
TMutex _ThreadMutex = KOLIBRI_MUTEX_INIT;
|
||||
unsigned int _ThreadSavedBegProc[4];
|
||||
|
||||
// Inline functions.
|
||||
|
||||
inline void GetWindowData(TWindowData &win_data) {GetWindowData(win_data, GetThreadData());}
|
||||
|
||||
inline void SetWindowData(const TWindowData &win_data) {SetWindowData(win_data, GetThreadData());}
|
||||
|
||||
inline void CloseWindow() {CloseWindow(GetThreadData());}
|
||||
|
||||
inline void Redraw(int frame) {Redraw(frame, GetThreadData());}
|
||||
|
||||
inline void Invalidate(int frame) {Invalidate(frame, GetThreadData());}
|
||||
|
||||
inline void* GetPicture(unsigned short &width, unsigned short &height)
|
||||
{
|
||||
return GetPicture(width, height, GetThreadData());
|
||||
}
|
||||
|
||||
inline void SetPicture(void *picture, unsigned short width, unsigned short height)
|
||||
{
|
||||
SetPicture(picture, width, height, GetThreadData());
|
||||
}
|
||||
|
||||
inline void GetBorderHeader(unsigned short &border_size, unsigned short &header_size)
|
||||
{
|
||||
GetBorderHeader(border_size, header_size, GetThreadData());
|
||||
}
|
||||
|
||||
inline void GetClientSize(unsigned short &width, unsigned short &height)
|
||||
{
|
||||
unsigned int pid;
|
||||
int rect[4];
|
||||
GetProcessInfo(0, 0, 0, &pid, rect);
|
||||
GetClientSize(width, height, rect[2], rect[3], GetThreadData(pid));
|
||||
}
|
||||
|
||||
inline void GetClientSize(unsigned short &width, unsigned short &height, TThreadData thread_data)
|
||||
{
|
||||
int rect[4];
|
||||
GetProcessInfo(0, 0, 0, 0, rect);
|
||||
GetClientSize(width, height, rect[2], rect[3], thread_data);
|
||||
}
|
||||
|
||||
inline void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height)
|
||||
{
|
||||
GetClientSize(width, height, win_width, win_height, GetThreadData());
|
||||
}
|
||||
|
||||
inline void GetTimeDate(int t[/* 6 */]) {GetTime(t); GetDate(t + 3);}
|
||||
|
||||
inline void InitMutex(TMutex *mutex) {mutex->mut = 0;}
|
||||
|
||||
inline void InitRecMutex(TRecMutex *mutex) {mutex->mut = 0; mutex->pid = -1;}
|
||||
|
||||
inline bool TryLock(TRecMutex *mutex) {return TryLock(mutex, GetPid());}
|
||||
|
||||
inline bool TryLock(TRecMutex *mutex, TThreadData thread_data) {return TryLock(mutex, GetPid(thread_data));}
|
||||
|
||||
inline void Lock(TRecMutex *mutex) {Lock(mutex, GetPid());}
|
||||
|
||||
inline void Lock(TRecMutex *mutex, TThreadData thread_data) {Lock(mutex, GetPid(thread_data));}
|
||||
|
||||
inline bool LockTime(TRecMutex *mutex, int time) {return LockTime(mutex, time, GetPid());}
|
||||
|
||||
inline bool LockTime(TRecMutex *mutex, int time, TThreadData thread_data)
|
||||
{return LockTime(mutex, time, GetPid(thread_data));}
|
||||
|
||||
inline void UnLock(TRecMutex *mutex) {UnLock(mutex, GetPid());}
|
||||
|
||||
inline void UnLock(TRecMutex *mutex, TThreadData thread_data) {UnLock(mutex, GetPid(thread_data));}
|
||||
|
||||
inline int GetThreadNumber() {return _ThreadNumber;}
|
||||
|
||||
// Constants from fasm.
|
||||
|
||||
#include "kos_func.inc"
|
||||
|
||||
// Functions.
|
||||
|
||||
unsigned char _HashByte(unsigned int value);
|
||||
unsigned short _HashWord(unsigned int value);
|
||||
unsigned int _HashDword(unsigned int value);
|
||||
|
||||
void _GetStartData(TStartData &start_data, TThreadData thread_data)
|
||||
{
|
||||
start_data.Left = (unsigned short)((unsigned long)thread_data[KOLIBRI_THREAD_DATA_X] >> 16);
|
||||
start_data.Width = (unsigned short)((unsigned long)thread_data[KOLIBRI_THREAD_DATA_X]);
|
||||
start_data.Top = (unsigned short)((unsigned long)thread_data[KOLIBRI_THREAD_DATA_Y] >> 16);
|
||||
start_data.Height = (unsigned short)((unsigned long)thread_data[KOLIBRI_THREAD_DATA_Y]);
|
||||
GetWindowData(start_data.WinData, thread_data);
|
||||
}
|
||||
|
||||
void _SetStartData(const TStartData &start_data, TThreadData thread_data)
|
||||
{
|
||||
(unsigned long&)thread_data[KOLIBRI_THREAD_DATA_X] =
|
||||
((unsigned int)start_data.Left << 16) | start_data.Width;
|
||||
(unsigned long&)thread_data[KOLIBRI_THREAD_DATA_Y] =
|
||||
((unsigned int)start_data.Top << 16) | start_data.Height;
|
||||
SetWindowData(start_data.WinData, thread_data);
|
||||
}
|
||||
|
||||
void _ApplyCommonColors(TWindowData &win_data)
|
||||
{
|
||||
unsigned int colors[10];
|
||||
ReadCommonColors(colors);
|
||||
win_data.WindowColor = colors[5];
|
||||
win_data.HeaderColor = colors[1];
|
||||
win_data.BorderColor = colors[0];
|
||||
win_data.TitleColor = colors[4];
|
||||
}
|
||||
|
||||
void _SetValueFunctionPriority(void *beg, int n)
|
||||
{
|
||||
int k, i;
|
||||
unsigned char num[256];
|
||||
for (i = 0; i < 256; i++) num[i] = 0;
|
||||
for (k = 0; k < n; k++)
|
||||
{
|
||||
i = ((unsigned char*)beg + 6*k)[1];
|
||||
((unsigned char*)beg + 6*k)[0] = num[i];
|
||||
if (num[i] != 255) num[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
void _CallFunctionPriority(void *beg, void *end, bool reverse = false)
|
||||
{
|
||||
struct _Local
|
||||
{
|
||||
static int cmp(void *beg, int i, int j)
|
||||
{
|
||||
unsigned char *x = (unsigned char*)beg + 6*i;
|
||||
unsigned char *y = (unsigned char*)beg + 6*j;
|
||||
if (*(unsigned short*)x < *(unsigned short*)y) return -1;
|
||||
if (*(unsigned short*)x > *(unsigned short*)y) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void swap(void *beg, int i, int j)
|
||||
{
|
||||
unsigned char *x = (unsigned char*)beg + 6*i;
|
||||
unsigned char *y = (unsigned char*)beg + 6*j;
|
||||
short s;
|
||||
int t;
|
||||
s = *(short*)x; *(short*)x = *(short*)y; *(short*)y = s;
|
||||
x += 2; y += 2;
|
||||
t = *(int*)x; *(int*)x = *(int*)y; *(int*)y = t;
|
||||
}
|
||||
|
||||
static void call(void *beg, int i)
|
||||
{
|
||||
unsigned char *x = (unsigned char*)beg + 6*i;
|
||||
(*(void(**)())(x+2))();
|
||||
}
|
||||
};
|
||||
|
||||
if (!beg || !end || end <= beg) return;
|
||||
int i, j, k, m, n;
|
||||
n = ((unsigned char*)end - (unsigned char*)beg) / 6;
|
||||
if (n <= 0) return;
|
||||
_SetValueFunctionPriority(beg, n);
|
||||
m = n; k = n;
|
||||
while (m > 1)
|
||||
{
|
||||
if (k > 0) k--;
|
||||
else _Local::swap(beg, 0, --m);
|
||||
j = k;
|
||||
for (;;)
|
||||
{
|
||||
i = j;
|
||||
if (2*i + 1 >= m) break;
|
||||
if (_Local::cmp(beg, 2*i + 1, j) > 0) j = 2*i + 1;
|
||||
if (2*i + 2 < m && _Local::cmp(beg, 2*i + 2, j) > 0) j = 2*i + 2;
|
||||
if (i == j) break;
|
||||
_Local::swap(beg, i, j);
|
||||
}
|
||||
}
|
||||
if (!reverse)
|
||||
{
|
||||
for (k = 0; k < n; k++) _Local::call(beg, k);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (k = n-1; k >= 0; k--) _Local::call(beg, k);
|
||||
}
|
||||
}
|
||||
|
||||
bool _CallStart(TThreadData thread_data, void *init = 0, void *init_end = 0)
|
||||
{
|
||||
struct _TThreadDataTemplate
|
||||
{
|
||||
unsigned int data[12];
|
||||
};
|
||||
static const _TThreadDataTemplate _ThreadDataTemplate =
|
||||
{{3, 0x00320100, 0x00320100, 0x33FFFFFF, 0x806060FF, 0x00000000, 0x00FFFF40, 0, 0, 0, -1, -1}};
|
||||
|
||||
unsigned int pid = GetPid();
|
||||
volatile TThreadData *thread_table_item;
|
||||
Lock(&_ThreadMutex);
|
||||
if (_ExitProcessNow) ExitProcess();
|
||||
thread_table_item = &_ThreadTable[_HashByte(pid)];
|
||||
thread_data[KOLIBRI_THREAD_DATA_NEXT] = (void*)*thread_table_item;
|
||||
(unsigned int&)thread_data[KOLIBRI_THREAD_DATA_PID] = pid;
|
||||
*(_TThreadDataTemplate*)(thread_data + KOLIBRI_THREAD_DATA_FLAG) = _ThreadDataTemplate;
|
||||
*thread_table_item = thread_data;
|
||||
UnLock(&_ThreadMutex);
|
||||
if (_ExitProcessNow) ExitProcess();
|
||||
_CallFunctionPriority(init, init_end, false);
|
||||
TStartData start_data;
|
||||
_GetStartData(start_data, thread_data);
|
||||
_ApplyCommonColors(start_data.WinData);
|
||||
(unsigned int&)thread_data[KOLIBRI_THREAD_DATA_FLAG] |= 0x40000000;
|
||||
thread_data[KOLIBRI_THREAD_DATA_TITLE] = (void*)(&start_data);
|
||||
if (!KolibriOnStart(start_data, thread_data)) return false;
|
||||
(unsigned int&)thread_data[KOLIBRI_THREAD_DATA_FLAG] &= ~0x40000000;
|
||||
_SetStartData(start_data, thread_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
void _RemoveThreadData(TThreadData thread_data, void *exit = 0, void *exit_end = 0)
|
||||
{
|
||||
_CallFunctionPriority(exit, exit_end, true);
|
||||
volatile TThreadData *thread_table_item;
|
||||
Lock(&_ThreadMutex);
|
||||
if (_ExitProcessNow) ExitProcess();
|
||||
thread_table_item = &_ThreadTable[_HashByte(GetPid(thread_data))];
|
||||
while (*thread_table_item)
|
||||
{
|
||||
if (*thread_table_item == thread_data)
|
||||
{
|
||||
*thread_table_item = (TThreadData)thread_data[KOLIBRI_THREAD_DATA_NEXT];
|
||||
break;
|
||||
}
|
||||
thread_table_item = (TThreadData*)(*thread_table_item + KOLIBRI_THREAD_DATA_NEXT);
|
||||
}
|
||||
UnLock(&_ThreadMutex);
|
||||
if (_ExitProcessNow) ExitProcess();
|
||||
}
|
||||
|
||||
void GetWindowData(TWindowData &win_data, TThreadData thread_data)
|
||||
{
|
||||
if ((unsigned int)thread_data[KOLIBRI_THREAD_DATA_FLAG] & 0x40000000)
|
||||
{
|
||||
win_data = ((TStartData*)thread_data[KOLIBRI_THREAD_DATA_TITLE])->WinData;
|
||||
return;
|
||||
}
|
||||
win_data.WindowType = (unsigned short)((unsigned int)thread_data[KOLIBRI_THREAD_DATA_C_WINDOW] >> 24);
|
||||
win_data.HeaderType = (unsigned short)((unsigned int)thread_data[KOLIBRI_THREAD_DATA_C_HEADER] >> 24);
|
||||
win_data.WindowColor = (unsigned int)thread_data[KOLIBRI_THREAD_DATA_C_WINDOW] & 0xFFFFFF;
|
||||
win_data.HeaderColor = (unsigned int)thread_data[KOLIBRI_THREAD_DATA_C_HEADER] & 0xFFFFFF;
|
||||
win_data.BorderColor = (unsigned int)thread_data[KOLIBRI_THREAD_DATA_C_BORDER] & 0xFFFFFF;
|
||||
win_data.TitleColor = (unsigned int)thread_data[KOLIBRI_THREAD_DATA_C_TITLE] & 0xFFFFFF;
|
||||
win_data.Title = (char*)thread_data[KOLIBRI_THREAD_DATA_TITLE];
|
||||
}
|
||||
|
||||
void SetWindowData(const TWindowData &win_data, TThreadData thread_data)
|
||||
{
|
||||
if ((unsigned int)thread_data[KOLIBRI_THREAD_DATA_FLAG] & 0x40000000)
|
||||
{
|
||||
((TStartData*)thread_data[KOLIBRI_THREAD_DATA_TITLE])->WinData = win_data;
|
||||
return;
|
||||
}
|
||||
(unsigned int&)thread_data[KOLIBRI_THREAD_DATA_C_WINDOW] =
|
||||
((unsigned int)win_data.WindowType << 24) | (win_data.WindowColor & 0xFFFFFF);
|
||||
(unsigned int&)thread_data[KOLIBRI_THREAD_DATA_C_HEADER] =
|
||||
((unsigned int)win_data.HeaderType << 24) | (win_data.HeaderColor & 0xFFFFFF);
|
||||
(unsigned int&)thread_data[KOLIBRI_THREAD_DATA_C_BORDER] = win_data.BorderColor & 0xFFFFFF;
|
||||
(unsigned int&)thread_data[KOLIBRI_THREAD_DATA_C_TITLE] = win_data.TitleColor & 0xFFFFFF;
|
||||
thread_data[KOLIBRI_THREAD_DATA_TITLE] = (void*)win_data.Title;
|
||||
Invalidate(1, thread_data);
|
||||
}
|
||||
|
||||
void CloseWindow(TThreadData thread_data)
|
||||
{
|
||||
(unsigned int&)thread_data[KOLIBRI_THREAD_DATA_FLAG] |= 0x80000000;
|
||||
}
|
||||
|
||||
void Invalidate(int frame, TThreadData thread_data)
|
||||
{
|
||||
if (frame < 0) return;
|
||||
(unsigned int&)thread_data[KOLIBRI_THREAD_DATA_FLAG] |= (frame ? 3 : 1);
|
||||
}
|
||||
|
||||
void* GetPicture(unsigned short &width, unsigned short &height, TThreadData thread_data)
|
||||
{
|
||||
width = (unsigned short)((unsigned int)thread_data[KOLIBRI_THREAD_DATA_SZ_PICT] >> 16);
|
||||
height = (unsigned short)((unsigned int)thread_data[KOLIBRI_THREAD_DATA_SZ_PICT]);
|
||||
return (void*)thread_data[KOLIBRI_THREAD_DATA_PICTURE];
|
||||
}
|
||||
|
||||
void SetPicture(void *picture, unsigned short width, unsigned short height, TThreadData thread_data)
|
||||
{
|
||||
thread_data[KOLIBRI_THREAD_DATA_PICTURE] = (void*)picture;
|
||||
(unsigned int&)thread_data[KOLIBRI_THREAD_DATA_SZ_PICT] =
|
||||
(width == 0 || height == 0) ? 0 : (((unsigned int)width << 16) | height);
|
||||
Invalidate(0, thread_data);
|
||||
}
|
||||
|
||||
int _GetSkinHeader();
|
||||
|
||||
void GetBorderHeader(unsigned short &border_size, unsigned short &header_size, TThreadData thread_data)
|
||||
{
|
||||
int win_type = ((unsigned int)thread_data[KOLIBRI_THREAD_DATA_FLAG] & 0x40000000) ?
|
||||
((TStartData*)thread_data[KOLIBRI_THREAD_DATA_TITLE])->WinData.WindowType :
|
||||
((unsigned int)thread_data[KOLIBRI_THREAD_DATA_C_WINDOW] >> 24);
|
||||
border_size = KOLIBRI_BORDER_SIZE;
|
||||
header_size = short(((win_type & 15) == 3) ? _GetSkinHeader() : KOLIBRI_HEADER_SIZE);
|
||||
}
|
||||
|
||||
void GetClientSize(unsigned short &width, unsigned short &height,
|
||||
int win_width, int win_height, TThreadData thread_data)
|
||||
{
|
||||
const int MAX_SIZE = 32767;
|
||||
unsigned short border_size, header_size;
|
||||
GetBorderHeader(border_size, header_size, thread_data);
|
||||
win_width -= 2 * border_size;
|
||||
win_height -= border_size + header_size;
|
||||
if (win_width < 0) win_width = 0;
|
||||
else if (win_width > MAX_SIZE) win_width = MAX_SIZE;
|
||||
if (win_height < 0) win_height = 0;
|
||||
else if (win_height > MAX_SIZE) win_height = MAX_SIZE;
|
||||
width = (unsigned short)win_width;
|
||||
height = (unsigned short)win_height;
|
||||
}
|
||||
|
||||
void GetMousePosPicture(short &x, short &y)
|
||||
{
|
||||
unsigned short dx, dy;
|
||||
GetMousePosition(x, y);
|
||||
GetBorderHeader(dx, dy);
|
||||
x -= dx; y -= dy;
|
||||
}
|
||||
}
|
||||
|
||||
#else // def __KOLIBRI__
|
||||
|
||||
namespace Kolibri
|
||||
{
|
||||
struct TMutex
|
||||
{
|
||||
unsigned int mut;
|
||||
|
||||
TMutex();
|
||||
~TMutex();
|
||||
};
|
||||
#undef KOLIBRI_MUTEX_INIT
|
||||
#define KOLIBRI_MUTEX_INIT TMutex()
|
||||
|
||||
struct TRecMutex
|
||||
{
|
||||
unsigned int mut;
|
||||
|
||||
TRecMutex();
|
||||
~TRecMutex();
|
||||
};
|
||||
#undef KOLIBRI_REC_MUTEX_INIT
|
||||
#define KOLIBRI_REC_MUTEX_INIT TRecMutex()
|
||||
}
|
||||
|
||||
#endif // else: def __KOLIBRI__
|
||||
|
||||
#endif // ndef __KOLIBRI_H_INCLUDED_
|
||||
|
278
programs/bcc32/include/kos_file.h
Normal file
278
programs/bcc32/include/kos_file.h
Normal file
@ -0,0 +1,278 @@
|
||||
#ifndef __KOLIBRI_FILE_H_INCLUDED_
|
||||
#define __KOLIBRI_FILE_H_INCLUDED_
|
||||
|
||||
#include "kolibri.h"
|
||||
#include "kos_heap.h"
|
||||
|
||||
// Kolibri file interface.
|
||||
|
||||
namespace Kolibri // All kolibri functions, types and data are nested in the (Kolibri) namespace.
|
||||
{
|
||||
struct _FileDataStruct;
|
||||
typedef _FileDataStruct *TFileData;
|
||||
|
||||
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)};
|
||||
};
|
||||
|
||||
// Inline functions.
|
||||
|
||||
inline bool FileEof(TFileData file_data)
|
||||
{
|
||||
return file_data && file_data->position >= file_data->length;
|
||||
}
|
||||
|
||||
inline unsigned int FileGetPosition(TFileData file_data)
|
||||
{
|
||||
return file_data ? file_data->position : 0;
|
||||
}
|
||||
|
||||
inline void FileReset(TFileData file_data)
|
||||
{
|
||||
if (!file_data) return;
|
||||
file_data->length = -1;
|
||||
file_data->position = 0;
|
||||
if (file_data->buffer) file_data->buffer[1] = 0;
|
||||
}
|
||||
|
||||
// Functions.
|
||||
|
||||
int _FileAccess(void *file_access_param);
|
||||
|
||||
TFileData FileOpen(const char *name, unsigned int buffer_length)
|
||||
{
|
||||
if (!name || !name[0]) return 0;
|
||||
unsigned int name_len = StrLen(name) + 1;
|
||||
unsigned int data_len = (_FileDataStruct::PosName + name_len + 3) & ~3;
|
||||
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);
|
||||
unsigned int attr[40/4];
|
||||
file->access_param[0] = 5;
|
||||
file->access_param[1] = 0;
|
||||
file->access_param[2] = 0;
|
||||
file->access_param[3] = 0;
|
||||
file->access_param[4] = (int)attr;
|
||||
_FileAccess(file->access_param);
|
||||
file->length = attr[32/4];
|
||||
return file;
|
||||
}
|
||||
|
||||
int FileClose(TFileData file_data)
|
||||
{
|
||||
if (!file_data) return -1;
|
||||
Free(file_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileSetPosition(TFileData file_data, unsigned int pos)
|
||||
{
|
||||
if (!file_data) return;
|
||||
if (file_data->buffer && file_data->buffer[1])
|
||||
{
|
||||
if (pos >= file_data->position && pos < file_data->position + file_data->buffer[1])
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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 unsigned int FileGetLength(TFileData file_data)
|
||||
{
|
||||
if (!file_data) return -1;
|
||||
if (file_data->length == -1) FileTestRead(file_data);
|
||||
return file_data->length;
|
||||
}
|
||||
}
|
||||
|
||||
#else // def __KOLIBRI__
|
||||
|
||||
namespace Kolibri
|
||||
{
|
||||
struct _FileDataStruct
|
||||
{
|
||||
unsigned int data;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // else: def __KOLIBRI__
|
||||
|
||||
#endif // ndef __KOLIBRI_FILE_H_INCLUDED_
|
||||
|
1057
programs/bcc32/include/kos_func.inc
Normal file
1057
programs/bcc32/include/kos_func.inc
Normal file
File diff suppressed because it is too large
Load Diff
90
programs/bcc32/include/kos_heap.h
Normal file
90
programs/bcc32/include/kos_heap.h
Normal file
@ -0,0 +1,90 @@
|
||||
#ifndef __KOLIBRI_HEAP_H_INCLUDED_
|
||||
#define __KOLIBRI_HEAP_H_INCLUDED_
|
||||
|
||||
#include "kolibri.h"
|
||||
#include "memheap.h"
|
||||
|
||||
// Kolibri memory heap interface.
|
||||
|
||||
namespace Kolibri // All kolibri functions, types and data are nested in the (Kolibri) namespace.
|
||||
{
|
||||
void *Alloc(unsigned int size);
|
||||
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);
|
||||
_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)
|
||||
{
|
||||
if (!size) return 0;
|
||||
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)
|
||||
{
|
||||
Lock(&_MemHeapMutex);
|
||||
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)
|
||||
{
|
||||
Lock(&_MemHeapMutex);
|
||||
MemoryHeap::Free(_KolibriFreeSpace, mem);
|
||||
UnLock(&_MemHeapMutex);
|
||||
}
|
||||
|
||||
void _FreeAndThreadFinish(void *mem, int *exit_proc_now);
|
||||
}
|
||||
|
||||
#endif // def __KOLIBRI__
|
||||
|
||||
#endif // ndef __KOLIBRI_HEAP_H_INCLUDED_
|
97
programs/bcc32/include/kos_heap.inc
Normal file
97
programs/bcc32/include/kos_heap.inc
Normal file
@ -0,0 +1,97 @@
|
||||
;/***
|
||||
|
||||
KolibriHeapInit = @@Kolibri@_HeapInit$qpvt1t1
|
||||
|
||||
KolibriHeapAlloc = @@Kolibri@Alloc$qui
|
||||
|
||||
KolibriHeapReAlloc = @@Kolibri@ReAlloc$qpvui
|
||||
|
||||
KolibriHeapFree = @@Kolibri@Free$qpv
|
||||
|
||||
KolibriHeapFreeAndThreadFinish = @Kolibri@_FreeAndThreadFinish$qpvpi
|
||||
|
||||
proc @Kolibri@_SetUseMemory$qui
|
||||
push ebx
|
||||
mov eax,64
|
||||
mov ebx,1
|
||||
mov ecx,[esp+8]
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
;/**/
|
16
programs/bcc32/include/kos_lib.h
Normal file
16
programs/bcc32/include/kos_lib.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __KOLIBRI_LIB_H_INCLUDED_
|
||||
#define __KOLIBRI_LIB_H_INCLUDED_
|
||||
|
||||
// Kolibri interface.
|
||||
|
||||
namespace Kolibri // All kolibri functions, types and data are nested in the (Kolibri) namespace.
|
||||
{
|
||||
unsigned int StrLen(const char *str);
|
||||
char *StrCopy(char *dest, const char *src);
|
||||
void *MemCopy(void *dest, const void *src, unsigned int n);
|
||||
void *MemSet(void *s, char c, unsigned int n);
|
||||
|
||||
double Floor(double x);
|
||||
}
|
||||
|
||||
#endif // __KOLIBRI_LIB_H_INCLUDED_
|
106
programs/bcc32/include/kos_lib.inc
Normal file
106
programs/bcc32/include/kos_lib.inc
Normal file
@ -0,0 +1,106 @@
|
||||
proc @Kolibri@StrLen$qpxc uses edi
|
||||
cld
|
||||
mov edi,[esp+8]
|
||||
mov ecx,-1
|
||||
xor al,al
|
||||
repnz scas byte [edi]
|
||||
not ecx
|
||||
lea eax,[ecx-1]
|
||||
ret
|
||||
endp
|
||||
|
||||
proc @Kolibri@StrCopy$qpcpxc uses esi edi
|
||||
cld
|
||||
mov edi,[esp+16]
|
||||
mov ecx,-1
|
||||
mov esi,edi
|
||||
xor al,al
|
||||
repnz scas byte [edi]
|
||||
not ecx
|
||||
mov edi,[esp+12]
|
||||
mov edx,ecx
|
||||
mov eax,edi
|
||||
shr ecx,2
|
||||
rep movs dword [edi],[esi]
|
||||
mov ecx,edx
|
||||
and ecx,3
|
||||
rep movs byte [edi],[esi]
|
||||
ret
|
||||
endp
|
||||
|
||||
proc @Kolibri@MemCopy$qpvpxvui uses esi edi
|
||||
cld
|
||||
mov edi,[esp+12]
|
||||
mov eax,edi
|
||||
mov ecx,[esp+20]
|
||||
mov esi,[esp+16]
|
||||
mov edx,ecx
|
||||
shr ecx,2
|
||||
rep movs dword [edi],[esi]
|
||||
mov ecx,edx
|
||||
and ecx,3
|
||||
rep movs byte [edi],[esi]
|
||||
ret
|
||||
endp
|
||||
|
||||
proc @Kolibri@MemSet$qpvcui uses edi
|
||||
cld
|
||||
mov edi,[esp+8]
|
||||
mov al,[esp+12]
|
||||
mov ah,al
|
||||
mov dx,ax
|
||||
shl eax,16
|
||||
mov ax,dx
|
||||
mov ecx,[esp+16]
|
||||
mov edx,ecx
|
||||
shr ecx,2
|
||||
rep stos dword [edi]
|
||||
mov ecx,edx
|
||||
and ecx,3
|
||||
rep stos byte [edi]
|
||||
mov eax,[esp+4]
|
||||
ret
|
||||
endp
|
||||
|
||||
proc __ftol
|
||||
sub esp,12
|
||||
wait
|
||||
fstcw word [esp+8]
|
||||
wait
|
||||
mov al,[esp+9]
|
||||
or byte [esp+9],0x0c
|
||||
fldcw word [esp+8]
|
||||
fistp qword [esp]
|
||||
mov [esp+9],al
|
||||
fldcw word [esp+8]
|
||||
mov eax,[esp]
|
||||
mov edx,[esp+4]
|
||||
add esp,12
|
||||
ret
|
||||
endp
|
||||
|
||||
proc @Kolibri@Floor$qd
|
||||
fld qword [esp+4]
|
||||
mov ax,[esp+10]
|
||||
shl ax,1
|
||||
cmp ax,0x8680
|
||||
ja .floor_end
|
||||
mov ch,4
|
||||
sub esp,2
|
||||
wait
|
||||
fstcw word [esp]
|
||||
mov ax,0xf3ff
|
||||
wait
|
||||
mov dx,[esp]
|
||||
and ax,dx
|
||||
or ah,ch
|
||||
mov [esp],ax
|
||||
fldcw word [esp]
|
||||
frndint
|
||||
mov [esp],dx
|
||||
fldcw word [esp]
|
||||
add esp,2
|
||||
.floor_end:
|
||||
ret
|
||||
endp
|
||||
|
85
programs/bcc32/include/kos_start.inc
Normal file
85
programs/bcc32/include/kos_start.inc
Normal file
@ -0,0 +1,85 @@
|
||||
use32
|
||||
org 0
|
||||
db 'MENUET01'
|
||||
dd 1
|
||||
dd @Kolibri@Main$qv
|
||||
dd I_END
|
||||
dd U_END+STACKSIZE+HEAPSIZE
|
||||
dd U_END+STACKSIZE
|
||||
dd @Kolibri@CommandLine,0
|
||||
|
||||
ptr equ
|
||||
offset equ
|
||||
short equ
|
||||
tbyte equ tword
|
||||
|
||||
PTR equ
|
||||
OFFSET equ
|
||||
SHORT equ
|
||||
TBYTE equ TWORD
|
||||
|
||||
macro movsb a,b
|
||||
{
|
||||
if a eq & b eq
|
||||
movsb
|
||||
else
|
||||
movsx a,b
|
||||
end if
|
||||
}
|
||||
|
||||
macro movsw a,b
|
||||
{
|
||||
if a eq & b eq
|
||||
movsw
|
||||
else
|
||||
movsx a,b
|
||||
end if
|
||||
}
|
||||
|
||||
macro segment name {}
|
||||
|
||||
macro endseg name {}
|
||||
|
||||
macro usedef [link]
|
||||
{
|
||||
common
|
||||
if ~link eq
|
||||
virtual at 0
|
||||
forward
|
||||
dd link
|
||||
common
|
||||
end virtual
|
||||
end if
|
||||
}
|
||||
|
||||
macro define_f x,[link]
|
||||
{
|
||||
common
|
||||
if x eq
|
||||
else if used x
|
||||
x:
|
||||
usedef link
|
||||
}
|
||||
|
||||
macro enddef [link]
|
||||
{
|
||||
common
|
||||
usedef link
|
||||
end if
|
||||
}
|
||||
|
||||
macro newdef x,[link]
|
||||
{
|
||||
common
|
||||
end if
|
||||
if x eq
|
||||
else if used x
|
||||
x:
|
||||
usedef link
|
||||
}
|
||||
|
||||
macro nextdef x
|
||||
{
|
||||
x:
|
||||
}
|
||||
|
626
programs/bcc32/include/memheap.h
Normal file
626
programs/bcc32/include/memheap.h
Normal file
@ -0,0 +1,626 @@
|
||||
#ifndef __MEMORY_HEAP_RBTREE_H_INCLUDED_
|
||||
#define __MEMORY_HEAP_RBTREE_H_INCLUDED_
|
||||
|
||||
namespace MemoryHeap
|
||||
{
|
||||
typedef unsigned int TMemItem;
|
||||
|
||||
enum {NumTreeSmall = 8 * sizeof(TMemItem)};
|
||||
|
||||
// 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_
|
||||
|
8
programs/bcc32/kos32-bcc/compile.txt
Normal file
8
programs/bcc32/kos32-bcc/compile.txt
Normal file
@ -0,0 +1,8 @@
|
||||
В файле kos32-bcc.asm находится патч для компилятора Borland C++ 5.5.1.
|
||||
После применения данного патча компилятор в режиме компиляции с опцией '-S'
|
||||
выдает *.asm файлы с синтаксисом более похожим на ассемблер fasm.
|
||||
|
||||
Применение:
|
||||
fasm kos32-bcc.asm kos32-bcc.exe
|
||||
|
||||
bcc32.exe должен лежать рядом с kos32-bcc.asm
|
27
programs/bcc32/kos32-bcc/kos32-bcc.asm
Normal file
27
programs/bcc32/kos32-bcc/kos32-bcc.asm
Normal file
@ -0,0 +1,27 @@
|
||||
; patch for new fasm
|
||||
use32
|
||||
|
||||
file 'bcc32.exe':0,0x4a8f
|
||||
dd 0x90909090,0x90909090 ;fix end proc
|
||||
db 0xb8
|
||||
dd 0x4a626b
|
||||
|
||||
file 'bcc32.exe':0x4a9c,0x5753-0x4a9c
|
||||
dd 0x4b2472 ;fix label byte
|
||||
file 'bcc32.exe':0x5757,0x575a-0x5757
|
||||
dd 0x4b2472 ;fix proc near
|
||||
file 'bcc32.exe':0x575e,0x5761-0x575e
|
||||
dd 0x4b2472 ;fix label word
|
||||
file 'bcc32.exe':0x5765,0x5768-0x5765
|
||||
dd 0x4b2472 ;fix label dword
|
||||
file 'bcc32.exe':0x576c,0x576f-0x576c
|
||||
dd 0x4b2472 ;fix label qword
|
||||
file 'bcc32.exe':0x5773,0x5776-0x5773
|
||||
dd 0x4b2472 ;fix label tbyte
|
||||
|
||||
file 'bcc32.exe':0x577a,0x56216-0x577a
|
||||
db '_' ;fix '$' to '_'
|
||||
file 'bcc32.exe':0x56217,0xd4400-0x56217
|
||||
|
||||
;0x4b2472 - ':',13,10,0
|
||||
;0x4a626b - 13,10,0
|
Loading…
Reference in New Issue
Block a user