Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 1768 → Rev 1769

/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