956 lines
19 KiB
PHP
956 lines
19 KiB
PHP
|
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$
|
||
|
; *************** STAR^2 SOFTWARE ****************
|
||
|
; ????????????????? SYSTEM.INC ???????????????????
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;; IMPORT ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
; RVAs of dll names and tables, ending with 20
|
||
|
; zero bytes
|
||
|
|
||
|
macro library [names] {
|
||
|
forward dd 0,0,0,\
|
||
|
RVA names#_name, RVA names#_table
|
||
|
common dd 0,0,0,0,0
|
||
|
}
|
||
|
|
||
|
; DLL name + import RVA table. each table ends with 0.
|
||
|
; finally, import names. dw 0 is "ordinal" (N/A)
|
||
|
|
||
|
macro import name, [names] {
|
||
|
common
|
||
|
name#_name \ ; text DLL_name='DLL.DLL'
|
||
|
db `name#'.DLL', 0
|
||
|
name#_table: ; DLL_table:
|
||
|
forward
|
||
|
IF used !#names
|
||
|
!#names dd RVA _#names ; import name RVAs
|
||
|
macro names [p] \{ ; call with no
|
||
|
\common ; invoke prefix
|
||
|
pushr p
|
||
|
call [!#names]
|
||
|
\}
|
||
|
END IF
|
||
|
common dd 0 ; end
|
||
|
forward
|
||
|
IF used !#names
|
||
|
_#names dw 0 ; import names
|
||
|
db `names, 0 ; 'import'
|
||
|
END IF
|
||
|
}
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;; IMPORTS ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
data import
|
||
|
|
||
|
library MSVCRT, KERNEL32, USER32, SHELL32,\
|
||
|
GDI32, COMDLG32
|
||
|
|
||
|
import MSVCRT, sprintf
|
||
|
|
||
|
import KERNEL32,\
|
||
|
ExitProcess, GetCommandLineA,\
|
||
|
HeapCreate, HeapAlloc, HeapReAlloc, HeapSize,\
|
||
|
HeapFree, HeapDestroy, VirtualAlloc, VirtualFree,\
|
||
|
GetModuleHandleA, GetModuleFileNameA,\
|
||
|
CreateFileA, GetFileSize, ReadFile, WriteFile,\
|
||
|
SetFilePointer, CloseHandle, CopyFileA,\
|
||
|
MoveFileA, DeleteFileA, GetTickCount,\
|
||
|
GetSystemTime, GetLocalTime, GetFileTime,\
|
||
|
FileTimeToSystemTime, SystemTimeToFileTime,\
|
||
|
FileTimeToLocalFileTime,\
|
||
|
SystemTimeToTzSpecificLocalTime,\
|
||
|
GetFileAttributesExA, CompareFileTimeA,\
|
||
|
GetCurrentDirectoryA, SetCurrentDirectoryA,\
|
||
|
CreateDirectoryA, LoadLibraryA, FreeLibrary,\
|
||
|
GetProcAddress, FindFirstFileA, FindNextFileA,\
|
||
|
FindClose, WaitForSingleObject, Sleep
|
||
|
|
||
|
import USER32,\
|
||
|
GetDC, ReleaseDC,\
|
||
|
MessageBoxA, RegisterClassExA, CreateWindowExA,\
|
||
|
DestroyWindow, ShowWindow, MoveWindow,\
|
||
|
UpdateWindow, GetMessageA, PeekMessageA,\
|
||
|
TranslateMessage, DispatchMessageA,\
|
||
|
SendMessageA, DefWindowProcA, PostQuitMessage,\
|
||
|
WaitMessage, GetAsyncKeyState, LoadImageA,\
|
||
|
LoadIconA, LoadCursorA, SetCursor, ShowCursor,\
|
||
|
SetCursorPos, OpenClipboard, SetClipboardData,\
|
||
|
IsClipboardFormatAvailable, GetClipboardData,\
|
||
|
CloseClipboard, EmptyClipboard,\
|
||
|
GetSystemMetrics, BeginPaint, EndPaint,\
|
||
|
FillRect, InvalidateRect, SetTimer
|
||
|
|
||
|
import SHELL32, ShellExecuteA, ShellExecuteExA
|
||
|
|
||
|
import GDI32, SelectObject, DeleteObject,\
|
||
|
GetObjectA, DeleteDC, TextOutA, CreateFontA,\
|
||
|
CreateFontIndirectA, SetDIBits, BitBlt, StretchBlt,\
|
||
|
CreateBitmap, CreateCompatibleDC
|
||
|
|
||
|
import COMDLG32, GetOpenFileNameA,\
|
||
|
GetSaveFileNameA, ChooseColorA, ChooseFontA
|
||
|
|
||
|
END data
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;; SYSTEM ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
align
|
||
|
|
||
|
void @module, @heap
|
||
|
|
||
|
void directory, file.name, command.line
|
||
|
|
||
|
?t equ directory
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;; MINIMAL ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
; say t - display message
|
||
|
; say t, m - title and message
|
||
|
; say.n n - number
|
||
|
|
||
|
; examples:
|
||
|
|
||
|
; say 'Hi'
|
||
|
; say name
|
||
|
; say.n 123
|
||
|
|
||
|
macro os.say t, m { MessageBoxA 0, m, t, 0 }
|
||
|
|
||
|
macro os.ask q, t { MessageBoxA, 0, q, t, 3 }
|
||
|
|
||
|
function _say, t, m
|
||
|
os.say t, m
|
||
|
endf
|
||
|
|
||
|
macro say a, b {
|
||
|
pusha
|
||
|
IF a eqtype ''
|
||
|
make.txt r0, a
|
||
|
ELSE
|
||
|
. r0=a
|
||
|
END IF
|
||
|
IF b eq
|
||
|
_say r0, r0
|
||
|
ELSE
|
||
|
IF b eqtype ''
|
||
|
make.txt r2, b
|
||
|
ELSE
|
||
|
. r2=b
|
||
|
END IF
|
||
|
_say r2, r0
|
||
|
END IF
|
||
|
popa
|
||
|
}
|
||
|
|
||
|
function say.n, n
|
||
|
locale t(32)
|
||
|
pusha
|
||
|
. r1=&t
|
||
|
u2t n, r1
|
||
|
. r1=&t
|
||
|
_say r1, r1
|
||
|
popa
|
||
|
endf
|
||
|
|
||
|
function say.h, n
|
||
|
locale t(32)
|
||
|
pusha
|
||
|
. r1=&t
|
||
|
h2t n, r1
|
||
|
. r1=&t
|
||
|
_say r1, r1
|
||
|
popa
|
||
|
endf
|
||
|
|
||
|
function say.b, n
|
||
|
locale t(32)
|
||
|
pusha
|
||
|
. r1=&t
|
||
|
b2t n, r1
|
||
|
. r1=&t
|
||
|
_say r1, r1
|
||
|
popa
|
||
|
endf
|
||
|
|
||
|
macro sayz t {
|
||
|
say ?LITERALS+?literals.i
|
||
|
?literal t
|
||
|
}
|
||
|
|
||
|
macro ask q, t { os.ask q, t }
|
||
|
|
||
|
macro cinvoke proc,[arg]
|
||
|
{ common
|
||
|
size@ccall = 0
|
||
|
IF ~ arg eq
|
||
|
reverse
|
||
|
pushd arg
|
||
|
size@ccall = size@ccall+4
|
||
|
common
|
||
|
END IF
|
||
|
call [proc]
|
||
|
IF size@ccall
|
||
|
add esp,size@ccall
|
||
|
END IF }
|
||
|
|
||
|
macro sprintf t, f, [p] {
|
||
|
common
|
||
|
cinvoke !sprintf, t, f, p
|
||
|
}
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;; DEBUG ;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
bug.t db 'BUG', 0
|
||
|
|
||
|
macro bug { say bug.t }
|
||
|
|
||
|
macro bug.x t {
|
||
|
log t
|
||
|
execute log.file
|
||
|
exit
|
||
|
}
|
||
|
|
||
|
macro BUG { db 0CCh } ; int3 breakpoint
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;; MEMORY ;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
macro os.memory
|
||
|
{ get @heap=HeapCreate 0, 0, 0 }
|
||
|
|
||
|
macro os.allocate n { HeapAlloc @heap, 0, n }
|
||
|
|
||
|
macro os.reallocate p, n
|
||
|
{ HeapReAlloc @heap, 0, p, n }
|
||
|
|
||
|
macro os.destroy p { HeapFree @heap, 0, p }
|
||
|
|
||
|
;;;;;;;;;;;;;;; ALLOCATE, DESTROY ;;;;;;;;;;;;;;;;
|
||
|
|
||
|
; allocate n
|
||
|
; allocate.p &p, n
|
||
|
; destroy &p
|
||
|
|
||
|
; example: try p=allocate 4*KB
|
||
|
|
||
|
function allocate, n
|
||
|
os.allocate n
|
||
|
endf
|
||
|
|
||
|
function allocate.p, p, n
|
||
|
if p=0
|
||
|
allocate n
|
||
|
return
|
||
|
end
|
||
|
os.reallocate p, n
|
||
|
endf
|
||
|
|
||
|
function destroy, p
|
||
|
if p
|
||
|
os.destroy p
|
||
|
end
|
||
|
endf
|
||
|
|
||
|
macro destroy [p] { forward destroy p }
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;; TIME ;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
FILE.TIME fix u64
|
||
|
|
||
|
macro os.get.time {
|
||
|
GetLocalTime local.time
|
||
|
update.time local.time
|
||
|
}
|
||
|
|
||
|
function os.delay, ms
|
||
|
locals start
|
||
|
get start=GetTickCount
|
||
|
@@:
|
||
|
GetTickCount
|
||
|
. r1=start, r1+ms
|
||
|
cmp r0, r1
|
||
|
jb @b
|
||
|
endf
|
||
|
|
||
|
get.clock fix GetTickCount
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;; RANDOM ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
align integer @seed
|
||
|
|
||
|
; generate unique random number: 0-n
|
||
|
|
||
|
; seed=(seed*343FDh)+269EC3h
|
||
|
; seed=((seed>>16)&7FFFh)/(n+1)
|
||
|
|
||
|
function random, n
|
||
|
. r0=@seed
|
||
|
if false ; initialize seed
|
||
|
rdtsc ; read date/time stamp counter
|
||
|
. @seed=r0
|
||
|
end
|
||
|
. r0*343FDh, r0+269EC3h,\
|
||
|
@seed=r0, r0>>16, r0&7FFFh,\
|
||
|
r1=n, r1+1, r0/r1, r0=r2
|
||
|
endf
|
||
|
|
||
|
; random(from-to-2)+from
|
||
|
|
||
|
function random.x, from, to
|
||
|
. r0=from, r0-to, r0-2
|
||
|
random r0
|
||
|
. r0+from
|
||
|
endf
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;; FILE I/O ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
numeric EOF=-1,\
|
||
|
CREATE_NEW=1, CREATE_ALWAYS, OPEN_EXISTING,\
|
||
|
OPEN_ALWAYS, TRUNCATE_EXISTING,\
|
||
|
GENERIC_READ=80000000h, GENERIC_WRITE=40000000h,\
|
||
|
FILE_SHARE_READ=1, FILE_SHARE_WRITE,\
|
||
|
FILE_ATTRIBUTE_NORMAL=80h,\
|
||
|
SEEK.BEGIN=0, SEEK.SET, SEEK.END
|
||
|
|
||
|
;;;;;;;;;;;;;;;;; CURRENT FILE ;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
align
|
||
|
|
||
|
void file.p ; pointer for load/save
|
||
|
integer file.h,\ ; handle
|
||
|
file.n64, file.n ; size 64:32
|
||
|
integer tmp.rw
|
||
|
|
||
|
macro flush { destroy file.p }
|
||
|
|
||
|
; return handle or -1 if error
|
||
|
|
||
|
function os.create.file, file, access, share,\
|
||
|
security, action, attributes, template
|
||
|
call !text.copy, file.name, file
|
||
|
CreateFileA file.name, access, share,\
|
||
|
security, action, attributes, template
|
||
|
. file.h=r0
|
||
|
endf
|
||
|
|
||
|
macro os.open file {
|
||
|
os.create.file file, GENERIC_READ \
|
||
|
or GENERIC_WRITE, FILE_SHARE_READ,\
|
||
|
0, OPEN_EXISTING, 0, 0
|
||
|
}
|
||
|
|
||
|
macro os.create file {
|
||
|
os.create.file file, GENERIC_WRITE,\
|
||
|
0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
|
||
|
}
|
||
|
|
||
|
macro os.seek n, r
|
||
|
{ SetFilePointer file.h, n, 0, r }
|
||
|
|
||
|
macro os.read p, n {
|
||
|
. r0=&tmp.rw
|
||
|
ReadFile file.h, p, n, r0, 0
|
||
|
}
|
||
|
|
||
|
macro os.write p, n {
|
||
|
. r0=&tmp.rw
|
||
|
WriteFile file.h, p, n, r0, 0
|
||
|
}
|
||
|
|
||
|
macro os.get.file.size { GetFileSize file.h, 0 }
|
||
|
|
||
|
macro os.close { CloseHandle file.h }
|
||
|
|
||
|
;;;;;;;;;;;;;;; COPY, MOVE, DELETE ;;;;;;;;;;;;;;;
|
||
|
|
||
|
macro copy.file a, b, r { CopyFileA a, b, r }
|
||
|
macro move.file a, b { MoveFileA a, b }
|
||
|
macro delete.file f { DeleteFileA f }
|
||
|
macro rename.file a, b { os.move.file a, b }
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;; DIRECTORIES ;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
macro os.get.directory
|
||
|
{ GetCurrentDirectoryA 256, directory }
|
||
|
|
||
|
macro os.set.directory f
|
||
|
{ SetCurrentDirectoryA f }
|
||
|
|
||
|
macro os.create.directory f
|
||
|
{ CreateDirectoryA f, 0 }
|
||
|
|
||
|
macro os.get.file.name
|
||
|
{ GetModuleFileNameA 0, directory, 1*KB }
|
||
|
|
||
|
macro os.get.command.line { GetCommandLineA }
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;; EXECUTE ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
macro execute file
|
||
|
{ ShellExecuteA 0, 0, file, 0, 0, 3 }
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;; FIND FILES ;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
macro os.find.data {
|
||
|
BLOCK find.data(338) ; WIN32_FIND_DATA
|
||
|
os.found.file equ find.data+44
|
||
|
}
|
||
|
|
||
|
macro os.find.first file
|
||
|
{ FindFirstFileA file, find.data }
|
||
|
|
||
|
macro os.find.next
|
||
|
{ FindNextFileA find.data.h, find.data }
|
||
|
|
||
|
macro os.find.end { FindClose find.data.h }
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;; REDRAW ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
macro create.blank.screen w, h {
|
||
|
create.vga os.w, os.h, WHITE ; 0
|
||
|
create.blank.window w, h
|
||
|
}
|
||
|
|
||
|
macro redraw {
|
||
|
calle draw
|
||
|
}
|
||
|
|
||
|
macro render b {
|
||
|
; call !clear.screen
|
||
|
IF b eq
|
||
|
redraw
|
||
|
END IF
|
||
|
IF used cursor
|
||
|
call !draw.cursor, cursor
|
||
|
END IF
|
||
|
IF b eq
|
||
|
call !show.vga
|
||
|
ELSE
|
||
|
copy.box box, b
|
||
|
call !show.vga.box
|
||
|
END IF
|
||
|
}
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;; WINDOZE ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
macro POINT [a] { a: integer a#.x, a#.y }
|
||
|
|
||
|
macro RECT [a] { a: integer a#.left,\
|
||
|
a#.top, a#.right, a#.bottom }
|
||
|
|
||
|
macro MSG [a] {
|
||
|
a: integer a#.hwnd, a#.message,\
|
||
|
a#.wParam, a#.lParam, a#.time
|
||
|
POINT a#.pt
|
||
|
}
|
||
|
|
||
|
macro WNDCLASSEX [a] {
|
||
|
a: integer a#.cbSize=48,\
|
||
|
a#.style, a#.lpfnWndProc, a#.cbClsExtra,\
|
||
|
a#.cbWndExtra, a#.hInstance, a#.hIcon,\
|
||
|
a#.hCursor, a#.hbrBackground,\
|
||
|
a#.lpszMenuName, a#.lpszClassName, a#.hIconSm
|
||
|
WNDCLASSEX.$=$-a
|
||
|
}
|
||
|
|
||
|
macro PAINTSTRUCT [a] {
|
||
|
a: integer a#.hdc, a#.fErase
|
||
|
RECT a#.rcPaint
|
||
|
integer a#.fRestore, a#.fIncUpdate
|
||
|
text a#.rgbReserved(32)
|
||
|
}
|
||
|
|
||
|
macro BITMAP [a] {
|
||
|
a: integer a#.bmType,\
|
||
|
a#.bmWidth, a#.bmHeight, a#.bmWidthBytes
|
||
|
short a#.bmPlanes, a#.bmBitsPixel
|
||
|
void a#.bmBits
|
||
|
BITMAP.$=$-a
|
||
|
}
|
||
|
|
||
|
macro BITMAPINFOHEADER [a] {
|
||
|
a: integer a#.biSize, a#.biWidth, a#.biHeight
|
||
|
short a#.biPlanes, a#.biBitCount
|
||
|
integer a#.biCompression, a#.biSizeImage,\
|
||
|
a#.biXPelsPerMeter, a#.biYPelsPerMeter,\
|
||
|
a#.biClrUsed, a#.biClrImportant
|
||
|
BITMAPINFOHEADER.$=$-a
|
||
|
}
|
||
|
|
||
|
macro BITMAPINFO [a] {
|
||
|
BITMAPINFOHEADER a
|
||
|
integer bmiColors
|
||
|
BITMAPINFO.$=BITMAPINFOHEADER.$+4
|
||
|
}
|
||
|
|
||
|
; window messages
|
||
|
|
||
|
numeric WM_*, \
|
||
|
CREATE=1, DESTROY=2, MOVE=3, SIZE=5,\
|
||
|
SETFOCUS=7, KILLFOCUS=8, GETTEXT=0Dh,\
|
||
|
SETTEXT=0Ch, GETTEXTLENGTH=0Eh,\
|
||
|
PAINT=0Fh, CLOSE=10h, QUIT=12h, CUT=300h,\
|
||
|
COPY=301h, PASTE=302h, CLEAR=303h,\
|
||
|
SETFONT=30h, COMMAND=111h, TIMER=0113h
|
||
|
|
||
|
; window styles
|
||
|
|
||
|
numeric WS_*, \
|
||
|
POPUP=80000000h, MINIMIZE=20000000h,\
|
||
|
VISIBLE=10000000h, MAXIMIZE=1000000h,\
|
||
|
CAPTION=0C00000h, BORDER=800000h,\
|
||
|
DLGFRAME=400000h, VSCROLL=200000h,\
|
||
|
HSCROLL=100000h, SYSMENU=80000h,\
|
||
|
THICKFRAME=40000h, MINIMIZEBOX=20000h,\
|
||
|
MAXIMIZEBOX=10000h
|
||
|
|
||
|
WS_BLANK = WS_VISIBLE+WS_POPUP
|
||
|
WS_DEFAULT = WS_VISIBLE+WS_CAPTION+\
|
||
|
WS_MINIMIZEBOX+WS_SYSMENU
|
||
|
|
||
|
CS_DBLCLKS=8
|
||
|
|
||
|
; keyboard+mouse messages
|
||
|
|
||
|
numeric WM_*,\
|
||
|
KEYDOWN=100h, KEYUP, CHAR, DEADCHAR,\
|
||
|
SYSKEYDOWN, SYSKEYUP, SYSCHAR
|
||
|
|
||
|
numeric WM_*,\
|
||
|
MOUSEMOVE=200h, LBUTTONDOWN, LBUTTONUP,\
|
||
|
LBUTTONDBLCLK, RBUTTONDOWN, RBUTTONUP,\
|
||
|
RBUTTONDBLCLK, MBUTTONDOWN, MBUTTONUP,\
|
||
|
MBUTTONDBLCLK, MOUSEWHEEL
|
||
|
|
||
|
; virtual key codes. function keys=(6Fh+N).
|
||
|
; example: F1=70h (6Fh+1)
|
||
|
|
||
|
numeric K.*,\
|
||
|
FUNCTION=6Fh, LEFT=25h, UP=26h, RIGHT=27h,\
|
||
|
DOWN=28h, ESCAPE=1Bh, SPACE=20h, DELETE=2Eh,\
|
||
|
CONTROL=11h, LCONTROL=0A2h, RCONTROL=0A3h,\
|
||
|
LALT=0A4h, RALT=0A5h, BACK=8, TAB=9,\
|
||
|
RETURN=0Dh, END=23h, HOME=24h,\
|
||
|
A='A', S='S', D='D', W='W'
|
||
|
|
||
|
SRCCOPY=00CC0020h
|
||
|
|
||
|
macro os.show.cursor { ShowCursor 1 }
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;; SYSTEM ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
align
|
||
|
|
||
|
integer os.w, os.h, os.bpp
|
||
|
|
||
|
void _hwnd ; handle
|
||
|
void _dc ; device context
|
||
|
void _mdc ; memory dc
|
||
|
|
||
|
WNDCLASSEX _wc ; window
|
||
|
MSG _wm ; message
|
||
|
PAINTSTRUCT _ps ; for PAINT
|
||
|
BITMAP _bm ; for draw.bitmap.w
|
||
|
|
||
|
void vga.hbm
|
||
|
BITMAPINFO vga.bmi
|
||
|
RECT vga.rect
|
||
|
|
||
|
text _cn='WC', _wt='' ; classname, title
|
||
|
|
||
|
;;;;;;;;;;;;;;;;; CREATE WINDOW ;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
function create.window.x, style, procedure,\
|
||
|
w, h, title, class.name
|
||
|
locals x, y
|
||
|
|
||
|
. _wc.cbSize=WNDCLASSEX.$
|
||
|
. _wc.hInstance=@module
|
||
|
. _wc.lpfnWndProc=procedure
|
||
|
. _wc.lpszClassName=class.name
|
||
|
. _wc.style=CS_DBLCLKS, _wc.hbrBackground=8
|
||
|
get _wc.hIcon=LoadIconA 0, 7F00h
|
||
|
get _wc.hCursor=LoadCursorA 0, 7F00h
|
||
|
|
||
|
try RegisterClassExA _wc
|
||
|
|
||
|
. r0=os.w, r0>>1, r2=w, r2>>1, r0-r2, x=r0
|
||
|
. r0=os.h, r0>>1, r2=h, r2>>1, r0-r2, y=r0
|
||
|
|
||
|
try _hwnd=CreateWindowExA 0, class.name,\
|
||
|
title, style, x, y, w, h, 0, 0, @module, 0
|
||
|
endf 1
|
||
|
|
||
|
macro create.blank.window w, h {
|
||
|
create.window.x WS_BLANK, !_window.procedure,\
|
||
|
w, h, _wt, _wc
|
||
|
}
|
||
|
|
||
|
macro create.default.window title {
|
||
|
create.window.x WS_DEFAULT, !_window.procedure,\
|
||
|
os.w, os.h, title, _wc
|
||
|
}
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;; MESSAGE LOOP ;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
macro begin.message.loop {
|
||
|
.begin.ml:
|
||
|
GetMessageA _wm, 0, 0, 0
|
||
|
fail .end.ml
|
||
|
TranslateMessage _wm
|
||
|
DispatchMessageA _wm
|
||
|
}
|
||
|
|
||
|
macro end.message.loop {
|
||
|
go .begin.ml
|
||
|
.end.ml:
|
||
|
. r0=_wm.wParam
|
||
|
}
|
||
|
|
||
|
macro message.loop {
|
||
|
begin.message.loop
|
||
|
end.message.loop
|
||
|
}
|
||
|
|
||
|
macro process.messages {
|
||
|
.begin.ml:
|
||
|
PeekMessageA _wm, 0, 0, 0, 0
|
||
|
fail .no.message
|
||
|
GetMessageA _wm, 0, 0, 0
|
||
|
fail .end.ml
|
||
|
TranslateMessage _wm
|
||
|
DispatchMessageA _wm
|
||
|
go .begin.ml
|
||
|
.no.message:
|
||
|
}
|
||
|
|
||
|
macro end.messages {
|
||
|
go .begin.ml
|
||
|
.end.ml:
|
||
|
ExitProcess _wm.wParam
|
||
|
}
|
||
|
|
||
|
macro minimize.window { ShowWindow _hwnd, 6 }
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;; INPUT ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
align 4
|
||
|
|
||
|
integer event.id, key.event, mouse.event,\
|
||
|
key, any.key, key.c, exit.if.esc=YES,\
|
||
|
mouse.1, mouse.2, mouse.x, mouse.y,\
|
||
|
mouse.px, mouse.py, mouse.double, mouse.wheel,\
|
||
|
mouse.drag, mouse.drag.x, mouse.drag.y,\
|
||
|
mouse.drop, mouse.drop.x, mouse.drop.y
|
||
|
|
||
|
macro os.key.state k { GetAsyncKeyState k }
|
||
|
|
||
|
macro os.set.cursor.xy x, y
|
||
|
{ SetCursorPos x, y }
|
||
|
|
||
|
function key.state, k
|
||
|
os.key.state k
|
||
|
endf
|
||
|
|
||
|
; if key state
|
||
|
|
||
|
macro if.key k { !if key.state K.#k }
|
||
|
macro if.not.keys k { !if.n key.state K.#k }
|
||
|
|
||
|
function select.box, box
|
||
|
. r0=mouse.x, r1=mouse.y
|
||
|
IF defined cursor
|
||
|
. r0+cursor.spot.x, r1+cursor.spot.y
|
||
|
END IF
|
||
|
call !point.inside, box, r0, r1
|
||
|
endf
|
||
|
|
||
|
macro if.select box { !if select.box, box }
|
||
|
macro else.if.select box
|
||
|
{ !else.if select.box, box }
|
||
|
|
||
|
macro if.not.select box
|
||
|
{ !if.n select.box, box }
|
||
|
|
||
|
macro if.click box {
|
||
|
select.box box
|
||
|
and r0, mouse.1
|
||
|
if true
|
||
|
}
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;; EVENTS ;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
align
|
||
|
void !_on.event, !on.main,\
|
||
|
!_on.create, !_on.destroy, !_on.close,\
|
||
|
!_on.draw, !_on.game, !_on.command,\
|
||
|
!_on.key, !_on.mouse, !_on.timer, !_on.exit
|
||
|
|
||
|
macro define.events [e]
|
||
|
{ mov [!!_on.#e], !on.#e }
|
||
|
|
||
|
macro calle e {
|
||
|
if dword [!!_on.#e]
|
||
|
call dword [!!_on.#e]
|
||
|
end
|
||
|
}
|
||
|
|
||
|
!call fix calle
|
||
|
|
||
|
macro !on name { function on.#name }
|
||
|
macro !end { endf 1 }
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;; TIMER ;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
macro os.set.timer f, ms
|
||
|
{ SetTimer _hwnd, 1, ms, f }
|
||
|
|
||
|
macro set.timer a, b {
|
||
|
IF b eq
|
||
|
os.set.timer !on.timer, a
|
||
|
ELSE
|
||
|
os.set.timer a, b
|
||
|
END IF
|
||
|
}
|
||
|
|
||
|
;;;;;;;;;;;;;;;; WINDOW PROCEDURE ;;;;;;;;;;;;;;;;
|
||
|
|
||
|
function _window.procedure, window, message, wp, lp
|
||
|
alias m=r0
|
||
|
. m=message, event.id=0, mouse.double=0
|
||
|
|
||
|
if m=WM_PAINT
|
||
|
get _dc=BeginPaint _hwnd, _ps
|
||
|
render
|
||
|
EndPaint _hwnd, _ps
|
||
|
go .default
|
||
|
|
||
|
else.if m=WM_COMMAND
|
||
|
calle command
|
||
|
|
||
|
else.if m=WM_KEYDOWN
|
||
|
. key=wp, event.id='k', key.event='k'
|
||
|
if exit.if.esc
|
||
|
if wp=K.ESCAPE
|
||
|
SendMessageA window, WM_DESTROY, 0, 0
|
||
|
end
|
||
|
end
|
||
|
.key:
|
||
|
calle key
|
||
|
return 0
|
||
|
|
||
|
else.if m=WM_KEYUP
|
||
|
. key=NO, event.id='k', key.event='r'
|
||
|
go .key
|
||
|
|
||
|
else.if m=WM_CHAR
|
||
|
. key=wp, event.id='k', key.event='c'
|
||
|
go .key
|
||
|
|
||
|
else.if m=WM_MOUSEMOVE
|
||
|
. mouse.event='m'
|
||
|
if mouse.1
|
||
|
if not mouse.drag
|
||
|
. mouse.drag=YES,\
|
||
|
mouse.drag.x=mouse.x,\
|
||
|
mouse.drag.y=mouse.y
|
||
|
end
|
||
|
end
|
||
|
.mouse:
|
||
|
. event.id='m', r0=lp, r1=r0,\
|
||
|
r0&0FFFFh, mouse.x=r0,\
|
||
|
r1>>16, r1&0FFFFh, mouse.y=r1
|
||
|
calle mouse
|
||
|
if mouse.event='m'
|
||
|
. mouse.px=mouse.x,\
|
||
|
mouse.py=mouse.y
|
||
|
end
|
||
|
return 0
|
||
|
|
||
|
else.if m=WM_LBUTTONDOWN
|
||
|
. mouse.event='c', mouse.1=YES,\
|
||
|
mouse.drop=NO
|
||
|
go .mouse
|
||
|
|
||
|
else.if m=WM_LBUTTONUP
|
||
|
. mouse.event='r', mouse.1=NO
|
||
|
if mouse.drag
|
||
|
. mouse.drop=YES,\
|
||
|
mouse.drop.x=mouse.x,\
|
||
|
mouse.drop.y=mouse.y,\
|
||
|
mouse.drag=NO
|
||
|
end
|
||
|
go .mouse
|
||
|
|
||
|
else.if m=WM_LBUTTONDBLCLK
|
||
|
. mouse.double=YES
|
||
|
go .mouse
|
||
|
|
||
|
else.if m=WM_RBUTTONDOWN
|
||
|
. mouse.event='rc', mouse.2=YES
|
||
|
go .mouse
|
||
|
|
||
|
else.if m=WM_RBUTTONUP
|
||
|
. mouse.event='rr', mouse.2=NO
|
||
|
go .mouse
|
||
|
|
||
|
else.if m=WM_MOUSEWHEEL
|
||
|
. mouse.event='w', r1=wp,\
|
||
|
r1>>16, mouse.wheel=r1
|
||
|
go .mouse
|
||
|
|
||
|
else.if m=WM_CREATE
|
||
|
calle create
|
||
|
go .default
|
||
|
|
||
|
else.if m=WM_DESTROY
|
||
|
.destroy:
|
||
|
calle destroy
|
||
|
PostQuitMessage 0
|
||
|
end
|
||
|
|
||
|
.default: DefWindowProcA \
|
||
|
window, message, wp, lp
|
||
|
endf
|
||
|
|
||
|
;;;;;;;;;;;;;;; LOAD/DRAW H/BITMAP ;;;;;;;;;;;;;;;
|
||
|
|
||
|
function load.bitmap.w, file
|
||
|
locals p
|
||
|
try p=LoadImageA @module, file, 0, 0, 0, 10h
|
||
|
GetObjectA p, BITMAP.$, _bm
|
||
|
endf p
|
||
|
|
||
|
function draw.bitmap.w, hbmp, x, y, w, h
|
||
|
locals bmw, bmh
|
||
|
GetObjectA hbmp, BITMAP.$, _bm
|
||
|
. bmw=_bm.bmWidth, bmh=_bm.bmHeight
|
||
|
get _mdc=CreateCompatibleDC _dc
|
||
|
SelectObject _mdc, hbmp
|
||
|
StretchBlt _dc, x, y, w, h,\
|
||
|
_mdc, 0, 0, bmw, bmh, SRCCOPY
|
||
|
DeleteDC _mdc
|
||
|
endf
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;; VGA ;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
macro os.get.screen.w
|
||
|
{ get os.w=GetSystemMetrics 0 }
|
||
|
|
||
|
macro os.get.screen.h
|
||
|
{ get os.h=GetSystemMetrics 1 }
|
||
|
|
||
|
function os.create.vga, w, h
|
||
|
alias p=r0, x=r1
|
||
|
; set.screen screen.w, screen.h, screen.bpp
|
||
|
try vga.hbm=CreateBitmap \
|
||
|
screen.w, screen.h, 32, 1, vga.p
|
||
|
memory.zero vga.bmi, BITMAPINFOHEADER.$
|
||
|
. vga.bmi.biSize=BITMAPINFOHEADER.$
|
||
|
. vga.bmi.biWidth=screen.w
|
||
|
. x=screen.h, neg x, vga.bmi.biHeight=x
|
||
|
. vga.bmi.biPlanes=1, vga.bmi.biBitCount=32
|
||
|
endf
|
||
|
|
||
|
function os.show.vga
|
||
|
SetDIBits _dc, vga.hbm, 0, screen.h,\
|
||
|
vga.p, vga.bmi, 0
|
||
|
draw.bitmap.w vga.hbm, 0, 0, screen.w, screen.h
|
||
|
. vga.rect.left=0, vga.rect.top=0,\
|
||
|
vga.rect.right=screen.w,\
|
||
|
vga.rect.bottom=screen.h
|
||
|
InvalidateRect _hwnd, vga.rect, 0
|
||
|
endf
|
||
|
|
||
|
function show.vga.box
|
||
|
SetDIBits _dc, vga.hbm, 0, screen.h,\
|
||
|
vga.p, vga.bmi, 0
|
||
|
draw.bitmap.w vga.hbm,\
|
||
|
box.x, box.y, box.w, box.y
|
||
|
. r0=box.x, r1=box.y,\
|
||
|
vga.rect.left=r0, vga.rect.top=r1,\
|
||
|
r0+box.w, vga.rect.right=r0,\
|
||
|
r1+box.h, vga.rect.bottom=r1
|
||
|
InvalidateRect _hwnd, vga.rect, 0
|
||
|
endf
|
||
|
|
||
|
macro show.vga.box b {
|
||
|
IF ~b eq
|
||
|
copy.box box, b
|
||
|
END IF
|
||
|
show.vga.box
|
||
|
}
|
||
|
|
||
|
macro define.vga { os.define.vga }
|
||
|
|
||
|
; create vga/buffer for drawing
|
||
|
|
||
|
function create.vga, w, h, c
|
||
|
if vga.p=0, r0=w, r0*h, r0<<2
|
||
|
try vga.p=allocate r0
|
||
|
end
|
||
|
call !clear.screen, c
|
||
|
os.create.vga w, h
|
||
|
endf 1
|
||
|
|
||
|
function show.vga
|
||
|
os.show.vga
|
||
|
endf
|
||
|
|
||
|
function set.vga, w, h
|
||
|
os.set.vga
|
||
|
endf
|
||
|
|
||
|
function end.vga
|
||
|
destroy vga
|
||
|
os.end.vga
|
||
|
endf
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;; ENTER+EXIT ;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
; user-defined enter/exit routines will be called
|
||
|
; if defined/nonzero
|
||
|
|
||
|
function os.enter
|
||
|
try @module=GetModuleHandleA 0
|
||
|
try @heap=HeapCreate 0, 0, 0
|
||
|
try directory=allocate 1*KB
|
||
|
. r0=directory, *r0=0
|
||
|
try file.name=allocate 1*KB
|
||
|
. r0=file.name, *r0=0
|
||
|
os.get.directory
|
||
|
os.get.command.line
|
||
|
. command.line=r0
|
||
|
endf 1
|
||
|
|
||
|
function exit
|
||
|
ExitProcess 0
|
||
|
endf
|
||
|
|
||
|
;;;;;;;;;;;;; EXECUTABLE STRUCTURE ;;;;;;;;;;;;;;;
|
||
|
|
||
|
align
|
||
|
|
||
|
section '.one' \
|
||
|
code readable writable executable
|
||
|
!main:
|
||
|
os.enter
|
||
|
if false
|
||
|
say 'System error'
|
||
|
exit
|
||
|
end
|
||
|
call !main!
|
||
|
exit
|
||
|
ret
|
||
|
|
||
|
function main!
|
||
|
os.get.screen.w
|
||
|
os.get.screen.h
|
||
|
set.screen WINDOW.W, WINDOW.H, 32
|
||
|
try create.vga screen.w, screen.h, BLACK
|
||
|
define.events create, draw, key, mouse
|
||
|
create.blank.window screen.w, screen.h
|
||
|
os.show.cursor
|
||
|
message.loop
|
||
|
endf
|
||
|
|
||
|
align
|