Compare commits

..

1 Commits

Author SHA1 Message Date
3ede6ade8c
feat: Libini (closes #2) 2024-03-24 18:49:16 +03:00
23 changed files with 1498 additions and 183 deletions

2
.gitignore vendored
View File

@ -2,4 +2,4 @@
**/*.rs.bk **/*.rs.bk
/Cargo.lock /Cargo.lock
/rust_dos.com /rust_dos.com
*.kex rust.kex

View File

@ -2,7 +2,7 @@
name = "kos" name = "kos"
version = "0.1.0" version = "0.1.0"
authors = ["Kitsu <mail@kitsu.me>", "Sweetbread"] authors = ["Kitsu <mail@kitsu.me>", "Sweetbread"]
edition = "2021" edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -14,10 +14,11 @@ path = "examples/hwa.rs"
name = "con" name = "con"
path = "examples/con.rs" path = "examples/con.rs"
[[example]]
name = "dark"
path = "examples/dark.rs"
[profile.release] [profile.release]
opt-level = "z" opt-level = "z"
lto = "thin" lto = "thin"
[dependencies]
cstr_core = { version = "0.2.4", default-features = false, features = ["nightly"] }
[build-dependencies]

View File

@ -1,8 +1,7 @@
# Rust library for KolibriOS # Rust library for KolibriOS
Project uses [cargo-make](https://github.com/sagiegurari/cargo-make) for building steps. Project uses [cargo-make](https://github.com/sagiegurari/cargo-make) for building steps.
You need to install cargo-binutils: `cargo install cargo-binutils` and llvm-tools-preview: `rustup component add llvm-tools-preview` to make it work.
Also you need a working [FASM](https://flatassembler.net/download.php). Also you need a working [FASM](https://flatassembler.net/download.php).
Once installed building is trivial then: `cargo make --profile production example <example name>` produces Once installed building is trivial then: `cargo make --profile production <example name>` produces
a ready-to-use binary at root. a ready-to-use binary at root.

View File

@ -1,15 +1,19 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
use cstr_core::cstr;
use kos::{dll::Console, threads::exit}; use kos::{dll::Console, threads::exit};
extern crate alloc; extern crate alloc;
#[no_mangle] #[no_mangle]
pub fn kol_main() { pub fn kol_main() {
let header = cstr!("Rust!");
let string = "Hi from Rust!";
let con_lib = Console::import(None).unwrap(); let con_lib = Console::import(None).unwrap();
con_lib.init(u32::MAX, u32::MAX, u32::MAX, u32::MAX, c"Rust!"); con_lib.init(u32::MAX, u32::MAX, u32::MAX, u32::MAX, header);
con_lib.write_string("Hi from Rust!"); con_lib.write_string(string);
con_lib.exit(false); con_lib.exit(false);
exit(); exit();

View File

@ -1,116 +0,0 @@
#![no_std]
#![no_main]
use kos::{
graphics::{display_message, Color, Dot, Size},
input::fetch_key,
threads::{exit, fetch_event, Event},
windows::{
define_button, define_window, end_window_draw, get_button_id, invert_pixel,
start_window_draw, WindowKind, WindowParams, CLOSE_BUTTON,
},
};
const HEADER: &'static CStr = c"Dark Mode Demo";
const TEXT: [&'static CStr; 6] = [
c"Lorem ipsum dolor sit amet,",
c"semper et rutrum placerat,",
c"Integer sed diam commodo quam varius",
c"Sed finibus urna sit amet felis",
c"vestibulum elementum. Maecenas at feugiat lacus",
c"tristique et sit amet tortor.",
];
const BTN: u32 = 42;
const WINDOW_SIZE: Size = Size {
width: 400,
height: 400,
};
extern crate alloc;
fn draw_window(invert: bool) {
start_window_draw();
define_window(
Dot { x: 50, y: 50 },
WINDOW_SIZE,
WindowParams {
color: Color::rgb(0xff, 0xff, 0xff),
kind: WindowKind::FixedThemed,
title: Some(HEADER),
},
);
display_message(Dot { x: 10, y: 10 }, Color::rgb(0, 0, 0), TEXT[0], None);
display_message(Dot { x: 10, y: 50 }, Color::rgb(0, 0, 0), TEXT[1], None);
display_message(Dot { x: 10, y: 90 }, Color::rgb(0, 0, 0), TEXT[2], None);
display_message(Dot { x: 10, y: 130 }, Color::rgb(0, 0, 0), TEXT[3], None);
display_message(Dot { x: 10, y: 170 }, Color::rgb(0, 0, 0), TEXT[4], None);
display_message(Dot { x: 10, y: 210 }, Color::rgb(0, 0, 0), TEXT[5], None);
define_button(
Dot { x: 10, y: 300 },
Size {
width: 100,
height: 30,
},
BTN,
true,
true,
Some(Color::rgb(147, 112, 219)),
);
display_message(
Dot { x: 20, y: 310 },
Color::rgb(255, 255, 255),
if invert {
c"Light mode"
} else {
c"Dark mode"
},
None,
);
if invert {
for x in 0..WINDOW_SIZE.width {
for y in 0..WINDOW_SIZE.height {
invert_pixel(Dot { x, y })
}
}
}
end_window_draw();
return;
}
fn button_handler(invert: &mut bool) {
let btn_id = get_button_id();
if btn_id.is_some() {
match btn_id.unwrap() {
CLOSE_BUTTON => exit(),
BTN => {
*invert = !*invert;
draw_window(*invert);
}
_ => {}
}
}
}
#[no_mangle]
fn kol_main() {
let mut invert = false;
while let Some(ev) =
fetch_event((Event::Redraw as u32) | (Event::KeyPress as u32) | (Event::BtnPress as u32))
{
match ev {
Event::Redraw => draw_window(invert),
Event::KeyPress => drop(fetch_key()),
Event::BtnPress => button_handler(&mut invert),
_ => break,
}
}
}

View File

@ -1,8 +1,8 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
use alloc::ffi::CString; use cstr_core::{cstr, CStr};
use core::ffi::CStr;
use kos::{ use kos::{
graphics::{display_message, Color, Dot, Size}, graphics::{display_message, Color, Dot, Size},
input::fetch_key, input::fetch_key,
@ -14,8 +14,8 @@ use kos::{
}, },
}; };
const HEADER: &CStr = c"Hey Kolibri"; const HEADER: &CStr = cstr!("Hey Kolibri");
const MSG: &CStr = c"Hello from Rust!"; const MSG: &CStr = cstr!("Hello from Rust!");
const BTN: u32 = 42; const BTN: u32 = 42;
#[macro_use] #[macro_use]
@ -45,18 +45,16 @@ fn draw_window(c: usize) {
); );
let btn_str = match get_lang() { let btn_str = match get_lang() {
Lang::German => format!("Taste gedrückt: {} mal", c), Lang::German => format!("Taste gedrückt: {} mal\0", c),
Lang::Russian => format!("Кнопка нажата: {} раз", c), Lang::Russian => format!("Кнопка нажата: {} раз\0", c),
Lang::French => format!("Button enfoncé : {} fois", c), Lang::French => format!("Button enfoncé : {} fois\0", c),
_ => format!("Button pressed: {} times", c), _ => format!("Button pressed: {} times\0", c),
}; };
display_message( display_message(
Dot { x: 10, y: 30 }, Dot { x: 10, y: 30 },
Color::rgb(0, 0, 0), Color::rgb(0, 0, 0),
CString::new(btn_str.as_bytes()) CStr::from_bytes_with_nul(btn_str.as_bytes()).unwrap_or(cstr!("String error")),
.expect("CString error")
.as_c_str(),
None, None,
); );

49
examples/ini.rs Normal file
View File

@ -0,0 +1,49 @@
#![no_std]
#![no_main]
use cstr_core::{cstr, CStr};
use kos::{dll::Libini, system::debug_write, threads::exit};
extern crate alloc;
use alloc::format;
static mut LIB: Option<Libini> = None;
#[no_mangle]
pub fn kol_main() {
unsafe {
// FIXME: Find any possible solution to drop that fucking unsafe
LIB = Libini::import(None).ok();
let filename = cstr!("/sys/File Managers/Kfar.ini");
LIB.unwrap()
.enum_sections(filename.as_ptr() as *const u8, sec_handler);
}
exit();
}
extern "stdcall" fn sec_handler(filename: *const u8, section: *const u8) {
unsafe {
debug_write(&format!(
"{}\n",
CStr::from_ptr(section as *const i8).to_str().unwrap()
));
LIB.unwrap().enum_keys(filename, section, key_handler);
};
}
extern "stdcall" fn key_handler(
_filename: *const u8,
_section: *const u8,
key: *const u8,
value: *const u8,
) {
unsafe {
debug_write(&format!(
"- {}\t = {}\n",
CStr::from_ptr(key as *const i8).to_str().unwrap(),
CStr::from_ptr(value as *const i8).to_str().unwrap()
))
}
}

View File

@ -1,7 +1,7 @@
{ {
"arch": "x86", "arch": "x86",
"cpu": "pentium", "cpu": "pentium",
"data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128",
"dynamic-linking": false, "dynamic-linking": false,
"executables": true, "executables": true,
"has-rpath": true, "has-rpath": true,

View File

@ -170,13 +170,15 @@ unsafe impl alloc::alloc::GlobalAlloc for GlobalAlloc {
return null_mut(); return null_mut();
} }
init(); // init();
malloc(layout.size()) // malloc(layout.size())
sys::alloc(layout.size()) as *mut u8
} }
unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) { unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) {
// free keeps track of layout presumably???? // free keeps track of layout presumably????
free(ptr) // free(ptr)
sys::free(ptr);
} }
} }

View File

@ -1,9 +1,15 @@
use crate::sys; use crate::sys;
use core::ffi::CStr; use core::mem::transmute;
use cstr_core::{cstr, CStr};
mod console; mod console;
pub use console::Console; pub use console::Console;
mod libini;
pub use libini::Libini;
use crate::system::debug_write;
pub struct DLL { pub struct DLL {
table: *const ImportTableEl, table: *const ImportTableEl,
} }
@ -22,6 +28,20 @@ impl DLL {
} }
} }
pub fn init_dll(name: &CStr) -> Result<DLL, &str> {
unsafe {
let lib = DLL::load_dll(name);
match lib {
Err(e) => Err(e),
Ok(dll) => {
let init: fn() = transmute(dll.get_func(cstr!("lib_init")).ok().unwrap());
sys::dllInit(init);
Ok(dll)
}
}
}
}
pub fn get_func(&self, name: &CStr) -> Result<*const (), &str> { pub fn get_func(&self, name: &CStr) -> Result<*const (), &str> {
unsafe { unsafe {
let mut i = 0; let mut i = 0;
@ -31,6 +51,11 @@ impl DLL {
return Err("Function not found"); return Err("Function not found");
} }
let cur_name = CStr::from_ptr((*el).func_name as *const i8); let cur_name = CStr::from_ptr((*el).func_name as *const i8);
debug_write(&format!(
"{}: {:x}\n",
cur_name.to_str().unwrap(),
(*el).func_addr as usize
));
if cur_name == name { if cur_name == name {
return Ok((*el).func_addr as *const ()); return Ok((*el).func_addr as *const ());
} }

View File

@ -1,6 +1,7 @@
use crate::dll::DLL; use crate::dll::DLL;
use core::ffi::CStr;
use core::mem::transmute; use core::mem::transmute;
use cstr_core::cstr;
use cstr_core::CStr;
pub struct Console { pub struct Console {
con_init: extern "stdcall" fn(u32, u32, u32, u32, *const u8), con_init: extern "stdcall" fn(u32, u32, u32, u32, *const u8),
@ -10,14 +11,16 @@ pub struct Console {
impl Console { impl Console {
pub fn import(path: Option<&CStr>) -> Result<Self, &str> { pub fn import(path: Option<&CStr>) -> Result<Self, &str> {
let lib = DLL::load_dll(path.unwrap_or(c"/sys/lib/console.obj")); let lib = DLL::load_dll(path.unwrap_or(cstr!("/sys/lib/console.obj")));
match lib { match lib {
Err(e) => return Err(e), Err(e) => return Err(e),
Ok(dll) => unsafe { Ok(dll) => unsafe {
Ok(Console { Ok(Console {
con_init: transmute(dll.get_func(c"con_init").ok().unwrap()), con_init: transmute(dll.get_func(cstr!("con_init")).ok().unwrap()),
con_write_string: transmute(dll.get_func(c"con_write_string").ok().unwrap()), con_write_string: transmute(
con_exit: transmute(dll.get_func(c"con_exit").ok().unwrap()), dll.get_func(cstr!("con_write_string")).ok().unwrap(),
),
con_exit: transmute(dll.get_func(cstr!("con_exit")).ok().unwrap()),
}) })
}, },
} }

48
src/dll/libini.rs Normal file
View File

@ -0,0 +1,48 @@
use crate::{dll::DLL, system::debug_write};
use core::mem::transmute;
use cstr_core::{cstr, CStr};
#[derive(Clone, Copy)]
pub struct Libini {
ini_enum_sections: extern "stdcall" fn(*const u8, extern "stdcall" fn(*const u8, *const u8)),
ini_enum_keys: extern "stdcall" fn(
*const u8,
*const u8,
extern "stdcall" fn(*const u8, *const u8, *const u8, *const u8),
),
}
impl Libini {
pub fn import(path: Option<&CStr>) -> Result<Self, &str> {
let lib = DLL::init_dll(path.unwrap_or(cstr!("/sys/lib/libini.obj")));
match lib {
Err(e) => return Err(e),
Ok(dll) => unsafe {
Ok(Libini {
ini_enum_sections: transmute(
dll.get_func(cstr!("ini_enum_sections")).ok().unwrap(),
),
ini_enum_keys: transmute(dll.get_func(cstr!("ini_enum_keys")).ok().unwrap()),
})
},
}
}
pub fn enum_sections(
&self,
filename: *const u8,
callback: extern "stdcall" fn(*const u8, *const u8),
) {
debug_write("--enum_sections\n");
(self.ini_enum_sections)(filename, callback);
}
pub fn enum_keys(
self,
filename: *const u8,
section_name: *const u8,
callback: extern "stdcall" fn(*const u8, *const u8, *const u8, *const u8),
) {
(self.ini_enum_keys)(filename, section_name, callback);
}
}

166
src/include/dll.inc Executable file
View File

@ -0,0 +1,166 @@
;-----------------------------------------------------------------------------
; load one or more DLL file in COFF format and try to import functions by our list
; if first function in import list begins with 'lib_', call it as DLL initialization
; return eax = 1 as fail, if anyone of .obj file not found in /sys/lib
; return 0 if all fine, but 0 not garantees in succesfull import - see dll.Link comment
; dirties all registers! eax, ebx, ecx, edx, esi, edi
proc dll.Load, import_table:dword
mov esi, [import_table]
.next_lib:
mov edx, [esi]
or edx, edx
jz .exit
push esi
mov esi, [esi + 4]
mov edi, esi
cmp byte[esi], '/'
jz .load_lib
mov edi, s_libdir.fname
@@:
lodsb
stosb
or al, al
jnz @b
mov edi, s_libdir
.load_lib:
mcall 68, 19, edi ;s_libdir
or eax, eax
jz .fail
stdcall dll.Link, eax, edx
push eax
mov eax, [eax]
cmp dword[eax], 'lib_'
pop eax
jnz @f
stdcall dll.Init, [eax + 4]
@@:
pop esi
add esi, 8
jmp .next_lib
.exit:
xor eax, eax
ret
.fail:
add esp, 4
xor eax, eax
inc eax
ret
endp
;-----------------------------------------------------------------------------
; scans dll export table for a functions we want to import
; break scan on first unresolved import
; no return value
proc dll.Link, exp:dword, imp:dword
push eax
mov esi, [imp]
test esi, esi
jz .done
.next:
lodsd
test eax, eax
jz .done
stdcall dll.GetProcAddress, [exp], eax
or eax, eax
jz @f
mov [esi - 4], eax
jmp .next
@@:
mov dword[esp], 0
.done:
pop eax
ret
endp
;-----------------------------------------------------------------------------
; calls lib_init with predefined parameters
; no return value
proc dll.Init, dllentry:dword
pushad
mov eax, mem.Alloc
mov ebx, mem.Free
mov ecx, mem.ReAlloc
mov edx, dll.Load
stdcall [dllentry]
popad
ret
endp
;-----------------------------------------------------------------------------
; scans export table for a sz_name function
; returns in eax function address or 0 if not found
proc dll.GetProcAddress, exp:dword, sz_name:dword
mov edx, [exp]
xor eax, eax
.next:
or edx, edx
jz .end
cmp dword[edx], 0
jz .end
stdcall strcmp, [edx], [sz_name]
test eax, eax
jz .ok
add edx, 8
jmp .next
.ok:
mov eax, [edx + 4]
.end:
cmp eax, -1
jnz @f
xor eax, eax
@@:
ret
endp
;-----------------------------------------------------------------------------
; compares strings
; returns eax = 0 if equal, -1 otherwise
proc strcmp, str1:dword, str2:dword
push esi edi
mov esi, [str1]
mov edi, [str2]
xor eax, eax
@@:
lodsb
scasb
jne .fail
or al, al
jnz @b
jmp .ok
.fail:
or eax, -1
.ok:
pop edi esi
ret
endp
;-----------------------------------------------------------------------------
if defined dll.Load
s_libdir:
db '/sys/lib/'
.fname rb 32
end if
;-----------------------------------------------------------------------------
proc mem.Alloc, size
push ebx ecx
mov ecx, [size]
mcall 68, 12
pop ecx ebx
ret
endp
;-----------------------------------------------------------------------------
proc mem.ReAlloc, mptr, size
push ebx ecx edx
mov ecx, [size]
mov edx, [mptr]
mcall 68, 20
pop edx ecx ebx
ret
endp
;-----------------------------------------------------------------------------
proc mem.Free, mptr
push ebx ecx
mov ecx,[mptr]
mcall 68, 13
pop ecx ebx
ret
endp
;-----------------------------------------------------------------------------

604
src/include/macros.inc Executable file
View File

@ -0,0 +1,604 @@
@^ fix macro comment {
^@ fix }
; --------------------------
macro library [lname,fname]
{
forward
dd __#lname#_library_table__,__#lname#_library_name__
common
dd 0
forward
align 4
__#lname#_library_name__ db fname,0
}
macro import lname,[name,sname]
{
common
align 4
__#lname#_library_table__:
forward
if used name
name dd __#name#_import_name__
end if
common
dd 0
forward
if used name
align 4
__#name#_import_name__ db sname,0
end if
}
macro export [name,sname]
{
forward
dd __#name#_export_name__,name
common
dd 0
forward
align 4
__#name#_export_name__ db sname,0
}
; -------------------------
macro m2m dest,src {
push src
pop dest
}
macro iglobal {
IGlobals equ IGlobals,
macro __IGlobalBlock { }
macro uglobal {
UGlobals equ UGlobals,
macro __UGlobalBlock { }
endg fix } ; Use endg for ending iglobal and uglobal blocks.
macro IncludeIGlobals{
macro IGlobals dummy,[n] \{ __IGlobalBlock
purge __IGlobalBlock \}
match I, IGlobals \{ I \} }
macro IncludeUGlobals{
macro UGlobals dummy,[n] \{
\common
\local begin, size
begin = $
virtual at $
\forward
__UGlobalBlock
purge __UGlobalBlock
\common
size = $ - begin
end virtual
rb size
\}
match U, UGlobals \{ U \} }
uglobal
endg
iglobal
endg
; new application structure
macro meos_app_start
{
use32
org 0x0
db 'MENUET01'
dd 0x01
dd __start
dd __end
dd __memory
dd __stack
if used __params & ~defined __params
dd __params
else
dd 0x0
end if
dd 0x0
}
MEOS_APP_START fix meos_app_start
KOS_APP_START fix meos_app_start
macro code
{
__start:
}
CODE fix code
macro data
{
__data:
IncludeIGlobals
}
DATA fix data
macro udata
{
if used __params & ~defined __params
__params:
db 0
__end:
rb 255
else
__end:
end if
__udata:
IncludeUGlobals
}
UDATA fix udata
macro meos_app_end
{
align 32
rb 2048
__stack:
__memory:
}
MEOS_APP_END fix meos_app_end
KOS_APP_END fix meos_app_end
; macro for defining multiline text data
struc mstr [sstring]
{
forward
local ssize
virtual at 0
db sstring
ssize = $
end virtual
dd ssize
db sstring
common
dd -1
}
; macro for defining multiline text data
struc mls [sstring]
{
forward
local ssize
virtual at 0
db sstring ; mod
ssize = $
end virtual
db ssize
db sstring
common
db -1 ; mod
}
; strings
macro sz name,[data] { ; [mike.dld]
common
if used name
name db data
.size = $-name
end if
}
macro szZ name,[data] { ; same as sz, but for zero terminated string [dunkaist]
common
if used name
name db data,0
.size = $-name-1
end if
}
sz0 fix szZ
macro lsz name,[lng,data] { ; [mike.dld]
common
if used name
label name
forward
if lang eq lng
db data
end if
common
.size = $-name
end if
}
macro szc name,elsz,[data] { ; [mike.dld]
common
local s,m
m = 0
if used name
label name
forward
virtual at 0
db data
s = $
end virtual
d#elsz s
if m < s
m = s
end if
db data
common
.size = $-name
.maxl = m
end if
}
macro lszc name,elsz,[lng,data] { ; [mike.dld]
common
local s,m,c
m = 0
c = 0
if used name
label name
forward
if lang eq lng
virtual at 0
db data
s = $
end virtual
d#elsz s
if m < s
m = s
end if
db data
c = c+1
end if
common
.size = $-name
.maxl = m
.count = c
end if
}
; easy system call macro
macro mpack dest, hsrc, lsrc
{
if (hsrc eqtype 0) & (lsrc eqtype 0)
mov dest, (hsrc) shl 16 + lsrc
else
if (hsrc eqtype 0) & (~lsrc eqtype 0)
mov dest, (hsrc) shl 16
add dest, lsrc
else
mov dest, hsrc
shl dest, 16
add dest, lsrc
end if
end if
}
macro __mov reg,a,b { ; mike.dld
if (~a eq)&(~b eq)
mpack reg,a,b
else if (~a eq)&(b eq)
mov reg,a
end if
}
;include 'config.inc'
__CPU_type equ p5
SYSENTER_VAR equ 0
macro mcall a,b,c,d,e,f,g { ; [mike.dld], [Ghost]
local ..ret_point
__mov eax,a
__mov ebx,b
__mov ecx,c
__mov edx,d
__mov esi,e
__mov edi,f
__mov ebp,g
if __CPU_type eq p5
int 0x40
else
if __CPU_type eq p6
push ebp
mov ebp, esp
push ..ret_point ; it may be 2 or 5 byte
sysenter
..ret_point:
pop edx
pop ecx
else
if __CPU_type eq k6
push ecx
syscall
pop ecx
else
display 'ERROR : unknown CPU type (set to p5)', 10, 13
__CPU_type equ p5
int 0x40
end if
end if
end if
}
; -------------------------
macro __header a,[b] {
common
use32
org 0
db 'MENUET',a
forward
if b eq
dd 0
else
dd b
end if
}
macro __section name {
align 16
label name
}
macro __func name {
if ~used name
display 'FUNC NOT USED: ',`name,13,10
else
align 4
name:
;diff16 `name,0,name
}
macro endf { end if }
macro diff16 title,l1,l2
{
local s,d
s = l2-l1
display title,': 0x'
repeat 8
d = '0' + s shr ((8-%) shl 2) and $0F
if d > '9'
d = d + 'A'-'9'-1
end if
display d
end repeat
display 13,10
}
macro diff10 title,l1,l2
{
local s,d,z,m
s = l2-l1
z = 0
m = 1000000000
display title,': '
repeat 10
d = '0' + s / m
s = s - (s/m)*m
m = m / 10
if d <> '0'
z = 1
end if
if z <> 0
display d
end if
end repeat
display 13,10
}
macro movi arg1,arg2
{
if (arg1 in <eax,ebx,ecx,edx,esi,edi,ebp,esp>) & ((arg2 eqtype 0) | (arg2 eqtype '0'))
if (arg2) = 0
xor arg1,arg1
else if (arg2) = 1
xor arg1,arg1
inc arg1
else if (arg2) = -1
or arg1,-1
else if (arg2) >= -128 & (arg2) <= 127
push arg2
pop arg1
else
mov arg1,arg2
end if
else
mov arg1,arg2
end if
}
macro RGB [a] {
common
match (r=,g=,b),a \{
\dd ((r) shl 16) or ((g) shl 8) or (b)
\}
}
struc POINT _t,_dx,_dy {
.x _t _dx
.y _t _dy
}
; structure definition helper
include 'struct.inc'
struct RECT
left dd ?
top dd ?
right dd ?
bottom dd ?
ends
struct BOX
left dd ?
top dd ?
width dd ?
height dd ?
ends
; structures used in KolibriOS
struct process_information
cpu_usage dd ? ; +0
window_stack_position dw ? ; +4
window_stack_value dw ? ; +6
dw ? ; +8
process_name rb 12 ; +10
memory_start dd ? ; +22
used_memory dd ? ; +26
PID dd ? ; +30
box BOX ; +34
slot_state dw ? ; +50
dw ? ; +52
client_box BOX ; +54
wnd_state db ? ; +70
event_mask dd ? ; +71
keyboard_mode db ? ; +75
rb (1024-76)
ends
struct system_colors
frame dd ? ;nonset1
grab dd ? ;nonset2
work_dark dd ?
work_light dd ?
grab_text dd ? ;window_title
work dd ?
work_button dd ?
work_button_text dd ?
work_text dd ?
work_graph dd ?
ends
struct FILEDATE
Second db ?
Minute db ?
Hour db ?
db ?
Day db ?
Month db ?
Year dw ?
ends
struct FILEINFO
Attributes dd ?
IsUnicode db ?
db 3 dup(?)
DateCreate FILEDATE
DateAccess FILEDATE
DateModify FILEDATE
Size dq ?
ends
cmove fix cmovz
macro cmovz reg1, reg2 {
local ..jumpaddr
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
jnz ..jumpaddr
mov reg1, reg2
..jumpaddr:
else
cmovz reg1, reg2
end if
}
cmovne fix cmovnz
macro cmovnz reg1, reg2 {
local ..jumpaddr
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
jz ..jumpaddr
mov reg1, reg2
..jumpaddr:
else
cmovnz reg1, reg2
end if
}
macro cmovg reg1, reg2 {
local ..jumpaddr
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
jle ..jumpaddr
mov reg1, reg2
..jumpaddr:
else
cmovg reg1, reg2
end if
}
macro cmovl reg1, reg2 {
local ..jumpaddr
if __CPU_type eq p5 ; CMOVcc isnt supported on the P5
jge ..jumpaddr
mov reg1, reg2
..jumpaddr:
else
cmovl reg1, reg2
end if
}
; replaces /programs/cmp.inc
irp cond, e, ne, g, ng, l, nl, ge, le {
macro cmp#cond a, b, c\{
cmp a, b
j#cond c
\}
}
; constants
; button flags
BT_DEL = 0x80000000
BT_HIDE = 0x40000000
BT_NOFRAME = 0x20000000
; events
EV_IDLE = 0
EV_TIMER = 0
EV_REDRAW = 1
EV_KEY = 2
EV_BUTTON = 3
EV_EXIT = 4
EV_BACKGROUND = 5
EV_MOUSE = 6
EV_IPC = 7
EV_STACK = 8
; event mask bits for function 40
EVM_REDRAW = 1b
EVM_KEY = 10b
EVM_BUTTON = 100b
EVM_EXIT = 1000b
EVM_BACKGROUND = 10000b
EVM_MOUSE = 100000b
EVM_IPC = 1000000b
EVM_STACK = 10000000b
EVM_DEBUG = 100000000b
EVM_STACK2 = 1000000000b
EVM_MOUSE_FILTER = 0x80000000
EVM_CURSOR_FILTER = 0x40000000

301
src/include/proc32.inc Executable file
View File

@ -0,0 +1,301 @@
; Macroinstructions for defining and calling procedures
macro stdcall proc,[arg] ; directly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call proc }
macro invoke proc,[arg] ; indirectly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call [proc] }
macro ccall proc,[arg] ; directly call CDECL procedure
{ 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 cinvoke proc,[arg] ; indirectly call CDECL procedure
{ 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 proc [args] ; define procedure
{ common
match name params, args>
\{ define@proc name,<params \} }
prologue@proc equ prologuedef
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ local loc
loc = (localbytes+3) and (not 3)
parmbase@proc equ ebp+8
localbase@proc equ ebp-loc
if parmbytes | localbytes
push ebp
mov ebp,esp
if localbytes
sub esp,loc
end if
end if
irps reg, reglist \{ push reg \} }
epilogue@proc equ epiloguedef
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
if parmbytes | localbytes
leave
end if
if flag and 10000b
retn
else
retn parmbytes
end if }
close@proc equ
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current
if used name
name:
match =stdcall args, statement \{ params equ args
flag = 11b \}
match =stdcall, statement \{ params equ
flag = 11b \}
match =c args, statement \{ params equ args
flag = 10001b \}
match =c, statement \{ params equ
flag = 10001b \}
match =params, params \{ params equ statement
flag = 0 \}
match =uses reglist=,args, params \{ regs equ reglist
params equ args \}
match =regs =uses reglist, regs params \{ regs equ reglist
params equ \}
match =regs, regs \{ regs equ \}
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
virtual at parmbase@proc
match =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $-(parmbase@proc)
end virtual
name # % = parmbytes/4
all@vars equ
current = 0
macro locals
\{ virtual at localbase@proc+current
macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc du [val] \\{ \common deflocal@proc .,du,val \\}
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
macro endl
\{ purge label
restruc db,du,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
current = $-(localbase@proc)
end virtual \}
macro ret operand
\{ match any, operand \\{ retn operand \\}
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
macro finish@proc
\{ localbytes = current
match close:reglist, close@proc:<regs> \\{ close name,flag,parmbytes,localbytes,reglist \\}
end if \} }
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if qqword eq type
dd ?,?,?,?,?,?,?,?
else if dqword eq type
dd ?,?,?,?
else if tbyte eq type
dd ?,?,?
else if qword eq type | pword eq type
dd ?,?
else
dd ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dd ? \}
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
macro deflocal@proc name,def,[val] { name def val }
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
..var def val
match =?, val \{ ..tmp equ \}
match any =?, val \{ ..tmp equ \}
match any (=?), val \{ ..tmp equ \}
match =label, def \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \} }
struc label type { label . type }
macro initlocal@proc name,def
{ virtual at name
def
size@initlocal = $ - name
end virtual
position@initlocal = 0
while size@initlocal > position@initlocal
virtual at name
def
if size@initlocal - position@initlocal < 2
current@initlocal = 1
load byte@initlocal byte from name+position@initlocal
else if size@initlocal - position@initlocal < 4
current@initlocal = 2
load word@initlocal word from name+position@initlocal
else
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
end if
end virtual
if current@initlocal = 1
mov byte [name+position@initlocal],byte@initlocal
else if current@initlocal = 2
mov word [name+position@initlocal],word@initlocal
else
mov dword [name+position@initlocal],dword@initlocal
end if
position@initlocal = position@initlocal + current@initlocal
end while }
macro endp
{ purge ret,locals,endl
finish@proc
purge finish@proc
restore regs@proc
match all,args@proc \{ restore all \}
restore args@proc
match all,all@vars \{ restore all \} }
macro local [var]
{ common
locals
forward done@local equ
match varname[count]:vartype, var
\{ match =BYTE, vartype \\{ varname rb count
restore done@local \\}
match =WORD, vartype \\{ varname rw count
restore done@local \\}
match =DWORD, vartype \\{ varname rd count
restore done@local \\}
match =PWORD, vartype \\{ varname rp count
restore done@local \\}
match =QWORD, vartype \\{ varname rq count
restore done@local \\}
match =TBYTE, vartype \\{ varname rt count
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
rq count*2
restore done@local \\}
match =QQWORD, vartype \\{ label varname qqword
rq count*4
restore done@local \\}
match =XWORD, vartype \\{ label varname xword
rq count*2
restore done@local \\}
match =YWORD, vartype \\{ label varname yword
rq count*4
restore done@local \\}
match , done@local \\{ virtual
varname vartype
end virtual
rb count*sizeof.\#vartype
restore done@local \\} \}
match :varname:vartype, done@local:var
\{ match =BYTE, vartype \\{ varname db ?
restore done@local \\}
match =WORD, vartype \\{ varname dw ?
restore done@local \\}
match =DWORD, vartype \\{ varname dd ?
restore done@local \\}
match =PWORD, vartype \\{ varname dp ?
restore done@local \\}
match =QWORD, vartype \\{ varname dq ?
restore done@local \\}
match =TBYTE, vartype \\{ varname dt ?
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
dq ?,?
restore done@local \\}
match =QQWORD, vartype \\{ label varname qqword
dq ?,?,?,?
restore done@local \\}
match =XWORD, vartype \\{ label varname xword
dq ?,?
restore done@local \\}
match =YWORD, vartype \\{ label varname yword
dq ?,?,?,?
restore done@local \\}
match , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }

240
src/include/struct.inc Executable file
View File

@ -0,0 +1,240 @@
; Macroinstructions for defining data structures
macro struct name
{ virtual at 0
fields@struct equ name
match child parent, name \{ fields@struct equ child,fields@\#parent \}
sub@struct equ
struc db [val] \{ \common define field@struct .,db,<val>
fields@struct equ fields@struct,field@struct \}
struc dw [val] \{ \common define field@struct .,dw,<val>
fields@struct equ fields@struct,field@struct \}
struc du [val] \{ \common define field@struct .,du,<val>
fields@struct equ fields@struct,field@struct \}
struc dd [val] \{ \common define field@struct .,dd,<val>
fields@struct equ fields@struct,field@struct \}
struc dp [val] \{ \common define field@struct .,dp,<val>
fields@struct equ fields@struct,field@struct \}
struc dq [val] \{ \common define field@struct .,dq,<val>
fields@struct equ fields@struct,field@struct \}
struc dt [val] \{ \common define field@struct .,dt,<val>
fields@struct equ fields@struct,field@struct \}
struc rb count \{ define field@struct .,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rw count \{ define field@struct .,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rd count \{ define field@struct .,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rp count \{ define field@struct .,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rq count \{ define field@struct .,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
struc rt count \{ define field@struct .,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro db [val] \{ \common \local anonymous
define field@struct anonymous,db,<val>
fields@struct equ fields@struct,field@struct \}
macro dw [val] \{ \common \local anonymous
define field@struct anonymous,dw,<val>
fields@struct equ fields@struct,field@struct \}
macro du [val] \{ \common \local anonymous
define field@struct anonymous,du,<val>
fields@struct equ fields@struct,field@struct \}
macro dd [val] \{ \common \local anonymous
define field@struct anonymous,dd,<val>
fields@struct equ fields@struct,field@struct \}
macro dp [val] \{ \common \local anonymous
define field@struct anonymous,dp,<val>
fields@struct equ fields@struct,field@struct \}
macro dq [val] \{ \common \local anonymous
define field@struct anonymous,dq,<val>
fields@struct equ fields@struct,field@struct \}
macro dt [val] \{ \common \local anonymous
define field@struct anonymous,dt,<val>
fields@struct equ fields@struct,field@struct \}
macro rb count \{ \local anonymous
define field@struct anonymous,db,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rw count \{ \local anonymous
define field@struct anonymous,dw,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rd count \{ \local anonymous
define field@struct anonymous,dd,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rp count \{ \local anonymous
define field@struct anonymous,dp,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rq count \{ \local anonymous
define field@struct anonymous,dq,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro rt count \{ \local anonymous
define field@struct anonymous,dt,count dup (?)
fields@struct equ fields@struct,field@struct \}
macro union \{ fields@struct equ fields@struct,,union,<
sub@struct equ union \}
macro struct \{ fields@struct equ fields@struct,,substruct,<
sub@struct equ substruct \} }
macro ends
{ match , sub@struct \{ restruc db,dw,du,dd,dp,dq,dt
restruc rb,rw,rd,rp,rq,rt
purge db,dw,du,dd,dp,dq,dt
purge rb,rw,rd,rp,rq,rt
purge union,struct
match name tail,fields@struct, \\{ if $
display 'Error: definition of ',\\`name,' contains illegal instructions.',0Dh,0Ah
err
end if \\}
match name=,fields,fields@struct \\{ fields@struct equ
make@struct name,fields
define fields@\\#name fields \\}
end virtual \}
match any, sub@struct \{ fields@struct equ fields@struct> \}
restore sub@struct }
macro make@struct name,[field,type,def]
{ common
local define
define equ name
forward
local sub
match , field \{ make@substruct type,name,sub def
define equ define,.,sub, \}
match any, field \{ define equ define,.#field,type,<def> \}
common
match fields, define \{ define@struct fields \} }
macro define@struct name,[field,type,def]
{ common
virtual
db `name
load initial@struct byte from 0
if initial@struct = '.'
display 'Error: name of structure should not begin with a dot.',0Dh,0Ah
err
end if
end virtual
local list
list equ
forward
if ~ field eq .
name#field type def
sizeof.#name#field = $ - name#field
else
label name#.#type
rb sizeof.#type
end if
local value
match any, list \{ list equ list, \}
list equ list <value>
common
sizeof.#name = $
restruc name
match values, list \{
struc name value \\{ \\local \\..base
match any, fields@struct \\\{ fields@struct equ fields@struct,.,name,<values> \\\}
match , fields@struct \\\{ label \\..base
forward
match , value \\\\{ field type def \\\\}
match any, value \\\\{ field type value
if ~ field eq .
rb sizeof.#name#field - ($-field)
end if \\\\}
common label . at \\..base \\\}
\\}
macro name value \\{
match any, fields@struct \\\{ \\\local anonymous
fields@struct equ fields@struct,anonymous,name,<values> \\\}
match , fields@struct \\\{
forward
match , value \\\\{ type def \\\\}
match any, value \\\\{ \\\\local ..field
..field = $
type value
if ~ field eq .
rb sizeof.#name#field - ($-..field)
end if \\\\}
common \\\} \\} \} }
macro enable@substruct
{ macro make@substruct substruct,parent,name,[field,type,def]
\{ \common
\local define
define equ parent,name
\forward
\local sub
match , field \\{ match any, type \\\{ enable@substruct
make@substruct type,parent,sub def
purge make@substruct
define equ define,.,sub, \\\} \\}
match any, field \\{ define equ define,.\#field,type,<def> \\}
\common
match fields, define \\{ define@\#substruct fields \\} \} }
enable@substruct
macro define@union parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
virtual at parent#.#name
parent#field type def
sizeof.#parent#field = $ - parent#field
end virtual
if sizeof.#parent#field > $ - parent#.#name
rb sizeof.#parent#field - ($ - parent#.#name)
end if
else
virtual at parent#.#name
label parent#.#type
type def
end virtual
label name#.#type at parent#.#name
if sizeof.#type > $ - parent#.#name
rb sizeof.#type - ($ - parent#.#name)
end if
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name [value] \{ \common
label .\#name
last@union equ
forward
match any, last@union \\{ virtual at .\#name
field type def
end virtual \\}
match , last@union \\{ match , value \\\{ field type def \\\}
match any, value \\\{ field type value \\\} \\}
last@union equ field
common rb sizeof.#name - ($ - .\#name) \}
macro name [value] \{ \common \local ..anonymous
..anonymous name value \} }
macro define@substruct parent,name,[field,type,def]
{ common
virtual at parent#.#name
forward
if ~ field eq .
parent#field type def
sizeof.#parent#field = $ - parent#field
else
label parent#.#type
rb sizeof.#type
end if
common
sizeof.#name = $ - parent#.#name
end virtual
struc name value \{
label .\#name
forward
match , value \\{ field type def \\}
match any, value \\{ field type value
if ~ field eq .
rb sizeof.#parent#field - ($-field)
end if \\}
common \}
macro name value \{ \local ..anonymous
..anonymous name \} }

View File

@ -1,5 +1,5 @@
use crate::sys; use crate::sys;
use core::ffi::CStr; use cstr_core::CStr;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Color(u8, u8, u8); pub struct Color(u8, u8, u8);

View File

@ -1,7 +1,7 @@
use crate::sys; use crate::sys;
use crate::throw_new; use crate::throw_new;
use alloc::string::String; use alloc::string::String;
use core::ffi::CStr; use cstr_core::CStr;
trait Debuggable { trait Debuggable {
fn data_iter(self) -> impl Iterator<Item = u8>; fn data_iter(self) -> impl Iterator<Item = u8>;

View File

@ -2,8 +2,7 @@ use crate::graphics::{Color, Dot, Size};
use crate::sys; use crate::sys;
use crate::system::debug_write; use crate::system::debug_write;
use crate::throw_new; use crate::throw_new;
use alloc::ffi::CString; use cstr_core::{cstr, CStr};
use core::ffi::CStr;
#[repr(u32)] #[repr(u32)]
pub enum WindowKind { pub enum WindowKind {
@ -17,12 +16,12 @@ pub enum WindowKind {
pub struct WindowParams<'a> { pub struct WindowParams<'a> {
pub color: Color, pub color: Color,
pub kind: WindowKind, pub kind: WindowKind,
pub title: Option<&'a CStr>, pub title: Option<&'a cstr_core::CStr>,
} }
pub const CLOSE_BUTTON: u32 = 1; pub const CLOSE_BUTTON: u32 = 1;
pub fn define_window(start: Dot, size: Size, params: WindowParams) { pub fn define_window(start: Dot, size: Size, params: WindowParams<'_>) {
const RELATIVE_FLAG: u32 = 0x20; const RELATIVE_FLAG: u32 = 0x20;
unsafe { unsafe {
@ -40,15 +39,6 @@ pub fn define_window(start: Dot, size: Size, params: WindowParams) {
} }
} }
pub fn put_pixel(pos: Dot, color: Option<Color>) {
let color: u32 = color.unwrap_or(Color::rgb(255, 255, 255)).as_rgb_val();
unsafe { sys::put_pixel(pos.x, pos.y, color) }
}
pub fn invert_pixel(pos: Dot) {
unsafe { sys::put_pixel(pos.x, pos.y, 1 << 24) }
}
pub fn define_button( pub fn define_button(
start: Dot, start: Dot,
size: Size, size: Size,
@ -61,12 +51,14 @@ pub fn define_button(
crate::graphics::display_message( crate::graphics::display_message(
Dot { x: 10, y: 200 }, Dot { x: 10, y: 200 },
Color::rgb(255, 0, 0), Color::rgb(255, 0, 0),
CString::new(format!( CStr::from_bytes_with_nul(
"x:{:?} y:{:?} w:{:?} h:{:?}\n", format!(
"x:{:?} y:{:?} w:{:?} h:{:?}\n\0",
start.x, start.y, size.width, size.height start.x, start.y, size.width, size.height
)) )
.expect("CString error") .as_bytes(),
.as_c_str(), )
.unwrap_or(cstr!("String error")),
None, None,
); );
throw_new!(format!( throw_new!(format!(

View File

@ -8,10 +8,6 @@ extern "C" {
#[link_name = "_define_window"] #[link_name = "_define_window"]
pub fn define_window(ebx: u32, ecx: u32, edx: u32, esi: u32, edi: u32); pub fn define_window(ebx: u32, ecx: u32, edx: u32, esi: u32, edi: u32);
// 1
#[link_name = "_put_pixel"]
pub fn put_pixel(ebx: u32, ecx: u32, edx: u32);
// 2 // 2
#[link_name = "_pressed_key"] #[link_name = "_pressed_key"]
pub fn pressed_key() -> u32; pub fn pressed_key() -> u32;
@ -68,3 +64,10 @@ extern "C" {
#[link_name = "_load_dll"] #[link_name = "_load_dll"]
pub fn load_dll(name: *const u8) -> *const u32; pub fn load_dll(name: *const u8) -> *const u32;
} }
// dll.inc
#[link(name = "syscalls")]
extern "stdcall" {
#[link_name = "dll.Init"]
pub fn dllInit(init_function: fn());
}

View File

@ -1,13 +1,15 @@
format ELF format ELF
include "src/func_constants.inc" include "src/include/macros.inc"
include "src/include/proc32.inc"
include "src/include/dll.inc"
include "src/include/func_constants.inc"
section '.text' section '.text'
public _exit public _exit
public _start_window_draw public _start_window_draw
public _end_window_draw public _end_window_draw
public _define_window public _define_window
public _put_pixel
public _display_message public _display_message
public _wait_event public _wait_event
public _pressed_key public _pressed_key
@ -21,6 +23,8 @@ section '.text'
public _load_dll public _load_dll
public _set_event_mask public _set_event_mask
public dll.Init
_exit: _exit:
mov eax, SF_TERMINATE_PROCESS mov eax, SF_TERMINATE_PROCESS
int 0x40 int 0x40
@ -51,14 +55,6 @@ _define_window:
pop edi pop edi
ret ret
_put_pixel:
mov eax, SF_PUT_PIXEL
mov ebx, dword [esp + 4 * 1]
mov ecx, dword [esp + 4 * 2]
mov edx, dword [esp + 4 * 3]
int 0x40
ret
_display_message: _display_message:
push esi edi push esi edi
mov eax, SF_DRAW_TEXT mov eax, SF_DRAW_TEXT