/programs/demos/life2/include/me_file.h |
---|
0,0 → 1,278 |
#ifndef __MENUET_FILE_H_INCLUDED_ |
#define __MENUET_FILE_H_INCLUDED_ |
#include <menuet.h> |
#include <me_heap.h> |
// Menuet file interface. |
namespace Menuet // All menuet functions, types and data are nested in the (Menuet) 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 __MENUET__ |
namespace Menuet |
{ |
// 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 / MENUET_FILE_BLOCK_SIZE) * MENUET_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 + MENUET_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 /= MENUET_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 / MENUET_FILE_BLOCK_SIZE) * MENUET_FILE_BLOCK_SIZE; |
file_data->access_param[2] = 0; |
file_data->access_param[3] = size * MENUET_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 * MENUET_FILE_BLOCK_SIZE - (file_data->position % MENUET_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(MENUET_FILE_BLOCK_SIZE + 2*sizeof(unsigned int)); |
if (!temp_mem) return -10; |
} |
buffer = (unsigned int*)((char*)temp_mem + MENUET_FILE_BLOCK_SIZE); |
buffer[0] = MENUET_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 % MENUET_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 % MENUET_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] : MENUET_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 / MENUET_FILE_BLOCK_SIZE) * MENUET_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 __MENUET__ |
namespace Menuet |
{ |
struct _FileDataStruct |
{ |
unsigned int data; |
}; |
} |
#endif // else: def __MENUET__ |
#endif // ndef __MENUET_FILE_H_INCLUDED_ |
/programs/demos/life2/include/me_func.inc |
---|
0,0 → 1,1124 |
;const int |
MENUET_BORDER_SIZE = 4; |
;const int |
MENUET_HEADER_SIZE = 20; |
;const int |
MENUET_THREAD_DATA_USER = 0; // Thread data begin from the user dword |
;const int |
MENUET_THREAD_DATA_ST_BEGIN = 1; // Stack beginning follows after the user dword |
;const int |
MENUET_THREAD_DATA_NEXT = 2; |
;const int |
MENUET_THREAD_DATA_PID = 3; |
;const int |
MENUET_THREAD_DATA_FLAG = 4; |
;const int |
MENUET_THREAD_DATA_X = 5; |
;const int |
MENUET_THREAD_DATA_Y = 6; |
;const int |
MENUET_THREAD_DATA_C_WINDOW = 7; |
;const int |
MENUET_THREAD_DATA_C_HEADER = 8; |
;const int |
MENUET_THREAD_DATA_C_BORDER = 9; |
;const int |
MENUET_THREAD_DATA_C_TITLE = 10; |
;const int |
MENUET_THREAD_DATA_TITLE = 11; |
;const int |
MENUET_THREAD_DATA_PICTURE = 12; |
;const int |
MENUET_THREAD_DATA_SZ_PICT = 13; |
;const int |
MENUET_THREAD_DATA_LAST_SX = 14; |
;const int |
MENUET_THREAD_DATA_LAST_SY = 15; |
;const int |
MENUET_THREAD_DATA_LEN = 16; |
;const int |
MENUET_MUTEX_MAX_TIME_WAIT = 20; |
;const int |
MENUET_FILE_BLOCK_SIZE = 512; |
;const int |
MENUET_FILE_MEMORY_OS_NEED = 4096; |
;/*** |
macro segment name |
{ |
segment name |
if name eq _init_ | name eq _INIT_ |
Menuet_SegmentInit: |
else if name eq _exit_ | name eq _EXIT_ |
Menuet_SegmentExit: |
end if |
} |
macro endseg name |
{ |
if name eq _init_ | name eq _INIT_ |
Menuet_SegmentInitEnd: |
else if name eq _exit_ | name eq _EXIT_ |
Menuet_SegmentExitEnd: |
end if |
endseg name |
} |
macro Menuet_Put_MovEaxVal_Ret address,val |
{ |
mov byte [address],0xB8 |
mov dword [address+4],0xC089C300 |
mov dword [address+1],val |
} |
define @Menuet@Main$qv |
nextdef MenuetEntryPoint |
and esp,not 3 |
sub esp,1024 |
mov eax,9 |
mov ebx,esp |
mov ecx,-1 |
int 0x40 |
mov ebx,[esp+26] |
mov edx,[esp+30] |
lea eax,[ebx-0x20] |
add esp,1024 |
cmp esp,eax |
cmova esp,eax |
and esp,not 3 |
if defined @Menuet@CommandLine |
mov byte [@Menuet@CommandLine+256], 0 |
end if |
xor eax,eax |
cld |
mov edi,@Menuet@_ThreadTable |
mov ecx,256 |
rep stos dword [edi] |
mov esi,@Menuet@GetPid$qv |
mov edi,@Menuet@_ThreadSavedBegProc |
movs dword [edi],[esi] |
movs dword [edi],[esi] |
mov esi,@Menuet@GetThreadData$qv |
movs dword [edi],[esi] |
movs dword [edi],[esi] |
Menuet_Put_MovEaxVal_Ret @Menuet@GetPid$qv,edx |
if defined MenuetHeapInit |
mov ecx,esp |
push ebx |
push ecx |
push U_END |
call MenuetHeapInit ; Initialize a dynamic heap and create new memory in its begin. |
pop ecx ; Parameters: begin of a new heap, end of data to create in |
mov [esp+4],eax ; the begin of a heap. Return address of the created data. |
mov dword [esp],0 |
else |
xor eax,eax |
push eax |
push eax |
end if |
call @Menuet@ThreadMain$qpvt1 |
nextdef Menuet_ThreadFinish |
add esp,8 |
if defined MenuetHeapFreeAndThreadFinish |
test eax,eax |
jz Menuet_ThreadFinish_end |
push dword @Menuet@_ExitProcessNow |
push eax |
call MenuetHeapFreeAndThreadFinish ; Free the given memory and finish the thread, |
end if ; should exit process if second argument points to not zero. |
Menuet_ThreadFinish_end: |
or eax,-1 |
int 0x40 |
enddef |
define @Menuet@ThreadMain$qpvt1 |
xchg ebx,[esp+4] |
xchg ebp,[esp+8] |
push esi |
push edi |
sub esp,MENUET_THREAD_DATA_LEN*4 |
mov [esp],ebx |
mov [esp+4],ebp |
mov eax,40 |
mov ebx,0x27 |
int 0x40 |
mov ebx,esp |
cmp byte [@Menuet@_ThreadSavedBegProc],0x90 |
jz Menuet_main_else_first_check |
Menuet_Put_MovEaxVal_Ret @Menuet@GetThreadData$qv,esp |
if defined Menuet_SegmentInit & defined Menuet_SegmentInitEnd |
push Menuet_SegmentInitEnd |
push Menuet_SegmentInit |
jmp Menuet_main_after_first_check |
end if |
Menuet_main_else_first_check: |
xor eax,eax |
push eax |
push eax |
Menuet_main_after_first_check: |
push ebx |
call @@Menuet@_CallStart$qppvpvt2 |
add esp,12 |
test al,al |
jnz Menuet_main_test_close_first |
jmp Menuet_main_end |
Menuet_main_close_first: |
btr dword [esp+MENUET_THREAD_DATA_FLAG*4],31 |
push esp |
call @@MenuetOnClose$qppv |
pop ecx |
test al,al |
jnz Menuet_main_end |
Menuet_main_test_close_first: |
cmp dword [esp+MENUET_THREAD_DATA_FLAG*4],0 |
jl Menuet_main_close_first |
push esp |
push dword 1 |
call @Menuet@Redraw$qippv |
add esp,8 |
Menuet_main_paint_msg: |
or dword [esp+MENUET_THREAD_DATA_FLAG*4],3 |
sub esp,1024 |
mov eax,9 |
mov ebx,esp |
mov ecx,-1 |
int 0x40 |
mov eax,[esp+34] |
mov ebx,[esp+38] |
mov ecx,[esp+42] |
mov edx,[esp+46] |
add esp,1024 |
cmp ecx,[esp+MENUET_THREAD_DATA_LAST_SX*4] |
jnz Menuet_main_size |
cmp edx,[esp+MENUET_THREAD_DATA_LAST_SY*4] |
jz Menuet_main_paint |
Menuet_main_size: |
mov [esp+MENUET_THREAD_DATA_LAST_SX*4],ecx |
mov [esp+MENUET_THREAD_DATA_LAST_SY*4],edx |
push edx |
push ecx |
push ebx |
push eax |
lea ecx,[esp+16] |
mov edx,esp |
push ecx |
push edx |
call @@MenuetOnSize$qpippv |
add esp,24 |
test dword [esp+MENUET_THREAD_DATA_FLAG*4],3 |
jz Menuet_main_cycle |
Menuet_main_paint: |
cmp dword [esp+MENUET_THREAD_DATA_FLAG*4],0 |
jl Menuet_main_close |
push esp |
push dword 0 |
call @Menuet@Redraw$qippv |
add esp,8 |
Menuet_main_cycle: |
mov eax,11 |
Menuet_main_message: |
cmp dword [esp+MENUET_THREAD_DATA_FLAG*4],0 |
jl Menuet_main_close |
int 0x40 |
test eax,eax |
jnz Menuet_main_on_message |
cmp dword [esp+MENUET_THREAD_DATA_FLAG*4],0 |
jne Menuet_main_paint |
push esp |
call @@MenuetOnIdle$qppv |
pop ecx |
test eax,eax |
jz Menuet_main_cycle |
jl Menuet_main_wait_message |
mov ebx,eax |
mov eax,23 |
jmp Menuet_main_message |
Menuet_main_wait_message: |
mov eax,10 |
jmp Menuet_main_message |
Menuet_main_key_press: |
push esp |
call @@MenuetOnKeyPress$qppv |
pop ecx |
jmp Menuet_main_cycle |
Menuet_main_mouse: |
push esp |
call @@MenuetOnMouse$qppv |
pop ecx |
jmp Menuet_main_cycle |
Menuet_main_on_message: |
dec eax |
jz Menuet_main_paint_msg |
dec eax |
jz Menuet_main_key_press |
cmp eax,4 |
jz Menuet_main_mouse |
dec eax |
jnz Menuet_main_cycle |
Menuet_main_button: |
mov eax,17 |
int 0x40 |
test al,al |
jnz Menuet_main_cycle |
Menuet_main_close: |
btr dword [esp+MENUET_THREAD_DATA_FLAG*4],31 |
push esp |
call @@MenuetOnClose$qppv |
pop ecx |
test al,al |
jz Menuet_main_button |
Menuet_main_end: |
mov ebx,esp |
lock dec dword [@Menuet@_ThreadNumber] |
if defined Menuet_SegmentExit & defined Menuet_SegmentExitEnd |
jnz Menuet_main_else_last_check |
push Menuet_SegmentExitEnd |
push Menuet_SegmentExit |
jmp Menuet_main_after_last_check |
end if |
Menuet_main_else_last_check: |
xor eax,eax |
push eax |
push eax |
Menuet_main_after_last_check: |
push ebx |
call @@Menuet@_RemoveThreadData$qppvpvt2 |
add esp,12 |
lock inc dword [@Menuet@_ThreadScanCount+4] |
mov ebx,1 |
jmp Menuet_main_end_wait |
Menuet_main_end_wait_loop: |
mov eax,5 |
int 0x40 |
shl ebx,1 |
cmp ebx,MENUET_MUTEX_MAX_TIME_WAIT |
jna Menuet_main_end_wait |
mov ebx,MENUET_MUTEX_MAX_TIME_WAIT |
Menuet_main_end_wait: |
cmp dword [@Menuet@_ExitProcessNow],0 |
jnz @Menuet@ExitProcess$qv |
cmp dword [@Menuet@_ThreadScanCount],0 |
jnz Menuet_main_end_wait_loop |
lock dec dword [@Menuet@_ThreadScanCount+4] |
mov ebp,[esp+4] |
mov ebx,[esp] |
add esp,MENUET_THREAD_DATA_LEN*4 |
mov eax,ebp |
pop edi |
pop esi |
xchg ebp,[esp+8] |
xchg ebx,[esp+4] |
ret |
enddef |
macro call func |
{ |
if func eq __chkstk |
sub esp,eax |
else |
call func |
end if |
} |
define @Menuet@Redraw$qippv |
push ebp |
mov ebp,[esp+12] |
mov edx,[ebp+MENUET_THREAD_DATA_FLAG*4] |
cmp dword [esp+8],0 |
jl Menuet_redraw_only_inv |
jz Menuet_redraw_no_frame |
or dl,2 |
Menuet_redraw_no_frame: |
bt edx,30 |
jnc Menuet_redraw_begin |
or dl,1 |
mov [ebp+MENUET_THREAD_DATA_FLAG*4],edx |
jmp Menuet_redraw_end |
Menuet_redraw_only_inv: |
test dl,3 |
jnz Menuet_redraw_no_frame |
Menuet_redraw_end: |
pop ebp |
ret |
Menuet_redraw_begin: |
push ebx |
push esi |
push edi |
and dword [ebp+MENUET_THREAD_DATA_FLAG*4],0xFFFFFFFC |
test dl,2 |
jz Menuet_redraw_picture |
mov eax,12 |
mov ebx,1 |
int 0x40 |
xor eax,eax |
mov ebx,[ebp+MENUET_THREAD_DATA_X*4] |
mov ecx,[ebp+MENUET_THREAD_DATA_Y*4] |
mov edx,[ebp+MENUET_THREAD_DATA_C_WINDOW*4] |
mov esi,[ebp+MENUET_THREAD_DATA_C_HEADER*4] |
mov edi,[ebp+MENUET_THREAD_DATA_C_BORDER*4] |
int 0x40 |
mov edx,[ebp+MENUET_THREAD_DATA_TITLE*4] |
test edx,edx |
jz Menuet_window_defined |
mov edi,edx |
mov ecx,0xFFFFFFFF |
xor al,al |
cld |
repnz scas byte [edi] |
not ecx |
mov esi,ecx |
dec esi |
jz Menuet_window_defined |
mov eax,4 |
mov ebx,0x00070007 |
mov ecx,[ebp+MENUET_THREAD_DATA_C_TITLE*4] |
int 0x40 |
Menuet_window_defined: |
mov eax,12 |
mov ebx,2 |
int 0x40 |
Menuet_redraw_picture: |
mov eax,12 |
mov ebx,2 |
int 0x40 |
mov esi,[ebp+MENUET_THREAD_DATA_PICTURE*4] |
test esi,esi |
jz Menuet_redraw_end_draw |
mov ecx,[ebp+MENUET_THREAD_DATA_SZ_PICT*4] |
jecxz Menuet_redraw_end_draw |
mov al,byte [ebp+MENUET_THREAD_DATA_C_WINDOW*4+3] |
and al,15 |
mov edx,MENUET_BORDER_SIZE*65536+MENUET_HEADER_SIZE |
cmp al,3 |
jnz Menuet_redraw_no_skin |
mov eax,48 |
mov ebx,4 |
int 0x40 |
mov dx,ax |
Menuet_redraw_no_skin: |
mov eax,7 |
mov ebx,esi |
int 0x40 |
Menuet_redraw_end_draw: |
pop edi |
pop esi |
pop ebx |
pop ebp |
ret |
enddef |
define @Menuet@MoveWindow$qxpxi |
push ebx |
push esi |
mov eax,[esp+12] |
mov ebx,[eax] |
mov ecx,[eax+4] |
mov edx,[eax+8] |
mov esi,[eax+12] |
mov eax,67 |
int 0x40 |
pop esi |
pop ebx |
ret |
enddef |
define @Menuet@Abort$qv |
push dword [@Menuet@DebugPrefix] |
call @Menuet@DebugPutString$qpxc |
mov dword [esp],Menuet_abort_string |
call @Menuet@DebugPutString$qpxc |
pop ecx |
nextdef @Menuet@ExitProcess$qv |
lock bts dword [@Menuet@_ExitProcessNow],0 |
jc Menuet_exit_process_wait |
sub esp,1024 |
mov eax,9 |
mov ebx,esp |
mov ecx,-1 |
int 0x40 |
mov esi,eax |
mov edi,[esp+30] |
Menuet_exit_process_loop: |
mov eax,9 |
mov ebx,esp |
mov ecx,esi |
int 0x40 |
mov eax,[esp+30] |
cmp eax,edi |
jz Menuet_exit_process_continue |
mov ebx,eax |
or bl,15 |
inc ebx |
jz Menuet_exit_process_continue |
mov ebx,eax |
call Menuet_HashInt |
movzx eax,al |
mov eax,dword [@Menuet@_ThreadTable+eax*4] |
jmp Menuet_exit_process_test |
Menuet_exit_process_next: |
mov eax,dword [eax+MENUET_THREAD_DATA_NEXT*4] |
Menuet_exit_process_test: |
test eax,eax |
jz Menuet_exit_process_continue |
cmp ebx,[eax+MENUET_THREAD_DATA_PID*4] |
jnz Menuet_exit_process_next |
mov eax,18 |
mov ebx,2 |
mov ecx,esi |
int 0x40 |
Menuet_exit_process_continue: |
dec esi |
jnl Menuet_exit_process_loop |
add esp,1024 |
mov dword [@Menuet@_ExitProcessNow],-1 |
if defined EMULATOR |
int3 |
call 0x76543210 |
end if |
Menuet_exit_process_end: |
mov dword [@Menuet@_ThreadMutex],0 |
or eax,-1 |
int 0x40 |
Menuet_exit_process_wait: |
mov eax,5 |
mov ebx,1 |
Menuet_exit_process_wait_loop: |
cmp dword [@Menuet@_ExitProcessNow],0 |
jl Menuet_exit_process_end |
int 0x40 |
shl ebx,1 |
cmp ebx,MENUET_MUTEX_MAX_TIME_WAIT |
jna Menuet_exit_process_wait_loop |
mov ebx,MENUET_MUTEX_MAX_TIME_WAIT |
jmp Menuet_exit_process_wait_loop |
enddef |
define @Menuet@ExitThread$qppv,@Menuet@ThreadMain$qpvt1 |
mov esp,[esp+4] |
jmp Menuet_main_end |
enddef |
define @Menuet@ReturnMessageLoop$qppv,@Menuet@ThreadMain$qpvt1 |
mov esp,[esp+4] |
bt dword [esp+MENUET_THREAD_DATA_FLAG*4],30 |
jc Menuet_main_end |
jmp Menuet_main_cycle |
enddef |
define @Menuet@Delay$qui |
push ebx |
mov eax,5 |
mov ebx,[esp+8] |
int 0x40 |
pop ebx |
ret |
enddef |
define @Menuet@Clock$qv |
push ebx |
mov eax,26 |
mov ebx,9 |
int 0x40 |
pop ebx |
ret |
enddef |
define @Menuet@GetPackedTime$qv |
mov eax,3 |
int 0x40 |
ret |
enddef |
define @Menuet@GetTime$qpi |
mov eax,3 |
int 0x40 |
mov edx,[esp+4] |
movzx ecx,al |
shr ecx,4 |
and al,0x0F |
imul ecx,10 |
add cl,al |
mov dword [edx+8],ecx |
mov cl,ah |
shr ecx,4 |
and ah,0x0F |
imul ecx,10 |
add cl,ah |
mov dword [edx+4],ecx |
bswap eax |
mov cl,ah |
shr ecx,4 |
and ah,0x0F |
imul ecx,10 |
add cl,ah |
mov dword [edx],ecx |
ret |
enddef |
define @Menuet@GetPackedDate$qv |
mov eax,29 |
int 0x40 |
ret |
enddef |
define @Menuet@GetDate$qpi |
mov eax,29 |
int 0x40 |
mov edx,[esp+4] |
movzx ecx,al |
shr ecx,4 |
and al,0x0F |
imul ecx,10 |
add cl,al |
mov dword [edx+4],ecx |
mov cl,ah |
shr ecx,4 |
and ah,0x0F |
imul ecx,10 |
add cl,ah |
mov dword [edx],ecx |
bswap eax |
mov cl,ah |
shr ecx,4 |
and ah,0x0F |
imul ecx,10 |
add cl,ah |
mov dword [edx+8],ecx |
ret |
enddef |
define @Menuet@ReadCommonColors$qpui |
push ebx |
mov eax,48 |
mov ebx,3 |
mov ecx,[esp+8] |
mov edx,40 |
int 0x40 |
pop ebx |
ret |
enddef |
define @Menuet@GetProcessInfo$qpuipct1t1piui |
push ebx |
push esi |
push edi |
sub esp,1024 |
mov eax,9 |
mov ebx,esp |
mov ecx,[1024+12+24+esp] |
int 0x40 |
xor edi,edi |
or edi,[1024+12+4+esp] |
jz Menuet_get_proc_info_no_usecpu |
mov ecx,[esp] |
mov [edi],ecx |
xor edi,edi |
Menuet_get_proc_info_no_usecpu: |
or edi,[1024+12+8+esp] |
jz Menuet_get_proc_info_no_name |
lea esi,[esp+10] |
cld |
movs dword [edi],[esi] |
movs dword [edi],[esi] |
movs dword [edi],[esi] |
mov byte [edi],0 |
xor edi,edi |
Menuet_get_proc_info_no_name: |
or edi,[1024+12+12+esp] |
jz Menuet_get_proc_info_no_mem |
mov ecx,[esp+26] |
mov [edi],ecx |
xor edi,edi |
Menuet_get_proc_info_no_mem: |
or edi,[1024+12+16+esp] |
jz Menuet_get_proc_info_no_pid |
mov ecx,[esp+30] |
mov [edi],ecx |
xor edi,edi |
Menuet_get_proc_info_no_pid: |
or edi,[1024+12+20+esp] |
jz Menuet_get_proc_info_no_rect |
lea esi,[esp+34] |
cld |
movs dword [edi],[esi] |
movs dword [edi],[esi] |
movs dword [edi],[esi] |
movs dword [edi],[esi] |
xor edi,edi |
Menuet_get_proc_info_no_rect: |
add esp,1024 |
pop edi |
pop esi |
pop ebx |
ret |
enddef |
define @Menuet@GetPid$qv |
push ebx |
sub esp,1024 |
mov eax,9 |
mov ebx,esp |
mov ecx,-1 |
int 0x40 |
mov eax,[esp+30] |
add esp,1024 |
pop ebx |
ret |
enddef |
define @Menuet@GetPid$qppv |
mov ecx,[esp+4] |
mov eax,[ecx+MENUET_THREAD_DATA_PID*4] |
ret |
enddef |
define @Menuet@_HashByte$qui |
nextdef @Menuet@_HashWord$qui |
nextdef @Menuet@_HashDword$qui |
mov eax,[esp+4] |
nextdef Menuet_HashInt |
mul dword [Menuet_hash_int_val0] |
xor eax,edx |
bswap eax |
mul dword [Menuet_hash_int_val1] |
shrd eax,edx,14 |
bswap eax |
lea eax,[eax+4*eax] |
ror eax,9 |
ret |
Menuet_hash_int_val0: |
dd 0xA82F94C5 |
Menuet_hash_int_val1: |
dd 0x9193780B |
enddef |
define @Menuet@GetThreadData$qv |
call @Menuet@GetPid$qv |
push eax |
call @Menuet@GetThreadData$qui |
pop ecx |
ret |
enddef |
define @Menuet@GetThreadData$qui |
mov eax,[esp+4] |
call Menuet_HashInt |
movzx eax,al |
cmp dword [@Menuet@_ThreadScanCount+4],0 |
jnz Menuet_get_thread_data_wait |
Menuet_get_thread_data_nowait: |
lock inc dword [@Menuet@_ThreadScanCount] |
mov eax,dword [@Menuet@_ThreadTable+eax*4] |
mov ecx,[esp+4] |
jmp Menuet_get_thread_data_test |
Menuet_get_thread_data_loop: |
mov eax,dword [eax+MENUET_THREAD_DATA_NEXT*4] |
Menuet_get_thread_data_test: |
test eax,eax |
jz Menuet_get_thread_data_end |
cmp ecx,[eax+MENUET_THREAD_DATA_PID*4] |
jnz Menuet_get_thread_data_loop |
Menuet_get_thread_data_end: |
lock dec dword [@Menuet@_ThreadScanCount] |
ret |
Menuet_get_thread_data_wait: |
push eax |
push ebx |
mov eax,5 |
mov ebx,1 |
Menuet_get_thread_data_wait_loop: |
int 0x40 |
cmp dword [@Menuet@_ThreadScanCount+4],0 |
jz Menuet_get_thread_data_wait_end |
shl ebx,1 |
cmp ebx,MENUET_MUTEX_MAX_TIME_WAIT |
jna Menuet_get_thread_data_wait_loop |
mov ebx,MENUET_MUTEX_MAX_TIME_WAIT |
jmp Menuet_get_thread_data_wait_loop |
Menuet_get_thread_data_wait_end: |
pop ebx |
pop eax |
jmp Menuet_get_thread_data_nowait |
enddef |
define @Menuet@_GetSkinHeader$qv |
push ebx |
mov eax,48 |
mov ebx,4 |
int 0x40 |
pop ebx |
ret |
enddef |
define @Menuet@GetScreenSize$qrust1 |
mov eax,14 |
int 0x40 |
mov ecx,[esp+8] |
mov word [ecx],ax |
mov ecx,[esp+4] |
shr eax,16 |
mov word [ecx],ax |
ret |
enddef |
define Menuet_MutexLockNoWait |
pop eax |
xor al,al |
ret |
enddef |
define Menuet_MutexLockWait |
push ebx |
mov eax,5 |
xor ebx,ebx |
Menuet_lock_wait_cycle: |
int 0x40 |
shl byte [ecx],1 |
jz Menuet_lock_wait_cycle |
pop ebx |
mov al,1 |
ret |
enddef |
define Menuet_MutexLockWaitTime |
cmp dword [esp+12],0 |
jng Menuet_MutexLockWait |
push ebx |
push edx |
mov edx,[esp+20] |
mov eax,26 |
mov ebx,9 |
int 0x40 |
add edx,eax |
Menuet_lock_wait_time_cycle: |
mov eax,5 |
xor ebx,ebx |
int 0x40 |
shl byte [ecx],1 |
jnz Menuet_lock_wait_time_ret_true |
mov eax,26 |
mov ebx,9 |
int 0x40 |
cmp eax,edx |
js Menuet_lock_wait_time_cycle |
pop edx |
pop ebx |
pop eax |
xor al,al |
ret |
Menuet_lock_wait_time_ret_true: |
pop edx |
pop ebx |
mov al,1 |
ret |
enddef |
define Menuet_MutexLock |
shl byte [ecx],1 |
jnz Menuet_lock_first |
call eax |
Menuet_lock_first: |
mov al,1 |
ret |
enddef |
define @Menuet@TryLock$qp13Menuet@TMutex |
mov eax,Menuet_MutexLockNoWait |
mov ecx,[esp+4] |
jmp Menuet_MutexLock |
enddef |
define @Menuet@Lock$qp13Menuet@TMutex |
mov eax,Menuet_MutexLockWait |
mov ecx,[esp+4] |
jmp Menuet_MutexLock |
enddef |
define @Menuet@LockTime$qp13Menuet@TMutexi |
mov eax,Menuet_MutexLockWaitTime |
mov ecx,[esp+4] |
jmp Menuet_MutexLock |
enddef |
define @Menuet@UnLock$qp13Menuet@TMutex |
mov ecx,[esp+4] |
shr byte [ecx],1 |
jz Menuet_unlock_pause |
ret |
Menuet_unlock_pause: |
mov byte [ecx],0x40 |
push ebx |
mov eax,5 |
xor ebx,ebx |
int 0x40 |
pop ebx |
ret |
enddef |
define Menuet_MutexLockRec |
shl byte [ecx],1 |
jng Menuet_lock_first |
cmp dword [ecx+4],edx |
jz Menuet_lock_rec_self |
call eax |
Menuet_lock_rec_first: |
mov al,1 |
mov dword [ecx+4],edx |
ret |
Menuet_lock_rec_self: |
mov al,1 |
add dword [ecx],0x100 |
jc Menuet_lock_rec_overflow |
ret |
Menuet_lock_rec_overflow: |
push dword [@Menuet@DebugPrefix] |
call @Menuet@DebugPutString$qpxc |
mov dword [esp],Menuet_try_lock_rec_overflow_string |
call @Menuet@DebugPutString$qpxc |
pop ecx |
jmp @Menuet@Abort$qv |
enddef |
define @Menuet@TryLock$qp16Menuet@TRecMutexui |
mov eax,Menuet_MutexLockNoWait |
mov ecx,[esp+4] |
mov edx,[esp+8] |
jmp Menuet_MutexLockRec |
enddef |
define @Menuet@Lock$qp16Menuet@TRecMutexui |
mov eax,Menuet_MutexLockWait |
mov ecx,[esp+4] |
mov edx,[esp+8] |
jmp Menuet_MutexLockRec |
enddef |
define @Menuet@LockTime$qp16Menuet@TRecMutexiui |
mov eax,Menuet_MutexLockWaitTime |
mov ecx,[esp+4] |
mov edx,[esp+12] |
jmp Menuet_MutexLockRec |
enddef |
define @Menuet@UnLock$qp16Menuet@TRecMutexui |
mov ecx,[esp+4] |
mov edx,[esp+8] |
cmp dword [ecx+4],edx |
jnz Menuet_unlock_rec_notlocked |
sub dword [ecx],0x100 |
jnc Menuet_unlock_rec_end |
add dword [ecx],0x100 |
shl byte [ecx],1 |
shr byte [ecx],2 |
jng Menuet_unlock_rec_pause |
Menuet_unlock_rec_end: |
ret |
Menuet_unlock_rec_pause: |
mov byte [ecx],0x20 |
push ebx |
mov eax,5 |
xor ebx,ebx |
int 0x40 |
pop ebx |
ret |
Menuet_unlock_rec_notlocked: |
push dword [@Menuet@DebugPrefix] |
call @Menuet@DebugPutString$qpxc |
mov dword [esp],Menuet_unlock_rec_notlocked_string |
call @Menuet@DebugPutString$qpxc |
pop ecx |
jmp @Menuet@Abort$qv |
enddef |
define @Menuet@DebugPutChar$qc |
mov cl,byte [esp+4] |
cmp cl,13 |
jz Menuet_debug_put_char_ret |
push ebx |
cmp cl,10 |
jz Menuet_debug_put_char_enter |
Menuet_debug_put_char_after_cmp: |
mov eax,63 |
mov ebx,1 |
int 0x40 |
pop ebx |
Menuet_debug_put_char_ret: |
ret |
Menuet_debug_put_char_enter: |
mov cl,13 |
mov eax,63 |
mov ebx,1 |
int 0x40 |
mov cl,10 |
jmp Menuet_debug_put_char_after_cmp |
enddef |
define @Menuet@DebugPutString$qpxc |
push esi |
push dword 0 |
mov esi,dword [esp+12] |
jmp Menuet_debug_put_string_test |
Menuet_debug_put_string_loop: |
mov dword [esp],eax |
call @Menuet@DebugPutChar$qc |
inc esi |
Menuet_debug_put_string_test: |
xor eax,eax |
or al,[esi] |
test al,al |
jnz Menuet_debug_put_string_loop |
pop ecx |
pop esi |
ret |
enddef |
define @Menuet@GetKey$qv |
mov eax,2 |
int 0x40 |
test al,al |
jnz Menuet_get_key_eof |
movzx eax,ah |
ret |
Menuet_get_key_eof: |
mov eax,-1 |
ret |
enddef |
define @Menuet@GetMouseButton$qv |
push ebx |
mov eax,37 |
mov ebx,2 |
int 0x40 |
pop ebx |
ret |
enddef |
define @Menuet@GetMousePosition$qrst1o |
push ebx |
mov eax,37 |
xor ebx,ebx |
cmp byte [esp+16],0 |
jnz Menuet_get_mouse_pos_absolute |
inc ebx |
Menuet_get_mouse_pos_absolute: |
int 0x40 |
mov ecx,[esp+12] |
mov word [ecx],ax |
mov ecx,[esp+8] |
shr eax,16 |
mov word [ecx],ax |
pop ebx |
ret |
enddef |
define @Menuet@WasThreadCreated$qv |
cmp byte [@Menuet@_ThreadSavedBegProc],0x90 |
setz al |
ret |
enddef |
define @Menuet@CreateThread$qpvuit1 |
push ebx |
mov edx,[esp+16] |
mov ebx,[esp+12] |
test edx,edx |
jnz Menuet_create_thread_after_new |
if defined MenuetHeapAlloc |
cmp ebx,4096 |
jnb Menuet_create_thread_alloc |
mov ebx,STACKSIZE |
Menuet_create_thread_alloc: |
push ebx |
call MenuetHeapAlloc ; Create new dynamic memory of the given size |
pop ecx |
test eax,eax |
jnz Menuet_create_thread_mem_created |
end if |
or eax,-1 |
jmp Menuet_create_thread_end |
Menuet_create_thread_mem_created: |
lea edx,[eax+ebx] |
Menuet_create_thread_after_new: |
neg ebx |
jz Menuet_create_thread_test_first |
add ebx,edx |
Menuet_create_thread_test_first: |
cmp byte [@Menuet@_ThreadSavedBegProc],0x90 |
jnz Menuet_create_thread_init |
Menuet_create_thread_fill_stack: |
lock inc dword [@Menuet@_ThreadNumber] |
and edx,not 3 |
sub edx,12 |
mov ecx,[esp+8] |
mov dword [edx+8],ebx |
mov dword [edx+4],ecx |
mov dword [edx],Menuet_ThreadFinish |
mov eax,51 |
mov ebx,1 |
mov ecx,@Menuet@ThreadMain$qpvt1 |
int 0x40 |
mov ebx,eax |
or bl,15 |
inc ebx |
jnz Menuet_create_thread_end |
lock dec dword [@Menuet@_ThreadNumber] |
if defined MenuetHeapFree |
or ebx,[edx+8] |
jz Menuet_create_thread_end |
push ebx |
call MenuetHeapFree ; Delete the given dynamic memory |
pop ecx |
end if |
Menuet_create_thread_end: |
pop ebx |
ret |
Menuet_create_thread_init: |
push esi |
push edi |
cld |
mov esi,@Menuet@_ThreadSavedBegProc |
mov edi,@Menuet@GetPid$qv |
movs dword [edi],[esi] |
movs dword [edi],[esi] |
mov edi,@Menuet@GetThreadData$qv |
movs dword [edi],[esi] |
movs dword [edi],[esi] |
mov eax,0x90909090 |
mov edi,@Menuet@_ThreadSavedBegProc |
stos dword [edi] |
stos dword [edi] |
stos dword [edi] |
stos dword [edi] |
pop edi |
pop esi |
jmp Menuet_create_thread_fill_stack |
enddef |
define @Menuet@_FileAccess$qpv |
push ebx |
mov eax,70 |
mov ebx,[esp+8] |
int 0x40 |
mov ecx,[esp+8] |
mov [ecx],ebx |
pop ebx |
ret |
enddef |
define Menuet_abort_string |
db 'Abnormal program termination.',10,0 |
newdef Menuet_try_lock_rec_overflow_string |
db 'Recursive mutex lock count overflow.',10,0 |
newdef Menuet_unlock_rec_notlocked_string |
db 'Recursive mutex unlock error.',10,0 |
enddef |
include "me_lib.inc" |
;/**/ |
/programs/demos/life2/include/me_heap.h |
---|
0,0 → 1,90 |
#ifndef __MENUET_HEAP_H_INCLUDED_ |
#define __MENUET_HEAP_H_INCLUDED_ |
#include <menuet.h> |
#include <memheap.h> |
// Menuet memory heap interface. |
namespace Menuet // All menuet functions, types and data are nested in the (Menuet) namespace. |
{ |
void *Alloc(unsigned int size); |
void *ReAlloc(void *mem, unsigned int size); |
void Free(void *mem); |
} |
#ifdef __MENUET__ |
namespace Menuet |
{ |
// Global variables |
MemoryHeap::TFreeSpace _MenuetFreeSpace; |
MemoryHeap::TMemBlock _MenuetMemBlock; |
TMutex _MemHeapMutex = MENUET_MUTEX_INIT; |
// Functions |
void *_HeapInit(void *begin, void *use_end, void *end) |
{ |
MemoryHeap::InitFreeSpace(_MenuetFreeSpace); |
_MenuetMemBlock = MemoryHeap::CreateBlock(begin, end, _MenuetFreeSpace); |
unsigned int use_beg = (unsigned int)MemoryHeap::BlockBegin(_MenuetMemBlock) + |
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(_MenuetFreeSpace, 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(_MenuetFreeSpace, size); |
if (!res) |
{ |
unsigned use_mem = (unsigned int)MemoryHeap::BlockEndFor(_MenuetMemBlock, size); |
if (_SetUseMemory(_RecalculateUseMemory(use_mem))) |
{ |
res = MemoryHeap::Alloc(_MenuetFreeSpace, size); |
} |
} |
UnLock(&_MemHeapMutex); |
return res; |
} |
void *ReAlloc(void *mem, unsigned int size) |
{ |
Lock(&_MemHeapMutex); |
void *res = MemoryHeap::ReAlloc(_MenuetFreeSpace, mem, size); |
if (!res && size) |
{ |
unsigned use_mem = (unsigned int)MemoryHeap::BlockEndFor(_MenuetMemBlock, size); |
if (_SetUseMemory(_RecalculateUseMemory(use_mem))) |
{ |
res = MemoryHeap::ReAlloc(_MenuetFreeSpace, mem, size); |
} |
} |
UnLock(&_MemHeapMutex); |
return res; |
} |
void Free(void *mem) |
{ |
Lock(&_MemHeapMutex); |
MemoryHeap::Free(_MenuetFreeSpace, mem); |
UnLock(&_MemHeapMutex); |
} |
void _FreeAndThreadFinish(void *mem, int *exit_proc_now); |
} |
#endif // def __MENUET__ |
#endif // ndef __MENUET_HEAP_H_INCLUDED_ |
/programs/demos/life2/include/me_heap.inc |
---|
0,0 → 1,97 |
;/*** |
MenuetHeapInit = @@Menuet@_HeapInit$qpvt1t1 |
MenuetHeapAlloc = @@Menuet@Alloc$qui |
MenuetHeapReAlloc = @@Menuet@ReAlloc$qpvui |
MenuetHeapFree = @@Menuet@Free$qpv |
MenuetHeapFreeAndThreadFinish = @Menuet@_FreeAndThreadFinish$qpvpi |
define @Menuet@_SetUseMemory$qui |
push ebx |
mov eax,64 |
mov ebx,1 |
mov ecx,[esp+8] |
int 0x40 |
pop ebx |
test eax,eax |
jnz Menuet_set_use_memory_nomem |
push ecx |
push dword [@Menuet@_MenuetMemBlock] |
call @@MemoryHeap@ResizeBlock$q20MemoryHeap@TMemBlockpv |
add esp,8 |
mov al,1 |
ret |
Menuet_set_use_memory_nomem: |
xor al,al |
ret |
enddef |
define @Menuet@_RecalculateUseMemory$qui |
mov eax,dword [esp+4] |
mov ecx,(U_END + 3) and not 3 |
cmp eax,ecx |
jna Menuet_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 |
Menuet_recalculate_use_memory_min: |
mov eax,ecx |
ret |
enddef |
define @Menuet@_FreeAndThreadFinish$qpvpi |
mov ebx,1 |
mov ecx,[esp+8] |
jmp Menuet_heap_free_tf_wait |
Menuet_heap_free_tf_wait_loop: |
mov eax,5 |
int 0x40 |
shl ebx,1 |
cmp ebx,MENUET_MUTEX_MAX_TIME_WAIT |
jna Menuet_heap_free_tf_wait |
mov ebx,MENUET_MUTEX_MAX_TIME_WAIT |
Menuet_heap_free_tf_wait: |
cmp dword [ecx],0 |
jnz @Menuet@ExitProcess$qv |
lock bts dword [@Menuet@_MemHeapMutex],0 |
jc Menuet_heap_free_tf_wait_loop |
push dword [esp+4] |
push @Menuet@_MenuetFreeSpace |
call @@MemoryHeap@Free$qr21MemoryHeap@TFreeSpacepv |
add esp,8 |
mov byte [@Menuet@_MemHeapMutex],0x40 |
or eax,-1 |
int 0x40 |
enddef |
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 |
} |
;/**/ |
/programs/demos/life2/include/me_lib.h |
---|
0,0 → 1,16 |
#ifndef __MENUET_LIB_H_INCLUDED_ |
#define __MENUET_LIB_H_INCLUDED_ |
// Menuet interface. |
namespace Menuet // All menuet functions, types and data are nested in the (Menuet) 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 // __MENUET_LIB_H_INCLUDED_ |
/programs/demos/life2/include/me_lib.inc |
---|
0,0 → 1,118 |
define @Menuet@StrLen$qpxc |
push edi |
cld |
mov edi,[esp+8] |
mov ecx,-1 |
xor al,al |
repnz scas byte [edi] |
not ecx |
lea eax,[ecx-1] |
pop edi |
ret |
enddef |
define @Menuet@StrCopy$qpcpxc |
push esi |
push 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] |
pop edi |
pop esi |
ret |
enddef |
define @Menuet@MemCopy$qpvpxvui |
push esi |
push 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] |
pop edi |
pop esi |
ret |
enddef |
define @Menuet@MemSet$qpvcui |
push 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] |
pop edi |
mov eax,[esp+4] |
ret |
enddef |
define __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 |
enddef |
define @Menuet@Floor$qd |
fld qword [esp+4] |
mov ax,[esp+10] |
shl ax,1 |
cmp ax,0x8680 |
ja Menuet_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 |
Menuet_floor_end: |
ret |
enddef |
/programs/demos/life2/include/me_start.inc |
---|
0,0 → 1,90 |
use32 |
org 0x0 |
db 'MENUET01' |
dd 0x1 |
dd MenuetEntryPoint |
dd I_END |
dd U_END+STACKSIZE+HEAPSIZE |
dd U_END+STACKSIZE |
dd @Menuet@CommandLine,0x0 |
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 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,[link] |
{ |
common |
usedef x |
end if |
if x eq |
else if used x |
x: |
usedef link |
} |
/programs/demos/life2/include/memheap.h |
---|
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_ |
/programs/demos/life2/include/menuet.h |
---|
0,0 → 1,537 |
#ifndef __MENUET_H_INCLUDED_ |
#define __MENUET_H_INCLUDED_ |
#include <me_lib.h> |
// Menuet interface. |
namespace Menuet // All menuet functions, types and data are nested in the (Menuet) 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 MenuetOnStart 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 MENUET_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 MENUET_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 (MenuetOnStart). |
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. |
} |
// Function, defined outside. |
bool MenuetOnStart(Menuet::TStartData &me_start, Menuet::TThreadData thread_data); |
// Window will be created iff return value is true. |
bool MenuetOnClose(Menuet::TThreadData thread_data); // Window will be closed iff return value is true. |
int MenuetOnIdle(Menuet::TThreadData thread_data); // Return the time to wait next message. |
void MenuetOnSize(int window_rect[/* 4 */], Menuet::TThreadData thread_data); // When the window is resized. |
void MenuetOnKeyPress(Menuet::TThreadData thread_data); // When user press a key. |
void MenuetOnMouse(Menuet::TThreadData thread_data); // When user move a mouse. |
#ifdef __MENUET__ |
namespace Menuet |
{ |
// Structures. |
struct TMutex // Simple mutex can be locked only once at a time. |
{ |
unsigned int mut; |
}; |
#undef MENUET_MUTEX_INIT |
#define MENUET_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 MENUET_REC_MUTEX_INIT |
#define MENUET_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 = MENUET_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 <me_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[MENUET_THREAD_DATA_X] >> 16); |
start_data.Width = (unsigned short)((unsigned long)thread_data[MENUET_THREAD_DATA_X]); |
start_data.Top = (unsigned short)((unsigned long)thread_data[MENUET_THREAD_DATA_Y] >> 16); |
start_data.Height = (unsigned short)((unsigned long)thread_data[MENUET_THREAD_DATA_Y]); |
GetWindowData(start_data.WinData, thread_data); |
} |
void _SetStartData(const TStartData &start_data, TThreadData thread_data) |
{ |
(unsigned long&)thread_data[MENUET_THREAD_DATA_X] = |
((unsigned int)start_data.Left << 16) | start_data.Width; |
(unsigned long&)thread_data[MENUET_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, 0x03FFFFFF, 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[MENUET_THREAD_DATA_NEXT] = (void*)*thread_table_item; |
(unsigned int&)thread_data[MENUET_THREAD_DATA_PID] = pid; |
*(_TThreadDataTemplate*)(thread_data + MENUET_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[MENUET_THREAD_DATA_FLAG] |= 0x40000000; |
thread_data[MENUET_THREAD_DATA_TITLE] = (void*)(&start_data); |
if (!MenuetOnStart(start_data, thread_data)) return false; |
(unsigned int&)thread_data[MENUET_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[MENUET_THREAD_DATA_NEXT]; |
break; |
} |
thread_table_item = (TThreadData*)(*thread_table_item + MENUET_THREAD_DATA_NEXT); |
} |
UnLock(&_ThreadMutex); |
if (_ExitProcessNow) ExitProcess(); |
} |
void GetWindowData(TWindowData &win_data, TThreadData thread_data) |
{ |
if ((unsigned int)thread_data[MENUET_THREAD_DATA_FLAG] & 0x40000000) |
{ |
win_data = ((TStartData*)thread_data[MENUET_THREAD_DATA_TITLE])->WinData; |
return; |
} |
win_data.WindowType = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_C_WINDOW] >> 24); |
win_data.HeaderType = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_C_HEADER] >> 24); |
win_data.WindowColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_WINDOW] & 0xFFFFFF; |
win_data.HeaderColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_HEADER] & 0xFFFFFF; |
win_data.BorderColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_BORDER] & 0xFFFFFF; |
win_data.TitleColor = (unsigned int)thread_data[MENUET_THREAD_DATA_C_TITLE] & 0xFFFFFF; |
win_data.Title = (char*)thread_data[MENUET_THREAD_DATA_TITLE]; |
} |
void SetWindowData(const TWindowData &win_data, TThreadData thread_data) |
{ |
if ((unsigned int)thread_data[MENUET_THREAD_DATA_FLAG] & 0x40000000) |
{ |
((TStartData*)thread_data[MENUET_THREAD_DATA_TITLE])->WinData = win_data; |
return; |
} |
(unsigned int&)thread_data[MENUET_THREAD_DATA_C_WINDOW] = |
((unsigned int)win_data.WindowType << 24) | (win_data.WindowColor & 0xFFFFFF); |
(unsigned int&)thread_data[MENUET_THREAD_DATA_C_HEADER] = |
((unsigned int)win_data.HeaderType << 24) | (win_data.HeaderColor & 0xFFFFFF); |
(unsigned int&)thread_data[MENUET_THREAD_DATA_C_BORDER] = win_data.BorderColor & 0xFFFFFF; |
(unsigned int&)thread_data[MENUET_THREAD_DATA_C_TITLE] = win_data.TitleColor & 0xFFFFFF; |
thread_data[MENUET_THREAD_DATA_TITLE] = (void*)win_data.Title; |
Invalidate(1, thread_data); |
} |
void CloseWindow(TThreadData thread_data) |
{ |
(unsigned int&)thread_data[MENUET_THREAD_DATA_FLAG] |= 0x80000000; |
} |
void Invalidate(int frame, TThreadData thread_data) |
{ |
if (frame < 0) return; |
(unsigned int&)thread_data[MENUET_THREAD_DATA_FLAG] |= (frame ? 3 : 1); |
} |
void* GetPicture(unsigned short &width, unsigned short &height, TThreadData thread_data) |
{ |
width = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_SZ_PICT] >> 16); |
height = (unsigned short)((unsigned int)thread_data[MENUET_THREAD_DATA_SZ_PICT]); |
return (void*)thread_data[MENUET_THREAD_DATA_PICTURE]; |
} |
void SetPicture(void *picture, unsigned short width, unsigned short height, TThreadData thread_data) |
{ |
thread_data[MENUET_THREAD_DATA_PICTURE] = (void*)picture; |
(unsigned int&)thread_data[MENUET_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[MENUET_THREAD_DATA_FLAG] & 0x40000000) ? |
((TStartData*)thread_data[MENUET_THREAD_DATA_TITLE])->WinData.WindowType : |
((unsigned int)thread_data[MENUET_THREAD_DATA_C_WINDOW] >> 24); |
border_size = MENUET_BORDER_SIZE; |
header_size = short(((win_type & 15) == 3) ? _GetSkinHeader() : MENUET_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 __MENUET__ |
namespace Menuet |
{ |
struct TMutex |
{ |
unsigned int mut; |
TMutex(); |
~TMutex(); |
}; |
#undef MENUET_MUTEX_INIT |
#define MENUET_MUTEX_INIT TMutex() |
struct TRecMutex |
{ |
unsigned int mut; |
TRecMutex(); |
~TRecMutex(); |
}; |
#undef MENUET_REC_MUTEX_INIT |
#define MENUET_REC_MUTEX_INIT TRecMutex() |
} |
#endif // else: def __MENUET__ |
#endif // ndef __MENUET_H_INCLUDED_ |
/programs/demos/life2/include/menuet_win.cpp |
---|
0,0 → 1,921 |
#include <windows.h> |
#include <string.h> |
#include <process.h> |
#include <stdio.h> |
#include <math.h> |
#include <assert.h> |
#include <deque.h> |
#include <menuet.h> |
#include <me_heap.h> |
#include <me_file.h> |
using namespace Menuet; |
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[] = "Menuet 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 (MenuetOnIdle((TThreadData)(&ThreadDataStruct)) == 0 && |
GetTickCount() - t + 2 < timeout); |
return 0; |
case WM_MOUSEMOVE: |
MenuetOnMouse((TThreadData)(&ThreadDataStruct)); |
return 0; |
case WM_LBUTTONDOWN: |
if (!ThreadDataStruct.mouse_state) SetCapture(hWnd); |
ThreadDataStruct.mouse_state |= 1; |
MenuetOnMouse((TThreadData)(&ThreadDataStruct)); |
return 0; |
case WM_LBUTTONUP: |
if (ThreadDataStruct.mouse_state & 1) |
{ |
ThreadDataStruct.mouse_state &= ~1; |
if (!ThreadDataStruct.mouse_state) ReleaseCapture(); |
MenuetOnMouse((TThreadData)(&ThreadDataStruct)); |
} |
return 0; |
case WM_RBUTTONDOWN: |
if (!ThreadDataStruct.mouse_state) SetCapture(hWnd); |
ThreadDataStruct.mouse_state |= 2; |
MenuetOnMouse((TThreadData)(&ThreadDataStruct)); |
return 0; |
case WM_RBUTTONUP: |
if (ThreadDataStruct.mouse_state & 2) |
{ |
ThreadDataStruct.mouse_state &= ~2; |
if (!ThreadDataStruct.mouse_state) ReleaseCapture(); |
MenuetOnMouse((TThreadData)(&ThreadDataStruct)); |
} |
return 0; |
case WM_CAPTURECHANGED: |
if (ThreadDataStruct.mouse_state) |
{ |
ThreadDataStruct.mouse_state = 0; |
MenuetOnMouse((TThreadData)(&ThreadDataStruct)); |
} |
return 0; |
//case WM_SYSKEYDOWN: case WM_KEYDOWN: |
case WM_CHAR: |
ThreadDataStruct.keys->push_back((unsigned char)wParam); |
MenuetOnKeyPress((TThreadData)(&ThreadDataStruct)); |
return 0; |
case WM_SIZE: |
GetProcessInfo(0, 0, 0, 0, window_rect); |
MenuetOnSize(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 (MenuetOnClose((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 Menuet |
{ |
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 (MenuetOnStart(start_data, (TThreadData)(&ThreadDataStruct))) |
{ |
while (ThreadDataStruct.flag < 0) |
{ |
ThreadDataStruct.flag &= ~0x80000000; |
if (MenuetOnClose((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; |
} |
/programs/demos/life2/include/write_macro.inc |
---|
0,0 → 1,49 |
macro writestr [arg] |
{ |
common |
local straddr |
local strend |
pushad |
push straddr |
push strend |
jmp @Menuet@DebugPutString$qpxc |
straddr db arg,0 |
strend: |
pop eax |
popad |
} |
macro writeint arg |
{ |
push dword arg |
xchg eax,[esp] |
pushad |
push eax |
call @DebugPutNumber$qi |
pop eax |
popad |
pop eax |
} |
macro write [arg] |
{ |
forward |
if arg eq |
else if arg eq endline |
writestr 10 |
else if arg eqtype '' |
writestr arg |
else |
writeint arg |
end if |
} |
macro writeln [arg] |
{ |
common |
write arg,endline |
} |
/programs/demos/life2/include/. |
---|
Property changes: |
Added: tsvn:logminsize |
+5 |
\ No newline at end of property |