Compare commits
33
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ee27c5595 | ||
|
|
dc7d6dd842 | ||
|
|
a8ade5e0c2 | ||
|
|
f143ca1928 | ||
|
|
931071a0e9 | ||
|
|
bed9528756 | ||
|
|
570a432a84 | ||
|
|
1215116155 | ||
|
|
e470ef5db5 | ||
|
|
24d1b5877a | ||
|
|
aa8913ea33 | ||
|
|
647f35ea10 | ||
|
|
f44ceb560c | ||
|
|
6defa11a9e | ||
|
|
944d74f013 | ||
|
|
2bebbcbdc3 | ||
|
|
201e8b2de3 | ||
|
|
0390ad41e4 | ||
|
|
2515d1fa37 | ||
|
|
da0e6f492b | ||
|
|
3c2bdfb418 | ||
|
|
67770ec3f4 | ||
|
|
76294451d2 | ||
|
|
031fe62338 | ||
|
|
8766bfc546 | ||
|
|
2db92868a9 | ||
|
|
4bdee82489 | ||
|
|
b9fe23b7b2 | ||
|
|
d33a03c2e4
|
||
|
|
35f35b39e7 | ||
|
|
a020a2c434 | ||
|
|
77d600c663 | ||
|
|
f7dd4033ba |
No files matched your search
+12
-6
@@ -74,7 +74,6 @@ if build_type == "ru_RU" then tup.append_table(img_files, {
|
||||
{"WELCOME.HTM", VAR_DATA .. "/" .. build_type .. "/welcome.htm.kpack"},
|
||||
{"EXAMPLE.ASM", SRC_PROGS .. "/develop/examples/example/rus/example.asm"},
|
||||
{"DEVELOP/BACKY", SRC_PROGS .. "/develop/backy/Backy_ru"},
|
||||
{"GAMES/BASEKURS.KLA", build_type .. "/games/basekurs.kla"},
|
||||
{"File Managers/KFAR.INI", build_type .. "/File Managers/kfar.ini"},
|
||||
{"GAMES/DESCENT", build_type .. "/games/descent"},
|
||||
{"SETTINGS/.shell", SRC_PROGS .. "/system/shell/bin/rus/.shell"},
|
||||
@@ -192,6 +191,12 @@ extra_files = {
|
||||
{"kolibrios/develop/tcc/samples/", SRC_PROGS .. "/develop/ktcc/libc.obj/samples/*.sh"},
|
||||
{"kolibrios/develop/tcc/samples/clayer/", SRC_PROGS .. "/develop/ktcc/libc.obj/samples/clayer/*"},
|
||||
{"kolibrios/develop/utils/SPEDump", SRC_PROGS .. "/develop/SPEDump/SPEDump.kex"},
|
||||
{"kolibrios/develop/XDPascal/", SRC_PROGS .. "/develop/XDPascal/xdpk/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2025/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2025/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2025/Compiler/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2025/Compiler/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2026/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2026/*"},
|
||||
{"kolibrios/develop/XDPascal/source/", SRC_PROGS .. "/develop/XDPascal/xdpk/source/*"},
|
||||
{"kolibrios/develop/XDPascal/units/", SRC_PROGS .. "/develop/XDPascal/xdpk/units/*"},
|
||||
{"kolibrios/emul/", "common/emul/*"},
|
||||
{"kolibrios/emul/dosbox/", "common/emul/DosBox/*"},
|
||||
{"kolibrios/emul/e80/readme.txt", SRC_PROGS .. "/emulator/e80/readme.txt"},
|
||||
@@ -291,8 +296,6 @@ extra_files = {
|
||||
{"kolibrios/utils/vmode", "common/vmode"},
|
||||
{"kolibrios/utils/texture", "common/utils/texture"},
|
||||
{"kolibrios/utils/kterm/kterm", VAR_PROGS .. "/other/kterm/kterm"},
|
||||
{"kolibrios/utils/kterm/serial.sys", VAR_DRVS .. "/serial/serial.sys"},
|
||||
{"kolibrios/utils/kterm/install.sh", SRC .. "/drivers/serial/install.sh"},
|
||||
{"kolibrios/utils/cnc_editor/cnc_editor", VAR_PROGS .. "/other/cnc_editor/cnc_editor"},
|
||||
{"kolibrios/utils/cnc_editor/kolibri.NC", SRC_PROGS .. "/other/cnc_editor/kolibri.NC"},
|
||||
{"kolibrios/utils/kfm/kfm.ini", "common/File Managers/kfm.ini"},
|
||||
@@ -424,7 +427,7 @@ tup.append_table(img_files, {
|
||||
{"DOCPACK", VAR_PROGS .. "/system/docpack/docpack"},
|
||||
{"DEFAULT.SKN", VAR_SKINS .. "/../skins/Leency/Shkvorka/Shkvorka.skn"},
|
||||
{"DISPTEST", VAR_PROGS .. "/testing/disptest/disptest"},
|
||||
{"END", VAR_PROGS .. "/system/end/light/end"},
|
||||
{"END", VAR_PROGS .. "/system/end/end"},
|
||||
{"ESKIN", VAR_PROGS .. "/system/eskin/eskin"},
|
||||
{"GMON", VAR_PROGS .. "/system/gmon/gmon"},
|
||||
{"HDD_INFO", VAR_PROGS .. "/system/hdd_info/hdd_info"},
|
||||
@@ -539,7 +542,7 @@ tup.append_table(img_files, {
|
||||
{"NETWORK/PING", VAR_PROGS .. "/network/ping/ping"},
|
||||
{"NETWORK/NETCFG", VAR_PROGS .. "/network/netcfg/netcfg"},
|
||||
{"NETWORK/NETSTAT", VAR_PROGS .. "/network/netstat/netstat"},
|
||||
{"NETWORK/NSINST", VAR_PROGS .. "/network/netsurf/nsinstall"},
|
||||
{"NETWORK/NETSURF", VAR_PROGS .. "/network/netsurf/netsurf"},
|
||||
{"NETWORK/NSLOOKUP", VAR_PROGS .. "/network/nslookup/nslookup"},
|
||||
{"NETWORK/PASTA", VAR_PROGS .. "/network/pasta/pasta"},
|
||||
{"NETWORK/SYNERGYC", VAR_PROGS .. "/network/synergyc/synergyc"},
|
||||
@@ -571,11 +574,13 @@ tup.append_table(img_files, {
|
||||
{"DRIVERS/OHCI.SYS", VAR_DRVS .. "/usb/ohci.sys"},
|
||||
{"DRIVERS/EHCI.SYS", VAR_DRVS .. "/usb/ehci.sys"},
|
||||
{"DRIVERS/USBHID.SYS", VAR_DRVS .. "/usb/usbhid/usbhid.sys"},
|
||||
{"DRIVERS/USBFTDI.SYS", VAR_DRVS .. "/usb/usbftdi/usbftdi.sys"},
|
||||
{"DRIVERS/USBOTHER.SYS",VAR_DRVS .. "/usb/usbother/usbother.sys"},
|
||||
{"DRIVERS/USBCDC.SYS", VAR_DRVS .. "/usb/usbnet/usbcdc.sys"},
|
||||
{"DRIVERS/USBRNDIS.SYS", VAR_DRVS .. "/usb/usbnet/usbrndis.sys"},
|
||||
{"DRIVERS/USBSTOR.SYS", VAR_DRVS .. "/usb/usbstor.sys"},
|
||||
{"DRIVERS/RDC.SYS", VAR_DRVS .. "/video/rdc.sys"},
|
||||
{"DRIVERS/SERIAL.SYS", VAR_DRVS .. "/serial/serial.sys"},
|
||||
{"DRIVERS/COMMOUSE.SYS", VAR_DRVS .. "/mouse/commouse.sys"},
|
||||
{"DRIVERS/PS2MOUSE.SYS", VAR_DRVS .. "/mouse/ps2mouse4d/ps2mouse.sys"},
|
||||
{"DRIVERS/TMPDISK.SYS", VAR_DRVS .. "/disk/tmpdisk.sys"},
|
||||
@@ -649,7 +654,6 @@ tup.append_table(extra_files, {
|
||||
})
|
||||
-- For russian build, add russian-only programs.
|
||||
if build_type == "ru_RU" then tup.append_table(img_files, {
|
||||
{"GAMES/KLAVISHA", VAR_PROGS .. "/games/klavisha/klavisha"},
|
||||
{"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_rus"},
|
||||
}) else tup.append_table(img_files, {
|
||||
{"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_eng"},
|
||||
@@ -658,6 +662,8 @@ if build_type == "ru_RU" then tup.append_table(img_files, {
|
||||
if build_type == "ru_RU" then tup.append_table(extra_files, {
|
||||
{"kolibrios/utils/period", VAR_PROGS .. "/other/period/period"},
|
||||
{"kolibrios/games/Dungeons/Dungeons", VAR_PROGS .. "/games/Dungeons/Dungeons"},
|
||||
{"kolibrios/games/klavisha/klavisha", VAR_PROGS .. "/games/klavisha/klavisha"},
|
||||
{"kolibrios/games/klavisha/basekurs.kla", "ru_RU/games/basekurs.kla"},
|
||||
}) end
|
||||
|
||||
end -- tup.getconfig('NO_FASM') ~= 'full'
|
||||
|
||||
@@ -48,7 +48,7 @@ mht=/sys/network/WebView
|
||||
docx=/sys/network/WebView
|
||||
url=/sys/network/WebView
|
||||
fb2=/sys/fb2read
|
||||
kla=/sys/games/klavisha
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
avi=/kolibrios/media/fplay_run
|
||||
mpg=/kolibrios/media/fplay_run
|
||||
|
||||
@@ -179,7 +179,7 @@ stl=/sys/3d/view3ds
|
||||
skn=/sys/skincfg
|
||||
dtp=/sys/skincfg
|
||||
lif=/kolibrios/demos/life2
|
||||
kla=/sys/games/klavisha
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
|
||||
smc=/kolibrios/emul/zsnes/zsnes
|
||||
|
||||
@@ -39,7 +39,7 @@ Donkey=/kg/donkey
|
||||
Loderunner=/kg/LRL/LRL,41
|
||||
; 21days=/kg/21days,104 ;rus only
|
||||
BabyPainter=/kg/BabyPainter,87
|
||||
Klavisha=games/klavisha,69
|
||||
Klavisha=/kg/klavisha/klavisha,69
|
||||
Millioneer=/kg/WHOWTBAM/whowtbam,114
|
||||
StarTrek71=/kg/sstartrek/SStarTrek
|
||||
Descent=games/descent
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
path=/sys/NETWORK/NETSURF
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -116,6 +116,7 @@
|
||||
33 HTTPGet |network/httpget
|
||||
33 Downloader |network/dl
|
||||
12 WebView Browser |network/webview
|
||||
12 NetSurf |network/netsurf
|
||||
#13 **** SERVERS
|
||||
24 FTP |network/ftpd
|
||||
#14 **** OTHER
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
path=/sys/NETWORK/NETSURF
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -121,6 +121,7 @@
|
||||
16 HTTPGet |network/httpget
|
||||
16 Descargas |network/dl
|
||||
16 Navegador WebView |network/webview
|
||||
12 NetSurf |network/netsurf
|
||||
#15 **** OTROS
|
||||
16 Reloj analвgico |demos/aclock
|
||||
16 Reloj binario |demos/bcdclk
|
||||
|
||||
@@ -39,7 +39,7 @@ docx=/sys/network/WebView
|
||||
url=/sys/network/WebView
|
||||
fb2=/sys/fb2read
|
||||
mht=/sys/network/WebView
|
||||
kla=/sys/games/klavisha
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
avi=/kolibrios/media/fplay_run
|
||||
mpg=/kolibrios/media/fplay_run
|
||||
|
||||
@@ -39,7 +39,7 @@ Donkey=/kg/donkey
|
||||
Loderunner=/kg/LRL/LRL,41
|
||||
21days=/kg/21days,104 ;rus only
|
||||
BabyPainter=/kg/BabyPainter,87
|
||||
Klavisha=games/klavisha,69
|
||||
Klavisha=/kg/klavisha/klavisha,69
|
||||
Millioneer=/kg/WHOWTBAM/whowtbam,114
|
||||
StarTrek71=/kg/sstartrek/SStarTrek
|
||||
Descent=games/descent
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
path=/sys/NETWORK/NETSURF
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
33 HTTPGet |network/httpget
|
||||
33 Загрузчик |network/dl
|
||||
12 Браузер WebView |network/webview
|
||||
12 Браузер NetSurf |network/netsurf
|
||||
#14 **** Разное
|
||||
00 Эмуляторы* > |@6
|
||||
45 Создание скриншотов |scrshoot
|
||||
@@ -122,7 +123,7 @@
|
||||
18 FB2 Читалка |fb2read
|
||||
16 Аналоговые часы |aclock
|
||||
21 Таблица Менделеева |/kolibrios/utils/period
|
||||
59 Тренажёр KJ|ABuIIIA |games/klavisha
|
||||
59 Тренажёр KJIABuIIIA |/kolibrios/games/klavisha/klavisha
|
||||
16 Бинарные часы |demos/bcdclk
|
||||
53 Таймер |timer
|
||||
09 Разархиватор Unz |unz
|
||||
|
||||
@@ -515,20 +515,18 @@ HDA_AMP_VOLMASK equ 0x7F
|
||||
|
||||
|
||||
; unsolicited event handler
|
||||
HDA_UNSOL_QUEUE_SIZE equ 64
|
||||
HDA_UNSOL_QUEUE_SIZE equ 64 ; must stay a power of 2 (used as a bitmask for wrap)
|
||||
|
||||
;struc HDA_BUS_UNSOLICITED
|
||||
;{
|
||||
; ; ring buffer
|
||||
; .queue:
|
||||
; times HDA_UNSOL_QUEUE_SIZE*2 dd ?
|
||||
; .rp dd ?
|
||||
; .wp dd ?
|
||||
;
|
||||
; ; workqueue
|
||||
; .work dd ?;struct work_struct work;
|
||||
; .bus dd ? ;struct hda_bus ;bus
|
||||
;};
|
||||
struc HDA_BUS_UNSOLICITED
|
||||
{
|
||||
; ring buffer
|
||||
.queue rd HDA_UNSOL_QUEUE_SIZE * 2 ; 2 dword for each event (res and res_ex)
|
||||
.rp dd ? ; Read pointer
|
||||
.wp dd ? ; Write pointer
|
||||
; ; workqueue
|
||||
; .work dd ? ;struct work_struct work;
|
||||
; .bus dd ? ;struct hda_bus ;bus
|
||||
}
|
||||
|
||||
; Helper for automatic ping configuration
|
||||
AUTO_PIN_MIC equ 0
|
||||
|
||||
@@ -654,7 +654,15 @@ end if
|
||||
stdcall hda_codec_setup_stream, eax, SDO_TAG, 0, 0x11 ; Left & Right channels (Back panel)
|
||||
;Asper+ ]
|
||||
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
if USE_UNSOL_EV = 0
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 1
|
||||
else
|
||||
; Keep the unsolicited-event mode on the event-driven path. Running
|
||||
; snd_hda_automute at startup can issue codec commands before the new
|
||||
; unsolicited-response flow is ready, which hangs some systems.
|
||||
invoke TimerHS, 1, 0, process_unsol_events, 0
|
||||
end if
|
||||
|
||||
if USE_SINGLE_MODE
|
||||
mov esi, msgSingleMode
|
||||
invoke SysMsgBoardStr
|
||||
@@ -2635,7 +2643,7 @@ proc snd_hda_automute stdcall, data:dword
|
||||
test eax, eax
|
||||
jz .out
|
||||
|
||||
stdcall snd_hda_read_pin_sense, edx, 1
|
||||
stdcall snd_hda_read_pin_sense, edx, [data]
|
||||
test eax, AC_PINSENSE_PRESENCE
|
||||
jnz @f
|
||||
xchg ecx, esi
|
||||
@@ -2664,24 +2672,64 @@ proc snd_hda_automute stdcall, data:dword
|
||||
endp
|
||||
|
||||
|
||||
;Asper remember to add this functions:
|
||||
proc snd_hda_queue_unsol_event stdcall, par1:dword, par2:dword
|
||||
;if DEBUG
|
||||
; push esi
|
||||
; mov esi, msgUnsolEvent
|
||||
; invoke SysMsgBoardStr
|
||||
; pop esi
|
||||
;end if
|
||||
if USE_UNSOL_EV = 1
|
||||
;Test. Do not make queue, process immediately!
|
||||
;stdcall here snd_hda_read_pin_sense stdcall, nid:dword, trigger_sense:dword
|
||||
;and then mute/unmute pin based on the results
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
end if
|
||||
ret
|
||||
endp
|
||||
;...
|
||||
; ;Asper remember to add this functions:
|
||||
; proc snd_hda_queue_unsol_event stdcall, par1:dword, par2:dword
|
||||
; ;if DEBUG
|
||||
; ; push esi
|
||||
; ; mov esi, msgUnsolEvent
|
||||
; ; invoke SysMsgBoardStr
|
||||
; ; pop esi
|
||||
; ;end if
|
||||
; if USE_UNSOL_EV = 1
|
||||
; ;Test. Do not make queue, process immediately!
|
||||
; ;stdcall here snd_hda_read_pin_sense stdcall, nid:dword, trigger_sense:dword
|
||||
; ;and then mute/unmute pin based on the results
|
||||
; invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
; end if
|
||||
; ret
|
||||
; endp
|
||||
; ;...
|
||||
|
||||
align 4
|
||||
proc snd_hda_queue_unsol_event stdcall, res:dword, res_ex:dword
|
||||
; Single-producer (HDA IRQ) lock-free enqueue. The caller azx_update_rirb
|
||||
; only carries EBX across iterations and reloads the rest, and TimerHS
|
||||
; preserves EBX too - so by using scratch regs only we need no saves.
|
||||
mov eax, [unsol_events.wp]
|
||||
lea edx, [eax+1]
|
||||
and edx, HDA_UNSOL_QUEUE_SIZE - 1 ; next write pos (size must be 2^n)
|
||||
cmp edx, [unsol_events.rp]
|
||||
je .full ; ring full -> drop, keep 1 slot free
|
||||
|
||||
mov ecx, [res]
|
||||
mov [unsol_events.queue + eax*8], ecx
|
||||
mov ecx, [res_ex]
|
||||
mov [unsol_events.queue + eax*8 + 4], ecx
|
||||
mov [unsol_events.wp], edx ; publish only after data is stored
|
||||
|
||||
invoke TimerHS, 1, 0, process_unsol_events, 0
|
||||
.full:
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc process_unsol_events stdcall, data:dword
|
||||
; Runs from TimerHS (single consumer). Uses only EAX (scratch) and calls
|
||||
; snd_hda_automute, which preserves every register, so nothing is saved.
|
||||
.loop:
|
||||
mov eax, [unsol_events.rp]
|
||||
cmp eax, [unsol_events.wp]
|
||||
je .done
|
||||
; The event payload is at [unsol_events.queue + eax*8] (res) and +4 (res_ex).
|
||||
; Per-pin tag parsing is not implemented yet, so just re-evaluate jack state.
|
||||
inc eax
|
||||
and eax, HDA_UNSOL_QUEUE_SIZE - 1
|
||||
mov [unsol_events.rp], eax
|
||||
stdcall snd_hda_automute, 0
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc fdword2str stdcall, flags:dword ; bit 0 - skipLeadZeroes; bit 1 - newLine; other bits undefined
|
||||
@@ -3057,6 +3105,7 @@ aspinlock dd SPINLOCK_FREE
|
||||
|
||||
codec CODEC
|
||||
ctrl AC_CNTRL
|
||||
unsol_events HDA_BUS_UNSOLICITED
|
||||
|
||||
;Asper: BDL must be aligned to 128 according to HDA specification.
|
||||
pcmout_bdl rd 1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SERIAL_COMPATIBLE_API_VER = 0 ; increments in case of breaking changes
|
||||
SERIAL_COMPATIBLE_API_VER = 1 ; increments in case of breaking changes
|
||||
|
||||
SERIAL_API_GET_VERSION = 0
|
||||
SERIAL_API_SRV_ADD_PORT = 1
|
||||
@@ -9,6 +9,7 @@ SERIAL_API_CLOSE_PORT = 5
|
||||
SERIAL_API_SETUP_PORT = 6
|
||||
SERIAL_API_READ = 7
|
||||
SERIAL_API_WRITE = 8
|
||||
SERIAL_API_ENUM_PORTS = 9
|
||||
|
||||
SERIAL_API_ERR_PORT_INVALID = 1
|
||||
SERIAL_API_ERR_PORT_BUSY = 2
|
||||
@@ -29,6 +30,9 @@ SERIAL_CONF_STOP_BITS_2 = 2
|
||||
|
||||
SERIAL_CONF_FLOW_CTRL_NONE = 0
|
||||
|
||||
SERIAL_INFO_DRIVER_LEN = 16
|
||||
SERIAL_INFO_DESCR_LEN = 64
|
||||
|
||||
struct SP_DRIVER
|
||||
size dd ? ; size of this struct
|
||||
startup dd ? ; int __stdcall (*startup)(void *drv_data, const struct serial_conf *conf);
|
||||
@@ -46,7 +50,20 @@ struct SP_CONF
|
||||
flow_ctrl db ?
|
||||
ends
|
||||
|
||||
proc serial_add_port stdcall, drv:dword, drv_data:dword
|
||||
struct SP_PORT_INFO
|
||||
size dd ? ; size of this struct
|
||||
driver dd ? ; ASCIIZ driver name, e.g. "uart16550", "usb-cdc"
|
||||
descr dd ? ; ASCIIZ description, may be NULL
|
||||
ends
|
||||
|
||||
struct SP_PORT_ENUM_ENTRY
|
||||
id dd ? ; unique port number (SERIAL_PORT.id)
|
||||
busy dd ? ; 0 = free, non-zero = port is opened
|
||||
driver rb SERIAL_INFO_DRIVER_LEN
|
||||
descr rb SERIAL_INFO_DESCR_LEN
|
||||
ends
|
||||
|
||||
proc serial_add_port stdcall, drv:dword, drv_data:dword, info:dword
|
||||
locals
|
||||
handler dd ?
|
||||
io_code dd ?
|
||||
@@ -60,7 +77,7 @@ endl
|
||||
mov [io_code], SERIAL_API_SRV_ADD_PORT
|
||||
lea eax, [drv]
|
||||
mov [input], eax
|
||||
mov [inp_size], 8
|
||||
mov [inp_size], 12
|
||||
xor eax, eax
|
||||
mov [output], eax
|
||||
mov [out_size], eax
|
||||
@@ -129,7 +146,7 @@ proc serial_port_init
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_get_version stdcall, version:dword
|
||||
proc serial_port_get_version stdcall uses ebx, version:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
@@ -149,7 +166,7 @@ endl
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
|
||||
ret
|
||||
endp
|
||||
|
||||
@@ -297,6 +314,43 @@ endl
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_enum stdcall uses ebx, buf:dword, buf_size:dword, \
|
||||
total:dword, filled:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
.input dd ?
|
||||
.inp_size dd ?
|
||||
.output dd ?
|
||||
.out_size dd ?
|
||||
endl
|
||||
push [buf_size]
|
||||
push [buf]
|
||||
mov eax, [serial_drv_handle]
|
||||
mov [.handler], eax
|
||||
mov dword [.io_code], SERIAL_API_ENUM_PORTS
|
||||
mov [.input], esp
|
||||
mov dword [.inp_size], 8
|
||||
sub esp, 8
|
||||
mov [.output], esp
|
||||
mov dword [.out_size], 8
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
pop ebx edx
|
||||
cmp eax, -1
|
||||
je .err
|
||||
mov ecx, [total]
|
||||
mov [ecx], ebx
|
||||
mov ecx, [filled]
|
||||
mov [ecx], edx
|
||||
.err:
|
||||
|
||||
add esp, 8
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
serial_drv_name db "SERIAL", 0
|
||||
serial_drv_handle dd ?
|
||||
@@ -1,5 +0,0 @@
|
||||
#SHS
|
||||
echo Installing serial driver for kterm...
|
||||
cp /kolibrios/utils/kterm/serial.sys /sys/drivers/
|
||||
/sys/loaddrv serial
|
||||
echo Serial driver successfully installed!
|
||||
+148
-7
@@ -44,6 +44,8 @@ struct SERIAL_PORT
|
||||
rx_buf RING_BUF
|
||||
tx_buf RING_BUF
|
||||
conf SP_CONF
|
||||
driver rb SERIAL_INFO_DRIVER_LEN ; ASCIIZ, copied from SP_PORT_INFO.driver in add_port
|
||||
descr rb SERIAL_INFO_DESCR_LEN ; ASCIIZ, copied from SP_PORT_INFO.descr in add_port (may be empty)
|
||||
ends
|
||||
|
||||
proc START c, reason:dword, cmdline:dword
|
||||
@@ -57,7 +59,7 @@ proc START c, reason:dword, cmdline:dword
|
||||
stdcall uart_probe, 0x2f8, 3
|
||||
stdcall uart_probe, 0x3e8, 4
|
||||
stdcall uart_probe, 0x2e8, 3
|
||||
invoke RegService, drv_name, service_proc
|
||||
invoke RegService, serial_drv_name, service_proc
|
||||
ret
|
||||
|
||||
.fail:
|
||||
@@ -75,7 +77,7 @@ srv_calls:
|
||||
dd service_proc.setup
|
||||
dd service_proc.read
|
||||
dd service_proc.write
|
||||
; TODO enumeration
|
||||
dd service_proc.enum_ports
|
||||
srv_calls_end:
|
||||
|
||||
proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
@@ -97,11 +99,13 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
; in:
|
||||
; +0: driver
|
||||
; +4: driver data
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
; +8: port info (SP_PORT_INFO*)
|
||||
cmp [edx + IOCTL.inp_size], 12
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
mov ecx, [ebx]
|
||||
mov edx, [ebx + 4]
|
||||
mov ebx, [ebx + 8]
|
||||
call add_port
|
||||
ret
|
||||
|
||||
@@ -137,6 +141,7 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
; +4 addr to SERIAL_CONF
|
||||
; out:
|
||||
; +0 port handle if success
|
||||
; eax = 0 if success, otherwise an error code SERIAL_API_ERR_*
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 4
|
||||
@@ -220,25 +225,60 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
mov [ebx], ecx
|
||||
ret
|
||||
|
||||
.enum_ports:
|
||||
; in:
|
||||
; +0 output buffer (array of SP_PORT_ENUM_ENTRY), may be NULL
|
||||
; +4 output buffer size in bytes
|
||||
; out:
|
||||
; +0 total number of ports in the system
|
||||
; +4 number of entries actually filled into the buffer
|
||||
; eax = 0 if success, -1 otherwise
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 8
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
push edx
|
||||
mov eax, [ebx]
|
||||
mov edx, [ebx + 4]
|
||||
call sp_enum
|
||||
pop edx
|
||||
mov ebx, [edx + IOCTL.output]
|
||||
mov [ebx], eax
|
||||
mov [ebx + 4], ecx
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
.err:
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
|
||||
; struct SERIAL_PORT __fastcall *add_port(const struct SP_DRIVER *drv, const void *drv_data);
|
||||
align 4
|
||||
; @param ecx pointer to SP_DRIVER
|
||||
; @param edx driver-specific argument
|
||||
; @param ebx pointer to SP_PORT_INFO
|
||||
; @return SERIAL_PORT descriptor
|
||||
proc add_port uses edi
|
||||
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x\n", ecx, edx
|
||||
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x info=%x\n", ecx, edx, ebx
|
||||
|
||||
mov eax, [ecx + SP_DRIVER.size]
|
||||
cmp eax, sizeof.SP_DRIVER
|
||||
jne .fail
|
||||
|
||||
test ebx, ebx
|
||||
jz .fail
|
||||
mov eax, [ebx + SP_PORT_INFO.size]
|
||||
cmp eax, sizeof.SP_PORT_INFO
|
||||
jne .fail
|
||||
|
||||
; alloc memory for serial port descriptor
|
||||
push ecx
|
||||
push edx
|
||||
push ebx
|
||||
movi eax, sizeof.SERIAL_PORT
|
||||
invoke Kmalloc
|
||||
pop ebx
|
||||
pop edx
|
||||
pop ecx
|
||||
test eax, eax
|
||||
@@ -252,6 +292,17 @@ proc add_port uses edi
|
||||
invoke MutexInit
|
||||
and [edi + SERIAL_PORT.con], 0
|
||||
|
||||
; copy port info strings
|
||||
mov eax, [ebx + SP_PORT_INFO.driver]
|
||||
lea edx, [edi + SERIAL_PORT.driver]
|
||||
mov ecx, SERIAL_INFO_DRIVER_LEN
|
||||
call copy_bounded_str
|
||||
|
||||
mov eax, [ebx + SP_PORT_INFO.descr]
|
||||
lea edx, [edi + SERIAL_PORT.descr]
|
||||
mov ecx, SERIAL_INFO_DESCR_LEN
|
||||
call copy_bounded_str
|
||||
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexLock
|
||||
|
||||
@@ -282,7 +333,35 @@ proc add_port uses edi
|
||||
endp
|
||||
|
||||
align 4
|
||||
; u32 __fastcall *remove_port(struct SERIAL_PORT *port);
|
||||
; copies an ASCIIZ string into a fixed-size buffer: copies up to (size - 1)
|
||||
; bytes or until the NUL, then zero-pads the rest of the buffer
|
||||
; @param eax source ASCIIZ ptr, may be NULL
|
||||
; @param edx dest buffer ptr
|
||||
; @param ecx dest buffer size in bytes, must be >= 1
|
||||
proc copy_bounded_str uses esi edi
|
||||
mov esi, eax
|
||||
mov edi, edx
|
||||
dec ecx ; reserve the last byte for the NUL terminator
|
||||
.copy:
|
||||
test ecx, ecx
|
||||
jz .pad
|
||||
test esi, esi
|
||||
jz .pad
|
||||
lodsb
|
||||
test al, al
|
||||
jz .pad
|
||||
stosb
|
||||
dec ecx
|
||||
jmp .copy
|
||||
.pad:
|
||||
inc ecx ; account for the reserved NUL byte
|
||||
xor al, al
|
||||
rep stosb
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
; @param ecx serial port descriptor
|
||||
proc remove_port uses esi
|
||||
mov esi, ecx
|
||||
mov ecx, port_list_mutex
|
||||
@@ -657,7 +736,69 @@ proc sp_write
|
||||
ret
|
||||
endp
|
||||
|
||||
drv_name db 'SERIAL', 0
|
||||
align 4
|
||||
; @param eax buf
|
||||
; @param edx buf_size (bytes)
|
||||
; @return eax total port count in the system
|
||||
; ecx entries filled into buf
|
||||
proc sp_enum uses ebx esi edi
|
||||
mov ecx, eax
|
||||
mov eax, edx
|
||||
xor edx, edx
|
||||
mov ebx, sizeof.SP_PORT_ENUM_ENTRY
|
||||
div ebx
|
||||
; eax max entries count
|
||||
|
||||
mov edi, ecx
|
||||
imul eax, sizeof.SP_PORT_ENUM_ENTRY
|
||||
add eax, ecx
|
||||
mov edx, eax ; end-of-buffer boundary
|
||||
|
||||
xor ebx, ebx ; total port count
|
||||
xor ecx, ecx ; filled count
|
||||
|
||||
push ecx edx
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexLock
|
||||
pop edx ecx
|
||||
|
||||
mov esi, port_list
|
||||
.next:
|
||||
mov esi, [esi + SERIAL_PORT.fd]
|
||||
cmp esi, port_list
|
||||
jz .done
|
||||
inc ebx
|
||||
cmp edi, edx
|
||||
jae .next
|
||||
|
||||
mov eax, [esi + SERIAL_PORT.id]
|
||||
mov [edi + SP_PORT_ENUM_ENTRY.id], eax
|
||||
xor eax, eax
|
||||
cmp dword [esi + SERIAL_PORT.con], 0
|
||||
setnz al
|
||||
mov [edi + SP_PORT_ENUM_ENTRY.busy], eax
|
||||
|
||||
push ecx esi edi
|
||||
lea esi, [esi + SERIAL_PORT.driver]
|
||||
lea edi, [edi + SP_PORT_ENUM_ENTRY.driver]
|
||||
mov ecx, (SERIAL_INFO_DRIVER_LEN + SERIAL_INFO_DESCR_LEN) / 4
|
||||
rep movsd
|
||||
pop edi esi ecx
|
||||
|
||||
add edi, sizeof.SP_PORT_ENUM_ENTRY
|
||||
inc ecx
|
||||
jmp .next
|
||||
|
||||
.done:
|
||||
push ecx
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexUnlock
|
||||
pop ecx
|
||||
|
||||
mov eax, ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
include_debug_strings
|
||||
|
||||
align 4
|
||||
|
||||
@@ -169,6 +169,7 @@ proc uart_probe stdcall uses ebx esi edi, io_addr:dword, irqn:dword
|
||||
; register port
|
||||
lea ecx, [uart_drv]
|
||||
mov edx, edi
|
||||
lea ebx, [uart_port_info]
|
||||
call add_port
|
||||
test eax, eax
|
||||
jz .free_desc ; TODO detach_int_handler?
|
||||
@@ -406,3 +407,11 @@ uart_drv:
|
||||
dd uart_reconf
|
||||
dd uart_tx
|
||||
uart_drv_end:
|
||||
|
||||
align 4
|
||||
uart_port_info:
|
||||
dd uart_port_end - uart_port_info
|
||||
dd uart_port_name
|
||||
dd 0
|
||||
uart_port_end:
|
||||
uart_port_name db 'uart16550', 0
|
||||
+203
-310
@@ -1,6 +1,6 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2026. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; FTDI chips driver for KolibriOS ;;
|
||||
@@ -15,10 +15,11 @@
|
||||
format PE DLL native 0.05
|
||||
entry START
|
||||
|
||||
DEBUG = 1
|
||||
L_DBG = 1
|
||||
L_ERR = 2
|
||||
|
||||
__DEBUG__ = 1
|
||||
__DEBUG_LEVEL__ = 1
|
||||
__DEBUG_LEVEL__ = L_ERR
|
||||
|
||||
node equ ftdi_context
|
||||
node.next equ ftdi_context.next_context
|
||||
@@ -122,9 +123,10 @@ TYPE_232H=6
|
||||
TYPE_230X=7
|
||||
|
||||
;strings
|
||||
my_driver db 'usbother',0
|
||||
my_driver db 'usbftdi',0
|
||||
serial_driver db 'SERIAL',0
|
||||
nomemory_msg db 'K : no memory',13,10,0
|
||||
nomemory_msg db 'ftdi: no memory',13,10,0
|
||||
ftdi_port_name db 'ftdi',0
|
||||
|
||||
; Structures
|
||||
struct ftdi_context
|
||||
@@ -200,10 +202,13 @@ endp
|
||||
|
||||
|
||||
proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD, .interface:DWORD
|
||||
|
||||
locals
|
||||
.pinfo rb sizeof.SP_PORT_INFO
|
||||
endl
|
||||
|
||||
invoke USBGetParam, [.config_pipe], 0
|
||||
mov edx, eax
|
||||
DEBUGF 2,'K : Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
|
||||
DEBUGF L_DBG, 'ftdi: Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
|
||||
cmp word[eax+usb_descr.idVendor], 0x0403
|
||||
jnz .notftdi
|
||||
mov eax, sizeof.ftdi_context
|
||||
@@ -214,7 +219,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
invoke SysMsgBoardStr
|
||||
jmp .nothing
|
||||
@@:
|
||||
DEBUGF 2,'K : Adding struct to list 0x%x\n', eax
|
||||
DEBUGF L_DBG, 'ftdi: Adding struct to list 0x%x\n', eax
|
||||
call linkedlist_add
|
||||
|
||||
mov ebx, [.config_pipe]
|
||||
@@ -233,7 +238,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
jmp .slow
|
||||
|
||||
mov cx, [edx+usb_descr.bcdDevice]
|
||||
DEBUGF 2, 'K : Chip type 0x%x\n', ecx
|
||||
DEBUGF L_DBG, 'ftdi: Chip type 0x%x\n', ecx
|
||||
cmp cx, 0x400
|
||||
jnz @f
|
||||
mov [eax + ftdi_context.chipType], TYPE_BM
|
||||
@@ -287,8 +292,13 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
mov eax, [serial_drv_entry]
|
||||
test eax, eax
|
||||
jz @f
|
||||
stdcall serial_add_port, uart_drv, ebx
|
||||
DEBUGF 1, "usbftdi: add serial port with result %x\n", eax
|
||||
mov dword [.pinfo + SP_PORT_INFO.size], sizeof.SP_PORT_INFO
|
||||
mov dword [.pinfo + SP_PORT_INFO.driver], ftdi_port_name
|
||||
; TODO obtain iManufacturer, iProduct and iSerial strings
|
||||
mov dword [.pinfo + SP_PORT_INFO.descr], 0
|
||||
lea ecx, [.pinfo]
|
||||
stdcall serial_add_port, uart_drv, ebx, ecx
|
||||
DEBUGF L_DBG, 'ftdi: add serial port with result %x\n', eax
|
||||
@@:
|
||||
mov [ebx + ftdi_context.port_handle], eax
|
||||
|
||||
@@ -296,7 +306,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
ret
|
||||
|
||||
.notftdi:
|
||||
DEBUGF 1,'K : Skipping not FTDI device\n'
|
||||
DEBUGF L_DBG, 'ftdi: Skipping not FTDI device\n'
|
||||
.nothing:
|
||||
xor eax, eax
|
||||
ret
|
||||
@@ -317,7 +327,7 @@ EventData rd 3
|
||||
endl
|
||||
mov edi, [ioctl]
|
||||
mov eax, [edi+io_code]
|
||||
DEBUGF 1,'K : FTDI got the request: %d\n', eax
|
||||
DEBUGF L_DBG, 'ftdi: FTDI got the request: %d\n', eax
|
||||
test eax, eax ;0
|
||||
jz .version
|
||||
dec eax ;1
|
||||
@@ -416,7 +426,7 @@ endl
|
||||
.version:
|
||||
jmp .endswitch
|
||||
.error:
|
||||
DEBUGF 1, 'K : FTDI error occured! %d\n', eax
|
||||
DEBUGF L_ERR, 'ftdi: error occured! %d\n', eax
|
||||
;mov esi, [edi+output]
|
||||
;mov [esi], dword 'ERR0'
|
||||
;or [esi], eax
|
||||
@@ -449,7 +459,7 @@ endl
|
||||
mov word[ConfPacket+6], cx
|
||||
.own_index:
|
||||
mov ebx, [edi+4]
|
||||
DEBUGF 2,'K : ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
|
||||
DEBUGF L_DBG, 'ftdi: ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
|
||||
lea esi, [ConfPacket]
|
||||
lea edi, [EventData]
|
||||
invoke USBControlTransferAsync, [ebx + ftdi_context.nullP], esi, 0,\
|
||||
@@ -465,7 +475,7 @@ endl
|
||||
jmp .error
|
||||
|
||||
.ftdi_setrtshigh:
|
||||
DEBUGF 2,'K : FTDI Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -473,7 +483,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setrtslow:
|
||||
DEBUGF 2,'K : FTDI Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -481,7 +491,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setdtrhigh:
|
||||
DEBUGF 2,'K : FTDI Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -489,7 +499,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setdtrlow:
|
||||
DEBUGF 2,'K : FTDI Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -497,7 +507,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_usb_reset:
|
||||
DEBUGF 2,'K : FTDI Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -505,7 +515,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_purge_rx_buf:
|
||||
DEBUGF 2, 'K : FTDI Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -513,7 +523,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_purge_tx_buf:
|
||||
DEBUGF 2, 'K : FTDI Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -521,42 +531,42 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_set_bitmode:
|
||||
DEBUGF 2, 'K : FTDI Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8]:2,[edi+10]:2,[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BITMODE_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_line_property:
|
||||
DEBUGF 2, 'K : FTDI Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8]:4,[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_DATA_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_latency_timer:
|
||||
DEBUGF 2, 'K : FTDI Set latency %d PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set latency %d PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_LATENCY_TIMER_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_event_char:
|
||||
DEBUGF 2, 'K : FTDI Set event char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set event char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_EVENT_CHAR_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_error_char:
|
||||
DEBUGF 2, 'K : FTDI Set error char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set error char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_ERROR_CHAR_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_setflowctrl:
|
||||
DEBUGF 2, 'K : FTDI Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_FLOW_CTRL_REQUEST shl 8) + (0 shl 16)
|
||||
@@ -569,7 +579,7 @@ endl
|
||||
jmp .own_index
|
||||
|
||||
.ftdi_read_pins:
|
||||
DEBUGF 2, 'K : FTDI Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
|
||||
@@ -598,7 +608,7 @@ endl
|
||||
jmp .error
|
||||
|
||||
.ftdi_set_wchunksize:
|
||||
DEBUGF 2, 'K : FTDI Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov ecx, [edi+8]
|
||||
@@ -608,7 +618,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_wchunksize:
|
||||
DEBUGF 2, 'K : FTDI Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov esi, [edi+output]
|
||||
mov edi, [edi+input]
|
||||
@@ -618,7 +628,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_set_rchunksize:
|
||||
DEBUGF 2, 'K : FTDI Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov ecx, [edi+8]
|
||||
@@ -628,7 +638,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_rchunksize:
|
||||
DEBUGF 2, 'K : FTDI Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov esi, [edi+output]
|
||||
mov edi, [edi+input]
|
||||
@@ -638,7 +648,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_write_data:
|
||||
DEBUGF 2, 'K : FTDI Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
DEBUGF L_DBG, 'ftdi: Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
[edi], [edi+4]
|
||||
mov esi, edi
|
||||
add esi, 12
|
||||
@@ -685,7 +695,7 @@ endl
|
||||
jmp .write_loop
|
||||
|
||||
.ftdi_read_data:
|
||||
DEBUGF 2, 'K : FTDI Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
DEBUGF L_DBG, 'ftdi: Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
[edi], [edi+4]
|
||||
mov edi, [ioctl]
|
||||
mov esi, [edi+input]
|
||||
@@ -743,7 +753,7 @@ endl
|
||||
;---Dirty hack end
|
||||
|
||||
.ftdi_poll_modem_status:
|
||||
DEBUGF 2, 'K : FTDI Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
|
||||
@@ -767,7 +777,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_latency_timer:
|
||||
DEBUGF 2, 'K : FTDI Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], FTDI_DEVICE_IN_REQTYPE \
|
||||
@@ -787,7 +797,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_list:
|
||||
DEBUGF 2, 'K : FTDI devices list request\n'
|
||||
DEBUGF L_DBG, 'ftdi: devices list request\n'
|
||||
mov edi, [edi+output]
|
||||
xor ecx, ecx
|
||||
call linkedlist_gethead
|
||||
@@ -817,7 +827,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_lock:
|
||||
DEBUGF 2, 'K : FTDI Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
DEBUGF L_DBG, 'ftdi: Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
mov esi, [edi+input]
|
||||
mov ebx, [esi+4]
|
||||
mov eax, [ebx + ftdi_context.lockPID]
|
||||
@@ -831,7 +841,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_unlock:
|
||||
DEBUGF 2, 'K : FTDI Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
DEBUGF L_DBG, 'ftdi: Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
mov esi, [edi+input]
|
||||
mov edi, [edi+output]
|
||||
mov ebx, [esi+4]
|
||||
@@ -845,145 +855,19 @@ endl
|
||||
mov [edi], eax
|
||||
jmp .endswitch
|
||||
|
||||
H_CLK = 120000000
|
||||
C_CLK = 48000000
|
||||
.ftdi_set_baudrate:
|
||||
DEBUGF 2, 'K : FTDI Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
|
||||
DEBUGF L_DBG, 'ftdi: Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, [edi+8], 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp dword[edi+8], H_CLK/10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK/10
|
||||
jmp .calcend
|
||||
|
||||
.c_clk:
|
||||
cmp dword[edi+8], C_CLK/16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK/16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp dword[edi+8], H_CLK/(10 + 10/2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK/(10 + 10/2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp dword[edi+8], C_CLK/(16 + 16/2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16/2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp dword[edi+8], H_CLK/(2*10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK/(2*10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp dword[edi+8], C_CLK/(2*16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK/(2*16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK*16/10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword[edi+8] ; [edi+8] - baudrate
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK*16/10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword[edi+8] ; [edi+8] - baudrate
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp+eax*4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
jmp .preparepacket
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
|
||||
.preparepacket:
|
||||
mov esi, [edi+8]
|
||||
call ftdi_calc_baud_divisor
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
|
||||
mov word[ConfPacket+2], ax
|
||||
mov word[ConfPacket+4], cx
|
||||
mov word[ConfPacket+6], 0
|
||||
jmp .own_index
|
||||
|
||||
jmp .own_index
|
||||
|
||||
endp
|
||||
restore handle
|
||||
restore io_code
|
||||
@@ -993,10 +877,143 @@ restore output
|
||||
restore out_size
|
||||
|
||||
|
||||
proc ftdi_calc_baud_divisor
|
||||
; in: ebx = ftdi_context pointer
|
||||
; esi = baud rate
|
||||
; out: ax = encoded value
|
||||
; cx = encoded index
|
||||
; destroys: eax, ecx, edx, esi
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, esi, 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp esi, H_CLK / 10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK / 10
|
||||
jmp .calcend
|
||||
|
||||
.c_clk:
|
||||
cmp esi, C_CLK / 16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK / 16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp esi, H_CLK / (10 + 10 / 2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK / (10 + 10 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp esi, C_CLK / (16 + 16 / 2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp esi, H_CLK / (2 * 10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK / (2 * 10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp esi, C_CLK / (2 * 16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK / (2 * 16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div esi
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK * 16 / 10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div esi
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp + eax * 4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
ret
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
ret
|
||||
endp
|
||||
|
||||
proc control_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
.buffer:DWORD, .length:DWORD, .calldata:DWORD
|
||||
|
||||
DEBUGF 1, 'K : status is %d\n', [.status]
|
||||
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
|
||||
mov ecx, [.calldata]
|
||||
mov eax, [ecx]
|
||||
mov ebx, [ecx+4]
|
||||
@@ -1011,7 +1028,7 @@ endp
|
||||
proc bulk_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
.buffer:DWORD, .length:DWORD, .calldata:DWORD
|
||||
|
||||
DEBUGF 1, 'K : status is %d\n', [.status]
|
||||
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
|
||||
mov ecx, [.calldata]
|
||||
mov eax, [ecx]
|
||||
mov ebx, [ecx+4]
|
||||
@@ -1034,7 +1051,7 @@ endp
|
||||
|
||||
proc DeviceDisconnected stdcall uses ebx esi edi, .device_data:DWORD
|
||||
|
||||
DEBUGF 1, 'K : FTDI deleting device data 0x%x\n', [.device_data]
|
||||
DEBUGF L_DBG, 'ftdi: deleting device data 0x%x\n', [.device_data]
|
||||
mov esi, [.device_data]
|
||||
mov eax, [esi + ftdi_context.readBufPtr]
|
||||
test eax, eax
|
||||
@@ -1062,7 +1079,7 @@ proc bulk_in_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
mov eax, [.status]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF 2, 'ftdi: bulk in error %x\n', eax
|
||||
DEBUGF L_ERR, 'ftdi: bulk in error %x\n', eax
|
||||
@@:
|
||||
mov ebx, [.calldata]
|
||||
btr dword [ebx + ftdi_context.writeBufLock], 0
|
||||
@@ -1075,7 +1092,7 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
mov eax, [.status]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF 2, 'ftdi: bulk out error %x\n', eax
|
||||
DEBUGF L_ERR, 'ftdi: bulk out error %x\n', eax
|
||||
@@:
|
||||
mov ebx, [.calldata]
|
||||
mov ecx, [.length]
|
||||
@@ -1092,18 +1109,18 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
endp
|
||||
|
||||
proc uart_startup stdcall uses ebx, data:dword, conf:dword
|
||||
DEBUGF 1, "ftdi: startup %x %x\n", [data], [conf]
|
||||
DEBUGF L_DBG, "ftdi: startup %x %x\n", [data], [conf]
|
||||
stdcall uart_reconf, [data], [conf]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF 2, "ftdi: uart reconf error %x\n", eax
|
||||
DEBUGF L_ERR, "ftdi: uart reconf error %x\n", eax
|
||||
jmp .exit
|
||||
@@:
|
||||
mov ebx, [data]
|
||||
invoke TimerHS, 2, 2, uart_rx, ebx
|
||||
test eax, eax
|
||||
jnz @f
|
||||
DEBUGF 2, "ftdi: timer creation error\n"
|
||||
DEBUGF L_ERR, "ftdi: timer creation error\n"
|
||||
or eax, -1
|
||||
jmp .exit
|
||||
@@:
|
||||
@@ -1114,7 +1131,7 @@ proc uart_startup stdcall uses ebx, data:dword, conf:dword
|
||||
endp
|
||||
|
||||
proc uart_shutdown stdcall uses ebx, data:dword
|
||||
DEBUGF 1, "ftdi: shutdown %x\n", [data]
|
||||
DEBUGF L_DBG, "ftdi: shutdown %x\n", [data]
|
||||
mov ebx, [data]
|
||||
cmp [ebx + ftdi_context.rx_timer], 0
|
||||
jz @f
|
||||
@@ -1246,137 +1263,14 @@ proc uart_rx stdcall uses ebx esi, data:dword
|
||||
ret
|
||||
endp
|
||||
|
||||
proc ftdi_set_baudrate stdcall uses ebx, dev:dword, baud:dword
|
||||
proc ftdi_set_baudrate stdcall uses ebx esi, dev:dword, baud:dword
|
||||
locals
|
||||
ConfPacket rb 8
|
||||
endl
|
||||
mov ebx, [dev]
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, [baud], 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp dword [baud], H_CLK / 10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK / 10
|
||||
jmp .calcend
|
||||
mov esi, [baud]
|
||||
call ftdi_calc_baud_divisor
|
||||
|
||||
.c_clk:
|
||||
cmp dword [baud], C_CLK / 16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK / 16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp dword [baud], H_CLK / (10 + 10 / 2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK / (10 + 10 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp dword [baud], C_CLK / (16 + 16 / 2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp dword [baud], H_CLK / (2 * 10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK / (2 * 10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp dword [baud], C_CLK / (2 * 16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK / (2 * 16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword [baud]
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK * 16 / 10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword [baud]
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp + eax * 4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
jmp .preparepacket
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
|
||||
.preparepacket:
|
||||
mov word [ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
|
||||
mov word [ConfPacket + 2], ax
|
||||
@@ -1451,10 +1345,9 @@ uart_drv:
|
||||
dd uart_tx
|
||||
uart_drv_end:
|
||||
|
||||
serial_drv_entry dd 0
|
||||
include_debug_strings
|
||||
|
||||
data fixups
|
||||
end data
|
||||
|
||||
;for DEBUGF macro
|
||||
include_debug_strings
|
||||
|
||||
serial_drv_entry dd ?
|
||||
@@ -2204,6 +2204,9 @@ proc acm_arm_rx
|
||||
endp
|
||||
|
||||
proc acm_add_device stdcall uses ebx esi edi, .pipe0:dword, .config:dword, .interface:dword
|
||||
locals
|
||||
.pinfo rb sizeof.SP_PORT_INFO
|
||||
endl
|
||||
|
||||
; 1. Parse the descriptors (the ACM data interface is alt setting 0).
|
||||
xor eax, eax
|
||||
@@ -2264,7 +2267,12 @@ proc acm_add_device stdcall uses ebx esi edi, .pipe0:dword, .config:dword, .inte
|
||||
|
||||
cmp [serial_drv_entry], 0
|
||||
je .no_serial
|
||||
stdcall serial_add_port, acm_sp_driver, ebx
|
||||
mov dword [.pinfo+SP_PORT_INFO.size], sizeof.SP_PORT_INFO
|
||||
mov dword [.pinfo+SP_PORT_INFO.driver], acm_port_name
|
||||
; TODO obtain iManufacturer, iProduct and iSerial strings
|
||||
mov dword [.pinfo+SP_PORT_INFO.descr], 0
|
||||
lea ecx, [.pinfo]
|
||||
stdcall serial_add_port, acm_sp_driver, ebx, ecx
|
||||
mov [ebx+acm_dev.PortHandle], eax
|
||||
test eax, eax
|
||||
jz .no_serial
|
||||
@@ -2652,6 +2660,7 @@ endp
|
||||
|
||||
; strings and static data
|
||||
my_service db 'usbcdc', 0
|
||||
acm_port_name db 'cdc-acm', 0
|
||||
netdev_name db 'USB CDC-NCM', 0
|
||||
ecm_netdev_name db 'USB CDC-ECM', 0
|
||||
ecm_zlp_dummy db 0 ; address for zero-length transfers
|
||||
|
||||
@@ -1721,7 +1721,8 @@ endp
|
||||
; out: eax = 1 if the interrupt came from this controller, 0 otherwise
|
||||
align 4
|
||||
ahci_irq_handler:
|
||||
mov esi, [esp + 4]
|
||||
push ebx esi edi
|
||||
mov esi, [esp + 12 + 4]
|
||||
test esi, esi
|
||||
jz .not_our
|
||||
mov edx, [esi + AHCI_CTR.abar]
|
||||
@@ -1786,9 +1787,11 @@ ahci_irq_handler:
|
||||
@@:
|
||||
pop eax
|
||||
mov eax, 1
|
||||
pop edi esi ebx
|
||||
ret
|
||||
.not_our:
|
||||
xor eax, eax
|
||||
pop edi esi ebx
|
||||
ret
|
||||
|
||||
|
||||
|
||||
@@ -1489,19 +1489,31 @@ dyndisk_handler:
|
||||
; 12. The fs operation has specified some partition.
|
||||
push edx ecx
|
||||
xor eax, eax
|
||||
mov ecx, eax
|
||||
lodsb
|
||||
@@:
|
||||
lea ecx, [ecx*4 + ecx]
|
||||
shl ecx, 1
|
||||
|
||||
sub eax, '0'
|
||||
jz .dyndisk_cleanup
|
||||
jb .dyndisk_cleanup
|
||||
cmp eax, 10
|
||||
jnc .dyndisk_cleanup
|
||||
mov ecx, eax
|
||||
|
||||
add ecx, eax
|
||||
cmp ecx, MAX_NUM_PARTITIONS
|
||||
ja .dyndisk_cleanup
|
||||
|
||||
lodsb
|
||||
cmp eax, '/'
|
||||
jz @f
|
||||
test eax, eax
|
||||
jnz .dyndisk_cleanup
|
||||
jnz @b
|
||||
dec esi
|
||||
@@:
|
||||
test ecx, ecx
|
||||
jz .dyndisk_cleanup
|
||||
|
||||
cmp byte [esi], 0
|
||||
jnz @f
|
||||
; partition info
|
||||
|
||||
@@ -12,6 +12,13 @@
|
||||
; Source code author - Kulakov Vladimir Gennadievich.
|
||||
; Adaptation and improvement - Mario79.
|
||||
|
||||
give_back_application_data_1:
|
||||
mov esi, FDD_BUFF;FDD_DataBuffer ;0x40000
|
||||
mov ecx, 128
|
||||
cld
|
||||
rep movsd
|
||||
ret
|
||||
|
||||
take_data_from_application_1:
|
||||
mov edi, FDD_BUFF;FDD_DataBuffer ;0x40000
|
||||
mov ecx, 128
|
||||
@@ -710,38 +717,18 @@ endg
|
||||
; This function is called in boot process.
|
||||
; It creates filesystems /fd and/or /fd2, if the system has one/two floppy drives.
|
||||
proc floppy_init
|
||||
; search for FDDs and add them to the list of disks
|
||||
; author - Mario79
|
||||
mov al, 0x10
|
||||
out 0x70, al
|
||||
mov cx, 0xff
|
||||
.wait_cmos:
|
||||
dec cx
|
||||
test cx, cx
|
||||
jnz .wait_cmos
|
||||
in al, 0x71
|
||||
test al, al
|
||||
jz .no_fdd
|
||||
|
||||
push eax ; b[esp]=al [esp+1..3]- ??
|
||||
|
||||
stdcall attach_int_handler, 6, FDCInterrupt, 0
|
||||
DEBUGF 1, "K : Set Floppy IRQ6 return code %x\n", eax
|
||||
|
||||
mov ecx, floppy_mutex
|
||||
call mutex_init
|
||||
; First floppy is present if [esp] and 0xF0 is nonzero.
|
||||
test byte [esp], 0xF0
|
||||
; First floppy is present if [DRIVE_DATA] and 0xF0 is nonzero.
|
||||
test byte [DRIVE_DATA], 0xF0
|
||||
jz .no1
|
||||
stdcall disk_add, floppy_functions, floppy1_name, 1, DISK_NO_INSERT_NOTIFICATION
|
||||
.no1:
|
||||
; Second floppy is present if [esp] and 0x0F is nonzero.
|
||||
test byte [esp], 0x0F
|
||||
; Second floppy is present if [DRIVE_DATA] and 0x0F is nonzero.
|
||||
test byte [DRIVE_DATA], 0x0F
|
||||
jz .no2
|
||||
stdcall disk_add, floppy_functions, floppy2_name, 2, DISK_NO_INSERT_NOTIFICATION
|
||||
.no2:
|
||||
add esp, 4
|
||||
.no_fdd:
|
||||
ret
|
||||
endp
|
||||
|
||||
|
||||
@@ -18,7 +18,24 @@ saverd_fileinfo:
|
||||
.name:
|
||||
dd ?
|
||||
endg
|
||||
sysfn_saveramdisk: ; 18.6 = SAVE FLOPPY IMAGE (HD version only)
|
||||
sysfn_saveramdisk: ; 18.6 = SAVE RAMDISK IMAGE
|
||||
; ecx -> path to the image file; ecx = 0 - write the image back to the
|
||||
; medium it was booted from (a floppy or the file found by rdload.inc)
|
||||
test ecx, ecx
|
||||
jnz .have_path
|
||||
if ~ defined extended_primary_loader
|
||||
mov ecx, read_image_fsinfo.name
|
||||
cmp [BOOT.rd_load_from], RD_LOAD_FROM_HD
|
||||
je .have_path
|
||||
end if
|
||||
movi eax, ERROR_UNSUPPORTED_FS
|
||||
cmp [BOOT.rd_load_from], RD_LOAD_FROM_FLOPPY
|
||||
jne .done
|
||||
mov ebx, 1
|
||||
call save_image
|
||||
imul eax, ERROR_DEVICE ; 0 -> 0, 1 -> ERROR_DEVICE
|
||||
jmp .done
|
||||
.have_path:
|
||||
mov ebx, saverd_fileinfo
|
||||
mov [ebx+21], ecx
|
||||
mov eax, [ramdisk_actual_size]
|
||||
@@ -27,5 +44,6 @@ sysfn_saveramdisk: ; 18.6 = SAVE FLOPPY IMAGE (HD version only)
|
||||
pushad
|
||||
call file_system_lfn_protected ;in ebx
|
||||
popad
|
||||
.done:
|
||||
mov [esp+32], eax
|
||||
ret
|
||||
@@ -878,6 +878,37 @@ struct PCIDEV
|
||||
owner dd ? ; pointer to SRV or 0
|
||||
ends
|
||||
|
||||
struct IDE_DATA
|
||||
ProgrammingInterface dd ?
|
||||
Interrupt dw ?
|
||||
RegsBaseAddres dw ?
|
||||
BAR0_val dw ?
|
||||
BAR1_val dw ?
|
||||
BAR2_val dw ?
|
||||
BAR3_val dw ?
|
||||
dma_hdd_channel_1 db ?
|
||||
dma_hdd_channel_2 db ?
|
||||
pcidev dd ? ; pointer to corresponding PCIDEV structure
|
||||
ends
|
||||
|
||||
struct IDE_CACHE
|
||||
pointer dd ?
|
||||
size dd ? ; not use
|
||||
data_pointer dd ?
|
||||
system_data_size dd ? ; not use
|
||||
appl_data_size dd ? ; not use
|
||||
system_data dd ?
|
||||
appl_data dd ?
|
||||
system_sad_size dd ?
|
||||
appl_sad_size dd ?
|
||||
search_start dd ?
|
||||
appl_search_start dd ?
|
||||
ends
|
||||
|
||||
struct IDE_DEVICE
|
||||
UDMA_possible_modes db ?
|
||||
UDMA_set_mode db ?
|
||||
ends
|
||||
|
||||
; The following macro assume that we are on uniprocessor machine.
|
||||
; Serious work is needed for multiprocessor machines.
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
;***************************************************
|
||||
; clear the DRIVE_DATA table,
|
||||
; search for FDDs and add them into the table
|
||||
; author - Mario79
|
||||
;***************************************************
|
||||
xor eax, eax
|
||||
mov edi, DRIVE_DATA
|
||||
mov ecx, DRIVE_DATA_SIZE/4
|
||||
cld
|
||||
rep stosd
|
||||
|
||||
mov al, 0x10
|
||||
out 0x70, al
|
||||
mov cx, 0xff
|
||||
wait_cmos:
|
||||
dec cx
|
||||
test cx, cx
|
||||
jnz wait_cmos
|
||||
in al, 0x71
|
||||
mov [DRIVE_DATA], al
|
||||
test al, al
|
||||
jz @f
|
||||
|
||||
stdcall attach_int_handler, 6, FDCInterrupt, 0
|
||||
DEBUGF 1, "K : Set IDE IRQ6 return code %x\n", eax
|
||||
call floppy_init
|
||||
@@:
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
include 'dev_fd.inc'
|
||||
include 'dev_hdcd.inc'
|
||||
include 'getcache.inc'
|
||||
include 'sear_par.inc'
|
||||
|
||||
+334
-689
File diff suppressed because it is too large.
Load diff
+107
-17
@@ -781,12 +781,21 @@ picture rb Xsize*Ysize*4 ; 32 бита
|
||||
* ebx = 6 - номер подфункции
|
||||
* ecx = указатель на строку с полным именем файла
|
||||
(например, "/hd0/1/kolibri/kolibri.img")
|
||||
* ecx = 0 - записать образ обратно на носитель, с которого была
|
||||
загружена система: на дискету или в файл образа, найденный при
|
||||
загрузке на разделе жёсткого диска
|
||||
Возвращаемое значение:
|
||||
* eax = 0 - успешно
|
||||
* иначе eax = код ошибки файловой системы
|
||||
Замечания:
|
||||
* Все папки в указанном пути должны существовать, иначе вернётся
|
||||
значение 5, "файл не найден".
|
||||
* Для ecx = 0: если рамдиск не был загружен с перезаписываемого
|
||||
носителя (например, образ заранее загружен в память
|
||||
загрузчиком), вернётся значение 2; ошибка записи на дискету
|
||||
вернёт значение 11.
|
||||
* Устройство-источник загрузки можно заранее узнать подфункцией
|
||||
13 функции 26.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_SYSTEM (18)
|
||||
@@ -1654,6 +1663,27 @@ Remarks:
|
||||
eax - SF_SYSTEM_GET (26)
|
||||
ebx - SSF_ACCESS_PCI (12)
|
||||
======================================================================
|
||||
===== Функция 26, подфункция 13 - откуда загружен рамдиск. ===========
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 26 - номер функции
|
||||
* ebx = 13 - номер подфункции
|
||||
Возвращаемое значение:
|
||||
* eax = устройство, с которого при загрузке был прочитан образ
|
||||
рамдиска:
|
||||
* 1 = дискета
|
||||
* 2 = раздел жёсткого диска
|
||||
* 3 = образ заранее загружен в память загрузчиком
|
||||
* 4 = рамдиск создан пустым (отформатирован при загрузке)
|
||||
* 5 = рамдиска нет
|
||||
Замечания:
|
||||
* Для сохранения рамдиска на загрузочный носитель используйте
|
||||
функцию 18.6 с ecx = 0; она успешна для значений 1 и 2.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_SYSTEM_GET (26)
|
||||
ebx - SSF_RD_BOOT_SOURCE (13)
|
||||
======================================================================
|
||||
================ Функция 29 - получить системную дату. ===============
|
||||
======================================================================
|
||||
Параметры:
|
||||
@@ -2507,7 +2537,7 @@ dword-значение цвета 0x00RRGGBB
|
||||
* иначе eax = TID - идентификатор потока
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_CREATE_THREAD (51) /
|
||||
eax - SF_THREAD_CONTROL (51) /
|
||||
ebx - SSF_CREATE_THREAD (1), SSF_GET_CURR_THREAD_SLOT (2),
|
||||
SSF_GET_THREAD_PRIORITY (3), SSF_SET_THREAD_PRIORITY (4)
|
||||
|
||||
@@ -4098,6 +4128,9 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* подфункция 7 - запуск программы
|
||||
* подфункция 8 - удаление файла/папки
|
||||
* подфункция 9 - создание папки
|
||||
* подфункция 10 - переименование/перемещение
|
||||
* подфункция 11 - создание симлинка
|
||||
* подфункция 12 - чтение симлинка
|
||||
Для CD-приводов в связи с аппаратными ограничениями доступны
|
||||
только подфункции 0,1,5 и 7, вызов других подфункций завершится
|
||||
ошибкой с кодом 2.
|
||||
@@ -4112,7 +4145,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
[ebx] - SSF_READ_FILE (0), SSF_READ_FOLDER (1), SSF_CREATE_FILE (2),
|
||||
SSF_WRITE_FILE (3), SSF_SET_END (4), SSF_GET_INFO (5),
|
||||
SSF_SET_INFO (6), SSF_START_APP (7), SSF_DELETE (8),
|
||||
SSF_CREATE_FOLDER (9)
|
||||
SSF_CREATE_FOLDER (9), SSF_RENAME (10), SSF_CREATE_SYMLINK (11),
|
||||
SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
= Функция 70, подфункция 0 - чтение файла с поддержкой длинных имён. =
|
||||
======================================================================
|
||||
@@ -4464,6 +4498,62 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Формирование нового пути отличается от общих правил:
|
||||
относительный путь относится к папке целевого файла (или папки),
|
||||
абсолютный путь считается от корня раздела.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_RENAME (10)
|
||||
======================================================================
|
||||
=========== Функция 70, подфункция 11 - создание симлинка. ===========
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 70 - номер функции
|
||||
* ebx = указатель на информационную структуру
|
||||
Формат информационной структуры:
|
||||
* +0: dword: 11 = номер подфункции
|
||||
* +4: dword: 0 (зарезервировано)
|
||||
* +8: dword: 0 (зарезервировано)
|
||||
* +12 = +0xC: dword: 0 (зарезервировано)
|
||||
* +16 = +0x10: dword: указатель на строку с целевым путём
|
||||
* +20 = +0x14: путь, правила формирования имён указаны в общем
|
||||
описании (путь ссылки)
|
||||
Возвращаемое значение:
|
||||
* eax = 0 - успешно, иначе код ошибки файловой системы
|
||||
* ebx разрушается
|
||||
Замечания:
|
||||
* Родительская папка должна существовать.
|
||||
* Для CD функция не поддерживается (возвращает код ошибки 2).
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_CREATE_SYMLINK (11)
|
||||
======================================================================
|
||||
============ Функция 70, подфункция 12 - чтение симлинка. ============
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 70 - номер функции
|
||||
* ebx = указатель на информационную структуру
|
||||
Формат информационной структуры:
|
||||
* +0: dword: 12 = номер подфункции
|
||||
* +4: dword: 0 (зарезервировано)
|
||||
* +8: dword: 0 (зарезервировано)
|
||||
* +12 = +0xC: dword: размер буфера в байтах
|
||||
* +16 = +0x10: dword: указатель на буфер для целевого пути
|
||||
* +20 = +0x14: путь, правила формирования имён указаны в общем
|
||||
описании (путь ссылки)
|
||||
Возвращаемое значение:
|
||||
* eax = 0 - успешно, иначе код ошибки файловой системы
|
||||
* ebx = число байт, записанных в буфер
|
||||
Замечания:
|
||||
* Функция не следует по симлинку; она читает целевой путь,
|
||||
на который указывает симлинк.
|
||||
* Целевой путь всегда завершается нулём, в том числе при обрезании;
|
||||
записывается не более (размер буфера - 1) байт пути.
|
||||
* Значение в ebx включает завершающий 0, как в подфункции 2
|
||||
функции 30.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
========== Функция 71 - установить заголовок окна программы ==========
|
||||
======================================================================
|
||||
@@ -5059,8 +5149,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* eax = дескриптор фьютекса, 0 при ошибке
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_CREATE (0)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_CREATE (0)
|
||||
======================================================================
|
||||
============= Функция 77, подфункция 1, Удалить фьютекс. =============
|
||||
======================================================================
|
||||
@@ -5074,8 +5164,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Ядро автоматически удаляет фьютексы при завершении процесса.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_DESTROY (1)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_DESTROY (1)
|
||||
======================================================================
|
||||
================= Функция 77, подфункция 2, Ожидать. =================
|
||||
======================================================================
|
||||
@@ -5091,8 +5181,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
-2 - контрольное значение фьютекса не соответствует
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAIT (2)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAIT (2)
|
||||
======================================================================
|
||||
================ Функция 77, подфункция 3, Разбудить. ================
|
||||
======================================================================
|
||||
@@ -5105,8 +5195,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* eax = количество разбуженых
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAKE (3)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAKE (3)
|
||||
======================================================================
|
||||
Замечания:
|
||||
* Подфункции 4-7 зарезервированы и сейчас возвращают -1.
|
||||
@@ -5128,8 +5218,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Поддерживаются только pipe-дескрипторы.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_READ (10)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_READ (10)
|
||||
|
||||
======================================================================
|
||||
======== Функция 77, подфункция 11, Записать из буфера в файл. =======
|
||||
@@ -5148,8 +5238,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Поддерживаются только pipe-дескрипторы.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_WRITE (11)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_WRITE (11)
|
||||
|
||||
======================================================================
|
||||
=========== Функция 77, подфункция 13, Создать новый pipe. ===========
|
||||
@@ -5170,11 +5260,11 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
-EINVAL (-11), -EFAULT (-14), -ENFILE (-23), -EMFILE (-24)
|
||||
Примечания:
|
||||
* В случае успеха pipefd[0] является дескриптором чтения, а pipefd[1]
|
||||
- дескриптором записи.
|
||||
- дескриптором записи.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_PIPE_CREATE (13)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_PIPE2 (13)
|
||||
|
||||
======================================================================
|
||||
========== Функция -1 - завершить выполнение потока/процесса =========
|
||||
|
||||
+102
-16
@@ -769,12 +769,20 @@ Parameters:
|
||||
* ebx = 6 - subfunction number
|
||||
* ecx = pointer to the full path to file
|
||||
(for example, "/hd0/1/kolibri/kolibri.img")
|
||||
* ecx = 0 - write the image back to the medium the system was
|
||||
booted from: the floppy drive, or the image file found on a hard
|
||||
disk partition at boot
|
||||
Returned value:
|
||||
* eax = 0 - success
|
||||
* else eax = error code of the file system
|
||||
Remarks:
|
||||
* All folders in the given path must exist, otherwise function
|
||||
returns value 5, "file not found".
|
||||
* For ecx = 0: if the ramdisk was not loaded from a writable
|
||||
medium (e.g. it was preloaded to memory by the loader), function
|
||||
returns value 2; a failed floppy write returns value 11.
|
||||
* The boot source device can be checked in advance with
|
||||
subfunction 13 of function 26.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_SYSTEM (18)
|
||||
@@ -1639,6 +1647,26 @@ Remarks:
|
||||
eax - SF_SYSTEM_GET (26)
|
||||
ebx - SSF_ACCESS_PCI (12)
|
||||
======================================================================
|
||||
== Function 26, subfunction 13 - get ramdisk boot source device. =====
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 26 - function number
|
||||
* ebx = 13 - subfunction number
|
||||
Returned value:
|
||||
* eax = device the ramdisk image was loaded from at boot:
|
||||
* 1 = floppy drive
|
||||
* 2 = hard disk partition
|
||||
* 3 = image preloaded to memory by the loader
|
||||
* 4 = ramdisk was created empty (formatted at boot)
|
||||
* 5 = no ramdisk
|
||||
Remarks:
|
||||
* To save the ramdisk back to the boot medium use function 18.6
|
||||
with ecx = 0; it succeeds for values 1 and 2.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_SYSTEM_GET (26)
|
||||
ebx - SSF_RD_BOOT_SOURCE (13)
|
||||
======================================================================
|
||||
=================== Function 29 - get system date. ===================
|
||||
======================================================================
|
||||
Parameters:
|
||||
@@ -2492,7 +2520,7 @@ Returned value:
|
||||
* otherwise eax = TID - thread identifier
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_CREATE_THREAD (51)
|
||||
eax - SF_THREAD_CONTROL (51)
|
||||
ebx - SSF_CREATE_THREAD (1), SSF_GET_CURR_THREAD_SLOT (2),
|
||||
SSF_GET_THREAD_PRIORITY (3), SSF_SET_THREAD_PRIORITY (4)
|
||||
======================================================================
|
||||
@@ -4060,6 +4088,9 @@ Available subfunctions:
|
||||
* subfunction 7 - start application
|
||||
* subfunction 8 - delete file/folder
|
||||
* subfunction 9 - create folder
|
||||
* subfunction 10 - rename/move
|
||||
* subfunction 11 - create symlink
|
||||
* subfunction 12 - read symlink
|
||||
For CD-drives due to hardware limitations only subfunctions
|
||||
0,1,5 and 7 are available, other subfunctions return error
|
||||
with code 2.
|
||||
@@ -4073,7 +4104,8 @@ is called for corresponding device.
|
||||
[ebx] - SSF_READ_FILE (0), SSF_READ_FOLDER (1), SSF_CREATE_FILE (2),
|
||||
SSF_WRITE_FILE (3), SSF_SET_END (4), SSF_GET_INFO (5),
|
||||
SSF_SET_INFO (6), SSF_START_APP (7), SSF_DELETE (8),
|
||||
SSF_CREATE_FOLDER (9)
|
||||
SSF_CREATE_FOLDER (9), SSF_RENAME (10), SSF_CREATE_SYMLINK (11),
|
||||
SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
=== Function 70, subfunction 0 - read file with long names support. ==
|
||||
======================================================================
|
||||
@@ -4423,6 +4455,60 @@ Remarks:
|
||||
* New path forming differs from general rules:
|
||||
relative path relates to the target's parent folder,
|
||||
absolute path relates to the partition's root folder.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_RENAME (10)
|
||||
======================================================================
|
||||
=========== Function 70, subfunction 11 - create symlink. ============
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 70 - function number
|
||||
* ebx = pointer to the information structure
|
||||
Format of the information structure:
|
||||
* +0: dword: 11 = subfunction number
|
||||
* +4: dword: 0 (reserved)
|
||||
* +8: dword: 0 (reserved)
|
||||
* +12 = +0xC: dword: 0 (reserved)
|
||||
* +16 = +0x10: dword: pointer to the target path string
|
||||
* +20 = +0x14: path, general rules of names forming (link path)
|
||||
Returned value:
|
||||
* eax = 0 - success, otherwise file system error code
|
||||
* ebx destroyed
|
||||
Remarks:
|
||||
* The parent folder must already exist.
|
||||
* The function is not supported for CD (returns error code 2).
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_CREATE_SYMLINK (11)
|
||||
======================================================================
|
||||
============ Function 70, subfunction 12 - read symlink. =============
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 70 - function number
|
||||
* ebx = pointer to the information structure
|
||||
Format of the information structure:
|
||||
* +0: dword: 12 = subfunction number
|
||||
* +4: dword: 0 (reserved)
|
||||
* +8: dword: 0 (reserved)
|
||||
* +12 = +0xC: dword: buffer size in bytes
|
||||
* +16 = +0x10: dword: pointer to buffer for target path
|
||||
* +20 = +0x14: path, general rules of names forming (link path)
|
||||
Returned value:
|
||||
* eax = 0 - success, otherwise file system error code
|
||||
* ebx = number of bytes written to the buffer
|
||||
Remarks:
|
||||
* The function does not follow the symlink; it reads the target path
|
||||
that the symlink points to.
|
||||
* The target path is always terminated with 0, even when truncated;
|
||||
at most (buffer size - 1) path bytes are written.
|
||||
* The value returned in ebx includes the terminating 0, as in
|
||||
subfunction 2 of function 30.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
================== Function 71 - set window caption ==================
|
||||
======================================================================
|
||||
@@ -5273,8 +5359,8 @@ Returned value:
|
||||
* eax = futex handle, 0 on error
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_CREATE (0)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_CREATE (0)
|
||||
======================================================================
|
||||
========= Function 77, Subfunction 1, Destroy futex object ===========
|
||||
======================================================================
|
||||
@@ -5289,8 +5375,8 @@ Remarks:
|
||||
terminates.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_DESTROY (1)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_DESTROY (1)
|
||||
======================================================================
|
||||
=============== Function 77, Subfunction 2, Futex wait ===============
|
||||
======================================================================
|
||||
@@ -5306,8 +5392,8 @@ Returned value:
|
||||
-2 - futex control value doesn't match
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAIT (2)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAIT (2)
|
||||
======================================================================
|
||||
=============== Function 77, Subfunction 3, Futex wake ===============
|
||||
======================================================================
|
||||
@@ -5320,8 +5406,8 @@ Returned value:
|
||||
* eax = number of waiters that were woken up
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAKE (3)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAKE (3)
|
||||
======================================================================
|
||||
Remarks:
|
||||
* Subfunctions 4-7 are reserved and currently return -1.
|
||||
@@ -5343,8 +5429,8 @@ Remarks:
|
||||
* Only pipe descriptors are supported.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_READ (10)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_READ (10)
|
||||
======================================================================
|
||||
=========== Function 77, Subfunction 11, Write to file. =============
|
||||
======================================================================
|
||||
@@ -5362,8 +5448,8 @@ Remarks:
|
||||
* Only pipe descriptors are supported.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_WRITE (11)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_WRITE (11)
|
||||
======================================================================
|
||||
========== Function 77, Subfunction 13, Create pipe. ================
|
||||
======================================================================
|
||||
@@ -5381,8 +5467,8 @@ Remarks:
|
||||
write handle.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_PIPE_CREATE (13)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_PIPE2 (13)
|
||||
======================================================================
|
||||
=== Function 80 - file system interface with parameter of encoding ===
|
||||
======================================================================
|
||||
|
||||
+301
-33
@@ -30,6 +30,8 @@ ext_user_functions:
|
||||
dd ext_Delete
|
||||
dd ext_CreateFolder
|
||||
dd ext_Rename
|
||||
dd ext_CreateSymlink
|
||||
dd ext_ReadSymlink
|
||||
ext_user_functions_end:
|
||||
endg
|
||||
|
||||
@@ -169,7 +171,9 @@ blocksFree_hi dd ?
|
||||
minExtraISize dw ?
|
||||
wantExtraISize dw ?
|
||||
Flags dd ?
|
||||
csum_seed_padding rb 268
|
||||
logGroupsPerFlex_padding rb 16
|
||||
logGroupsPerFlex db ?
|
||||
csum_seed_padding rb 251
|
||||
checksumSeed dd ?
|
||||
checksum_padding rb 392
|
||||
checksum dd ?
|
||||
@@ -222,10 +226,13 @@ EXT4_IMMUTABLE_FL = 10h
|
||||
EXT4_APPEND_ONLY_FL = 20h
|
||||
EXT4_NOATIME_FL = 80h
|
||||
; File System Feature Flags
|
||||
INCOMPAT_64BIT = 80h
|
||||
INCOMPAT_CSUM_SEED = 2000h
|
||||
RO_COMPAT_METADATA_CSUM = 400h
|
||||
RO_COMPAT_GDT_CSUM = 10h ; Not supported but need to check it for csum validation on RO.
|
||||
INCOMPAT_FILETYPE = 2h
|
||||
INCOMPAT_EXTENTS = 40h
|
||||
INCOMPAT_64BIT = 80h
|
||||
INCOMPAT_FLEX_BG = 200h
|
||||
INCOMPAT_CSUM_SEED = 2000h
|
||||
RO_COMPAT_METADATA_CSUM = 400h
|
||||
RO_COMPAT_GDT_CSUM = 10h ; Not supported but need to check it for csum validation on RO.
|
||||
CSUM_FLAGS = RO_COMPAT_GDT_CSUM or RO_COMPAT_METADATA_CSUM
|
||||
|
||||
EXT_CRC_POLY = 82F63B78h
|
||||
@@ -240,9 +247,9 @@ EXT_CSUM_FAKE_TAIL = 0DEh
|
||||
; 80h = 64bit
|
||||
; 200h = flexible block groups
|
||||
; 2000h = metadata_csum_seed
|
||||
INCOMPATIBLE_SUPPORT = 22C2h
|
||||
INCOMPATIBLE_SUPPORT = INCOMPAT_FILETYPE or INCOMPAT_EXTENTS or INCOMPAT_64BIT or INCOMPAT_FLEX_BG or INCOMPAT_CSUM_SEED
|
||||
; Read only support for "incompatible" features:
|
||||
INCOMPATIBLE_READ_SUPPORT = 240h
|
||||
INCOMPATIBLE_READ_SUPPORT = INCOMPAT_EXTENTS
|
||||
|
||||
; Mount policies
|
||||
MOUNT_POLICY_NOATIME = 0
|
||||
@@ -261,6 +268,7 @@ Lock MUTEX
|
||||
mountType dd ?
|
||||
descShift db ?
|
||||
descSize dd ?
|
||||
flexGroupSize dd ?
|
||||
bytesPerBlock dd ?
|
||||
sectorsPerBlock dd ?
|
||||
dwordsPerBlock dd ?
|
||||
@@ -277,7 +285,8 @@ align2 rb 800h-EXTFS.align2
|
||||
inodeBuffer INODE
|
||||
align3 rb 0A00h-EXTFS.align3
|
||||
symlink_workspace rb maxPathLength
|
||||
symlink_depth dd ?
|
||||
symlink_depth dw ?
|
||||
symlink_no_follow dw ?
|
||||
MOUNT_POLICY dd ? ; TODO: add proper mount syscall
|
||||
c_inode dd ?
|
||||
c_sz dd ?
|
||||
@@ -482,6 +491,19 @@ ext2_create_partition:
|
||||
mov [ebp+EXTFS.descSize], eax
|
||||
bsf eax, eax
|
||||
mov [ebp+EXTFS.descShift], al
|
||||
|
||||
mov eax, 1
|
||||
test [ebx+SUPERBLOCK.incompatibleFlags], INCOMPAT_FLEX_BG
|
||||
jz .no_flex_bg
|
||||
movzx ecx, [ebx+SUPERBLOCK.logGroupsPerFlex]
|
||||
cmp ecx, 31
|
||||
jbe @f
|
||||
xor ecx, ecx
|
||||
@@:
|
||||
shl eax, cl
|
||||
.no_flex_bg:
|
||||
mov [ebp+EXTFS.flexGroupSize], eax
|
||||
|
||||
mov eax, [ebx+SUPERBLOCK.inodesTotal]
|
||||
dec eax
|
||||
xor edx, edx
|
||||
@@ -759,8 +781,11 @@ extfsInodeAlloc:
|
||||
push ebx
|
||||
.test_block_group:
|
||||
push ebx
|
||||
cmp [ebp+EXTFS.flexGroupSize], 1
|
||||
ja @f
|
||||
cmp [ebx+BGDESCR.blocksFree_lo], 0
|
||||
jz .next
|
||||
@@:
|
||||
cmp [ebx+BGDESCR.inodesFree_lo], 0
|
||||
jz .next
|
||||
dec [ebx+BGDESCR.inodesFree_lo]
|
||||
@@ -840,16 +865,30 @@ extfsInodeAlloc:
|
||||
jmp .ret
|
||||
|
||||
extfsExtentAlloc:
|
||||
; in: eax = parent inode number, ecx = blocks max
|
||||
; in: edi = goal block (0 = use inode, clobbered), eax = parent inode number, ecx = blocks max
|
||||
; out: ebx = first block number, ecx = blocks allocated
|
||||
push edx esi edi ecx
|
||||
; On error, ecx is undefined, no longer guaranteed to be 0.
|
||||
push edx esi ecx
|
||||
test edi, edi
|
||||
jnz .use_goal
|
||||
dec eax
|
||||
xor edx, edx
|
||||
div [ebp+EXTFS.superblock.inodesPerGroup]
|
||||
jmp .calc_group
|
||||
.use_goal:
|
||||
mov eax, edi
|
||||
sub eax, [ebp+EXTFS.superblock.firstGroupBlock]
|
||||
xor edx, edx
|
||||
div [ebp+EXTFS.superblock.blocksPerGroup]
|
||||
.calc_group:
|
||||
mov ebx, [ebp+EXTFS.descriptorTable]
|
||||
mov cl, [ebp+EXTFS.descShift]
|
||||
shl eax, cl
|
||||
add ebx, eax
|
||||
cmp ebx, [ebp+EXTFS.descriptorTable]
|
||||
jb .oob
|
||||
cmp ebx, [ebp+EXTFS.descriptorTableEnd]
|
||||
jae .oob
|
||||
push ebx
|
||||
.test_block_group:
|
||||
push ebx
|
||||
@@ -860,7 +899,7 @@ extfsExtentAlloc:
|
||||
mov edx, eax
|
||||
mov edi, ebx
|
||||
call extfsReadBlock
|
||||
jc .fail
|
||||
jc .fail5
|
||||
mov ecx, [ebp+EXTFS.superblock.blocksPerGroup]
|
||||
shr ecx, 5
|
||||
or eax, -1
|
||||
@@ -975,9 +1014,13 @@ extfsExtentAlloc:
|
||||
add [ebp+EXTFS.inodeBuffer.sectorsUsed], eax
|
||||
xor eax, eax
|
||||
.ret:
|
||||
pop edi esi edx
|
||||
pop esi edx
|
||||
ret
|
||||
|
||||
.oob:
|
||||
movi eax, ERROR_FS_FAIL
|
||||
jmp .fail3
|
||||
|
||||
.next: ; search forward, then backward
|
||||
pop ebx
|
||||
cmp ebx, [esp]
|
||||
@@ -992,9 +1035,10 @@ extfsExtentAlloc:
|
||||
jnc .test_block_group
|
||||
movi eax, ERROR_DISK_FULL
|
||||
push eax
|
||||
.fail:
|
||||
add esp, 12
|
||||
xor ecx, ecx
|
||||
.fail5:
|
||||
pop ecx ecx
|
||||
.fail3:
|
||||
pop ecx
|
||||
stc
|
||||
jmp .ret
|
||||
|
||||
@@ -1451,7 +1495,10 @@ doublyIndirectBlockAlloc:
|
||||
xor eax, eax
|
||||
jecxz .end
|
||||
mov eax, [esp+16]
|
||||
push edi
|
||||
lea edi, [ebx-1]
|
||||
call extfsExtentAlloc
|
||||
pop edi
|
||||
jc .end
|
||||
sub [esp+12], ecx
|
||||
jmp @b
|
||||
@@ -1492,6 +1539,18 @@ extfsExtendFile:
|
||||
mov eax, [esp+4]
|
||||
test ecx, ecx
|
||||
jz .done
|
||||
|
||||
xor edi, edi
|
||||
test edx, edx
|
||||
jz .call_alloc
|
||||
push ecx
|
||||
lea ecx, [edx-1]
|
||||
call extfsGetExtent
|
||||
pop ecx
|
||||
jc .call_alloc
|
||||
mov edi, eax
|
||||
.call_alloc:
|
||||
mov eax, [esp+4]
|
||||
call extfsExtentAlloc
|
||||
jc .errDone
|
||||
sub [esp], ecx
|
||||
@@ -1617,7 +1676,10 @@ extfsExtendFile:
|
||||
mov ecx, [esp]
|
||||
mov eax, [esp+4]
|
||||
jecxz @f
|
||||
push edi
|
||||
lea edi, [ebx-1]
|
||||
call extfsExtentAlloc
|
||||
pop edi
|
||||
jc .errSave
|
||||
sub [esp], ecx
|
||||
jmp @b
|
||||
@@ -2096,6 +2158,11 @@ unlinkInode:
|
||||
pop eax
|
||||
ret
|
||||
|
||||
reachSymlink:
|
||||
; Set symlink_depth = SYMLINK_MAX_DEPTH and symlink_no_follow = 1
|
||||
mov dword [ebp+EXTFS.symlink_depth], SYMLINK_MAX_DEPTH + 10000h
|
||||
jmp @f
|
||||
|
||||
findInode:
|
||||
; in: esi -> path string in UTF-8
|
||||
; out:
|
||||
@@ -2104,7 +2171,8 @@ findInode:
|
||||
; [ebp+EXTFS.inodeBuffer] = last inode
|
||||
; ecx = parent inode number
|
||||
; CF=1 -> file not found, edi=0 -> error
|
||||
mov [ebp+EXTFS.symlink_depth], SYMLINK_MAX_DEPTH
|
||||
mov dword [ebp+EXTFS.symlink_depth], SYMLINK_MAX_DEPTH
|
||||
@@:
|
||||
push esi
|
||||
lea esi, [ebp+EXTFS.rootInodeBuffer]
|
||||
lea edi, [ebp+EXTFS.inodeBuffer]
|
||||
@@ -2201,7 +2269,13 @@ findInode:
|
||||
and eax, TYPE_MASK
|
||||
; check if symlink
|
||||
cmp eax, FLAG_SYMLINK
|
||||
jz .resolve_symlink
|
||||
jne @f
|
||||
cmp byte [esi], 0
|
||||
jnz .resolve_symlink
|
||||
cmp [ebp+EXTFS.symlink_no_follow], 0
|
||||
jnz .ret
|
||||
jmp .resolve_symlink
|
||||
@@:
|
||||
|
||||
cmp byte [esi], 0
|
||||
je .ret
|
||||
@@ -2239,14 +2313,12 @@ findInode:
|
||||
; Symlink path is in symlink_workspace. esi points to the remaining path (tail).
|
||||
; Shift tail by symlink size to prevent overwriting during insertion.
|
||||
push edi ecx eax
|
||||
|
||||
; Find tail length
|
||||
mov edi, esi
|
||||
mov ecx, -1
|
||||
xor al, al
|
||||
repnz scasb
|
||||
not ecx ; ecx = tail length including null
|
||||
|
||||
; Boundary overflow check
|
||||
mov eax, [ebx+INODE.fileSize]
|
||||
lea edi, [esi + eax]
|
||||
@@ -2254,13 +2326,11 @@ findInode:
|
||||
lea eax, [ebp+EXTFS.symlink_workspace + maxPathLength]
|
||||
cmp edi, eax
|
||||
ja .error_nested
|
||||
|
||||
; Shift
|
||||
mov eax, [ebx+INODE.fileSize]
|
||||
lea edi, [esi + ecx - 1]
|
||||
add edi, eax
|
||||
lea esi, [esi + ecx - 1]
|
||||
|
||||
std
|
||||
rep movsb
|
||||
cld
|
||||
@@ -2281,23 +2351,21 @@ findInode:
|
||||
mov edx, [ebx+INODE.fileSize]
|
||||
cmp edx, maxPathLength
|
||||
jae .error_slow
|
||||
cmp edx, [ebp+EXTFS.bytesPerBlock]
|
||||
ja .error_slow
|
||||
|
||||
push ecx edx edi
|
||||
|
||||
call extfsGetExtent
|
||||
jc .error_slow
|
||||
mov ebx, [ebp+EXTFS.tempBlockBuffer]
|
||||
call extfsReadBlock
|
||||
jc .error_slow
|
||||
|
||||
pop edi edx ecx
|
||||
|
||||
push esi
|
||||
mov esi, [ebp+EXTFS.tempBlockBuffer]
|
||||
mov ecx, edx
|
||||
rep movsb
|
||||
pop esi
|
||||
|
||||
jmp .symlink_merge
|
||||
|
||||
; The target path is short enough, it's stored in the inode's block numbers.
|
||||
@@ -2308,7 +2376,6 @@ findInode:
|
||||
|
||||
.symlink_merge:
|
||||
pop esi ; Restore the remaining path
|
||||
|
||||
cmp byte [esi], 0
|
||||
jne .symlink_copy_remaining
|
||||
mov byte [edi], 0
|
||||
@@ -2322,10 +2389,19 @@ findInode:
|
||||
mov byte [edi], '/'
|
||||
inc edi
|
||||
@@:
|
||||
lodsb
|
||||
stosb
|
||||
test al, al
|
||||
jnz @b
|
||||
push edi
|
||||
mov edi, esi
|
||||
xor ecx, ecx
|
||||
dec ecx
|
||||
xor eax, eax
|
||||
repnz scasb
|
||||
not ecx
|
||||
lea eax, [ebp+EXTFS.symlink_workspace + maxPathLength]
|
||||
sub eax, [esp]
|
||||
cmp ecx, eax
|
||||
pop edi
|
||||
ja .error
|
||||
rep movsb
|
||||
|
||||
.symlink_check_type:
|
||||
lea esi, [ebp+EXTFS.symlink_workspace]
|
||||
@@ -2336,16 +2412,13 @@ findInode:
|
||||
inc esi
|
||||
mov dword [esp], ROOT_INODE
|
||||
mov dword [esp+4], ROOT_INODE
|
||||
|
||||
push esi
|
||||
lea esi, [ebp+EXTFS.rootInodeBuffer]
|
||||
lea edi, [ebp+EXTFS.inodeBuffer]
|
||||
movzx ecx, [ebp+EXTFS.superblock.inodeSize]
|
||||
rep movsb
|
||||
pop esi
|
||||
|
||||
lea edx, [ebp+EXTFS.inodeBuffer]
|
||||
|
||||
cmp byte [esi], 0
|
||||
jz .ret
|
||||
jmp .next_path_part
|
||||
@@ -3642,3 +3715,198 @@ ext_Rename:
|
||||
call ext_unlock
|
||||
pop eax ebx
|
||||
ret
|
||||
|
||||
ext_CreateSymlink:
|
||||
; Copy target path into workspace and find its length
|
||||
push esi
|
||||
mov edi, [ebx+16]
|
||||
mov esi, edi
|
||||
call strlen
|
||||
inc ecx
|
||||
cmp ecx, maxPathLength
|
||||
jae .path_too_long
|
||||
cmp ecx, [ebp+EXTFS.bytesPerBlock]
|
||||
ja .path_too_long
|
||||
lea edi, [ebp+EXTFS.symlink_workspace]
|
||||
rep movsb
|
||||
pop esi
|
||||
|
||||
call extfsWritingInit
|
||||
call reachSymlink
|
||||
mov [ebp+EXTFS.symlink_no_follow], 0
|
||||
jnc .exist
|
||||
test edi, edi
|
||||
jz .error
|
||||
|
||||
mov eax, esi
|
||||
call extfsInodeAlloc ; ebx = allocated inode number
|
||||
jc .error
|
||||
|
||||
push ebx esi edi
|
||||
lea edi, [ebp+EXTFS.inodeBuffer]
|
||||
movzx ecx, [ebp+EXTFS.superblock.inodeSize]
|
||||
xor eax, eax
|
||||
rep stosb
|
||||
lea ebx, [ebp+EXTFS.inodeBuffer]
|
||||
call initializeTimeFields
|
||||
pop edi esi edx ; edx = inode number
|
||||
|
||||
mov [ebx+INODE.accessMode], FLAG_SYMLINK or 110110110b
|
||||
mov byte [ebx+INODE.linksCount], 1
|
||||
|
||||
push esi edi
|
||||
lea edi, [ebp+EXTFS.symlink_workspace]
|
||||
mov esi, edi
|
||||
call strlen
|
||||
mov [ebx+INODE.fileSize], ecx
|
||||
pop edi esi
|
||||
|
||||
; Choose fast symlink (<=60 bytes) or slow symlink (>60 bytes)
|
||||
cmp ecx, FAST_SYMLINK_MAX_SIZE
|
||||
ja .slow_symlink
|
||||
|
||||
push esi edi
|
||||
lea esi, [ebp+EXTFS.symlink_workspace]
|
||||
lea edi, [ebx+INODE.blockNumbers]
|
||||
inc ecx
|
||||
rep movsb
|
||||
pop edi esi
|
||||
jmp .write_inode
|
||||
|
||||
.slow_symlink:
|
||||
; Allocate a data block and write the path to it
|
||||
push ebx
|
||||
mov eax, edx
|
||||
mov ecx, 1
|
||||
push edi
|
||||
xor edi, edi
|
||||
call extfsExtentAlloc ; ebx = allocated block number
|
||||
pop edi
|
||||
jc .error_alloc
|
||||
|
||||
push esi edi ebx
|
||||
lea esi, [ebp+EXTFS.symlink_workspace]
|
||||
mov edi, [ebp+EXTFS.tempBlockBuffer]
|
||||
push edi
|
||||
mov eax, esi
|
||||
call strlen
|
||||
inc ecx
|
||||
rep movsb
|
||||
pop ebx
|
||||
mov eax, [esp]
|
||||
|
||||
call extfsWriteBlock
|
||||
jc .error_write
|
||||
|
||||
pop eax edi esi ebx
|
||||
mov [ebx+INODE.blockNumbers], eax
|
||||
jmp .write_inode
|
||||
|
||||
.write_inode:
|
||||
; Write constructed inode to disk and link to parent
|
||||
mov eax, edx
|
||||
call writeInode
|
||||
jc .error
|
||||
|
||||
mov eax, esi
|
||||
mov ebx, edx
|
||||
mov esi, edi
|
||||
mov dl, DIR_SYMLINK
|
||||
call linkInode
|
||||
jc .error
|
||||
|
||||
xor eax, eax
|
||||
jmp .error
|
||||
|
||||
.exist:
|
||||
movi eax, ERROR_ACCESS_DENIED
|
||||
jmp .error
|
||||
.error_write:
|
||||
pop edx edi esi
|
||||
.error_alloc:
|
||||
pop ebx
|
||||
.error:
|
||||
push eax
|
||||
call ext_unlock
|
||||
pop eax
|
||||
ret
|
||||
.path_too_long:
|
||||
pop esi
|
||||
movi eax, ERROR_FS_FAIL
|
||||
ret
|
||||
|
||||
;----------------------------------------------------------------
|
||||
ext_ReadSymlink:
|
||||
call ext_lock
|
||||
call reachSymlink
|
||||
mov [ebp+EXTFS.symlink_no_follow], 0
|
||||
pushd 0 eax
|
||||
jc .ret
|
||||
|
||||
lea esi, [ebp+EXTFS.inodeBuffer]
|
||||
mov dword [esp], ERROR_ACCESS_DENIED
|
||||
movzx eax, [esi+INODE.accessMode]
|
||||
and eax, TYPE_MASK
|
||||
cmp eax, FLAG_SYMLINK
|
||||
jne .ret
|
||||
|
||||
mov dword [esp], ERROR_END_OF_FILE
|
||||
mov eax, [esi+INODE.fileSize]
|
||||
cmp eax, [ebp+EXTFS.bytesPerBlock]
|
||||
jbe @f
|
||||
mov eax, [ebp+EXTFS.bytesPerBlock]
|
||||
@@:
|
||||
mov ecx, [ebx+12]
|
||||
test ecx, ecx
|
||||
jz .done_copy
|
||||
dec ecx
|
||||
cmp ecx, eax
|
||||
jb @f
|
||||
mov ecx, eax
|
||||
@@:
|
||||
mov [esp+4], ecx
|
||||
mov edi, [ebx+16]
|
||||
test ecx, ecx
|
||||
jz .write_nul
|
||||
|
||||
cmp [esi+INODE.fileSize], FAST_SYMLINK_MAX_SIZE
|
||||
jbe .fast_symlink
|
||||
|
||||
.slow_symlink:
|
||||
push ecx edi
|
||||
xor ecx, ecx
|
||||
call extfsGetExtent
|
||||
jc .errorGet
|
||||
mov ebx, [ebp+EXTFS.mainBlockBuffer]
|
||||
call extfsReadBlock
|
||||
jc .errorGet
|
||||
pop edi ecx
|
||||
|
||||
push esi
|
||||
mov esi, [ebp+EXTFS.mainBlockBuffer]
|
||||
rep movsb
|
||||
pop esi
|
||||
jmp .write_nul
|
||||
|
||||
.errorGet:
|
||||
pop edi ecx
|
||||
mov dword [esp], ERROR_DEVICE
|
||||
jmp .ret
|
||||
|
||||
.fast_symlink:
|
||||
push esi
|
||||
lea esi, [esi+INODE.blockNumbers]
|
||||
rep movsb
|
||||
pop esi
|
||||
|
||||
.write_nul:
|
||||
mov byte [edi], 0
|
||||
inc dword [esp+4]
|
||||
|
||||
.done_copy:
|
||||
mov dword [esp], 0
|
||||
|
||||
.ret:
|
||||
call ext_unlock
|
||||
pop eax ebx
|
||||
ret
|
||||
@@ -182,10 +182,22 @@ proc file_system_is_operation_safe stdcall, inf_struct_ptr: dword
|
||||
|
||||
.case6:
|
||||
cmp dword [ebx], 6
|
||||
jnz .switch_none
|
||||
jnz .case11
|
||||
mov ecx, 32
|
||||
jmp .end_switch
|
||||
|
||||
.case11:
|
||||
cmp dword [ebx], 11
|
||||
jnz .case12
|
||||
stdcall is_string_userspace, edx
|
||||
jmp .ret
|
||||
|
||||
.case12:
|
||||
cmp dword [ebx], 12
|
||||
jnz .switch_none
|
||||
mov ecx, dword [ebx + 12]
|
||||
jmp .end_switch
|
||||
|
||||
.switch_none:
|
||||
cmp ecx, ecx
|
||||
jmp .ret
|
||||
|
||||
@@ -253,9 +253,10 @@ UTF16to8_string:
|
||||
|
||||
UTF16to8:
|
||||
; in:
|
||||
; eax = UTF-16 char
|
||||
; ax = UTF-16 char
|
||||
; edi -> buffer for UTF-8 char (increasing)
|
||||
; ecx = byte counter (decreasing)
|
||||
movzx eax, ax
|
||||
dec ecx
|
||||
js .ret
|
||||
cmp eax, 80h
|
||||
|
||||
+12
-2
@@ -754,7 +754,7 @@ end if
|
||||
;-----------------------------------------------------------------------------
|
||||
mov esi, boot_detectfloppy
|
||||
call boot_log
|
||||
call floppy_init
|
||||
include 'detect/dev_fd.inc'
|
||||
;-----------------------------------------------------------------------------
|
||||
; create pci-devices list
|
||||
;-----------------------------------------------------------------------------
|
||||
@@ -1634,6 +1634,7 @@ sys_getsetup:
|
||||
; 10 = not used
|
||||
; 11 = get the state "lba read"
|
||||
; 12 = get the state "pci access"
|
||||
; 13 = get device the ramdisk was loaded from
|
||||
;-----------------------------------------------------------------------------
|
||||
; F.26.2 - get keyboard layout
|
||||
sub ebx, 2
|
||||
@@ -1725,12 +1726,21 @@ sys_getsetup:
|
||||
@@:
|
||||
; F.26.12 - Find out whether low-level PCI access is enabled
|
||||
dec ebx
|
||||
jnz .error
|
||||
jnz @f
|
||||
|
||||
mov eax, [pci_access_enabled]
|
||||
mov [esp + SYSCALL_STACK.eax], eax
|
||||
ret
|
||||
;--------------------------------------
|
||||
@@:
|
||||
; F.26.13 - get device the ramdisk was loaded from, RD_LOAD_FROM_*
|
||||
dec ebx
|
||||
jnz .error
|
||||
|
||||
movzx eax, byte [BOOT.rd_load_from]
|
||||
mov [esp + SYSCALL_STACK.eax], eax
|
||||
ret
|
||||
;--------------------------------------
|
||||
.error:
|
||||
or [esp + SYSCALL_STACK.eax], -1
|
||||
ret
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2026. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; IPv4.INC ;;
|
||||
@@ -765,9 +765,9 @@ ipv4_output_raw:
|
||||
push ebx ; push the mac
|
||||
push ax
|
||||
|
||||
inc [IPv4_packets_tx + 4*edi]
|
||||
inc [IPv4_packets_tx + edi]
|
||||
mov ax, ETHER_PROTO_IPv4
|
||||
mov ebx, [net_device_list + 4*edi]
|
||||
mov ebx, [net_device_list + edi]
|
||||
mov ecx, [esp + 6 + 4]
|
||||
add ecx, sizeof.IPv4_header
|
||||
mov edx, esp
|
||||
@@ -951,7 +951,7 @@ endp
|
||||
; edi = device number*4 ;
|
||||
; ;
|
||||
; DESTROYED: ;
|
||||
; ecx ;
|
||||
; ebx, ecx ;
|
||||
; ;
|
||||
;-----------------------------------------------------------------;
|
||||
align 4
|
||||
@@ -964,6 +964,7 @@ ipv4_route:
|
||||
cmp eax, 0xffffffff
|
||||
je .broadcast
|
||||
|
||||
; Check for on-link
|
||||
xor edi, edi
|
||||
.loop:
|
||||
mov ebx, [IPv4_address + edi]
|
||||
@@ -978,9 +979,55 @@ ipv4_route:
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .loop
|
||||
|
||||
mov eax, [IPv4_gateway + 4] ; TODO: let user (or a user space daemon) configure default route
|
||||
; no on-link match, find first device with a gateway
|
||||
mov edi, 4 ; skip loopback device
|
||||
.loop_gw:
|
||||
cmp [IPv4_gateway + edi], 0
|
||||
jne .found_gw
|
||||
add edi, 4
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .loop_gw
|
||||
jmp .loopback ; no gateway found, fall-back to loopback device
|
||||
|
||||
.found_gw:
|
||||
mov eax, [IPv4_gateway + edi]
|
||||
jmp .got_it
|
||||
|
||||
.broadcast:
|
||||
mov edi, 4 ; TODO: same as above
|
||||
; broadcast: we will do our best without full routing..
|
||||
|
||||
; find the first non loopback device which has an active link without IP address
|
||||
mov edi, 4 ; skip loopback device
|
||||
.bc_loop1:
|
||||
mov ebx, [net_device_list + edi]
|
||||
test ebx, ebx
|
||||
jz @f
|
||||
cmp [ebx + NET_DEVICE.link_state], 0
|
||||
je @f
|
||||
cmp [IPv4_address + edi], 0
|
||||
je .got_it
|
||||
@@:
|
||||
add edi, 4
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .bc_loop1
|
||||
|
||||
; If there is no such device, try the one with active link and IP address
|
||||
mov edi, 4 ; skip loopback device
|
||||
.bc_loop2:
|
||||
mov ebx, [net_device_list + edi]
|
||||
test ebx, ebx
|
||||
jz @f
|
||||
cmp [ebx + NET_DEVICE.link_state], 0
|
||||
jne .got_it
|
||||
@@:
|
||||
add edi, 4
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .bc_loop2
|
||||
; jmp .loopback ; no gateway found, fall-back to loopback device
|
||||
|
||||
.loopback:
|
||||
xor edi, edi ; nowhere to go for now.. route it to the loopback device
|
||||
|
||||
.got_it:
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
|
||||
test edx, edx
|
||||
|
||||
@@ -780,8 +780,6 @@ socket_close:
|
||||
|
||||
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
|
||||
jne .free
|
||||
test [eax + SOCKET.state], SS_ISCONNECTED
|
||||
jz @f
|
||||
test [eax + SOCKET.state], SS_ISDISCONNECTING
|
||||
jnz @f
|
||||
call tcp_disconnect
|
||||
|
||||
@@ -355,9 +355,14 @@ endl
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
|
||||
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
|
||||
|
||||
; remember the peer's scale factor; it is applied to SND_SCALE when the
|
||||
; connection is established (together with our RCV_SCALE)
|
||||
lodsb
|
||||
mov [ebx + TCP_SOCKET.SND_SCALE], al
|
||||
;;;;; TODO
|
||||
cmp al, TCP_max_winshift
|
||||
jbe .wscale_capped
|
||||
mov al, TCP_max_winshift
|
||||
.wscale_capped:
|
||||
mov [ebx + TCP_SOCKET.requested_s_scale], al
|
||||
|
||||
@@:
|
||||
jmp .opt_loop
|
||||
|
||||
@@ -320,12 +320,12 @@ tcp_respond:
|
||||
stosb
|
||||
mov eax, SOCKET_BUFFER_SIZE
|
||||
sub eax, [esi + STREAM_SOCKET.rcv.size]
|
||||
cmp eax, TCP_max_win
|
||||
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
|
||||
shr eax, cl ; scale first, then clamp to the
|
||||
cmp eax, TCP_max_win ; 16-bit field maximum
|
||||
jbe .lessthanmax
|
||||
mov eax, TCP_max_win
|
||||
.lessthanmax:
|
||||
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
|
||||
shr eax, cl
|
||||
|
||||
xchg al, ah
|
||||
stosw ; window
|
||||
@@ -488,7 +488,7 @@ tcp_set_persist:
|
||||
; Start/restart persistence timer.
|
||||
|
||||
tcpt_rangeset [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
|
||||
or [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
|
||||
or [eax + TCP_SOCKET.timer_flags], timer_flag_persist
|
||||
pop ebx
|
||||
|
||||
cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
|
||||
|
||||
@@ -111,13 +111,13 @@ proc tcp_timer_640ms
|
||||
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Keepalive expired\n", eax
|
||||
|
||||
cmp [eax + TCP_SOCKET.state], TCPS_ESTABLISHED
|
||||
ja .dont_kill
|
||||
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
|
||||
jae .dont_kill
|
||||
|
||||
push eax
|
||||
push [eax + SOCKET.NextPtr]
|
||||
call tcp_disconnect
|
||||
pop eax
|
||||
jmp .loop
|
||||
jmp .check_only
|
||||
|
||||
.dont_kill:
|
||||
test [eax + SOCKET.options], SO_KEEPALIVE
|
||||
|
||||
+15
-9
@@ -84,6 +84,12 @@ SF_SCREEN_PUT_IMAGE=25
|
||||
SF_SYSTEM_GET=26
|
||||
SSF_TIME_COUNT=9
|
||||
SSF_TIME_COUNT_PRO=10
|
||||
SSF_RD_BOOT_SOURCE=13
|
||||
RD_LOAD_FROM_FLOPPY=1
|
||||
RD_LOAD_FROM_HD=2
|
||||
RD_LOAD_FROM_MEMORY=3
|
||||
RD_LOAD_FROM_FORMAT=4
|
||||
RD_LOAD_FROM_NONE=5
|
||||
SF_GET_SYS_DATE=29
|
||||
SF_CURRENT_FOLDER=30
|
||||
SSF_SET_CF=1
|
||||
@@ -125,7 +131,7 @@ SF_STYLE_SETTINGS=48
|
||||
SSF_SET_FONT_SIZE=12
|
||||
SF_APM=49
|
||||
SF_SET_WINDOW_SHAPE=50
|
||||
SF_CREATE_THREAD=51
|
||||
SF_THREAD_CONTROL=51
|
||||
SSF_CREATE_THREAD=1
|
||||
SSF_GET_CURR_THREAD_SLOT=2
|
||||
SSF_GET_THREAD_PRIORITY=3
|
||||
@@ -281,14 +287,14 @@ SF_NETWORK_PROTOCOL=76
|
||||
SSF_ARP_DEL_ENTRY=50005h
|
||||
SSF_ARP_SEND_ANNOUNCE=50006h
|
||||
SSF_ARP_CONFLICTS_COUNT=50007h
|
||||
SF_FUTEX=77
|
||||
SSF_CREATE=0
|
||||
SSF_DESTROY=1
|
||||
SSF_WAIT=2
|
||||
SSF_WAKE=3
|
||||
SSF_FILE_READ=10
|
||||
SSF_FILE_WRITE=11
|
||||
SSF_PIPE_CREATE=13
|
||||
SF_POSIX=77
|
||||
SSF_FUTEX_CREATE=0
|
||||
SSF_FUTEX_DESTROY=1
|
||||
SSF_FUTEX_WAIT=2
|
||||
SSF_FUTEX_WAKE=3
|
||||
SSF_FD_READ=10
|
||||
SSF_FD_WRITE=11
|
||||
SSF_FD_PIPE2=13
|
||||
|
||||
; File system errors:
|
||||
FSERR_SUCCESS=0
|
||||
|
||||
@@ -1111,7 +1111,7 @@ end if
|
||||
mov dword [edx+8],ebx
|
||||
mov dword [edx+4],ecx
|
||||
mov dword [edx],Kolibri_ThreadFinish
|
||||
mov eax,SF_CREATE_THREAD
|
||||
mov eax,SF_THREAD_CONTROL
|
||||
mov ebx,1
|
||||
mov ecx,@Kolibri@ThreadMain$qpvt1
|
||||
int 0x40
|
||||
|
||||
@@ -1067,7 +1067,7 @@ end if
|
||||
mov dword [edx+8],ebx
|
||||
mov dword [edx+4],ecx
|
||||
mov dword [edx],Kolibri_ThreadFinish
|
||||
mov eax,SF_CREATE_THREAD
|
||||
mov eax,SF_THREAD_CONTROL
|
||||
mov ebx,1
|
||||
mov ecx,@Kolibri@ThreadMain$qpvt1
|
||||
int 0x40
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
Компилятор XD Pascal, [оригинал проекта](https://github.com/vtereshkov/xdpw), автор оригинала Василий Терешков.
|
||||
В [архиве](./release) компилятор и исходники для `xdpw_2026`(версия для Windows) и `xdpk`(версия для KolibriOS).
|
||||
Компилятор также компилирует сам себя из-под KolibriOS.
|
||||
Размер сжатого компилятора менее 30 килобайтов.
|
||||
|
||||
В папке `xdpk/projects` находятся примеры, также там находится сам компилятор под KolibriOS(`xdpk/projects/Compiler`).
|
||||
Чтобы собрать какой-нибудь пример, нужно просто зайти из-под KolibriOS в папку с примером и запустить файл `MAKE.SH`.
|
||||
Скомпилированное приложение должно появиться в той же папке с примером(если нет, то нажмите "обновить"(F5) в файловом менеджере).
|
||||
А для сборки из-под Windows нужно запустить файл `make.bat`.
|
||||
|
||||
Компиляция:
|
||||
* "xdpw_2026/xdpw.exe" — компилирует из-под Windows приложения для Windows
|
||||
* "xdpk/xdpk.exe" — компилирует из-под Windows приложения для KolibriOS
|
||||
* "xdpk/xdpk.kex" — компилирует из-под KolibriOS приложения для KolibriOS
|
||||
|
||||
Компиляторы вырезают недостижимый код (smart linking): бинарники меньше в 1.5–5 раз.
|
||||
Ключ `-nosmart` отключает оптимизацию. В `xdpw_2020` лежит прежний компилятор без неё.
|
||||
|
||||
Для KolibriOS реализованы модули:
|
||||
* CRT
|
||||
* LibImg
|
||||
* LibINI
|
||||
* Network
|
||||
* OpenDlg
|
||||
* ColorDlg
|
||||
* TinyGL
|
||||
|
||||
[Сайт проекта XD Pascal для KolibriOS: xdpk](https://gitflic.ru/project/kolibrios-programming/xd-pascal)
|
||||
[Архивная копия](https://web.archive.org/web/http://forum.cantor.systems/viewtopic.php?id=131) обсуждения на форуме.
|
||||
@@ -0,0 +1,25 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,3 @@
|
||||
..\xdpw_2026\xdpw source\XDPK.pas
|
||||
move /y source\xdpk.exe xdpk.exe
|
||||
pause
|
||||
@@ -0,0 +1,6 @@
|
||||
cd source
|
||||
dcc32 xdpk.pas
|
||||
copy xdpk.exe ..\xdpk.exe /y
|
||||
del xdpk.exe, *.dcu
|
||||
cd ..
|
||||
pause
|
||||
@@ -0,0 +1,24 @@
|
||||
program ClrEolTest;
|
||||
|
||||
uses
|
||||
CRT;
|
||||
|
||||
begin
|
||||
|
||||
CRT_initialization;
|
||||
|
||||
WriteLn('Hello, this is a ClrEolTest!');
|
||||
Delay(500);
|
||||
ClrScr;
|
||||
Writeln('The function CLREOL clears all characters from the');
|
||||
Delay(500);
|
||||
Writeln('cursor position to the end of the line within the');
|
||||
Delay(500);
|
||||
Writeln('current text window, without moving the cursor.');
|
||||
Delay(500);
|
||||
Writeln('Press any key to continue . . .');
|
||||
GotoXY(14, 4);
|
||||
ReadKey;
|
||||
ClrEOL;
|
||||
ReadKey;
|
||||
end.
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
launch this program with some
|
||||
command line arguments
|
||||
if argument has spaces then
|
||||
need to quote them
|
||||
for example:
|
||||
CmdLineArgs.kex param1 param2 "p a r a m 3"
|
||||
note that ParamStr(0) is always present
|
||||
and contents full file path to CmdLineArgs.kex
|
||||
}
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program CmdLineArgs;
|
||||
|
||||
var
|
||||
i: LongInt;
|
||||
|
||||
begin
|
||||
WriteLn('ParamCount = ', ParamCount);
|
||||
for i := 0 to ParamCount do
|
||||
WriteLn('ParamStr(', i, ') = ', ParamStr(i));
|
||||
end.
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,399 @@
|
||||
// XD Pascal - a 32-bit compiler for KolibriOS
|
||||
// Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov
|
||||
|
||||
{$I-}
|
||||
{$H-}
|
||||
|
||||
unit Linker;
|
||||
|
||||
|
||||
interface
|
||||
|
||||
|
||||
uses Common, CodeGen;
|
||||
|
||||
|
||||
procedure InitializeLinker;
|
||||
procedure SetProgramEntryPoint;
|
||||
function AddImportFunc(const ImportLibName, ImportFuncName: TString): LongInt;
|
||||
procedure LinkAndWriteProgram(const ExeName: TString);
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
const
|
||||
IMGBASE = $0;
|
||||
SECTALIGN = $20;
|
||||
FILEALIGN = SECTALIGN;
|
||||
|
||||
MAXIMPORTLIBS = 100;
|
||||
MAXIMPORTS = 2000;
|
||||
|
||||
|
||||
type
|
||||
TDOSStub = array [0..127] of Byte;
|
||||
|
||||
|
||||
TPEHeader = packed record
|
||||
PE: array [0..3] of TCharacter;
|
||||
Machine: Word;
|
||||
NumberOfSections: Word;
|
||||
TimeDateStamp: LongInt;
|
||||
PointerToSymbolTable: LongInt;
|
||||
NumberOfSymbols: LongInt;
|
||||
SizeOfOptionalHeader: Word;
|
||||
Characteristics: Word;
|
||||
end;
|
||||
|
||||
|
||||
TPEOptionalHeader = packed record
|
||||
Magic: Word;
|
||||
MajorLinkerVersion: Byte;
|
||||
MinorLinkerVersion: Byte;
|
||||
SizeOfCode: LongInt;
|
||||
SizeOfInitializedData: LongInt;
|
||||
SizeOfUninitializedData: LongInt;
|
||||
AddressOfEntryPoint: LongInt;
|
||||
BaseOfCode: LongInt;
|
||||
BaseOfData: LongInt;
|
||||
ImageBase: LongInt;
|
||||
SectionAlignment: LongInt;
|
||||
FileAlignment: LongInt;
|
||||
MajorOperatingSystemVersion: Word;
|
||||
MinorOperatingSystemVersion: Word;
|
||||
MajorImageVersion: Word;
|
||||
MinorImageVersion: Word;
|
||||
MajorSubsystemVersion: Word;
|
||||
MinorSubsystemVersion: Word;
|
||||
Win32VersionValue: LongInt;
|
||||
SizeOfImage: LongInt;
|
||||
SizeOfHeaders: LongInt;
|
||||
CheckSum: LongInt;
|
||||
Subsystem: Word;
|
||||
DllCharacteristics: Word;
|
||||
SizeOfStackReserve: LongInt;
|
||||
SizeOfStackCommit: LongInt;
|
||||
SizeOfHeapReserve: LongInt;
|
||||
SizeOfHeapCommit: LongInt;
|
||||
LoaderFlags: LongInt;
|
||||
NumberOfRvaAndSizes: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TDataDirectory = packed record
|
||||
VirtualAddress: LongInt;
|
||||
Size: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TPESectionHeader = packed record
|
||||
Name: array [0..7] of TCharacter;
|
||||
VirtualSize: LongInt;
|
||||
VirtualAddress: LongInt;
|
||||
SizeOfRawData: LongInt;
|
||||
PointerToRawData: LongInt;
|
||||
PointerToRelocations: LongInt;
|
||||
PointerToLinenumbers: LongInt;
|
||||
NumberOfRelocations: Word;
|
||||
NumberOfLinenumbers: Word;
|
||||
Characteristics: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
THeaders = packed record
|
||||
Signature: array [0..7] of TCharacter;
|
||||
Version: LongInt;
|
||||
EntryPoint: LongInt;
|
||||
EndImage: LongInt;
|
||||
Memory: LongInt;
|
||||
StackTop: LongInt;
|
||||
CmdLine: LongInt;
|
||||
FilePath: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TImportLibName = array [0..15] of TCharacter;
|
||||
TImportFuncName = array [0..31] of TCharacter;
|
||||
|
||||
|
||||
TImportDirectoryTableEntry = packed record
|
||||
Characteristics: LongInt;
|
||||
TimeDateStamp: LongInt;
|
||||
ForwarderChain: LongInt;
|
||||
Name: LongInt;
|
||||
FirstThunk: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TImportNameTableEntry = packed record
|
||||
Hint: Word;
|
||||
Name: TImportFuncName;
|
||||
end;
|
||||
|
||||
|
||||
TImport = record
|
||||
LibName, FuncName: TString;
|
||||
end;
|
||||
|
||||
|
||||
TImportSectionData = record
|
||||
DirectoryTable: array [1..MAXIMPORTLIBS + 1] of TImportDirectoryTableEntry;
|
||||
LibraryNames: array [1..MAXIMPORTLIBS] of TImportLibName;
|
||||
LookupTable: array [1..MAXIMPORTS + MAXIMPORTLIBS] of LongInt;
|
||||
NameTable: array [1..MAXIMPORTS] of TImportNameTableEntry;
|
||||
NumImports, NumImportLibs: Integer;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
var
|
||||
Headers: THeaders;
|
||||
Import: array [1..MAXIMPORTS] of TImport;
|
||||
ImportSectionData: TImportSectionData;
|
||||
LastImportLibName: TString;
|
||||
ProgramEntryPoint: LongInt;
|
||||
|
||||
CodeSectionHeader_VirtualAddress: LongInt;
|
||||
DataSectionHeader_VirtualAddress: LongInt;
|
||||
BSSSectionHeader_VirtualAddress: LongInt;
|
||||
ImportSectionHeader_VirtualAddress: LongInt;
|
||||
{
|
||||
const
|
||||
DOSStub: TDOSStub =
|
||||
(
|
||||
$4D, $5A, $90, $00, $03, $00, $00, $00, $04, $00, $00, $00, $FF, $FF, $00, $00,
|
||||
$B8, $00, $00, $00, $00, $00, $00, $00, $40, $00, $00, $00, $00, $00, $00, $00,
|
||||
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
|
||||
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $80, $00, $00, $00,
|
||||
$0E, $1F, $BA, $0E, $00, $B4, $09, $CD, $21, $B8, $01, $4C, $CD, $21, $54, $68,
|
||||
$69, $73, $20, $70, $72, $6F, $67, $72, $61, $6D, $20, $63, $61, $6E, $6E, $6F,
|
||||
$74, $20, $62, $65, $20, $72, $75, $6E, $20, $69, $6E, $20, $44, $4F, $53, $20,
|
||||
$6D, $6F, $64, $65, $2E, $0D, $0D, $0A, $24, $00, $00, $00, $00, $00, $00, $00
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
procedure Pad(var f: file; Size, Alignment: Integer);
|
||||
var
|
||||
i: Integer;
|
||||
b: Byte;
|
||||
begin
|
||||
b := 0;
|
||||
for i := 0 to Align(Size, Alignment) - Size - 1 do
|
||||
BlockWrite(f, b, 1);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FillHeaders(CodeSize, InitializedDataSize, UninitializedDataSize, ImportSize: Integer);
|
||||
const
|
||||
PATH_SIZE = 1024;
|
||||
PARAMS_SIZE = 256;
|
||||
STACK_SIZE = 1024 * 1024;
|
||||
|
||||
begin
|
||||
FillChar(Headers, SizeOf(Headers), #0);
|
||||
|
||||
CodeSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN);
|
||||
DataSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN);
|
||||
BSSSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN) + Align(InitializedDataSize, SECTALIGN);
|
||||
ImportSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN) + Align(InitializedDataSize, SECTALIGN) + Align(UninitializedDataSize, SECTALIGN);
|
||||
|
||||
with Headers do
|
||||
begin
|
||||
Signature[0] := 'M';
|
||||
Signature[1] := 'E';
|
||||
Signature[2] := 'N';
|
||||
Signature[3] := 'U';
|
||||
Signature[4] := 'E';
|
||||
Signature[5] := 'T';
|
||||
Signature[6] := '0';
|
||||
Signature[7] := '1';
|
||||
Version := 1;
|
||||
EntryPoint := Align(SizeOf(Headers), SECTALIGN) + ProgramEntryPoint;
|
||||
EndImage := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN) + Align(InitializedDataSize, SECTALIGN);
|
||||
FilePath := EndImage + Align(UninitializedDataSize, SECTALIGN);
|
||||
Memory := FilePath + PATH_SIZE + PARAMS_SIZE + STACK_SIZE;
|
||||
StackTop := FilePath + PATH_SIZE + PARAMS_SIZE + STACK_SIZE;
|
||||
CmdLine := FilePath + PATH_SIZE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure InitializeLinker;
|
||||
begin
|
||||
FillChar(Import, SizeOf(Import), #0);
|
||||
FillChar(ImportSectionData, SizeOf(ImportSectionData), #0);
|
||||
LastImportLibName := '';
|
||||
ProgramEntryPoint := 0;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure SetProgramEntryPoint;
|
||||
begin
|
||||
if ProgramEntryPoint <> 0 then
|
||||
Error('Duplicate program entry point');
|
||||
|
||||
ProgramEntryPoint := GetCodeSize;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function AddImportFunc(const ImportLibName, ImportFuncName: TString): LongInt;
|
||||
begin
|
||||
with ImportSectionData do
|
||||
begin
|
||||
Inc(NumImports);
|
||||
if NumImports > MAXIMPORTS then
|
||||
Error('Maximum number of import functions exceeded');
|
||||
|
||||
Import[NumImports].LibName := ImportLibName;
|
||||
Import[NumImports].FuncName := ImportFuncName;
|
||||
|
||||
if ImportLibName <> LastImportLibName then
|
||||
begin
|
||||
Inc(NumImportLibs);
|
||||
if NumImportLibs > MAXIMPORTLIBS then
|
||||
Error('Maximum number of import libraries exceeded');
|
||||
LastImportLibName := ImportLibName;
|
||||
end;
|
||||
|
||||
Result := (NumImports - 1 + NumImportLibs - 1) * SizeOf(LongInt); // Relocatable
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FillImportSection(var ImportSize, LookupTableOffset: Integer);
|
||||
var
|
||||
ImportIndex, ImportLibIndex, LookupIndex: Integer;
|
||||
LibraryNamesOffset, NameTableOffset: Integer;
|
||||
|
||||
begin
|
||||
with ImportSectionData do
|
||||
begin
|
||||
LibraryNamesOffset := SizeOf(DirectoryTable[1]) * (NumImportLibs + 1);
|
||||
LookupTableOffset := LibraryNamesOffset + SizeOf(LibraryNames[1]) * NumImportLibs;
|
||||
NameTableOffset := LookupTableOffset + SizeOf(LookupTable[1]) * (NumImports + NumImportLibs);
|
||||
ImportSize := NameTableOffset + SizeOf(NameTable[1]) * NumImports;
|
||||
|
||||
LastImportLibName := '';
|
||||
ImportLibIndex := 0;
|
||||
LookupIndex := 0;
|
||||
|
||||
for ImportIndex := 1 to NumImports do
|
||||
begin
|
||||
// Add new import library
|
||||
if (ImportLibIndex = 0) or (Import[ImportIndex].LibName <> LastImportLibName) then
|
||||
begin
|
||||
if ImportLibIndex <> 0 then Inc(LookupIndex); // Add null entry before the first thunk of a new library
|
||||
|
||||
Inc(ImportLibIndex);
|
||||
|
||||
DirectoryTable[ImportLibIndex].Name := LibraryNamesOffset + SizeOf(LibraryNames[1]) * (ImportLibIndex - 1);
|
||||
DirectoryTable[ImportLibIndex].FirstThunk := LookupTableOffset + SizeOf(LookupTable[1]) * LookupIndex;
|
||||
|
||||
Move(Import[ImportIndex].LibName[1], LibraryNames[ImportLibIndex], Length(Import[ImportIndex].LibName));
|
||||
|
||||
LastImportLibName := Import[ImportIndex].LibName;
|
||||
end; // if
|
||||
|
||||
// Add new import function
|
||||
Inc(LookupIndex);
|
||||
if LookupIndex > MAXIMPORTS + MAXIMPORTLIBS then
|
||||
Error('Maximum number of lookup entries exceeded');
|
||||
|
||||
LookupTable[LookupIndex] := NameTableOffset + SizeOf(NameTable[1]) * (ImportIndex - 1);
|
||||
|
||||
Move(Import[ImportIndex].FuncName[1], NameTable[ImportIndex].Name, Length(Import[ImportIndex].FuncName));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FixupImportSection(VirtualAddress: LongInt);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
with ImportSectionData do
|
||||
begin
|
||||
for i := 1 to NumImportLibs do
|
||||
with DirectoryTable[i] do
|
||||
begin
|
||||
Name := Name + VirtualAddress;
|
||||
FirstThunk := FirstThunk + VirtualAddress;
|
||||
end;
|
||||
|
||||
for i := 1 to NumImports + NumImportLibs do
|
||||
if LookupTable[i] <> 0 then
|
||||
LookupTable[i] := LookupTable[i] + VirtualAddress;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure LinkAndWriteProgram(const ExeName: TString);
|
||||
var
|
||||
OutFile: TOutFile;
|
||||
CodeSize, ImportSize, LookupTableOffset: Integer;
|
||||
|
||||
begin
|
||||
if ProgramEntryPoint = 0 then
|
||||
Error('Program entry point not found');
|
||||
|
||||
CodeSize := GetCodeSize;
|
||||
|
||||
FillImportSection(ImportSize, LookupTableOffset);
|
||||
FillHeaders(CodeSize, InitializedGlobalDataSize, UninitializedGlobalDataSize, ImportSize);
|
||||
|
||||
Relocate(IMGBASE + CodeSectionHeader_VirtualAddress,
|
||||
IMGBASE + DataSectionHeader_VirtualAddress,
|
||||
IMGBASE + BSSSectionHeader_VirtualAddress,
|
||||
IMGBASE + ImportSectionHeader_VirtualAddress + LookupTableOffset);
|
||||
|
||||
//FixupImportSection(Headers.ImportSectionHeader.VirtualAddress);
|
||||
|
||||
// Write output file
|
||||
Assign(OutFile, TGenericString(ExeName));
|
||||
Rewrite(OutFile, 1);
|
||||
|
||||
if IOResult <> 0 then
|
||||
Error('Unable to open output file ' + ExeName);
|
||||
|
||||
BlockWrite(OutFile, Headers, SizeOf(Headers));
|
||||
Pad(OutFile, SizeOf(Headers), FILEALIGN);
|
||||
|
||||
BlockWrite(OutFile, Code, CodeSize);
|
||||
Pad(OutFile, CodeSize, FILEALIGN);
|
||||
|
||||
BlockWrite(OutFile, InitializedGlobalData, InitializedGlobalDataSize);
|
||||
Pad(OutFile, InitializedGlobalDataSize, FILEALIGN);
|
||||
{
|
||||
with ImportSectionData do
|
||||
begin
|
||||
BlockWrite(OutFile, DirectoryTable, SizeOf(DirectoryTable[1]) * (NumImportLibs + 1));
|
||||
BlockWrite(OutFile, LibraryNames, SizeOf(LibraryNames[1]) * NumImportLibs);
|
||||
BlockWrite(OutFile, LookupTable, SizeOf(LookupTable[1]) * (NumImports + NumImportLibs));
|
||||
BlockWrite(OutFile, NameTable, SizeOf(NameTable[1]) * NumImports);
|
||||
end;
|
||||
Pad(OutFile, ImportSize, FILEALIGN);
|
||||
}
|
||||
Close(OutFile);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#SHS
|
||||
rm xdpk.kex
|
||||
../../xdpk.kex xdpk.pas
|
||||
exit
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,698 @@
|
||||
// XD Pascal - a 32-bit compiler for KolibriOS
|
||||
// Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov
|
||||
|
||||
{$I-}
|
||||
{$H-}
|
||||
|
||||
unit Scanner;
|
||||
|
||||
|
||||
interface
|
||||
|
||||
|
||||
uses Common;
|
||||
|
||||
|
||||
var
|
||||
Tok: TToken;
|
||||
|
||||
|
||||
procedure InitializeScanner(const Name: TString);
|
||||
function SaveScanner: Boolean;
|
||||
function RestoreScanner: Boolean;
|
||||
procedure FinalizeScanner;
|
||||
procedure NextTok;
|
||||
procedure CheckTok(ExpectedTokKind: TTokenKind);
|
||||
procedure EatTok(ExpectedTokKind: TTokenKind);
|
||||
procedure AssertIdent;
|
||||
function ScannerFileName: TString;
|
||||
function ScannerLine: Integer;
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
|
||||
type
|
||||
TBuffer = record
|
||||
Ptr: PCharacter;
|
||||
Size, Pos: Integer;
|
||||
end;
|
||||
|
||||
|
||||
TScannerState = record
|
||||
Token: TToken;
|
||||
FileName: TString;
|
||||
Line: Integer;
|
||||
Buffer: TBuffer;
|
||||
ch, ch2: TCharacter;
|
||||
EndOfUnit: Boolean;
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
SCANNERSTACKSIZE = 10;
|
||||
|
||||
|
||||
var
|
||||
ScannerState: TScannerState;
|
||||
ScannerStack: array [1..SCANNERSTACKSIZE] of TScannerState;
|
||||
ScannerStackTop: Integer = 0;
|
||||
|
||||
|
||||
const
|
||||
Digits: set of TCharacter = ['0'..'9'];
|
||||
HexDigits: set of TCharacter = ['0'..'9', 'A'..'F'];
|
||||
Spaces: set of TCharacter = [#1..#31, ' '];
|
||||
AlphaNums: set of TCharacter = ['A'..'Z', 'a'..'z', '0'..'9', '_'];
|
||||
|
||||
|
||||
|
||||
|
||||
procedure InitializeScanner(const Name: TString);
|
||||
var
|
||||
F: TInFile;
|
||||
ActualSize: Integer;
|
||||
FolderIndex: Integer;
|
||||
|
||||
begin
|
||||
ScannerState.Buffer.Ptr := nil;
|
||||
|
||||
// First search the source folder, then the units folder, then the folders specified in $UNITPATH
|
||||
FolderIndex := 1;
|
||||
|
||||
repeat
|
||||
Assign(F, TGenericString(Folders[FolderIndex] + Name));
|
||||
Reset(F, 1);
|
||||
if IOResult = 0 then Break;
|
||||
Inc(FolderIndex);
|
||||
until FolderIndex > NumFolders;
|
||||
|
||||
if FolderIndex > NumFolders then
|
||||
Error('Unable to open source file ' + Name);
|
||||
|
||||
with ScannerState do
|
||||
begin
|
||||
FileName := Name;
|
||||
Line := 1;
|
||||
|
||||
with Buffer do
|
||||
begin
|
||||
Size := FileSize(F);
|
||||
Pos := 0;
|
||||
|
||||
GetMem(Ptr, Size);
|
||||
|
||||
ActualSize := 0;
|
||||
BlockRead(F, Ptr^, Size, ActualSize);
|
||||
Close(F);
|
||||
|
||||
if ActualSize <> Size then
|
||||
Error('Unable to read source file ' + Name);
|
||||
end;
|
||||
|
||||
ch := ' ';
|
||||
ch2 := ' ';
|
||||
EndOfUnit := FALSE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function SaveScanner: Boolean;
|
||||
begin
|
||||
Result := FALSE;
|
||||
if ScannerStackTop < SCANNERSTACKSIZE then
|
||||
begin
|
||||
Inc(ScannerStackTop);
|
||||
ScannerStack[ScannerStackTop] := ScannerState;
|
||||
Result := TRUE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function RestoreScanner: Boolean;
|
||||
begin
|
||||
Result := FALSE;
|
||||
if ScannerStackTop > 0 then
|
||||
begin
|
||||
ScannerState := ScannerStack[ScannerStackTop];
|
||||
Dec(ScannerStackTop);
|
||||
Tok := ScannerState.Token;
|
||||
Result := TRUE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FinalizeScanner;
|
||||
begin
|
||||
ScannerState.EndOfUnit := TRUE;
|
||||
with ScannerState.Buffer do
|
||||
if Ptr <> nil then
|
||||
begin
|
||||
FreeMem(Ptr);
|
||||
Ptr := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure AppendStrSafe(var s: TString; ch: TCharacter);
|
||||
begin
|
||||
if Length(s) >= MAXSTRLENGTH - 1 then
|
||||
Error('String is too long');
|
||||
s := s + ch;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadChar(var ch: TCharacter);
|
||||
begin
|
||||
if ScannerState.ch = #10 then Inc(ScannerState.Line); // End of line found
|
||||
|
||||
ch := #0;
|
||||
with ScannerState.Buffer do
|
||||
if Pos < Size then
|
||||
begin
|
||||
ch := PCharacter(Integer(Ptr) + Pos)^;
|
||||
Inc(Pos);
|
||||
end
|
||||
else
|
||||
ScannerState.EndOfUnit := TRUE;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadUppercaseChar(var ch: TCharacter);
|
||||
begin
|
||||
ReadChar(ch);
|
||||
ch := UpCase(ch);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadLiteralChar(var ch: TCharacter);
|
||||
begin
|
||||
ReadChar(ch);
|
||||
if (ch = #0) or (ch = #10) then
|
||||
Error('Unterminated string');
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadSingleLineComment;
|
||||
begin
|
||||
with ScannerState do
|
||||
while (ch <> #10) and not EndOfUnit do
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadMultiLineComment;
|
||||
begin
|
||||
with ScannerState do
|
||||
while (ch <> '}') and not EndOfUnit do
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadDirective;
|
||||
var
|
||||
Text: TString;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Text := '';
|
||||
repeat
|
||||
AppendStrSafe(Text, ch);
|
||||
ReadUppercaseChar(ch);
|
||||
until not (ch in AlphaNums);
|
||||
|
||||
if Text = '$APPTYPE' then // Console/GUI application type directive
|
||||
begin
|
||||
Text := '';
|
||||
ReadChar(ch);
|
||||
while (ch <> '}') and not EndOfUnit do
|
||||
begin
|
||||
if (ch = #0) or (ch > ' ') then
|
||||
AppendStrSafe(Text, UpCase(ch));
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
if Text = 'CONSOLE' then
|
||||
IsConsoleProgram := TRUE
|
||||
else if Text = 'GUI' then
|
||||
IsConsoleProgram := FALSE
|
||||
else
|
||||
Error('Unknown application type ' + Text);
|
||||
end
|
||||
|
||||
else if Text = '$UNITPATH' then // Unit path directive
|
||||
begin
|
||||
Text := '';
|
||||
ReadChar(ch);
|
||||
while (ch <> '}') and not EndOfUnit do
|
||||
begin
|
||||
if (ch = #0) or (ch > ' ') then
|
||||
AppendStrSafe(Text, UpCase(ch));
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
Inc(NumFolders);
|
||||
if NumFolders > MAXFOLDERS then
|
||||
Error('Maximum number of unit paths exceeded');
|
||||
Folders[NumFolders] := Folders[1] + Text;
|
||||
end
|
||||
|
||||
else // All other directives are ignored
|
||||
ReadMultiLineComment;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadHexadecimalNumber;
|
||||
var
|
||||
Num, Digit: Integer;
|
||||
NumFound: Boolean;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Num := 0;
|
||||
|
||||
NumFound := FALSE;
|
||||
while ch in HexDigits do
|
||||
begin
|
||||
if Num and $F0000000 <> 0 then
|
||||
Error('Numeric constant is too large');
|
||||
|
||||
if ch in Digits then
|
||||
Digit := Ord(ch) - Ord('0')
|
||||
else
|
||||
Digit := Ord(ch) - Ord('A') + 10;
|
||||
|
||||
Num := Num shl 4 or Digit;
|
||||
NumFound := TRUE;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
|
||||
if not NumFound then
|
||||
Error('Hexadecimal constant is not found');
|
||||
|
||||
Token.Kind := INTNUMBERTOK;
|
||||
Token.OrdValue := Num;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadDecimalNumber;
|
||||
var
|
||||
Num, Expon, Digit: Integer;
|
||||
Frac, FracWeight: Double;
|
||||
NegExpon, RangeFound, ExponFound: Boolean;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Num := 0;
|
||||
Frac := 0;
|
||||
Expon := 0;
|
||||
NegExpon := FALSE;
|
||||
|
||||
while ch in Digits do
|
||||
begin
|
||||
Digit := Ord(ch) - Ord('0');
|
||||
|
||||
if Num > (HighBound(INTEGERTYPEINDEX) - Digit) div 10 then
|
||||
Error('Numeric constant is too large');
|
||||
|
||||
Num := 10 * Num + Digit;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
|
||||
if (ch <> '.') and (ch <> 'E') then // Integer number
|
||||
begin
|
||||
Token.Kind := INTNUMBERTOK;
|
||||
Token.OrdValue := Num;
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
// Check for '..' token
|
||||
RangeFound := FALSE;
|
||||
if ch = '.' then
|
||||
begin
|
||||
ReadUppercaseChar(ch2);
|
||||
if ch2 = '.' then // Integer number followed by '..' token
|
||||
begin
|
||||
Token.Kind := INTNUMBERTOK;
|
||||
Token.OrdValue := Num;
|
||||
RangeFound := TRUE;
|
||||
end;
|
||||
if not EndOfUnit then Dec(Buffer.Pos);
|
||||
end; // if ch = '.'
|
||||
|
||||
if not RangeFound then // Fractional number
|
||||
begin
|
||||
|
||||
// Check for fractional part
|
||||
if ch = '.' then
|
||||
begin
|
||||
FracWeight := 0.1;
|
||||
ReadUppercaseChar(ch);
|
||||
|
||||
while ch in Digits do
|
||||
begin
|
||||
Digit := Ord(ch) - Ord('0');
|
||||
Frac := Frac + FracWeight * Digit;
|
||||
FracWeight := FracWeight / 10;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end; // if ch = '.'
|
||||
|
||||
// Check for exponent
|
||||
if ch = 'E' then
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
|
||||
// Check for exponent sign
|
||||
if ch = '+' then
|
||||
ReadUppercaseChar(ch)
|
||||
else if ch = '-' then
|
||||
begin
|
||||
NegExpon := TRUE;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
|
||||
ExponFound := FALSE;
|
||||
while ch in Digits do
|
||||
begin
|
||||
Digit := Ord(ch) - Ord('0');
|
||||
Expon := 10 * Expon + Digit;
|
||||
ReadUppercaseChar(ch);
|
||||
ExponFound := TRUE;
|
||||
end;
|
||||
|
||||
if not ExponFound then
|
||||
Error('Exponent is not found');
|
||||
|
||||
if NegExpon then Expon := -Expon;
|
||||
end; // if ch = 'E'
|
||||
|
||||
Token.Kind := REALNUMBERTOK;
|
||||
Token.RealValue := (Num + Frac) * exp(Expon * ln(10));
|
||||
end; // if not RangeFound
|
||||
end; // else
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadNumber;
|
||||
begin
|
||||
with ScannerState do
|
||||
if ch = '$' then
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
ReadHexadecimalNumber;
|
||||
end
|
||||
else
|
||||
ReadDecimalNumber;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadCharCode;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
|
||||
if not (ch in Digits + ['$']) then
|
||||
Error('Character code is not found');
|
||||
|
||||
ReadNumber;
|
||||
|
||||
if (Token.Kind = REALNUMBERTOK) or (Token.OrdValue < 0) or (Token.OrdValue > 255) then
|
||||
Error('Illegal character code');
|
||||
|
||||
Token.Kind := CHARLITERALTOK;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadKeywordOrIdentifier;
|
||||
var
|
||||
Text, NonUppercaseText: TString;
|
||||
CurToken: TTokenKind;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Text := '';
|
||||
NonUppercaseText := '';
|
||||
|
||||
repeat
|
||||
AppendStrSafe(NonUppercaseText, ch);
|
||||
ch := UpCase(ch);
|
||||
AppendStrSafe(Text, ch);
|
||||
ReadChar(ch);
|
||||
until not (ch in AlphaNums);
|
||||
|
||||
CurToken := GetKeyword(Text);
|
||||
if CurToken <> EMPTYTOK then // Keyword found
|
||||
Token.Kind := CurToken
|
||||
else
|
||||
begin // Identifier found
|
||||
Token.Kind := IDENTTOK;
|
||||
Token.Name := Text;
|
||||
Token.NonUppercaseName := NonUppercaseText;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadCharOrStringLiteral;
|
||||
var
|
||||
Text: TString;
|
||||
EndOfLiteral: Boolean;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Text := '';
|
||||
EndOfLiteral := FALSE;
|
||||
|
||||
repeat
|
||||
ReadLiteralChar(ch);
|
||||
if ch <> '''' then
|
||||
AppendStrSafe(Text, ch)
|
||||
else
|
||||
begin
|
||||
ReadChar(ch2);
|
||||
if ch2 = '''' then // Apostrophe character found
|
||||
AppendStrSafe(Text, ch)
|
||||
else
|
||||
begin
|
||||
if not EndOfUnit then Dec(Buffer.Pos); // Discard ch2
|
||||
EndOfLiteral := TRUE;
|
||||
end;
|
||||
end;
|
||||
until EndOfLiteral;
|
||||
|
||||
if Length(Text) = 1 then
|
||||
begin
|
||||
Token.Kind := CHARLITERALTOK;
|
||||
Token.OrdValue := Ord(Text[1]);
|
||||
end
|
||||
else
|
||||
begin
|
||||
Token.Kind := STRINGLITERALTOK;
|
||||
Token.Name := Text;
|
||||
Token.StrLength := Length(Text);
|
||||
DefineStaticString(Text, Token.StrAddress);
|
||||
end;
|
||||
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure NextTok;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Token.Kind := EMPTYTOK;
|
||||
|
||||
// Skip spaces, comments, directives
|
||||
while (ch in Spaces) or (ch = '{') or (ch = '/') do
|
||||
begin
|
||||
if ch = '{' then // Multi-line comment or directive
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '$' then ReadDirective else ReadMultiLineComment;
|
||||
end
|
||||
else if ch = '/' then
|
||||
begin
|
||||
ReadUppercaseChar(ch2);
|
||||
if ch2 = '/' then
|
||||
ReadSingleLineComment // Double-line comment
|
||||
else
|
||||
begin
|
||||
if not EndOfUnit then Dec(Buffer.Pos); // Discard ch2
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
// Read token
|
||||
case ch of
|
||||
'0'..'9', '$':
|
||||
ReadNumber;
|
||||
'#':
|
||||
ReadCharCode;
|
||||
'A'..'Z', 'a'..'z', '_':
|
||||
ReadKeywordOrIdentifier;
|
||||
'''':
|
||||
ReadCharOrStringLiteral;
|
||||
':': // Single- or double-character tokens
|
||||
begin
|
||||
Token.Kind := COLONTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '=' then
|
||||
begin
|
||||
Token.Kind := ASSIGNTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
'>':
|
||||
begin
|
||||
Token.Kind := GTTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '=' then
|
||||
begin
|
||||
Token.Kind := GETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
'<':
|
||||
begin
|
||||
Token.Kind := LTTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '=' then
|
||||
begin
|
||||
Token.Kind := LETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end
|
||||
else if ch = '>' then
|
||||
begin
|
||||
Token.Kind := NETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
'.':
|
||||
begin
|
||||
Token.Kind := PERIODTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '.' then
|
||||
begin
|
||||
Token.Kind := RANGETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end
|
||||
else // Double-character tokens
|
||||
case ch of
|
||||
'=': Token.Kind := EQTOK;
|
||||
',': Token.Kind := COMMATOK;
|
||||
';': Token.Kind := SEMICOLONTOK;
|
||||
'(': Token.Kind := OPARTOK;
|
||||
')': Token.Kind := CPARTOK;
|
||||
'*': Token.Kind := MULTOK;
|
||||
'/': Token.Kind := DIVTOK;
|
||||
'+': Token.Kind := PLUSTOK;
|
||||
'-': Token.Kind := MINUSTOK;
|
||||
'^': Token.Kind := DEREFERENCETOK;
|
||||
'@': Token.Kind := ADDRESSTOK;
|
||||
'[': Token.Kind := OBRACKETTOK;
|
||||
']': Token.Kind := CBRACKETTOK
|
||||
else
|
||||
Error('Unexpected character or end of file');
|
||||
end; // case
|
||||
|
||||
ReadChar(ch);
|
||||
end; // case
|
||||
end;
|
||||
|
||||
Tok := ScannerState.Token;
|
||||
end; // NextTok
|
||||
|
||||
|
||||
|
||||
|
||||
procedure CheckTok(ExpectedTokKind: TTokenKind);
|
||||
begin
|
||||
with ScannerState do
|
||||
if Token.Kind <> ExpectedTokKind then
|
||||
Error(GetTokSpelling(ExpectedTokKind) + ' expected but ' + GetTokSpelling(Token.Kind) + ' found');
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure EatTok(ExpectedTokKind: TTokenKind);
|
||||
begin
|
||||
CheckTok(ExpectedTokKind);
|
||||
NextTok;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure AssertIdent;
|
||||
begin
|
||||
with ScannerState do
|
||||
if Token.Kind <> IDENTTOK then
|
||||
Error('Identifier expected but ' + GetTokSpelling(Token.Kind) + ' found');
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function ScannerFileName: TString;
|
||||
begin
|
||||
Result := ScannerState.FileName;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function ScannerLine: Integer;
|
||||
begin
|
||||
Result := ScannerState.Line;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,128 @@
|
||||
// XD Pascal - a 32-bit compiler for KolibriOS
|
||||
// Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
{$I-}
|
||||
{$H-}
|
||||
|
||||
program XDPK;
|
||||
|
||||
|
||||
uses SysUtils, Common, Scanner, Parser, CodeGen, Linker;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure SplitPath(const Path: TString; var Folder, Name, Ext: TString);
|
||||
var
|
||||
DotPos, SlashPos, i: Integer;
|
||||
begin
|
||||
Folder := '';
|
||||
Name := Path;
|
||||
Ext := '';
|
||||
|
||||
DotPos := 0;
|
||||
SlashPos := 0;
|
||||
|
||||
for i := Length(Path) downto 1 do
|
||||
if (Path[i] = '.') and (DotPos = 0) then
|
||||
DotPos := i
|
||||
else if (Path[i] = '/') and (SlashPos = 0) then
|
||||
SlashPos := i;
|
||||
|
||||
if DotPos > 0 then
|
||||
begin
|
||||
Name := Copy(Path, 1, DotPos - 1);
|
||||
Ext := Copy(Path, DotPos, Length(Path) - DotPos + 1);
|
||||
end;
|
||||
|
||||
if SlashPos > 0 then
|
||||
begin
|
||||
Folder := Copy(Path, 1, SlashPos);
|
||||
Name := Copy(Path, SlashPos + 1, Length(Name) - SlashPos);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure NoticeProc(ClassInstance: Pointer; const Msg: TString);
|
||||
begin
|
||||
WriteLn(Msg);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure WarningProc(ClassInstance: Pointer; const Msg: TString);
|
||||
begin
|
||||
if NumUnits >= 1 then
|
||||
Notice(ScannerFileName + ' (' + IntToStr(ScannerLine) + ') Warning: ' + Msg)
|
||||
else
|
||||
Notice('Warning: ' + Msg);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ErrorProc(ClassInstance: Pointer; const Msg: TString);
|
||||
begin
|
||||
if NumUnits >= 1 then
|
||||
Notice(ScannerFileName + ' (' + IntToStr(ScannerLine) + ') Error: ' + Msg)
|
||||
else
|
||||
Notice('Error: ' + Msg);
|
||||
|
||||
repeat FinalizeScanner until not RestoreScanner;
|
||||
FinalizeCommon;
|
||||
Halt(1);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
var
|
||||
CompilerPath, CompilerFolder, CompilerName, CompilerExt,
|
||||
PasPath, PasFolder, PasName, PasExt,
|
||||
ExePath: TString;
|
||||
|
||||
|
||||
|
||||
begin
|
||||
SetWriteProcs(nil, @NoticeProc, @WarningProc, @ErrorProc);
|
||||
|
||||
Notice('XD Pascal for KolibriOS ' + VERSION);
|
||||
Notice('Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov');
|
||||
|
||||
if ParamCount < 1 then
|
||||
begin
|
||||
Notice('Usage: xdpk <file.pas>');
|
||||
Halt(1);
|
||||
end;
|
||||
|
||||
CompilerPath := TString(ParamStr(0));
|
||||
SplitPath(CompilerPath, CompilerFolder, CompilerName, CompilerExt);
|
||||
|
||||
PasPath := TString(ParamStr(1));
|
||||
SplitPath(PasPath, PasFolder, PasName, PasExt);
|
||||
|
||||
InitializeCommon;
|
||||
InitializeLinker;
|
||||
InitializeCodeGen;
|
||||
|
||||
Folders[1] := PasFolder;
|
||||
Folders[2] := CompilerFolder + 'units/';
|
||||
NumFolders := 2;
|
||||
|
||||
CompileProgramOrUnit('system.pas');
|
||||
CompileProgramOrUnit(PasName + PasExt);
|
||||
|
||||
ExePath := PasFolder + PasName + '.kex';
|
||||
LinkAndWriteProgram(ExePath);
|
||||
|
||||
Notice('Complete. Code size: ' + IntToStr(GetCodeSize) + ' bytes. Data size: ' + IntToStr(InitializedGlobalDataSize + UninitializedGlobalDataSize) + ' bytes');
|
||||
|
||||
repeat FinalizeScanner until not RestoreScanner;
|
||||
FinalizeCommon;
|
||||
end.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
if exist xdpk.kex del xdpk.kex
|
||||
..\..\xdpk xdpk.pas
|
||||
if exist xdpk.kex ..\..\kpack xdpk.kex
|
||||
pause
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
program Draw_Scaled_PNG_Image;
|
||||
|
||||
uses
|
||||
KolibriOS, LibImg;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: Integer;
|
||||
|
||||
ImageToDraw: PImage; // шчюсЁрцхэшх, ъюЄюЁюх сєфхь ЁшёютрЄ№
|
||||
|
||||
// яЁюсєхь чруЁєчшЄ№ Їрщы шчюсЁрцхэш , фхъюфшЁютрЄ№ ш ьрё°ЄрсшЁютрЄ№
|
||||
function OpenImageFile(FilePath: PAnsiChar): PImage;
|
||||
var
|
||||
FileAttributes: TFileAttributes;
|
||||
BytesRead: Integer;
|
||||
imgFile: Pointer;
|
||||
imgFileSize: Integer;
|
||||
imgData, imgScaled: PImage;
|
||||
begin
|
||||
Result := nil;
|
||||
// хёыш Їрщы фюёЄєяхэ
|
||||
if GetFileAttributes(FilePath, FileAttributes) = 0 then
|
||||
begin
|
||||
// єчэр╕ь ЁрчьхЁ Їрщыр т срщЄрї
|
||||
imgFileSize := FileAttributes.SizeLo;
|
||||
// т√фхы хь ярь Є№ фы ўЄхэш Єєфр ¤Єюую Їрщыр
|
||||
GetMem(imgFile, imgFileSize);
|
||||
// ўшЄрхь Їрщы
|
||||
ReadFile(FilePath, PAnsiChar(imgFile)^, imgFileSize, 0, 0, BytesRead);
|
||||
// яЁюсєхь фхъюфшЁютрЄ№ Їрщы шчюсЁрцхэш
|
||||
imgData := img_decode(imgFile, imgFileSize, nil);
|
||||
// юётюсюцфрхь т√фхыхээє■ яюф Їрщы ярь Є№
|
||||
FreeMem(imgFile);
|
||||
// хёыш єфрыюё№ фхъюфшЁютрЄ№ Їрщы шчюсЁрцхэш
|
||||
if imgData <> nil then
|
||||
begin
|
||||
// хёыш эхяюффхЁцштрхьр сшсышюЄхъющ уыєсшэр ЎтхЄр
|
||||
if not (imgData^.ImageType in [IMAGE_BPP24, IMAGE_BPP32, IMAGE_BPP8G]) then
|
||||
begin
|
||||
// ъюэтхЁЄшЁєхь т шчюсЁрцхэшх ё яюффхЁцштрхьющ уыєсшэющ
|
||||
imgScaled := img_convert(imgData, nil, IMAGE_BPP24, 0, 0);
|
||||
// єэшўЄюцрхь шёїюфэюх шчюсЁрцхэшх
|
||||
img_destroy(imgData);
|
||||
imgData := imgScaled;
|
||||
end;
|
||||
// яЁюсєхь ьрё°ЄрсшЁютрЄ№ т эют√щ ЁрчьхЁ 200x150
|
||||
imgScaled := img_scale(imgData, 0, 0, imgData^.Width, imgData^.Height,
|
||||
nil, LIBIMG_SCALE_STRETCH, LIBIMG_INTER_DEFAULT, 200, 150);
|
||||
Result := imgScaled;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
//SetAppDirAsCurrent;
|
||||
|
||||
LibImg_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 4;
|
||||
WndHeight := Height div 4;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
ImageToDraw := OpenImageFile('./Background.png');
|
||||
|
||||
while True do
|
||||
case WaitEvent of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Draw Scaled PNG Image', $00FFFFFF,
|
||||
WS_SKINNED_FIXED + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
// хёыш яюыєўшыюё№ ьрё°ЄрсшЁютрЄ№, Єю Ёшёєхь хую т Єюўъх (10, 5)
|
||||
if ImageToDraw <> nil then
|
||||
img_draw(ImageToDraw, 10, 5, $ffffffff, $ffffffff, 0, 0);
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
Exit;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,12 @@
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program EnterNumber;
|
||||
|
||||
var
|
||||
Number: LongInt;
|
||||
|
||||
begin
|
||||
Write('Enter Number please:');
|
||||
ReadLn(Number);
|
||||
WriteLn('You entered "', Number, '"');
|
||||
end.
|
||||
@@ -0,0 +1,48 @@
|
||||
program ExpSinGraph_CRT;
|
||||
|
||||
{ example from K. Jensen, N. Wirth "Pascal User Manual and Report" }
|
||||
|
||||
uses
|
||||
CRT;
|
||||
|
||||
const
|
||||
d = 1 / 16; // 16 lines for interval [x, x + 1]
|
||||
s = 32 / 1.5; // 32 character widths for interval [y, y + 1]
|
||||
h = 34; // character position of x-axis
|
||||
c = 2 * PI;
|
||||
lim = 32;
|
||||
|
||||
var
|
||||
i, n: Integer;
|
||||
x, y: Extended;
|
||||
|
||||
Colors: array [0..14] of Byte = (LightRed, Yellow, LightGreen, LightCyan, LightBlue,
|
||||
LightMagenta, White, LightGray, DarkGray, Magenta, Blue, Cyan, Green, Brown, Red);
|
||||
|
||||
ColorIndex: Integer = 0;
|
||||
|
||||
procedure SwitchColor;
|
||||
begin
|
||||
TextColor(Colors[ColorIndex]);
|
||||
Inc(ColorIndex);
|
||||
if ColorIndex > High(Colors) then
|
||||
ColorIndex := Low(Colors);
|
||||
end;
|
||||
|
||||
begin
|
||||
|
||||
CRT_initialization();
|
||||
|
||||
for i := 0 to lim do
|
||||
begin
|
||||
x := d * i;
|
||||
y := Exp(-x) * Sin(c * x);
|
||||
n := Round(s * y) + h;
|
||||
SwitchColor();
|
||||
repeat
|
||||
Write(' ');
|
||||
Dec(n);
|
||||
until n = 0;
|
||||
WriteLn('*');
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,24 @@
|
||||
program GetIPAddr;
|
||||
|
||||
uses
|
||||
KolibriOS, Network;
|
||||
|
||||
var
|
||||
AddrInfo: PAddrInfo;
|
||||
InputStr: string;
|
||||
|
||||
begin
|
||||
Network_initialization;
|
||||
|
||||
while True do
|
||||
begin
|
||||
Write('Input host:'); ReadLn(InputStr);
|
||||
if getaddrinfo(InputStr, nil, nil, AddrInfo) = 0{success} then
|
||||
WriteLn(PString(inet_ntoa(AddrInfo^.ai_addr^.sin_addr))^)
|
||||
else
|
||||
WriteLn('Error!');
|
||||
freeaddrinfo(AddrInfo);
|
||||
Write('Continue?[Y/N]:'); ReadLn(InputStr);
|
||||
if UpCase(InputStr[1]) = 'N' then Exit;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,49 @@
|
||||
program INI_File_Read;
|
||||
|
||||
uses
|
||||
LibINI;
|
||||
|
||||
procedure IniKeyCallback(FileName, SectionName, KeyName, KeyValue: PAnsiChar) stdcall;
|
||||
begin
|
||||
Write(' ', PString(KeyName)^);
|
||||
Write(' = ');
|
||||
WriteLn(PString(KeyValue)^);
|
||||
end;
|
||||
|
||||
procedure IniSectionCallback(FileName, SectionName: PAnsiChar) stdcall;
|
||||
begin
|
||||
WriteLn(PString(SectionName)^);
|
||||
ini_enum_keys(FileName, SectionName, @IniKeyCallback);
|
||||
end;
|
||||
|
||||
const
|
||||
FILE_PATH = '/sys/settings/system.ini';
|
||||
|
||||
var
|
||||
SystemLang: array [0..255] of AnsiChar;
|
||||
MouseSpeed: Integer;
|
||||
|
||||
begin
|
||||
LibINI_initialization;
|
||||
|
||||
WriteLn('Hello, this is a test for LibINI!');
|
||||
WriteLn;
|
||||
ini_enum_sections(FILE_PATH, @IniSectionCallback);
|
||||
WriteLn;
|
||||
|
||||
WriteLn('Try to get system.language and mouse.speed:');
|
||||
|
||||
if ini_get_str(FILE_PATH, 'system', 'language', SystemLang, SizeOf(SystemLang), 'ru') = 0 then
|
||||
WriteLn('Lang = "', SystemLang, '"')
|
||||
else
|
||||
WriteLn('Lang not found, used default "', SystemLang , '"');
|
||||
|
||||
MouseSpeed := ini_get_int(FILE_PATH, 'mouse', 'speed', -1);
|
||||
if MouseSpeed <> -1 then
|
||||
WriteLn('MouseSpeed = "', MouseSpeed, '"')
|
||||
else
|
||||
begin
|
||||
MouseSpeed := 5;
|
||||
WriteLn('MouseSpeed not found, used default "', MouseSpeed , '"');
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,22 @@
|
||||
program Just_Window;
|
||||
|
||||
uses
|
||||
KolibriOS;
|
||||
|
||||
begin
|
||||
while True do
|
||||
case WaitEvent of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(300, 200, 350, 250, 'Hello from XDPascal!', $00D5E3F1,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
Exit;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,38 @@
|
||||
#SHS
|
||||
rm ClrEOL_CRT.kex
|
||||
rm CmdLineArgs.kex
|
||||
rm Draw_Scaled_PNG_Image.kex
|
||||
rm EnterNumber.kex
|
||||
rm ExpSinGraph_CRT.kex
|
||||
rm factor.kex
|
||||
rm GetIPAddr.kex
|
||||
rm hello.kex
|
||||
rm INI_file_Read.kex
|
||||
rm Just_Window.kex
|
||||
rm Mouse_Test.kex
|
||||
rm Pyramid_TinyGL.kex
|
||||
rm raytracer.kex
|
||||
rm Select_Color_in_ColorDialog.kex
|
||||
rm Select_File_in_OpenDialog.kex
|
||||
rm Sierpinski.kex
|
||||
rm sort.kex
|
||||
rm SpiralMat.kex
|
||||
../xdpk.kex ClrEOL_CRT.pas
|
||||
../xdpk.kex CmdLineArgs.pas
|
||||
../xdpk.kex Draw_Scaled_PNG_Image.pas
|
||||
../xdpk.kex EnterNumber.pas
|
||||
../xdpk.kex ExpSinGraph_CRT.pas
|
||||
../xdpk.kex factor.pas
|
||||
../xdpk.kex GetIPAddr.pas
|
||||
../xdpk.kex hello.pas
|
||||
../xdpk.kex INI_file_Read.pas
|
||||
../xdpk.kex Just_Window.pas
|
||||
../xdpk.kex Mouse_Test.pas
|
||||
../xdpk.kex Pyramid_TinyGL.pas
|
||||
../xdpk.kex raytracer.pas
|
||||
../xdpk.kex Select_Color_in_ColorDialog.pas
|
||||
../xdpk.kex Select_File_in_OpenDialog.pas
|
||||
../xdpk.kex Sierpinski.pas
|
||||
../xdpk.kex sort.pas
|
||||
../xdpk.kex SpiralMat.pas
|
||||
exit
|
||||
@@ -0,0 +1,74 @@
|
||||
program Mouse_Test;
|
||||
|
||||
uses
|
||||
KolibriOS;
|
||||
|
||||
const
|
||||
MY_BUTTON = 1000;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: Integer;
|
||||
|
||||
TxtClickResult: string = 'Yet not clicked.';
|
||||
|
||||
procedure On_Redraw;
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(300, 200, 350, 250, 'Mouse test.', $00D5E3F1,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
DrawButton(10, 20, 50, 30, $0075D3F1, 0, MY_BUTTON);
|
||||
DrawText(20, 55, 'Click on window', $00AF4F3F, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING, 0);
|
||||
DrawText(20, 70, 'or click on button', $003F4FAF, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING, 0);
|
||||
DrawText(15, 90, TxtClickResult, $001F7F1F, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL, Length(TxtClickResult));
|
||||
EndDraw;
|
||||
end;
|
||||
|
||||
begin
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 2;
|
||||
WndHeight := Height div 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
SetEventMask(EM_REDRAW + EM_BUTTON + EM_KEY + EM_MOUSE);
|
||||
|
||||
while True do
|
||||
case WaitEvent of
|
||||
REDRAW_EVENT:
|
||||
On_Redraw;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
MOUSE_EVENT:
|
||||
begin
|
||||
case GetMouseButtons of
|
||||
1: if GetWindowMousePos.X > 100 then
|
||||
TxtClickResult := 'Left mouse button down(X > 100).'
|
||||
else
|
||||
TxtClickResult := 'Left mouse button down(X <= 100).';
|
||||
2: TxtClickResult := 'Right mouse button down.';
|
||||
4: TxtClickResult := 'Middle mouse button down.';
|
||||
end;
|
||||
On_Redraw;
|
||||
end;
|
||||
BUTTON_EVENT:
|
||||
with GetButton do
|
||||
case ID of
|
||||
1: Exit;
|
||||
MY_BUTTON:
|
||||
begin
|
||||
case MouseButton of
|
||||
0: TxtClickResult := 'Button clicked by left mouse button.';
|
||||
2: TxtClickResult := 'Button clicked by right mouse button.';
|
||||
4: TxtClickResult := 'Button clicked by middle mouse button.';
|
||||
end;
|
||||
On_Redraw;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,104 @@
|
||||
program Pyramid_TinyGL;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
var
|
||||
CTX: TKOSGLContext;
|
||||
Angle: GLFloat = 0;
|
||||
Speed: GLFloat = 3.5;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: Integer;
|
||||
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit; // otherwise app crashes
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort (0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.11, 0.22, 0.66, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glLoadIdentity();
|
||||
glTranslatef(0, 0, -5);
|
||||
|
||||
glRotatef(Angle, 0.25, 0.75, 0.75);
|
||||
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glColor3f(1, 0, 0); glVertex3f(0, 0.75, 0);
|
||||
glColor3f(1, 1, 0); glVertex3f(-0.75, -0.75, 0.75);
|
||||
glColor3f(1, 1, 1); glVertex3f(0.75, -0.75, 0.75);
|
||||
glColor3f(0, 1, 1); glVertex3f(0.75, -0.75, -0.75);
|
||||
glColor3f(0, 0, 1); glVertex3f(-0.75, -0.75, -0.75);
|
||||
glColor3f(0, 1, 0); glVertex3f(-0.75, -0.75, 0.75);
|
||||
glEnd();
|
||||
|
||||
Angle := Angle + Speed;
|
||||
if Angle > 360 then Angle := 0;
|
||||
|
||||
kosglSwapBuffers();
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Pyramid TinyGL', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_TRANSPARENT_FILL + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
Exit;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,61 @@
|
||||
program Select_Color_in_ColorDialog;
|
||||
|
||||
uses
|
||||
KolibriOS, ColorDlg;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: Integer;
|
||||
TextColor: Integer = $00707070;
|
||||
ColorDialog: TColorDialog;
|
||||
|
||||
procedure On_Redraw;
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Test ColorDialog, press key to select text color', $00FAFBFC,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
DrawText(2, 75, 'press key to select text color', TextColor, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING + DT_X2, 0);
|
||||
EndDraw;
|
||||
end;
|
||||
|
||||
begin
|
||||
ColorDlg_initialization;
|
||||
|
||||
with ColorDialog do
|
||||
begin
|
||||
Mode := CDM_PALETTE_TONE;
|
||||
DrawWindow := @On_Redraw;
|
||||
XSize := 510;
|
||||
YSize := 310;
|
||||
ColorType := CDCT_RGB;
|
||||
end;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := 600;
|
||||
WndHeight := Height div 3;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
ColorDialog.Init();
|
||||
|
||||
while True do
|
||||
case WaitEvent of
|
||||
REDRAW_EVENT:
|
||||
On_Redraw;
|
||||
KEY_EVENT:
|
||||
begin
|
||||
GetKey;
|
||||
ColorDialog.Start();
|
||||
with ColorDialog do
|
||||
if Status = CDS_OK then
|
||||
begin
|
||||
TextColor := Color;
|
||||
On_Redraw;
|
||||
end;
|
||||
end;
|
||||
BUTTON_EVENT:
|
||||
Exit;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,90 @@
|
||||
program Select_File_in_OpenDialog;
|
||||
|
||||
uses
|
||||
KolibriOS, OpenDlg;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: Integer;
|
||||
OpenDialog: TOpenDialog;
|
||||
TxtSelectResult: string = 'Yet not selected.';
|
||||
|
||||
procedure On_Redraw;
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Select File in OpenDialog', $00FFFFFF,
|
||||
WS_SKINNED_FIXED + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
DrawText(2, 75, 'press key ENTER to select file', $00AF4F3F, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING, 0);
|
||||
DrawText(2, 90, 'press key SPACE to select dir', $003F4FAF, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING, 0);
|
||||
DrawText(15, 110, TxtSelectResult, $001F7F1F, 0,
|
||||
DT_CP866_8X16 + DT_TRANSPARENT_FILL, Length(TxtSelectResult));
|
||||
EndDraw;
|
||||
end;
|
||||
|
||||
procedure BrowseFile;
|
||||
begin
|
||||
with OpenDialog do
|
||||
begin
|
||||
Mode := ODM_OPEN;
|
||||
Start();
|
||||
if Status = ODS_OK then
|
||||
begin
|
||||
TxtSelectResult := 'File = "' + PString(OpenFilePath)^ + '"';
|
||||
On_Redraw;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure BrowseDir;
|
||||
begin
|
||||
with OpenDialog do
|
||||
begin
|
||||
Mode := ODM_DIR;
|
||||
Start();
|
||||
if Status = ODS_OK then
|
||||
begin
|
||||
TxtSelectResult := 'Dir = "' + PString(OpenFilePath)^ + '"';
|
||||
On_Redraw;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
OpenDlg_initialization;
|
||||
|
||||
with OpenDialog do
|
||||
begin
|
||||
DirDefaultPath := '/sys';
|
||||
DrawWindow := @On_Redraw;
|
||||
XSize := 400;
|
||||
YSize := 480;
|
||||
end;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 4;
|
||||
WndHeight := Height div 4;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
OpenDialog.Init();
|
||||
OpenDialog.SetFilter('txt,png,dat,ini,inf,sys,asm,htm');
|
||||
|
||||
while True do
|
||||
case WaitEvent of
|
||||
REDRAW_EVENT:
|
||||
On_Redraw;
|
||||
KEY_EVENT:
|
||||
case GetKey.Code of
|
||||
#13{ENTER}: BrowseFile;
|
||||
#32{SPACE}: BrowseDir;
|
||||
else
|
||||
// nothing to do
|
||||
end;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
Exit;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,70 @@
|
||||
{ see original code here http://rosettacode.org/wiki/Sierpinski_triangle#Pascal }
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Sierpinski;
|
||||
|
||||
function ipow(b, n: Integer): Integer;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result := 1;
|
||||
for i := 1 to n do
|
||||
Result := Result * b
|
||||
end;
|
||||
|
||||
function Truth(a: Char): Boolean;
|
||||
begin
|
||||
if a = '*' then
|
||||
Truth := True
|
||||
else
|
||||
Truth := False
|
||||
end;
|
||||
|
||||
function Rule_90(ev: string): string;
|
||||
var
|
||||
l, i: Integer;
|
||||
cp: string;
|
||||
s: array[0..1] of Boolean;
|
||||
begin
|
||||
l := Length(ev);
|
||||
cp := Copy(ev, 1, l);
|
||||
for i := 1 to l do
|
||||
begin
|
||||
if (i-1) < 1 then
|
||||
s[0] := False
|
||||
else
|
||||
s[0] := Truth(ev[i - 1]);
|
||||
if (i+1) > l then
|
||||
s[1] := False
|
||||
else
|
||||
s[1] := Truth(ev[i + 1]);
|
||||
if (s[0] and not s[1]) or (s[1] and not s[0]) then
|
||||
cp[i] := '*'
|
||||
else
|
||||
cp[i] := ' ';
|
||||
end;
|
||||
rule_90 := cp
|
||||
end;
|
||||
|
||||
procedure Triangle(N: Integer);
|
||||
var
|
||||
i, l : Integer;
|
||||
b : string;
|
||||
begin
|
||||
l := ipow(2, n + 1);
|
||||
b := ' ';
|
||||
for i := 1 to l do
|
||||
b := b + ' ';
|
||||
b[Round(l / 2)] := '*';
|
||||
WriteLn(b);
|
||||
for i := 1 to (Round(l / 2) - 1) do
|
||||
begin
|
||||
b := Rule_90(b);
|
||||
WriteLn(b)
|
||||
end
|
||||
end;
|
||||
|
||||
begin
|
||||
Triangle(4)
|
||||
end.
|
||||
@@ -0,0 +1,79 @@
|
||||
{ see original code here http://rosettacode.org/wiki/Spiral_matrix#Pascal }
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Spiralmat;
|
||||
|
||||
type
|
||||
TDir = (Left, Down, Right, Up);
|
||||
|
||||
TDXY = record
|
||||
DX, DY: LongInt;
|
||||
end;
|
||||
|
||||
TDeltaDir = array[TDir] of TDXY;
|
||||
|
||||
const
|
||||
Nextdir: array[TDir] of TDir = (Down, Right, Up, Left);
|
||||
cDir: TDeltaDir = ((dx: 1; dy: 0), (dx: 0; dy: 1), (dx: -1; dy: 0), (dx: 0; dy: -1));
|
||||
cMaxN = 32;
|
||||
|
||||
type
|
||||
TSpiral = array[0..cMaxN, 0..cMaxN] of LongInt;
|
||||
|
||||
function FillSpiral(n: LongInt): TSpiral;
|
||||
var
|
||||
b, i, k, dn, x, y : LongInt;
|
||||
dir: TDir;
|
||||
tmpSp: TSpiral;
|
||||
begin
|
||||
b := 0;
|
||||
x := 0;
|
||||
y := 0;
|
||||
//only for the first line
|
||||
k := -1;
|
||||
dn := n - 1;
|
||||
tmpSp[x, y] := b;
|
||||
dir := left;
|
||||
repeat
|
||||
i := 0;
|
||||
while i < dn do
|
||||
begin
|
||||
inc(b);
|
||||
tmpSp[x,y] := b;
|
||||
x := x + cDir[dir].dx;
|
||||
y := y + cDir[dir].dy;
|
||||
Inc(i);
|
||||
end;
|
||||
Dir := NextDir[dir];
|
||||
Inc(k);
|
||||
if k > 1 then
|
||||
begin
|
||||
k := 0;
|
||||
//shorten the line every second direction change
|
||||
dn := dn-1;
|
||||
if dn <= 0 then
|
||||
Break;
|
||||
end;
|
||||
until false;
|
||||
//the last
|
||||
tmpSp[x, y] := b + 1;
|
||||
FillSpiral := tmpSp;
|
||||
end;
|
||||
|
||||
var
|
||||
a: TSpiral;
|
||||
x, y, n: LongInt;
|
||||
begin
|
||||
for n := 1 to 5 do
|
||||
begin
|
||||
A := FillSpiral(n);
|
||||
for y := 0 to n - 1 do
|
||||
begin
|
||||
for x := 0 to n - 1 do
|
||||
Write(A[x, y]:4);
|
||||
WriteLn;
|
||||
end;
|
||||
WriteLn;
|
||||
end;
|
||||
end.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,63 @@
|
||||
// Factorization demo
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Factor;
|
||||
|
||||
|
||||
|
||||
var
|
||||
LowBound, HighBound, Number, Dividend, Divisor: Integer;
|
||||
DivisorFound: Boolean;
|
||||
|
||||
|
||||
|
||||
begin
|
||||
WriteLn;
|
||||
WriteLn('Integer factorization demo');
|
||||
WriteLn;
|
||||
Write('From number: '); ReadLn(LowBound);
|
||||
Write('To number : '); ReadLn(HighBound);
|
||||
WriteLn;
|
||||
|
||||
if LowBound < 2 then
|
||||
begin
|
||||
WriteLn('Numbers should be greater than 1');
|
||||
ReadLn;
|
||||
Halt(1);
|
||||
end;
|
||||
|
||||
for Number := LowBound to HighBound do
|
||||
begin
|
||||
Write(Number, ' = ');
|
||||
|
||||
Dividend := Number;
|
||||
while Dividend > 1 do
|
||||
begin
|
||||
Divisor := 1;
|
||||
DivisorFound := FALSE;
|
||||
|
||||
while sqr(Divisor) <= Dividend do
|
||||
begin
|
||||
Inc(Divisor);
|
||||
if Dividend mod Divisor = 0 then
|
||||
begin
|
||||
DivisorFound := TRUE;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
|
||||
if not DivisorFound then Divisor := Dividend; // Prime number
|
||||
|
||||
Write(Divisor, ' ');
|
||||
Dividend := Dividend div Divisor;
|
||||
end; // while
|
||||
|
||||
WriteLn;
|
||||
end; // for
|
||||
|
||||
WriteLn;
|
||||
WriteLn('Done.');
|
||||
|
||||
ReadLn;
|
||||
end.
|
||||
@@ -0,0 +1,7 @@
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Hello;
|
||||
|
||||
begin
|
||||
WriteLn('Hello, World!');
|
||||
end.
|
||||
@@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
|
||||
if exist bin rmdir /s /q bin
|
||||
mkdir bin
|
||||
|
||||
For /R %%i In (*.pas) Do (
|
||||
..\xdpk "%%i"
|
||||
)
|
||||
|
||||
:: Переносим все скомпилированные файлы .kex из подпапок в общую папку bin
|
||||
move /y *.kex bin\
|
||||
:: Если они сохраняются прямо рядом с исходниками в тех же папках, то лучше так:
|
||||
:: For /R %%i In (*.kex) Do move /y "%%i" bin\
|
||||
|
||||
pause
|
||||
@@ -0,0 +1,440 @@
|
||||
// Raytracer demo - demonstrates XD Pascal methods and interfaces
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Raytracer;
|
||||
|
||||
|
||||
type
|
||||
TVec = array [1..3] of Real;
|
||||
|
||||
|
||||
function add for u: TVec (var v: TVec): TVec;
|
||||
var i: Integer;
|
||||
begin
|
||||
for i := 1 to 3 do Result[i] := u[i] + v[i];
|
||||
end;
|
||||
|
||||
|
||||
function sub for u: TVec (var v: TVec): TVec;
|
||||
var i: Integer;
|
||||
begin
|
||||
for i := 1 to 3 do Result[i] := u[i] - v[i];
|
||||
end;
|
||||
|
||||
|
||||
function mul for v: TVec (a: Real): TVec;
|
||||
var i: Integer;
|
||||
begin
|
||||
for i := 1 to 3 do Result[i] := a * v[i];
|
||||
end;
|
||||
|
||||
|
||||
function dot for u: TVec (var v: TVec): Real;
|
||||
var i: Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
for i := 1 to 3 do Result := Result + u[i] * v[i];
|
||||
end;
|
||||
|
||||
|
||||
function elementwise for u: TVec (var v: TVec): TVec;
|
||||
var i: Integer;
|
||||
begin
|
||||
for i := 1 to 3 do Result[i] := u[i] * v[i];
|
||||
end;
|
||||
|
||||
|
||||
function norm(var v: TVec): Real;
|
||||
begin
|
||||
Result := sqrt(v.dot(v));
|
||||
end;
|
||||
|
||||
|
||||
function normalize(var v: TVec): TVec;
|
||||
begin
|
||||
Result := v.mul(1.0 / norm(v));
|
||||
end;
|
||||
|
||||
|
||||
function rand: TVec;
|
||||
var i: Integer;
|
||||
begin
|
||||
for i := 1 to 3 do Result[i] := Random - 0.5;
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
TColor = TVec;
|
||||
|
||||
TRay = record
|
||||
Origin, Dir: TVec;
|
||||
end;
|
||||
|
||||
TGenericBody = record
|
||||
Center: TVec;
|
||||
Color: TColor;
|
||||
Diffuseness: Real;
|
||||
IsLamp: Boolean;
|
||||
end;
|
||||
|
||||
PGenericBody = ^TGenericBody;
|
||||
|
||||
|
||||
function LambertFactor for b: TGenericBody (Lambert: Real): Real;
|
||||
begin
|
||||
Result := 1.0 - (1.0 - Lambert) * b.Diffuseness;
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
TBox = record
|
||||
GenericBody: TGenericBody;
|
||||
HalfSize: TVec;
|
||||
end;
|
||||
|
||||
|
||||
function GetGenericBody for b: TBox: PGenericBody;
|
||||
begin
|
||||
Result := @b.GenericBody;
|
||||
end;
|
||||
|
||||
|
||||
function Intersect for b: TBox (var Ray: TRay; var Point, Normal: TVec): Boolean;
|
||||
|
||||
function IntersectFace(i, j, k: Integer): Boolean;
|
||||
|
||||
function Within(x, y, xmin, ymin, xmax, ymax: Real): Boolean;
|
||||
begin
|
||||
Result := (x > xmin) and (x < xmax) and (y > ymin) and (y < ymax);
|
||||
end;
|
||||
|
||||
var
|
||||
Side, Factor: Real;
|
||||
|
||||
begin // IntersectFace
|
||||
Result := FALSE;
|
||||
|
||||
if abs(Ray.Dir[k]) > 1e-9 then
|
||||
begin
|
||||
Side := 1.0;
|
||||
if Ray.Dir[k] > 0.0 then Side := -1.0;
|
||||
|
||||
Factor := (b.GenericBody.Center[k] + Side * b.HalfSize[k] - Ray.Origin[k]) / Ray.Dir[k];
|
||||
if Factor > 0.1 then
|
||||
begin
|
||||
Point := Ray.Origin.add(Ray.Dir.mul(Factor));
|
||||
|
||||
if Within(Point[i], Point[j],
|
||||
b.GenericBody.Center[i] - b.HalfSize[i], b.GenericBody.Center[j] - b.HalfSize[j],
|
||||
b.GenericBody.Center[i] + b.HalfSize[i], b.GenericBody.Center[j] + b.HalfSize[j])
|
||||
then
|
||||
begin
|
||||
Normal[i] := 0; Normal[j] := 0; Normal[k] := Side;
|
||||
Result := TRUE;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin // Intersect
|
||||
Result := IntersectFace(1, 2, 3) or IntersectFace(3, 1, 2) or IntersectFace(2, 3, 1);
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
TSphere = record
|
||||
GenericBody: TGenericBody;
|
||||
Radius: Real;
|
||||
end;
|
||||
|
||||
|
||||
function GetGenericBody for s: TSphere: PGenericBody;
|
||||
begin
|
||||
Result := @s.GenericBody;
|
||||
end;
|
||||
|
||||
|
||||
function Intersect for s: TSphere (var Ray: TRay; var Point, Normal: TVec): Boolean;
|
||||
var
|
||||
Displacement: TVec;
|
||||
Proj, Discr, Factor: Real;
|
||||
begin
|
||||
Displacement := s.GenericBody.Center.sub(Ray.Origin);
|
||||
Proj := Displacement.dot(Ray.Dir);
|
||||
Discr := sqr(s.Radius) + sqr(Proj) - Displacement.dot(Displacement);
|
||||
|
||||
if Discr > 0 then
|
||||
begin
|
||||
Factor := Proj - sqrt(Discr);
|
||||
if Factor > 0.1 then
|
||||
begin
|
||||
Point := Ray.Origin.add(Ray.Dir.mul(Factor));
|
||||
Normal := Point.sub(s.GenericBody.Center).mul(1.0 / s.Radius);
|
||||
Result := TRUE;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result := FALSE;
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
IBody = interface
|
||||
GetGenericBody: function: PGenericBody;
|
||||
Intersect: function (var Ray: TRay; var Point, Normal: TVec): Boolean;
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
MAXBODIES = 10;
|
||||
|
||||
|
||||
type
|
||||
TScene = record
|
||||
AmbientColor: TColor;
|
||||
Body: array [1..MAXBODIES] of IBody;
|
||||
NumBodies: Integer;
|
||||
end;
|
||||
|
||||
|
||||
function Trace for sc: TScene (var Ray: TRay; Depth: Integer): TColor;
|
||||
var
|
||||
BestBody: PGenericBody;
|
||||
Point, Normal, BestPoint, BestNormal, SpecularDir, DiffuseDir: TVec;
|
||||
DiffuseRay: TRay;
|
||||
Dist, BestDist, Lambert: Real;
|
||||
BestIndex, i: Integer;
|
||||
|
||||
begin
|
||||
if Depth > 3 then
|
||||
begin
|
||||
Result := sc.AmbientColor;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// Find nearest intersection
|
||||
BestDist := 1e9;
|
||||
BestIndex := 0;
|
||||
|
||||
for i := 1 to sc.NumBodies do
|
||||
begin
|
||||
if sc.Body[i].Intersect(Ray, Point, Normal) then
|
||||
begin
|
||||
Dist := norm(Point.sub(Ray.Origin));
|
||||
if Dist < BestDist then
|
||||
begin
|
||||
BestDist := Dist;
|
||||
BestIndex := i;
|
||||
BestPoint := Point;
|
||||
BestNormal := Normal;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Reflect rays
|
||||
if BestIndex > 0 then
|
||||
begin
|
||||
BestBody := sc.Body[BestIndex].GetGenericBody();
|
||||
|
||||
if BestBody^.IsLamp then
|
||||
begin
|
||||
Result := BestBody^.Color;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
SpecularDir := Ray.Dir.sub(BestNormal.mul(2.0 * (Ray.Dir.dot(BestNormal))));
|
||||
DiffuseDir := normalize(SpecularDir.add(rand.mul(2.0 * BestBody^.Diffuseness)));
|
||||
|
||||
Lambert := DiffuseDir.dot(BestNormal);
|
||||
if Lambert < 0 then
|
||||
begin
|
||||
DiffuseDir := DiffuseDir.sub(BestNormal.mul(2.0 * Lambert));
|
||||
Lambert := -Lambert;
|
||||
end;
|
||||
|
||||
DiffuseRay.Origin := BestPoint;
|
||||
DiffuseRay.Dir := DiffuseDir;
|
||||
|
||||
with BestBody^ do
|
||||
Result := sc.Trace(DiffuseRay, Depth + 1).mul(LambertFactor(Lambert)).elementwise(Color);
|
||||
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Result := sc.AmbientColor;
|
||||
end;
|
||||
|
||||
|
||||
// Main program
|
||||
|
||||
const
|
||||
// Define scene
|
||||
Box1: TBox =
|
||||
(
|
||||
GenericBody:
|
||||
(
|
||||
Center: (500, -100, 1200);
|
||||
Color: (0.4, 0.7, 1.0);
|
||||
Diffuseness: 0.1;
|
||||
IsLamp: FALSE
|
||||
);
|
||||
HalfSize: (400 / 2, 600 / 2, 300 / 2)
|
||||
);
|
||||
|
||||
Box2: TBox =
|
||||
(
|
||||
GenericBody:
|
||||
(
|
||||
Center: (550, 210, 1100);
|
||||
Color: (0.9, 1.0, 0.6);
|
||||
Diffuseness: 0.3;
|
||||
IsLamp: FALSE
|
||||
);
|
||||
HalfSize: (1000 / 2, 20 / 2, 1000 / 2)
|
||||
);
|
||||
|
||||
Sphere1: TSphere =
|
||||
(
|
||||
GenericBody:
|
||||
(
|
||||
Center: (600, 0, 700);
|
||||
Color: (1.0, 0.4, 0.6);
|
||||
Diffuseness: 0.2;
|
||||
IsLamp: FALSE
|
||||
);
|
||||
Radius: 200
|
||||
);
|
||||
|
||||
Sphere2: TSphere =
|
||||
(
|
||||
GenericBody:
|
||||
(
|
||||
Center: (330, 150, 700);
|
||||
Color: (1.0, 1.0, 0.3);
|
||||
Diffuseness: 0.15;
|
||||
IsLamp: FALSE
|
||||
);
|
||||
Radius: 50
|
||||
);
|
||||
|
||||
// Define light
|
||||
Lamp1: TSphere =
|
||||
(
|
||||
GenericBody:
|
||||
(
|
||||
Center: (500, -1000, -700);
|
||||
Color: (1.0, 1.0, 1.0);
|
||||
Diffuseness: 1.0;
|
||||
IsLamp: TRUE
|
||||
);
|
||||
Radius: 800
|
||||
);
|
||||
|
||||
AmbientLightColor: TColor = (0.2, 0.2, 0.2);
|
||||
|
||||
|
||||
// Define eye
|
||||
Pos: TVec = (0, 0, 0);
|
||||
Azimuth = 30.0 * pi / 180.0;
|
||||
Width = 640;
|
||||
Height = 480;
|
||||
Focal = 500;
|
||||
Antialiasing = 1.0;
|
||||
|
||||
|
||||
// Output file
|
||||
FileName = 'scene.ppm';
|
||||
|
||||
|
||||
var
|
||||
Scene: TScene;
|
||||
Dir, RotDir, RandomDir: TVec;
|
||||
Color: TColor;
|
||||
Ray: TRay;
|
||||
sinAz, cosAz: Real;
|
||||
F: Text;
|
||||
Rays, i, j, r: Integer;
|
||||
StartTime, StopTime: LongInt;
|
||||
|
||||
Buf: array [0..Width * Height * 3 - 1] of Byte;
|
||||
BufPos: LongInt = 0;
|
||||
|
||||
|
||||
begin
|
||||
WriteLn('Raytracer demo');
|
||||
WriteLn;
|
||||
Write('Rays per pixel (recommended 1 to 100): '); ReadLn(Rays);
|
||||
WriteLn;
|
||||
|
||||
Randomize;
|
||||
|
||||
with Scene do
|
||||
begin
|
||||
AmbientColor := AmbientLightColor;
|
||||
Body[1] := Box1;
|
||||
Body[2] := Box2;
|
||||
Body[3] := Sphere1;
|
||||
Body[4] := Sphere2;
|
||||
Body[5] := Lamp1;
|
||||
NumBodies := 5;
|
||||
end;
|
||||
|
||||
sinAz := sin(Azimuth); cosAz := cos(Azimuth);
|
||||
|
||||
Assign(F, FileName);
|
||||
Rewrite(F);
|
||||
Write(F, 'P6 ');
|
||||
|
||||
Write(F, Width, ' ', Height, ' ');
|
||||
Write(F, 255, ' ');
|
||||
|
||||
StartTime := GetTickCount;
|
||||
|
||||
for i := 0 to Height - 1 do
|
||||
begin
|
||||
for j := 0 to Width - 1 do
|
||||
begin
|
||||
Color[1] := 0;
|
||||
Color[2] := 0;
|
||||
Color[3] := 0;
|
||||
|
||||
Dir[1] := j - Width / 2;
|
||||
Dir[2] := i - Height / 2;
|
||||
Dir[3] := Focal;
|
||||
|
||||
RotDir[1] := Dir[1] * cosAz + Dir[3] * sinAz;
|
||||
RotDir[2] := Dir[2];
|
||||
RotDir[3] := -Dir[1] * sinAz + Dir[3] * cosAz;
|
||||
|
||||
for r := 1 to Rays do
|
||||
begin
|
||||
RandomDir := RotDir.add(rand.mul(Antialiasing));
|
||||
Ray.Origin := Pos;
|
||||
Ray.Dir := normalize(RandomDir);
|
||||
Color := Color.add(Scene.Trace(Ray, 0));
|
||||
end;
|
||||
|
||||
Color := Color.mul(255.0 / Rays);
|
||||
|
||||
Buf[BufPos] := Round(Color[1]);
|
||||
Buf[BufPos + 1] := Round(Color[2]);
|
||||
Buf[BufPos + 2] := Round(Color[3]);
|
||||
BufPos := BufPos + 3;
|
||||
end;
|
||||
|
||||
WriteLn(i + 1, '/', Height);
|
||||
end;
|
||||
|
||||
BlockWrite(F, Buf, SizeOf(Buf));
|
||||
|
||||
StopTime := GetTickCount;
|
||||
|
||||
Close(F);
|
||||
|
||||
WriteLn;
|
||||
WriteLn('Rendering time: ', (StopTime - StartTime) / 1000 :5:1, ' s');
|
||||
WriteLn('Done. See ' + FileName);
|
||||
ReadLn;
|
||||
end.
|
||||
@@ -0,0 +1,243 @@
|
||||
// Sorting demo
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
program Sort;
|
||||
|
||||
|
||||
|
||||
type
|
||||
TValue = Integer;
|
||||
TCompareFunc = function(x, y: TValue): Boolean;
|
||||
|
||||
|
||||
|
||||
procedure Swap(var x, y: TValue);
|
||||
var
|
||||
buf: TValue;
|
||||
begin
|
||||
buf := x;
|
||||
x := y;
|
||||
y := buf;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure QuickSort(var data: array of TValue; len: Integer; Ordered: TCompareFunc);
|
||||
|
||||
|
||||
function Partition(var data: array of TValue; low, high: Integer; Ordered: TCompareFunc): Integer;
|
||||
var
|
||||
pivot: TValue;
|
||||
pivotIndex, i: Integer;
|
||||
begin
|
||||
pivot := data[high];
|
||||
pivotIndex := low;
|
||||
|
||||
for i := low to high - 1 do
|
||||
if not Ordered(data[i], pivot) then
|
||||
begin
|
||||
Swap(data[pivotIndex], data[i]);
|
||||
Inc(pivotIndex);
|
||||
end; // if
|
||||
|
||||
Swap(data[high], data[pivotIndex]);
|
||||
|
||||
Result := pivotIndex;
|
||||
end;
|
||||
|
||||
|
||||
procedure Sort(var data: array of TValue; low, high: Integer; Ordered: TCompareFunc);
|
||||
var
|
||||
pivotIndex: Integer;
|
||||
begin
|
||||
if high > low then
|
||||
begin
|
||||
pivotIndex := Partition(data, low, high, Ordered);
|
||||
|
||||
Sort(data, low, pivotIndex - 1, Ordered);
|
||||
Sort(data, pivotIndex + 1, high, Ordered);
|
||||
end; // if
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
Sort(data, 0, len - 1, Ordered);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure BubbleSort(var data: array of TValue; len: Integer; Ordered: TCompareFunc);
|
||||
var
|
||||
changed: Boolean;
|
||||
i: Integer;
|
||||
begin
|
||||
repeat
|
||||
changed := FALSE;
|
||||
|
||||
for i := 0 to len - 2 do
|
||||
if not Ordered(data[i + 1], data[i]) then
|
||||
begin
|
||||
Swap(data[i + 1], data[i]);
|
||||
changed := TRUE;
|
||||
end;
|
||||
|
||||
until not changed;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure SelectionSort(var data: array of TValue; len: Integer; Ordered: TCompareFunc);
|
||||
var
|
||||
i, j, extrIndex: Integer;
|
||||
extr: TValue;
|
||||
begin
|
||||
for i := 0 to len - 1 do
|
||||
begin
|
||||
extr := data[i];
|
||||
extrIndex := i;
|
||||
|
||||
for j := i + 1 to len - 1 do
|
||||
if not Ordered(data[j], extr) then
|
||||
begin
|
||||
extr := data[j];
|
||||
extrIndex := j;
|
||||
end;
|
||||
|
||||
Swap(data[i], data[extrIndex]);
|
||||
end; // for
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function Sorted(var data: array of TValue; len: Integer; Ordered: TCompareFunc): Boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result := TRUE;
|
||||
for i := 0 to len - 2 do
|
||||
if not Ordered(data[i + 1], data[i]) then
|
||||
begin
|
||||
Result := FALSE;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function OrderedAscending(y, x: TValue): Boolean;
|
||||
begin
|
||||
Result := y >= x;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function OrderedDescending(y, x: TValue): Boolean;
|
||||
begin
|
||||
Result := y <= x;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
const
|
||||
DataLength = 600;
|
||||
|
||||
|
||||
|
||||
var
|
||||
RandomData: array [1..DataLength] of TValue;
|
||||
i: Integer;
|
||||
Ordered: TCompareFunc;
|
||||
Order, Method: Char;
|
||||
|
||||
|
||||
|
||||
begin
|
||||
WriteLn;
|
||||
WriteLn('Sorting demo');
|
||||
WriteLn;
|
||||
WriteLn('Initial array: ');
|
||||
WriteLn;
|
||||
|
||||
Randomize;
|
||||
|
||||
for i := 1 to DataLength do
|
||||
begin
|
||||
RandomData[i] := Round((Random - 0.5) * 1000000);
|
||||
Write(RandomData[i]: 8);
|
||||
if i mod 6 = 0 then WriteLn;
|
||||
end;
|
||||
|
||||
WriteLn;
|
||||
WriteLn;
|
||||
Write('Select order (A - ascending, D - descending): '); ReadLn(Order);
|
||||
WriteLn;
|
||||
|
||||
case Order of
|
||||
'A', 'a':
|
||||
begin
|
||||
WriteLn('Ascending order');
|
||||
Ordered := @OrderedAscending;
|
||||
end;
|
||||
'D', 'd':
|
||||
begin
|
||||
WriteLn('Descending order');
|
||||
Ordered := @OrderedDescending;
|
||||
end
|
||||
else
|
||||
WriteLn('Order is not selected.');
|
||||
Ordered := nil;
|
||||
ReadLn;
|
||||
Halt;
|
||||
end;
|
||||
|
||||
WriteLn;
|
||||
Write('Select method (Q - quick, B - bubble, S - selection): '); ReadLn(Method);
|
||||
WriteLn;
|
||||
|
||||
case Method of
|
||||
'Q', 'q':
|
||||
begin
|
||||
WriteLn('Quick sorting');
|
||||
QuickSort(RandomData, DataLength, Ordered);
|
||||
end;
|
||||
'B', 'b':
|
||||
begin
|
||||
WriteLn('Bubble sorting');
|
||||
BubbleSort(RandomData, DataLength, Ordered);
|
||||
end;
|
||||
'S', 's':
|
||||
begin
|
||||
WriteLn('Selection sorting');
|
||||
SelectionSort(RandomData, DataLength, Ordered);
|
||||
end
|
||||
else
|
||||
WriteLn('Sorting method is not selected.');
|
||||
ReadLn;
|
||||
Halt;
|
||||
end;
|
||||
|
||||
WriteLn;
|
||||
WriteLn('Sorted array: ');
|
||||
WriteLn;
|
||||
|
||||
for i := 1 to DataLength do
|
||||
begin
|
||||
Write(RandomData[i]: 8);
|
||||
if i mod 6 = 0 then WriteLn;
|
||||
end;
|
||||
WriteLn;
|
||||
|
||||
WriteLn('Sorted: ', Sorted(RandomData, DataLength, Ordered));
|
||||
WriteLn('Done.');
|
||||
|
||||
ReadLn;
|
||||
end.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
program TorusDemo;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
MAX_VERTICES = 20000;
|
||||
MAX_FACES = 20000;
|
||||
|
||||
type
|
||||
TVertex = record
|
||||
x, y, z: Single;
|
||||
r, g, b: Byte;
|
||||
end;
|
||||
|
||||
TFace = record
|
||||
v1, v2, v3, v4: TVertex;
|
||||
avgZ: Single;
|
||||
colorR, colorG, colorB: Byte;
|
||||
end;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
MainRadius, BaseTubeRadius: Single;
|
||||
TorusSegments, TubeSegments, WaveCount: Integer;
|
||||
|
||||
ProjectedVertices: array[0..MAX_VERTICES - 1] of TVertex;
|
||||
Faces: array[0..MAX_FACES - 1] of TFace;
|
||||
TotalVerticesCount, TotalFacesCount: Integer;
|
||||
|
||||
AngleX: Single = 0.6;
|
||||
AngleY: Single = 0.5;
|
||||
TimeColor: Single = 0.0;
|
||||
TimeScale: Single = 0.0;
|
||||
|
||||
// яЁюЎхфєЁр яхЁёяхъЄштэющ ьрЄЁшЎ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
function Min(A, B: Extended): Extended;
|
||||
begin
|
||||
if A < B then Result := A else Result := B;
|
||||
end;
|
||||
|
||||
function Max(A, B: Extended): Extended;
|
||||
begin
|
||||
if A > B then Result := A else Result := B;
|
||||
end;
|
||||
|
||||
function Power(Base, Exponent: Extended): Extended;
|
||||
begin
|
||||
Result := Exp(Exponent * Ln(Base));
|
||||
end;
|
||||
|
||||
procedure ResizeTopology(W, H: Integer);
|
||||
begin
|
||||
MainRadius := H / 4.85;
|
||||
BaseTubeRadius := MainRadius / 2.45;
|
||||
|
||||
TorusSegments := Round(H / 10);
|
||||
TubeSegments := Round(H / 15);
|
||||
WaveCount := Round(H / 100);
|
||||
|
||||
if TorusSegments < 16 then TorusSegments := 16;
|
||||
if TubeSegments < 8 then TubeSegments := 8;
|
||||
if WaveCount < 3 then WaveCount := 3;
|
||||
|
||||
TotalVerticesCount := (TorusSegments + 1) * (TubeSegments + 1);
|
||||
TotalFacesCount := TorusSegments * TubeSegments;
|
||||
|
||||
// ╟р∙шЄр юЄ яхЁхяюыэхэш ёЄрЄшўхёъюую сєЇхЁр
|
||||
if TotalVerticesCount > MAX_VERTICES then TotalVerticesCount := MAX_VERTICES;
|
||||
if TotalFacesCount > MAX_FACES then TotalFacesCount := MAX_FACES;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
I, J, Idx, Stride: Integer;
|
||||
U, V, Wave1, Wave2, CurrentTubeRadius, SpineWave: Single;
|
||||
CosU, SinU, CosV, SinV, CosX, SinX, CosY, SinY: Single;
|
||||
X, Y, Z, X1, Z1, Y2, Z2, Factor, Fov: Single;
|
||||
CamDist, CenterX, CenterY: Single;
|
||||
Idx1, Idx2, Idx3, Idx4: Integer;
|
||||
P1, P2, P3, P4: TVertex;
|
||||
AX, AY, AZ, BX, BY, BZ, NX, NY, NZ, Len: Single;
|
||||
RFinal, GFinal, BFinal: Single;
|
||||
ViewDot, Rim, CenterDarkness: Single;
|
||||
NormX, NormY, NormZ: Single;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if not (ThreadInfo.Client.Height > 3) then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(10/255, 10/255, 10/255, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// ╤ўшЄрхь °руш ёхЄъш
|
||||
ResizeTopology(ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
CamDist := 500.0;
|
||||
CenterX := ThreadInfo.Client.Width / 2.0;
|
||||
CenterY := ThreadInfo.Client.Height / 2.0;
|
||||
Fov := Min(ThreadInfo.Client.Width, ThreadInfo.Client.Height) * 1.1;
|
||||
|
||||
CosY := Cos(AngleY); SinY := Sin(AngleY);
|
||||
CosX := Cos(AngleX); SinX := Sin(AngleX);
|
||||
|
||||
// === ╪ру 1: ╠рЄхьрЄшўхёъшщ ЁрёўхЄ тюыэютюую ЄюЁр ===
|
||||
Idx := 0;
|
||||
for I := 0 to TorusSegments do
|
||||
begin
|
||||
U := (I / TorusSegments) * PI * 2.0;
|
||||
Wave1 := Sin(U * WaveCount + TimeScale) * (BaseTubeRadius * 0.44);
|
||||
Wave2 := Cos(U * (WaveCount * 2) - TimeScale * 1.5) * (BaseTubeRadius * 0.17);
|
||||
CurrentTubeRadius := BaseTubeRadius + Wave1 + Wave2;
|
||||
SpineWave := Sin(U * 3.0 - TimeScale * 1.2) * (MainRadius * 0.25);
|
||||
CosU := Cos(U); SinU := Sin(U);
|
||||
|
||||
for J := 0 to TubeSegments do
|
||||
begin
|
||||
if Idx >= MAX_VERTICES then Break;
|
||||
|
||||
V := (J / TubeSegments) * PI * 2.0;
|
||||
CosV := Cos(V); SinV := Sin(V);
|
||||
|
||||
X := (MainRadius + CurrentTubeRadius * CosV) * CosU;
|
||||
Y := CurrentTubeRadius * SinV + SpineWave;
|
||||
Z := (MainRadius + CurrentTubeRadius * CosV) * SinU;
|
||||
|
||||
X1 := X * CosY - Z * SinY;
|
||||
Z1 := X * SinY + Z * CosY;
|
||||
Y2 := Y * CosX - Z1 * SinX;
|
||||
Z2 := Y * SinX + Z1 * CosX;
|
||||
|
||||
Factor := Fov / (Z2 + CamDist);
|
||||
|
||||
ProjectedVertices[Idx].x := CenterX + X1 * Factor;
|
||||
ProjectedVertices[Idx].y := CenterY + Y2 * Factor;
|
||||
ProjectedVertices[Idx].z := Z2;
|
||||
|
||||
ProjectedVertices[Idx].r := Round((Sin(X * 0.015 + TimeColor) * 0.5 + 0.5) * 255.0);
|
||||
ProjectedVertices[Idx].g := Round((Sin(Y * 0.015 + TimeColor * 1.4) * 0.5 + 0.5) * 255.0);
|
||||
ProjectedVertices[Idx].b := Round((Cos(Z * 0.015 + TimeColor) * 0.5 + 0.5) * 255.0);
|
||||
|
||||
Inc(Idx);
|
||||
end;
|
||||
end;
|
||||
|
||||
// === ╪ру 2: ╤сюЁър ўхЄ√Ёхїєуюы№э√ї уЁрэхщ ш Rim Lighting ===
|
||||
Stride := TubeSegments + 1;
|
||||
Idx := 0;
|
||||
for I := 0 to TorusSegments - 1 do
|
||||
begin
|
||||
for J := 0 to TubeSegments - 1 do
|
||||
begin
|
||||
if Idx >= MAX_FACES then Break;
|
||||
|
||||
Idx1 := I * Stride + J;
|
||||
Idx2 := (I + 1) * Stride + J;
|
||||
Idx3 := (I + 1) * Stride + (J + 1);
|
||||
Idx4 := I * Stride + (J + 1);
|
||||
|
||||
if (Idx1 >= MAX_VERTICES) or (Idx2 >= MAX_VERTICES) or
|
||||
(Idx3 >= MAX_VERTICES) or (Idx4 >= MAX_VERTICES) then Continue;
|
||||
|
||||
P1 := ProjectedVertices[Idx1];
|
||||
P2 := ProjectedVertices[Idx2];
|
||||
P3 := ProjectedVertices[Idx3];
|
||||
P4 := ProjectedVertices[Idx4];
|
||||
|
||||
AX := P2.x - P1.x; AY := P2.y - P1.y; AZ := P2.z - P1.z;
|
||||
BX := P4.x - P1.x; BY := P4.y - P1.y; BZ := P4.z - P1.z;
|
||||
NX := AY * BZ - AZ * BY;
|
||||
NY := AZ * BX - ax * BZ;
|
||||
NZ := AX * BY - AY * BX;
|
||||
Len := Sqrt(NX * NX + NY * NY + NZ * NZ);
|
||||
|
||||
RFinal := P1.r; GFinal := P1.g; BFinal := P1.b;
|
||||
|
||||
if Len > 0.0 then
|
||||
begin
|
||||
NZ := NZ / Len;
|
||||
ViewDot := Abs(NZ);
|
||||
Rim := Power(1.0 - ViewDot, 3) * 1.5;
|
||||
CenterDarkness := Max(0.15, ViewDot * 0.5);
|
||||
|
||||
RFinal := (P1.r * CenterDarkness) + (P1.r * Rim);
|
||||
GFinal := (P1.g * CenterDarkness) + (P1.g * Rim);
|
||||
BFinal := (P1.b * CenterDarkness) + (P1.b * Rim);
|
||||
|
||||
if RFinal > 255.0 then RFinal := 255.0;
|
||||
if GFinal > 255.0 then GFinal := 255.0;
|
||||
if BFinal > 255.0 then BFinal := 255.0;
|
||||
end;
|
||||
|
||||
Faces[Idx].v1 := P1;
|
||||
Faces[Idx].v2 := P2;
|
||||
Faces[Idx].v3 := P3;
|
||||
Faces[Idx].v4 := P4;
|
||||
Faces[Idx].avgZ := (P1.z + P2.z + P3.z + P4.z) * 0.25;
|
||||
Faces[Idx].colorR := Round(RFinal);
|
||||
Faces[Idx].colorG := Round(GFinal);
|
||||
Faces[Idx].colorB := Round(BFinal);
|
||||
|
||||
Inc(Idx);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ╬ЄЁшёютър т ёЄрэфрЁЄэюь яхЁёяхъЄштэюь 3D-яЁюёЄЁрэёЄтх
|
||||
// ╤фтшурхь ёЎхэє эрчрф яю юёш Z, ўЄюс√ ухюьхЄЁш яюыэюёЄ№■ тю°ыр т яшЁрьшфє Frustum
|
||||
glTranslatef(0.0, 0.0, -4.7);
|
||||
|
||||
// === ╪ру 4: ┬шчєрышчрЎш яюышуюэют ёЁхфёЄтрьш TinyGL ===
|
||||
for I := 0 to TotalFacesCount - 1 do
|
||||
begin
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(Faces[I].colorR / 255.0, Faces[I].colorG / 255.0, Faces[I].colorB / 255.0);
|
||||
|
||||
// яхЁхтюфшь яшъёхыш т фшрярчюэ (-1.0..1.0)
|
||||
// ┬ glVertex3f яхЁхфрхЄё уыєсшэр NormZ
|
||||
NormX := (Faces[I].v1.x / ThreadInfo.Client.Width) * 2.0 - 1.0;
|
||||
NormY := 1.0 - (Faces[I].v1.y / ThreadInfo.Client.Height) * 2.0;
|
||||
NormZ := -((Faces[I].v1.z + 250.0) / 500.0); // ╠рё°ЄрсшЁєхь Z т ърэюэшўхёъшщ фшрярчюэ тшфшьюёЄш
|
||||
glVertex3f(NormX * 1.95, NormY * 1.45, NormZ);
|
||||
|
||||
NormX := (Faces[I].v2.x / ThreadInfo.Client.Width) * 2.0 - 1.0;
|
||||
NormY := 1.0 - (Faces[I].v2.y / ThreadInfo.Client.Height) * 2.0;
|
||||
NormZ := -((Faces[I].v2.z + 250.0) / 500.0);
|
||||
glVertex3f(NormX * 1.95, NormY * 1.45, NormZ);
|
||||
|
||||
NormX := (Faces[I].v3.x / ThreadInfo.Client.Width) * 2.0 - 1.0;
|
||||
NormY := 1.0 - (Faces[I].v3.y / ThreadInfo.Client.Height) * 2.0;
|
||||
NormZ := -((Faces[I].v3.z + 250.0) / 500.0);
|
||||
glVertex3f(NormX * 1.95, NormY * 1.45, NormZ);
|
||||
|
||||
NormX := (Faces[I].v4.x / ThreadInfo.Client.Width) * 2.0 - 1.0;
|
||||
NormY := 1.0 - (Faces[I].v4.y / ThreadInfo.Client.Height) * 2.0;
|
||||
NormZ := -((Faces[I].v4.z + 250.0) / 500.0);
|
||||
glVertex3f(NormX * 1.95, NormY * 1.45, NormZ);
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
// === ╪ру 5: ╚эъЁхьхэЄ °руют рэшьрЎшш ш фшэрьшўхёъшї Їрчют√ї ёфтшуют ===
|
||||
AngleX := AngleX + 0.01;
|
||||
AngleY := AngleY + 0.02;
|
||||
TimeColor := TimeColor + 0.02;
|
||||
TimeScale := TimeScale + 0.1;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'TinyGL Torus Demo', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,368 @@
|
||||
program CircleParticlesTinyGL;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
// ╠ръёшьры№эюх ъюышўхёЄтю ўрёЄшЎ
|
||||
MAX_PARTICLES = 3000;
|
||||
|
||||
// ╩юышўхёЄтю эют√ї ўрёЄшЎ чр ърфЁ
|
||||
SPAWN_PER_FRAME = 18;
|
||||
|
||||
// ╨рчьхЁ ярышЄЁ√
|
||||
PALETTE_SIZE = 64;
|
||||
|
||||
// ╩юышўхёЄтю ёхуьхэЄют ъЁєур
|
||||
CIRCLE_SEGMENTS = 12;
|
||||
|
||||
// ╙уюы юсчюЁр яхЁёяхъЄшт√
|
||||
FIELD_OF_VIEW = 45.0;
|
||||
|
||||
type
|
||||
// ╫рёЄшЎр
|
||||
TParticle = record
|
||||
Life: LongInt;
|
||||
X, Y: GLFloat;
|
||||
VX, VY: GLFloat;
|
||||
Radius: GLFloat;
|
||||
end;
|
||||
|
||||
// ╓тхЄ ярышЄЁ√
|
||||
TPaletteColor = record
|
||||
R, G, B: GLFloat;
|
||||
end;
|
||||
|
||||
var
|
||||
// ╩юэЄхъёЄ TinyGL
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
// ╧єы ўрёЄшЎ
|
||||
Particles: array[0..MAX_PARTICLES - 1] of TParticle;
|
||||
|
||||
// ╨рфєцэр ярышЄЁр
|
||||
RainbowPalette: array[0..PALETTE_SIZE - 1] of TPaletteColor;
|
||||
|
||||
// ╩єЁёюЁ яюшёър ётюсюфэющ ўрёЄшЎ√
|
||||
PoolCursor: LongInt = 0;
|
||||
|
||||
// ╤ў╕Єўшъ ърфЁют
|
||||
FrameCounter: LongInt = 0;
|
||||
|
||||
// ╨рчьхЁ√ ш яюыюцхэшх юъэр
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
// ╤ыєўрщэюх Float ўшёыю
|
||||
function RandomFloat(MinValue, MaxValue: GLFloat): GLFloat;
|
||||
begin
|
||||
RandomFloat :=
|
||||
MinValue +
|
||||
Random * (MaxValue - MinValue);
|
||||
end;
|
||||
|
||||
// HSV -> RGB
|
||||
procedure HSVtoRGB(H, S, V: GLFloat; var R, G, B: GLFloat);
|
||||
var
|
||||
I: LongInt;
|
||||
F, P, Q, T: GLFloat;
|
||||
begin
|
||||
H := H * 6.0;
|
||||
I := Trunc(H);
|
||||
F := H - I;
|
||||
P := V * (1.0 - S);
|
||||
Q := V * (1.0 - S * F);
|
||||
T := V * (1.0 - S * (1.0 - F));
|
||||
case I mod 6 of
|
||||
0: begin R := V; G := T; B := P; end;
|
||||
1: begin R := Q; G := V; B := P; end;
|
||||
2: begin R := P; G := V; B := T; end;
|
||||
3: begin R := P; G := Q; B := V; end;
|
||||
4: begin R := T; G := P; B := V; end;
|
||||
else
|
||||
begin R := V; G := P; B := Q; end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// ╨рфєцэр ярышЄЁр
|
||||
procedure BuildRainbowPalette;
|
||||
var
|
||||
I: LongInt;
|
||||
H: GLFloat;
|
||||
begin
|
||||
for I := 0 to PALETTE_SIZE - 1 do
|
||||
begin
|
||||
H := 1 - I / (PALETTE_SIZE - 1);
|
||||
HSVtoRGB(
|
||||
H,
|
||||
1.0,
|
||||
1.0,
|
||||
RainbowPalette[I].R,
|
||||
RainbowPalette[I].G,
|
||||
RainbowPalette[I].B
|
||||
);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ╨шёютрэшх ъЁєуыющ ўрёЄшЎ√
|
||||
procedure DrawParticleCircle(X, Y, Radius: GLFloat);
|
||||
var
|
||||
I: LongInt;
|
||||
Angle, PX, PY: GLFloat;
|
||||
begin
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
|
||||
// ╓хэЄЁ ъЁєур
|
||||
glVertex3f(X, Y, 0.0);
|
||||
|
||||
// ╬ъЁєцэюёЄ№
|
||||
for I := 0 to CIRCLE_SEGMENTS do
|
||||
begin
|
||||
Angle := (PI * 2.0 * I) / CIRCLE_SEGMENTS;
|
||||
|
||||
PX := X + Cos(Angle) * Radius;
|
||||
PY := Y + Sin(Angle) * Radius;
|
||||
|
||||
glVertex3f(PX, PY, 0.0);
|
||||
end;
|
||||
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
// ╤ючфрэшх ўрёЄшЎ√
|
||||
procedure SpawnParticle(EmitX, EmitY: GLFloat);
|
||||
var
|
||||
Attempts: LongInt;
|
||||
P: ^TParticle;
|
||||
Angle,
|
||||
Speed: GLFloat;
|
||||
begin
|
||||
Attempts := MAX_PARTICLES;
|
||||
|
||||
while Attempts > 0 do
|
||||
begin
|
||||
P := @Particles[PoolCursor];
|
||||
|
||||
PoolCursor :=
|
||||
(PoolCursor + 1) mod MAX_PARTICLES;
|
||||
|
||||
if P^.Life <= 0 then
|
||||
begin
|
||||
Angle := RandomFloat(0.0, PI * 2.0);
|
||||
Speed := RandomFloat(5.0, 13.0);
|
||||
|
||||
P^.X := EmitX;
|
||||
P^.Y := EmitY;
|
||||
|
||||
P^.VX := Cos(Angle) * Speed;
|
||||
P^.VY := Sin(Angle) * Speed - 7.0;
|
||||
|
||||
P^.Life := Round(40 + Random * 24);
|
||||
|
||||
P^.Radius := 1 + Random * 3;
|
||||
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Dec(Attempts);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ╬ёэютэющ ЁхэфхЁ
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
Width,
|
||||
Height: LongInt;
|
||||
CameraZ, EmitX,
|
||||
EmitY: GLFloat;
|
||||
I: LongInt;
|
||||
P: ^TParticle;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
|
||||
Width := ThreadInfo.Client.Width;
|
||||
Height := ThreadInfo.Client.Height;
|
||||
|
||||
if Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, Width, Height, CTX);
|
||||
glViewPort( 0, 0, Width, Height);
|
||||
|
||||
// ╧хЁт√щ ърфЁ яюыэюёЄ№■ юўш∙рхЄ ¤ъЁрэ
|
||||
if FrameCounter = 0 then
|
||||
begin
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
end;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(
|
||||
FIELD_OF_VIEW,
|
||||
Width / Height,
|
||||
0.1,
|
||||
5000.0
|
||||
);
|
||||
|
||||
// ─шэрьшўхёър ърьхЁр
|
||||
// ╨рчьхЁ ёЎхэ√ ёЄрсшыхэ яЁш ы■сюь ЁрчьхЁх юъэр
|
||||
CameraZ :=
|
||||
Height /
|
||||
(Sin(FIELD_OF_VIEW * PI / 360.0) /
|
||||
Cos(FIELD_OF_VIEW * PI / 360.0));
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(
|
||||
-Width * 0.5,
|
||||
-Height * 0.5,
|
||||
-CameraZ * 0.5
|
||||
);
|
||||
|
||||
// ╧юыюцхэшх ¤ьшЄЄхЁр
|
||||
// ╬ЄёЄєя√ ёЄрсшы№э√ яЁш ы■сюь ЁрчьхЁх юъэр
|
||||
EmitX :=
|
||||
(Width * 0.5) +
|
||||
Sin(FrameCounter * 0.03) *
|
||||
(Width * 0.46);
|
||||
|
||||
EmitY :=
|
||||
(Height * 0.5) +
|
||||
Cos(FrameCounter * 0.02) *
|
||||
(Height * 0.44);
|
||||
|
||||
// ╤ючфрэшх эют√ї ўрёЄшЎ
|
||||
for I := 0 to SPAWN_PER_FRAME - 1 do
|
||||
SpawnParticle(EmitX, EmitY);
|
||||
|
||||
// ╬сэютыхэшх ўрёЄшЎ
|
||||
for I := 0 to MAX_PARTICLES - 1 do
|
||||
begin
|
||||
P := @Particles[I];
|
||||
|
||||
if P^.Life <= 0 then
|
||||
Continue;
|
||||
|
||||
// ─тшцхэшх
|
||||
P^.X := P^.X + P^.VX;
|
||||
P^.Y := P^.Y + P^.VY;
|
||||
|
||||
// ├ЁртшЄрЎш
|
||||
P^.VY := P^.VY + 0.18;
|
||||
|
||||
// ╬Єёъюъ юЄ ёЄхэюъ
|
||||
if P^.X > Width - P^.Radius then
|
||||
begin
|
||||
P^.X := Width - P^.Radius;
|
||||
P^.VX := P^.VX * (-0.80);
|
||||
end;
|
||||
|
||||
if P^.X < P^.Radius then
|
||||
begin
|
||||
P^.X := P^.Radius;
|
||||
P^.VX := P^.VX * (-0.80);
|
||||
end;
|
||||
|
||||
// ╬Єёъюъ юЄ яюЄюыър ш яюыр
|
||||
if P^.Y > Height - P^.Radius then
|
||||
begin
|
||||
P^.Y := Height - P^.Radius;
|
||||
P^.VY := P^.VY * (-0.70);
|
||||
P^.VX := P^.VX * 0.94;
|
||||
end;
|
||||
|
||||
if P^.Y < P^.Radius then
|
||||
begin
|
||||
P^.Y := P^.Radius;
|
||||
P^.VY := P^.VY * (-0.70);
|
||||
P^.VX := P^.VX * 0.94;
|
||||
end;
|
||||
|
||||
// ╙ьхэ№°хэшх цшчэш
|
||||
Dec(P^.Life);
|
||||
|
||||
if P^.Life > 0 then
|
||||
begin
|
||||
glColor3f(
|
||||
RainbowPalette[P^.Life].R,
|
||||
RainbowPalette[P^.Life].G,
|
||||
RainbowPalette[P^.Life].B
|
||||
);
|
||||
|
||||
DrawParticleCircle(
|
||||
P^.X,
|
||||
P^.Y,
|
||||
P^.Radius
|
||||
);
|
||||
end;
|
||||
end;
|
||||
|
||||
// ┬√тюф ърфЁр
|
||||
kosglSwapBuffers();
|
||||
|
||||
Inc(FrameCounter);
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
Randomize;
|
||||
BuildRainbowPalette;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 2;
|
||||
WndHeight := Height div 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
begin
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(
|
||||
WndLeft,
|
||||
WndTop,
|
||||
WndWidth,
|
||||
WndHeight,
|
||||
'Circle Particles TinyGL',
|
||||
$00000000,
|
||||
WS_SKINNED_SIZABLE +
|
||||
WS_CLIENT_COORDS +
|
||||
WS_CAPTION,
|
||||
CAPTION_MOVABLE
|
||||
);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,169 @@
|
||||
program DNAHelix3D;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
MAX_ELEMENTS = 40; { ╩юышўхёЄтю ёЄєяхэхщ т Ўхяюўъх ─═╩ }
|
||||
RADIUS = 1.1; { ╨рфшєё чръЁєўштрэш ёяшЁрыш }
|
||||
STEP_HEIGHT = 0.12; { ╨рёёЄю эшх ьхцфє ёЄєяхэ ьш яю тхЁЄшърыш }
|
||||
|
||||
type
|
||||
TBaseNode = record
|
||||
X1, Y1, Z1: GLFloat;
|
||||
X2, Y2, Z2: GLFloat;
|
||||
R, G, B: GLFloat;
|
||||
end;
|
||||
|
||||
var
|
||||
Nodes: array[1..MAX_ELEMENTS] of TBaseNode;
|
||||
Rotation: GLFloat = 0;
|
||||
Speed: GLFloat = 0.5;
|
||||
ZTr: GLFloat = -7.5;
|
||||
TimeVal: GLFloat = 0;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
{ ╠рЄхьрЄшўхёъшщ ЁрёўхЄ тюыэютюую ёъЁєўштрэш ш фхЇюЁьрЎшш ─═╩ }
|
||||
procedure UpdateDNAPhysics;
|
||||
var
|
||||
I: Integer;
|
||||
Angle, VertPos, Wave: GLFloat;
|
||||
begin
|
||||
for I := 1 to MAX_ELEMENTS do
|
||||
begin
|
||||
{ ┴рчют√щ єуюы чръЁєўштрэш + фшэрьшўхёър тюыэр тЁхьхэш }
|
||||
Angle := (I * 0.4) + Sin(TimeVal + I * 0.15) * 0.25;
|
||||
VertPos := (I - (MAX_ELEMENTS div 2)) * STEP_HEIGHT;
|
||||
|
||||
{ ╥хяыютющ тюыэютющ °єь }
|
||||
Wave := Cos(TimeVal * 2.0 + I * 0.1) * 0.08;
|
||||
|
||||
{ ═шЄ№ └ ёяшЁрыш }
|
||||
Nodes[I].X1 := Cos(Angle) * (RADIUS + Wave);
|
||||
Nodes[I].Y1 := VertPos;
|
||||
Nodes[I].Z1 := Sin(Angle) * (RADIUS + Wave);
|
||||
|
||||
{ ═шЄ№ ┴ ёяшЁрыш (яЁюЄштюЇрчр 180 уЁрфєёют / PI) }
|
||||
Nodes[I].X2 := Cos(Angle + 3.14159) * (RADIUS + Wave);
|
||||
Nodes[I].Y2 := VertPos;
|
||||
Nodes[I].Z2 := Sin(Angle + 3.14159) * (RADIUS + Wave);
|
||||
|
||||
{ ╓тхЄютюх ъюфшЁютрэшх эєъыхюЄшфют т чртшёшьюёЄш юЄ т√ёюЄ√ }
|
||||
Nodes[I].R := 0.4 + Sin(I * 0.2) * 0.4;
|
||||
Nodes[I].G := 0.2 + Cos(I * 0.1) * 0.4;
|
||||
Nodes[I].B := 0.8 - Sin(I * 0.05) * 0.2;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
I: Integer;
|
||||
S: GLFloat;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.15, 0.15, 0.3, 0.0); { ├ыєсюъшщ сшю-ъшсхЁэхЄшўхёъшщ Їюэ }
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glTranslatef(0.0, 0.0, ZTr);
|
||||
glRotatef(Rotation, 0.3, 1.0, 0.1); { ╧ыртэ√щ юсыхЄ ърьхЁ√ }
|
||||
|
||||
S := 0.06; { ╥юы∙шэр єчыют }
|
||||
|
||||
for I := 1 to MAX_ELEMENTS do
|
||||
begin
|
||||
{ 1. ╨шёєхь яхЁхь√ўъш ьхцфє эшЄ ьш ─═╩ }
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(Nodes[I].R * 0.6, Nodes[I].G * 0.6, Nodes[I].B * 0.6);
|
||||
glVertex3f(Nodes[I].X1, Nodes[I].Y1 - 0.02, Nodes[I].Z1);
|
||||
glVertex3f(Nodes[I].X2, Nodes[I].Y2 - 0.02, Nodes[I].Z2);
|
||||
glVertex3f(Nodes[I].X2, Nodes[I].Y2 + 0.02, Nodes[I].Z2);
|
||||
glVertex3f(Nodes[I].X1, Nodes[I].Y1 + 0.02, Nodes[I].Z1);
|
||||
glEnd();
|
||||
|
||||
{ 2. ╨шёєхь ёЇхЁє-ъєсшъ эшЄш └ }
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(Nodes[I].R, Nodes[I].G, Nodes[I].B);
|
||||
glVertex3f(Nodes[I].X1 - S, Nodes[I].Y1 - S, Nodes[I].Z1 + S);
|
||||
glVertex3f(Nodes[I].X1 + S, Nodes[I].Y1 - S, Nodes[I].Z1 + S);
|
||||
glVertex3f(Nodes[I].X1 + S, Nodes[I].Y1 + S, Nodes[I].Z1 + S);
|
||||
glVertex3f(Nodes[I].X1 - S, Nodes[I].Y1 + S, Nodes[I].Z1 + S);
|
||||
glEnd();
|
||||
|
||||
{ 3. ╨шёєхь ёЇхЁє-ъєсшъ эшЄш ┴ }
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(Nodes[I].B, Nodes[I].R, Nodes[I].G); { ╚этхЁЄшЁютрээ√щ ЎтхЄ фы ярЁ√ }
|
||||
glVertex3f(Nodes[I].X2 - S, Nodes[I].Y2 - S, Nodes[I].Z2 + S);
|
||||
glVertex3f(Nodes[I].X2 + S, Nodes[I].Y2 - S, Nodes[I].Z2 + S);
|
||||
glVertex3f(Nodes[I].X2 + S, Nodes[I].Y2 + S, Nodes[I].Z2 + S);
|
||||
glVertex3f(Nodes[I].X2 - S, Nodes[I].Y2 + S, Nodes[I].Z2 + S);
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
UpdateDNAPhysics;
|
||||
Rotation := Rotation + Speed;
|
||||
TimeVal := TimeVal + 0.03;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, '3D DNA Helix Wave', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT: GetKey;
|
||||
BUTTON_EVENT: if GetButton.ID = 1 then ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,181 @@
|
||||
program FractalStormForest;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
NUM_TREES = 7; // ъюышўхёЄтю фхЁхт№хт
|
||||
MAX_DEPTH = 5; // уыєсшэр ЇЁръЄрыр
|
||||
|
||||
var
|
||||
Rotation: GLFloat = 0;
|
||||
Speed: GLFloat = 0.5;
|
||||
ZTr: GLFloat = -11.0;
|
||||
TimeVal: GLFloat = 0;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
procedure DrawBranch(Length: GLFloat; Depth: Integer; WindForce: GLFloat);
|
||||
var
|
||||
R, G, B: GLFloat;
|
||||
begin
|
||||
if Depth > MAX_DEPTH then Exit;
|
||||
|
||||
// ╬╤┼══▀▀ ╧└╦╚╥╨└ ╦╚╤╥┬█
|
||||
// ╤Єтюы Єхьэю-сюЁфют√щ }
|
||||
// ╩Ёюэр Ёъю-чюыюЄр / юЁрэцхтр }
|
||||
R := 0.3 + (Depth * 0.18);
|
||||
G := 0.05 + (Depth * 0.18);
|
||||
B := 0.1;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(R, G, B);
|
||||
glVertex3f(-0.1 * Length, 0.0, 0.1 * Length);
|
||||
glVertex3f( 0.1 * Length, 0.0, 0.1 * Length);
|
||||
glVertex3f( 0.05 * Length, Length, 0.05 * Length);
|
||||
glVertex3f(-0.05 * Length, Length, 0.05 * Length);
|
||||
|
||||
glColor3f(R * 0.8, G * 0.8, B * 0.8);
|
||||
glVertex3f( 0.1 * Length, 0.0, 0.1 * Length);
|
||||
glVertex3f( 0.1 * Length, 0.0, -0.1 * Length);
|
||||
glVertex3f( 0.05 * Length, Length, -0.05 * Length);
|
||||
glVertex3f( 0.05 * Length, Length, 0.05 * Length);
|
||||
|
||||
glColor3f(R * 0.6, G * 0.6, B * 0.6);
|
||||
glVertex3f( 0.1 * Length, 0.0, -0.1 * Length);
|
||||
glVertex3f(-0.1 * Length, 0.0, -0.1 * Length);
|
||||
glVertex3f(-0.05 * Length, Length, -0.05 * Length);
|
||||
glVertex3f( 0.05 * Length, Length, -0.05 * Length);
|
||||
|
||||
glColor3f(R * 0.7, G * 0.7, B * 0.7);
|
||||
glVertex3f(-0.1 * Length, 0.0, -0.1 * Length);
|
||||
glVertex3f(-0.1 * Length, 0.0, 0.1 * Length);
|
||||
glVertex3f(-0.05 * Length, Length, 0.05 * Length);
|
||||
glVertex3f(-0.05 * Length, Length, -0.05 * Length);
|
||||
glEnd();
|
||||
|
||||
glTranslatef(0.0, Length, 0.0);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(22.0 + WindForce, 1.0, 0.0, 0.0);
|
||||
glRotatef(20.0, 0.0, 0.0, 1.0);
|
||||
glScalef(0.75, 0.75, 0.75);
|
||||
DrawBranch(Length, Depth + 1, WindForce * 1.25);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(-22.0 + WindForce, 1.0, 0.0, 0.0);
|
||||
glRotatef(-20.0, 0.0, 0.0, 1.0);
|
||||
glScalef(0.75, 0.75, 0.75);
|
||||
DrawBranch(Length, Depth + 1, WindForce * 1.25);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(30.0, 0.0, 1.0, 0.0);
|
||||
glRotatef(15.0 + WindForce, 0.0, 0.0, 1.0);
|
||||
glScalef(0.7, 0.7, 0.7);
|
||||
DrawBranch(Length, Depth + 1, WindForce * 1.15);
|
||||
glPopMatrix();
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
I: Integer;
|
||||
TreeAngle, Wind: GLFloat;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.04, 0.04, 0.08, 0.0); // ╚ёёшэ -ўхЁэюх эхсю
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glTranslatef(0.0, -1.2, ZTr);
|
||||
glRotatef(Rotation, 0.0, 1.0, 0.0);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(0.35, 0.30, 0.20);
|
||||
glVertex3f(-4.0, -1.0, 4.0); glVertex3f( 4.0, -1.0, 4.0);
|
||||
glVertex3f( 4.0, -1.0, -4.0); glVertex3f(-4.0, -1.0, -4.0);
|
||||
glEnd();
|
||||
|
||||
// ╧╬╨█┬╚╤╥█╔ ┬┼╥┼╨
|
||||
Wind := (Sin(TimeVal * 0.8) * 6.0) + (Sin(TimeVal * 2.5) * 3.5) + (Sin(TimeVal * 6.0) * 1.5);
|
||||
|
||||
for I := 0 to NUM_TREES - 1 do
|
||||
begin
|
||||
glPushMatrix();
|
||||
TreeAngle := (I * 360.0) / NUM_TREES;
|
||||
glRotatef(TreeAngle, 0.0, 1.0, 0.0);
|
||||
glTranslatef(0.0, -1.0, 2.2);
|
||||
|
||||
DrawBranch(2.0, 1, Wind);
|
||||
glPopMatrix();
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
Rotation := Rotation + Speed;
|
||||
TimeVal := TimeVal + 0.04;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'TinyGL Autumn Storm', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,413 @@
|
||||
program Perfect3DBalls;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
MAX_BALLS = 72;
|
||||
GRAVITY = 0.015;
|
||||
AIR = 0.99;
|
||||
BOUNCE = -0.85;
|
||||
|
||||
type
|
||||
TBall = record
|
||||
Active: Boolean;
|
||||
IsShard: Boolean;
|
||||
X, Y, Z: Single;
|
||||
VX, VY, VZ: Single;
|
||||
Radius: Single;
|
||||
Hue: Integer;
|
||||
Darkness: Single;
|
||||
Life: Single;
|
||||
end;
|
||||
|
||||
var
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
CTX: TKOSGLContext;
|
||||
Balls: array[0..MAX_BALLS - 1] of TBall;
|
||||
Angle: Single = 0.0;
|
||||
|
||||
BOX_X, BOX_Y, BOX_Z: Single;
|
||||
i: Integer;
|
||||
|
||||
function Max(A, B: Extended): Extended; begin if A > B then Result := A else Result := B; end;
|
||||
function Min(A, B: Extended): Extended; begin if A < B then Result := A else Result := B; end;
|
||||
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
function Frac(N: Single): Single;
|
||||
begin
|
||||
Result := N - Trunc(N) ;
|
||||
end;
|
||||
|
||||
procedure HSLtoRGB(H: Integer; S, L: Single; var R, G, B: Single);
|
||||
var
|
||||
C, X, M, R1, G1, B1: Single;
|
||||
HPrime: Single;
|
||||
begin
|
||||
C := (1.0 - Abs(2.0 * L - 1.0)) * S;
|
||||
HPrime := H / 60.0;
|
||||
X := C * (1.0 - Abs(Frac(HPrime / 2.0) * 2.0 - 1.0));
|
||||
M := L - C / 2.0;
|
||||
if (HPrime >= 0) and (HPrime < 1) then begin R1 := C; G1 := X; B1 := 0; end
|
||||
else if (HPrime >= 1) and (HPrime < 2) then begin R1 := X; G1 := C; B1 := 0; end
|
||||
else if (HPrime >= 2) and (HPrime < 3) then begin R1 := 0; G1 := C; B1 := X; end
|
||||
else if (HPrime >= 3) and (HPrime < 4) then begin R1 := 0; G1 := X; B1 := C; end
|
||||
else if (HPrime >= 4) and (HPrime < 5) then begin R1 := X; G1 := 0; B1 := C; end
|
||||
else begin R1 := C; G1 := 0; B1 := X; end;
|
||||
R := R1 + M; G := G1 + M; B := B1 + M;
|
||||
end;
|
||||
|
||||
procedure DrawSphere(Radius: Single);
|
||||
var
|
||||
l_i, l_j: Integer;
|
||||
t_Segments: Integer;
|
||||
lat0, z0, r0, lat1, z1, r1: Single;
|
||||
lng, x, y: Single;
|
||||
begin
|
||||
t_Segments := 18;
|
||||
|
||||
for l_i := 0 to t_Segments - 1 do
|
||||
begin
|
||||
lat0 := PI * (-0.5 + l_i / t_Segments);
|
||||
z0 := Sin(lat0);
|
||||
r0 := Cos(lat0);
|
||||
|
||||
lat1 := PI * (-0.5 + (l_i + 1) / t_Segments);
|
||||
z1 := Sin(lat1);
|
||||
r1 := Cos(lat1);
|
||||
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for l_j := 0 to t_Segments do
|
||||
begin
|
||||
lng := 2.0 * PI * l_j / t_Segments;
|
||||
x := Cos(lng);
|
||||
y := Sin(lng);
|
||||
|
||||
glNormal3f(x * r0, y * r0, z0);
|
||||
glVertex3f(x * r0 * Radius, y * r0 * Radius, z0 * Radius);
|
||||
|
||||
glNormal3f(x * r1, y * r1, z1);
|
||||
glVertex3f(x * r1 * Radius, y * r1 * Radius, z1 * Radius);
|
||||
end;
|
||||
glEnd();
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ResizeTopology(W, H: Integer);
|
||||
begin
|
||||
BOX_X := 5.0 * (W / H);
|
||||
BOX_Y := 5.0;
|
||||
BOX_Z := 5.0;
|
||||
end;
|
||||
|
||||
function FindFreeBallIndex: Integer;
|
||||
var
|
||||
K: Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
for K := 0 to MAX_BALLS - 1 do
|
||||
begin
|
||||
if not Balls[K].Active then
|
||||
begin
|
||||
Result := K;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure SpawnBall(Index: Integer; IsShard: Boolean; ParentIndex: Integer);
|
||||
begin
|
||||
Balls[Index].Active := True;
|
||||
Balls[Index].IsShard := IsShard;
|
||||
Balls[Index].Darkness := 1.0;
|
||||
|
||||
if not IsShard then
|
||||
begin
|
||||
// ╧ю ты ■Єё т ёрьюь тхЁїє (BOX_Y) ш ярфр■Є тэшч
|
||||
Balls[Index].X := (Random * 100 / 100.0 - 0.5) * BOX_X * 1.6;
|
||||
Balls[Index].Y := BOX_Y - 0.5 - (Random * 100 / 50.0);
|
||||
Balls[Index].Z := (Random * 100 / 100.0 - 0.5) * BOX_Z * 1.6;
|
||||
Balls[Index].VX := (Random * 100 / 100.0 - 0.5) * 0.4;
|
||||
Balls[Index].VY := -(Random * 100 / 100.0) * 0.1; // ═ряЁртыхэшх тхъЄюЁр тэшч
|
||||
Balls[Index].VZ := (Random * 100 / 100.0 - 0.5) * 0.4;
|
||||
Balls[Index].Radius := 0.4 + (Random * 100 / 250.0);
|
||||
Balls[Index].Hue := Trunc(Random * 360);
|
||||
Balls[Index].Life := 1.0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Balls[Index].X := Balls[ParentIndex].X;
|
||||
Balls[Index].Y := Balls[ParentIndex].Y;
|
||||
Balls[Index].Z := Balls[ParentIndex].Z;
|
||||
Balls[Index].Radius := Balls[ParentIndex].Radius * 0.35;
|
||||
Balls[Index].Hue := Balls[ParentIndex].Hue;
|
||||
Balls[Index].Life := 1.0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure UpdatePhysics;
|
||||
var
|
||||
Idx, J, FreeIdx: Integer;
|
||||
DX, DY, DZ, Dist, MinDist: Single;
|
||||
NX, NY, NZ, Overlap: Single;
|
||||
KX, KY, KZ, PFactor: Single;
|
||||
XS, YS, ZS: Single;
|
||||
begin
|
||||
for Idx := 0 to MAX_BALLS - 1 do
|
||||
begin
|
||||
if not Balls[Idx].Active then Continue;
|
||||
for J := Idx + 1 to MAX_BALLS - 1 do
|
||||
begin
|
||||
if not Balls[J].Active then Continue;
|
||||
DX := Balls[J].X - Balls[Idx].X;
|
||||
DY := Balls[J].Y - Balls[Idx].Y;
|
||||
DZ := Balls[J].Z - Balls[Idx].Z;
|
||||
Dist := Sqrt(DX * DX + DY * DY + DZ * DZ);
|
||||
MinDist := Balls[Idx].Radius + Balls[J].Radius;
|
||||
|
||||
if Dist < MinDist then
|
||||
begin
|
||||
if Dist > 0.001 then
|
||||
begin
|
||||
NX := DX / Dist; NY := DY / Dist; NZ := DZ / Dist;
|
||||
end
|
||||
else
|
||||
begin
|
||||
NX := 0.1; NY := 0.0; NZ := 0.0;
|
||||
end;
|
||||
Overlap := MinDist - Dist;
|
||||
Balls[Idx].X := Balls[Idx].X - NX * Overlap * 0.5;
|
||||
Balls[Idx].Y := Balls[Idx].Y - NY * Overlap * 0.5;
|
||||
Balls[Idx].Z := Balls[Idx].Z - NZ * Overlap * 0.5;
|
||||
Balls[J].X := Balls[J].X + NX * Overlap * 0.5;
|
||||
Balls[J].Y := Balls[J].Y + NY * Overlap * 0.5;
|
||||
Balls[J].Z := Balls[J].Z + NZ * Overlap * 0.5;
|
||||
KX := Balls[Idx].VX - Balls[J].VX;
|
||||
KY := Balls[Idx].VY - Balls[J].VY;
|
||||
KZ := Balls[Idx].VZ - Balls[J].VZ;
|
||||
PFactor := 2.0 * (NX * KX + NY * KY + NZ * KZ) / 2.0 + 0.01;
|
||||
Balls[Idx].VX := Balls[Idx].VX - PFactor * NX;
|
||||
Balls[Idx].VY := Balls[Idx].VY - PFactor * NY;
|
||||
Balls[Idx].VZ := Balls[Idx].VZ - PFactor * NZ;
|
||||
Balls[J].VX := Balls[J].VX + PFactor * NX;
|
||||
Balls[J].VY := Balls[J].VY + PFactor * NY;
|
||||
Balls[J].VZ := Balls[J].VZ + PFactor * NZ;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
for Idx := 0 to MAX_BALLS - 1 do
|
||||
begin
|
||||
if not Balls[Idx].Active then Continue;
|
||||
|
||||
Balls[Idx].VY := Balls[Idx].VY - GRAVITY;
|
||||
Balls[Idx].VX := Balls[Idx].VX * AIR;
|
||||
Balls[Idx].VY := Balls[Idx].VY * AIR;
|
||||
Balls[Idx].VZ := Balls[Idx].VZ * AIR;
|
||||
Balls[Idx].X := Balls[Idx].X + Balls[Idx].VX;
|
||||
Balls[Idx].Y := Balls[Idx].Y + Balls[Idx].VY;
|
||||
Balls[Idx].Z := Balls[Idx].Z + Balls[Idx].VZ;
|
||||
|
||||
if Balls[Idx].IsShard then
|
||||
begin
|
||||
Balls[Idx].Life := Balls[Idx].Life - 0.015;
|
||||
Balls[Idx].Darkness := Balls[Idx].Life;
|
||||
|
||||
if Balls[Idx].Y - Balls[Idx].Radius < -BOX_Y then
|
||||
begin
|
||||
Balls[Idx].Y := -BOX_Y + Balls[Idx].Radius; Balls[Idx].VY := Balls[Idx].VY * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].Y + Balls[Idx].Radius > BOX_Y then
|
||||
begin
|
||||
Balls[Idx].Y := BOX_Y - Balls[Idx].Radius; Balls[Idx].VY := Balls[Idx].VY * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].X - Balls[Idx].Radius < -BOX_X then
|
||||
begin
|
||||
Balls[Idx].X := -BOX_X + Balls[Idx].Radius; Balls[Idx].VX := Balls[Idx].VX * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].X + Balls[Idx].Radius > BOX_X then
|
||||
begin
|
||||
Balls[Idx].X := BOX_X - Balls[Idx].Radius; Balls[Idx].VX := Balls[Idx].VX * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].Z - Balls[Idx].Radius < -BOX_Z then
|
||||
begin
|
||||
Balls[Idx].Z := -BOX_Z + Balls[Idx].Radius; Balls[Idx].VZ := Balls[Idx].VZ * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].Z + Balls[Idx].Radius > BOX_Z then
|
||||
begin
|
||||
Balls[Idx].Z := BOX_Z - Balls[Idx].Radius; Balls[Idx].VZ := Balls[Idx].VZ * BOUNCE;
|
||||
end;
|
||||
if Balls[Idx].Life <= 0.0 then Balls[Idx].Active := False;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// ╨рчЁє°хэшх сюы№°шї °рЁют яЁш ъюэЄръЄх ё ы■сющ шч 3D-уЁрэшЎ юъэр
|
||||
if (Balls[Idx].Y - Balls[Idx].Radius < -BOX_Y) or
|
||||
(Balls[Idx].Y + Balls[Idx].Radius > BOX_Y) or
|
||||
(Abs(Balls[Idx].X) + Balls[Idx].Radius > BOX_X) or
|
||||
(Abs(Balls[Idx].Z) + Balls[Idx].Radius > BOX_Z) then
|
||||
begin
|
||||
XS := -0.25;
|
||||
while XS <= 0.25 do
|
||||
begin
|
||||
YS := -0.25;
|
||||
while YS <= 0.25 do
|
||||
begin
|
||||
ZS := -0.25;
|
||||
while ZS <= 0.25 do
|
||||
begin
|
||||
FreeIdx := FindFreeBallIndex;
|
||||
if FreeIdx <> -1 then
|
||||
begin
|
||||
SpawnBall(FreeIdx, True, Idx);
|
||||
Balls[FreeIdx].VX := Balls[Idx].VX * 0.4 + XS * (1.0 + Random * 50 / 100.0);
|
||||
Balls[FreeIdx].VY := Balls[Idx].VY * BOUNCE + YS * (1.0 + Random * 50 / 100.0) + 0.15;
|
||||
Balls[FreeIdx].VZ := Balls[Idx].VZ * 0.4 + ZS * (1.0 + Random * 50 / 100.0);
|
||||
end;
|
||||
ZS := ZS + 0.5;
|
||||
end;
|
||||
YS := YS + 0.5;
|
||||
end;
|
||||
XS := XS + 0.5;
|
||||
end;
|
||||
SpawnBall(Idx, False, 0);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
CosA, SinA: Single;
|
||||
LightPos: array[0..3] of GLfloat;
|
||||
LightAmbient: array[0..3] of GLfloat;
|
||||
LightDiffuse: array[0..3] of GLfloat;
|
||||
MatAmbient: array[0..3] of GLfloat;
|
||||
MatDiffuse: array[0..3] of GLfloat;
|
||||
MatSpecular: array[0..3] of GLfloat;
|
||||
R, G, B: Single;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if not (ThreadInfo.Client.Height > 3) then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(5/255, 6/255, 11/255, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
|
||||
UpdatePhysics;
|
||||
ResizeTopology(ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
Angle := Angle + 0.003;
|
||||
CosA := Cos(Angle); SinA := Sin(Angle);
|
||||
|
||||
glTranslatef(0.0, 0.0, -13.5);
|
||||
|
||||
// ═рёЄЁющър яючшЎшш ётхЄр (ёьх∙хэ ўєЄ№ т√°х фы ъЁрёштюую сышър)
|
||||
LightPos[0] := -8.0 * CosA - (-6.0) * SinA;
|
||||
LightPos[1] := 15.0; // ═ряЁртыхэ ётхЁїє тэшч
|
||||
LightPos[2] := -8.0 * SinA + (-6.0) * CosA;
|
||||
LightPos[3] := 0.5;
|
||||
|
||||
LightAmbient[0] := 0.35; LightAmbient[1] := 0.35; LightAmbient[2] := 0.38; LightAmbient[3] := 0.5;
|
||||
LightDiffuse[0] := 0.95; LightDiffuse[1] := 0.95; LightDiffuse[2] := 0.95; LightDiffuse[3] := 0.5;
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, @LightPos[0]);
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, @LightAmbient[0]);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, @LightDiffuse[0]);
|
||||
|
||||
MatSpecular[0] := 0.9; MatSpecular[1] := 0.9; MatSpecular[2] := 0.9; MatSpecular[3] := 0.5;
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, @MatSpecular[0]);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, 64.0);
|
||||
|
||||
for i := 0 to MAX_BALLS - 1 do
|
||||
begin
|
||||
if not Balls[i].Active then Continue;
|
||||
|
||||
HSLtoRGB(Balls[i].Hue, 0.95, 0.55 * Balls[i].Darkness, R, G, B);
|
||||
|
||||
MatAmbient[0] := R * 0.6; MatAmbient[1] := G * 0.6; MatAmbient[2] := B * 0.6; MatAmbient[3] := 1.0;
|
||||
MatDiffuse[0] := R; MatDiffuse[1] := G; MatDiffuse[2] := B; MatDiffuse[3] := 1.0;
|
||||
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, @MatAmbient[0]);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, @MatDiffuse[0]);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(Balls[i].X, Balls[i].Y, Balls[i].Z);
|
||||
DrawSphere(Balls[i].Radius);
|
||||
glPopMatrix();
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
Randomize;
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
ResizeTopology(WndWidth, WndHeight);
|
||||
|
||||
FillChar(Balls, SizeOf(Balls), #0);
|
||||
for i := 0 to 24 do
|
||||
begin
|
||||
SpawnBall(i, False, 0);
|
||||
// ╨рёяЁхфхы хь ЁртэюьхЁэю яю тёхщ т√ёюЄх ъюЁюсъш (юЄ -BOX_Y фю BOX_Y)
|
||||
Balls[i].Y := -BOX_Y + 1.0 + (Random * 100 / 100.0) * (BOX_Y * 2.0 - 2.0);
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'TinyGL Light 3D Balls', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,22 @@
|
||||
#SHS
|
||||
rm Bublick_TinyGL.kex
|
||||
rm CircleParticles_TinyGL.kex
|
||||
rm DNAHelix3D_TinyGL.kex
|
||||
rm FractalStormForest_TinyGL.kex
|
||||
rm GravityShardBalls_TinyGL.kex
|
||||
rm MengerSponge_TinyGL.kex
|
||||
rm RubikRotate3D.kex
|
||||
rm Sierpinski3D_TinyGL.kex
|
||||
rm WaveMesh_TinyGL.kex
|
||||
rm XDRUSH.kex
|
||||
../xdpk.kex Bublick_TinyGL.pas
|
||||
../xdpk.kex CircleParticles_TinyGL.pas
|
||||
../xdpk.kex DNAHelix3D_TinyGL.pas
|
||||
../xdpk.kex FractalStormForest_TinyGL.pas
|
||||
../xdpk.kex GravityShardBalls_TinyGL.pas
|
||||
../xdpk.kex MengerSponge_TinyGL.pas
|
||||
../xdpk.kex RubikRotate3D.pas
|
||||
../xdpk.kex Sierpinski3D_TinyGL.pas
|
||||
../xdpk.kex WaveMesh_TinyGL.pas
|
||||
../xdpk.kex XDRUSH.pas
|
||||
exit
|
||||
@@ -0,0 +1,207 @@
|
||||
program MengerSpongeFractal;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
MAX_DEPTH = 2; { ├ыєсшэр ЇЁръЄрыр. ┬эшьрэшх: чэрўхэшх 3 чрЄюЁьючшЄ ёЄрЁ√щ яЁюЎхёёюЁ }
|
||||
|
||||
var
|
||||
Rotation: GLFloat = 0;
|
||||
Speed: GLFloat = 0.835;
|
||||
ZTr: GLFloat = -5.0;
|
||||
TimeVal: GLFloat = 0;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
IsLine: Boolean;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
// ╬ЄЁшёютър срчютюую ъєср ЇЁръЄрыр ё яёхтфю-юётх∙хэшхь уЁрэхщ
|
||||
procedure DrawSolidCube(Size: GLFloat);
|
||||
var
|
||||
S: GLFloat;
|
||||
begin
|
||||
S := Size * 0.5;
|
||||
glBegin(GL_QUADS);
|
||||
// ╧хЁхфэ уЁрэ№ - ▀Ёър сшЁ■чютр
|
||||
if not IsLine then
|
||||
glColor3f(0.1, 0.7, 0.8)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f(-S, -S, S); glVertex3f( S, -S, S);
|
||||
glVertex3f( S, S, S); glVertex3f(-S, S, S);
|
||||
// ╟рфэ уЁрэ№ - ╤шэ
|
||||
if not IsLine then
|
||||
glColor3f(0.05, 0.4, 0.6)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f(-S, -S, -S); glVertex3f(-S, S, -S);
|
||||
glVertex3f( S, S, -S); glVertex3f( S, -S, -S);
|
||||
// ┬хЁїэ уЁрэ№ - ╤тхЄыю-уюыєср
|
||||
if not IsLine then
|
||||
glColor3f(0.2, 0.8, 1.0)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f(-S, S, -S); glVertex3f(-S, S, S);
|
||||
glVertex3f( S, S, S); glVertex3f( S, S, -S);
|
||||
// ═шцэ уЁрэ№ - ╥хьэю-ёшэ
|
||||
if not IsLine then
|
||||
glColor3f(0.02, 0.2, 0.4)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f(-S, -S, -S); glVertex3f( S, -S, -S);
|
||||
glVertex3f( S, -S, S); glVertex3f(-S, -S, S);
|
||||
// ╧Ёртр уЁрэ№ }
|
||||
if not IsLine then
|
||||
glColor3f(0.08, 0.5, 0.7)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f( S, -S, -S); glVertex3f( S, S, -S);
|
||||
glVertex3f( S, S, S); glVertex3f( S, -S, S);
|
||||
// ╦хтр уЁрэ№ }
|
||||
if not IsLine then
|
||||
glColor3f(0.06, 0.45, 0.65)
|
||||
else
|
||||
glColor3f(0.5, 0.5, 0.5);
|
||||
glVertex3f(-S, -S, -S); glVertex3f(-S, -S, S);
|
||||
glVertex3f(-S, S, S); glVertex3f(-S, S, -S);
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
// ╨хъєЁёштэ√щ рыуюЁшЄь ухэхЁрЎшш ├єсъш ╠хэухЁр
|
||||
procedure BuildSponge(X, Y, Z, Size: GLFloat; Depth: Integer);
|
||||
var
|
||||
NewSize: GLFloat;
|
||||
dx, dy, dz: Integer;
|
||||
Sum: Integer;
|
||||
begin
|
||||
// ┼ёыш фю°ыш фю яЁхфхыр ЁхъєЁёшш Ч Ёшёєхь ёяыю°эющ ъєсшъ т ¤Єшї ъююЁфшэрЄрї
|
||||
if Depth = MAX_DEPTH then
|
||||
begin
|
||||
glPushMatrix();
|
||||
glTranslatef(X, Y, Z);
|
||||
DrawSolidCube(Size);
|
||||
glPopMatrix();
|
||||
end
|
||||
else
|
||||
begin
|
||||
NewSize := Size / 3.0;
|
||||
// ╧хЁхсшЁрхь ёхЄъє 3x3x3
|
||||
for dx := -1 to 1 do
|
||||
for dy := -1 to 1 do
|
||||
for dz := -1 to 1 do
|
||||
begin
|
||||
// ┬√ўшёы хь ьрЄхьрЄшўхёъюх єёыютшх яєёЄюЄ√ фы ├єсъш ╠хэухЁр
|
||||
Sum := 0;
|
||||
if dx = 0 then Inc(Sum);
|
||||
if dy = 0 then Inc(Sum);
|
||||
if dz = 0 then Inc(Sum);
|
||||
// ┼ёыш сюыхх ўхь юфэр ъююЁфшэрЄр Ёртэр 0, ¤Єю ёътючэюх юЄтхЁёЄшх Ч яЁюяєёърхь хую
|
||||
if Sum < 2 then
|
||||
begin
|
||||
BuildSponge(
|
||||
X + dx * NewSize,
|
||||
Y + dy * NewSize,
|
||||
Z + dz * NewSize,
|
||||
NewSize,
|
||||
Depth + 1
|
||||
);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
Pulse: GLFloat;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.03, 0.04, 0.06, 0.0); // ├ыєсюъшщ ъюёьшўхёъшщ Їюэ
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glTranslatef(0.0, 0.0, ZTr);
|
||||
|
||||
// ┬Ёр∙рхь ЇЁръЄры яю фтєь юё ь фы яюыэюЎхээюую 3D юсчюЁр
|
||||
glRotatef(Rotation, 0.5, 1.0, 0.2);
|
||||
|
||||
// ┬√ўшёы хь Їшчшўхёъє■ яєы№ёрЎш■ ЁрчьхЁр юЄ тЁхьхэш
|
||||
Pulse := 1.8 + Sin(TimeVal) * 0.25;
|
||||
|
||||
// ╟ряєёъ ухэхЁрЎшш ЇЁръЄрыр шч ЎхэЄЁр (0,0,0) ё фшэрьшўхёъшь ЁрчьхЁюь
|
||||
IsLine := False;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Ёшёєхь ё чрыштъющ
|
||||
BuildSponge(0.0, 0.0, 0.0, Pulse, 0);
|
||||
IsLine := True;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Ёшёєхь ъюэЄєЁэ√х ышэшш
|
||||
BuildSponge(0.0, 0.0, 0.0, Pulse, 0);
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
Rotation := Rotation + Speed;
|
||||
TimeVal := TimeVal + 0.03;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Menger Sponge 3D Fractal', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,218 @@
|
||||
program ParticleCubeFountain;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
MAX_PARTICLES = 100; // ьръёшьры№эюх ъюышўхёЄтю ъєсшъют
|
||||
|
||||
// ═└╤╥╨╬╔╩└ ╘╚╟╚╩╚
|
||||
GRAVITY = 0.0066; // ╤шыр Є цхёЄш: ўхь ьхэ№°х, Єхь т√°х тчыхЄрхЄ ЇюэЄрэ
|
||||
BOUNCE_FACTOR = 0.70; // ╩ю¤ЇЇшЎшхэЄ юЄёъюър: 0.70 ючэрўрхЄ ёюїЁрэхэшх 70% т√ёюЄ√ яЁ√цър
|
||||
FLOOR_Y = -3.0; // ╙Ёютхэ№ яюыр, юЄ ъюЄюЁюую юЄёъръштр■Є ъєсшъш
|
||||
|
||||
type
|
||||
TParticle = record
|
||||
X, Y, Z: GLFloat;
|
||||
VX, VY, VZ: GLFloat;
|
||||
R, G, B: GLFloat;
|
||||
Life: GLFloat;
|
||||
end;
|
||||
|
||||
var
|
||||
Particles: array[1..MAX_PARTICLES] of TParticle;
|
||||
Rotation: GLFloat = 0;
|
||||
Speed: GLFloat = 0.8;
|
||||
ZTr: GLFloat = -15.0;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
procedure ResetParticle(Index: Integer);
|
||||
begin
|
||||
Particles[Index].X := 0.0;
|
||||
Particles[Index].Y := -1.5;
|
||||
Particles[Index].Z := 0.0;
|
||||
|
||||
Particles[Index].VX := ((Index mod 11) - 5) * 0.012;
|
||||
Particles[Index].VY := 0.10 + (Index mod 7) * 0.012; // ═рўры№эр ёъюЁюёЄ№ ттхЁї
|
||||
Particles[Index].VZ := ((Index mod 13) - 6) * 0.012;
|
||||
|
||||
// ═рё√∙хээ√х ЎтхЄр (ёьхё№ ЇшюыхЄютюую, ёшэхую ш сшЁ■чютюую фы ЁрчэююсЁрчш )
|
||||
Particles[Index].R := 0.2 + (Index mod 4) * 0.2;
|
||||
Particles[Index].G := 0.4 + (Index mod 6) * 0.1;
|
||||
Particles[Index].B := 0.8 + (Index mod 3) * 0.1;
|
||||
|
||||
Particles[Index].Life := 1.0;
|
||||
end;
|
||||
|
||||
procedure InitParticles;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
for I := 1 to MAX_PARTICLES do
|
||||
ResetParticle(I);
|
||||
end;
|
||||
|
||||
procedure UpdatePhysics;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
for I := 1 to MAX_PARTICLES do
|
||||
begin
|
||||
Particles[I].X := Particles[I].X + Particles[I].VX;
|
||||
Particles[I].Y := Particles[I].Y + Particles[I].VY;
|
||||
Particles[I].Z := Particles[I].Z + Particles[I].VZ;
|
||||
|
||||
// ╧Ёшьхэ хь эрёЄЁрштрхьє■ уЁртшЄрЎш■
|
||||
Particles[I].VY := Particles[I].VY - GRAVITY;
|
||||
|
||||
// ╬Єёъюъ юЄ яюыр ё єўхЄюь эрёЄЁрштрхь√ї ярЁрьхЄЁют
|
||||
if Particles[I].Y < FLOOR_Y then
|
||||
begin
|
||||
Particles[I].Y := FLOOR_Y;
|
||||
Particles[I].VY := -Particles[I].VY * BOUNCE_FACTOR;
|
||||
end;
|
||||
|
||||
Particles[I].Life := Particles[I].Life - 0.006;
|
||||
|
||||
if Particles[I].Life <= 0.0 then
|
||||
ResetParticle(I);
|
||||
end;
|
||||
end;
|
||||
|
||||
// яЁюЎхфєЁр юЄЁшёютъш 3D-ъєср ё уЁрэ ьш
|
||||
procedure DrawCube(R, G, B: GLFloat);
|
||||
begin
|
||||
glBegin(GL_QUADS);
|
||||
// ╧хЁхфэ уЁрэ№
|
||||
glColor3f(R, G, B);
|
||||
glVertex3f(-1.0, -1.0, 1.0); glVertex3f( 1.0, -1.0, 1.0);
|
||||
glVertex3f( 1.0, 1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
|
||||
// ╟рфэ уЁрэ№
|
||||
glColor3f(R * 0.8, G * 0.8, B * 0.8); // ╫єЄ№ Єхьэхх фы юс·хьр
|
||||
glVertex3f(-1.0, -1.0, -1.0); glVertex3f(-1.0, 1.0, -1.0);
|
||||
glVertex3f( 1.0, 1.0, -1.0); glVertex3f( 1.0, -1.0, -1.0);
|
||||
// ┬хЁїэ уЁрэ№
|
||||
glColor3f(R * 0.9, G * 0.9, B * 0.9);
|
||||
glVertex3f(-1.0, 1.0, -1.0); glVertex3f(-1.0, 1.0, 1.0);
|
||||
glVertex3f( 1.0, 1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0);
|
||||
// ═шцэ уЁрэ№
|
||||
glColor3f(R * 0.6, G * 0.6, B * 0.6);
|
||||
glVertex3f(-1.0, -1.0, -1.0); glVertex3f( 1.0, -1.0, -1.0);
|
||||
glVertex3f( 1.0, -1.0, 1.0); glVertex3f(-1.0, -1.0, 1.0);
|
||||
// ╧Ёртр уЁрэ№
|
||||
glColor3f(R * 0.85, G * 0.85, B * 0.85);
|
||||
glVertex3f( 1.0, -1.0, -1.0); glVertex3f( 1.0, 1.0, -1.0);
|
||||
glVertex3f( 1.0, 1.0, 1.0); glVertex3f( 1.0, -1.0, 1.0);
|
||||
// ╦хтр уЁрэ№
|
||||
glColor3f(R * 0.75, G * 0.75, B * 0.75);
|
||||
glVertex3f(-1.0, -1.0, -1.0); glVertex3f(-1.0, -1.0, 1.0);
|
||||
glVertex3f(-1.0, 1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
I: Integer;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.05, 0.05, 0.1, 0.0); // ├ыєсюъшщ яюыєэюўэ√щ Їюэ
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glTranslatef(0.0, 0.0, ZTr);
|
||||
glRotatef(Rotation, 0.0, 1.0, 0.0); // ┬Ёр∙хэшх ёЎхэ√ яю юёш Y
|
||||
|
||||
// ╬ЄЁшёютър яыюёъюёЄш яюыр
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(0.25, 0.25, 0.45);
|
||||
glVertex3f(-6.0, FLOOR_Y, 6.0);
|
||||
glVertex3f( 6.0, FLOOR_Y, 6.0);
|
||||
glVertex3f( 6.0, FLOOR_Y, -6.0);
|
||||
glVertex3f(-6.0, FLOOR_Y, -6.0);
|
||||
glEnd();
|
||||
|
||||
// ╓шъы юЄЁшёютъш 3D-ъєсшъют
|
||||
for I := 1 to MAX_PARTICLES do
|
||||
begin
|
||||
glPushMatrix();
|
||||
glTranslatef(Particles[I].X, Particles[I].Y, Particles[I].Z);
|
||||
// ┬Ёр∙рхь ърцф√щ ъєсшъ тюъЁєу ётюхщ юёш фы фшэрьшъш
|
||||
glRotatef(Rotation * 2.5 + I, 0.4, 0.8, 0.2);
|
||||
// ╠рё°ЄрсшЁєхь ъєс яЁюяюЁЎшюэры№эю хую тЁхьхэш цшчэш
|
||||
glScalef(Particles[I].Life * 0.25, Particles[I].Life * 0.25, Particles[I].Life * 0.25);
|
||||
// ┬√чют ърёЄюьэющ юЄЁшёютъш ухюьхЄЁшш
|
||||
DrawCube(Particles[I].R, Particles[I].G, Particles[I].B);
|
||||
glPopMatrix();
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
UpdatePhysics;
|
||||
Rotation := Rotation + Speed;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
InitParticles;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'TinyGL 3D Cube Fountain', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,226 @@
|
||||
program RubikRotate3D;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
CUBE_DIST = 0.72; // ╨рёёЄю эшх ьхцфє ЎхэЄЁрьш ъєсшъют
|
||||
|
||||
type
|
||||
TVertex3D = record
|
||||
X, Y, Z: GLFloat;
|
||||
end;
|
||||
|
||||
var
|
||||
Rotation: GLFloat = 0;
|
||||
CamSpeed: GLFloat = 0.5;
|
||||
ZTr: GLFloat = -6.5;
|
||||
TimeVal: GLFloat = 0;
|
||||
|
||||
// ╧рЁрьхЄЁ√ рэшьрЎшш ёыюхт
|
||||
LayerAngle: GLFloat = 0;
|
||||
ActiveAxis: Integer = 0; // 0 = X, 1 = Y, 2 = Z
|
||||
ActiveLayer: Integer = -1; // -1 = ыхт√щ, 0 = ЎхэЄЁры№э√щ, 1 = яЁрт√щ
|
||||
|
||||
CTX: TKOSGLContext;
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
// ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
// тЁр∙хэшх юфэющ 3D Єюўъш яю юё ь X, Y шыш Z
|
||||
procedure RotatePoint(var Px, Py, Pz: GLFloat; Axis: Integer; AngleDegrees: GLFloat);
|
||||
var
|
||||
Rad, CosA, SinA, Tx, Ty, Tz: GLFloat;
|
||||
begin
|
||||
Rad := AngleDegrees * PI / 180.0;
|
||||
CosA := Cos(Rad);
|
||||
SinA := Sin(Rad);
|
||||
Tx := Px; Ty := Py; Tz := Pz;
|
||||
|
||||
if Axis = 0 then { ┬юъЁєу X }
|
||||
begin
|
||||
Py := Ty * CosA - Tz * SinA;
|
||||
Pz := Ty * SinA + Tz * CosA;
|
||||
end
|
||||
else if Axis = 1 then { ┬юъЁєу Y }
|
||||
begin
|
||||
Px := Tx * CosA + Tz * SinA;
|
||||
Pz := -Tx * SinA + Tz * CosA;
|
||||
end
|
||||
else if Axis = 2 then { ┬юъЁєу Z }
|
||||
begin
|
||||
Px := Tx * CosA - Ty * SinA;
|
||||
Py := Tx * SinA + Ty * CosA;
|
||||
end;
|
||||
end;
|
||||
|
||||
// ╬ЄЁшёютър ъєср ё тэ√ь ЁрёўхЄюь 8 тхЁ°шэ
|
||||
procedure DrawSubCube(S: GLFloat; GridX, GridY, GridZ: Integer; R, G, B: GLFloat);
|
||||
var
|
||||
Pts: array[0..7] of TVertex3D;
|
||||
I: Integer;
|
||||
IsLayerActive: Boolean;
|
||||
begin
|
||||
IsLayerActive := False;
|
||||
if (ActiveAxis = 0) and (GridX = ActiveLayer) then IsLayerActive := True;
|
||||
if (ActiveAxis = 1) and (GridY = ActiveLayer) then IsLayerActive := True;
|
||||
if (ActiveAxis = 2) and (GridZ = ActiveLayer) then IsLayerActive := True;
|
||||
|
||||
// ╟рфрхь ыюъры№э√х ъююЁфшэрЄ√ ъєср
|
||||
Pts[0].X := -S; Pts[0].Y := -S; Pts[0].Z := S;
|
||||
Pts[1].X := S; Pts[1].Y := -S; Pts[1].Z := S;
|
||||
Pts[2].X := S; Pts[2].Y := S; Pts[2].Z := S;
|
||||
Pts[3].X := -S; Pts[3].Y := S; Pts[3].Z := S;
|
||||
Pts[4].X := -S; Pts[4].Y := -S; Pts[4].Z := -S;
|
||||
Pts[5].X := -S; Pts[5].Y := S; Pts[5].Z := -S;
|
||||
Pts[6].X := S; Pts[6].Y := S; Pts[6].Z := -S;
|
||||
Pts[7].X := S; Pts[7].Y := -S; Pts[7].Z := -S;
|
||||
|
||||
for I := 0 to 7 do
|
||||
begin
|
||||
// 1. ╤эрўрыр ёфтшурхь ¤ыхьхэЄ√ эр Ёрфшєё юЁсшЄ√
|
||||
Pts[I].X := Pts[I].X + (GridX * CUBE_DIST);
|
||||
Pts[I].Y := Pts[I].Y + (GridY * CUBE_DIST);
|
||||
Pts[I].Z := Pts[I].Z + (GridZ * CUBE_DIST);
|
||||
|
||||
// 2. ┼ёыш ъєсшъ т ръЄштэюь ёыюх, тЁр∙рхь хую ёЄЁюую т ыюъры№э√ї юё ї
|
||||
if IsLayerActive then
|
||||
RotatePoint(Pts[I].X, Pts[I].Y, Pts[I].Z, ActiveAxis, LayerAngle);
|
||||
end;
|
||||
|
||||
{ ┬√тюфшь 6 уЁрэхщ }
|
||||
glBegin(GL_QUADS);
|
||||
{ ╧хЁхфэ }
|
||||
glColor3f(R, G, B);
|
||||
glVertex3f(Pts[0].X, Pts[0].Y, Pts[0].Z); glVertex3f(Pts[1].X, Pts[1].Y, Pts[1].Z);
|
||||
glVertex3f(Pts[2].X, Pts[2].Y, Pts[2].Z); glVertex3f(Pts[3].X, Pts[3].Y, Pts[3].Z);
|
||||
{ ╟рфэ }
|
||||
glColor3f(R * 0.5, G * 0.5, B * 0.5);
|
||||
glVertex3f(Pts[4].X, Pts[4].Y, Pts[4].Z); glVertex3f(Pts[5].X, Pts[5].Y, Pts[5].Z);
|
||||
glVertex3f(Pts[6].X, Pts[6].Y, Pts[6].Z); glVertex3f(Pts[7].X, Pts[7].Y, Pts[7].Z);
|
||||
{ ┬хЁїэ }
|
||||
glColor3f(R * 0.9, G * 0.9, B * 0.9);
|
||||
glVertex3f(Pts[5].X, Pts[5].Y, Pts[5].Z); glVertex3f(Pts[3].X, Pts[3].Y, Pts[3].Z);
|
||||
glVertex3f(Pts[2].X, Pts[2].Y, Pts[2].Z); glVertex3f(Pts[6].X, Pts[6].Y, Pts[6].Z);
|
||||
{ ═шцэ }
|
||||
glColor3f(R * 0.3, G * 0.3, B * 0.3);
|
||||
glVertex3f(Pts[4].X, Pts[4].Y, Pts[4].Z); glVertex3f(Pts[7].X, Pts[7].Y, Pts[7].Z);
|
||||
glVertex3f(Pts[1].X, Pts[1].Y, Pts[1].Z); glVertex3f(Pts[0].X, Pts[0].Y, Pts[0].Z);
|
||||
{ ╧Ёртр }
|
||||
glColor3f(R * 0.8, G * 0.8, B * 0.8);
|
||||
glVertex3f(Pts[7].X, Pts[7].Y, Pts[7].Z); glVertex3f(Pts[6].X, Pts[6].Y, Pts[6].Z);
|
||||
glVertex3f(Pts[2].X, Pts[2].Y, Pts[2].Z); glVertex3f(Pts[1].X, Pts[1].Y, Pts[1].Z);
|
||||
{ ╦хтр }
|
||||
glColor3f(R * 0.6, G * 0.6, B * 0.6);
|
||||
glVertex3f(Pts[4].X, Pts[4].Y, Pts[4].Z); glVertex3f(Pts[0].X, Pts[0].Y, Pts[0].Z);
|
||||
glVertex3f(Pts[3].X, Pts[3].Y, Pts[3].Z); glVertex3f(Pts[5].X, Pts[5].Y, Pts[5].Z);
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
procedure UpdateRubikLogic;
|
||||
begin
|
||||
LayerAngle := LayerAngle + 3.0;
|
||||
if LayerAngle >= 90.0 then
|
||||
begin
|
||||
LayerAngle := 0;
|
||||
Inc(ActiveLayer);
|
||||
if ActiveLayer > 1 then
|
||||
begin
|
||||
ActiveLayer := -1;
|
||||
ActiveAxis := (ActiveAxis + 1) mod 3;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
X, Y, Z: Integer;
|
||||
R_Clr, G_Clr, B_Clr: GLFloat;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.03, 0.03, 0.06, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
// ╠╚╨╬┬█┼ ╥╨└═╤╘╬╨╠└╓╚╚ (┬Ёр∙хэшх ърьхЁ√ тюъЁєу тёхщ ёЎхэ√)
|
||||
glTranslatef(0.0, 0.0, ZTr);
|
||||
glRotatef(25.0 + Rotation * 0.4, 1.0, 0.0, 0.0);
|
||||
glRotatef(35.0 + Rotation, 0.0, 1.0, 0.0);
|
||||
|
||||
// ╤┴╬╨╩└ ╚ ╬╥╨╚╤╬┬╩└ ╤┼╥╩╚
|
||||
for X := -1 to 1 do
|
||||
for Y := -1 to 1 do
|
||||
for Z := -1 to 1 do
|
||||
begin
|
||||
// ярышЄЁр эр ёшэєёрї юЄ тЁхьхэш
|
||||
R_Clr := 0.7 + Sin(TimeVal + X * 0.5) * 0.3;
|
||||
G_Clr := 0.7 + Cos(TimeVal * 0.8 + Y * 0.5) * 0.3;
|
||||
B_Clr := 0.7 + Sin(TimeVal * 1.2 + Z * 0.5) * 0.3;
|
||||
|
||||
DrawSubCube(0.26, X, Y, Z, R_Clr, G_Clr, B_Clr);
|
||||
end;
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
UpdateRubikLogic;
|
||||
Rotation := Rotation + CamSpeed;
|
||||
TimeVal := TimeVal + 0.03;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, '3D Rubik Rotate', $00FFFFFF,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT: GetKey;
|
||||
BUTTON_EVENT: if GetButton.ID = 1 then ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,193 @@
|
||||
program SierpinskiTinyGL;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
|
||||
type
|
||||
Point3D = record
|
||||
X, Y, Z: GLFloat;
|
||||
end;
|
||||
|
||||
const
|
||||
{ ╩ююЁфшэрЄ√ срчютюую ЄхЄЁр¤фЁр }
|
||||
TopV: Point3D = (X: 0.0; Y: -1.0; Z: 0.0);
|
||||
LeftV: Point3D = (X: -1.0; Y: 0.7; Z: -0.5);
|
||||
RightV: Point3D = (X: 1.0; Y: 0.7; Z: -0.5);
|
||||
BackV: Point3D = (X: 0.0; Y: 0.7; Z: 1.0);
|
||||
|
||||
var
|
||||
AngleX: GLFloat = 0.5;
|
||||
AngleY: GLFloat = 0.5;
|
||||
TimeColor: GLFloat = 0.0;
|
||||
TimeDepth: GLFloat = 0.0;
|
||||
CTX: TKOSGLContext;
|
||||
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
IsLine: Boolean;
|
||||
|
||||
{ ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√ }
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLDouble);
|
||||
var
|
||||
fW, fH, fovYPI360: GLDouble;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
function Midpoint(P1, P2: Point3D): Point3D;
|
||||
begin
|
||||
Result.X := (P1.X + P2.X) / 2;
|
||||
Result.Y := (P1.Y + P2.Y) / 2;
|
||||
Result.Z := (P1.Z + P2.Z) / 2;
|
||||
end;
|
||||
|
||||
{ т√ўшёы хЄ цшфъшщ уЁрфшхэЄэ√щ ЎтхЄ яю ъююЁфшэрЄрь Єюўъш
|
||||
ш яхЁхфр╕Є тхЁ°шэє т TinyGL }
|
||||
procedure GlColorVertex(P: Point3D);
|
||||
var
|
||||
R, G, B: GLFloat;
|
||||
begin
|
||||
{ ╞шфъшщ уЁрфшхэЄ}
|
||||
R := sin(P.X * 2 + TimeColor) * 0.5 + 0.5;
|
||||
G := sin(P.Y * 2 + TimeColor * 1.5) * 0.5 + 0.5;
|
||||
B := cos(P.Z * 2 + TimeColor) * 0.5 + 0.5;
|
||||
|
||||
if not IsLine then
|
||||
glColor3f(R, G, B)
|
||||
else
|
||||
glColor3f(1 - R * 0.25, 1 - G * 0.25, 1 - B * 0.25);
|
||||
|
||||
glVertex3f(P.X, P.Y, P.Z);
|
||||
end;
|
||||
|
||||
procedure DrawTetrahedron(P1, P2, P3, P4: Point3D);
|
||||
begin
|
||||
GlColorVertex(P1); GlColorVertex(P2); GlColorVertex(P3);
|
||||
GlColorVertex(P1); GlColorVertex(P3); GlColorVertex(P4);
|
||||
GlColorVertex(P1); GlColorVertex(P4); GlColorVertex(P2);
|
||||
GlColorVertex(P2); GlColorVertex(P3); GlColorVertex(P4);
|
||||
end;
|
||||
|
||||
procedure Sierpinski3D(P1, P2, P3, P4: Point3D; Depth: Integer);
|
||||
var
|
||||
M12, M23, M31, M14, M24, M34: Point3D;
|
||||
begin
|
||||
if Depth = 0 then
|
||||
DrawTetrahedron(P1, P2, P3, P4)
|
||||
else
|
||||
begin
|
||||
M12 := Midpoint(P1, P2);
|
||||
M23 := Midpoint(P2, P3);
|
||||
M31 := Midpoint(P3, P1);
|
||||
M14 := Midpoint(P1, P4);
|
||||
M24 := Midpoint(P2, P4);
|
||||
M34 := Midpoint(P3, P4);
|
||||
|
||||
Sierpinski3D(P1, M12, M31, M14, Depth - 1);
|
||||
Sierpinski3D(M12, P2, M23, M24, Depth - 1);
|
||||
Sierpinski3D(M31, M23, P3, M34, Depth - 1);
|
||||
Sierpinski3D(M14, M24, M34, P4, Depth - 1);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
CurrentDepth: Integer;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 0.1, 100.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
{ ╩рьхЁр }
|
||||
glTranslatef(0.0, 0.0, -3.5);
|
||||
|
||||
{ ┬Ёр∙хэшх }
|
||||
glRotatef(AngleX * (180 / PI), 1.0, 0.0, 0.0);
|
||||
glRotatef(AngleY * (180 / PI), 0.0, 1.0, 0.0);
|
||||
|
||||
{ ╚чьхэхэшх уыєсшэ√ ЇЁръЄрыр }
|
||||
CurrentDepth := Trunc(2.5 + Sin(TimeDepth) * 1.6);
|
||||
if CurrentDepth < 1 then CurrentDepth := 1;
|
||||
if CurrentDepth > 4 then CurrentDepth := 4;
|
||||
|
||||
{ Ёшёєхь ё чрыштъющ }
|
||||
IsLine := False;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glBegin(GL_TRIANGLES);
|
||||
Sierpinski3D(TopV, LeftV, RightV, BackV, CurrentDepth);
|
||||
glEnd();
|
||||
|
||||
{ Ёшёєхь ъюэЄєЁэ√х ышэшш }
|
||||
IsLine := True;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glBegin(GL_TRIANGLES);
|
||||
Sierpinski3D(TopV, LeftV, RightV, BackV, CurrentDepth);
|
||||
glEnd();
|
||||
|
||||
kosglSwapBuffers();
|
||||
|
||||
{ ╬сэютыхэшх єуыют }
|
||||
AngleX := AngleX + 0.003;
|
||||
AngleY := AngleY + 0.007;
|
||||
|
||||
TimeColor := TimeColor + 0.02;
|
||||
TimeDepth := TimeDepth + 0.008;
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 3 * 2;
|
||||
WndHeight := Height div 3 * 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight,
|
||||
'Sierpinski 3D', $00000000,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION,
|
||||
CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
@@ -0,0 +1,281 @@
|
||||
program WaveMesh;
|
||||
|
||||
uses
|
||||
KolibriOS, TinyGL;
|
||||
|
||||
const
|
||||
// --- ╤┼╩╓╚▀ ╩╬═╤╥└═╥ ---
|
||||
GRID_SIZE = 45;
|
||||
TOTAL_POINTS = 2025; // 45 * 45 тхЁ°шэ
|
||||
SPACING = 11; // ╪ру ёхЄъш
|
||||
PHI = 1.6180339887; // ╟юыюЄюх ёхўхэшх
|
||||
|
||||
var
|
||||
CTX: TKOSGLContext;
|
||||
WndLeft, WndTop, WndWidth, WndHeight: LongInt;
|
||||
|
||||
// --- ╤┼╩╓╚▀ ├╦╬┴└╦▄═█╒ ╠└╤╤╚┬╬┬ ---
|
||||
Points_GridX: array[0..TOTAL_POINTS - 1] of GLint;
|
||||
Points_GridZ: array[0..TOTAL_POINTS - 1] of GLint;
|
||||
Points_LocalX: array[0..TOTAL_POINTS - 1] of GLFloat;
|
||||
Points_LocalZ: array[0..TOTAL_POINTS - 1] of GLFloat;
|
||||
|
||||
// ╒Ёрэшь ЄЁхїьхЁэ√х ъююЁфшэрЄ√ фы яхЁхфрўш т ъюэтхщхЁ TinyGL
|
||||
Render_X: array[0..TOTAL_POINTS - 1] of GLFloat;
|
||||
Render_Y: array[0..TOTAL_POINTS - 1] of GLFloat;
|
||||
Render_Z: array[0..TOTAL_POINTS - 1] of GLFloat;
|
||||
Render_ColorIdx: array[0..TOTAL_POINTS - 1] of GLint;
|
||||
|
||||
LookupTable: array[0..(GRID_SIZE * GRID_SIZE) - 1] of GLint;
|
||||
|
||||
// ╧ЁхюсЁрчютрээр ярышЄЁр фы TinyGL: їЁрэшЄ R, G, B ъюьяюэхэЄ√ юЄ 0.0 фю 1.0
|
||||
MeshPaletteR: array[0..255] of GLfloat;
|
||||
MeshPaletteG: array[0..255] of GLfloat;
|
||||
MeshPaletteB: array[0..255] of GLfloat;
|
||||
|
||||
// --- ╤┼╩╓╚▀ ╧╨╬╤╥█╒ ╧┼╨┼╠┼══█╒ ---
|
||||
Frame: GLint = 0;
|
||||
Out_X: GLFloat = 0.0;
|
||||
Out_Y: GLFloat = 0.0;
|
||||
Out_Z: GLFloat = 0.0;
|
||||
|
||||
// ├ыюсры№э√х яхЁхьхээ√х фы яЁхфЁрёўшЄрээющ ЄЁшуюэюьхЄЁшш ърфЁр
|
||||
CosY: GLFloat = 0.0; SinY: GLFloat = 0.0;
|
||||
CosX: GLFloat = 0.0; SinX: GLFloat = 0.0;
|
||||
|
||||
{ ═рёЄЁющър яхЁёяхъЄшт√ ърьхЁ√ }
|
||||
procedure Perspective(fovY, Aspect, zNear, zFar: GLFloat);
|
||||
var
|
||||
fW, fH, fovYPI360: GLFloat;
|
||||
M: array[0..15] of GLFloat;
|
||||
begin
|
||||
FillChar(M, SizeOf(M), #0);
|
||||
fovYPI360 := fovY * PI / 360;
|
||||
fH := Sin(fovYPI360) * zNear / Cos(fovYPI360);
|
||||
fW := fH * Aspect;
|
||||
M[0] := zNear / fW;
|
||||
M[5] := zNear / fH;
|
||||
M[10] := -(zFar + zNear) / (zFar - zNear);
|
||||
M[11] := -1;
|
||||
M[14] := -2 * zFar * zNear / (zFar - zNear);
|
||||
glLoadMatrixf(@M[0]);
|
||||
end;
|
||||
|
||||
// --- ═└╤╥╨╬╔╩└ ╨└─╙╞═╬╔ ╧└╦╚╥╨█ ═└ 256 ╓┬┼╥╬┬ ---
|
||||
procedure Setup256Palette;
|
||||
var
|
||||
C, Sector, Step: Integer;
|
||||
R, G, B: Byte;
|
||||
begin
|
||||
for C := 0 to 255 do
|
||||
begin
|
||||
Sector := Trunc((C / 256.0) * 6.0);
|
||||
Step := Trunc(((C / 256.0) * 6.0 - Sector) * 255.0);
|
||||
|
||||
if Sector = 0 then begin R := 255; G := Step; B := 0; end
|
||||
else if Sector = 1 then begin R := 255 - Step; G := 255; B := 0; end
|
||||
else if Sector = 2 then begin R := 0; G := 255; B := Step; end
|
||||
else if Sector = 3 then begin R := 0; G := 255 - Step; B := 255; end
|
||||
else if Sector = 4 then begin R := Step; G := 0; B := 255; end
|
||||
else begin R := 255; G := 0; B := 255 - Step; end;
|
||||
|
||||
// ╧хЁхтюфшь ЎтхЄр т фшрярчюэ 0.0 - 1.0 фы TinyGL
|
||||
MeshPaletteR[C] := R / 255.0;
|
||||
MeshPaletteG[C] := G / 255.0;
|
||||
MeshPaletteB[C] := B / 255.0;
|
||||
end;
|
||||
end;
|
||||
|
||||
// --- ═└╫└╦▄═└▀ ╚═╚╓╚└╦╚╟└╓╚▀ ╤┼╥╩╚ ---
|
||||
procedure InitializeGrid;
|
||||
var
|
||||
X, Z, Idx: Integer;
|
||||
StartOffset: GLFloat;
|
||||
begin
|
||||
StartOffset := -((GRID_SIZE - 1) * SPACING) / 2.0;
|
||||
Idx := 0;
|
||||
for X := 0 to GRID_SIZE - 1 do
|
||||
begin
|
||||
for Z := 0 to GRID_SIZE - 1 do
|
||||
begin
|
||||
Points_GridX[Idx] := X;
|
||||
Points_GridZ[Idx] := Z;
|
||||
Points_LocalX[Idx] := StartOffset + X * SPACING;
|
||||
Points_LocalZ[Idx] := StartOffset + Z * SPACING;
|
||||
LookupTable[Z * GRID_SIZE + X] := Idx;
|
||||
Inc(Idx);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// ┬Ёр∙хэшх яю юёш Y
|
||||
procedure FastRotateY(X, Z: GLFloat);
|
||||
begin
|
||||
Out_X := X * CosY - Z * SinY;
|
||||
Out_Z := X * SinY + Z * CosY;
|
||||
end;
|
||||
|
||||
// ┬Ёр∙хэшх яю юёш X
|
||||
procedure FastRotateX(Y, Z: GLFloat);
|
||||
begin
|
||||
Out_Y := Y * CosX - Z * SinX;
|
||||
Out_Z := Y * SinX + Z * CosX;
|
||||
end;
|
||||
|
||||
// --- ╬╥╨╚╤╬┬╩└ ╦╚═╚╚ ┬ ╥╨┼╒╠┼╨═╬╠ ╧╨╬╤╥╨└═╤╥┬┼ ---
|
||||
procedure DrawLine3D(X1, Y1, Z1, X2, Y2, Z2: GLFloat; ColorIdx: GLint);
|
||||
begin
|
||||
glColor3f(MeshPaletteR[ColorIdx], MeshPaletteG[ColorIdx], MeshPaletteB[ColorIdx]);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(X1, Y1, Z1);
|
||||
glVertex3f(X2, Y2, Z2);
|
||||
glEnd();
|
||||
end;
|
||||
|
||||
procedure GLDraw;
|
||||
var
|
||||
ThreadInfo: TThreadInfo;
|
||||
I, X, Z, CurrentIdx, NextXIdx, NextZIdx, ColorIdx, AvgColor: GLint;
|
||||
LX, LZ, TrueDistance, LogDist, Wave1, Wave2, TrueHeightY: GLFloat;
|
||||
RotY_X, RotY_Z, RotX_Y, RotX_Z: GLFloat;
|
||||
WorldRotation, CameraPitch: GLFloat;
|
||||
X1, Y1, Z1: GLFloat;
|
||||
C1, C2, C3: GLint;
|
||||
begin
|
||||
GetThreadInfo($FFFFFFFF, ThreadInfo);
|
||||
if ThreadInfo.Client.Height <= 3 then Exit;
|
||||
|
||||
// ╚эшЎшрышчшЁєхь ъюэЄхъёЄ яюф Єхъє∙шх ЁрчьхЁ√ юъэр
|
||||
kosglMakeCurrent(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height, CTX);
|
||||
glViewPort(0, 0, ThreadInfo.Client.Width, ThreadInfo.Client.Height);
|
||||
|
||||
// ╬ўш∙рхь ¤ъЁрэ ўхЁэ√ь ЎтхЄюь ш ёсЁрё√трхь сєЇхЁ уыєсшэ√
|
||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST); // ┬ъы■ўрхь ЄхёЄ уыєсшэ√ фы ъюЁЁхъЄэюую яхЁхъЁ√Єш ышэшщ т 3D
|
||||
|
||||
// ═рёЄЁрштрхь яхЁёяхъЄштэє■ яЁюхъЎш■
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
Perspective(45.0, ThreadInfo.Client.Width / ThreadInfo.Client.Height, 1.0, 2000.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
Inc(Frame);
|
||||
|
||||
// ┬√ўшёы хь єуы√ тЁр∙хэш ьрЄхьрЄшўхёъющ ёхЄъш
|
||||
WorldRotation := Frame * 0.005;
|
||||
CameraPitch := 0.6 + Sin(Frame * 0.01) * 0.15;
|
||||
|
||||
// ╧ЁхфЁрёўхЄ ЄЁшуюэюьхЄЁшш
|
||||
CosY := Cos(WorldRotation); SinY := Sin(WorldRotation);
|
||||
CosX := Cos(CameraPitch); SinX := Sin(CameraPitch);
|
||||
|
||||
// ╪└├ 1: ╠рЄхьрЄшўхёъшщ ЁрёўхЄ тюыэ ш ЄЁхїьхЁэ√ї ъююЁфшэрЄ тхЁ°шэ
|
||||
for I := 0 to TOTAL_POINTS - 1 do
|
||||
begin
|
||||
LX := Points_LocalX[I];
|
||||
LZ := Points_LocalZ[I];
|
||||
|
||||
// ┬√ўшёы хь Ёрфшры№эюх ЁрёёЄю эшх юЄ ЎхэЄЁр ёхЄъш
|
||||
TrueDistance := Sqrt(LX * LX + LZ * LZ);
|
||||
|
||||
// ╨рёўхЄ т√ёюЄ√ тюыэ√ яю ЇюЁьєых ╟юыюЄюую ёхўхэш (PHI)
|
||||
LogDist := TrueDistance * 0.035;
|
||||
Wave1 := Sin(LogDist - Frame * 0.04) * 22.0;
|
||||
Wave2 := Sin((LogDist * PHI) - (Frame * 0.04 / PHI)) * (22.0 / PHI);
|
||||
TrueHeightY := Wave1 + Wave2;
|
||||
|
||||
// ┬Ёр∙хэшх яю юёш Y
|
||||
FastRotateY(LX, LZ);
|
||||
RotY_X := Out_X;
|
||||
RotY_Z := Out_Z;
|
||||
|
||||
// ┬Ёр∙хэшх яю юёш X (эръыюэ)
|
||||
FastRotateX(TrueHeightY, RotY_Z);
|
||||
RotX_Y := Out_Y;
|
||||
RotX_Z := Out_Z;
|
||||
|
||||
// ╤юїЁрэ хь т√ўшёыхээ√х 3D-ъююЁфшэрЄ√.
|
||||
// ╤фтшурхь ёЎхэє яю юёш Z эр -600.0 хфшэшЎ туыєс№ ¤ъЁрэр, ўЄюс√ юэр яюярыр тю ЇЁєёЄєь ърьхЁ√.
|
||||
Render_X[I] := RotY_X;
|
||||
Render_Y[I] := RotX_Y;
|
||||
Render_Z[I] := RotX_Z - 600.0;
|
||||
|
||||
// ═юЁьрышчєхь т√ёюЄє т шэфхъё ЎтхЄр ярышЄЁ√ юЄ 0 фю 255
|
||||
ColorIdx := Trunc(((TrueHeightY + 35.0) / 70.0) * 255.0);
|
||||
if ColorIdx < 0 then ColorIdx := 0;
|
||||
if ColorIdx > 255 then ColorIdx := 255;
|
||||
Render_ColorIdx[I] := ColorIdx;
|
||||
end;
|
||||
|
||||
// ╪└├ 2: ╬ЄЁшёютър ЁхсхЁ ёхЄъш т 3D яЁюёЄЁрэёЄтх
|
||||
for X := 0 to GRID_SIZE - 1 do
|
||||
begin
|
||||
for Z := 0 to GRID_SIZE - 1 do
|
||||
begin
|
||||
CurrentIdx := LookupTable[Z * GRID_SIZE + X];
|
||||
X1 := Render_X[CurrentIdx];
|
||||
Y1 := Render_Y[CurrentIdx];
|
||||
Z1 := Render_Z[CurrentIdx];
|
||||
C1 := Render_ColorIdx[CurrentIdx];
|
||||
|
||||
// ├юЁшчюэЄры№эюх ЁхсЁю ёхЄъш (ъ яЁртюьє ёюёхфє)
|
||||
if X < GRID_SIZE - 1 then
|
||||
begin
|
||||
NextXIdx := LookupTable[Z * GRID_SIZE + (X + 1)];
|
||||
C2 := Render_ColorIdx[NextXIdx];
|
||||
AvgColor := (C1 + C2) div 2;
|
||||
DrawLine3D(X1, Y1, Z1, Render_X[NextXIdx], Render_Y[NextXIdx], Render_Z[NextXIdx], AvgColor);
|
||||
end;
|
||||
|
||||
// ┬хЁЄшъры№эюх ЁхсЁю ёхЄъш (ъ эшцэхьє ёюёхфє)
|
||||
if Z < GRID_SIZE - 1 then
|
||||
begin
|
||||
NextZIdx := LookupTable[(Z + 1) * GRID_SIZE + X];
|
||||
C3 := Render_ColorIdx[NextZIdx];
|
||||
AvgColor := (C1 + C3) div 2;
|
||||
DrawLine3D(X1, Y1, Z1, Render_X[NextZIdx], Render_Y[NextZIdx], Render_Z[NextZIdx], AvgColor);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// ┬√тюфшь уюЄют√щ ърфЁ эр ¤ъЁрэ
|
||||
kosglSwapBuffers();
|
||||
end;
|
||||
|
||||
begin
|
||||
TinyGL_initialization;
|
||||
|
||||
// ╧ЁхфтрЁшЄхы№э√щ ЁрёўхЄ ярышЄЁ√ ЎтхЄют ш ъююЁфшэрЄ ёхЄъш
|
||||
Setup256Palette;
|
||||
InitializeGrid;
|
||||
|
||||
with GetScreenSize do
|
||||
begin
|
||||
WndWidth := Width div 2;
|
||||
WndHeight := Height div 2;
|
||||
WndLeft := (Width - WndWidth) div 2;
|
||||
WndTop := (Height - WndHeight) div 2;
|
||||
end;
|
||||
|
||||
while True do
|
||||
case WaitEventByTime(1) of
|
||||
REDRAW_EVENT:
|
||||
begin
|
||||
BeginDraw;
|
||||
DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Wave Mesh (TinyGL 3D)', $00000000,
|
||||
WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
|
||||
GLDraw;
|
||||
EndDraw;
|
||||
end;
|
||||
KEY_EVENT:
|
||||
GetKey;
|
||||
BUTTON_EVENT:
|
||||
if GetButton.ID = 1 then
|
||||
ExitThread;
|
||||
else
|
||||
GLDraw;
|
||||
end;
|
||||
end.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
|
||||
if exist bin rmdir /s /q bin
|
||||
mkdir bin
|
||||
|
||||
For /R %%i In (*.pas) Do (
|
||||
..\xdpk "%%i"
|
||||
)
|
||||
|
||||
:: Переносим все скомпилированные файлы .kex из подпапок в общую папку bin
|
||||
move /y *.kex bin\
|
||||
:: Если они сохраняются прямо рядом с исходниками в тех же папках, то лучше так:
|
||||
:: For /R %%i In (*.kex) Do move /y "%%i" bin\
|
||||
|
||||
pause
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,399 @@
|
||||
// XD Pascal - a 32-bit compiler for Windows
|
||||
// Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov
|
||||
|
||||
{$I-}
|
||||
{$H-}
|
||||
|
||||
unit Linker;
|
||||
|
||||
|
||||
interface
|
||||
|
||||
|
||||
uses Common, CodeGen;
|
||||
|
||||
|
||||
procedure InitializeLinker;
|
||||
procedure SetProgramEntryPoint;
|
||||
function AddImportFunc(const ImportLibName, ImportFuncName: TString): LongInt;
|
||||
procedure LinkAndWriteProgram(const ExeName: TString);
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
const
|
||||
IMGBASE = $0;
|
||||
SECTALIGN = $20;
|
||||
FILEALIGN = SECTALIGN;
|
||||
|
||||
MAXIMPORTLIBS = 100;
|
||||
MAXIMPORTS = 2000;
|
||||
|
||||
|
||||
type
|
||||
TDOSStub = array [0..127] of Byte;
|
||||
|
||||
|
||||
TPEHeader = packed record
|
||||
PE: array [0..3] of TCharacter;
|
||||
Machine: Word;
|
||||
NumberOfSections: Word;
|
||||
TimeDateStamp: LongInt;
|
||||
PointerToSymbolTable: LongInt;
|
||||
NumberOfSymbols: LongInt;
|
||||
SizeOfOptionalHeader: Word;
|
||||
Characteristics: Word;
|
||||
end;
|
||||
|
||||
|
||||
TPEOptionalHeader = packed record
|
||||
Magic: Word;
|
||||
MajorLinkerVersion: Byte;
|
||||
MinorLinkerVersion: Byte;
|
||||
SizeOfCode: LongInt;
|
||||
SizeOfInitializedData: LongInt;
|
||||
SizeOfUninitializedData: LongInt;
|
||||
AddressOfEntryPoint: LongInt;
|
||||
BaseOfCode: LongInt;
|
||||
BaseOfData: LongInt;
|
||||
ImageBase: LongInt;
|
||||
SectionAlignment: LongInt;
|
||||
FileAlignment: LongInt;
|
||||
MajorOperatingSystemVersion: Word;
|
||||
MinorOperatingSystemVersion: Word;
|
||||
MajorImageVersion: Word;
|
||||
MinorImageVersion: Word;
|
||||
MajorSubsystemVersion: Word;
|
||||
MinorSubsystemVersion: Word;
|
||||
Win32VersionValue: LongInt;
|
||||
SizeOfImage: LongInt;
|
||||
SizeOfHeaders: LongInt;
|
||||
CheckSum: LongInt;
|
||||
Subsystem: Word;
|
||||
DllCharacteristics: Word;
|
||||
SizeOfStackReserve: LongInt;
|
||||
SizeOfStackCommit: LongInt;
|
||||
SizeOfHeapReserve: LongInt;
|
||||
SizeOfHeapCommit: LongInt;
|
||||
LoaderFlags: LongInt;
|
||||
NumberOfRvaAndSizes: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TDataDirectory = packed record
|
||||
VirtualAddress: LongInt;
|
||||
Size: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TPESectionHeader = packed record
|
||||
Name: array [0..7] of TCharacter;
|
||||
VirtualSize: LongInt;
|
||||
VirtualAddress: LongInt;
|
||||
SizeOfRawData: LongInt;
|
||||
PointerToRawData: LongInt;
|
||||
PointerToRelocations: LongInt;
|
||||
PointerToLinenumbers: LongInt;
|
||||
NumberOfRelocations: Word;
|
||||
NumberOfLinenumbers: Word;
|
||||
Characteristics: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
THeaders = packed record
|
||||
Signature: array [0..7] of TCharacter;
|
||||
Version: LongInt;
|
||||
EntryPoint: LongInt;
|
||||
EndImage: LongInt;
|
||||
Memory: LongInt;
|
||||
StackTop: LongInt;
|
||||
CmdLine: LongInt;
|
||||
FilePath: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TImportLibName = array [0..15] of TCharacter;
|
||||
TImportFuncName = array [0..31] of TCharacter;
|
||||
|
||||
|
||||
TImportDirectoryTableEntry = packed record
|
||||
Characteristics: LongInt;
|
||||
TimeDateStamp: LongInt;
|
||||
ForwarderChain: LongInt;
|
||||
Name: LongInt;
|
||||
FirstThunk: LongInt;
|
||||
end;
|
||||
|
||||
|
||||
TImportNameTableEntry = packed record
|
||||
Hint: Word;
|
||||
Name: TImportFuncName;
|
||||
end;
|
||||
|
||||
|
||||
TImport = record
|
||||
LibName, FuncName: TString;
|
||||
end;
|
||||
|
||||
|
||||
TImportSectionData = record
|
||||
DirectoryTable: array [1..MAXIMPORTLIBS + 1] of TImportDirectoryTableEntry;
|
||||
LibraryNames: array [1..MAXIMPORTLIBS] of TImportLibName;
|
||||
LookupTable: array [1..MAXIMPORTS + MAXIMPORTLIBS] of LongInt;
|
||||
NameTable: array [1..MAXIMPORTS] of TImportNameTableEntry;
|
||||
NumImports, NumImportLibs: Integer;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
var
|
||||
Headers: THeaders;
|
||||
Import: array [1..MAXIMPORTS] of TImport;
|
||||
ImportSectionData: TImportSectionData;
|
||||
LastImportLibName: TString;
|
||||
ProgramEntryPoint: LongInt;
|
||||
|
||||
CodeSectionHeader_VirtualAddress: LongInt;
|
||||
DataSectionHeader_VirtualAddress: LongInt;
|
||||
BSSSectionHeader_VirtualAddress: LongInt;
|
||||
ImportSectionHeader_VirtualAddress: LongInt;
|
||||
{
|
||||
const
|
||||
DOSStub: TDOSStub =
|
||||
(
|
||||
$4D, $5A, $90, $00, $03, $00, $00, $00, $04, $00, $00, $00, $FF, $FF, $00, $00,
|
||||
$B8, $00, $00, $00, $00, $00, $00, $00, $40, $00, $00, $00, $00, $00, $00, $00,
|
||||
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
|
||||
$00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $80, $00, $00, $00,
|
||||
$0E, $1F, $BA, $0E, $00, $B4, $09, $CD, $21, $B8, $01, $4C, $CD, $21, $54, $68,
|
||||
$69, $73, $20, $70, $72, $6F, $67, $72, $61, $6D, $20, $63, $61, $6E, $6E, $6F,
|
||||
$74, $20, $62, $65, $20, $72, $75, $6E, $20, $69, $6E, $20, $44, $4F, $53, $20,
|
||||
$6D, $6F, $64, $65, $2E, $0D, $0D, $0A, $24, $00, $00, $00, $00, $00, $00, $00
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
procedure Pad(var f: file; Size, Alignment: Integer);
|
||||
var
|
||||
i: Integer;
|
||||
b: Byte;
|
||||
begin
|
||||
b := 0;
|
||||
for i := 0 to Align(Size, Alignment) - Size - 1 do
|
||||
BlockWrite(f, b, 1);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FillHeaders(CodeSize, InitializedDataSize, UninitializedDataSize, ImportSize: Integer);
|
||||
const
|
||||
PATH_SIZE = 1024;
|
||||
PARAMS_SIZE = 256;
|
||||
STACK_SIZE = 1024 * 1024;
|
||||
|
||||
begin
|
||||
FillChar(Headers, SizeOf(Headers), #0);
|
||||
|
||||
CodeSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN);
|
||||
DataSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN);
|
||||
BSSSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN) + Align(InitializedDataSize, SECTALIGN);
|
||||
ImportSectionHeader_VirtualAddress := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN) + Align(InitializedDataSize, SECTALIGN) + Align(UninitializedDataSize, SECTALIGN);
|
||||
|
||||
with Headers do
|
||||
begin
|
||||
Signature[0] := 'M';
|
||||
Signature[1] := 'E';
|
||||
Signature[2] := 'N';
|
||||
Signature[3] := 'U';
|
||||
Signature[4] := 'E';
|
||||
Signature[5] := 'T';
|
||||
Signature[6] := '0';
|
||||
Signature[7] := '1';
|
||||
Version := 1;
|
||||
EntryPoint := Align(SizeOf(Headers), SECTALIGN) + ProgramEntryPoint;
|
||||
EndImage := Align(SizeOf(Headers), SECTALIGN) + Align(CodeSize, SECTALIGN) + Align(InitializedDataSize, SECTALIGN);
|
||||
FilePath := EndImage + Align(UninitializedDataSize, SECTALIGN);
|
||||
Memory := FilePath + PATH_SIZE + PARAMS_SIZE + STACK_SIZE;
|
||||
StackTop := FilePath + PATH_SIZE + PARAMS_SIZE + STACK_SIZE;
|
||||
CmdLine := FilePath + PATH_SIZE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure InitializeLinker;
|
||||
begin
|
||||
FillChar(Import, SizeOf(Import), #0);
|
||||
FillChar(ImportSectionData, SizeOf(ImportSectionData), #0);
|
||||
LastImportLibName := '';
|
||||
ProgramEntryPoint := 0;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure SetProgramEntryPoint;
|
||||
begin
|
||||
if ProgramEntryPoint <> 0 then
|
||||
Error('Duplicate program entry point');
|
||||
|
||||
ProgramEntryPoint := GetCodeSize;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function AddImportFunc(const ImportLibName, ImportFuncName: TString): LongInt;
|
||||
begin
|
||||
with ImportSectionData do
|
||||
begin
|
||||
Inc(NumImports);
|
||||
if NumImports > MAXIMPORTS then
|
||||
Error('Maximum number of import functions exceeded');
|
||||
|
||||
Import[NumImports].LibName := ImportLibName;
|
||||
Import[NumImports].FuncName := ImportFuncName;
|
||||
|
||||
if ImportLibName <> LastImportLibName then
|
||||
begin
|
||||
Inc(NumImportLibs);
|
||||
if NumImportLibs > MAXIMPORTLIBS then
|
||||
Error('Maximum number of import libraries exceeded');
|
||||
LastImportLibName := ImportLibName;
|
||||
end;
|
||||
|
||||
Result := (NumImports - 1 + NumImportLibs - 1) * SizeOf(LongInt); // Relocatable
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FillImportSection(var ImportSize, LookupTableOffset: Integer);
|
||||
var
|
||||
ImportIndex, ImportLibIndex, LookupIndex: Integer;
|
||||
LibraryNamesOffset, NameTableOffset: Integer;
|
||||
|
||||
begin
|
||||
with ImportSectionData do
|
||||
begin
|
||||
LibraryNamesOffset := SizeOf(DirectoryTable[1]) * (NumImportLibs + 1);
|
||||
LookupTableOffset := LibraryNamesOffset + SizeOf(LibraryNames[1]) * NumImportLibs;
|
||||
NameTableOffset := LookupTableOffset + SizeOf(LookupTable[1]) * (NumImports + NumImportLibs);
|
||||
ImportSize := NameTableOffset + SizeOf(NameTable[1]) * NumImports;
|
||||
|
||||
LastImportLibName := '';
|
||||
ImportLibIndex := 0;
|
||||
LookupIndex := 0;
|
||||
|
||||
for ImportIndex := 1 to NumImports do
|
||||
begin
|
||||
// Add new import library
|
||||
if (ImportLibIndex = 0) or (Import[ImportIndex].LibName <> LastImportLibName) then
|
||||
begin
|
||||
if ImportLibIndex <> 0 then Inc(LookupIndex); // Add null entry before the first thunk of a new library
|
||||
|
||||
Inc(ImportLibIndex);
|
||||
|
||||
DirectoryTable[ImportLibIndex].Name := LibraryNamesOffset + SizeOf(LibraryNames[1]) * (ImportLibIndex - 1);
|
||||
DirectoryTable[ImportLibIndex].FirstThunk := LookupTableOffset + SizeOf(LookupTable[1]) * LookupIndex;
|
||||
|
||||
Move(Import[ImportIndex].LibName[1], LibraryNames[ImportLibIndex], Length(Import[ImportIndex].LibName));
|
||||
|
||||
LastImportLibName := Import[ImportIndex].LibName;
|
||||
end; // if
|
||||
|
||||
// Add new import function
|
||||
Inc(LookupIndex);
|
||||
if LookupIndex > MAXIMPORTS + MAXIMPORTLIBS then
|
||||
Error('Maximum number of lookup entries exceeded');
|
||||
|
||||
LookupTable[LookupIndex] := NameTableOffset + SizeOf(NameTable[1]) * (ImportIndex - 1);
|
||||
|
||||
Move(Import[ImportIndex].FuncName[1], NameTable[ImportIndex].Name, Length(Import[ImportIndex].FuncName));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FixupImportSection(VirtualAddress: LongInt);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
with ImportSectionData do
|
||||
begin
|
||||
for i := 1 to NumImportLibs do
|
||||
with DirectoryTable[i] do
|
||||
begin
|
||||
Name := Name + VirtualAddress;
|
||||
FirstThunk := FirstThunk + VirtualAddress;
|
||||
end;
|
||||
|
||||
for i := 1 to NumImports + NumImportLibs do
|
||||
if LookupTable[i] <> 0 then
|
||||
LookupTable[i] := LookupTable[i] + VirtualAddress;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure LinkAndWriteProgram(const ExeName: TString);
|
||||
var
|
||||
OutFile: TOutFile;
|
||||
CodeSize, ImportSize, LookupTableOffset: Integer;
|
||||
|
||||
begin
|
||||
if ProgramEntryPoint = 0 then
|
||||
Error('Program entry point not found');
|
||||
|
||||
CodeSize := GetCodeSize;
|
||||
|
||||
FillImportSection(ImportSize, LookupTableOffset);
|
||||
FillHeaders(CodeSize, InitializedGlobalDataSize, UninitializedGlobalDataSize, ImportSize);
|
||||
|
||||
Relocate(IMGBASE + CodeSectionHeader_VirtualAddress,
|
||||
IMGBASE + DataSectionHeader_VirtualAddress,
|
||||
IMGBASE + BSSSectionHeader_VirtualAddress,
|
||||
IMGBASE + ImportSectionHeader_VirtualAddress + LookupTableOffset);
|
||||
|
||||
//FixupImportSection(Headers.ImportSectionHeader.VirtualAddress);
|
||||
|
||||
// Write output file
|
||||
Assign(OutFile, TGenericString(ExeName));
|
||||
Rewrite(OutFile, 1);
|
||||
|
||||
if IOResult <> 0 then
|
||||
Error('Unable to open output file ' + ExeName);
|
||||
|
||||
BlockWrite(OutFile, Headers, SizeOf(Headers));
|
||||
Pad(OutFile, SizeOf(Headers), FILEALIGN);
|
||||
|
||||
BlockWrite(OutFile, Code, CodeSize);
|
||||
Pad(OutFile, CodeSize, FILEALIGN);
|
||||
|
||||
BlockWrite(OutFile, InitializedGlobalData, InitializedGlobalDataSize);
|
||||
Pad(OutFile, InitializedGlobalDataSize, FILEALIGN);
|
||||
{
|
||||
with ImportSectionData do
|
||||
begin
|
||||
BlockWrite(OutFile, DirectoryTable, SizeOf(DirectoryTable[1]) * (NumImportLibs + 1));
|
||||
BlockWrite(OutFile, LibraryNames, SizeOf(LibraryNames[1]) * NumImportLibs);
|
||||
BlockWrite(OutFile, LookupTable, SizeOf(LookupTable[1]) * (NumImports + NumImportLibs));
|
||||
BlockWrite(OutFile, NameTable, SizeOf(NameTable[1]) * NumImports);
|
||||
end;
|
||||
Pad(OutFile, ImportSize, FILEALIGN);
|
||||
}
|
||||
Close(OutFile);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,698 @@
|
||||
// XD Pascal - a 32-bit compiler for Windows
|
||||
// Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov
|
||||
|
||||
{$I-}
|
||||
{$H-}
|
||||
|
||||
unit Scanner;
|
||||
|
||||
|
||||
interface
|
||||
|
||||
|
||||
uses Common;
|
||||
|
||||
|
||||
var
|
||||
Tok: TToken;
|
||||
|
||||
|
||||
procedure InitializeScanner(const Name: TString);
|
||||
function SaveScanner: Boolean;
|
||||
function RestoreScanner: Boolean;
|
||||
procedure FinalizeScanner;
|
||||
procedure NextTok;
|
||||
procedure CheckTok(ExpectedTokKind: TTokenKind);
|
||||
procedure EatTok(ExpectedTokKind: TTokenKind);
|
||||
procedure AssertIdent;
|
||||
function ScannerFileName: TString;
|
||||
function ScannerLine: Integer;
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
|
||||
type
|
||||
TBuffer = record
|
||||
Ptr: PCharacter;
|
||||
Size, Pos: Integer;
|
||||
end;
|
||||
|
||||
|
||||
TScannerState = record
|
||||
Token: TToken;
|
||||
FileName: TString;
|
||||
Line: Integer;
|
||||
Buffer: TBuffer;
|
||||
ch, ch2: TCharacter;
|
||||
EndOfUnit: Boolean;
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
SCANNERSTACKSIZE = 10;
|
||||
|
||||
|
||||
var
|
||||
ScannerState: TScannerState;
|
||||
ScannerStack: array [1..SCANNERSTACKSIZE] of TScannerState;
|
||||
ScannerStackTop: Integer = 0;
|
||||
|
||||
|
||||
const
|
||||
Digits: set of TCharacter = ['0'..'9'];
|
||||
HexDigits: set of TCharacter = ['0'..'9', 'A'..'F'];
|
||||
Spaces: set of TCharacter = [#1..#31, ' '];
|
||||
AlphaNums: set of TCharacter = ['A'..'Z', 'a'..'z', '0'..'9', '_'];
|
||||
|
||||
|
||||
|
||||
|
||||
procedure InitializeScanner(const Name: TString);
|
||||
var
|
||||
F: TInFile;
|
||||
ActualSize: Integer;
|
||||
FolderIndex: Integer;
|
||||
|
||||
begin
|
||||
ScannerState.Buffer.Ptr := nil;
|
||||
|
||||
// First search the source folder, then the units folder, then the folders specified in $UNITPATH
|
||||
FolderIndex := 1;
|
||||
|
||||
repeat
|
||||
Assign(F, TGenericString(Folders[FolderIndex] + Name));
|
||||
Reset(F, 1);
|
||||
if IOResult = 0 then Break;
|
||||
Inc(FolderIndex);
|
||||
until FolderIndex > NumFolders;
|
||||
|
||||
if FolderIndex > NumFolders then
|
||||
Error('Unable to open source file ' + Name);
|
||||
|
||||
with ScannerState do
|
||||
begin
|
||||
FileName := Name;
|
||||
Line := 1;
|
||||
|
||||
with Buffer do
|
||||
begin
|
||||
Size := FileSize(F);
|
||||
Pos := 0;
|
||||
|
||||
GetMem(Ptr, Size);
|
||||
|
||||
ActualSize := 0;
|
||||
BlockRead(F, Ptr^, Size, ActualSize);
|
||||
Close(F);
|
||||
|
||||
if ActualSize <> Size then
|
||||
Error('Unable to read source file ' + Name);
|
||||
end;
|
||||
|
||||
ch := ' ';
|
||||
ch2 := ' ';
|
||||
EndOfUnit := FALSE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function SaveScanner: Boolean;
|
||||
begin
|
||||
Result := FALSE;
|
||||
if ScannerStackTop < SCANNERSTACKSIZE then
|
||||
begin
|
||||
Inc(ScannerStackTop);
|
||||
ScannerStack[ScannerStackTop] := ScannerState;
|
||||
Result := TRUE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function RestoreScanner: Boolean;
|
||||
begin
|
||||
Result := FALSE;
|
||||
if ScannerStackTop > 0 then
|
||||
begin
|
||||
ScannerState := ScannerStack[ScannerStackTop];
|
||||
Dec(ScannerStackTop);
|
||||
Tok := ScannerState.Token;
|
||||
Result := TRUE;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure FinalizeScanner;
|
||||
begin
|
||||
ScannerState.EndOfUnit := TRUE;
|
||||
with ScannerState.Buffer do
|
||||
if Ptr <> nil then
|
||||
begin
|
||||
FreeMem(Ptr);
|
||||
Ptr := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure AppendStrSafe(var s: TString; ch: TCharacter);
|
||||
begin
|
||||
if Length(s) >= MAXSTRLENGTH - 1 then
|
||||
Error('String is too long');
|
||||
s := s + ch;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadChar(var ch: TCharacter);
|
||||
begin
|
||||
if ScannerState.ch = #10 then Inc(ScannerState.Line); // End of line found
|
||||
|
||||
ch := #0;
|
||||
with ScannerState.Buffer do
|
||||
if Pos < Size then
|
||||
begin
|
||||
ch := PCharacter(Integer(Ptr) + Pos)^;
|
||||
Inc(Pos);
|
||||
end
|
||||
else
|
||||
ScannerState.EndOfUnit := TRUE;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadUppercaseChar(var ch: TCharacter);
|
||||
begin
|
||||
ReadChar(ch);
|
||||
ch := UpCase(ch);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadLiteralChar(var ch: TCharacter);
|
||||
begin
|
||||
ReadChar(ch);
|
||||
if (ch = #0) or (ch = #10) then
|
||||
Error('Unterminated string');
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadSingleLineComment;
|
||||
begin
|
||||
with ScannerState do
|
||||
while (ch <> #10) and not EndOfUnit do
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadMultiLineComment;
|
||||
begin
|
||||
with ScannerState do
|
||||
while (ch <> '}') and not EndOfUnit do
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadDirective;
|
||||
var
|
||||
Text: TString;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Text := '';
|
||||
repeat
|
||||
AppendStrSafe(Text, ch);
|
||||
ReadUppercaseChar(ch);
|
||||
until not (ch in AlphaNums);
|
||||
|
||||
if Text = '$APPTYPE' then // Console/GUI application type directive
|
||||
begin
|
||||
Text := '';
|
||||
ReadChar(ch);
|
||||
while (ch <> '}') and not EndOfUnit do
|
||||
begin
|
||||
if (ch = #0) or (ch > ' ') then
|
||||
AppendStrSafe(Text, UpCase(ch));
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
if Text = 'CONSOLE' then
|
||||
IsConsoleProgram := TRUE
|
||||
else if Text = 'GUI' then
|
||||
IsConsoleProgram := FALSE
|
||||
else
|
||||
Error('Unknown application type ' + Text);
|
||||
end
|
||||
|
||||
else if Text = '$UNITPATH' then // Unit path directive
|
||||
begin
|
||||
Text := '';
|
||||
ReadChar(ch);
|
||||
while (ch <> '}') and not EndOfUnit do
|
||||
begin
|
||||
if (ch = #0) or (ch > ' ') then
|
||||
AppendStrSafe(Text, UpCase(ch));
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
Inc(NumFolders);
|
||||
if NumFolders > MAXFOLDERS then
|
||||
Error('Maximum number of unit paths exceeded');
|
||||
Folders[NumFolders] := Folders[1] + Text;
|
||||
end
|
||||
|
||||
else // All other directives are ignored
|
||||
ReadMultiLineComment;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadHexadecimalNumber;
|
||||
var
|
||||
Num, Digit: Integer;
|
||||
NumFound: Boolean;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Num := 0;
|
||||
|
||||
NumFound := FALSE;
|
||||
while ch in HexDigits do
|
||||
begin
|
||||
if Num and $F0000000 <> 0 then
|
||||
Error('Numeric constant is too large');
|
||||
|
||||
if ch in Digits then
|
||||
Digit := Ord(ch) - Ord('0')
|
||||
else
|
||||
Digit := Ord(ch) - Ord('A') + 10;
|
||||
|
||||
Num := Num shl 4 or Digit;
|
||||
NumFound := TRUE;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
|
||||
if not NumFound then
|
||||
Error('Hexadecimal constant is not found');
|
||||
|
||||
Token.Kind := INTNUMBERTOK;
|
||||
Token.OrdValue := Num;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadDecimalNumber;
|
||||
var
|
||||
Num, Expon, Digit: Integer;
|
||||
Frac, FracWeight: Double;
|
||||
NegExpon, RangeFound, ExponFound: Boolean;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Num := 0;
|
||||
Frac := 0;
|
||||
Expon := 0;
|
||||
NegExpon := FALSE;
|
||||
|
||||
while ch in Digits do
|
||||
begin
|
||||
Digit := Ord(ch) - Ord('0');
|
||||
|
||||
if Num > (HighBound(INTEGERTYPEINDEX) - Digit) div 10 then
|
||||
Error('Numeric constant is too large');
|
||||
|
||||
Num := 10 * Num + Digit;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
|
||||
if (ch <> '.') and (ch <> 'E') then // Integer number
|
||||
begin
|
||||
Token.Kind := INTNUMBERTOK;
|
||||
Token.OrdValue := Num;
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
||||
// Check for '..' token
|
||||
RangeFound := FALSE;
|
||||
if ch = '.' then
|
||||
begin
|
||||
ReadUppercaseChar(ch2);
|
||||
if ch2 = '.' then // Integer number followed by '..' token
|
||||
begin
|
||||
Token.Kind := INTNUMBERTOK;
|
||||
Token.OrdValue := Num;
|
||||
RangeFound := TRUE;
|
||||
end;
|
||||
if not EndOfUnit then Dec(Buffer.Pos);
|
||||
end; // if ch = '.'
|
||||
|
||||
if not RangeFound then // Fractional number
|
||||
begin
|
||||
|
||||
// Check for fractional part
|
||||
if ch = '.' then
|
||||
begin
|
||||
FracWeight := 0.1;
|
||||
ReadUppercaseChar(ch);
|
||||
|
||||
while ch in Digits do
|
||||
begin
|
||||
Digit := Ord(ch) - Ord('0');
|
||||
Frac := Frac + FracWeight * Digit;
|
||||
FracWeight := FracWeight / 10;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end; // if ch = '.'
|
||||
|
||||
// Check for exponent
|
||||
if ch = 'E' then
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
|
||||
// Check for exponent sign
|
||||
if ch = '+' then
|
||||
ReadUppercaseChar(ch)
|
||||
else if ch = '-' then
|
||||
begin
|
||||
NegExpon := TRUE;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
|
||||
ExponFound := FALSE;
|
||||
while ch in Digits do
|
||||
begin
|
||||
Digit := Ord(ch) - Ord('0');
|
||||
Expon := 10 * Expon + Digit;
|
||||
ReadUppercaseChar(ch);
|
||||
ExponFound := TRUE;
|
||||
end;
|
||||
|
||||
if not ExponFound then
|
||||
Error('Exponent is not found');
|
||||
|
||||
if NegExpon then Expon := -Expon;
|
||||
end; // if ch = 'E'
|
||||
|
||||
Token.Kind := REALNUMBERTOK;
|
||||
Token.RealValue := (Num + Frac) * exp(Expon * ln(10));
|
||||
end; // if not RangeFound
|
||||
end; // else
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadNumber;
|
||||
begin
|
||||
with ScannerState do
|
||||
if ch = '$' then
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
ReadHexadecimalNumber;
|
||||
end
|
||||
else
|
||||
ReadDecimalNumber;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadCharCode;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
|
||||
if not (ch in Digits + ['$']) then
|
||||
Error('Character code is not found');
|
||||
|
||||
ReadNumber;
|
||||
|
||||
if (Token.Kind = REALNUMBERTOK) or (Token.OrdValue < 0) or (Token.OrdValue > 255) then
|
||||
Error('Illegal character code');
|
||||
|
||||
Token.Kind := CHARLITERALTOK;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadKeywordOrIdentifier;
|
||||
var
|
||||
Text, NonUppercaseText: TString;
|
||||
CurToken: TTokenKind;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Text := '';
|
||||
NonUppercaseText := '';
|
||||
|
||||
repeat
|
||||
AppendStrSafe(NonUppercaseText, ch);
|
||||
ch := UpCase(ch);
|
||||
AppendStrSafe(Text, ch);
|
||||
ReadChar(ch);
|
||||
until not (ch in AlphaNums);
|
||||
|
||||
CurToken := GetKeyword(Text);
|
||||
if CurToken <> EMPTYTOK then // Keyword found
|
||||
Token.Kind := CurToken
|
||||
else
|
||||
begin // Identifier found
|
||||
Token.Kind := IDENTTOK;
|
||||
Token.Name := Text;
|
||||
Token.NonUppercaseName := NonUppercaseText;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ReadCharOrStringLiteral;
|
||||
var
|
||||
Text: TString;
|
||||
EndOfLiteral: Boolean;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Text := '';
|
||||
EndOfLiteral := FALSE;
|
||||
|
||||
repeat
|
||||
ReadLiteralChar(ch);
|
||||
if ch <> '''' then
|
||||
AppendStrSafe(Text, ch)
|
||||
else
|
||||
begin
|
||||
ReadChar(ch2);
|
||||
if ch2 = '''' then // Apostrophe character found
|
||||
AppendStrSafe(Text, ch)
|
||||
else
|
||||
begin
|
||||
if not EndOfUnit then Dec(Buffer.Pos); // Discard ch2
|
||||
EndOfLiteral := TRUE;
|
||||
end;
|
||||
end;
|
||||
until EndOfLiteral;
|
||||
|
||||
if Length(Text) = 1 then
|
||||
begin
|
||||
Token.Kind := CHARLITERALTOK;
|
||||
Token.OrdValue := Ord(Text[1]);
|
||||
end
|
||||
else
|
||||
begin
|
||||
Token.Kind := STRINGLITERALTOK;
|
||||
Token.Name := Text;
|
||||
Token.StrLength := Length(Text);
|
||||
DefineStaticString(Text, Token.StrAddress);
|
||||
end;
|
||||
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure NextTok;
|
||||
begin
|
||||
with ScannerState do
|
||||
begin
|
||||
Token.Kind := EMPTYTOK;
|
||||
|
||||
// Skip spaces, comments, directives
|
||||
while (ch in Spaces) or (ch = '{') or (ch = '/') do
|
||||
begin
|
||||
if ch = '{' then // Multi-line comment or directive
|
||||
begin
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '$' then ReadDirective else ReadMultiLineComment;
|
||||
end
|
||||
else if ch = '/' then
|
||||
begin
|
||||
ReadUppercaseChar(ch2);
|
||||
if ch2 = '/' then
|
||||
ReadSingleLineComment // Double-line comment
|
||||
else
|
||||
begin
|
||||
if not EndOfUnit then Dec(Buffer.Pos); // Discard ch2
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
ReadChar(ch);
|
||||
end;
|
||||
|
||||
// Read token
|
||||
case ch of
|
||||
'0'..'9', '$':
|
||||
ReadNumber;
|
||||
'#':
|
||||
ReadCharCode;
|
||||
'A'..'Z', 'a'..'z', '_':
|
||||
ReadKeywordOrIdentifier;
|
||||
'''':
|
||||
ReadCharOrStringLiteral;
|
||||
':': // Single- or double-character tokens
|
||||
begin
|
||||
Token.Kind := COLONTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '=' then
|
||||
begin
|
||||
Token.Kind := ASSIGNTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
'>':
|
||||
begin
|
||||
Token.Kind := GTTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '=' then
|
||||
begin
|
||||
Token.Kind := GETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
'<':
|
||||
begin
|
||||
Token.Kind := LTTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '=' then
|
||||
begin
|
||||
Token.Kind := LETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end
|
||||
else if ch = '>' then
|
||||
begin
|
||||
Token.Kind := NETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end;
|
||||
'.':
|
||||
begin
|
||||
Token.Kind := PERIODTOK;
|
||||
ReadUppercaseChar(ch);
|
||||
if ch = '.' then
|
||||
begin
|
||||
Token.Kind := RANGETOK;
|
||||
ReadUppercaseChar(ch);
|
||||
end;
|
||||
end
|
||||
else // Double-character tokens
|
||||
case ch of
|
||||
'=': Token.Kind := EQTOK;
|
||||
',': Token.Kind := COMMATOK;
|
||||
';': Token.Kind := SEMICOLONTOK;
|
||||
'(': Token.Kind := OPARTOK;
|
||||
')': Token.Kind := CPARTOK;
|
||||
'*': Token.Kind := MULTOK;
|
||||
'/': Token.Kind := DIVTOK;
|
||||
'+': Token.Kind := PLUSTOK;
|
||||
'-': Token.Kind := MINUSTOK;
|
||||
'^': Token.Kind := DEREFERENCETOK;
|
||||
'@': Token.Kind := ADDRESSTOK;
|
||||
'[': Token.Kind := OBRACKETTOK;
|
||||
']': Token.Kind := CBRACKETTOK
|
||||
else
|
||||
Error('Unexpected character or end of file');
|
||||
end; // case
|
||||
|
||||
ReadChar(ch);
|
||||
end; // case
|
||||
end;
|
||||
|
||||
Tok := ScannerState.Token;
|
||||
end; // NextTok
|
||||
|
||||
|
||||
|
||||
|
||||
procedure CheckTok(ExpectedTokKind: TTokenKind);
|
||||
begin
|
||||
with ScannerState do
|
||||
if Token.Kind <> ExpectedTokKind then
|
||||
Error(GetTokSpelling(ExpectedTokKind) + ' expected but ' + GetTokSpelling(Token.Kind) + ' found');
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure EatTok(ExpectedTokKind: TTokenKind);
|
||||
begin
|
||||
CheckTok(ExpectedTokKind);
|
||||
NextTok;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure AssertIdent;
|
||||
begin
|
||||
with ScannerState do
|
||||
if Token.Kind <> IDENTTOK then
|
||||
Error('Identifier expected but ' + GetTokSpelling(Token.Kind) + ' found');
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function ScannerFileName: TString;
|
||||
begin
|
||||
Result := ScannerState.FileName;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function ScannerLine: Integer;
|
||||
begin
|
||||
Result := ScannerState.Line;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,188 @@
|
||||
// XD Pascal - a 32-bit compiler for KolibriOS
|
||||
// Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
{$I-}
|
||||
{$H-}
|
||||
|
||||
program XDPK;
|
||||
|
||||
|
||||
uses SysUtils, Common, Scanner, Parser, CodeGen, Linker;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure SplitPath(const Path: TString; var Folder, Name, Ext: TString);
|
||||
var
|
||||
DotPos, SlashPos, i: Integer;
|
||||
begin
|
||||
Folder := '';
|
||||
Name := Path;
|
||||
Ext := '';
|
||||
|
||||
DotPos := 0;
|
||||
SlashPos := 0;
|
||||
|
||||
for i := Length(Path) downto 1 do
|
||||
if (Path[i] = '.') and (DotPos = 0) then
|
||||
DotPos := i
|
||||
else if (Path[i] = '\') and (SlashPos = 0) then
|
||||
SlashPos := i;
|
||||
|
||||
if DotPos > 0 then
|
||||
begin
|
||||
Name := Copy(Path, 1, DotPos - 1);
|
||||
Ext := Copy(Path, DotPos, Length(Path) - DotPos + 1);
|
||||
end;
|
||||
|
||||
if SlashPos > 0 then
|
||||
begin
|
||||
Folder := Copy(Path, 1, SlashPos);
|
||||
Name := Copy(Path, SlashPos + 1, Length(Name) - SlashPos);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function UnquotedParamStr(Index: Integer; var NextIndex: Integer): TString;
|
||||
var
|
||||
Fragment: TString;
|
||||
begin
|
||||
// XD Pascal's own ParseCmdLine splits the command line at spaces only and keeps the quotes,
|
||||
// so a quoted argument (as passed by the make.bat files) must be reassembled and unquoted here.
|
||||
// Compilers built by Delphi do this in their own run-time library
|
||||
Result := TString(ParamStr(Index));
|
||||
NextIndex := Index + 1;
|
||||
|
||||
if (Length(Result) > 0) and (Result[1] = '"') then
|
||||
begin
|
||||
Result := Copy(Result, 2, Length(Result) - 1);
|
||||
|
||||
// A quoted path may contain spaces and thus be split into several fragments - glue them back
|
||||
while (Length(Result) = 0) or (Result[Length(Result)] <> '"') do
|
||||
begin
|
||||
if NextIndex > ParamCount then Break; // Unterminated quote
|
||||
|
||||
Fragment := TString(ParamStr(NextIndex));
|
||||
Inc(NextIndex);
|
||||
Result := Result + ' ' + Fragment;
|
||||
end;
|
||||
|
||||
if (Length(Result) > 0) and (Result[Length(Result)] = '"') then
|
||||
Result := Copy(Result, 1, Length(Result) - 1);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure NoticeProc(ClassInstance: Pointer; const Msg: TString);
|
||||
begin
|
||||
WriteLn(Msg);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure WarningProc(ClassInstance: Pointer; const Msg: TString);
|
||||
begin
|
||||
if NumUnits >= 1 then
|
||||
Notice(ScannerFileName + ' (' + IntToStr(ScannerLine) + ') Warning: ' + Msg)
|
||||
else
|
||||
Notice('Warning: ' + Msg);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
procedure ErrorProc(ClassInstance: Pointer; const Msg: TString);
|
||||
begin
|
||||
if NumUnits >= 1 then
|
||||
Notice(ScannerFileName + ' (' + IntToStr(ScannerLine) + ') Error: ' + Msg)
|
||||
else
|
||||
Notice('Error: ' + Msg);
|
||||
|
||||
repeat FinalizeScanner until not RestoreScanner;
|
||||
FinalizeCommon;
|
||||
Halt(1);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
var
|
||||
CompilerPath, CompilerFolder, CompilerName, CompilerExt,
|
||||
PasPath, PasFolder, PasName, PasExt,
|
||||
ExePath: TString;
|
||||
NextParamIndex, LastParamIndex: Integer;
|
||||
|
||||
|
||||
|
||||
begin
|
||||
SetWriteProcs(nil, @NoticeProc, @WarningProc, @ErrorProc);
|
||||
|
||||
Notice('XD Pascal for KolibriOS ' + VERSION);
|
||||
Notice('Copyright (c) 2009-2010, 2019-2020, Vasiliy Tereshkov');
|
||||
|
||||
if ParamCount < 1 then
|
||||
begin
|
||||
Notice('Usage: xdpk <file.pas> [-nosmart]');
|
||||
Halt(1);
|
||||
end;
|
||||
|
||||
CompilerPath := TString(ParamStr(0));
|
||||
SplitPath(CompilerPath, CompilerFolder, CompilerName, CompilerExt);
|
||||
|
||||
PasPath := UnquotedParamStr(1, NextParamIndex);
|
||||
SplitPath(PasPath, PasFolder, PasName, PasExt);
|
||||
|
||||
InitializeSmartLinker;
|
||||
|
||||
if NextParamIndex <= ParamCount then
|
||||
if UnquotedParamStr(NextParamIndex, LastParamIndex) = '-nosmart' then
|
||||
DisableSmartLinking := TRUE;
|
||||
|
||||
// First pass: compile everything and build the routine call graph
|
||||
SuppressWarnings := TRUE;
|
||||
|
||||
InitializeCommon;
|
||||
InitializeLinker;
|
||||
InitializeCodeGen;
|
||||
|
||||
Folders[1] := PasFolder;
|
||||
Folders[2] := CompilerFolder + 'units\';
|
||||
NumFolders := 2;
|
||||
|
||||
CompileProgramOrUnit('system.pas');
|
||||
CompileProgramOrUnit(PasName + PasExt);
|
||||
|
||||
FinalizeCommon;
|
||||
|
||||
// Second pass: recompile, discarding the code of unreachable routines
|
||||
ComputeLiveProcs;
|
||||
IsSecondPass := TRUE;
|
||||
SuppressWarnings := FALSE;
|
||||
|
||||
InitializeCommon;
|
||||
InitializeLinker;
|
||||
InitializeCodeGen;
|
||||
|
||||
Folders[1] := PasFolder;
|
||||
Folders[2] := CompilerFolder + 'units\';
|
||||
NumFolders := 2;
|
||||
|
||||
CompileProgramOrUnit('system.pas');
|
||||
CompileProgramOrUnit(PasName + PasExt);
|
||||
|
||||
ExePath := PasFolder + PasName + '.kex';
|
||||
LinkAndWriteProgram(ExePath);
|
||||
|
||||
Notice('Complete. Code size: ' + IntToStr(GetCodeSize) + ' bytes. Data size: ' + IntToStr(InitializedGlobalDataSize + UninitializedGlobalDataSize) + ' bytes');
|
||||
|
||||
repeat FinalizeScanner until not RestoreScanner;
|
||||
FinalizeCommon;
|
||||
end.
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
unit CRT;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
KolibriOS;
|
||||
|
||||
type
|
||||
PKey = ^TKey;
|
||||
TKey = packed record
|
||||
CharCode, ScanCode: AnsiChar;
|
||||
end;
|
||||
|
||||
const
|
||||
Black = 0;
|
||||
Blue = 1;
|
||||
Green = 2;
|
||||
Cyan = 3;
|
||||
Red = 4;
|
||||
Magenta = 5;
|
||||
Brown = 6;
|
||||
LightGray = 7;
|
||||
DarkGray = 8;
|
||||
LightBlue = 9;
|
||||
LightGreen = 10;
|
||||
LightCyan = 11;
|
||||
LightRed = 12;
|
||||
LightMagenta = 13;
|
||||
Yellow = 14;
|
||||
White = 15;
|
||||
|
||||
procedure GotoXY(X, Y: Integer);
|
||||
function WhereX: Integer;
|
||||
function WhereY: Integer;
|
||||
|
||||
function NormVideo: Integer;
|
||||
function TextBackground(Color: Byte): Integer;
|
||||
function TextColor(Color: Byte): Integer;
|
||||
|
||||
procedure ClrEOL;
|
||||
procedure ClrScr;
|
||||
|
||||
function KeyPressed: Boolean;
|
||||
function ReadKey: AnsiChar;
|
||||
function ReadKeyEx: TKey;
|
||||
function ReadKeyWord: Word;
|
||||
|
||||
procedure SetTitle(Title: PAnsiChar);
|
||||
|
||||
procedure Delay(Milliseconds: Integer);
|
||||
|
||||
procedure CRT_initialization;
|
||||
|
||||
implementation
|
||||
|
||||
var
|
||||
con_cls: procedure stdcall;
|
||||
con_get_cursor_pos: procedure(var X, Y: Integer) stdcall;
|
||||
con_get_flags: function: Integer stdcall;
|
||||
con_getch: function: Integer stdcall;
|
||||
con_getch2: function: Word stdcall;
|
||||
con_kbhit: function: Boolean stdcall;
|
||||
con_set_flags: function(Flags: Integer): Integer stdcall;
|
||||
con_set_cursor_pos: procedure(X, Y: Integer) stdcall;
|
||||
con_set_title: procedure(Title: PAnsiChar) stdcall;
|
||||
|
||||
ClrEOLWidth: Integer = 80;
|
||||
|
||||
procedure SetTitle(Title: PAnsiChar);
|
||||
begin
|
||||
con_set_title(Title);
|
||||
end;
|
||||
|
||||
function NormVideo: Integer;
|
||||
begin
|
||||
Result := con_set_flags(con_get_flags() and $300 or $07);
|
||||
end;
|
||||
|
||||
function TextBackground(Color: Byte): Integer;
|
||||
begin
|
||||
Result := con_set_flags(con_get_flags() and $30F or Color and $0F shl 4);
|
||||
end;
|
||||
|
||||
function TextColor(Color: Byte): Integer;
|
||||
begin
|
||||
Result := con_set_flags(con_get_flags() and $3F0 or Color and $0F);
|
||||
end;
|
||||
|
||||
procedure GotoXY(X, Y: Integer);
|
||||
begin
|
||||
con_set_cursor_pos(X - 1, Y - 1);
|
||||
end;
|
||||
|
||||
function WhereX: Integer;
|
||||
var
|
||||
Y: Integer;
|
||||
begin
|
||||
con_get_cursor_pos(Result, Y);
|
||||
Inc(Result);
|
||||
end;
|
||||
|
||||
function WhereY: Integer;
|
||||
var
|
||||
X: Integer;
|
||||
begin
|
||||
con_get_cursor_pos(X, Result);
|
||||
Inc(Result);
|
||||
end;
|
||||
|
||||
procedure ClrEOL;
|
||||
var
|
||||
X, Y, Count: Integer;
|
||||
Buf: array [0..255] of AnsiChar;
|
||||
begin
|
||||
con_get_cursor_pos(X, Y);
|
||||
Count := ClrEOLWidth - X - 1;
|
||||
if Count > 0 then
|
||||
begin
|
||||
FillChar(Buf[0], Count, ' ');
|
||||
Buf[Count] := #0;
|
||||
Write(Buf);
|
||||
con_set_cursor_pos(X, Y);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ClrScr;
|
||||
begin
|
||||
con_cls();
|
||||
end;
|
||||
|
||||
function KeyPressed: Boolean;
|
||||
begin
|
||||
Result := con_kbhit();
|
||||
end;
|
||||
|
||||
function ReadKey: AnsiChar;
|
||||
begin
|
||||
Result := Chr(con_getch());
|
||||
end;
|
||||
|
||||
function ReadKeyEx: TKey;
|
||||
begin
|
||||
Result := PKey(con_getch2())^;
|
||||
end;
|
||||
|
||||
function ReadKeyWord: Word;
|
||||
begin
|
||||
Result := con_getch2();
|
||||
end;
|
||||
|
||||
procedure Delay(Milliseconds: Integer);
|
||||
begin
|
||||
Sleep((Milliseconds + 10 div 2) div 10);
|
||||
end;
|
||||
|
||||
procedure CRT_initialization;
|
||||
begin
|
||||
con_cls := GetProcAddress(hConsole, 'con_cls');
|
||||
con_getch := GetProcAddress(hConsole, 'con_getch');
|
||||
con_getch2 := GetProcAddress(hConsole, 'con_getch2');
|
||||
con_get_cursor_pos := GetProcAddress(hConsole, 'con_get_cursor_pos');
|
||||
con_get_flags := GetProcAddress(hConsole, 'con_get_flags');
|
||||
con_kbhit := GetProcAddress(hConsole, 'con_kbhit');
|
||||
con_set_cursor_pos := GetProcAddress(hConsole, 'con_set_cursor_pos');
|
||||
con_set_flags := GetProcAddress(hConsole, 'con_set_flags');
|
||||
con_set_title := GetProcAddress(hConsole, 'con_set_title');
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,74 @@
|
||||
unit ColorDlg;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
KolibriOS, ProcLib;
|
||||
|
||||
const
|
||||
// ColorDialog.Mode constants
|
||||
CDM_PALETTE_TONE = 0;
|
||||
|
||||
// ColorDialog.Status constants
|
||||
CDS_CANCEL = 0;
|
||||
CDS_OK = 1;
|
||||
CDS_ALTER = 2;
|
||||
|
||||
// ColorDialog.ColorType constants
|
||||
CDCT_RGB = 0;
|
||||
|
||||
type
|
||||
PColorDialog = ^TColorDialog;
|
||||
TColorDialog = packed record
|
||||
Mode: Integer;
|
||||
ProcInfo: Pointer;
|
||||
ComAreaName: PAnsiChar;
|
||||
ComArea: Pointer;
|
||||
StartPath: PAnsiChar;
|
||||
DrawWindow: procedure;
|
||||
Status: Integer;
|
||||
XSize: Word;
|
||||
XStart: SmallInt;
|
||||
YSize: Word;
|
||||
YStart: SmallInt;
|
||||
ColorType: Integer;
|
||||
Color: Integer;
|
||||
{private}
|
||||
ProcInfoBuffer: array [0..Pred(SizeOf(TThreadInfo))] of Byte;
|
||||
end;
|
||||
|
||||
procedure Init for ColorDialog: TColorDialog;
|
||||
procedure Start for ColorDialog: TColorDialog;
|
||||
|
||||
procedure ColorDlg_initialization;
|
||||
|
||||
implementation
|
||||
|
||||
var
|
||||
ColorDialog_init: procedure(var ColorDialog: TColorDialog) stdcall;
|
||||
ColorDialog_start: procedure(var ColorDialog: TColorDialog) stdcall;
|
||||
|
||||
procedure Init for ColorDialog: TColorDialog;
|
||||
begin
|
||||
with ColorDialog do
|
||||
begin
|
||||
ProcInfo := @ProcInfoBuffer;
|
||||
ComAreaName := 'FFFFFFFF_color_dialog';
|
||||
StartPath := '/sys/colrdial';
|
||||
end;
|
||||
ColorDialog_init(ColorDialog);
|
||||
end;
|
||||
|
||||
procedure Start for ColorDialog: TColorDialog;
|
||||
begin
|
||||
ColorDialog_start(ColorDialog);
|
||||
end;
|
||||
|
||||
procedure ColorDlg_initialization;
|
||||
begin
|
||||
if hProcLib = nil then ProcLib_initialization;
|
||||
ColorDialog_init := GetProcAddress(hProcLib, 'ColorDialog_init');
|
||||
ColorDialog_start := GetProcAddress(hProcLib, 'ColorDialog_start');
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,500 @@
|
||||
unit KolibriOS;
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
TSize = packed record
|
||||
Height: Word;
|
||||
Width: Word;
|
||||
end;
|
||||
|
||||
TPoint = packed record
|
||||
Y: SmallInt;
|
||||
X: SmallInt;
|
||||
end;
|
||||
|
||||
TRect = packed record
|
||||
Left: Integer;
|
||||
Top: Integer;
|
||||
Right: Integer;
|
||||
Bottom: Integer;
|
||||
end;
|
||||
|
||||
TBox = packed record
|
||||
Left: Integer;
|
||||
Top: Integer;
|
||||
Width: Integer;
|
||||
Height: Integer;
|
||||
end;
|
||||
|
||||
TSystemDate = packed record
|
||||
Year: Byte;
|
||||
Month: Byte;
|
||||
Day: Byte;
|
||||
Zero: Byte;
|
||||
end;
|
||||
|
||||
TSystemTime = packed record
|
||||
Hours: Byte;
|
||||
Minutes: Byte;
|
||||
Seconds: Byte;
|
||||
Zero: Byte;
|
||||
end;
|
||||
|
||||
TThreadInfo = packed record
|
||||
CpuUsage: Integer;
|
||||
WinStackPos: Word;
|
||||
Reserved0: Word;
|
||||
Reserved1: Word;
|
||||
Name: array[0..11] of AnsiChar;
|
||||
MemAddress: Integer;
|
||||
MemUsage: Integer;
|
||||
Identifier: Integer;
|
||||
Window: TBox;
|
||||
ThreadState: Word;
|
||||
Reserved2: Word;
|
||||
Client: TBox;
|
||||
WindowState: Byte;
|
||||
EventMask: Integer;
|
||||
KeyboardMode: Byte;
|
||||
Reserved3: array[0..947] of Byte;
|
||||
end;
|
||||
|
||||
TKeyboardInputMode = (kmChar, kmScan);
|
||||
|
||||
TKeyboardInputFlag = (kfCode, kfEmpty, kfHotKey);
|
||||
|
||||
TKeyboardInput = packed record
|
||||
Flag: TKeyboardInputFlag;
|
||||
Code: AnsiChar;
|
||||
case TKeyboardInputMode of
|
||||
kmChar:
|
||||
(ScanCode: AnsiChar);
|
||||
kmScan:
|
||||
(case TKeyboardInputFlag of
|
||||
kfCode:
|
||||
();
|
||||
kfHotKey:
|
||||
(Control: Word);
|
||||
);
|
||||
end;
|
||||
|
||||
TButtonInput = packed record
|
||||
MouseButton: Byte;
|
||||
ID: Word;
|
||||
HiID: Byte;
|
||||
end;
|
||||
|
||||
TKeyboardLayout = array[0..127] of AnsiChar;
|
||||
|
||||
TStandardColors = packed record
|
||||
Frames: Integer;
|
||||
Grab: Integer;
|
||||
Work3DDark: Integer;
|
||||
Work3DLight: Integer;
|
||||
GrabText: Integer;
|
||||
Work: Integer;
|
||||
WorkButton: Integer;
|
||||
WorkButtonText: Integer;
|
||||
WorkText: Integer;
|
||||
WorkGraph: Integer;
|
||||
end;
|
||||
|
||||
const
|
||||
WINDOW_BORDER_SIZE = 5;
|
||||
|
||||
// Window styles
|
||||
WS_SKINNED_FIXED = $4000000;
|
||||
WS_SKINNED_SIZABLE = $3000000;
|
||||
WS_FIXED = $0000000;
|
||||
WS_SIZABLE = $2000000;
|
||||
WS_NO_DRAW = $1000000;
|
||||
WS_TRANSPARENT_FILL = $40000000;
|
||||
WS_GRADIENT_FILL = $80000000;
|
||||
WS_CLIENT_COORDS = $20000000;
|
||||
WS_CAPTION = $10000000;
|
||||
|
||||
// Caption styles
|
||||
CAPTION_MOVABLE = $00000000;
|
||||
CAPTION_NONMOVABLE = $01000000;
|
||||
|
||||
// Window Z-ordering modes
|
||||
ZORDER_DESKTOP = -2;
|
||||
ZORDER_BOTTOM = -1;
|
||||
ZORDER_NORMAL = 0;
|
||||
ZORDER_TOP = 1;
|
||||
|
||||
// Events
|
||||
REDRAW_EVENT = 1;
|
||||
KEY_EVENT = 2;
|
||||
BUTTON_EVENT = 3;
|
||||
BACKGROUND_EVENT = 5;
|
||||
MOUSE_EVENT = 6;
|
||||
IPC_EVENT = 7;
|
||||
NETWORK_EVENT = 8;
|
||||
DEBUG_EVENT = 9;
|
||||
|
||||
// Event Mask constants
|
||||
EM_REDRAW = $001;
|
||||
EM_KEY = $002;
|
||||
EM_BUTTON = $004;
|
||||
EM_BACKGROUND = $010;
|
||||
EM_MOUSE = $020;
|
||||
EM_IPC = $040;
|
||||
EM_NETWORK = $080;
|
||||
EM_DEBUG = $100;
|
||||
|
||||
// Size multipliers for DrawText
|
||||
DT_x1 = $0000000;
|
||||
DT_x2 = $1000000;
|
||||
DT_x3 = $2000000;
|
||||
DT_x4 = $3000000;
|
||||
DT_x5 = $4000000;
|
||||
DT_x6 = $5000000;
|
||||
DT_x7 = $6000000;
|
||||
DT_x8 = $7000000;
|
||||
|
||||
// Charset specifiers for DrawText
|
||||
DT_CP866_6x9 = $00000000;
|
||||
DT_CP866_8x16 = $10000000;
|
||||
DT_UTF16LE_8x16 = $20000000;
|
||||
DT_UTF8_8x16 = $30000000;
|
||||
|
||||
// Fill styles for DrawText
|
||||
DT_TRANSPARENT_FILL = $00000000;
|
||||
DT_FILL_OPAQUE = $40000000;
|
||||
|
||||
// Draw zero terminated string for DrawText
|
||||
DT_ZSTRING = $80000000;
|
||||
|
||||
// Button styles
|
||||
BS_TRANSPARENT_FILL = $40000000;
|
||||
BS_NO_FRAME = $20000000;
|
||||
|
||||
// OpenSharedMemory open\access flags
|
||||
SHM_OPEN = $00;
|
||||
SHM_OPEN_ALWAYS = $04;
|
||||
SHM_CREATE = $08;
|
||||
SHM_READ = $00;
|
||||
SHM_WRITE = $01;
|
||||
|
||||
// KeyboardLayout flags
|
||||
KBL_NORMAL = 1;
|
||||
KBL_SHIFT = 2;
|
||||
KBL_ALT = 3;
|
||||
|
||||
// SystemShutdown parameters
|
||||
SHUTDOWN_TURNOFF = 2;
|
||||
SHUTDOWN_REBOOT = 3;
|
||||
SHUTDOWN_RESTART = 4;
|
||||
|
||||
// Blit flags
|
||||
BLIT_CLIENT_RELATIVE = $20000000;
|
||||
|
||||
{-1} procedure ExitThread;
|
||||
{0} procedure DrawWindow(Left, Top, Width, Height: Integer; Caption: PAnsiChar; BackColor, Style, CapStyle: Integer);
|
||||
{2} function GetKey: TKeyboardInput;
|
||||
{4} procedure DrawText(X, Y: Integer; Text: PAnsiChar; ForeColor, BackColor, Flags, Count: Integer);
|
||||
{5} procedure Sleep(Time: Integer);
|
||||
{8} procedure DrawButton(Left, Top, Width, Height, BackColor, Style, ID: Integer);
|
||||
{9} function GetThreadInfo(Slot: Integer; var Buffer: TThreadInfo): Integer;
|
||||
{10} function WaitEvent: Integer;
|
||||
{11} function CheckEvent: Integer;
|
||||
{12.1} procedure BeginDraw;
|
||||
{12.2} procedure EndDraw;
|
||||
{17} function GetButton: TButtonInput;
|
||||
{23} function WaitEventByTime(Time: Integer): Integer;
|
||||
{37.1} function GetWindowMousePos: TPoint;
|
||||
{37.2} function GetMouseButtons: Integer;
|
||||
{40} function SetEventMask(Mask: Integer): Integer;
|
||||
{61.1} function GetScreenSize: TSize;
|
||||
{68.19} function LoadLibrary(FileName: PAnsiChar): Pointer;
|
||||
function GetProcAddress(hLib: Pointer; ProcName: PAnsiChar): Pointer;
|
||||
|
||||
implementation
|
||||
|
||||
function WaitEvent: Integer;
|
||||
type
|
||||
TWaitEventProc = function: Integer stdcall;
|
||||
const
|
||||
_WaitEvent: array[0..7] of Byte = (
|
||||
$B8, $0A, $00, $00, $00, $CD, $40, $C3
|
||||
);
|
||||
var
|
||||
WaitEventProc: TWaitEventProc;
|
||||
begin
|
||||
WaitEventProc := TWaitEventProc(@_WaitEvent);
|
||||
Result := WaitEventProc();
|
||||
end;
|
||||
|
||||
function CheckEvent: Integer;
|
||||
type
|
||||
TCheckEventProc = function: Integer stdcall;
|
||||
const
|
||||
_CheckEvent: array[0..7] of Byte = (
|
||||
$B8, $0B, $00, $00, $00, $CD, $40, $C3
|
||||
);
|
||||
var
|
||||
CheckEventProc: TCheckEventProc;
|
||||
begin
|
||||
CheckEventProc := TCheckEventProc(@_CheckEvent);
|
||||
Result := CheckEventProc();
|
||||
end;
|
||||
|
||||
function WaitEventByTime(Time: Integer): Integer;
|
||||
type
|
||||
TWaitEventByTimeProc = function(Time: Integer): Integer stdcall;
|
||||
const
|
||||
_WaitEventByTime: array[0..15] of Byte = (
|
||||
$53, $B8, $17, $00, $00, $00, $8B, $5C, $24, $08, $CD, $40, $5B, $C2, $04,
|
||||
$00
|
||||
);
|
||||
var
|
||||
WaitEventByTimeProc: TWaitEventByTimeProc;
|
||||
begin
|
||||
WaitEventByTimeProc := TWaitEventByTimeProc(@_WaitEventByTime);
|
||||
Result := WaitEventByTimeProc(Time);
|
||||
end;
|
||||
|
||||
procedure DrawWindow(Left, Top, Width, Height: Integer; Caption: PAnsiChar; BackColor, Style, CapStyle: Integer);
|
||||
type
|
||||
TDrawWindowProc = procedure(Left, Top, Width, Height: Integer; Caption: PAnsiChar; BackColor, Style, CapStyle: Integer) stdcall;
|
||||
const
|
||||
_DrawWindow: array[0..50] of Byte = (
|
||||
$53, $57, $56, $31, $C0, $8B, $5C, $24, $10, $8B, $4C, $24, $14, $C1, $E3,
|
||||
$10, $C1, $E1, $10, $0B, $5C, $24, $18, $0B, $4C, $24, $1C, $8B, $54, $24,
|
||||
$28, $0B, $54, $24, $24, $8B, $7C, $24, $20, $8B, $74, $24, $2C, $CD, $40,
|
||||
$5E, $5F, $5B, $C2, $20, $00
|
||||
);
|
||||
var
|
||||
DrawWindowProc: TDrawWindowProc;
|
||||
begin
|
||||
DrawWindowProc := TDrawWindowProc(@_DrawWindow);
|
||||
DrawWindowProc(Left, Top, Width, Height, Caption, BackColor, Style, CapStyle);
|
||||
end;
|
||||
|
||||
procedure ExitThread;
|
||||
type
|
||||
TExitThreadProc = procedure stdcall;
|
||||
const
|
||||
_ExitThread: array[0..4] of Byte = (
|
||||
$83, $C8, $FF, $CD, $40
|
||||
);
|
||||
var
|
||||
ExitThreadProc: TExitThreadProc;
|
||||
begin
|
||||
ExitThreadProc := TExitThreadProc(@_ExitThread);
|
||||
ExitThreadProc();
|
||||
end;
|
||||
|
||||
procedure BeginDraw;
|
||||
type
|
||||
TBeginDrawProc = procedure stdcall;
|
||||
const
|
||||
_BeginDraw: array[0..14] of Byte = (
|
||||
$53, $B8, $0C, $00, $00, $00, $BB, $01, $00, $00, $00, $CD, $40, $5B, $C3
|
||||
);
|
||||
var
|
||||
BeginDrawProc: TBeginDrawProc;
|
||||
begin
|
||||
BeginDrawProc := TBeginDrawProc(@_BeginDraw);
|
||||
BeginDrawProc();
|
||||
end;
|
||||
|
||||
procedure EndDraw;
|
||||
type
|
||||
TEndDrawProc = procedure stdcall;
|
||||
const
|
||||
_EndDraw: array[0..14] of Byte = (
|
||||
$53, $B8, $0C, $00, $00, $00, $BB, $02, $00, $00, $00, $CD, $40, $5B, $C3
|
||||
);
|
||||
var
|
||||
EndDrawProc: TEndDrawProc;
|
||||
begin
|
||||
EndDrawProc := TEndDrawProc(@_EndDraw);
|
||||
EndDrawProc();
|
||||
end;
|
||||
|
||||
function GetButton: TButtonInput;
|
||||
type
|
||||
TGetButtonProc = function: TButtonInput stdcall;
|
||||
const
|
||||
_GetButton: array[0..7] of Byte = (
|
||||
$B8, $11, $00, $00, $00, $CD, $40, $C3
|
||||
);
|
||||
var
|
||||
GetButtonProc: TGetButtonProc;
|
||||
begin
|
||||
GetButtonProc := TGetButtonProc(@_GetButton);
|
||||
Result := GetButtonProc();
|
||||
end;
|
||||
|
||||
function LoadLibrary(FileName: PAnsiChar): Pointer;
|
||||
type
|
||||
TLoadLibraryProc = function(FileName: PAnsiChar): Pointer stdcall;
|
||||
const
|
||||
_LoadLibrary: array[0..20] of Byte = (
|
||||
$53, $B8, $44, $00, $00, $00, $BB, $13, $00, $00, $00, $8B, $4C, $24, $08,
|
||||
$CD, $40, $5B, $C2, $04, $00
|
||||
);
|
||||
var
|
||||
LoadLibraryProc: TLoadLibraryProc;
|
||||
begin
|
||||
LoadLibraryProc := TLoadLibraryProc(@_LoadLibrary);
|
||||
Result := LoadLibraryProc(FileName);
|
||||
end;
|
||||
|
||||
function GetProcAddress(hLib: Pointer; ProcName: PAnsiChar): Pointer;
|
||||
type
|
||||
TGetProcAddressProc = function(hLib: Pointer; ProcName: PAnsiChar): Pointer stdcall;
|
||||
const
|
||||
_GetProcAddress: array[0..55] of Byte = (
|
||||
$56, $57, $53, $8B, $54, $24, $10, $31, $C0, $85, $D2, $74, $25, $8B, $7C,
|
||||
$24, $14, $B9, $FF, $FF, $FF, $FF, $F2, $AE, $89, $CB, $F7, $D3, $8B, $32,
|
||||
$85, $F6, $74, $10, $89, $D9, $8B, $7C, $24, $14, $83, $C2, $08, $F3, $A6,
|
||||
$75, $ED, $8B, $42, $FC, $5B, $5F, $5E, $C2, $08, $00
|
||||
);
|
||||
var
|
||||
GetProcAddressProc: TGetProcAddressProc;
|
||||
begin
|
||||
GetProcAddressProc := TGetProcAddressProc(@_GetProcAddress);
|
||||
Result := GetProcAddressProc(hLib, ProcName);
|
||||
end;
|
||||
|
||||
function GetKey: TKeyboardInput;
|
||||
type
|
||||
TGetKeyProc = function: TKeyboardInput stdcall;
|
||||
const
|
||||
_GetKey: array[0..7] of Byte = (
|
||||
$B8, $02, $00, $00, $00, $CD, $40, $C3
|
||||
);
|
||||
var
|
||||
GetKeyProc: TGetKeyProc;
|
||||
begin
|
||||
GetKeyProc := TGetKeyProc(@_GetKey);
|
||||
Result := GetKeyProc();
|
||||
end;
|
||||
|
||||
function SetEventMask(Mask: Integer): Integer;
|
||||
type
|
||||
TSetEventMaskProc = function(Mask: Integer): Integer stdcall;
|
||||
const
|
||||
_SetEventMask: array[0..15] of Byte = (
|
||||
$53, $B8, $28, $00, $00, $00, $8B, $5C, $24, $08, $CD, $40, $5B, $C2, $04,
|
||||
$00
|
||||
);
|
||||
var
|
||||
SetEventMaskProc: TSetEventMaskProc;
|
||||
begin
|
||||
SetEventMaskProc := TSetEventMaskProc(@_SetEventMask);
|
||||
Result := SetEventMaskProc(Mask);
|
||||
end;
|
||||
|
||||
function GetScreenSize: TSize;
|
||||
type
|
||||
TGetScreenSizeProc = function: TSize stdcall;
|
||||
const
|
||||
_GetScreenSize: array[0..16] of Byte = (
|
||||
$53, $B8, $3D, $00, $00, $00, $BB, $01, $00, $00, $00, $CD, $40, $5B, $C2,
|
||||
$00, $00
|
||||
);
|
||||
var
|
||||
GetScreenSizeProc: TGetScreenSizeProc;
|
||||
begin
|
||||
GetScreenSizeProc := TGetScreenSizeProc(@_GetScreenSize);
|
||||
Result := GetScreenSizeProc();
|
||||
end;
|
||||
|
||||
function GetThreadInfo(Slot: Integer; var Buffer: TThreadInfo): Integer;
|
||||
type
|
||||
TGetThreadInfoProc = function(Slot: Integer; var Buffer: TThreadInfo): Integer stdcall;
|
||||
const
|
||||
_GetThreadInfo: array[0..19] of Byte = (
|
||||
$53, $B8, $09, $00, $00, $00, $8B, $5C, $24, $0C, $8B, $4C, $24, $08, $CD,
|
||||
$40, $5B, $C2, $08, $00
|
||||
);
|
||||
var
|
||||
GetThreadInfoProc: TGetThreadInfoProc;
|
||||
begin
|
||||
GetThreadInfoProc := TGetThreadInfoProc(@_GetThreadInfo);
|
||||
Result := GetThreadInfoProc(Slot, Buffer);
|
||||
end;
|
||||
|
||||
procedure Sleep(Time: Integer);
|
||||
type
|
||||
TSleepProc = procedure(Time: Integer) stdcall;
|
||||
const
|
||||
_Sleep: array[0..15] of Byte = (
|
||||
$53, $B8, $05, $00, $00, $00, $8B, $5C, $24, $08, $CD, $40, $5B, $C2, $04,
|
||||
$00
|
||||
);
|
||||
var
|
||||
SleepProc: TSleepProc;
|
||||
begin
|
||||
SleepProc := TSleepProc(@_Sleep);
|
||||
SleepProc(Time);
|
||||
end;
|
||||
|
||||
function GetMouseButtons: Integer;
|
||||
type
|
||||
TGetMouseButtonsProc = function: Integer stdcall;
|
||||
const
|
||||
_GetMouseButtons: array[0..14] of Byte = (
|
||||
$53, $B8, $25, $00, $00, $00, $BB, $02, $00, $00, $00, $CD, $40, $5B, $C3
|
||||
);
|
||||
var
|
||||
GetMouseButtonsProc: TGetMouseButtonsProc;
|
||||
begin
|
||||
GetMouseButtonsProc := TGetMouseButtonsProc(@_GetMouseButtons);
|
||||
Result := GetMouseButtonsProc();
|
||||
end;
|
||||
|
||||
function GetWindowMousePos: TPoint;
|
||||
type
|
||||
TGetWindowMousePosProc = function: TPoint stdcall;
|
||||
const
|
||||
_GetWindowMousePos: array[0..14] of Byte = (
|
||||
$53, $B8, $25, $00, $00, $00, $BB, $01, $00, $00, $00, $CD, $40, $5B, $C3
|
||||
);
|
||||
var
|
||||
GetWindowMousePosProc: TGetWindowMousePosProc;
|
||||
begin
|
||||
GetWindowMousePosProc := TGetWindowMousePosProc(@_GetWindowMousePos);
|
||||
Result := GetWindowMousePosProc();
|
||||
end;
|
||||
|
||||
procedure DrawButton(Left, Top, Width, Height, BackColor, Style, ID: Integer);
|
||||
type
|
||||
TDrawButtonProc = procedure(Left, Top, Width, Height, BackColor, Style, ID: Integer) stdcall;
|
||||
const
|
||||
_DrawButton: array[0..47] of Byte = (
|
||||
$53, $56, $B8, $08, $00, $00, $00, $8B, $5C, $24, $0C, $8B, $4C, $24, $10,
|
||||
$C1, $E3, $10, $C1, $E1, $10, $0B, $5C, $24, $14, $0B, $4C, $24, $18, $8B,
|
||||
$54, $24, $24, $0B, $54, $24, $20, $8B, $74, $24, $1C, $CD, $40, $5E, $5B,
|
||||
$C2, $1C, $00
|
||||
);
|
||||
var
|
||||
DrawButtonProc: TDrawButtonProc;
|
||||
begin
|
||||
DrawButtonProc := TDrawButtonProc(@_DrawButton);
|
||||
DrawButtonProc(Left, Top, Width, Height, BackColor, Style, ID);
|
||||
end;
|
||||
|
||||
procedure DrawText(X, Y: Integer; Text: PAnsiChar; ForeColor, BackColor, Flags, Count: Integer);
|
||||
type
|
||||
TDrawTextProc = procedure(X, Y: Integer; Text: PAnsiChar; ForeColor, BackColor, Flags, Count: Integer) stdcall;
|
||||
const
|
||||
_DrawText: array[0..46] of Byte = (
|
||||
$53, $57, $56, $B8, $04, $00, $00, $00, $8B, $5C, $24, $10, $C1, $E3, $10,
|
||||
$0B, $5C, $24, $14, $8B, $4C, $24, $24, $0B, $4C, $24, $1C, $8B, $54, $24,
|
||||
$18, $8B, $7C, $24, $20, $8B, $74, $24, $28, $CD, $40, $5E, $5F, $5B, $C2,
|
||||
$1C, $00
|
||||
);
|
||||
var
|
||||
DrawTextProc: TDrawTextProc;
|
||||
begin
|
||||
DrawTextProc := TDrawTextProc(@_DrawText);
|
||||
DrawTextProc(X, Y, Text, ForeColor, BackColor, Flags, Count);
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,47 @@
|
||||
unit LibINI;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
KolibriOS, Libs;
|
||||
|
||||
type
|
||||
TIniKeyCallback = procedure(FileName, SectionName, KeyName, KeyValue: PAnsiChar) stdcall;
|
||||
TIniSectionCallback = procedure(FileName, SectionName: PAnsiChar) stdcall;
|
||||
|
||||
var
|
||||
ini_enum_sections: function(FileName: PAnsiChar; Callback: TIniSectionCallback): Integer stdcall;
|
||||
ini_enum_keys: function(FileName, SectionName: PAnsiChar; Callback: TIniKeyCallback): Integer stdcall;
|
||||
ini_get_str: function(FileName, SectionName, KeyName: PAnsiChar; var Buf; BufLen: Integer; DefValue: PAnsiChar): Integer stdcall;
|
||||
ini_get_int: function(FileName, SectionName, KeyName: PAnsiChar; DefValue: Integer): Integer stdcall;
|
||||
ini_get_color: function(FileName, SectionName, KeyName: PAnsiChar; DefValue: Integer): Integer stdcall;
|
||||
ini_set_str: function(FileName, SectionName, KeyName: PAnsiChar; var Buf; BufLen: Integer): Integer stdcall;
|
||||
ini_set_int: function(FileName, SectionName, KeyName: PAnsiChar; Value: Integer): Integer stdcall;
|
||||
ini_set_color: function(FileName, SectionName, KeyName: PAnsiChar; Value: Integer): Integer stdcall;
|
||||
ini_get_shortcut: function(FileName, SectionName, KeyName: PAnsiChar; DefValue: Integer; var Modifiers: Integer): Integer stdcall;
|
||||
ini_del_section: function(FileName, SectionName: PAnsiChar): Integer stdcall;
|
||||
|
||||
procedure LibINI_initialization;
|
||||
|
||||
implementation
|
||||
|
||||
var
|
||||
hLibINI: Pointer;
|
||||
|
||||
procedure LibINI_initialization;
|
||||
begin
|
||||
hLibIni := LoadLibrary('/sys/lib/libini.obj');
|
||||
ini_enum_sections := GetProcAddress(hLibIni, 'ini_enum_sections');
|
||||
ini_enum_keys := GetProcAddress(hLibIni, 'ini_enum_keys');
|
||||
ini_get_str := GetProcAddress(hLibINI, 'ini_get_str');
|
||||
ini_get_int := GetProcAddress(hLibINI, 'ini_get_int');
|
||||
ini_get_color := GetProcAddress(hLibINI, 'ini_get_color');
|
||||
ini_set_str := GetProcAddress(hLibINI, 'ini_set_str');
|
||||
ini_set_int := GetProcAddress(hLibINI, 'ini_set_int');
|
||||
ini_set_color := GetProcAddress(hLibINI, 'ini_set_color');
|
||||
ini_get_shortcut := GetProcAddress(hLibINI, 'ini_get_shortcut');
|
||||
ini_del_section := GetProcAddress(hLibINI, 'ini_del_section');
|
||||
InitLibrary(GetProcAddress(hLibIni, 'lib_init'));
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,179 @@
|
||||
unit LibImg;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
KolibriOS, Libs;
|
||||
|
||||
// ╤яшёюъ шфхэЄшЇшърЄюЁют ЇюЁьрЄют
|
||||
const
|
||||
LIBIMG_FORMAT_BMP = 1;
|
||||
LIBIMG_FORMAT_ICO = 2;
|
||||
LIBIMG_FORMAT_CUR = 3;
|
||||
LIBIMG_FORMAT_GIF = 4;
|
||||
LIBIMG_FORMAT_PNG = 5;
|
||||
LIBIMG_FORMAT_JPEG = 6;
|
||||
LIBIMG_FORMAT_TGA = 7;
|
||||
LIBIMG_FORMAT_PCX = 8;
|
||||
LIBIMG_FORMAT_XCF = 9;
|
||||
LIBIMG_FORMAT_TIFF = 10;
|
||||
LIBIMG_FORMAT_PNM = 11;
|
||||
LIBIMG_FORMAT_WBMP = 12;
|
||||
LIBIMG_FORMAT_XBM = 13;
|
||||
LIBIMG_FORMAT_Z80 = 14;
|
||||
|
||||
// ╥шя√ ьрё°ЄрсшЁютрэш // ёююЄтхЄёЄтє■∙шх ярЁрьхЄЁ√ фы img_scale:
|
||||
LIBIMG_SCALE_NONE = 0; // эх ьрё°ЄрсшЁютрЄ№
|
||||
LIBIMG_SCALE_INTEGER = 1; // ъю¤ЇЇшЎшхэЄ ьрё°ЄрсшЁютрэш ; чрЁхчхЁтшЁютрэю 0
|
||||
LIBIMG_SCALE_TILE = 2; // эютр °шЁшэр; эютр т√ёюЄр
|
||||
LIBIMG_SCALE_STRETCH = 3; // эютр °шЁшэр; эютр т√ёюЄр
|
||||
LIBIMG_SCALE_FIT_BOTH = LIBIMG_SCALE_STRETCH;
|
||||
LIBIMG_SCALE_FIT_MIN = 4; // эютр °шЁшэр; эютр т√ёюЄр
|
||||
LIBIMG_SCALE_FIT_RECT = LIBIMG_SCALE_FIT_MIN;
|
||||
LIBIMG_SCALE_FIT_WIDTH = 5; // эютр °шЁшэр; эютр т√ёюЄр
|
||||
LIBIMG_SCALE_FIT_HEIGHT = 6; // эютр °шЁшэр; эютр т√ёюЄр
|
||||
LIBIMG_SCALE_FIT_MAX = 7; // эютр °шЁшэр; эютр т√ёюЄр
|
||||
|
||||
// └ыуюЁшЄь шэЄхЁяюы Ўшш
|
||||
LIBIMG_INTER_NONE = 0; // шёяюы№чютрЄ№ ё LIBIMG_SCALE_INTEGER, LIBIMG_SCALE_TILE ш Є.ф.
|
||||
LIBIMG_INTER_BILINEAR = 1;
|
||||
// LIBIMG_INTER_BICUBIC = 2;
|
||||
// LIBIMG_INTER_LANCZOS = 3;
|
||||
LIBIMG_INTER_DEFAULT = LIBIMG_INTER_BILINEAR;
|
||||
|
||||
// ╩юф√ ю°шсюъ
|
||||
LIBIMG_ERROR_OUT_OF_MEMORY = 1;
|
||||
LIBIMG_ERROR_FORMAT = 2;
|
||||
LIBIMG_ERROR_CONDITIONS = 3;
|
||||
LIBIMG_ERROR_BIT_DEPTH = 4;
|
||||
LIBIMG_ERROR_ENCODER = 5;
|
||||
LIBIMG_ERROR_SRC_TYPE = 6;
|
||||
LIBIMG_ERROR_SCALE = 7;
|
||||
LIBIMG_ERROR_INTER = 8;
|
||||
LIBIMG_ERROR_NOT_INPLEMENTED = 9;
|
||||
LIBIMG_ERROR_INVALID_INPUT = 10;
|
||||
|
||||
// ╘ыруш ъюфшЁютрэш
|
||||
// LIBIMG_ENCODE_STRICT_SPECIFIC = $01;
|
||||
LIBIMG_ENCODE_STRICT_BIT_DEPTH = $02;
|
||||
// LIBIMG_ENCODE_DELETE_ALPHA = $08;
|
||||
// LIBIMG_ENCODE_FLUSH_ALPHA = $10;
|
||||
|
||||
// ╟эрўхэш фы Image.ImageType
|
||||
// фюыцэ√ с√Є№ яюёыхфютрЄхы№э√ьш фы с√ёЄЁюую яхЁхъы■ўхэш т ЇєэъЎш ї яюффхЁцъш
|
||||
IMAGE_BPP8I = 1; // шэфхъёшЁютрээ√щ
|
||||
IMAGE_BPP24 = 2;
|
||||
IMAGE_BPP32 = 3;
|
||||
IMAGE_BPP15 = 4;
|
||||
IMAGE_BPP16 = 5;
|
||||
IMAGE_BPP1 = 6;
|
||||
IMAGE_BPP8G = 7; // юЄЄхэъш ёхЁюую
|
||||
IMAGE_BPP2I = 8;
|
||||
IMAGE_BPP4I = 9;
|
||||
IMAGE_BPP8A = 10; // юЄЄхэъш ёхЁюую ё ры№Їр-ърэрыюь; Єюы№ъю єЁютхэ№ яЁшыюцхэш !
|
||||
|
||||
// ┴шЄ√ т Image.Flags
|
||||
IMAGE_IS_ANIMATED = 1;
|
||||
|
||||
// ╘ыруш юЄЁрцхэш
|
||||
FLIP_VERTICAL = $01;
|
||||
FLIP_HORIZONTAL = $02;
|
||||
FLIP_BOTH = FLIP_VERTICAL or FLIP_HORIZONTAL;
|
||||
|
||||
// ╘ыруш яютюЁюЄр
|
||||
ROTATE_90_CW = $01;
|
||||
ROTATE_180 = $02;
|
||||
ROTATE_270_CW = $03;
|
||||
ROTATE_90_CCW = ROTATE_270_CW;
|
||||
ROTATE_270_CCW = ROTATE_90_CW;
|
||||
|
||||
type
|
||||
// ╙ърчрЄхыш
|
||||
PFormatsTableEntry = ^TFormatsTableEntry;
|
||||
PImage = ^TImage;
|
||||
PImageDecodeOptions = ^TImageDecodeOptions;
|
||||
|
||||
// ╥шя√ ЇєэъЎшщ фы ЁрсюЄ√ ё ЇюЁьрЄрьш
|
||||
TFormatIsFunction = function(Data: Pointer; Length: Integer): Integer stdcall;
|
||||
TFormatDecodeFunction = function(Data: Pointer; Length: Integer; Options: PImageDecodeOptions): PImage stdcall;
|
||||
TFormatEncodeFunction = function(Img: PImage; Common: Integer; Specific: Pointer): Pointer stdcall;
|
||||
|
||||
TFormatsTableEntry = packed record
|
||||
FormatId: Integer;
|
||||
IsFormat: TFormatIsFunction; // ЇєэъЎш яЁютхЁъш ЇюЁьрЄр
|
||||
Decode: TFormatDecodeFunction; // ЇєэъЎш фхъюфшЁютрэш
|
||||
Encode: TFormatEncodeFunction; // ЇєэъЎш ъюфшЁютрэш
|
||||
Capabilities: Integer; // тючьюцэюёЄш ЇюЁьрЄр (сшЄютр ьрёър)
|
||||
end;
|
||||
|
||||
TImage = packed record
|
||||
Checksum: Integer; // ((Width ROL 16) OR Height) XOR Data[0]; яюър шуэюЁшЁєхЄё
|
||||
Width: Integer;
|
||||
Height: Integer;
|
||||
Next: PImage; // єърчрЄхы№ эр ёыхфє■∙хх шчюсЁрцхэшх
|
||||
Previous: PImage; // єърчрЄхы№ эр яЁхф√фє∙хх шчюсЁрцхэшх
|
||||
ImageType: Integer; // юфшэ шч IMAGE_BPPN
|
||||
Data: Pointer; // єърчрЄхы№ эр фрээ√х шчюсЁрцхэш
|
||||
Palette: Pointer; // шёяюы№чєхЄё хёыш Type = IMAGE_BPP1, IMAGE_BPP2, IMAGE_BPP4 шыш IMAGE_BPP8I
|
||||
Extended: Pointer; // Ёрё°шЁхээ√х фрээ√х
|
||||
Flags: Integer; // сшЄютюх яюых
|
||||
Delay: Integer; // шёяюы№чєхЄё хёыш IMAGE_IS_ANIMATED єёЄрэютыхэ т Flags
|
||||
end;
|
||||
|
||||
TImageDecodeOptions = packed record
|
||||
UsedSize: Integer; // хёыш >=8, яюых BackgroundColor фхщёЄтшЄхы№эю, ш Єръ фрыхх
|
||||
BackgroundColor: Integer; // шёяюы№чєхЄё фы яЁючЁрўэ√ї шчюсЁрцхэшщ ъръ Їюэ
|
||||
end;
|
||||
|
||||
var
|
||||
hLibImg: Pointer;
|
||||
|
||||
// ╬ёэютэ√х ЇєэъЎшш сшсышюЄхъш
|
||||
img_is_img: function(Data: Pointer; Length: Integer): Integer stdcall;
|
||||
img_count: function(Img: PImage): Integer stdcall;
|
||||
img_decode: function(Data: Pointer; Length: Integer; Options: PImageDecodeOptions): PImage stdcall;
|
||||
img_encode: function(Img: PImage; Common: Integer; Specific: Pointer): Pointer stdcall;
|
||||
img_draw: procedure(Img: PImage; X, Y, Width, Height, XPos, YPos: Integer) stdcall;
|
||||
|
||||
// ╘єэъЎшш ёючфрэш ш єфрыхэш шчюсЁрцхэшщ
|
||||
img_create: function(Width, Height, ImgType: Integer): PImage stdcall;
|
||||
img_destroy: function(Img: PImage): Boolean stdcall;
|
||||
|
||||
// ╘єэъЎшш яЁхюсЁрчютрэш ш юсЁрсюЄъш шчюсЁрцхэшщ
|
||||
img_to_rgb2: procedure(Img: PImage; Output: Pointer) stdcall;
|
||||
|
||||
{* т фрээ√щ ьюьхэЄ ЇєэъЎшш эх ёюїЁрэ ■Є EBX Ч ¤Єю ю°шсър сшсышюЄхъш! *}
|
||||
//img_flip: function(Img: PImage; FlipKind: Integer): Boolean stdcall;
|
||||
//img_rotate: function(Img: PImage; RotateKind: Integer): Boolean stdcall;
|
||||
//*********************************************************************
|
||||
|
||||
img_convert: function(Src: PImage; Dst: PImage; DstType: Integer; Flags: Integer; Param: Integer): PImage stdcall;
|
||||
img_scale: function(Src: PImage; CropX, CropY, CropWidth, CropHeight: Integer; Dst: PImage; Scale, Inter, Param1, Param2: Integer): PImage stdcall;
|
||||
|
||||
procedure LibImg_initialization;
|
||||
|
||||
implementation
|
||||
|
||||
procedure LibImg_initialization;
|
||||
begin
|
||||
hLibImg := LoadLibrary('/sys/lib/libimg.obj');
|
||||
img_is_img := GetProcAddress(hLibImg, 'img_is_img');
|
||||
img_count := GetProcAddress(hLibImg, 'img_count');
|
||||
img_decode := GetProcAddress(hLibImg, 'img_decode');
|
||||
img_encode := GetProcAddress(hLibImg, 'img_encode');
|
||||
img_create := GetProcAddress(hLibImg, 'img_create');
|
||||
img_destroy := GetProcAddress(hLibImg, 'img_destroy');
|
||||
img_to_rgb2 := GetProcAddress(hLibImg, 'img_to_rgb2');
|
||||
|
||||
{* т фрээ√щ ьюьхэЄ ЇєэъЎшш эх ёюїЁрэ ■Є EBX Ч ¤Єю ю°шсър сшсышюЄхъш! *}
|
||||
//img_flip := GetProcAddress(hLibImg, 'img_flip');
|
||||
//img_rotate := GetProcAddress(hLibImg, 'img_rotate');
|
||||
//*********************************************************************
|
||||
|
||||
img_convert := GetProcAddress(hLibImg, 'img_convert');
|
||||
img_draw := GetProcAddress(hLibImg, 'img_draw');
|
||||
img_scale := GetProcAddress(hLibImg, 'img_scale');
|
||||
InitLibrary(GetProcAddress(hLibImg, 'lib_init'));
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,153 @@
|
||||
unit Libs;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
KolibriOS;
|
||||
|
||||
procedure InitLibrary(LibInit: Pointer);
|
||||
|
||||
implementation
|
||||
|
||||
procedure LibInitialize(MemoryAllocate, MemoryFree, MemoryReallocate, DLLLoad, LibInit: Pointer);
|
||||
type
|
||||
TLibInitializeProc = procedure(MemoryAllocate, MemoryFree, MemoryReallocate,
|
||||
DLLLoad, LibInit: Pointer) stdcall;
|
||||
const
|
||||
_LibInitialize: array[0..24] of Byte = (
|
||||
$60, $8B, $44, $24, $24, $8B, $5C, $24, $28, $8B, $4C, $24, $2C, $8B, $54,
|
||||
$24, $30, $FF, $54, $24, $34, $61, $C2, $14, $00
|
||||
);
|
||||
var
|
||||
LibInitializeProc: TLibInitializeProc;
|
||||
begin
|
||||
LibInitializeProc := TLibInitializeProc(@_LibInitialize);
|
||||
LibInitializeProc(MemoryAllocate,
|
||||
MemoryFree,
|
||||
MemoryReallocate,
|
||||
DLLLoad,
|
||||
LibInit);
|
||||
end;
|
||||
|
||||
function MemoryAllocate(Bytes: Integer): Pointer stdcall;
|
||||
type
|
||||
TMemoryAllocateProc = function(Bytes: Integer): Pointer stdcall;
|
||||
const
|
||||
_MemoryAllocate: array[0..22] of Byte = (
|
||||
$51, $53, $B8, $44, $00, $00, $00, $BB, $0C, $00, $00, $00, $8B, $4C, $24,
|
||||
$0C, $CD, $40, $5B, $59, $C2, $04, $00
|
||||
);
|
||||
var
|
||||
MemoryAllocateProc: TMemoryAllocateProc;
|
||||
begin
|
||||
MemoryAllocateProc := TMemoryAllocateProc(@_MemoryAllocate);
|
||||
Result := MemoryAllocateProc(Bytes);
|
||||
end;
|
||||
|
||||
function MemoryFree(MemPtr: Pointer): Integer stdcall;
|
||||
type
|
||||
TMemoryFreeProc = function(MemPtr: Pointer): Integer stdcall;
|
||||
const
|
||||
_MemoryFree: array[0..22] of Byte = (
|
||||
$51, $53, $B8, $44, $00, $00, $00, $BB, $0D, $00, $00, $00, $8B, $4C, $24,
|
||||
$0C, $CD, $40, $5B, $59, $C2, $04, $00
|
||||
);
|
||||
var
|
||||
MemoryFreeProc: TMemoryFreeProc;
|
||||
begin
|
||||
MemoryFreeProc := TMemoryFreeProc(@_MemoryFree);
|
||||
Result := MemoryFreeProc(MemPtr);
|
||||
end;
|
||||
|
||||
function MemoryReallocate(MemPtr: Pointer; Bytes: Integer): Pointer stdcall;
|
||||
type
|
||||
TMemoryReallocateProc = function(MemPtr: Pointer; Bytes: Integer): Pointer stdcall;
|
||||
const
|
||||
_MemoryReallocate: array[0..28] of Byte = (
|
||||
$53, $51, $52, $B8, $44, $00, $00, $00, $BB, $14, $00, $00, $00, $8B, $4C,
|
||||
$24, $14, $8B, $54, $24, $10, $CD, $40, $5A, $59, $5B, $C2, $08, $00
|
||||
);
|
||||
var
|
||||
MemoryReallocateProc: TMemoryReallocateProc;
|
||||
begin
|
||||
MemoryReallocateProc := TMemoryReallocateProc(@_MemoryReallocate);
|
||||
Result := MemoryReallocateProc(MemPtr, Bytes);
|
||||
end;
|
||||
|
||||
const
|
||||
LIB_PATH = '/sys/lib/';
|
||||
|
||||
type
|
||||
PNameAddr = ^TNameAddr;
|
||||
TNameAddr = packed record
|
||||
Name: PAnsiChar;
|
||||
Addr: Pointer;
|
||||
end;
|
||||
|
||||
PAddrName = ^TAddrName;
|
||||
TAddrName = packed record
|
||||
Addr: Pointer;
|
||||
Name: PAnsiChar;
|
||||
end;
|
||||
|
||||
function StrEqual(Str1, Str2: PAnsiChar): Boolean;
|
||||
begin
|
||||
while (Str1^ = Str2^) and (Str1^ <> #0) do
|
||||
begin
|
||||
Inc(Str1);
|
||||
Inc(Str2);
|
||||
end;
|
||||
Result := Str1^ = Str2^;
|
||||
end;
|
||||
|
||||
procedure StrCopy(StrFrom, StrTo: PAnsiChar);
|
||||
begin
|
||||
repeat
|
||||
StrTo^ := StrFrom^;
|
||||
Inc(StrFrom);
|
||||
Inc(StrTo);
|
||||
until StrFrom[-1] = #0;
|
||||
end;
|
||||
|
||||
function DLLLoad(ImportTable: PAddrName): Integer stdcall;
|
||||
var
|
||||
ExportTable: PNameAddr;
|
||||
ProcAddr: Pointer;
|
||||
Name: PPAnsiChar;
|
||||
LibPath: array [0..32] of AnsiChar;
|
||||
begin
|
||||
Result := 1;
|
||||
StrCopy(LIB_PATH, @LibPath[0]);
|
||||
while ImportTable^.Addr <> nil do
|
||||
begin
|
||||
StrCopy(ImportTable^.Name, @LibPath[Length(LIB_PATH)]);
|
||||
ExportTable := LoadLibrary(LibPath);
|
||||
if ExportTable = nil then
|
||||
Exit;
|
||||
Name := PPAnsiChar(ImportTable^.Addr);
|
||||
while Name^ <> nil do
|
||||
begin
|
||||
ProcAddr := GetProcAddress(ExportTable, Name^);
|
||||
if ProcAddr <> nil then
|
||||
Name^ := PAnsiChar(ProcAddr)
|
||||
else
|
||||
Exit;
|
||||
Inc(Name);
|
||||
end;
|
||||
if StrEqual(ExportTable^.Name, 'lib_init') then
|
||||
InitLibrary(ExportTable^.Addr);
|
||||
Inc(ImportTable);
|
||||
end;
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
procedure InitLibrary(LibInit: Pointer);
|
||||
begin
|
||||
LibInitialize(@MemoryAllocate,
|
||||
@MemoryFree,
|
||||
@MemoryReallocate,
|
||||
@DLLLoad,
|
||||
LibInit);
|
||||
end;
|
||||
|
||||
end.
|
||||
Loaded 100 of 248 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user