forked from KolibriOS/kolibrios
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
da418f65b3 | ||
|
bfc59f6636 | ||
|
f7bdaa8909 | ||
|
2dd6a1516e | ||
5593d344cd | |||
|
28668acd86 | ||
|
cb733c6d1d | ||
|
cf354ec8d3 | ||
c8e9e5a2a7 | |||
|
b815aee084 | ||
|
7a6d042da7 | ||
2d9007da32 | |||
|
b558f23604 | ||
|
dd5a6a7316 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -7,3 +7,5 @@ ehthumbs_vista.db
|
||||
### macOS ###
|
||||
.DS_Store
|
||||
._*
|
||||
programs/cmm/cmm.code-workspace
|
||||
programs/cmm/menu/.gitignore
|
||||
|
@ -475,6 +475,7 @@ tup.append_table(img_files, {
|
||||
{"File Managers/KFAR", VAR_PROGS .. "/fs/kfar/trunk/kfar"},
|
||||
{"File Managers/OPENDIAL", VAR_PROGS .. "/fs/opendial/opendial"},
|
||||
{"GAMES/15", VAR_PROGS .. "/games/15/trunk/15"},
|
||||
{"GAMES/DINO", VAR_PROGS .. "/games/dino/dino"},
|
||||
{"GAMES/FREECELL", VAR_PROGS .. "/games/freecell/freecell"},
|
||||
{"GAMES/GOMOKU", VAR_PROGS .. "/games/gomoku/trunk/gomoku"},
|
||||
{"GAMES/LIGHTS", VAR_PROGS .. "/games/sq_game/trunk/SQ_GAME"},
|
||||
@ -590,6 +591,7 @@ tup.append_table(extra_files, {
|
||||
{"kolibrios/demos/life3", VAR_PROGS .. "/games/life3/trunk/life3"},
|
||||
{"kolibrios/demos/qjulia", VAR_PROGS .. "/demos/qjulia/trunk/qjulia"},
|
||||
{"kolibrios/develop/utils/koldbg", VAR_PROGS .. "/develop/koldbg/koldbg"},
|
||||
{"kolibrios/develop/utils/charset_checker", VAR_PROGS .. "/other/charset_checker/charchck"},
|
||||
{"kolibrios/games/Almaz", VAR_PROGS .. "/games/almaz/almaz"},
|
||||
{"kolibrios/games/arcanii", VAR_PROGS .. "/games/arcanii/trunk/arcanii"},
|
||||
{"kolibrios/games/bomber/bomber", VAR_PROGS .. "/games/bomber/bomber"},
|
||||
|
@ -1,9 +1,8 @@
|
||||
[rbmenu]
|
||||
Processes=cpu
|
||||
Themes=desktop
|
||||
Theme settings=skincfg
|
||||
Background=/sys/media/palitra
|
||||
Device setup=setup
|
||||
Shell=shell
|
||||
System panel=syspanel
|
||||
[00]
|
||||
name=KFM2
|
||||
path=/SYS/FILE MANAGERS/KFM2
|
||||
@ -22,23 +21,23 @@ y=68
|
||||
name=EOLITE
|
||||
path=/SYS/FILE MANAGERS/EOLITE
|
||||
param=
|
||||
ico=1
|
||||
ico=0
|
||||
x=68
|
||||
y=0
|
||||
[03]
|
||||
name=SHELL
|
||||
path=SHELL
|
||||
param=
|
||||
ico=2
|
||||
x=136
|
||||
y=0
|
||||
ico=1
|
||||
x=-203
|
||||
y=136
|
||||
[04]
|
||||
name=KFAR
|
||||
path=/SYS/FILE MANAGERS/KFAR
|
||||
param=
|
||||
ico=16
|
||||
x=68
|
||||
y=68
|
||||
x=136
|
||||
y=0
|
||||
[05]
|
||||
name=RDSAVE
|
||||
path=RDSAVE
|
||||
@ -64,7 +63,7 @@ y=68
|
||||
name=KPACK
|
||||
path=KPACK
|
||||
param=
|
||||
ico=10
|
||||
ico=99
|
||||
x=-67
|
||||
y=0
|
||||
[09]
|
||||
@ -89,10 +88,10 @@ ico=66
|
||||
x=-135
|
||||
y=-67
|
||||
[0C]
|
||||
name=MBLOCKS
|
||||
path=/SYS/GAMES/MBLOCKS
|
||||
name=TETRIS
|
||||
path=/SYS/GAMES/TETRIS
|
||||
param=
|
||||
ico=11
|
||||
ico=47
|
||||
x=-67
|
||||
y=-135
|
||||
[0D]
|
||||
@ -107,8 +106,8 @@ name=15
|
||||
path=/SYS/GAMES/15
|
||||
param=
|
||||
ico=34
|
||||
x=-271
|
||||
y=-67
|
||||
x=-67
|
||||
y=-203
|
||||
[0F]
|
||||
name=DOCPACK
|
||||
path=DOCPACK
|
||||
@ -170,8 +169,8 @@ name=FLAPPY-BIRD
|
||||
path=/SYS/GAMES/FLPYBIRD
|
||||
param=
|
||||
ico=49
|
||||
x=-271
|
||||
y=-135
|
||||
x=-135
|
||||
y=-203
|
||||
[18]
|
||||
name=KOSILKA
|
||||
path=/SYS/GAMES/KOSILKA
|
||||
@ -215,16 +214,44 @@ ico=6
|
||||
x=-67
|
||||
y=136
|
||||
[1E]
|
||||
name=CALC
|
||||
path=CALC
|
||||
param=
|
||||
ico=4
|
||||
x=-203
|
||||
y=68
|
||||
[1F]
|
||||
name=APP+
|
||||
path=app_plus
|
||||
param=
|
||||
ico=27
|
||||
x=204
|
||||
y=68
|
||||
[1F]
|
||||
name=DIFF
|
||||
path=/sys/DEVELOP/DIFF
|
||||
param=
|
||||
ico=84
|
||||
x=-203
|
||||
y=68
|
||||
[20]
|
||||
name=CEDIT
|
||||
path=/sys/develop/cedit
|
||||
param=
|
||||
ico=58
|
||||
x=68
|
||||
y=68
|
||||
[21]
|
||||
name=CALC
|
||||
path=CALC
|
||||
param=
|
||||
ico=4
|
||||
x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
y=136
|
||||
[23]
|
||||
name=DINO
|
||||
path=/sys/games/dino
|
||||
param=
|
||||
ico=129
|
||||
x=-203
|
||||
y=-203
|
Binary file not shown.
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 44 KiB |
@ -16,6 +16,7 @@ Freecell=games/freecell,68
|
||||
Pong=games/pong,101
|
||||
Pong3=games/pong3,12
|
||||
Arcanii=/kg/arcanii,12
|
||||
Dino=games/dino,129
|
||||
|
||||
[Arcade]
|
||||
LaserTank=/kg/lasertank/lasertank,72
|
||||
|
@ -106,8 +106,8 @@ name=15
|
||||
path=/SYS/GAMES/15
|
||||
param=
|
||||
ico=34
|
||||
x=-271
|
||||
y=-67
|
||||
x=-67
|
||||
y=-203
|
||||
[0F]
|
||||
name=DOCPACK
|
||||
path=DOCPACK
|
||||
@ -169,8 +169,8 @@ name=FLAPPY-BIRD
|
||||
path=/SYS/GAMES/FLPYBIRD
|
||||
param=
|
||||
ico=49
|
||||
x=-271
|
||||
y=-135
|
||||
x=-135
|
||||
y=-203
|
||||
[18]
|
||||
name=KOSILKA
|
||||
path=/SYS/GAMES/KOSILKA
|
||||
@ -248,3 +248,10 @@ param=
|
||||
ico=125
|
||||
x=204
|
||||
y=136
|
||||
[23]
|
||||
name=DINO
|
||||
path=/sys/games/dino
|
||||
param=
|
||||
ico=129
|
||||
x=-203
|
||||
y=-203
|
||||
|
@ -106,8 +106,8 @@ name=15
|
||||
path=/SYS/GAMES/15
|
||||
param=
|
||||
ico=34
|
||||
x=-271
|
||||
y=-67
|
||||
x=-67
|
||||
y=-203
|
||||
[0F]
|
||||
name=DOCPACK
|
||||
path=DOCPACK
|
||||
@ -169,8 +169,8 @@ name=FLAPPY-BIRD
|
||||
path=/SYS/GAMES/FLPYBIRD
|
||||
param=
|
||||
ico=49
|
||||
x=-271
|
||||
y=-135
|
||||
x=-135
|
||||
y=-203
|
||||
[18]
|
||||
name=KOSILKA
|
||||
path=/SYS/GAMES/KOSILKA
|
||||
@ -248,3 +248,10 @@ param=
|
||||
ico=125
|
||||
x=204
|
||||
y=136
|
||||
[23]
|
||||
name=DINO
|
||||
path=/sys/games/dino
|
||||
param=
|
||||
ico=129
|
||||
x=-203
|
||||
y=-203
|
||||
|
@ -106,8 +106,8 @@ name=15
|
||||
path=/SYS/GAMES/15
|
||||
param=
|
||||
ico=34
|
||||
x=-271
|
||||
y=-67
|
||||
x=-67
|
||||
y=-203
|
||||
[0F]
|
||||
name=DOCPACK
|
||||
path=DOCPACK
|
||||
@ -169,8 +169,8 @@ name=FLAPPY-BIRD
|
||||
path=/SYS/GAMES/FLPYBIRD
|
||||
param=
|
||||
ico=49
|
||||
x=-271
|
||||
y=-135
|
||||
x=-135
|
||||
y=-203
|
||||
[18]
|
||||
name=KOSILKA
|
||||
path=/SYS/GAMES/KOSILKA
|
||||
@ -248,3 +248,10 @@ param=
|
||||
ico=125
|
||||
x=204
|
||||
y=136
|
||||
[23]
|
||||
name=DINO
|
||||
path=/sys/games/dino
|
||||
param=
|
||||
ico=129
|
||||
x=-203
|
||||
y=-203
|
||||
|
@ -106,8 +106,8 @@ name=15
|
||||
path=/SYS/GAMES/15
|
||||
param=
|
||||
ico=34
|
||||
x=-271
|
||||
y=-67
|
||||
x=-67
|
||||
y=-203
|
||||
[0F]
|
||||
name=DOCPACK
|
||||
path=DOCPACK
|
||||
@ -169,8 +169,8 @@ name=FLAPPY-BIRD
|
||||
path=/SYS/GAMES/FLPYBIRD
|
||||
param=
|
||||
ico=49
|
||||
x=-271
|
||||
y=-135
|
||||
x=-135
|
||||
y=-203
|
||||
[18]
|
||||
name=KOSILKA
|
||||
path=/SYS/GAMES/KOSILKA
|
||||
@ -248,3 +248,10 @@ param=
|
||||
ico=125
|
||||
x=204
|
||||
y=136
|
||||
[23]
|
||||
name=DINO
|
||||
path=/sys/games/dino
|
||||
param=
|
||||
ico=129
|
||||
x=-203
|
||||
y=-203
|
||||
|
@ -16,6 +16,7 @@ Freecell=games/freecell,68
|
||||
Pong=games/pong,101
|
||||
Pong3=games/pong3,12
|
||||
Arcanii=/kg/arcanii,12
|
||||
Dino=games/dino,129
|
||||
|
||||
[€àª ¤ë]
|
||||
LaserTank=/kg/lasertank/lasertank,72
|
||||
|
@ -106,8 +106,8 @@ name=15
|
||||
path=/SYS/GAMES/15
|
||||
param=
|
||||
ico=34
|
||||
x=-271
|
||||
y=-67
|
||||
x=-67
|
||||
y=-203
|
||||
[0F]
|
||||
name=DOCPACK
|
||||
path=DOCPACK
|
||||
@ -169,8 +169,8 @@ name=FLAPPY-BIRD
|
||||
path=/SYS/GAMES/FLPYBIRD
|
||||
param=
|
||||
ico=49
|
||||
x=-271
|
||||
y=-135
|
||||
x=-135
|
||||
y=-203
|
||||
[18]
|
||||
name=KOSILKA
|
||||
path=/SYS/GAMES/KOSILKA
|
||||
@ -248,3 +248,10 @@ param=
|
||||
ico=125
|
||||
x=204
|
||||
y=136
|
||||
[23]
|
||||
name=DINO
|
||||
path=/sys/games/dino
|
||||
param=
|
||||
ico=129
|
||||
x=-203
|
||||
y=-203
|
||||
|
3
drivers/serial/Tupfile.lua
Normal file
3
drivers/serial/Tupfile.lua
Normal file
@ -0,0 +1,3 @@
|
||||
if tup.getconfig("NO_FASM") ~= "" then return end
|
||||
ROOT = "../.."
|
||||
tup.rule("serial.asm", "fasm %f %o " .. tup.getconfig("PESTRIP_CMD") .. tup.getconfig("KPACK_CMD"), "%B.sys")
|
272
drivers/serial/common.inc
Executable file
272
drivers/serial/common.inc
Executable file
@ -0,0 +1,272 @@
|
||||
SERIAL_API_GET_VERSION = 0
|
||||
SERIAL_API_SRV_ADD_PORT = 1
|
||||
SERIAL_API_SRV_REMOVE_PORT = 2
|
||||
SERIAL_API_SRV_HANDLE_EVENT = 3
|
||||
SERIAL_API_OPEN_PORT = 4
|
||||
SERIAL_API_CLOSE_PORT = 5
|
||||
SERIAL_API_SETUP_PORT = 6
|
||||
SERIAL_API_READ = 7
|
||||
SERIAL_API_WRITE = 8
|
||||
|
||||
SERIAL_API_ERR_PORT_INVALID = 1
|
||||
SERIAL_API_ERR_PORT_BUSY = 2
|
||||
SERIAL_API_ERR_CONF = 3
|
||||
|
||||
SERIAL_EVT_TXE = 1 ; tx fifo or register is empty, all data has been sent
|
||||
SERIAL_EVT_RXNE = 2 ; rx fifo or register is not empty
|
||||
|
||||
SERIAL_CONF_PARITY_NONE = 0
|
||||
SERIAL_CONF_PARITY_EVEN = 1
|
||||
SERIAL_CONF_PARITY_ODD = 2
|
||||
SERIAL_CONF_PARITY_MARK = 3
|
||||
SERIAL_CONF_PARITY_SPACE = 4
|
||||
|
||||
SERIAL_CONF_FLOW_CTRL_NONE = 0
|
||||
|
||||
struct SP_DRIVER
|
||||
size dd ? ; size of this struct
|
||||
startup dd ? ; void __stdcall (*startup)(void *drv_data, const struct serial_conf *conf);
|
||||
shutdown dd ? ; void __stdcall (*shutdown)(void *drv_data);
|
||||
reconf dd ? ; void __stdcall (*reconf)(void *drv_data, const struct serial_conf *conf);
|
||||
tx dd ? ; void __stdcall (*tx)(void *drv_data);
|
||||
ends
|
||||
|
||||
struct SP_CONF
|
||||
size dd ? ; size of this struct
|
||||
baudrate dd ?
|
||||
word_size db ?
|
||||
stop_bits db ?
|
||||
parity db ?
|
||||
flow_ctrl db ?
|
||||
ends
|
||||
|
||||
proc serial_add_port stdcall, drv:dword, drv_data:dword
|
||||
locals
|
||||
handler dd ?
|
||||
io_code dd ?
|
||||
input dd ?
|
||||
inp_size dd ?
|
||||
output dd ?
|
||||
out_size dd ?
|
||||
endl
|
||||
mov eax, [serial_drv_entry]
|
||||
mov [handler], eax
|
||||
mov [io_code], SERIAL_API_SRV_ADD_PORT
|
||||
lea eax, [drv]
|
||||
mov [input], eax
|
||||
mov [inp_size], 8
|
||||
xor eax, eax
|
||||
mov [output], eax
|
||||
mov [out_size], eax
|
||||
lea eax, [handler]
|
||||
push esi edi
|
||||
invoke ServiceHandler, eax
|
||||
pop edi esi
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_remove_port stdcall, port:dword
|
||||
locals
|
||||
handler dd ?
|
||||
io_code dd ?
|
||||
input dd ?
|
||||
inp_size dd ?
|
||||
output dd ?
|
||||
out_size dd ?
|
||||
endl
|
||||
mov eax, [serial_drv_entry]
|
||||
mov [handler], eax
|
||||
mov [io_code], SERIAL_API_SRV_REMOVE_PORT
|
||||
lea eax, [port]
|
||||
mov [input], eax
|
||||
mov [inp_size], 4
|
||||
xor eax, eax
|
||||
mov [output], eax
|
||||
mov [out_size], eax
|
||||
lea eax, [handler]
|
||||
push esi edi
|
||||
invoke ServiceHandler, eax
|
||||
pop edi esi
|
||||
ret
|
||||
endp
|
||||
|
||||
; see SERIAL_EVT_*
|
||||
proc serial_handle_event stdcall, port:dword, event:dword, count:dword, buff:dword
|
||||
locals
|
||||
handler dd ?
|
||||
io_code dd ?
|
||||
input dd ?
|
||||
inp_size dd ?
|
||||
output dd ?
|
||||
out_size dd ?
|
||||
endl
|
||||
mov eax, [serial_drv_entry]
|
||||
mov [handler], eax
|
||||
mov [io_code], SERIAL_API_SRV_HANDLE_EVENT
|
||||
lea eax, [port]
|
||||
mov [input], eax
|
||||
mov [inp_size], 16
|
||||
xor eax, eax
|
||||
mov [output], eax
|
||||
mov [out_size], eax
|
||||
lea eax, [handler]
|
||||
push esi edi
|
||||
invoke ServiceHandler, eax
|
||||
pop edi esi
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_init
|
||||
lea ecx, [serial_drv_name]
|
||||
mcall SF_SYS_MISC, SSF_LOAD_DRIVER
|
||||
mov [serial_drv_handle], eax
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_open stdcall uses ebx, port_id:dword, conf:dword, handle:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
.input dd ?
|
||||
.inp_size dd ?
|
||||
.output dd ?
|
||||
.out_size dd ?
|
||||
endl
|
||||
push [conf]
|
||||
push [port_id]
|
||||
mov eax, [serial_drv_handle]
|
||||
mov [.handler], eax
|
||||
mov dword [.io_code], SERIAL_API_OPEN_PORT
|
||||
mov [.input], esp
|
||||
mov dword [.inp_size], 8
|
||||
mov eax, [handle]
|
||||
mov [.output], eax
|
||||
mov dword [.out_size], 4
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
add esp, 8
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_close stdcall uses ebx, handle:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
.input dd ?
|
||||
.inp_size dd ?
|
||||
.output dd ?
|
||||
.out_size dd ?
|
||||
endl
|
||||
push [handle]
|
||||
mov eax, [serial_drv_handle]
|
||||
mov [.handler], eax
|
||||
mov dword [.io_code], SERIAL_API_CLOSE_PORT
|
||||
mov [.input], esp
|
||||
mov dword [.inp_size], 4
|
||||
mov dword [.output], 0
|
||||
mov dword [.out_size], 0
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
add esp, 4
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_setup stdcall uses ebx, handle:dword, conf:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
.input dd ?
|
||||
.inp_size dd ?
|
||||
.output dd ?
|
||||
.out_size dd ?
|
||||
endl
|
||||
push [conf]
|
||||
push [handle]
|
||||
mov eax, [serial_drv_handle]
|
||||
mov [.handler], eax
|
||||
mov dword [.io_code], SERIAL_API_SETUP_PORT
|
||||
mov [.input], esp
|
||||
mov dword [.inp_size], 8
|
||||
sub esp, 4
|
||||
mov [.output], esp
|
||||
mov dword [.out_size], 4
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
pop eax
|
||||
add esp, 8
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_read stdcall uses ebx, handle:dword, dest:dword, count_ptr:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
.input dd ?
|
||||
.inp_size dd ?
|
||||
.output dd ?
|
||||
.out_size dd ?
|
||||
endl
|
||||
mov eax, [count_ptr]
|
||||
push dword [eax]
|
||||
push [dest]
|
||||
push [handle]
|
||||
mov eax, [serial_drv_handle]
|
||||
mov [.handler], eax
|
||||
mov dword [.io_code], SERIAL_API_READ
|
||||
mov [.input], esp
|
||||
mov dword [.inp_size], 12
|
||||
sub esp, 4
|
||||
mov [.output], esp
|
||||
mov [.out_size], 4
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
pop ecx
|
||||
mov edx, [count_ptr]
|
||||
mov [edx], ecx
|
||||
add esp, 12
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_write stdcall uses ebx, handle:dword, src:dword, count_ptr:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
.input dd ?
|
||||
.inp_size dd ?
|
||||
.output dd ?
|
||||
.out_size dd ?
|
||||
endl
|
||||
mov eax, [count_ptr]
|
||||
push dword [eax]
|
||||
push [src]
|
||||
push [handle]
|
||||
mov eax, [serial_drv_handle]
|
||||
mov [.handler], eax
|
||||
mov dword [.io_code], SERIAL_API_WRITE
|
||||
mov [.input], esp
|
||||
mov dword [.inp_size], 12
|
||||
sub esp, 4
|
||||
mov dword [.output], esp
|
||||
mov dword [.out_size], 4
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
pop ecx
|
||||
mov edx, [count_ptr]
|
||||
mov [edx], ecx
|
||||
add esp, 12
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
serial_drv_name db "SERIAL", 0
|
||||
serial_drv_handle dd ?
|
178
drivers/serial/ring_buf.inc
Executable file
178
drivers/serial/ring_buf.inc
Executable file
@ -0,0 +1,178 @@
|
||||
struct RING_BUF
|
||||
start_ptr dd ? ; Pointer to start of buffer
|
||||
end_ptr dd ? ; Pointer to end of buffer
|
||||
read_ptr dd ? ; Read pointer
|
||||
write_ptr dd ? ; Write pointer
|
||||
size dd ? ; Size of buffer
|
||||
ends
|
||||
|
||||
;bool __fastcall ring_buf_create(struct RING_BUF *buf, u32 size)
|
||||
align 4
|
||||
proc ring_buf_create
|
||||
push ecx
|
||||
push edx
|
||||
invoke CreateRingBuffer, edx, PG_SW
|
||||
pop edx
|
||||
pop ecx
|
||||
test eax, eax
|
||||
jz .exit
|
||||
|
||||
mov [ecx + RING_BUF.start_ptr], eax
|
||||
mov [ecx + RING_BUF.write_ptr], eax
|
||||
mov [ecx + RING_BUF.read_ptr], eax
|
||||
add eax, edx
|
||||
mov [ecx + RING_BUF.end_ptr], eax
|
||||
mov [ecx + RING_BUF.size], edx
|
||||
or eax, 1
|
||||
.exit:
|
||||
ret
|
||||
endp
|
||||
|
||||
;void __fastcall ring_buf_destroy(struct RING_BUF *buf)
|
||||
align 4
|
||||
proc ring_buf_destroy
|
||||
xor eax, eax
|
||||
mov [ecx + RING_BUF.write_ptr], eax
|
||||
mov [ecx + RING_BUF.read_ptr], eax
|
||||
mov [ecx + RING_BUF.end_ptr], eax
|
||||
mov [ecx + RING_BUF.size], eax
|
||||
xchg eax, [ecx + RING_BUF.start_ptr]
|
||||
invoke KernelFree, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
;u32 __fastcall ring_buf_count(struct RING_BUF *buf)
|
||||
align 4
|
||||
proc ring_buf_count
|
||||
mov eax, [ecx + RING_BUF.write_ptr]
|
||||
mov edx, [ecx + RING_BUF.read_ptr]
|
||||
cmp eax, edx
|
||||
jb @f
|
||||
sub eax, edx
|
||||
ret
|
||||
|
||||
@@:
|
||||
sub eax, edx
|
||||
add eax, [ecx + RING_BUF.size]
|
||||
ret
|
||||
endp
|
||||
|
||||
;u32 __fastcall ring_buf_free(struct RING_BUF *buf)
|
||||
align 4
|
||||
proc ring_buf_free
|
||||
mov eax, [ecx + RING_BUF.read_ptr]
|
||||
mov edx, [ecx + RING_BUF.write_ptr]
|
||||
cmp eax, edx
|
||||
jae @f
|
||||
sub eax, edx
|
||||
dec eax
|
||||
ret
|
||||
|
||||
@@:
|
||||
sub eax, edx
|
||||
dec eax
|
||||
add eax, [ecx + RING_BUF.size]
|
||||
ret
|
||||
endp
|
||||
|
||||
;u32 __stdcall ring_buf_write(struct RING_BUF *buf, const u32 *src, u32 size)
|
||||
align 4
|
||||
proc ring_buf_write stdcall uses esi edi, buf, src, size
|
||||
mov ecx, [buf]
|
||||
call ring_buf_free
|
||||
test eax, eax
|
||||
jz .exit
|
||||
|
||||
mov esi, [src]
|
||||
mov edi, [ecx + RING_BUF.write_ptr]
|
||||
mov ecx, [size]
|
||||
cmp ecx, eax
|
||||
jbe .copy
|
||||
mov ecx, eax
|
||||
.copy:
|
||||
mov eax, ecx
|
||||
cld
|
||||
shr ecx, 1
|
||||
jnc .nb
|
||||
movsb
|
||||
.nb:
|
||||
shr ecx, 1
|
||||
jnc .nw
|
||||
movsw
|
||||
.nw:
|
||||
test ecx, ecx
|
||||
jz .nd
|
||||
rep movsd
|
||||
.nd:
|
||||
mov ecx, [buf]
|
||||
cmp edi, [ecx + RING_BUF.end_ptr]
|
||||
jb @f
|
||||
sub edi, [ecx + RING_BUF.size]
|
||||
@@:
|
||||
mov [ecx + RING_BUF.write_ptr], edi
|
||||
.exit:
|
||||
ret
|
||||
endp
|
||||
|
||||
;u32 __stdcall ring_buf_read(struct RING_BUF *buf, u32 *dst, u32 size)
|
||||
align 4
|
||||
proc ring_buf_read stdcall uses ebx esi edi, buf, dst, size
|
||||
mov ecx, [buf]
|
||||
call ring_buf_count
|
||||
test eax, eax
|
||||
jz .exit
|
||||
|
||||
mov esi, [ecx + RING_BUF.read_ptr]
|
||||
mov edi, [dst]
|
||||
mov ecx, [size]
|
||||
cmp ecx, eax
|
||||
jbe .copy
|
||||
mov ecx, eax
|
||||
.copy:
|
||||
mov eax, ecx
|
||||
shr ecx, 1
|
||||
jnc .nb
|
||||
cld
|
||||
movsb
|
||||
.nb:
|
||||
shr ecx, 1
|
||||
jnc .nw
|
||||
movsw
|
||||
.nw:
|
||||
test ecx, ecx
|
||||
jz .nd
|
||||
rep movsd
|
||||
.nd:
|
||||
mov ecx, [buf]
|
||||
cmp esi, [ecx + RING_BUF.end_ptr]
|
||||
jb .save_ptr
|
||||
sub esi, [ecx + RING_BUF.size]
|
||||
.save_ptr:
|
||||
mov [ecx + RING_BUF.read_ptr], esi
|
||||
.exit:
|
||||
ret
|
||||
endp
|
||||
|
||||
;u32 __fastcall ring_buf_discard(struct RING_BUF *buf, u32 size)
|
||||
align 4
|
||||
proc ring_buf_discard
|
||||
push ecx
|
||||
push edx
|
||||
call ring_buf_count
|
||||
pop edx
|
||||
pop ecx
|
||||
|
||||
cmp eax, edx
|
||||
jae .discard
|
||||
mov edx, eax
|
||||
.discard:
|
||||
push edx
|
||||
add edx, [ecx + RING_BUF.read_ptr]
|
||||
cmp edx, [ecx + RING_BUF.end_ptr]
|
||||
jb .save_ptr
|
||||
sub edx, [ecx + RING_BUF.size]
|
||||
.save_ptr:
|
||||
mov [ecx + RING_BUF.read_ptr], edx
|
||||
pop eax
|
||||
ret
|
||||
endp
|
675
drivers/serial/serial.asm
Executable file
675
drivers/serial/serial.asm
Executable file
@ -0,0 +1,675 @@
|
||||
format PE DLL native 0.05
|
||||
entry START
|
||||
|
||||
L_DBG = 1
|
||||
L_ERR = 2
|
||||
|
||||
__DEBUG__ = 0
|
||||
__DEBUG_LEVEL__ = L_DBG
|
||||
|
||||
SERIAL_RING_BUF_SIZE = 32768
|
||||
|
||||
API_VERSION = 1
|
||||
|
||||
section '.flat' readable writable executable
|
||||
|
||||
include '../struct.inc'
|
||||
include '../proc32.inc'
|
||||
include '../fdo.inc'
|
||||
include '../macros.inc'
|
||||
include '../peimport.inc'
|
||||
|
||||
include 'common.inc'
|
||||
include 'ring_buf.inc'
|
||||
include 'uart16550.inc'
|
||||
|
||||
struct SERIAL_OBJ
|
||||
magic dd ?
|
||||
destroy dd ?
|
||||
fd dd ?
|
||||
bk dd ?
|
||||
pid dd ?
|
||||
port dd ? ; pointer to SERIAL_PORT
|
||||
ends
|
||||
|
||||
struct SERIAL_PORT
|
||||
fd dd ?
|
||||
bk dd ?
|
||||
id dd ? ; unique port number
|
||||
mtx MUTEX
|
||||
con dd ? ; pointer to SERIAL_OBJ
|
||||
drv dd ? ; pointer to struct SP_DRIVER
|
||||
drv_data dd ? ; pointer to driver-defined data
|
||||
rx_buf RING_BUF
|
||||
tx_buf RING_BUF
|
||||
conf SP_CONF
|
||||
ends
|
||||
|
||||
proc START c, reason:dword
|
||||
cmp [reason], DRV_ENTRY
|
||||
jne .fail
|
||||
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexInit
|
||||
|
||||
stdcall uart_probe, 0x3f8, 4
|
||||
stdcall uart_probe, 0x2f8, 3
|
||||
stdcall uart_probe, 0x3e8, 4
|
||||
stdcall uart_probe, 0x2e8, 3
|
||||
invoke RegService, drv_name, service_proc
|
||||
ret
|
||||
|
||||
.fail:
|
||||
xor eax, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
srv_calls:
|
||||
dd service_proc.get_version
|
||||
dd service_proc.drv_add_port
|
||||
dd service_proc.drv_remove_port
|
||||
dd service_proc.drv_handle_event
|
||||
dd service_proc.open
|
||||
dd service_proc.close
|
||||
dd service_proc.setup
|
||||
dd service_proc.read
|
||||
dd service_proc.write
|
||||
; TODO enumeration
|
||||
srv_calls_end:
|
||||
|
||||
proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
mov edx, [ioctl]
|
||||
mov eax, [edx + IOCTL.io_code]
|
||||
cmp eax, (srv_calls_end - srv_calls) / 4
|
||||
jae .err
|
||||
jmp dword [srv_calls + eax * 4]
|
||||
|
||||
.get_version:
|
||||
cmp [edx + IOCTL.out_size], 4
|
||||
jb .err
|
||||
mov edx, [edx + IOCTL.output]
|
||||
mov dword [edx], API_VERSION
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
.drv_add_port:
|
||||
; in:
|
||||
; +0: driver
|
||||
; +4: driver data
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
mov ecx, [ebx]
|
||||
mov edx, [ebx + 4]
|
||||
call add_port
|
||||
ret
|
||||
|
||||
.drv_remove_port:
|
||||
; in:
|
||||
; +0: port handle
|
||||
cmp [edx + IOCTL.inp_size], 4
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
mov ecx, [ebx]
|
||||
call remove_port
|
||||
ret
|
||||
|
||||
.drv_handle_event:
|
||||
; in:
|
||||
; +0: port handle
|
||||
; +4: event
|
||||
; +8: count
|
||||
; +12: buf
|
||||
cmp [edx + IOCTL.inp_size], 16
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
mov eax, [ebx]
|
||||
mov edx, [ebx + 4]
|
||||
mov ecx, [ebx + 8]
|
||||
mov esi, [ebx + 12]
|
||||
call handle_event
|
||||
ret
|
||||
|
||||
.open:
|
||||
; in:
|
||||
; +0 port number
|
||||
; +4 addr to SERIAL_CONF
|
||||
; out:
|
||||
; +0 port handle if success
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 4
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
mov ecx, [edx + IOCTL.output]
|
||||
stdcall sp_open, [ebx], [ebx + 4], ecx
|
||||
ret
|
||||
|
||||
.close:
|
||||
; in:
|
||||
; +0 port handle
|
||||
cmp [edx + IOCTL.inp_size], 4
|
||||
jb .err
|
||||
mov ecx, [edx + IOCTL.input]
|
||||
mov ecx, [ecx]
|
||||
call sp_close
|
||||
ret
|
||||
|
||||
.setup:
|
||||
; in:
|
||||
; +0 port handle
|
||||
; +4 addr to SERIAL_CONF
|
||||
; out:
|
||||
; +0 result
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 4
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
push edx
|
||||
mov eax, [ebx]
|
||||
mov esi, [ebx + 4]
|
||||
call sp_setup
|
||||
pop edx
|
||||
mov ebx, [edx + IOCTL.output]
|
||||
mov [ebx], eax
|
||||
ret
|
||||
|
||||
.read:
|
||||
; in:
|
||||
; +0 port handle
|
||||
; +4 addr of dest buf
|
||||
; +8 count to read
|
||||
; out:
|
||||
; +0 bytes read
|
||||
cmp [edx + IOCTL.inp_size], 12
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 4
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
push edx
|
||||
mov eax, [ebx]
|
||||
mov edi, [ebx + 4]
|
||||
mov ecx, [ebx + 8]
|
||||
call sp_read
|
||||
pop edx
|
||||
mov ebx, [edx + IOCTL.output]
|
||||
mov [ebx], ecx
|
||||
ret
|
||||
|
||||
.write:
|
||||
; in:
|
||||
; +0 port handle
|
||||
; +4 addr to source buf
|
||||
; +8 count to write
|
||||
; out:
|
||||
; +0 bytes written
|
||||
cmp [edx + IOCTL.inp_size], 12
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 4
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
push edx
|
||||
mov eax, [ebx]
|
||||
mov esi, [ebx + 4]
|
||||
mov ecx, [ebx + 8]
|
||||
call sp_write
|
||||
pop edx
|
||||
mov ebx, [edx + IOCTL.output]
|
||||
mov [ebx], ecx
|
||||
ret
|
||||
|
||||
.err:
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
|
||||
; struct SERIAL_PORT __fastcall *add_port(const struct SP_DRIVER *drv, const void *drv_data);
|
||||
align 4
|
||||
proc add_port uses edi
|
||||
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x\n", ecx, edx
|
||||
|
||||
mov eax, [ecx + SP_DRIVER.size]
|
||||
cmp eax, sizeof.SP_DRIVER
|
||||
jne .fail
|
||||
|
||||
; alloc memory for serial port descriptor
|
||||
push ecx
|
||||
push edx
|
||||
movi eax, sizeof.SERIAL_PORT
|
||||
invoke Kmalloc
|
||||
pop edx
|
||||
pop ecx
|
||||
test eax, eax
|
||||
jz .fail
|
||||
|
||||
; initialize fields of descriptor
|
||||
mov edi, eax
|
||||
mov [edi + SERIAL_PORT.drv], ecx
|
||||
mov [edi + SERIAL_PORT.drv_data], edx
|
||||
lea ecx, [edi + SERIAL_PORT.mtx]
|
||||
invoke MutexInit
|
||||
and [edi + SERIAL_PORT.con], 0
|
||||
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexLock
|
||||
|
||||
; TODO obtain unused id's
|
||||
mov eax, [port_count]
|
||||
mov [edi + SERIAL_PORT.id], eax
|
||||
inc [port_count]
|
||||
|
||||
; add port to linked list
|
||||
mov eax, port_list
|
||||
mov ecx, [eax + SERIAL_PORT.bk]
|
||||
mov [edi + SERIAL_PORT.bk], ecx
|
||||
mov [edi + SERIAL_PORT.fd], eax
|
||||
mov [ecx + SERIAL_PORT.fd], edi
|
||||
mov [eax + SERIAL_PORT.bk], edi
|
||||
|
||||
DEBUGF L_DBG, "serial.sys: add port %x with id %x\n", edi, [edi + SERIAL_PORT.id]
|
||||
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexUnlock
|
||||
|
||||
mov eax, edi
|
||||
ret
|
||||
|
||||
.fail:
|
||||
xor eax, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
; u32 __fastcall *remove_port(struct SERIAL_PORT *port);
|
||||
proc remove_port uses esi
|
||||
mov esi, ecx
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexLock
|
||||
|
||||
lea ecx, [esi + SERIAL_PORT.mtx]
|
||||
invoke MutexLock
|
||||
|
||||
mov eax, [esi + SERIAL_PORT.con]
|
||||
test eax, eax
|
||||
jz @f
|
||||
push esi
|
||||
call sp_destroy
|
||||
pop esi
|
||||
@@:
|
||||
|
||||
mov eax, [esi + SERIAL_PORT.fd]
|
||||
mov edx, [esi + SERIAL_PORT.bk]
|
||||
mov [edx + SERIAL_PORT.fd], eax
|
||||
mov [eax + SERIAL_PORT.bk], edx
|
||||
DEBUGF L_DBG, "serial.sys: remove port %x with id %x\n", esi, [esi + SERIAL_PORT.id]
|
||||
mov eax, esi
|
||||
invoke Kfree
|
||||
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexUnlock
|
||||
|
||||
xor eax, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
; @param eax port
|
||||
; @param edx event
|
||||
; @param ecx count
|
||||
; @param esi buffer
|
||||
; @return eax count
|
||||
proc handle_event uses edi
|
||||
mov edi, eax
|
||||
cmp edx, SERIAL_EVT_RXNE
|
||||
jz .rx
|
||||
cmp edx, SERIAL_EVT_TXE
|
||||
jz .tx
|
||||
xor eax, eax
|
||||
jmp .exit
|
||||
.rx:
|
||||
lea eax, [edi + SERIAL_PORT.rx_buf]
|
||||
stdcall ring_buf_write, eax, esi, ecx
|
||||
jmp .exit
|
||||
.tx:
|
||||
lea eax, [edi + SERIAL_PORT.tx_buf]
|
||||
stdcall ring_buf_read, eax, esi, ecx
|
||||
; fallthrough
|
||||
.exit:
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc sp_validate_conf
|
||||
mov eax, [ecx + SP_CONF.size]
|
||||
cmp eax, sizeof.SP_CONF
|
||||
jnz .fail
|
||||
mov eax, [ecx + SP_CONF.baudrate]
|
||||
test eax, eax
|
||||
jz .fail
|
||||
mov al, [ecx + SP_CONF.word_size]
|
||||
cmp al, 8
|
||||
jne .fail ; TODO implement different word size
|
||||
mov al, [ecx + SP_CONF.stop_bits]
|
||||
cmp al, 1
|
||||
jne .fail ; TODO implement different stop bits count
|
||||
mov al, [ecx + SP_CONF.parity]
|
||||
cmp al, SERIAL_CONF_PARITY_NONE
|
||||
jne .fail ; TODO implement parity
|
||||
mov al, [ecx + SP_CONF.flow_ctrl]
|
||||
cmp al, SERIAL_CONF_FLOW_CTRL_NONE
|
||||
jne .fail ; TODO implement flow control
|
||||
.ok:
|
||||
xor eax, eax
|
||||
ret
|
||||
.fail:
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc sp_open stdcall uses ebx esi edi, port_id:dword, conf:dword, handle:dword
|
||||
DEBUGF L_DBG, "serial.sys: sp_open %x %x %x\n", [port_id], [conf], [handle]
|
||||
|
||||
mov ecx, [conf]
|
||||
call sp_validate_conf
|
||||
test eax, eax
|
||||
jz @f
|
||||
mov eax, SERIAL_API_ERR_CONF
|
||||
ret
|
||||
@@:
|
||||
mov edi, [conf]
|
||||
|
||||
; get access to the serial ports list
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexLock
|
||||
|
||||
; find port by id
|
||||
mov eax, [port_id]
|
||||
mov esi, port_list
|
||||
.find_port:
|
||||
mov esi, [esi + SERIAL_PORT.fd]
|
||||
cmp esi, port_list
|
||||
jz .not_found
|
||||
mov ecx, [esi + SERIAL_PORT.id]
|
||||
cmp ecx, eax
|
||||
jz .found
|
||||
jmp .find_port
|
||||
|
||||
.not_found:
|
||||
DEBUGF L_DBG, "serial.sys: port not found\n"
|
||||
mov eax, SERIAL_API_ERR_PORT_INVALID
|
||||
jmp .unlock_list
|
||||
|
||||
.found:
|
||||
DEBUGF L_DBG, "serial.sys: found port %x\n", esi
|
||||
|
||||
; get access to serial port
|
||||
lea ecx, [esi + SERIAL_PORT.mtx]
|
||||
invoke MutexLock
|
||||
|
||||
; availability check
|
||||
cmp [esi + SERIAL_PORT.con], 0
|
||||
jz .open
|
||||
mov eax, SERIAL_API_ERR_PORT_BUSY
|
||||
jmp .unlock_port
|
||||
|
||||
.open:
|
||||
; create rx and tx ring buffers
|
||||
lea ecx, [esi + SERIAL_PORT.rx_buf]
|
||||
mov edx, SERIAL_RING_BUF_SIZE
|
||||
call ring_buf_create
|
||||
test eax, eax
|
||||
jnz @f
|
||||
jmp .unlock_port
|
||||
@@:
|
||||
lea ecx, [esi + SERIAL_PORT.tx_buf]
|
||||
mov edx, SERIAL_RING_BUF_SIZE
|
||||
call ring_buf_create
|
||||
test eax, eax
|
||||
jnz @f
|
||||
jmp .free_rx_buf
|
||||
@@:
|
||||
invoke GetPid
|
||||
mov ebx, eax
|
||||
mov eax, sizeof.SERIAL_OBJ
|
||||
invoke CreateObject
|
||||
test eax, eax
|
||||
jnz @f
|
||||
or eax, -1
|
||||
jmp .free_tx_buf
|
||||
@@:
|
||||
DEBUGF L_DBG, "serial.sys: created object %x\n", eax
|
||||
|
||||
; save port handle
|
||||
mov ecx, [handle]
|
||||
mov [ecx], eax
|
||||
mov [eax + SERIAL_OBJ.magic], 'UART'
|
||||
mov [eax + SERIAL_OBJ.destroy], sp_destroy
|
||||
mov [eax + SERIAL_OBJ.port], esi
|
||||
|
||||
; fill fields
|
||||
mov [esi + SERIAL_PORT.con], eax
|
||||
; copy conf
|
||||
mov eax, [edi + SP_CONF.size]
|
||||
mov [esi + SERIAL_PORT.conf + SP_CONF.size], eax
|
||||
mov eax, [edi + SP_CONF.baudrate]
|
||||
mov [esi + SERIAL_PORT.conf + SP_CONF.baudrate], eax
|
||||
mov eax, dword [edi + SP_CONF.word_size]
|
||||
mov dword [esi + SERIAL_PORT.conf + SP_CONF.word_size], eax
|
||||
|
||||
; tell driver about port open
|
||||
mov ebx, [esi + SERIAL_PORT.drv]
|
||||
mov ecx, [esi + SERIAL_PORT.drv_data]
|
||||
stdcall dword [ebx + SP_DRIVER.startup], ecx, edi
|
||||
test eax, eax
|
||||
jz .unlock_port
|
||||
; on error fallthrough
|
||||
push eax
|
||||
mov eax, [esi + SERIAL_PORT.con]
|
||||
invoke DestroyObject
|
||||
and [esi + SERIAL_PORT.con], 0
|
||||
pop eax
|
||||
|
||||
.free_tx_buf:
|
||||
push eax
|
||||
lea ecx, [esi + SERIAL_PORT.tx_buf]
|
||||
call ring_buf_destroy
|
||||
pop eax
|
||||
|
||||
.free_rx_buf:
|
||||
push eax
|
||||
lea ecx, [esi + SERIAL_PORT.rx_buf]
|
||||
call ring_buf_destroy
|
||||
pop eax
|
||||
|
||||
.unlock_port:
|
||||
push eax
|
||||
lea ecx, [esi + SERIAL_PORT.mtx]
|
||||
invoke MutexUnlock
|
||||
pop eax
|
||||
|
||||
.unlock_list:
|
||||
push eax
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexUnlock
|
||||
pop eax
|
||||
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
; @param ecx serial port handle
|
||||
proc sp_close uses ebx esi
|
||||
mov eax, ecx
|
||||
cmp [eax + SERIAL_OBJ.magic], 'UART'
|
||||
je .ok
|
||||
or eax, -1
|
||||
ret
|
||||
.ok:
|
||||
mov ebx, [eax + SERIAL_OBJ.port]
|
||||
push eax
|
||||
lea ecx, [ebx + SERIAL_PORT.mtx]
|
||||
invoke MutexLock
|
||||
pop eax
|
||||
|
||||
push ebx
|
||||
call sp_destroy
|
||||
pop ebx
|
||||
|
||||
lea ecx, [ebx + SERIAL_PORT.mtx]
|
||||
invoke MutexUnlock
|
||||
|
||||
xor eax, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
; @param eax port handle
|
||||
; @param esi pointer to SP_CONF
|
||||
; @return eax = 0 on success
|
||||
proc sp_setup
|
||||
test esi, esi
|
||||
jz .fail
|
||||
cmp [eax + SERIAL_OBJ.magic], 'UART'
|
||||
jne .fail
|
||||
mov ebx, eax
|
||||
mov ecx, esi
|
||||
call sp_validate_conf
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF L_DBG, "serial.sys: invalid conf %x\n", ecx
|
||||
mov eax, SERIAL_API_ERR_CONF
|
||||
ret
|
||||
@@:
|
||||
; lock mutex
|
||||
mov edi, [ebx + SERIAL_OBJ.port]
|
||||
lea ecx, [edi + SERIAL_PORT.mtx]
|
||||
invoke MutexLock
|
||||
; reconfigure port
|
||||
mov eax, [edi + SERIAL_PORT.drv]
|
||||
mov ecx, [edi + SERIAL_PORT.drv_data]
|
||||
stdcall dword [eax + SP_DRIVER.reconf], ecx, esi
|
||||
xor eax, eax
|
||||
push eax
|
||||
test eax, eax
|
||||
jnz @f
|
||||
; copy conf if success
|
||||
mov eax, [esi + SP_CONF.size]
|
||||
mov [edi + SERIAL_PORT.conf + SP_CONF.size], eax
|
||||
mov eax, [esi + SP_CONF.baudrate]
|
||||
mov [edi + SERIAL_PORT.conf + SP_CONF.baudrate], eax
|
||||
mov eax, dword [esi + SP_CONF.word_size]
|
||||
mov dword [edi + SERIAL_PORT.conf + SP_CONF.word_size], eax
|
||||
@@:
|
||||
; unlock mutex
|
||||
lea ecx, [edi + SERIAL_PORT.mtx]
|
||||
invoke MutexUnlock
|
||||
pop eax
|
||||
ret
|
||||
.fail:
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
; @param eax serial obj
|
||||
proc sp_destroy
|
||||
mov esi, [eax + SERIAL_OBJ.port]
|
||||
DEBUGF L_DBG, "serial.sys: destroy port %x\n", esi
|
||||
|
||||
invoke DestroyObject
|
||||
and [esi + SERIAL_PORT.con], 0
|
||||
|
||||
; tell driver about port close
|
||||
mov ebx, [esi + SERIAL_PORT.drv]
|
||||
mov edx, [esi + SERIAL_PORT.drv_data]
|
||||
stdcall dword [ebx + SP_DRIVER.shutdown], edx
|
||||
|
||||
lea ecx, [esi + SERIAL_PORT.tx_buf]
|
||||
call ring_buf_destroy
|
||||
lea ecx, [esi + SERIAL_PORT.rx_buf]
|
||||
call ring_buf_destroy
|
||||
ret
|
||||
endp
|
||||
|
||||
|
||||
align 4
|
||||
; @param eax port handle
|
||||
; @param ecx bytes count
|
||||
; @param edi address of destination buffer
|
||||
; @return eax = 0 on success and ecx = count bytes read
|
||||
proc sp_read
|
||||
test edi, edi
|
||||
jz .fail
|
||||
test ecx, ecx
|
||||
jz .fail
|
||||
cmp [eax + SERIAL_OBJ.magic], 'UART'
|
||||
jne .fail
|
||||
mov esi, [eax + SERIAL_OBJ.port]
|
||||
push ecx ; last arg for ring_buf_read
|
||||
lea ecx, [esi + SERIAL_PORT.mtx]
|
||||
invoke MutexLock
|
||||
lea eax, [esi + SERIAL_PORT.rx_buf]
|
||||
stdcall ring_buf_read, eax, edi
|
||||
push eax
|
||||
lea ecx, [esi + SERIAL_PORT.mtx]
|
||||
invoke MutexUnlock
|
||||
pop ecx
|
||||
xor eax, eax
|
||||
ret
|
||||
.fail:
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
; @param eax port handle
|
||||
; @param ecx bytes count
|
||||
; @param esi address of source buffer
|
||||
; @return eax = 0 on success and ecx = count bytes written
|
||||
proc sp_write
|
||||
test esi, esi
|
||||
jz .fail
|
||||
test ecx, ecx
|
||||
jz .fail
|
||||
cmp [eax + SERIAL_OBJ.magic], 'UART'
|
||||
jne .fail
|
||||
|
||||
push ecx ; last arg for ring_buf_write
|
||||
mov edi, [eax + SERIAL_OBJ.port]
|
||||
lea ecx, [edi + SERIAL_PORT.mtx]
|
||||
invoke MutexLock
|
||||
|
||||
lea ecx, [edi + SERIAL_PORT.tx_buf]
|
||||
stdcall ring_buf_write, ecx, esi
|
||||
push eax
|
||||
test eax, eax
|
||||
jz @f
|
||||
mov ebx, [edi + SERIAL_PORT.drv]
|
||||
mov edx, [edi + SERIAL_PORT.drv_data]
|
||||
stdcall dword [ebx + SP_DRIVER.tx], edx
|
||||
@@:
|
||||
lea ecx, [edi + SERIAL_PORT.mtx]
|
||||
invoke MutexUnlock
|
||||
pop ecx
|
||||
xor eax, eax
|
||||
ret
|
||||
.fail:
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
|
||||
drv_name db 'SERIAL', 0
|
||||
include_debug_strings
|
||||
|
||||
align 4
|
||||
port_count dd 0
|
||||
port_list_mutex MUTEX
|
||||
port_list:
|
||||
.fd dd port_list
|
||||
.bk dd port_list
|
||||
|
||||
align 4
|
||||
data fixups
|
||||
end data
|
408
drivers/serial/uart16550.inc
Executable file
408
drivers/serial/uart16550.inc
Executable file
@ -0,0 +1,408 @@
|
||||
BASE_FREQ = 1843200
|
||||
BASE_DIV = 16
|
||||
|
||||
THR_REG = 0 ; transtitter/reciever
|
||||
IER_REG = 1 ; interrupt enable
|
||||
IIR_REG = 2 ; interrupt info
|
||||
FCR_REG = 2 ; FIFO control
|
||||
LCR_REG = 3 ; line control
|
||||
MCR_REG = 4 ; modem control
|
||||
LSR_REG = 5 ; line status
|
||||
MSR_REG = 6 ; modem status
|
||||
SCR_REG = 7 ; scratch
|
||||
|
||||
DLL_REG = THR_REG ; divisor latch (LSB)
|
||||
DLM_REG = IER_REG ; divisor latch (MSB)
|
||||
|
||||
LCR_5BIT = 0x00
|
||||
LCR_6BIT = 0x01
|
||||
LCR_7BIT = 0x02
|
||||
LCR_8BIT = 0x03
|
||||
LCR_STOP_1 = 0x00
|
||||
LCR_STOP_2 = 0x04
|
||||
LCR_PARITY = 0x08
|
||||
LCR_EVEN = 0x10
|
||||
LCR_STICK = 0x20
|
||||
LCR_BREAK = 0x40
|
||||
LCR_DLAB = 0x80
|
||||
|
||||
LSR_DR = 0x01 ; data ready
|
||||
LSR_OE = 0x02 ; overrun error
|
||||
LSR_PE = 0x04 ; parity error
|
||||
LSR_FE = 0x08 ; framing error
|
||||
LSR_BI = 0x10 ; break interrupt
|
||||
LSR_THRE = 0x20 ; transmitter holding empty
|
||||
LSR_TEMT = 0x40 ; transmitter empty
|
||||
LSR_FER = 0x80 ; FIFO error
|
||||
|
||||
FCR_EFIFO = 0x01 ; enable FIFO
|
||||
FCR_CRB = 0x02 ; clear reciever FIFO
|
||||
FCR_CXMIT = 0x04 ; clear transmitter FIFO
|
||||
FCR_RDY = 0x08 ; set RXRDY and TXRDY pins
|
||||
FCR_FIFO_1 = 0x00 ; 1 byte trigger
|
||||
FCR_FIFO_4 = 0x40 ; 4 bytes trigger
|
||||
FCR_FIFO_8 = 0x80 ; 8 bytes trigger
|
||||
FCR_FIFO_14 = 0xC0 ; 14 bytes trigger
|
||||
|
||||
IIR_INTR = 0x01 ; 1= no interrupts
|
||||
IIR_IID = 0x0E ; interrupt source mask
|
||||
|
||||
IER_RDAI = 0x01 ; reciever data interrupt
|
||||
IER_THRI = 0x02 ; transmitter empty interrupt
|
||||
IER_LSI = 0x04 ; line status interrupt
|
||||
IER_MSI = 0x08 ; modem status interrupt
|
||||
|
||||
MCR_DTR = 0x01 ; 0-> DTR=1, 1-> DTR=0
|
||||
MCR_RTS = 0x02 ; 0-> RTS=1, 1-> RTS=0
|
||||
MCR_OUT1 = 0x04 ; 0-> OUT1=1, 1-> OUT1=0
|
||||
MCR_OUT2 = 0x08 ; 0-> OUT2=1, 1-> OUT2=0; enable intr
|
||||
MCR_LOOP = 0x10 ; lopback mode
|
||||
|
||||
MSR_DCTS = 0x01 ; delta clear to send
|
||||
MSR_DDSR = 0x02 ; delta data set redy
|
||||
MSR_TERI = 0x04 ; trailinh edge of ring
|
||||
MSR_DDCD = 0x08 ; delta carrier detect
|
||||
MSR_CTS = 0x10
|
||||
MSR_DSR = 0x20
|
||||
MSR_RI = 0x40
|
||||
MSR_DCD = 0x80
|
||||
|
||||
MCR_TEST_MASK = MCR_DTR or MCR_RTS or MCR_OUT1 or MCR_OUT2 or MCR_LOOP
|
||||
MSR_CHECK_MASK = MSR_CTS or MSR_DSR or MSR_RI or MSR_DCD
|
||||
|
||||
struct DRV_DATA
|
||||
io_addr dd ? ; base address of io port
|
||||
port dd ? ; serial port descriptor
|
||||
ends
|
||||
|
||||
; dx = base io
|
||||
; al = result
|
||||
macro rd_reg reg
|
||||
{
|
||||
push edx
|
||||
add dx, reg
|
||||
in al, dx
|
||||
pop edx
|
||||
}
|
||||
|
||||
; dx = base io
|
||||
; al = new value
|
||||
macro wr_reg reg
|
||||
{
|
||||
push edx
|
||||
add dx, reg
|
||||
out dx, al
|
||||
pop edx
|
||||
}
|
||||
|
||||
; dx = port
|
||||
; ax = divisor value
|
||||
proc uart_set_baud
|
||||
push eax
|
||||
rd_reg LCR_REG
|
||||
or al, LCR_DLAB
|
||||
wr_reg LCR_REG
|
||||
pop eax
|
||||
wr_reg DLL_REG
|
||||
shr ax, 8
|
||||
wr_reg DLM_REG
|
||||
rd_reg LCR_REG
|
||||
and al, 0x7f
|
||||
wr_reg LCR_REG
|
||||
ret
|
||||
endp
|
||||
|
||||
proc uart_probe stdcall uses ebx esi edi, io_addr:dword, irqn:dword
|
||||
xor ebx, ebx ; 0 = reserve
|
||||
mov ecx, [io_addr]
|
||||
lea edx, [ecx + 7]
|
||||
push ebp
|
||||
invoke ReservePortArea
|
||||
pop ebp
|
||||
test eax, eax
|
||||
jnz .err
|
||||
|
||||
mov edx, [io_addr]
|
||||
|
||||
; enable loopback
|
||||
mov al, MCR_LOOP
|
||||
wr_reg MCR_REG
|
||||
|
||||
; read status
|
||||
rd_reg MSR_REG
|
||||
and al, MSR_CHECK_MASK
|
||||
test al, al
|
||||
jnz .free_port
|
||||
|
||||
; set test signals
|
||||
mov al, MCR_TEST_MASK
|
||||
wr_reg MCR_REG
|
||||
|
||||
; check signals
|
||||
rd_reg MSR_REG
|
||||
and al, MSR_CHECK_MASK
|
||||
cmp al, MSR_CHECK_MASK
|
||||
jnz .free_port
|
||||
|
||||
DEBUGF L_DBG, "uart16550: found serial port %x\n", [io_addr]
|
||||
|
||||
; initialize port
|
||||
xor ax, ax
|
||||
wr_reg MCR_REG
|
||||
wr_reg IER_REG
|
||||
wr_reg LCR_REG
|
||||
wr_reg FCR_REG
|
||||
|
||||
mov eax, sizeof.DRV_DATA
|
||||
invoke Kmalloc
|
||||
test eax, eax
|
||||
jz .free_port
|
||||
mov edi, eax
|
||||
|
||||
mov eax, [io_addr]
|
||||
mov [edi + DRV_DATA.io_addr], eax
|
||||
|
||||
invoke AttachIntHandler, [irqn], uart_int_handler, edi
|
||||
test eax, eax
|
||||
jz .free_desc
|
||||
|
||||
; register port
|
||||
lea ecx, [uart_drv]
|
||||
mov edx, edi
|
||||
call add_port
|
||||
test eax, eax
|
||||
jz .free_desc ; TODO detach_int_handler?
|
||||
|
||||
; save port handle
|
||||
mov [edi + DRV_DATA.port], eax
|
||||
ret
|
||||
|
||||
.free_desc:
|
||||
mov eax, edi
|
||||
invoke Kfree
|
||||
|
||||
.free_port:
|
||||
xor ebx, ebx
|
||||
inc ebx ; 1 = release
|
||||
mov ecx, [io_addr]
|
||||
lea edx, [ecx + 7]
|
||||
push ebp
|
||||
invoke ReservePortArea
|
||||
pop ebp
|
||||
|
||||
.err:
|
||||
ret
|
||||
endp
|
||||
|
||||
proc uart_int_handler c uses ebx esi edi, data:dword
|
||||
locals
|
||||
.buf db ?
|
||||
endl
|
||||
mov edi, [data]
|
||||
mov edx, [edi + DRV_DATA.io_addr]
|
||||
xor ebx, ebx
|
||||
|
||||
.read_iir:
|
||||
rd_reg IIR_REG
|
||||
test al, IIR_INTR
|
||||
jnz .exit
|
||||
|
||||
inc ebx
|
||||
and ax, IIR_IID
|
||||
shr ax, 1
|
||||
|
||||
; check source
|
||||
test ax, ax
|
||||
jz .modem
|
||||
cmp ax, 1
|
||||
jz .xmit
|
||||
cmp ax, 2
|
||||
jz .recv
|
||||
cmp ax, 3
|
||||
jz .status
|
||||
jmp .exit
|
||||
|
||||
.modem:
|
||||
; read MSR for clear interrupt
|
||||
rd_reg MSR_REG
|
||||
jmp .read_iir
|
||||
|
||||
.xmit:
|
||||
push edx
|
||||
mov eax, [edi + DRV_DATA.port]
|
||||
mov edx, SERIAL_EVT_TXE
|
||||
mov ecx, 1
|
||||
lea esi, [.buf]
|
||||
call handle_event
|
||||
pop edx
|
||||
|
||||
test eax, eax
|
||||
jz .no_data
|
||||
|
||||
mov al, [.buf]
|
||||
wr_reg THR_REG
|
||||
jmp .read_iir
|
||||
|
||||
.no_data:
|
||||
; disable THR empty interrupt
|
||||
rd_reg IER_REG
|
||||
and ax, not IER_THRI
|
||||
wr_reg IER_REG
|
||||
jmp .read_iir
|
||||
|
||||
.recv:
|
||||
; read byte
|
||||
rd_reg THR_REG
|
||||
push edx
|
||||
mov [.buf], al
|
||||
mov eax, [edi + DRV_DATA.port]
|
||||
mov edx, SERIAL_EVT_RXNE
|
||||
mov ecx, 1
|
||||
lea esi, [.buf]
|
||||
call handle_event
|
||||
pop edx
|
||||
|
||||
; check for more recevied bytes
|
||||
rd_reg LSR_REG
|
||||
test al, LSR_DR
|
||||
jnz .recv
|
||||
jmp .read_iir
|
||||
|
||||
.status:
|
||||
rd_reg LSR_REG
|
||||
jmp .read_iir
|
||||
|
||||
.fifo:
|
||||
jmp .read_iir
|
||||
|
||||
.exit:
|
||||
xchg eax, ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
proc uart_startup stdcall, data:dword, conf:dword
|
||||
DEBUGF L_DBG, "uart16550: startup %x %x\n", [data], [conf]
|
||||
; enable and reset fifo, 1 byte trigger level
|
||||
mov ecx, [data]
|
||||
mov edx, [ecx + DRV_DATA.io_addr]
|
||||
mov ax, FCR_EFIFO or FCR_CRB or FCR_CXMIT
|
||||
wr_reg FCR_REG
|
||||
; configure at startup
|
||||
stdcall uart_reconf, [data], [conf]
|
||||
ret
|
||||
endp
|
||||
|
||||
proc uart_shutdown stdcall, data:dword
|
||||
DEBUGF L_DBG, "uart16550: shutdown %x\n", [data]
|
||||
; disable interrupts
|
||||
mov ecx, [data]
|
||||
mov edx, [ecx + DRV_DATA.io_addr]
|
||||
xor ax, ax
|
||||
wr_reg IER_REG
|
||||
ret
|
||||
endp
|
||||
|
||||
proc uart_reconf stdcall uses ebx esi, data:dword, conf:dword
|
||||
locals
|
||||
divisor dw ?
|
||||
lcr dw ?
|
||||
endl
|
||||
; calc divisor = BASE_FREQ / BASE_DIV / baudrate
|
||||
mov esi, [conf]
|
||||
xor edx, edx
|
||||
mov eax, BASE_FREQ / BASE_DIV
|
||||
div [esi + SP_CONF.baudrate]
|
||||
test edx, edx
|
||||
jnz .fail
|
||||
test eax, eax
|
||||
jz .fail
|
||||
mov [divisor], ax
|
||||
|
||||
; calc word size
|
||||
xor eax, eax
|
||||
mov al, [esi + SP_CONF.word_size]
|
||||
cmp al, 8
|
||||
ja .fail
|
||||
sub al, 5
|
||||
jb .fail
|
||||
mov [lcr], ax
|
||||
|
||||
; calc parity
|
||||
mov al, [esi + SP_CONF.parity]
|
||||
xor bx, bx
|
||||
cmp al, SERIAL_CONF_PARITY_NONE
|
||||
je .parity_ok
|
||||
or bl, LCR_PARITY
|
||||
cmp al, SERIAL_CONF_PARITY_ODD
|
||||
je .parity_ok
|
||||
or bl, LCR_EVEN
|
||||
cmp al, SERIAL_CONF_PARITY_EVEN
|
||||
je .parity_ok
|
||||
mov bl, LCR_STICK or LCR_PARITY
|
||||
cmp al, SERIAL_CONF_PARITY_MARK
|
||||
je .parity_ok
|
||||
or bl, LCR_EVEN
|
||||
cmp al, SERIAL_CONF_PARITY_SPACE
|
||||
jne .fail
|
||||
.parity_ok:
|
||||
mov [lcr], bx
|
||||
|
||||
; calc stop bits
|
||||
mov bx, LCR_STOP_1
|
||||
mov al, [esi + SP_CONF.stop_bits]
|
||||
cmp al, 1
|
||||
je .stop_bits_ok
|
||||
or bx, LCR_STOP_2
|
||||
cmp al, 2
|
||||
jne .fail
|
||||
.stop_bits_ok:
|
||||
or [lcr], bx
|
||||
|
||||
mov esi, [data]
|
||||
mov edx, [esi + DRV_DATA.io_addr]
|
||||
|
||||
spin_lock_irqsave
|
||||
rd_reg IER_REG
|
||||
and ax, IER_RDAI or IER_LSI
|
||||
wr_reg IER_REG
|
||||
spin_unlock_irqrestore
|
||||
|
||||
mov ax, [divisor]
|
||||
call uart_set_baud
|
||||
|
||||
mov bx, [lcr]
|
||||
wr_reg LCR_REG
|
||||
|
||||
mov al, MCR_DTR or MCR_OUT1 or MCR_OUT2
|
||||
wr_reg MCR_REG
|
||||
|
||||
; enable rx interrupt
|
||||
mov al, IER_RDAI or IER_LSI
|
||||
wr_reg IER_REG
|
||||
|
||||
xor eax, eax
|
||||
ret
|
||||
.fail:
|
||||
mov eax, SERIAL_API_ERR_CONF
|
||||
ret
|
||||
endp
|
||||
|
||||
proc uart_tx stdcall, data:dword
|
||||
mov ecx, [data]
|
||||
mov edx, [ecx + DRV_DATA.io_addr]
|
||||
spin_lock_irqsave
|
||||
rd_reg IER_REG
|
||||
or ax, IER_THRI
|
||||
wr_reg IER_REG
|
||||
spin_unlock_irqrestore
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
uart_drv:
|
||||
dd uart_drv_end - uart_drv
|
||||
dd uart_startup
|
||||
dd uart_shutdown
|
||||
dd uart_reconf
|
||||
dd uart_tx
|
||||
uart_drv_end:
|
@ -27,6 +27,7 @@ include '../../proc32.inc'
|
||||
include '../../peimport.inc'
|
||||
include '../../fdo.inc'
|
||||
include '../../struct.inc'
|
||||
include '../../serial/common.inc'
|
||||
|
||||
; USB constants
|
||||
DEVICE_DESCR_TYPE = 1
|
||||
@ -60,6 +61,9 @@ LIBUSB_RECIPIENT_OTHER = 0x03
|
||||
LIBUSB_ENDPOINT_IN = 0x80
|
||||
LIBUSB_ENDPOINT_OUT = 0x00
|
||||
|
||||
H_CLK = 120000000
|
||||
C_CLK = 48000000
|
||||
|
||||
; FTDI Constants
|
||||
FTDI_DEVICE_OUT_REQTYPE = (LIBUSB_REQUEST_TYPE_VENDOR or LIBUSB_RECIPIENT_DEVICE or LIBUSB_ENDPOINT_OUT)
|
||||
FTDI_DEVICE_IN_REQTYPE = (LIBUSB_REQUEST_TYPE_VENDOR or LIBUSB_RECIPIENT_DEVICE or LIBUSB_ENDPOINT_IN)
|
||||
@ -119,6 +123,7 @@ TYPE_230X=7
|
||||
|
||||
;strings
|
||||
my_driver db 'usbother',0
|
||||
serial_driver db 'SERIAL',0
|
||||
nomemory_msg db 'K : no memory',13,10,0
|
||||
|
||||
; Structures
|
||||
@ -130,8 +135,8 @@ readBufChunkSize dd ?
|
||||
writeBufChunkSize dd ?
|
||||
readBufPtr dd ?
|
||||
writeBufPtr dd ?
|
||||
readBufSize dd ?
|
||||
writeBufSize dd ?
|
||||
readBufLock dd ?
|
||||
writeBufLock dd ?
|
||||
maxPacketSize dd ?
|
||||
interface dd ?
|
||||
index dd ?
|
||||
@ -140,6 +145,8 @@ outEP dd ?
|
||||
nullP dd ?
|
||||
lockPID dd ?
|
||||
next_context dd ?
|
||||
port_handle dd ?
|
||||
rx_timer dd ?
|
||||
ends
|
||||
|
||||
struct IOCTL
|
||||
@ -182,7 +189,9 @@ proc START c, .reason:DWORD, .cmdline:DWORD
|
||||
|
||||
xor eax, eax ; initialize return value
|
||||
cmp [.reason], 1 ; compare the argument
|
||||
jnz .nothing
|
||||
jnz .nothing
|
||||
invoke GetService, serial_driver
|
||||
mov [serial_drv_entry], eax
|
||||
invoke RegUSBDriver, my_driver, service_proc, usb_functions
|
||||
|
||||
.nothing:
|
||||
@ -215,6 +224,10 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
mov [eax + ftdi_context.maxPacketSize], 64
|
||||
mov [eax + ftdi_context.readBufChunkSize], 64
|
||||
mov [eax + ftdi_context.writeBufChunkSize], 64
|
||||
mov [eax + ftdi_context.readBufPtr], 0
|
||||
mov [eax + ftdi_context.writeBufPtr], 0
|
||||
mov [eax + ftdi_context.readBufLock], 0
|
||||
mov [eax + ftdi_context.writeBufLock], 0
|
||||
|
||||
mov [eax + ftdi_context.chipType], TYPE_R
|
||||
jmp .slow
|
||||
@ -270,6 +283,15 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
mov [ebx + ftdi_context.inEP], eax
|
||||
|
||||
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 [ebx + ftdi_context.port_handle], eax
|
||||
|
||||
mov eax, ebx
|
||||
ret
|
||||
|
||||
@ -1013,12 +1035,340 @@ endp
|
||||
proc DeviceDisconnected stdcall uses ebx esi edi, .device_data:DWORD
|
||||
|
||||
DEBUGF 1, 'K : FTDI deleting device data 0x%x\n', [.device_data]
|
||||
mov eax, [.device_data]
|
||||
mov esi, [.device_data]
|
||||
mov eax, [esi + ftdi_context.readBufPtr]
|
||||
test eax, eax
|
||||
jz @f
|
||||
invoke Kfree
|
||||
@@:
|
||||
mov eax, [esi + ftdi_context.writeBufPtr]
|
||||
test eax, eax
|
||||
jz @f
|
||||
invoke Kfree
|
||||
@@:
|
||||
mov eax, [esi + ftdi_context.port_handle]
|
||||
test eax, eax
|
||||
jz @f
|
||||
stdcall serial_remove_port, eax
|
||||
@@:
|
||||
mov eax, esi
|
||||
call linkedlist_unlink
|
||||
invoke Kfree
|
||||
ret
|
||||
endp
|
||||
|
||||
proc bulk_in_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
.buffer:DWORD, .length:DWORD, .calldata:DWORD
|
||||
mov eax, [.status]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF 2, 'ftdi: bulk in error %x\n', eax
|
||||
@@:
|
||||
mov ebx, [.calldata]
|
||||
btr dword [ebx + ftdi_context.writeBufLock], 0
|
||||
stdcall uart_tx, ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
.buffer:DWORD, .length:DWORD, .calldata:DWORD
|
||||
mov eax, [.status]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF 2, 'ftdi: bulk out error %x\n', eax
|
||||
@@:
|
||||
mov ebx, [.calldata]
|
||||
mov ecx, [.length]
|
||||
cmp ecx, 2
|
||||
jb @f
|
||||
mov esi, [.buffer]
|
||||
add esi, 2
|
||||
sub ecx, 2
|
||||
stdcall serial_handle_event, [ebx + ftdi_context.port_handle], \
|
||||
SERIAL_EVT_RXNE, ecx, esi
|
||||
@@:
|
||||
btr dword [ebx + ftdi_context.readBufLock], 0
|
||||
ret
|
||||
endp
|
||||
|
||||
proc uart_startup stdcall uses ebx, data:dword, conf:dword
|
||||
DEBUGF 1, "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
|
||||
jmp .exit
|
||||
@@:
|
||||
mov ebx, [data]
|
||||
invoke TimerHS, 2, 2, uart_rx, ebx
|
||||
test eax, eax
|
||||
jnz @f
|
||||
DEBUGF 2, "ftdi: timer creation error\n"
|
||||
or eax, -1
|
||||
jmp .exit
|
||||
@@:
|
||||
mov [ebx + ftdi_context.rx_timer], eax
|
||||
xor eax, eax
|
||||
.exit:
|
||||
ret
|
||||
endp
|
||||
|
||||
proc uart_shutdown stdcall uses ebx, data:dword
|
||||
DEBUGF 1, "ftdi: shutdown %x\n", [data]
|
||||
mov ebx, [data]
|
||||
cmp [ebx + ftdi_context.rx_timer], 0
|
||||
jz @f
|
||||
invoke CancelTimerHS, [ebx + ftdi_context.rx_timer]
|
||||
@@:
|
||||
ret
|
||||
endp
|
||||
|
||||
proc uart_reconf stdcall uses ebx esi, dev:dword, conf:dword
|
||||
mov ebx, [dev]
|
||||
mov esi, [conf]
|
||||
stdcall ftdi_set_baudrate, ebx, [esi + SP_CONF.baudrate]
|
||||
; TODO set word_size, parity, etc.
|
||||
ret
|
||||
endp
|
||||
|
||||
proc uart_tx stdcall uses ebx esi, data:dword
|
||||
xor eax, eax
|
||||
mov ebx, [data]
|
||||
bts dword [ebx + ftdi_context.writeBufLock], 0
|
||||
jc .exit
|
||||
|
||||
mov esi, [ebx + ftdi_context.writeBufPtr]
|
||||
test esi, esi
|
||||
jnz .read
|
||||
|
||||
; allocate buffer for bulk_in transfer if not yet
|
||||
mov eax, [ebx + ftdi_context.writeBufChunkSize]
|
||||
invoke Kmalloc
|
||||
test eax, eax
|
||||
jz .error
|
||||
mov [ebx + ftdi_context.writeBufPtr], eax
|
||||
mov esi, eax
|
||||
|
||||
.read:
|
||||
mov eax, [ebx + ftdi_context.writeBufChunkSize]
|
||||
stdcall serial_handle_event, [ebx + ftdi_context.port_handle], \
|
||||
SERIAL_EVT_TXE, eax, esi
|
||||
test eax, eax
|
||||
jz .unlock
|
||||
invoke USBNormalTransferAsync, [ebx + ftdi_context.inEP], esi, eax, \
|
||||
bulk_in_complete, ebx, 1
|
||||
test eax, eax
|
||||
jz .error
|
||||
xor eax, eax
|
||||
jmp .exit
|
||||
|
||||
.error:
|
||||
or eax, -1
|
||||
.unlock:
|
||||
btr dword [ebx + ftdi_context.writeBufLock], 0
|
||||
|
||||
.exit:
|
||||
ret
|
||||
endp
|
||||
|
||||
proc uart_rx stdcall uses ebx esi, data:dword
|
||||
xor eax, eax
|
||||
mov ebx, [data]
|
||||
bts dword [ebx + ftdi_context.readBufLock], 0
|
||||
jc .exit
|
||||
|
||||
mov esi, [ebx + ftdi_context.readBufPtr]
|
||||
test esi, esi
|
||||
jnz .read
|
||||
|
||||
; allocate buffer for bulk_out transfer if not yet
|
||||
mov eax, [ebx + ftdi_context.readBufChunkSize]
|
||||
invoke Kmalloc
|
||||
test eax, eax
|
||||
jz .error
|
||||
mov [ebx + ftdi_context.readBufPtr], eax
|
||||
mov esi, eax
|
||||
|
||||
.read:
|
||||
mov edx, [ebx + ftdi_context.readBufChunkSize]
|
||||
invoke USBNormalTransferAsync, [ebx + ftdi_context.outEP], esi, edx, \
|
||||
bulk_out_complete, ebx, 1
|
||||
test eax, eax
|
||||
jz .error
|
||||
xor eax, eax
|
||||
jmp .exit
|
||||
.error:
|
||||
btr dword [ebx + ftdi_context.readBufLock], 0
|
||||
or eax, -1
|
||||
.exit:
|
||||
ret
|
||||
endp
|
||||
|
||||
proc ftdi_set_baudrate stdcall uses ebx esi edi, dev:dword, baud:dword
|
||||
locals
|
||||
ConfPacket rb 10
|
||||
EventData rd 3
|
||||
endl
|
||||
xor esi, esi
|
||||
xor ecx, ecx
|
||||
invoke CreateEvent
|
||||
mov [EventData], eax
|
||||
mov [EventData + 4], edx
|
||||
|
||||
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
|
||||
|
||||
.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 [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 [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
|
||||
mov word [ConfPacket + 4], cx
|
||||
mov word [ConfPacket + 6], 0
|
||||
|
||||
lea esi, [ConfPacket]
|
||||
lea edi, [EventData]
|
||||
invoke USBControlTransferAsync, [ebx + ftdi_context.nullP], esi, 0,\
|
||||
0, control_callback, edi, 0
|
||||
test eax, eax
|
||||
jz .error
|
||||
mov eax, [EventData]
|
||||
mov ebx, [EventData + 4]
|
||||
invoke WaitEvent
|
||||
|
||||
mov eax, [EventData]
|
||||
mov ebx, [EventData + 4]
|
||||
invoke DestroyEvent
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
.error:
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
|
||||
include 'linkedlist.inc'
|
||||
|
||||
align 4
|
||||
@ -1029,6 +1379,17 @@ usb_functions:
|
||||
dd AddDevice
|
||||
dd DeviceDisconnected
|
||||
|
||||
align 4
|
||||
uart_drv:
|
||||
dd uart_drv_end - uart_drv
|
||||
dd uart_startup
|
||||
dd uart_shutdown
|
||||
dd uart_reconf
|
||||
dd uart_tx
|
||||
uart_drv_end:
|
||||
|
||||
serial_drv_entry dd 0
|
||||
|
||||
data fixups
|
||||
end data
|
||||
|
||||
|
@ -2,17 +2,17 @@
|
||||
|
||||
char file_actions[]=
|
||||
"Žâªàëâì |Enter
|
||||
Žâªàëâì á ¯®¬®éìî |CrlEnt
|
||||
Žâªàëâì á ¯®¬®éìî |Ctrl+Ent
|
||||
-
|
||||
Š®¯¨à®¢ âì |Crl+C
|
||||
‚ë१ âì |Crl+X
|
||||
‚áâ ¢¨âì |Crl+V
|
||||
Š®¯¨à®¢ âì |Ctrl+C
|
||||
‚ë१ âì |Ctrl+X
|
||||
‚áâ ¢¨âì |Ctrl+V
|
||||
-
|
||||
<EFBFBD>¥à¥¨¬¥®¢ âì |F2
|
||||
“¤ «¨âì |Del
|
||||
‘¢®©á⢠|F1";
|
||||
char empty_folder_actions[]=
|
||||
"‚áâ ¢¨âì |Crl+V";
|
||||
"‚áâ ¢¨âì |Ctrl+V";
|
||||
char burger_menu_items[] =
|
||||
"<EFBFBD>®¢®¥ ®ª®|Ctrl+N
|
||||
Žâªàëâì ª®á®«ì|Ctrl+G
|
||||
@ -23,17 +23,17 @@ char burger_menu_items[] =
|
||||
#elif LANG_EST
|
||||
char file_actions[]=
|
||||
"Ava |Enter
|
||||
Ava ... |CrlEnt
|
||||
Ava ... |Ctrl+Ent
|
||||
-
|
||||
Kopeeri |Crl+C
|
||||
Lõika |Crl+X
|
||||
Aseta |Crl+V
|
||||
Kopeeri |Ctrl+C
|
||||
Lõika |Ctrl+X
|
||||
Aseta |Ctrl+V
|
||||
-
|
||||
Nimeta ümber |F2
|
||||
Kustuta |Del
|
||||
Properties |F1";
|
||||
char empty_folder_actions[]=
|
||||
"Aseta |Crl+V";
|
||||
"Aseta |Ctrl+V";
|
||||
char burger_menu_items[] =
|
||||
"New window|Ctrl+N
|
||||
Open console here|Ctrl+G
|
||||
@ -43,18 +43,18 @@ About";
|
||||
|
||||
#else
|
||||
char file_actions[]=
|
||||
"Open |Enter
|
||||
Open with... |CrlEnt
|
||||
"Open |Enter
|
||||
Open with... |Ctrl+Ent
|
||||
-
|
||||
Copy |Crl+C
|
||||
Cut |Crl+X
|
||||
Paste |Crl+V
|
||||
Copy |Ctrl+C
|
||||
Cut |Ctrl+X
|
||||
Paste |Ctrl+V
|
||||
-
|
||||
Rename |F2
|
||||
Delete |Del
|
||||
Properties |F1";
|
||||
char empty_folder_actions[]=
|
||||
"Paste |Crl+V";
|
||||
"Paste |Ctrl+V";
|
||||
char burger_menu_items[] =
|
||||
"New window|Ctrl+N
|
||||
Open console here|Ctrl+G
|
||||
|
@ -5,8 +5,12 @@
|
||||
#include "../lib/list_box.h"
|
||||
#include "../lib/fs.h"
|
||||
|
||||
#define ITEM_H 19
|
||||
#define ITEM_H 24
|
||||
#define SEP_H 4
|
||||
#define TEXT_FONT_TYPE 0x90
|
||||
#define TEXT_MARGIN 13
|
||||
#define FONT_WIDTH 8
|
||||
#define FONT_HEIGHT 16
|
||||
|
||||
llist menu1;
|
||||
collection names=0;
|
||||
@ -43,9 +47,9 @@ void GetMenuWidths()
|
||||
for (i=0; i<hotkeys.count; i++) {
|
||||
max_hotkey_len = math.max(max_hotkey_len, strlen(hotkeys.get(i)));
|
||||
}
|
||||
max_name_len = max_name_len * 6;
|
||||
max_hotkey_len *= 6;
|
||||
if (max_hotkey_len) max_name_len += 12;
|
||||
max_name_len = max_name_len * FONT_WIDTH;
|
||||
max_hotkey_len *= FONT_WIDTH;
|
||||
if (max_hotkey_len) max_name_len += FONT_WIDTH*2;
|
||||
}
|
||||
|
||||
void GetMenuItems(dword current_name)
|
||||
@ -108,12 +112,14 @@ void main()
|
||||
GetMenuItems(#param);
|
||||
GetMenuWidths();
|
||||
|
||||
menu_w = max_name_len + max_hotkey_len + 23;
|
||||
menu_w = max_name_len + max_hotkey_len + TEXT_MARGIN + TEXT_MARGIN;//23;
|
||||
menu_h = GetSeparatorsCount() * SEP_H
|
||||
+ calc(names.count - GetSeparatorsCount() * ITEM_H);
|
||||
|
||||
menu1.count = names.count;
|
||||
menu1.SetFont(6, 9, 0x80);
|
||||
// menu1.SetFont(8, 14, 10011000b);
|
||||
menu1.SetFont(8, 16, 0x80); // TODO what is third par
|
||||
// menu1.SetFont(6, 9, 0x80);
|
||||
menu1.SetSizes(2,2, menu_w, menu_h, ITEM_H);
|
||||
menu1.cur_y = -1;
|
||||
|
||||
@ -231,17 +237,17 @@ void draw_list()
|
||||
name_color = sc.work_text;
|
||||
hotkey_color = sc.line;
|
||||
DrawBar(menu1.x, item_y, menu1.w, ITEM_H, inactive_background_color);
|
||||
if (!skin_dark) WriteText(13+1, item_y + menu1.text_y +1, 0x80,
|
||||
if (!skin_dark) WriteText(TEXT_MARGIN+1, item_y + menu1.text_y +1, TEXT_FONT_TYPE,
|
||||
inactive_text_shadow_color, names.get(i));
|
||||
}
|
||||
WriteText(-strlen(hotkeys.get(i))*6 + 13 + max_name_len + max_hotkey_len,
|
||||
item_y + menu1.text_y, 0x80, hotkey_color, hotkeys.get(i));
|
||||
WriteText(13, item_y + menu1.text_y, 0x80, name_color, names.get(i));
|
||||
WriteText(-strlen(hotkeys.get(i))*FONT_WIDTH + menu_w - TEXT_MARGIN,
|
||||
item_y + menu1.text_y, TEXT_FONT_TYPE, hotkey_color, hotkeys.get(i));
|
||||
WriteText(TEXT_MARGIN, item_y + menu1.text_y, TEXT_FONT_TYPE, name_color, names.get(i));
|
||||
item_y += ITEM_H;
|
||||
item_i++;
|
||||
}
|
||||
}
|
||||
if (selected) WriteText(5, selected-1*ITEM_H + menu1.y + menu1.text_y, 0x80, 0xEE0000, "\x10");
|
||||
if (selected) WriteText(5, selected-1*ITEM_H + menu1.y + menu1.text_y, TEXT_FONT_TYPE, 0xEE0000, "\x10"); // ?
|
||||
}
|
||||
|
||||
void click()
|
||||
|
@ -842,6 +842,19 @@ KOSAPI uint32_t _ksys_wait_event_timeout(uint32_t timeout)
|
||||
return val;
|
||||
}
|
||||
|
||||
/*=== Function 26, subfunction 2 - get keynoard layout. ==*/
|
||||
|
||||
typedef enum KSYS_KEYBOARD_LAYOUT {
|
||||
KSYS_KEYBOARD_LAYOUT_NORMAL = 1,
|
||||
KSYS_KEYBOARD_LAYOUT_SHIFT = 2,
|
||||
KSYS_KEYBOARD_LAYOUT_ALT = 3
|
||||
} ksys_keyboard_layout_t;
|
||||
|
||||
KOSAPI uint32_t _ksys_keyboard_layout(ksys_keyboard_layout_t layout, unsigned char *buf)
|
||||
{
|
||||
asm_inline("int $0x40" ::"a"(26), "b"(2), "c"(layout), "d"(buf) : "memory");
|
||||
}
|
||||
|
||||
/*=== Function 26, subfunction 9 - get the value of the time counter. ==*/
|
||||
|
||||
KOSAPI uint32_t _ksys_get_tick_count(void)
|
||||
|
@ -1,59 +0,0 @@
|
||||
# Libio
|
||||
> Lib for work with files
|
||||
|
||||
## Functions
|
||||
|
||||
### Files enumeration
|
||||
|
||||
##### `file_find_first`
|
||||
> Find first file with matching attributes and mask in specified directory.
|
||||
|
||||
**Prototype**:
|
||||
`proc file.find_first dir, mask, attr`
|
||||
|
||||
**Arguments**:
|
||||
| name | type | Describtion |
|
||||
| :--- | :----: | :------------------------------------------------------- |
|
||||
| dir | ASCIIZ | Directory path, to search in |
|
||||
| mask | ASCIIZ | File mask, with use of wildcards (a.k.a. shell patterns) |
|
||||
| attr | ASCIIZ | File attributes mask (combination of FA_* constants) |
|
||||
|
||||
**Result**:
|
||||
| register | type | Description |
|
||||
| :------- | :-------: | :--------------------------------------------------------------------- |
|
||||
| EAX | Fileinfo* | 0 for error<br/>Matched file data pointer (__acts as find descriptor__) |
|
||||
|
||||
|
||||
##### `file_find_next`
|
||||
> Find next file matching criteria.
|
||||
|
||||
**Prototype**:
|
||||
`proc file.find_next findd`
|
||||
|
||||
**Argument**:
|
||||
| name | type | Describtion |
|
||||
| :---- | :-------: | :--------------------------------------------------------- |
|
||||
| findd | Fileinfo* | Find describtion (see [file_find_first](#file_find_first)) |
|
||||
|
||||
**Result**:
|
||||
| register | type | Description |
|
||||
| :------- | :-------: | :--------------------------------------------------------------------- |
|
||||
| EAX | Fileinfo* | 0 for info<br/>Matched file data pointer (__acts as find descriptor__) |
|
||||
|
||||
|
||||
##### `file_find_close`
|
||||
> Find next file matching criteria.
|
||||
|
||||
**Prototype**:
|
||||
`Find next file matching criteria.`
|
||||
|
||||
**Arguments**:
|
||||
| name | type | Describtion |
|
||||
| :---- | :-------: | :--------------------------------------------------------- |
|
||||
| findd | Fileinfo* | Find describtion (see [file_find_first](#file_find_first)) |
|
||||
|
||||
|
||||
**Result**:
|
||||
| register | type | Description |
|
||||
| :------- | :---: | :------------------------------- |
|
||||
| EAX | dword | Result of memory freeing routine |
|
18
programs/games/dino/Makefile
Normal file
18
programs/games/dino/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
KTCC_DIR = ../kolibrios-nextgen/programs/develop/ktcc/trunk
|
||||
KLIBC = $(KTCC_DIR)/libc.obj
|
||||
|
||||
NAME = dino
|
||||
|
||||
KTCC = $(KTCC_DIR)/bin/kos32-tcc
|
||||
KPACK = kpack
|
||||
|
||||
SRC = $(wildcard *.c)
|
||||
FLAGS= -B$(KTCC_DIR)/bin -I $(KLIBC)/include -Wall# -stack=20480
|
||||
LIBS = -limg
|
||||
|
||||
all: $(SRC)
|
||||
$(KTCC) $(FLAGS) $(SRC) $(LIBS) -o $(NAME)
|
||||
# $(KPACK) $(NAME)
|
||||
|
||||
clean:
|
||||
rm $(NAME)
|
25
programs/games/dino/Tupfile.lua
Normal file
25
programs/games/dino/Tupfile.lua
Normal file
@ -0,0 +1,25 @@
|
||||
if tup.getconfig("NO_TCC") ~= "" then return end
|
||||
if tup.getconfig("HELPERDIR") == ""
|
||||
then
|
||||
HELPERDIR = "../../../programs"
|
||||
end
|
||||
tup.include(HELPERDIR .. "/use_tcc.lua")
|
||||
|
||||
SRCS = {
|
||||
"cloud.c",
|
||||
"game_over_panel.c",
|
||||
"horizon.c",
|
||||
"main.c",
|
||||
"obstacle.c",
|
||||
"trex.c",
|
||||
"distance_meter.c",
|
||||
"graphics.c",
|
||||
"horizon_line.c",
|
||||
"misc.c",
|
||||
"runner.c",
|
||||
"ulist.c"
|
||||
}
|
||||
|
||||
LIBS = " -limg"
|
||||
|
||||
link_tcc(SRCS, "dino");
|
34
programs/games/dino/cloud.c
Normal file
34
programs/games/dino/cloud.c
Normal file
@ -0,0 +1,34 @@
|
||||
#include "cloud.h"
|
||||
|
||||
void cloudInit(Cloud* cloud, int w) {
|
||||
cloud->width = w;
|
||||
cloud->xPos = w;
|
||||
cloud->yPos = 0;
|
||||
cloud->remove = false;
|
||||
cloud->cloudGap = getRandomNumber(CLOUD_MIN_GAP, CLOUD_MAX_GAP);
|
||||
|
||||
cloud->yPos = getRandomNumber(CLOUD_MAX_SKY_LEVEL, CLOUD_MIN_SKY_LEVEL); // NOTE why swapped
|
||||
cloudDraw(cloud);
|
||||
}
|
||||
|
||||
void cloudDraw(const Cloud* cloud) {
|
||||
graphicsBlitAtlasImage(ATLAS_CLOUD_X, ATLAS_CLOUD_Y, cloud->xPos, cloud->yPos, CLOUD_WIDTH, CLOUD_HEIGHT, false);
|
||||
}
|
||||
|
||||
void cloudUpdate(Cloud* cloud, double speed) {
|
||||
// printf("cloudUpdate(., %f)\n", speed);
|
||||
if (!cloud->remove) {
|
||||
cloud->xPos -= (int)ceil(speed);
|
||||
cloudDraw(cloud);
|
||||
|
||||
// Mark as removeable if no longer in the canvas.
|
||||
if (!cloudIsVisible(cloud)) {
|
||||
cloud->remove = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cloudIsVisible(const Cloud* cloud) {
|
||||
return cloud->xPos + CLOUD_WIDTH > 0;
|
||||
}
|
||||
|
29
programs/games/dino/cloud.h
Normal file
29
programs/games/dino/cloud.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef CLOUD_H
|
||||
#define CLOUD_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include "graphics.h"
|
||||
#include "misc.h"
|
||||
|
||||
#define CLOUD_WIDTH 46
|
||||
#define CLOUD_HEIGHT 14
|
||||
#define CLOUD_MAX_GAP 400
|
||||
#define CLOUD_MAX_SKY_LEVEL 30
|
||||
#define CLOUD_MIN_GAP 100
|
||||
#define CLOUD_MIN_SKY_LEVEL 71
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int xPos;
|
||||
int yPos;
|
||||
bool remove;
|
||||
int cloudGap;
|
||||
} Cloud;
|
||||
|
||||
void cloudInit(Cloud* cloud, int w);
|
||||
void cloudDraw(const Cloud* cloud);
|
||||
void cloudUpdate(Cloud* cloud, double speed);
|
||||
bool cloudIsVisible(const Cloud* cloud);
|
||||
|
||||
#endif
|
11
programs/games/dino/collisionbox.h
Normal file
11
programs/games/dino/collisionbox.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef COLLISIONBOX_H
|
||||
#define COLLISIONBOX_H
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
} CollisionBox;
|
||||
|
||||
#endif
|
20
programs/games/dino/config.h
Normal file
20
programs/games/dino/config.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#define DEFAULT_WIDTH 600
|
||||
#define DEFAULT_HEIGHT 200
|
||||
#define FPS 60
|
||||
|
||||
#define DELTA_MS_DEFAULT 20
|
||||
|
||||
#define WINDOW_TITLE "DINO. Jump: UP/SPACE Duck: DOWN Restart: jump or ENTER"
|
||||
|
||||
// #define DBG
|
||||
|
||||
#ifdef DBG
|
||||
#define dbg_printf(...) debug_printf(__VA_ARGS__)
|
||||
#else
|
||||
#define dbg_printf(...)
|
||||
#endif
|
||||
|
||||
#endif
|
134
programs/games/dino/distance_meter.c
Normal file
134
programs/games/dino/distance_meter.c
Normal file
@ -0,0 +1,134 @@
|
||||
#include "distance_meter.h"
|
||||
|
||||
DistanceMeter distanceMeter;
|
||||
|
||||
void distanceMeterInit(int w) {
|
||||
distanceMeter.x = 0;
|
||||
distanceMeter.y = 5;
|
||||
distanceMeter.currentDistance = 0;
|
||||
distanceMeter.maxScore = 0;
|
||||
distanceMeter.achievement = false;
|
||||
distanceMeter.flashTimer = 0;
|
||||
distanceMeter.flashIterations = 0;
|
||||
distanceMeter.invertTrigger = false;
|
||||
distanceMeter.maxScoreUnits = DM_MAX_DISTANCE_UNITS;
|
||||
distanceMeterCalcXPos(w);
|
||||
for (int i = 0; i < distanceMeter.maxScoreUnits; i++) {
|
||||
distanceMeterDraw(i, 0, false);
|
||||
}
|
||||
distanceMeter.maxScore = (int)pow(10, distanceMeter.maxScoreUnits) - 1;
|
||||
distanceMeter.digits[0] = '\0';
|
||||
distanceMeter.highScore[0] = '\0';
|
||||
}
|
||||
|
||||
void distanceMeterCalcXPos(int w) {
|
||||
distanceMeter.x = w - (DM_DEST_WIDTH * (distanceMeter.maxScoreUnits + 1));
|
||||
}
|
||||
|
||||
void distanceMeterDraw(int digitPos, int value, bool opt_highscore) {
|
||||
|
||||
int dx, dy;
|
||||
if (opt_highscore) {
|
||||
dx = distanceMeter.x - (distanceMeter.maxScoreUnits * 2) * DM_WIDTH;
|
||||
dy = distanceMeter.y;
|
||||
}
|
||||
else {
|
||||
dx = distanceMeter.x;
|
||||
dy = distanceMeter.y;
|
||||
}
|
||||
//printf("%d %d %d %d %d %d\n", digitPos, value, opt_highscore, dx, dy, DM_WIDTH * value + ATLAS_TEXT_SPRITE_X);
|
||||
graphicsBlitAtlasImage(
|
||||
DM_WIDTH * value + ATLAS_TEXT_SPRITE_X,
|
||||
0 + ATLAS_TEXT_SPRITE_Y,
|
||||
digitPos * DM_DEST_WIDTH + dx,
|
||||
distanceMeter.y + dy,
|
||||
DM_WIDTH,
|
||||
DM_HEIGHT,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
void distanceMeterDrawHighScore() {
|
||||
// TODO canvasCtx.globalAlpha = .8;
|
||||
for (int i = (int)strlen(distanceMeter.highScore) - 1; i >= 0; i--) {
|
||||
distanceMeterDraw(i, distanceMeter.highScore[i] > 12 ? distanceMeter.highScore[i] - '0' : distanceMeter.highScore[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
void distanceMeterSetHighScore(int _distance) {
|
||||
int distance = distanceMeterGetActualDistance(_distance);
|
||||
distanceMeter.highScore[0] = 10;
|
||||
distanceMeter.highScore[1] = 11;
|
||||
distanceMeter.highScore[2] = 12;
|
||||
intToStr(distance, distanceMeter.maxScoreUnits, distanceMeter.highScore + 3);
|
||||
}
|
||||
|
||||
void distanceMeterReset() {
|
||||
distanceMeterUpdate(0, 0);
|
||||
distanceMeter.achievement = false;
|
||||
}
|
||||
|
||||
int distanceMeterGetActualDistance(int distance) {
|
||||
return distance ? (int)round(distance * DM_COEFFICIENT) : 0;
|
||||
}
|
||||
|
||||
bool distanceMeterUpdate(int deltaTime, int _distance) {
|
||||
bool paint = true;
|
||||
bool playSound = false;
|
||||
int distance = _distance;
|
||||
if (!distanceMeter.achievement) {
|
||||
distance = distanceMeterGetActualDistance(distance);
|
||||
// check if score has gone beyond the initial digit count.
|
||||
if (distance > distanceMeter.maxScore && distanceMeter.maxScoreUnits == DM_MAX_DISTANCE_UNITS) {
|
||||
distanceMeter.maxScoreUnits++;
|
||||
distanceMeter.maxScore = distanceMeter.maxScore * 10 + 9;
|
||||
}
|
||||
// else {
|
||||
// NOTE this.distance was in original but i didsnt see any usage of this field
|
||||
// }
|
||||
|
||||
if (distance > 0) {
|
||||
// Acheivement unlocked
|
||||
if (distance % DM_ACHIEVEMENT_DISTANCE == 0) {
|
||||
// Flash score and play sound
|
||||
distanceMeter.achievement = true;
|
||||
distanceMeter.flashTimer = 0;
|
||||
playSound = true;
|
||||
}
|
||||
// Create a string representation of the distance with leading 0.
|
||||
intToStr(distance, distanceMeter.maxScoreUnits, distanceMeter.digits);
|
||||
}
|
||||
else {
|
||||
intToStr(0, distanceMeter.maxScoreUnits, distanceMeter.digits);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Control flashing of the score on reaching acheivement.
|
||||
if (distanceMeter.flashIterations <= DM_FLASH_ITERATIONS) {
|
||||
distanceMeter.flashTimer += deltaTime;
|
||||
|
||||
if (distanceMeter.flashTimer < DM_FLASH_DURATION) {
|
||||
paint = false;
|
||||
}
|
||||
else if (distanceMeter.flashTimer > DM_FLASH_DURATION * 2) {
|
||||
distanceMeter.flashTimer = 0;
|
||||
distanceMeter.flashIterations++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
distanceMeter.achievement = false;
|
||||
distanceMeter.flashIterations = 0;
|
||||
distanceMeter.flashTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the digits if not flashing
|
||||
if (paint) {
|
||||
for (int i = distanceMeter.maxScoreUnits - 1; i >= 0; i--) {
|
||||
distanceMeterDraw(i, (int)distanceMeter.digits[i] - '0', false);
|
||||
}
|
||||
}
|
||||
|
||||
distanceMeterDrawHighScore();
|
||||
return playSound;
|
||||
}
|
44
programs/games/dino/distance_meter.h
Normal file
44
programs/games/dino/distance_meter.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef DISTANCE_METER_H
|
||||
#define DISTANCE_METER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "graphics.h"
|
||||
#include "misc.h"
|
||||
|
||||
#define DM_MAX_DISTANCE_UNITS 5
|
||||
#define DM_ACHIEVEMENT_DISTANCE 100
|
||||
#define DM_COEFFICIENT 0.025
|
||||
#define DM_FLASH_DURATION 1000/4
|
||||
#define DM_FLASH_ITERATIONS 3
|
||||
#define DM_WIDTH 10
|
||||
#define DM_HEIGHT 13
|
||||
#define DM_DEST_WIDTH 11
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int currentDistance;
|
||||
int maxScore;
|
||||
char digits[16];
|
||||
char highScore[16];
|
||||
bool achievement;
|
||||
int flashTimer;
|
||||
int flashIterations;
|
||||
bool invertTrigger;
|
||||
int maxScoreUnits;
|
||||
} DistanceMeter;
|
||||
|
||||
extern DistanceMeter distanceMeter;
|
||||
|
||||
void distanceMeterInit(int w);
|
||||
void distanceMeterCalcXPos(int w);
|
||||
void distanceMeterDraw(int digitPos, int value, bool opt_highscore);
|
||||
int distanceMeterGetActualDistance(int distance);
|
||||
bool distanceMeterUpdate(int deltaTime, int _distance);
|
||||
void distanceMeterDrawHighScore();
|
||||
void distanceMeterSetHighScore(int _distance);
|
||||
void distanceMeterReset();
|
||||
|
||||
#endif
|
22
programs/games/dino/game_over_panel.c
Normal file
22
programs/games/dino/game_over_panel.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "game_over_panel.h"
|
||||
|
||||
GameOverPanel gameOverPanel;
|
||||
|
||||
void gameOverPanelInit(int width, int height) {
|
||||
gameOverPanel.width = width;
|
||||
gameOverPanel.height = height;
|
||||
}
|
||||
|
||||
void gameOverPanelDraw() {
|
||||
double centerX = gameOverPanel.width / 2;
|
||||
int textTargetX = (int)round(centerX - (GOP_TEXT_WIDTH / 2));
|
||||
int textTargetY = (int)round((gameOverPanel.height - 25) / 3);
|
||||
int restartTargetX = centerX - (GOP_RESTART_WIDTH / 2);
|
||||
int restartTargetY = gameOverPanel.height / 2;
|
||||
// Game over text from sprite
|
||||
graphicsBlitAtlasImage(GOP_TEXT_X + ATLAS_TEXT_SPRITE_X, GOP_TEXT_Y + ATLAS_TEXT_SPRITE_Y,
|
||||
textTargetX, textTargetY, GOP_TEXT_WIDTH, GOP_TEXT_HEIGHT, false);
|
||||
// Restart button
|
||||
graphicsBlitAtlasImage(ATLAS_RESTART_X, ATLAS_RESTART_Y,
|
||||
restartTargetX, restartTargetY, GOP_RESTART_WIDTH, GOP_RESTART_HEIGHT, false);
|
||||
}
|
24
programs/games/dino/game_over_panel.h
Normal file
24
programs/games/dino/game_over_panel.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef GAME_OVER_PANEL_H
|
||||
#define GAME_OVER_PANEL_H
|
||||
|
||||
#include <math.h>
|
||||
#include "graphics.h"
|
||||
|
||||
#define GOP_TEXT_X 0
|
||||
#define GOP_TEXT_Y 13
|
||||
#define GOP_TEXT_WIDTH 191
|
||||
#define GOP_TEXT_HEIGHT 11
|
||||
#define GOP_RESTART_WIDTH 36
|
||||
#define GOP_RESTART_HEIGHT 32
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
} GameOverPanel;
|
||||
|
||||
extern GameOverPanel gameOverPanel;
|
||||
|
||||
void gameOverPanelInit(int width, int height);
|
||||
void gameOverPanelDraw();
|
||||
|
||||
#endif
|
89
programs/games/dino/graphics.c
Normal file
89
programs/games/dino/graphics.c
Normal file
@ -0,0 +1,89 @@
|
||||
#include "graphics.h"
|
||||
#include "sprites.h"
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
Image* screenImage;
|
||||
static Image* spriteAtlas;
|
||||
|
||||
|
||||
void graphicsInit() {
|
||||
spriteAtlas = img_decode((void*)sprites100, sizeof(sprites100), 0);
|
||||
*((uint8_t*)spriteAtlas->Palette + 3) = 0; // set black as transparent
|
||||
// for (int i = 0; i < 16; i++) {
|
||||
// dbg_printf("%x\n", *((uint8_t*)spriteAtlas->Palette + i));
|
||||
// }
|
||||
if (spriteAtlas->Type != IMAGE_BPP32) {
|
||||
spriteAtlas = img_convert(spriteAtlas, NULL, IMAGE_BPP32, 0, 0);
|
||||
if (!spriteAtlas) {
|
||||
dbg_printf("spriteAtlas convert error\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
dbg_printf("spriteAtlas->Type = %d\n", spriteAtlas->Type);
|
||||
screenImage = img_create(DEFAULT_WIDTH, DEFAULT_HEIGHT, IMAGE_BPP32);
|
||||
// asm_inline("emms"); // doenst need bec. libimg functions used here does not use mmx (=> does not currept fpu state)
|
||||
}
|
||||
|
||||
void graphicsBlitAtlasImage(int atlasX, int atlasY, int destX, int destY, int w, int h, bool center) {
|
||||
// dbg_printf("start graphicsBlitAtlasImage ax = %d ay = %d dx = %d dy = %d w = %d h = %d %x %x\n", atlasX, atlasY, destX, destY, w, h, screenImage, spriteAtlas);
|
||||
|
||||
int screen_width = (int)screenImage->Width;
|
||||
int screen_height = (int)screenImage->Height;
|
||||
|
||||
if (destX >= screen_width) {
|
||||
return;
|
||||
}
|
||||
if (destY >= screen_height) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (destX < 0) {
|
||||
atlasX -= destX;
|
||||
w = destX + w;
|
||||
destX = 0;
|
||||
}
|
||||
if (destX + w > screen_width) {
|
||||
w = screen_width - destX;
|
||||
}
|
||||
|
||||
if (destY < 0) {
|
||||
atlasY -= destY;
|
||||
h = destY + h;
|
||||
destY = 0;
|
||||
}
|
||||
if (destY + h > screen_height) {
|
||||
h = screen_height - destY;
|
||||
}
|
||||
|
||||
if (w <= 0 || h <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//printf("start graphicsBlitAtlasImage ax = %d ay = %d dx = %d dy = %d w = %d h = %d %x %x\n\n", atlasX, atlasY, destX, destY, w, h, screenImage, spriteAtlas);
|
||||
|
||||
img_blend(screenImage, spriteAtlas, destX, destY, atlasX, atlasY, w, h);
|
||||
asm_inline("emms");
|
||||
|
||||
// dbg_printf("end graphicsBlitAtlasImage\n\n");
|
||||
}
|
||||
|
||||
void graphicsFillBackground(unsigned r, unsigned g, unsigned b) {
|
||||
img_fill_color(screenImage, screenImage->Width, screenImage->Height, (0xFF << 24) | (r << 16) | (g << 8) | b);
|
||||
}
|
||||
|
||||
void graphicsRender() {
|
||||
// don't redraw window on each frame. redraw window only when redraw event (called when widow moved e.g.)
|
||||
img_draw(screenImage, 5, 24, screenImage->Width, screenImage->Height, 0, 0);
|
||||
}
|
||||
|
||||
void graphicsDelay(int ms) {
|
||||
// dbg_printf("ms = %d\n", ms);
|
||||
_ksys_delay(ms/10 ? ms/10 : 2);
|
||||
}
|
||||
|
||||
|
||||
void graphicsDestroy() {
|
||||
img_destroy(screenImage);
|
||||
img_destroy(spriteAtlas);
|
||||
}
|
43
programs/games/dino/graphics.h
Normal file
43
programs/games/dino/graphics.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef GRAPHICS_H
|
||||
#define GRAPHICS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/ksys.h>
|
||||
#include <clayer/libimg.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define ATLAS_CACTUS_LARGE_X 332
|
||||
#define ATLAS_CACTUS_LARGE_Y 2
|
||||
#define ATLAS_CACTUS_SMALL_X 228
|
||||
#define ATLAS_CACTUS_SMALL_Y 2
|
||||
#define ATLAS_CLOUD_X 86
|
||||
#define ATLAS_CLOUD_Y 2
|
||||
#define ATLAS_HORIZON_X 2
|
||||
#define ATLAS_HORIZON_Y 54
|
||||
#define ATLAS_MOON_X 484
|
||||
#define ATLAS_MOON_Y 2
|
||||
#define ATLAS_PTERODACTYL_X 134
|
||||
#define ATLAS_PTERODACTYL_Y 2
|
||||
#define ATLAS_RESTART_X 2
|
||||
#define ATLAS_RESTART_Y 2
|
||||
#define ATLAS_TEXT_SPRITE_X 655
|
||||
#define ATLAS_TEXT_SPRITE_Y 2
|
||||
#define ATLAS_TREX_X 848
|
||||
#define ATLAS_TREX_Y 2
|
||||
#define ATLAS_STAR_X 645
|
||||
#define ATLAS_STAR_Y 2
|
||||
|
||||
extern Image* screenImage;
|
||||
|
||||
void graphicsInit();
|
||||
void graphicsBlitAtlasImage(int atlasX, int atlasY, int destX, int destY, int w, int h, bool center);
|
||||
void graphicsFillBackground(unsigned r, unsigned g, unsigned b);
|
||||
void graphicsRender();
|
||||
void graphicsDelay(int ms);
|
||||
void graphicsDestroy();
|
||||
|
||||
#endif
|
147
programs/games/dino/horizon.c
Normal file
147
programs/games/dino/horizon.c
Normal file
@ -0,0 +1,147 @@
|
||||
#include "horizon.h"
|
||||
|
||||
Horizon horizon;
|
||||
|
||||
void horizonInit(int dim_width, double gapCoefficient) {
|
||||
horizon.dim_width = dim_width;
|
||||
horizon.gapCoefficient = gapCoefficient;
|
||||
horizon.obstacles = ulist_create();
|
||||
horizon.obstacleHistory = ulist_create();
|
||||
horizon.clouds = ulist_create();
|
||||
|
||||
horizonAddCloud();
|
||||
|
||||
horizonLineInit();
|
||||
}
|
||||
|
||||
void horizonUpdate(int deltaTime, double currentSpeed, bool updateObstacles, bool showNightMode) {
|
||||
//horizon.runningTime += deltaTime;
|
||||
horizonLineUpdate(deltaTime, currentSpeed);
|
||||
// if (currentSpeed != currentSpeed) {
|
||||
// currentSpeed = 6.0;
|
||||
// }
|
||||
// horizon.nightMode.update(showNightMode);
|
||||
horizonUpdateClouds(deltaTime, currentSpeed);
|
||||
if (updateObstacles) {
|
||||
horizonUpdateObstacles(deltaTime, currentSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
void horizonUpdateClouds(int deltaTime, double speed) {
|
||||
//printf("horizonUpdateClouds()\n");
|
||||
double cloudSpeed = HORIZON_BG_CLOUD_SPEED / 1000 * deltaTime * speed;
|
||||
int numClouds = ulist_size(horizon.clouds);
|
||||
//printf("horizonUpdateClouds() %d\n", numClouds);
|
||||
|
||||
if (numClouds) {
|
||||
Node *cloudNode = horizon.clouds->tail;
|
||||
while (cloudNode != NULL) {
|
||||
cloudUpdate(cloudNode->data, cloudSpeed);
|
||||
cloudNode = cloudNode->prev;
|
||||
}
|
||||
Cloud *lastCloud = horizon.clouds->tail->data;
|
||||
// Check for adding a new cloud
|
||||
if (numClouds < HORIZON_MAX_CLOUDS && (horizon.dim_width - lastCloud->xPos) > lastCloud->cloudGap && HORIZON_CLOUD_FREQUENCY > (double)rand()/RAND_MAX) {
|
||||
horizonAddCloud();
|
||||
}
|
||||
// Remove expired clouds
|
||||
cloudNode = horizon.clouds->head;
|
||||
while (cloudNode != NULL) {
|
||||
Node* cloudNodeNext = cloudNode->next;
|
||||
Cloud* c = cloudNode->data;
|
||||
if (c->remove) {
|
||||
ulist_remove(horizon.clouds, cloudNode);
|
||||
}
|
||||
cloudNode = cloudNodeNext;
|
||||
}
|
||||
}
|
||||
else {
|
||||
horizonAddCloud();
|
||||
}
|
||||
}
|
||||
|
||||
void horizonUpdateObstacles(int deltaTime, double currentSpeed) {
|
||||
//printf("horizonUpdateObstacles()\n");
|
||||
// Obstacles, move to Horizon layer
|
||||
Node* obNode = horizon.obstacles->head;
|
||||
while (obNode != NULL) {
|
||||
Node* obNodeNext = obNode->next;
|
||||
Obstacle* ob = obNode->data;
|
||||
obstacleUpdate(ob, deltaTime, currentSpeed);
|
||||
// Clean up existing obstacles
|
||||
if (ob->remove) {
|
||||
//ulist_remove(horizon.obstacles, obNode);
|
||||
//ulist_print(horizon.obstacles);
|
||||
ulist_remove_front(horizon.obstacles);
|
||||
//ulist_print(horizon.obstacles);
|
||||
//puts("");
|
||||
}
|
||||
obNode = obNodeNext;
|
||||
}
|
||||
|
||||
if (ulist_size(horizon.obstacles) > 0) {
|
||||
Obstacle *lastObstacle = horizon.obstacles->tail->data;
|
||||
|
||||
if (lastObstacle && !lastObstacle->followingObstacleCreated && obstacleIsVisible(lastObstacle) && (lastObstacle->xPos + lastObstacle->width + lastObstacle->gap) < horizon.dim_width) {
|
||||
horizonAddNewObstacle(currentSpeed);
|
||||
lastObstacle->followingObstacleCreated = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Create new obstacles.
|
||||
horizonAddNewObstacle(currentSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
void horizonAddNewObstacle(double currentSpeed) {
|
||||
int obstacleTypeIndex = getRandomNumber(0, sizeof(obstacleTypeConfigs)/sizeof(ObstacleTypeConfig) - 1);
|
||||
ObstacleTypeConfig *otc = &obstacleTypeConfigs[obstacleTypeIndex];
|
||||
|
||||
// Check for multiples of the same type of obstacle.
|
||||
// Also check obstacle is available at current speed.
|
||||
if (horizonDuplicateObstacleCheck(otc->type) || currentSpeed < otc->minSpeed) {
|
||||
horizonAddNewObstacle(currentSpeed);
|
||||
}
|
||||
else {
|
||||
Obstacle* ob = malloc(sizeof(Obstacle));
|
||||
obstacleInit(ob, otc, horizon.dim_width, horizon.gapCoefficient, currentSpeed, otc->width);
|
||||
ulist_push_back(horizon.obstacles, ob);
|
||||
ulist_push_front(horizon.obstacleHistory, &(otc->type));
|
||||
if (ulist_size(horizon.obstacleHistory) > 1) {
|
||||
ulist_splice(horizon.obstacleHistory, RUNNER_MAX_OBSTACLE_DUPLICATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool horizonDuplicateObstacleCheck(ObstacleType nextObstacleType) {
|
||||
//printf("horizonDuplicateObstacleCheck(%d)\n", nextObstacleType);
|
||||
int duplicateCount = 0;
|
||||
Node* ohNode = horizon.obstacleHistory->head;
|
||||
while (ohNode != NULL) {
|
||||
//printf("%d\n", *(int*)ohNode->data);
|
||||
duplicateCount = *(int*)ohNode->data == nextObstacleType ? duplicateCount + 1 : 0;
|
||||
ohNode = ohNode->next;
|
||||
}
|
||||
//printf("duplicateCount = %d\n\n", duplicateCount);
|
||||
return duplicateCount >= RUNNER_MAX_OBSTACLE_DUPLICATION;
|
||||
}
|
||||
|
||||
void horizonReset() {
|
||||
// printf("horizonReset() !!\n");
|
||||
ulist_destroy(horizon.obstacles);
|
||||
horizon.obstacles = ulist_create();
|
||||
horizonLineReset();
|
||||
}
|
||||
|
||||
//void horizonResize(int width, int height) {
|
||||
//
|
||||
//}
|
||||
|
||||
void horizonAddCloud() {
|
||||
Cloud* c = malloc(sizeof(Cloud));
|
||||
cloudInit(c, horizon.dim_width);
|
||||
//printf("horizonAddCloud() %d -> ", ulist_size(horizon.obstacles));
|
||||
ulist_push_back(horizon.clouds, c);
|
||||
//printf("%d\n", ulist_size(horizon.obstacles));
|
||||
}
|
||||
|
41
programs/games/dino/horizon.h
Normal file
41
programs/games/dino/horizon.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef HORIZON_H
|
||||
#define HORIZON_H
|
||||
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include "obstacle.h"
|
||||
#include "cloud.h"
|
||||
#include "horizon_line.h"
|
||||
#include "runner.h"
|
||||
#include "graphics.h"
|
||||
#include "ulist.h"
|
||||
|
||||
#define HORIZON_BG_CLOUD_SPEED 0.2
|
||||
#define HORIZON_BUMPY_THRESHOLD 0.3
|
||||
#define HORIZON_CLOUD_FREQUENCY 0.5
|
||||
#define HORIZON_HORIZON_HEIGHT 16
|
||||
#define HORIZON_MAX_CLOUDS 6
|
||||
|
||||
typedef struct {
|
||||
int dim_width;
|
||||
double gapCoefficient;
|
||||
Ulist* obstacles;
|
||||
Ulist* obstacleHistory;
|
||||
// nightMode
|
||||
Ulist* clouds;
|
||||
} Horizon;
|
||||
|
||||
extern Horizon horizon;
|
||||
|
||||
void horizonInit(int dim_width, double gapCoefficient);
|
||||
void horizonUpdate(int deltaTime, double currentSpeed, bool updateObstacles, bool showNightMode);
|
||||
void horizonUpdateClouds(int deltaTime, double speed);
|
||||
void horizonUpdateObstacles(int deltaTime, double currentSpeed);
|
||||
//void horizonRemoveFirstObstacle();
|
||||
void horizonAddNewObstacle(double currentSpeed);
|
||||
bool horizonDuplicateObstacleCheck(ObstacleType nextObstacleType);
|
||||
void horizonReset();
|
||||
//void horizonResize(int width, int height);
|
||||
void horizonAddCloud();
|
||||
|
||||
#endif
|
56
programs/games/dino/horizon_line.c
Normal file
56
programs/games/dino/horizon_line.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include "horizon_line.h"
|
||||
|
||||
HorizonLine horizonLine;
|
||||
|
||||
void horizonLineInit() {
|
||||
horizonLine.width = HORIZON_LINE_WIDTH;
|
||||
horizonLine.height = HORIZON_LINE_HEIGHT;
|
||||
horizonLine.sourceXPos[0] = ATLAS_HORIZON_X;
|
||||
horizonLine.sourceXPos[1] = ATLAS_HORIZON_X + horizonLine.width;
|
||||
horizonLine.bumpThreshold = 0.5;
|
||||
horizonLine.xPos[0] = 0;
|
||||
horizonLine.xPos[1] = horizonLine.width;
|
||||
horizonLine.yPos = HORIZON_LINE_YPOS;
|
||||
horizonLineDraw();
|
||||
}
|
||||
|
||||
void horizonLineDraw() {
|
||||
//printf("horizonLineDraw(); xPos[0] = %d, xPos[1] = %d, yPos = %d, width = %d, height = %d\n", horizonLine.xPos[0], horizonLine.xPos[1], horizonLine.yPos, horizonLine.width, horizonLine.height);
|
||||
graphicsBlitAtlasImage(horizonLine.sourceXPos[0], ATLAS_HORIZON_Y, horizonLine.xPos[0], horizonLine.yPos, horizonLine.width, horizonLine.height, false);
|
||||
graphicsBlitAtlasImage(horizonLine.sourceXPos[1], ATLAS_HORIZON_Y, horizonLine.xPos[1], horizonLine.yPos, horizonLine.width, horizonLine.height, false);
|
||||
}
|
||||
|
||||
int horizonLineGetRandomType() {
|
||||
return (double)rand() / RAND_MAX > horizonLine.bumpThreshold ? horizonLine.width : 0;
|
||||
}
|
||||
|
||||
void horizonLineUpdateXPos(int pos, int increment) {
|
||||
int line1 = pos;
|
||||
int line2 = pos == 0 ? 1 : 0;
|
||||
|
||||
horizonLine.xPos[line1] -= increment;
|
||||
horizonLine.xPos[line2] = horizonLine.xPos[line1] + horizonLine.width;
|
||||
|
||||
if (horizonLine.xPos[line1] <= -horizonLine.width) {
|
||||
horizonLine.xPos[line1] += horizonLine.width * 2;
|
||||
horizonLine.xPos[line2] = horizonLine.xPos[line1] - horizonLine.width;
|
||||
horizonLine.sourceXPos[line1] = horizonLineGetRandomType() + ATLAS_HORIZON_X;
|
||||
}
|
||||
}
|
||||
|
||||
void horizonLineUpdate(int deltaTime, double speed) {
|
||||
int increment = floor(speed * (FPS / 1000.0) * deltaTime);
|
||||
if (horizonLine.xPos[0] <= 0) {
|
||||
horizonLineUpdateXPos(0, increment);
|
||||
}
|
||||
else {
|
||||
horizonLineUpdateXPos(1, increment);
|
||||
}
|
||||
// asm_inline("int $3");
|
||||
horizonLineDraw();
|
||||
}
|
||||
|
||||
void horizonLineReset() {
|
||||
horizonLine.xPos[0] = 0;
|
||||
horizonLine.xPos[1] = horizonLine.width;
|
||||
}
|
33
programs/games/dino/horizon_line.h
Normal file
33
programs/games/dino/horizon_line.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef HORIZON_LINE_H
|
||||
#define HORIZON_LINE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include "config.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#define HORIZON_LINE_WIDTH 600
|
||||
#define HORIZON_LINE_HEIGHT 12
|
||||
#define HORIZON_LINE_YPOS 127
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
int sourceXPos[2];
|
||||
int xPos[2];
|
||||
int yPos;
|
||||
double bumpThreshold;
|
||||
} HorizonLine;
|
||||
|
||||
extern HorizonLine horizonLine;
|
||||
|
||||
void horizonLineInit();
|
||||
void horizonLineDraw();
|
||||
int horizonLineGetRandomType();
|
||||
void horizonLineUpdateXPos(int pos, int increment);
|
||||
void horizonLineUpdate(int deltaTime, double speed);
|
||||
void horizonLineReset();
|
||||
|
||||
#endif
|
136
programs/games/dino/main.c
Normal file
136
programs/games/dino/main.c
Normal file
@ -0,0 +1,136 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <sys/ksys.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "graphics.h"
|
||||
#include "distance_meter.h"
|
||||
#include "cloud.h"
|
||||
#include "obstacle.h"
|
||||
#include "horizon_line.h"
|
||||
#include "trex.h"
|
||||
#include "runner.h"
|
||||
|
||||
static uint8_t keyboard_layout[128];
|
||||
|
||||
int main(int argc, char* args[]) {
|
||||
srand((unsigned int)time(NULL)); // Seed the random number generator
|
||||
|
||||
ksys_pos_t win_pos = _ksys_screen_size();
|
||||
win_pos.x /= 2;
|
||||
win_pos.x -= DEFAULT_WIDTH/2;
|
||||
win_pos.y /= 2;
|
||||
win_pos.y -= DEFAULT_HEIGHT/2;
|
||||
dbg_printf("wx = %d, wy = %d\n", win_pos.x, win_pos.y);
|
||||
ksys_colors_table_t sys_color_table;
|
||||
_ksys_get_system_colors(&sys_color_table);
|
||||
_ksys_set_event_mask(0xC0000027); // !
|
||||
_ksys_set_key_input_mode(KSYS_KEY_INPUT_MODE_SCANC);
|
||||
_ksys_keyboard_layout(KSYS_KEYBOARD_LAYOUT_NORMAL, keyboard_layout);
|
||||
|
||||
graphicsInit();
|
||||
|
||||
runnerInit();
|
||||
|
||||
dbg_printf("dino started\n");
|
||||
|
||||
int ext_code = 0;
|
||||
uint8_t old_mode = 0;
|
||||
|
||||
bool quit = false;
|
||||
while (quit == false) {
|
||||
int frameStartTime = getTimeStamp();
|
||||
//printf("frameStartTime = %d\n", frameStartTime);
|
||||
uint32_t kos_event = _ksys_check_event();
|
||||
switch (kos_event) {
|
||||
case KSYS_EVENT_BUTTON:
|
||||
switch (_ksys_get_button()){
|
||||
case 1:
|
||||
quit = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case KSYS_EVENT_KEY:
|
||||
{
|
||||
ksys_oskey_t key = _ksys_get_key();
|
||||
uint8_t scancode = key.code;
|
||||
if (scancode == 0xE0 || scancode == 0xE1) {
|
||||
ext_code = scancode;
|
||||
break;
|
||||
}
|
||||
if (ext_code == 0xE1 && (scancode & 0x7F) == 0x1D) {
|
||||
break;
|
||||
}
|
||||
if (ext_code == 0xE1 && scancode == 0xC5) {
|
||||
ext_code = 0;
|
||||
break;
|
||||
}
|
||||
uint8_t code = keyboard_layout[scancode & 0x7F];
|
||||
|
||||
if (ext_code == 0xE0) {
|
||||
code -= 96;
|
||||
}
|
||||
ext_code = 0;
|
||||
|
||||
if (scancode < 128) { // KEYDOWN
|
||||
//dbg_printf("Keydown: key = 0x%x, scancode = 0x%x, code = 0x%x (%u) state = 0x%x\n", key.val, scancode, code, code, key.state);
|
||||
//dbg_printf("keydown c = %u\n", key.code);
|
||||
runnerOnKeyDown(code);
|
||||
} else { // KEYUP
|
||||
//dbg_printf("Keyup: key = 0x%x, scancode = 0x%x, code = 0x%x (%u) state = 0x%x\n", key.val, scancode, code, code, key.state);
|
||||
//dbg_printf("keyup c = %u\n", key.code);
|
||||
runnerOnKeyUp(code);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KSYS_EVENT_REDRAW:
|
||||
//dbg_printf("KSYS_EVENT_REDRAW\n");
|
||||
_ksys_start_draw();
|
||||
_ksys_create_window(win_pos.x, win_pos.y, screenImage->Width + 10, screenImage->Height + 29, WINDOW_TITLE, sys_color_table.work_area, 0x54); // 0x54. note: C = 1 !!
|
||||
graphicsRender();
|
||||
_ksys_end_draw();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (runner.nextUpdateScheduled) {
|
||||
//printf("runner update! %u\n", getTimeStamp());
|
||||
//dbg_printf("runnerUpdate\n");
|
||||
runnerUpdate();
|
||||
}
|
||||
else {
|
||||
if (runner.skipUpdateNow) {
|
||||
//printf("Skipped one update\n");
|
||||
runner.nextUpdateScheduled = true;
|
||||
runner.skipUpdateNow = false;
|
||||
}
|
||||
}
|
||||
|
||||
int frameTime = getTimeStamp() - frameStartTime;
|
||||
if (frameTime < 0) {
|
||||
frameTime = DELTA_MS_DEFAULT;
|
||||
}
|
||||
#define FRAME_TIME 20 //16
|
||||
// dbg_printf("frameTime = %d\n", frameTime);
|
||||
if (frameTime < FRAME_TIME) { // 1000ms/60frames = 16.(6)
|
||||
// printf("frameTime = %d\n", frameTime);
|
||||
if (runner.crashed) {
|
||||
// dbg_printf("runner.timeAfterCrashedMs +=\n");
|
||||
runner.timeAfterCrashedMs += FRAME_TIME - frameTime;
|
||||
}
|
||||
graphicsDelay(FRAME_TIME - frameTime);
|
||||
}
|
||||
}
|
||||
|
||||
graphicsDestroy();
|
||||
|
||||
return 0;
|
||||
}
|
28
programs/games/dino/misc.c
Normal file
28
programs/games/dino/misc.c
Normal file
@ -0,0 +1,28 @@
|
||||
#include "misc.h"
|
||||
|
||||
int getRandomNumber(int _min, int _max) {
|
||||
return rand() % (_max - _min + 1) + _min;
|
||||
}
|
||||
|
||||
void intToStr(int num, int ndigits, char* result) {
|
||||
char num_str[16]; // 16 more than enough for int
|
||||
sprintf(num_str, "%d", num); // Convert num to a string
|
||||
if (strlen(num_str) > ndigits) {
|
||||
// Copy only the last ndigits to result
|
||||
strcpy(result, num_str + strlen(num_str) - ndigits);
|
||||
}
|
||||
else {
|
||||
// Pad the string with leading zeros until it reaches a length of ndigits
|
||||
size_t z = ndigits - strlen(num_str);
|
||||
for (size_t i = 0; i < z; i++) {
|
||||
result[i] = '0';
|
||||
}
|
||||
strcpy(result + z, num_str);
|
||||
}
|
||||
}
|
||||
|
||||
int getTimeStamp() { // in ms
|
||||
uint64_t x = 0;
|
||||
x = _ksys_get_ns_count();
|
||||
return (x/1000000);
|
||||
}
|
13
programs/games/dino/misc.h
Normal file
13
programs/games/dino/misc.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef MISC_H
|
||||
#define MISC_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ksys.h>
|
||||
|
||||
int getRandomNumber(int _min, int _max);
|
||||
void intToStr(int num, int ndigits, char* result);
|
||||
int getTimeStamp();
|
||||
|
||||
#endif
|
156
programs/games/dino/obstacle.c
Normal file
156
programs/games/dino/obstacle.c
Normal file
@ -0,0 +1,156 @@
|
||||
#include "obstacle.h"
|
||||
|
||||
ObstacleTypeConfig obstacleTypeConfigs[3] = {
|
||||
{
|
||||
.type = CACTUS_SMALL,
|
||||
.width = 17,
|
||||
.height = 35,
|
||||
.yPos = 105,
|
||||
.multipleSpeed = 4,
|
||||
.minGap = 120,
|
||||
.minSpeed = 0,
|
||||
.collisionBoxesCount = 3,
|
||||
.collisionBoxes = {
|
||||
{.x = 0, .y = 7, .width = 5, .height = 27},
|
||||
{.x = 4, .y = 0, .width = 6, .height = 34},
|
||||
{.x = 10, .y = 4, .width = 7, .height = 14}
|
||||
},
|
||||
.numFrames = 1,
|
||||
.speedOffset = 0
|
||||
},
|
||||
{
|
||||
.type = CACTUS_LARGE,
|
||||
.width = 25,
|
||||
.height = 50,
|
||||
.yPos = 90,
|
||||
.multipleSpeed = 7,
|
||||
.minGap = 120,
|
||||
.minSpeed = 0,
|
||||
.collisionBoxesCount = 3,
|
||||
.collisionBoxes = {
|
||||
{.x = 0, .y = 12, .width = 7, .height = 38},
|
||||
{.x = 8, .y = 0, .width = 7, .height = 49},
|
||||
{.x = 13, .y = 10, .width = 10, .height = 38}
|
||||
},
|
||||
.numFrames = 1,
|
||||
.speedOffset = 0
|
||||
},
|
||||
{
|
||||
.type = PTERODACTYL,
|
||||
.width = 46,
|
||||
.height = 40,
|
||||
.yPos = -1,
|
||||
.yPosArrSize = 3,
|
||||
.yPosArr = {100, 75, 50},
|
||||
.multipleSpeed = 999,
|
||||
.minGap = 150,
|
||||
.minSpeed = 8.5,
|
||||
.collisionBoxesCount = 5,
|
||||
.collisionBoxes = {
|
||||
{.x = 15, .y = 15, .width = 16, .height = 5},
|
||||
{.x = 18, .y = 21, .width = 24, .height = 6},
|
||||
{.x = 2, .y = 14, .width = 4, .height = 3},
|
||||
{.x = 6, .y = 10, .width = 4, .height = 7},
|
||||
{.x = 10, .y = 8, .width = 6, .height = 9}
|
||||
},
|
||||
.numFrames = 2,
|
||||
.frameRate = 1000 / 6,
|
||||
.speedOffset = 0.8
|
||||
}
|
||||
};
|
||||
|
||||
int obstacleSpritePosX[3] = { ATLAS_CACTUS_SMALL_X, ATLAS_CACTUS_LARGE_X, ATLAS_PTERODACTYL_X};
|
||||
int obstacleSpritePosY[3] = { ATLAS_CACTUS_SMALL_Y, ATLAS_CACTUS_LARGE_Y, ATLAS_PTERODACTYL_Y};
|
||||
|
||||
|
||||
void obstacleInit(Obstacle* ob, const ObstacleTypeConfig *otc, int dim_width, double gapCoefficient, double speed, int opt_xOffset) {
|
||||
ob->typeConfig = *otc;
|
||||
ob->gapCoefficient = gapCoefficient;
|
||||
ob->size = getRandomNumber(1, OBSTACLE_MAX_OBSTACLE_LENGTH);
|
||||
ob->remove = false;
|
||||
ob->xPos = dim_width + opt_xOffset;
|
||||
ob->yPos = 0;
|
||||
|
||||
// For animated obstacles
|
||||
ob->currentFrame = 0;
|
||||
ob->timer = 0;
|
||||
|
||||
ob->followingObstacleCreated = false;
|
||||
|
||||
if (ob->size > 1 && ob->typeConfig.multipleSpeed > speed) { // NOTE what it this?
|
||||
ob->size = 1;
|
||||
}
|
||||
ob->width = ob->typeConfig.width * ob->size;
|
||||
|
||||
if (ob->typeConfig.yPos == -1) {
|
||||
ob->yPos = ob->typeConfig.yPosArr[getRandomNumber(0, ob->typeConfig.yPosArrSize)];
|
||||
}
|
||||
else {
|
||||
ob->yPos = ob->typeConfig.yPos;
|
||||
}
|
||||
|
||||
obstacleDraw(ob);
|
||||
|
||||
// Make collision box adjustments,
|
||||
// Central box is adjusted to the size as one box.
|
||||
// ____ ______ ________
|
||||
// _| |-| _| |-| _| |-|
|
||||
// | |<->| | | |<--->| | | |<----->| |
|
||||
// | | 1 | | | | 2 | | | | 3 | |
|
||||
// |_|___|_| |_|_____|_| |_|_______|_|
|
||||
//
|
||||
|
||||
if (ob->size > 1) {
|
||||
ob->typeConfig.collisionBoxes[1].width = ob->width - ob->typeConfig.collisionBoxes[0].width - ob->typeConfig.collisionBoxes[2].width;
|
||||
ob->typeConfig.collisionBoxes[2].x = ob->width - ob->typeConfig.collisionBoxes[2].width;
|
||||
}
|
||||
|
||||
// For obstacles that go at a different speed from the horizon
|
||||
if (ob->typeConfig.speedOffset) {
|
||||
ob->typeConfig.speedOffset = (double)rand() / RAND_MAX > 0.5 ? ob->typeConfig.speedOffset : -ob->typeConfig.speedOffset;
|
||||
}
|
||||
ob->gap = obstacleGetGap(ob, ob->gapCoefficient, speed);
|
||||
}
|
||||
|
||||
void obstacleDraw(const Obstacle *ob) {
|
||||
int sourceWidth = ob->typeConfig.width;
|
||||
int sourceHeight = ob->typeConfig.height;
|
||||
int sourceX = (sourceWidth * ob->size) * (0.5 * ((double)ob->size - 1)) + obstacleSpritePosX[ob->typeConfig.type];
|
||||
if (ob->currentFrame > 0) {
|
||||
sourceX += sourceWidth*ob->currentFrame;
|
||||
}
|
||||
//dbg_printf("od ax=%u, ay=%u, dx=%u, dy=%u, w=%u, h=%u\n", sourceX, obstacleSpritePosY[ob->typeConfig.type], ob->xPos, ob->yPos, sourceWidth*ob->size, sourceHeight);
|
||||
graphicsBlitAtlasImage(sourceX, obstacleSpritePosY[ob->typeConfig.type], ob->xPos, ob->yPos, sourceWidth*ob->size, sourceHeight, false);
|
||||
}
|
||||
|
||||
void obstacleUpdate(Obstacle *ob, int deltaTime, double speed) {
|
||||
if (!ob->remove) {
|
||||
double dx = floor(((speed + ob->typeConfig.speedOffset)*FPS/1000.)*deltaTime);
|
||||
//dbg_printf("sp = %lf, ots = %lf, dx = %d, xpos = %d\n", speed, ob->typeConfig.speedOffset, (int)dx, ob->xPos - dx);
|
||||
ob->xPos -= dx;//floor(((speed + ob->typeConfig.speedOffset)*FPS/1000.)*deltaTime);
|
||||
}
|
||||
// Update frames
|
||||
if (ob->typeConfig.numFrames > 1) {
|
||||
ob->timer += deltaTime;
|
||||
if (ob->timer >= ob->typeConfig.frameRate) {
|
||||
ob->currentFrame = ob->currentFrame == ob->typeConfig.numFrames - 1 ? 0 : ob->currentFrame + 1;
|
||||
ob->timer = 0;
|
||||
}
|
||||
}
|
||||
obstacleDraw(ob);
|
||||
if (!obstacleIsVisible(ob)) {
|
||||
ob->remove = true;
|
||||
}
|
||||
}
|
||||
|
||||
int obstacleGetGap(const Obstacle *ob, double gapCoefficient, double speed) {
|
||||
int minGap = round(ob->width * speed + ob->typeConfig.minGap * gapCoefficient);
|
||||
int maxGap = round(minGap * OBSTACLE_MAX_GAP_COEFFICIENT);
|
||||
return getRandomNumber(minGap, maxGap);
|
||||
}
|
||||
|
||||
bool obstacleIsVisible(const Obstacle* ob) {
|
||||
return ob->xPos + ob->width > 0;
|
||||
}
|
||||
|
||||
|
67
programs/games/dino/obstacle.h
Normal file
67
programs/games/dino/obstacle.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef OBSTACLE_H
|
||||
#define OBSTACLE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "graphics.h"
|
||||
#include "misc.h"
|
||||
#include "config.h"
|
||||
#include "collisionbox.h"
|
||||
|
||||
// Coefficient for calculating the maximum gap
|
||||
#define OBSTACLE_MAX_GAP_COEFFICIENT 1.5
|
||||
|
||||
// Maximum obstacle grouping count
|
||||
#define OBSTACLE_MAX_OBSTACLE_LENGTH 3
|
||||
|
||||
typedef enum {
|
||||
CACTUS_SMALL = 0,
|
||||
CACTUS_LARGE = 1,
|
||||
PTERODACTYL = 2
|
||||
} ObstacleType;
|
||||
|
||||
extern int obstacleSpritePosX[3];
|
||||
extern int obstacleSpritePosY[3];
|
||||
|
||||
typedef struct {
|
||||
ObstacleType type;
|
||||
int width;
|
||||
int height;
|
||||
int yPos;
|
||||
int yPosArrSize;
|
||||
int yPosArr[3]; // used if yPos is -1
|
||||
int multipleSpeed;
|
||||
int minGap;
|
||||
int minSpeed;
|
||||
int collisionBoxesCount;
|
||||
CollisionBox collisionBoxes[5];
|
||||
int numFrames;
|
||||
double frameRate;
|
||||
double speedOffset;
|
||||
} ObstacleTypeConfig;
|
||||
|
||||
typedef struct {
|
||||
ObstacleTypeConfig typeConfig;
|
||||
double gapCoefficient;
|
||||
int size;
|
||||
bool remove;
|
||||
int xPos;
|
||||
int yPos;
|
||||
int width;
|
||||
int gap;
|
||||
// double speedOffset;
|
||||
int currentFrame;
|
||||
int timer;
|
||||
bool followingObstacleCreated;
|
||||
} Obstacle;
|
||||
|
||||
extern ObstacleTypeConfig obstacleTypeConfigs[3];
|
||||
|
||||
void obstacleInit(Obstacle *ob, const ObstacleTypeConfig *otc, int dim_width, double gapCoefficient, double speed, int opt_xOffset);
|
||||
void obstacleDraw(const Obstacle* ob);
|
||||
void obstacleUpdate(Obstacle* ob, int deltaTime, double speed);
|
||||
int obstacleGetGap(const Obstacle* ob, double gapCoefficient, double speed);
|
||||
bool obstacleIsVisible(const Obstacle* ob);
|
||||
|
||||
#endif
|
333
programs/games/dino/runner.c
Normal file
333
programs/games/dino/runner.c
Normal file
@ -0,0 +1,333 @@
|
||||
#include "runner.h"
|
||||
|
||||
int aaaaaaa[10000];
|
||||
Runner runner;
|
||||
int bbbbbb[10000];
|
||||
|
||||
void runnerInit() {
|
||||
runner.distanceRan = 0;
|
||||
runner.highestScore = 0;
|
||||
runner.time = 0;
|
||||
runner.msPerFrame = 1000.0 / FPS;
|
||||
runner.currentSpeed = RUNNER_SPEED;
|
||||
runner.activated = false;
|
||||
runner.playing = false;
|
||||
runner.crashed = false;
|
||||
runner.timeAfterCrashedMs = 0;
|
||||
runner.paused = false;
|
||||
runner.inverted = false;
|
||||
runner.playingIntro = false;
|
||||
runner.isRunning = false; // is running or game stopped
|
||||
runner.invertTimer = 0;
|
||||
runner.playCount = 0;
|
||||
runner.nextUpdateScheduled = false;
|
||||
runner.skipUpdateNow = false;
|
||||
// TODO sound
|
||||
// runnerLoadImages();
|
||||
runnerAdjustDimensions();
|
||||
// setSpeed
|
||||
graphicsFillBackground(0xF7, 0xF7, 0xF7);
|
||||
|
||||
gameOverPanelInit(runner.width, runner.height);
|
||||
|
||||
horizonInit(runner.width, RUNNER_GAP_COEFFICIENT);
|
||||
distanceMeterInit(runner.width);
|
||||
trexInit();
|
||||
|
||||
// this.startListening();
|
||||
runnerUpdate();
|
||||
//window.addEventListener(Runner.events.RESIZE, this.debounceResize.bind(this));
|
||||
}
|
||||
|
||||
void runnerAdjustDimensions() {
|
||||
runner.width = DEFAULT_WIDTH;
|
||||
runner.height = RUNNER_DEFAULT_HEIGHT;
|
||||
// distance meter ...
|
||||
}
|
||||
|
||||
void runnerOnKeyDown(int key) {
|
||||
if (!runner.crashed && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2)) {
|
||||
if (!runner.playing) {
|
||||
// this.loadSounds(); // TODO
|
||||
runner.playing = true;
|
||||
//printf("first jump! %u\n", getTimeStamp());
|
||||
runnerUpdate();
|
||||
runner.nextUpdateScheduled = false;
|
||||
runner.skipUpdateNow = true;
|
||||
}
|
||||
// Play sound effect and jump on starting the game for the first time.
|
||||
if (!trex.jumping && !trex.ducking) {
|
||||
// this.playSound(this.soundFx.BUTTON_PRESS); // TODO
|
||||
trexStartJump(runner.currentSpeed);
|
||||
}
|
||||
}
|
||||
if (runner.playing && !runner.crashed && key == RUNNER_KEYCODE_DUCK) {
|
||||
if (trex.jumping) {
|
||||
// Speed drop, activated only when jump key is not pressed.
|
||||
trexSetSpeedDrop();
|
||||
}
|
||||
//else if (!trex.jumping &&!trex.ducking) {
|
||||
else if (!trex.ducking) {
|
||||
// Duck
|
||||
trexSetDuck(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void runnerOnKeyUp(int key) {
|
||||
if (runner.isRunning && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2)) {
|
||||
trexEndJump();
|
||||
}
|
||||
else if (key == RUNNER_KEYCODE_DUCK) {
|
||||
trex.speedDrop = false;
|
||||
trexSetDuck(false);
|
||||
}
|
||||
else if (runner.crashed) {
|
||||
// Check that enough time has elapsed before allowing jump key to restart.
|
||||
|
||||
int now = getTimeStamp();
|
||||
int deltaTime = now - runner.time;
|
||||
// if (deltaTime < 0) {
|
||||
// deltaTime = DELTA_MS_DEFAULT;
|
||||
// runner.time = 0;
|
||||
// }
|
||||
|
||||
// dbg_printf(".now = %d .deltaTime = %d runner.time = %d\n", now, deltaTime, runner.time);
|
||||
if (key == RUNNER_KEYCODE_RESTART || (runner.timeAfterCrashedMs >= RUNNER_GAMEOVER_CLEAR_TIME && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2))) {
|
||||
//dbg_printf("timeAfterCrashedMs = %d\n", runner.timeAfterCrashedMs);
|
||||
runnerRestart();
|
||||
}
|
||||
}
|
||||
else if (runner.paused && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2)) {
|
||||
trexReset();
|
||||
runnerPlay();
|
||||
}
|
||||
}
|
||||
|
||||
void runnerClearCanvas() {
|
||||
graphicsFillBackground(0xF7, 0xF7, 0xF7);
|
||||
//graphicsRender();
|
||||
}
|
||||
|
||||
void runnerUpdate() {
|
||||
//dbg_printf("runnerUpdate() runner.playing = %d\n", runner.playing);
|
||||
//runner.updatePending = false;
|
||||
int now = getTimeStamp();
|
||||
//printf("now = %d\n", now);
|
||||
int deltaTime = now - (runner.time ? runner.time : 0);
|
||||
if (deltaTime < 0) {
|
||||
deltaTime = DELTA_MS_DEFAULT;
|
||||
}
|
||||
// dbg_printf("runnerUpdate() deltaTime = %d\n", deltaTime);
|
||||
runner.time = now;
|
||||
if (runner.playing) {
|
||||
//printf("runnerUpdate() %d\n", getTimeStamp());
|
||||
runnerClearCanvas();
|
||||
|
||||
if (trex.jumping) {
|
||||
trexUpdateJump(deltaTime);
|
||||
}
|
||||
|
||||
runner.runningTime += deltaTime;
|
||||
bool hasObstacles = runner.runningTime > RUNNER_CLEAR_TIME;
|
||||
|
||||
// First jump triggers the intro.
|
||||
if (trex.jumpCount == 1 && !runner.playingIntro) {
|
||||
//printf("trex.jumpCount = %d\n", trex.jumpCount);
|
||||
runnerPlayIntro();
|
||||
}
|
||||
|
||||
// The horizon doesn't move until the intro is over.
|
||||
if (runner.playingIntro) {
|
||||
horizonUpdate(0, runner.currentSpeed, hasObstacles, false);
|
||||
}
|
||||
else {
|
||||
deltaTime = !runner.activated ? 0 : deltaTime;
|
||||
horizonUpdate(deltaTime, runner.currentSpeed, hasObstacles, runner.inverted);
|
||||
}
|
||||
|
||||
// Check for collisions.
|
||||
bool collision = hasObstacles && runnerCheckForCollision(horizon.obstacles->head->data);
|
||||
|
||||
if (!collision) {
|
||||
runner.distanceRan += runner.currentSpeed * deltaTime / runner.msPerFrame;
|
||||
|
||||
if (runner.currentSpeed < RUNNER_MAX_SPEED) {
|
||||
runner.currentSpeed += RUNNER_ACCELERATION;
|
||||
}
|
||||
}
|
||||
else {
|
||||
runnerGameOver();
|
||||
}
|
||||
|
||||
bool playAchievementSound = distanceMeterUpdate(deltaTime, (int)ceil(runner.distanceRan));
|
||||
|
||||
if (playAchievementSound) {
|
||||
//this.playSound(this.soundFx.SCORE); // TODO
|
||||
}
|
||||
|
||||
/*// Night mode.
|
||||
if (this.invertTimer > this.config.INVERT_FADE_DURATION) {
|
||||
this.invertTimer = 0;
|
||||
this.invertTrigger = false;
|
||||
this.invert();
|
||||
}
|
||||
else if (this.invertTimer) {
|
||||
this.invertTimer += deltaTime;
|
||||
}
|
||||
else {
|
||||
var actualDistance =
|
||||
this.distanceMeter.getActualDistance(Math.ceil(this.distanceRan));
|
||||
|
||||
if (actualDistance > 0) {
|
||||
this.invertTrigger = !(actualDistance %
|
||||
this.config.INVERT_DISTANCE);
|
||||
|
||||
if (this.invertTrigger&& this.invertTimer == = 0) {
|
||||
this.invertTimer += deltaTime;
|
||||
this.invert();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
runner.nextUpdateScheduled = false;//
|
||||
if (runner.playing || (!runner.activated && trex.blinkCount < RUNNER_MAX_BLINK_COUNT)) {
|
||||
trexUpdate(deltaTime, -1);
|
||||
runner.nextUpdateScheduled = true;
|
||||
}
|
||||
|
||||
graphicsRender(); // blit all drawn to the screen
|
||||
//printf("runner update end\n\n");
|
||||
}
|
||||
|
||||
void runnerGameOver() {
|
||||
// this.playSound(this.soundFx.HIT); // TODO
|
||||
runnerStop();
|
||||
runner.crashed = true;
|
||||
distanceMeter.achievement = false;
|
||||
trexUpdate(100, TREX_STATUS_CRASHED);
|
||||
|
||||
// Game over panel
|
||||
gameOverPanelDraw();
|
||||
// Update the high score
|
||||
if (runner.distanceRan > runner.highestScore) {
|
||||
runner.highestScore = (int)ceil(runner.distanceRan);
|
||||
distanceMeterSetHighScore(runner.highestScore);
|
||||
}
|
||||
// Reset the time clock
|
||||
runner.time = getTimeStamp();
|
||||
}
|
||||
|
||||
void runnerStop() {
|
||||
runner.playing = false;
|
||||
runner.paused = true;
|
||||
runner.isRunning = false;
|
||||
}
|
||||
|
||||
void runnerPlay() {
|
||||
if (!runner.crashed) {
|
||||
runner.playing = true;
|
||||
runner.paused = false;
|
||||
trexUpdate(0, TREX_STATUS_RUNNING);
|
||||
runner.time = getTimeStamp();
|
||||
runnerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void runnerRestart() {
|
||||
if (!runner.isRunning) {
|
||||
runner.playCount++;
|
||||
runner.runningTime = 0;
|
||||
runner.playing = true;
|
||||
runner.crashed = false;
|
||||
runner.timeAfterCrashedMs = 0;
|
||||
runner.distanceRan = 0;
|
||||
runner.currentSpeed = RUNNER_SPEED;
|
||||
runner.time = getTimeStamp();
|
||||
runnerClearCanvas();
|
||||
distanceMeterReset(runner.highestScore);
|
||||
horizonReset();
|
||||
trexReset();
|
||||
//this.playSound(this.soundFx.BUTTON_PRESS);
|
||||
//this.invert(true);
|
||||
runner.isRunning = true;
|
||||
runnerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void runnerPlayIntro() {
|
||||
//printf("runnerPlayIntro()\n");
|
||||
if (!runner.activated && !runner.crashed) {
|
||||
runner.playingIntro = true;
|
||||
trex.playingIntro = true;
|
||||
runner.playing = true;
|
||||
runner.activated = true;
|
||||
}
|
||||
else if (runner.crashed) {
|
||||
runnerRestart();
|
||||
}
|
||||
}
|
||||
|
||||
void runnerStartGame() {
|
||||
runner.runningTime = 0;
|
||||
runner.playingIntro = false;
|
||||
trex.playingIntro = false;
|
||||
runner.playCount++;
|
||||
runner.isRunning = true;
|
||||
}
|
||||
|
||||
CollisionBox createAdjustedCollisionBox(CollisionBox box, CollisionBox adjustment) {
|
||||
return (CollisionBox){ .x = box.x + adjustment.x, .y = box.y + adjustment.y, .width = box.width, .height = box.height };
|
||||
}
|
||||
|
||||
// Returns whether boxes intersected
|
||||
bool boxCompare(CollisionBox tRexBox, CollisionBox obstacleBox) {
|
||||
// Axis-Aligned Bounding Box method.
|
||||
return (tRexBox.x < obstacleBox.x + obstacleBox.width &&
|
||||
tRexBox.x + tRexBox.width > obstacleBox.x &&
|
||||
tRexBox.y < obstacleBox.y + obstacleBox.height &&
|
||||
tRexBox.height + tRexBox.y > obstacleBox.y);
|
||||
}
|
||||
|
||||
bool runnerCheckForCollision(const Obstacle* obstacle) {
|
||||
// Adjustments are made to the bounding box as there is a 1 pixel white
|
||||
// border around the t-rex and obstacles.
|
||||
CollisionBox tRexBox = {
|
||||
.x = trex.xPos + 1,
|
||||
.y = trex.yPos + 1,
|
||||
.width = TREX_WIDTH - 2,
|
||||
.height = TREX_HEIGHT - 2 };
|
||||
|
||||
CollisionBox obstacleBox = {
|
||||
.x = obstacle->xPos + 1,
|
||||
.y = obstacle->yPos + 1,
|
||||
.width = obstacle->typeConfig.width * obstacle->size - 2,
|
||||
.height = obstacle->typeConfig.height - 2 };
|
||||
|
||||
// Simple outer bounds check.
|
||||
if (boxCompare(tRexBox, obstacleBox)) {
|
||||
CollisionBox* tRexCollisionBoxes = &trexDuckingCollisionBox;
|
||||
int tRexCollisionBoxesCount = 1;
|
||||
if (!trex.ducking) {
|
||||
tRexCollisionBoxes = trexRunningCollisionBox;
|
||||
tRexCollisionBoxesCount = 6;
|
||||
}
|
||||
|
||||
// Detailed axis aligned box check.
|
||||
for (int t = 0; t < tRexCollisionBoxesCount; t++) {
|
||||
for (int i = 0; i < obstacle->typeConfig.collisionBoxesCount; i++) {
|
||||
// Adjust the box to actual positions.
|
||||
CollisionBox adjTrexBox = createAdjustedCollisionBox(tRexCollisionBoxes[t], tRexBox);
|
||||
CollisionBox adjObstacleBox = createAdjustedCollisionBox(obstacle->typeConfig.collisionBoxes[i], obstacleBox);
|
||||
|
||||
if (boxCompare(adjTrexBox, adjObstacleBox)) {
|
||||
return true;// [adjTrexBox, adjObstacleBox] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
91
programs/games/dino/runner.h
Normal file
91
programs/games/dino/runner.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef RUNNER_H
|
||||
#define RUNNER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "config.h"
|
||||
#include "ulist.h"
|
||||
#include "graphics.h"
|
||||
#include "horizon.h"
|
||||
#include "distance_meter.h"
|
||||
#include "game_over_panel.h"
|
||||
#include "trex.h"
|
||||
|
||||
#define RUNNER_DEFAULT_HEIGHT 150
|
||||
|
||||
#define RUNNER_ACCELERATION 0.001
|
||||
#define RUNNER_BG_CLOUD_SPEED 0.2
|
||||
#define RUNNER_BOTTOM_PAD 10
|
||||
#define RUNNER_CLEAR_TIME 3000
|
||||
#define RUNNER_CLOUD_FREQUENCY 0.5
|
||||
#define RUNNER_GAMEOVER_CLEAR_TIME 750
|
||||
#define RUNNER_GAP_COEFFICIENT 0.6
|
||||
#define RUNNER_GRAVITY 0.6
|
||||
#define RUNNER_INITIAL_JUMP_VELOCITY 12
|
||||
#define RUNNER_INVERT_FADE_DURATION 12000
|
||||
#define RUNNER_INVERT_DISTANCE 700
|
||||
#define RUNNER_MAX_BLINK_COUNT 3
|
||||
#define RUNNER_MAX_CLOUDS 6
|
||||
#define RUNNER_MAX_OBSTACLE_LENGTH 3
|
||||
#define RUNNER_MAX_OBSTACLE_DUPLICATION 2
|
||||
#define RUNNER_MAX_SPEED 13.0
|
||||
#define RUNNER_MIN_JUMP_HEIGHT 35
|
||||
#define RUNNER_MOBILE_SPEED_COEFFICIENT 1.2
|
||||
#define RUNNER_SPEED 6.0
|
||||
#define RUNNER_SPEED_DROP_COEFFICIENT 3
|
||||
|
||||
#define RUNNER_KEYCODE_JUMP_1 82
|
||||
#define RUNNER_KEYCODE_JUMP_2 32
|
||||
#define RUNNER_KEYCODE_DUCK 81
|
||||
#define RUNNER_KEYCODE_RESTART 13
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
double distanceRan;
|
||||
int highestScore;
|
||||
int time;
|
||||
int runningTime;
|
||||
double msPerFrame;
|
||||
double azazzaza; //
|
||||
double currentSpeed;
|
||||
// Ulist* obstacles;
|
||||
bool activated;
|
||||
bool playing;
|
||||
bool crashed;
|
||||
int timeAfterCrashedMs;
|
||||
bool paused;
|
||||
bool inverted;
|
||||
bool invertTimer;
|
||||
bool playingIntro;
|
||||
bool isRunning;
|
||||
// resizeTimerId_
|
||||
int playCount;
|
||||
// soundFx
|
||||
// audioContext
|
||||
// images
|
||||
// imagesLoaded
|
||||
bool nextUpdateScheduled;
|
||||
bool skipUpdateNow;
|
||||
} Runner;
|
||||
|
||||
extern Runner runner;
|
||||
|
||||
void runnerInit();
|
||||
void runnerAdjustDimensions();
|
||||
//void runnerLoadImages();
|
||||
|
||||
void runnerClearCanvas();
|
||||
|
||||
void runnerPlayIntro();
|
||||
void runnerStartGame();
|
||||
void runnerUpdate();
|
||||
void runnerOnKeyDown(int key);
|
||||
void runnerOnKeyUp(int key);
|
||||
void runnerGameOver();
|
||||
void runnerStop();
|
||||
void runnerPlay();
|
||||
void runnerRestart();
|
||||
|
||||
bool runnerCheckForCollision(const Obstacle *obstacle);
|
||||
|
||||
#endif
|
169
programs/games/dino/sprites.h
Normal file
169
programs/games/dino/sprites.h
Normal file
@ -0,0 +1,169 @@
|
||||
// Original chrome dino sprite pack
|
||||
static const char sprites100[] = {
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
|
||||
0x00, 0x00, 0x04, 0xd1, 0x00, 0x00, 0x00, 0x44, 0x08, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x23, 0xfc,
|
||||
0x41, 0x00, 0x00, 0x00, 0x02, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x00, 0x76, 0x93, 0xcd, 0x38, 0x00,
|
||||
0x00, 0x0a, 0x0e, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xec, 0x9d, 0x5b, 0x76, 0xa4, 0xb8, 0x16,
|
||||
0x44, 0x83, 0xbb, 0xb8, 0x0f, 0x4d, 0x84, 0xa1, 0xd8, 0x03, 0x80, 0x4f, 0x0d, 0x4f, 0x9f, 0xa9,
|
||||
0x01, 0x54, 0x0d, 0x85, 0x89, 0xe8, 0x93, 0xae, 0x57, 0xac, 0xab, 0xaa, 0x68, 0xf2, 0x58, 0x2d,
|
||||
0xd2, 0x98, 0xf4, 0xd9, 0xbd, 0x3a, 0x13, 0x9f, 0x07, 0x95, 0x18, 0x57, 0x38, 0x24, 0x01, 0x05,
|
||||
0xc7, 0x71, 0x1c, 0xc7, 0x71, 0x1c, 0xe7, 0xc3, 0x31, 0xe0, 0x3b, 0x05, 0xf7, 0x08, 0x38, 0x8e,
|
||||
0x15, 0xc0, 0x84, 0x83, 0x29, 0x08, 0x6f, 0x2b, 0x43, 0xb8, 0x1f, 0xd8, 0x80, 0xa1, 0xb7, 0x85,
|
||||
0x65, 0x2c, 0x7c, 0x58, 0x82, 0xb4, 0x76, 0xac, 0xf8, 0xce, 0xd4, 0x11, 0x83, 0x55, 0xdd, 0x10,
|
||||
0x23, 0x5f, 0x5f, 0xf0, 0x93, 0x19, 0x40, 0xe6, 0x36, 0x32, 0x43, 0x3f, 0xa3, 0x33, 0xb8, 0xc9,
|
||||
0xca, 0x2a, 0xc4, 0x34, 0x63, 0xe0, 0x26, 0xcb, 0x19, 0xe2, 0xae, 0xea, 0xe6, 0xc7, 0x52, 0xa0,
|
||||
0x84, 0x0b, 0xd6, 0x5e, 0x80, 0x11, 0x00, 0x4a, 0xc4, 0x3d, 0x4a, 0x40, 0x07, 0xf2, 0xb3, 0xbc,
|
||||
0xae, 0x98, 0x70, 0x02, 0x25, 0xf2, 0x50, 0xf6, 0x02, 0xdb, 0x02, 0x6c, 0x43, 0x4f, 0x4b, 0x55,
|
||||
0xc6, 0xc2, 0xa3, 0x13, 0x4a, 0x7b, 0xc7, 0x84, 0xd3, 0x98, 0x80, 0x15, 0x77, 0x98, 0xa9, 0x64,
|
||||
0x94, 0xa0, 0xea, 0x3d, 0x4b, 0x21, 0x31, 0x42, 0x33, 0xb2, 0xec, 0xe5, 0x39, 0x71, 0x46, 0x5b,
|
||||
0xd0, 0x10, 0x4b, 0x40, 0xbf, 0x96, 0xff, 0xd0, 0x31, 0x6a, 0xda, 0x84, 0xe3, 0x28, 0x88, 0xa6,
|
||||
0x4b, 0xe3, 0x51, 0xf2, 0x50, 0x24, 0x40, 0x75, 0xc2, 0xb2, 0x0d, 0x1d, 0x2d, 0x55, 0x19, 0x0b,
|
||||
0x0f, 0x4f, 0xa8, 0x57, 0xb4, 0x3b, 0xc8, 0xba, 0x1f, 0x9b, 0xac, 0x3a, 0xac, 0xa6, 0xdd, 0xae,
|
||||
0x63, 0x54, 0x2f, 0xa3, 0x4e, 0xc9, 0xaa, 0x4c, 0xb4, 0x67, 0x14, 0xba, 0x2c, 0x59, 0xd9, 0x64,
|
||||
0x87, 0x6e, 0xc9, 0x7e, 0x33, 0xde, 0xc1, 0xa1, 0x45, 0xfc, 0x4e, 0xba, 0x72, 0xad, 0xf1, 0x9b,
|
||||
0x24, 0x9f, 0xac, 0x68, 0x14, 0x34, 0x5b, 0xd2, 0x3a, 0x8e, 0x7c, 0x45, 0xfd, 0x93, 0xbe, 0xe2,
|
||||
0x7a, 0xa8, 0xeb, 0xa1, 0x90, 0x9d, 0xea, 0x37, 0xdb, 0x99, 0x1e, 0x52, 0x3b, 0x61, 0xed, 0xb1,
|
||||
0x69, 0x5f, 0x7f, 0x0c, 0x3b, 0xa9, 0x5b, 0x33, 0xe6, 0x4c, 0x69, 0xe3, 0x98, 0x11, 0x32, 0x12,
|
||||
0xcd, 0x8c, 0xcd, 0xf5, 0x68, 0xb2, 0xee, 0xc8, 0x6e, 0xca, 0x3e, 0x1d, 0x23, 0xde, 0x89, 0x49,
|
||||
0x05, 0xee, 0x38, 0xc4, 0xa5, 0x59, 0xca, 0xa4, 0x81, 0x0d, 0x83, 0x4a, 0x55, 0x5d, 0x51, 0x22,
|
||||
0x1b, 0x59, 0xb5, 0x6c, 0xda, 0xf2, 0x78, 0xd4, 0x2b, 0xda, 0x74, 0x3b, 0x34, 0x8d, 0x31, 0x3a,
|
||||
0xdd, 0x8f, 0x4d, 0x58, 0xed, 0xba, 0xaf, 0x7c, 0x7d, 0x31, 0x4d, 0xc0, 0xcc, 0x31, 0xa4, 0xd6,
|
||||
0x64, 0x16, 0x66, 0xed, 0x81, 0x86, 0xde, 0x95, 0x68, 0xfc, 0xc4, 0x5e, 0xb9, 0x76, 0xd6, 0x08,
|
||||
0xf2, 0x65, 0x15, 0xcd, 0x3e, 0x72, 0x85, 0x23, 0xcf, 0x93, 0x26, 0x74, 0x4a, 0x2c, 0x41, 0x03,
|
||||
0xdb, 0x82, 0x4d, 0xa5, 0xaa, 0xaa, 0x28, 0x11, 0xb1, 0xfc, 0x2e, 0x68, 0x58, 0xb4, 0xa5, 0x05,
|
||||
0x1d, 0x3e, 0x3e, 0x9e, 0x09, 0xe7, 0x23, 0x36, 0xed, 0x85, 0x72, 0x76, 0x9f, 0x2c, 0x5f, 0x8a,
|
||||
0x7e, 0x49, 0x41, 0x9e, 0xeb, 0xad, 0x53, 0xb9, 0x61, 0x39, 0x63, 0xbf, 0x1d, 0xb5, 0xc0, 0xd2,
|
||||
0x5f, 0x7b, 0xbe, 0xa2, 0xa5, 0x88, 0x36, 0x32, 0xe6, 0x46, 0x6f, 0xb0, 0x4e, 0xc0, 0x54, 0x25,
|
||||
0x6a, 0x4a, 0xd3, 0xaa, 0x4a, 0x69, 0x76, 0x69, 0x25, 0xd6, 0xe6, 0x86, 0x81, 0xff, 0x2d, 0xc0,
|
||||
0x72, 0xab, 0xa4, 0x6a, 0xf8, 0xb3, 0x02, 0xfb, 0xb0, 0xe5, 0xf8, 0xe1, 0x63, 0xbf, 0x38, 0xf6,
|
||||
0x39, 0xb4, 0x49, 0x63, 0xfb, 0x4e, 0x6b, 0x5a, 0xff, 0xb9, 0x4b, 0xc3, 0xcb, 0xd7, 0x7d, 0x41,
|
||||
0xa3, 0xf3, 0xe2, 0xeb, 0x4c, 0x3f, 0xa6, 0x43, 0xca, 0xcc, 0x6c, 0x3d, 0xe4, 0x9c, 0x7f, 0x7c,
|
||||
0xa5, 0xcb, 0xa6, 0xce, 0x7d, 0x16, 0xdc, 0x7a, 0x6b, 0x4f, 0x60, 0x44, 0xaf, 0xa4, 0x09, 0xf6,
|
||||
0xd0, 0x64, 0x92, 0xd1, 0xe7, 0xd5, 0x28, 0xe1, 0x9c, 0xe1, 0xa3, 0x50, 0x82, 0x88, 0xe3, 0xd5,
|
||||
0x99, 0xf3, 0xbd, 0x31, 0x27, 0x93, 0x1a, 0xb3, 0x39, 0x57, 0xc6, 0x96, 0x53, 0xf7, 0xcb, 0xda,
|
||||
0xa7, 0x67, 0x44, 0xb7, 0xa4, 0xcd, 0xa6, 0x2b, 0x98, 0xcc, 0xc1, 0x07, 0x29, 0x88, 0xc6, 0xf5,
|
||||
0x65, 0x5a, 0x9d, 0x90, 0x10, 0x0d, 0x97, 0x56, 0x82, 0x15, 0xb0, 0x5b, 0x74, 0xe4, 0x7a, 0x3e,
|
||||
0xfc, 0x20, 0xb6, 0x38, 0xae, 0xf6, 0xf9, 0x31, 0xeb, 0x48, 0xeb, 0x5c, 0xda, 0x6a, 0xd7, 0x91,
|
||||
0x3c, 0xcb, 0x08, 0x73, 0xff, 0x6b, 0x5b, 0xcc, 0x64, 0x10, 0xc1, 0x0e, 0x1b, 0xe7, 0xd6, 0x5f,
|
||||
0x7b, 0xb6, 0xa2, 0xa5, 0x5a, 0xd2, 0x12, 0x10, 0x8f, 0xf2, 0x66, 0x46, 0xd5, 0x49, 0x73, 0x67,
|
||||
0x6d, 0x2d, 0x3a, 0x0c, 0x3d, 0x1f, 0x0e, 0xa1, 0xaf, 0x30, 0x8b, 0x66, 0x2c, 0x8e, 0x6e, 0xa0,
|
||||
0xa4, 0x55, 0xab, 0x99, 0x14, 0x2d, 0x0e, 0x3c, 0xbf, 0x27, 0xa9, 0x4a, 0xe4, 0xff, 0x31, 0xcd,
|
||||
0xd6, 0x0a, 0x29, 0x39, 0xf9, 0x33, 0x9e, 0x01, 0xf7, 0x7e, 0xff, 0x12, 0x41, 0xab, 0xb6, 0xd2,
|
||||
0x3b, 0x4c, 0x43, 0x4f, 0x55, 0x51, 0x29, 0xb1, 0x41, 0x44, 0xb5, 0x3a, 0xc6, 0x52, 0x0c, 0x05,
|
||||
0x92, 0xc0, 0xa3, 0x45, 0xab, 0x94, 0xb2, 0x97, 0x30, 0x3a, 0x3e, 0x11, 0x5f, 0xf8, 0xea, 0x38,
|
||||
0xc7, 0x79, 0xb4, 0xa4, 0x4b, 0x98, 0x29, 0x76, 0xf8, 0xb3, 0x95, 0x8b, 0x00, 0x06, 0x93, 0xd6,
|
||||
0x5c, 0x1f, 0x73, 0x72, 0xab, 0xe8, 0x20, 0xd9, 0xe8, 0x90, 0xfa, 0x86, 0xb5, 0x02, 0x59, 0x58,
|
||||
0x66, 0x8c, 0x71, 0x6b, 0xcc, 0xd9, 0x35, 0xee, 0x9c, 0x56, 0x8d, 0xd1, 0xa5, 0xfd, 0x88, 0xbd,
|
||||
0x02, 0xe0, 0x6b, 0x06, 0xa0, 0x1b, 0xba, 0xc9, 0xaf, 0x18, 0xd3, 0x42, 0xc9, 0x6a, 0x5b, 0x86,
|
||||
0xf3, 0xd4, 0xf3, 0x68, 0xf5, 0x68, 0x33, 0x22, 0xf5, 0x0d, 0x38, 0xa7, 0xc6, 0x8b, 0x69, 0x0b,
|
||||
0x62, 0xc3, 0xba, 0x65, 0x5d, 0x9d, 0x00, 0xed, 0x3c, 0x03, 0x4a, 0x88, 0xce, 0xfc, 0x6b, 0x02,
|
||||
0x88, 0x09, 0xc4, 0xea, 0xa0, 0x06, 0x86, 0x0e, 0x39, 0xfd, 0xe0, 0x2e, 0xed, 0xcb, 0x2b, 0xba,
|
||||
0x71, 0x9c, 0x11, 0x4a, 0x44, 0x37, 0x93, 0x6c, 0x5d, 0x80, 0xe5, 0x51, 0x8e, 0x8c, 0x89, 0xee,
|
||||
0xbb, 0x50, 0x63, 0xd3, 0x3e, 0x28, 0x8e, 0xd7, 0x19, 0x74, 0xbe, 0x02, 0xd8, 0xbd, 0x7b, 0x7c,
|
||||
0xde, 0x09, 0x66, 0xbe, 0x4b, 0xb1, 0xee, 0x47, 0xba, 0x59, 0xd1, 0xb3, 0xcf, 0xb9, 0x8a, 0x9a,
|
||||
0x24, 0x90, 0x33, 0x6b, 0x9f, 0x98, 0xf1, 0x28, 0x41, 0x4b, 0xfd, 0x77, 0x67, 0xee, 0xde, 0x31,
|
||||
0x1a, 0xcc, 0x6a, 0x9c, 0xef, 0xd2, 0x54, 0x42, 0x34, 0x71, 0x82, 0x1a, 0x19, 0x4f, 0xd1, 0x68,
|
||||
0x88, 0x99, 0xe3, 0xce, 0xf6, 0xd8, 0xb4, 0x32, 0x46, 0x39, 0x73, 0x9c, 0xa3, 0x15, 0x2d, 0xe2,
|
||||
0x13, 0x32, 0x6c, 0x0b, 0x9c, 0x13, 0x79, 0xe5, 0xa0, 0x93, 0xce, 0x48, 0x98, 0x79, 0xbf, 0xa7,
|
||||
0x26, 0xf2, 0x0c, 0x05, 0x5a, 0xb9, 0xe7, 0xef, 0x66, 0xa3, 0xd6, 0xdc, 0x67, 0xbd, 0x1f, 0xb9,
|
||||
0x46, 0xbc, 0xe8, 0x5f, 0x2f, 0x24, 0x04, 0xe0, 0x12, 0xb5, 0x60, 0x6d, 0xc3, 0xf7, 0xe8, 0x1a,
|
||||
0xf7, 0x75, 0x36, 0x7c, 0x97, 0xfa, 0x1d, 0x9a, 0xf8, 0xb5, 0xd0, 0x50, 0x7d, 0x97, 0x28, 0x01,
|
||||
0x53, 0xd2, 0xe2, 0xe9, 0x8b, 0xd6, 0xf2, 0xcd, 0x78, 0x36, 0xbe, 0xbc, 0xf2, 0xf5, 0x9e, 0x9e,
|
||||
0x01, 0x99, 0xaa, 0x21, 0x49, 0xc7, 0xa1, 0xa2, 0x7d, 0x3e, 0x52, 0x28, 0x7f, 0x06, 0x80, 0x61,
|
||||
0x03, 0x16, 0xbb, 0xa5, 0xe2, 0xb6, 0xe0, 0x04, 0xea, 0xf5, 0x81, 0x82, 0x27, 0xe1, 0x95, 0xaf,
|
||||
0xd7, 0xa7, 0x70, 0xa5, 0xaa, 0x3a, 0x45, 0x11, 0x24, 0x5d, 0xb7, 0x96, 0x7e, 0x58, 0x22, 0x24,
|
||||
0x43, 0xaf, 0x2f, 0x1c, 0xd0, 0x40, 0x5f, 0x2b, 0x19, 0x1f, 0x70, 0xa6, 0xba, 0xe7, 0xe1, 0x22,
|
||||
0x74, 0x6e, 0xac, 0x26, 0xa0, 0xbc, 0xb9, 0x3a, 0x40, 0xd5, 0xe9, 0x6f, 0x03, 0x03, 0x36, 0xfa,
|
||||
0x2e, 0xbb, 0xe5, 0x67, 0xfd, 0xf2, 0xde, 0x56, 0x8d, 0xeb, 0x03, 0x4f, 0x38, 0x3f, 0x30, 0x18,
|
||||
0x8b, 0x00, 0xed, 0xcc, 0x1d, 0x63, 0x20, 0x1d, 0xc9, 0x9a, 0xfb, 0x9c, 0xd1, 0x8a, 0xb3, 0x41,
|
||||
0x19, 0x3a, 0x5b, 0x47, 0x7c, 0x2e, 0x12, 0x10, 0xf6, 0x03, 0xe4, 0x36, 0x14, 0xa9, 0x10, 0x68,
|
||||
0xeb, 0xd8, 0x72, 0x96, 0xe1, 0x7c, 0x8e, 0xbb, 0x39, 0xed, 0x87, 0x1f, 0xcc, 0xfb, 0xc5, 0x7f,
|
||||
0x5b, 0x9f, 0xbb, 0xfe, 0xf4, 0x59, 0xf7, 0x20, 0x11, 0x43, 0x82, 0xf9, 0x6b, 0x5f, 0x08, 0x20,
|
||||
0x17, 0xad, 0x25, 0xb3, 0x75, 0xf3, 0xfa, 0x06, 0x60, 0xd8, 0xd1, 0x1f, 0x0c, 0x87, 0xb7, 0xaa,
|
||||
0xa2, 0x25, 0x28, 0xfd, 0x47, 0x6e, 0x73, 0x67, 0x9e, 0x4c, 0xed, 0x48, 0xaa, 0xea, 0xed, 0xea,
|
||||
0x82, 0x50, 0xc5, 0xd8, 0xa9, 0x81, 0x0a, 0xaa, 0x93, 0x56, 0xa8, 0x4d, 0x3b, 0x46, 0xd0, 0x4a,
|
||||
0x9f, 0xa0, 0xc5, 0x12, 0x64, 0x57, 0xd7, 0xe2, 0xeb, 0xcb, 0x8f, 0xff, 0x3f, 0x13, 0xce, 0x06,
|
||||
0x1d, 0xde, 0xdc, 0xb0, 0xf5, 0xb4, 0x0e, 0xa8, 0x15, 0x2d, 0xa6, 0x67, 0x5d, 0xf7, 0x0c, 0x25,
|
||||
0x1a, 0x81, 0x8a, 0x1b, 0x30, 0xec, 0xb4, 0xc4, 0x7b, 0x2d, 0x1d, 0x44, 0xb4, 0x43, 0x69, 0xe7,
|
||||
0xcd, 0x9d, 0xd7, 0x3e, 0x63, 0x2f, 0x7c, 0x86, 0xad, 0xce, 0xfd, 0xcb, 0xcd, 0xe9, 0x4a, 0xc6,
|
||||
0xc1, 0x64, 0x7a, 0xae, 0x36, 0x5b, 0x97, 0x65, 0xde, 0x43, 0x7e, 0xd7, 0x8a, 0x6d, 0xb8, 0x5a,
|
||||
0x2d, 0xcf, 0x8e, 0x9e, 0x0a, 0x75, 0xb5, 0x4b, 0x25, 0x51, 0x4b, 0xc3, 0xbd, 0xed, 0x5d, 0xad,
|
||||
0x23, 0xee, 0x48, 0x5a, 0x04, 0xda, 0x8f, 0xfc, 0x00, 0x82, 0xfa, 0xae, 0xca, 0x42, 0x86, 0xb6,
|
||||
0xea, 0x66, 0x49, 0x1b, 0xd0, 0xde, 0x72, 0x84, 0xd6, 0xb6, 0x13, 0x70, 0x7d, 0xe4, 0x19, 0xb6,
|
||||
0xbc, 0xdf, 0xbc, 0x9b, 0xf9, 0x9e, 0xde, 0x51, 0x3d, 0x59, 0xa1, 0xa9, 0xdc, 0xb6, 0xcf, 0x3c,
|
||||
0x37, 0x3f, 0xbb, 0xd5, 0x59, 0xa0, 0x91, 0x5b, 0x67, 0xeb, 0xa8, 0x0a, 0xf6, 0x8c, 0x84, 0x02,
|
||||
0x44, 0x0d, 0x34, 0xb6, 0xc4, 0xe3, 0xbf, 0x4d, 0xdc, 0xe9, 0xf9, 0x7b, 0x3a, 0x0b, 0x79, 0x86,
|
||||
0xed, 0xf5, 0xe1, 0x9d, 0x79, 0x51, 0xe2, 0x09, 0xf1, 0xe2, 0xb5, 0xd4, 0xed, 0xd9, 0x9a, 0xfc,
|
||||
0x54, 0xe5, 0xd1, 0x84, 0xb6, 0xf5, 0xb7, 0x8e, 0x8f, 0x3b, 0x53, 0xc7, 0xa3, 0x4e, 0x50, 0x5d,
|
||||
0x9a, 0x56, 0xb3, 0x44, 0x7b, 0xf6, 0xd9, 0x6b, 0x89, 0xba, 0xfa, 0x79, 0xae, 0x10, 0x95, 0x00,
|
||||
0x6e, 0x71, 0x4f, 0xd7, 0x9c, 0x47, 0xfb, 0xfe, 0xdf, 0x1d, 0x4f, 0xc5, 0x60, 0x6e, 0x8b, 0x1b,
|
||||
0xe4, 0xa6, 0x54, 0xbe, 0x5b, 0x9a, 0x71, 0x59, 0xfc, 0x7a, 0x34, 0x27, 0x85, 0x8f, 0xe0, 0xd2,
|
||||
0xb8, 0x28, 0xc0, 0xad, 0x4b, 0xbb, 0xb4, 0xa7, 0xf0, 0x68, 0xf6, 0x78, 0x27, 0x5d, 0xb7, 0xd6,
|
||||
0x5e, 0x75, 0x6e, 0xfc, 0x37, 0x0d, 0x74, 0x67, 0xfd, 0xad, 0x18, 0x1f, 0x79, 0xa6, 0xfa, 0xb1,
|
||||
0x67, 0xd1, 0xd4, 0xa5, 0xd9, 0xd5, 0x9d, 0x24, 0x63, 0xbf, 0xa5, 0xde, 0xb2, 0x13, 0xa1, 0x00,
|
||||
0x88, 0x9a, 0x20, 0xf6, 0x53, 0xdc, 0xb8, 0x15, 0xea, 0x45, 0x68, 0x79, 0xb8, 0xe2, 0x3a, 0x49,
|
||||
0x8c, 0x34, 0xc6, 0x94, 0xe9, 0x9f, 0xc5, 0x56, 0xc6, 0x1c, 0xc7, 0x3d, 0xda, 0x79, 0x04, 0x5b,
|
||||
0xf3, 0xeb, 0xad, 0x14, 0x8a, 0x26, 0x2a, 0xa3, 0x17, 0x80, 0xa2, 0x1d, 0xaa, 0x81, 0x36, 0xa1,
|
||||
0x2e, 0x2c, 0xfc, 0x43, 0x2e, 0xc1, 0x8b, 0xff, 0xec, 0x5c, 0xbc, 0x56, 0xaf, 0x6c, 0xba, 0x61,
|
||||
0xe9, 0x6f, 0x3d, 0x4d, 0xd1, 0xc2, 0xc3, 0x9c, 0x19, 0x09, 0x6d, 0xb3, 0x5e, 0x08, 0x1f, 0x7b,
|
||||
0x84, 0xaa, 0x71, 0xcd, 0xa8, 0x06, 0x16, 0x18, 0x48, 0x07, 0x3e, 0x11, 0x8e, 0x33, 0x1a, 0x13,
|
||||
0x39, 0xfe, 0xd7, 0xa2, 0x77, 0x4a, 0x2c, 0x05, 0x26, 0x9a, 0x04, 0x2d, 0xc5, 0xfe, 0xf3, 0xc0,
|
||||
0x8e, 0xfa, 0x71, 0xb1, 0xd0, 0xf1, 0xe4, 0x3a, 0x75, 0x8e, 0x3b, 0x27, 0x23, 0xb6, 0x3e, 0xf7,
|
||||
0x98, 0x53, 0xe7, 0x3f, 0x9e, 0xae, 0x96, 0x64, 0xcc, 0x1f, 0xdd, 0xa5, 0x8d, 0xb0, 0x25, 0x2d,
|
||||
0x05, 0x3d, 0xf2, 0xc7, 0xd3, 0xfc, 0x2c, 0x8f, 0xf0, 0x21, 0x25, 0x2d, 0x05, 0x26, 0xe4, 0xda,
|
||||
0x58, 0xe3, 0xdb, 0x1d, 0x61, 0x5b, 0x37, 0xff, 0x55, 0x74, 0x25, 0x12, 0xc2, 0xd3, 0xd6, 0xe6,
|
||||
0x0f, 0x35, 0x8f, 0x66, 0x8c, 0x65, 0x42, 0xc3, 0x91, 0xbb, 0x4b, 0x13, 0xe1, 0x92, 0x04, 0xa3,
|
||||
0x82, 0x74, 0x68, 0x82, 0x51, 0x1b, 0x55, 0x4d, 0x71, 0x69, 0xa7, 0xb2, 0x82, 0xb8, 0x4b, 0x73,
|
||||
0x97, 0x76, 0xeb, 0x69, 0x55, 0x45, 0x43, 0xe8, 0x3f, 0xf2, 0x7e, 0x9e, 0x42, 0x29, 0x7f, 0x5f,
|
||||
0x6e, 0x0c, 0x9a, 0x30, 0x08, 0x7b, 0xea, 0x18, 0x24, 0xda, 0xb0, 0x2b, 0x63, 0x3c, 0xb9, 0x4e,
|
||||
0x66, 0x5d, 0xcf, 0x3a, 0xe7, 0x6a, 0xd7, 0x39, 0x8e, 0xaf, 0x75, 0x9e, 0x8d, 0xbd, 0xdc, 0xa8,
|
||||
0x89, 0x76, 0x75, 0x8c, 0x1a, 0x8d, 0x70, 0x2e, 0xe8, 0xd2, 0xd2, 0x95, 0x6b, 0x0d, 0x97, 0x96,
|
||||
0x5b, 0x5d, 0x1a, 0xcd, 0x15, 0x53, 0x0b, 0x18, 0x19, 0x3a, 0x5b, 0xc7, 0x03, 0xce, 0xd4, 0x95,
|
||||
0xdc, 0x53, 0xb8, 0x13, 0x18, 0xb6, 0x1f, 0xaf, 0x1d, 0x2d, 0xc7, 0xab, 0x63, 0xb1, 0x6f, 0xcf,
|
||||
0xb2, 0x31, 0xdd, 0xd7, 0x8a, 0x76, 0x97, 0xe6, 0x0e, 0xcd, 0x71, 0x8f, 0x76, 0x2a, 0xc1, 0x0c,
|
||||
0x0c, 0x1d, 0x2d, 0xef, 0x6c, 0x01, 0xfe, 0x78, 0x20, 0x48, 0x7c, 0xeb, 0x32, 0xc0, 0xda, 0xa4,
|
||||
0x23, 0xeb, 0x84, 0x86, 0x62, 0x9f, 0x44, 0x33, 0xae, 0xf8, 0x0e, 0x4f, 0x51, 0xab, 0x2e, 0x2d,
|
||||
0x63, 0x9f, 0x01, 0xd8, 0xc4, 0x6a, 0x55, 0x16, 0x4e, 0x22, 0xbd, 0xad, 0xe3, 0x81, 0x67, 0xca,
|
||||
0x67, 0xd1, 0xce, 0x5c, 0x89, 0x48, 0xe1, 0xc1, 0x2e, 0x0d, 0xab, 0x3b, 0x34, 0xa7, 0x9f, 0x9b,
|
||||
0xf1, 0x8c, 0x8d, 0xce, 0xd6, 0x11, 0xd7, 0xc7, 0x25, 0x4d, 0x6f, 0xcc, 0xea, 0xb7, 0x69, 0x8d,
|
||||
0x8b, 0xa3, 0xab, 0x1b, 0x34, 0x7d, 0x7a, 0x03, 0xdf, 0x1f, 0x54, 0x0b, 0x44, 0x44, 0x20, 0x15,
|
||||
0x20, 0xec, 0xd7, 0xb2, 0xb2, 0xff, 0x33, 0xa8, 0x4b, 0xe3, 0xbb, 0xc1, 0x52, 0x4d, 0x7c, 0xdd,
|
||||
0x5a, 0xc6, 0x38, 0x75, 0xd3, 0xc2, 0xfd, 0xdc, 0x6f, 0x1d, 0x1f, 0x7b, 0xa6, 0x7a, 0x5c, 0x7b,
|
||||
0x80, 0x63, 0x13, 0x0a, 0xe2, 0xdb, 0x6d, 0xf2, 0x44, 0x41, 0x91, 0x18, 0x85, 0xae, 0x8a, 0x19,
|
||||
0x36, 0xcd, 0xf6, 0x5d, 0xab, 0xfb, 0x33, 0x67, 0xdb, 0x19, 0x30, 0x2e, 0x7c, 0xe8, 0xac, 0xd5,
|
||||
0xaa, 0xb0, 0xb5, 0x4f, 0xd1, 0xe6, 0x86, 0x5c, 0xc6, 0x7b, 0xe2, 0x92, 0xd6, 0x0c, 0xd5, 0xcb,
|
||||
0x2f, 0x43, 0x7b, 0xf8, 0x64, 0x67, 0x02, 0x67, 0x6a, 0xc2, 0x03, 0x6a, 0x13, 0x83, 0xbb, 0xb5,
|
||||
0x09, 0x11, 0x11, 0x09, 0xa9, 0xfb, 0x33, 0x28, 0xb9, 0xd5, 0xa5, 0x01, 0x37, 0x0c, 0x68, 0x84,
|
||||
0x4d, 0xdb, 0xc1, 0x2b, 0x03, 0x99, 0xef, 0xf6, 0x91, 0x7f, 0xe8, 0xfb, 0x44, 0x9d, 0xa9, 0x3f,
|
||||
0xd6, 0xbf, 0x07, 0xe7, 0x79, 0x51, 0x47, 0xa6, 0xdc, 0x7e, 0xe6, 0x1e, 0xd0, 0x3a, 0xc2, 0x71,
|
||||
0x9c, 0x4b, 0xde, 0xf7, 0x64, 0xd7, 0xd3, 0xc7, 0x05, 0x94, 0x33, 0xef, 0x7b, 0xba, 0x01, 0x3d,
|
||||
0x0e, 0x0d, 0x95, 0x86, 0x6d, 0x30, 0x18, 0xdf, 0x75, 0x1d, 0xd2, 0x71, 0x1c, 0x67, 0x78, 0x60,
|
||||
0xeb, 0x88, 0x26, 0x66, 0x38, 0x8e, 0xf3, 0x56, 0x22, 0x0a, 0x42, 0xb5, 0x75, 0x7c, 0xad, 0x05,
|
||||
0xab, 0x8e, 0xff, 0x0c, 0x33, 0xb2, 0x6c, 0x41, 0xa9, 0xcd, 0xd5, 0x22, 0x13, 0xfa, 0x0d, 0x53,
|
||||
0x70, 0xe4, 0x58, 0x45, 0xcb, 0x00, 0xd2, 0xdb, 0x8f, 0xdc, 0x29, 0xe1, 0xd1, 0x09, 0xd2, 0xdf,
|
||||
0xa1, 0x38, 0x8e, 0xdf, 0x33, 0x30, 0xe7, 0xcf, 0xae, 0x61, 0x45, 0xff, 0x1d, 0x80, 0xf6, 0x04,
|
||||
0xb1, 0x13, 0x8a, 0x76, 0x38, 0x67, 0x90, 0x64, 0xeb, 0xe8, 0xda, 0x16, 0x8e, 0xfd, 0x0c, 0x59,
|
||||
0xb7, 0x2c, 0x6e, 0x10, 0xfa, 0x9a, 0xfa, 0xaf, 0xde, 0xc8, 0xe6, 0x91, 0xfb, 0xa5, 0x1b, 0x25,
|
||||
0x96, 0x08, 0x90, 0x50, 0x42, 0x7b, 0x42, 0xc4, 0x91, 0x09, 0xd3, 0x76, 0x69, 0x87, 0xe3, 0xb8,
|
||||
0x47, 0x33, 0x34, 0x39, 0xe8, 0x96, 0x53, 0xcb, 0x48, 0xa9, 0xbf, 0xec, 0x48, 0x50, 0xea, 0x98,
|
||||
0x10, 0xdb, 0x25, 0x0a, 0xa7, 0x1d, 0xce, 0x69, 0x04, 0xd9, 0x3a, 0xb6, 0xb6, 0x81, 0xfe, 0xcf,
|
||||
0xd0, 0xcf, 0xd0, 0xdf, 0xe4, 0x9c, 0x4c, 0x99, 0x4b, 0x5f, 0xa2, 0xa0, 0x10, 0x26, 0xf8, 0xf6,
|
||||
0x1d, 0x36, 0x94, 0x52, 0xee, 0x74, 0xfc, 0xd5, 0xce, 0x7d, 0x25, 0x35, 0x0c, 0x04, 0x51, 0x14,
|
||||
0x1d, 0xad, 0xf1, 0xae, 0x73, 0xd6, 0xa7, 0x5f, 0x7e, 0x00, 0x23, 0x39, 0x36, 0xd5, 0xcf, 0xf1,
|
||||
0x1e, 0x32, 0xd8, 0x0a, 0x8f, 0xc9, 0x53, 0x65, 0xb5, 0x90, 0xb4, 0xe6, 0xff, 0xb0, 0x5e, 0x3f,
|
||||
0xb9, 0x24, 0x49, 0x92, 0x24, 0x65, 0xb8, 0xf4, 0x26, 0x11, 0xd9, 0x80, 0x37, 0x40, 0x83, 0x95,
|
||||
0x1e, 0x00, 0x0e, 0x9f, 0xf5, 0xff, 0x00, 0xaf, 0xff, 0xde, 0x31, 0x9a, 0x94, 0xc6, 0xcf, 0x20,
|
||||
0x82, 0xce, 0xc1, 0x84, 0x01, 0x1a, 0xac, 0xf4, 0x00, 0xb0, 0xf9, 0xbe, 0x87, 0x01, 0x6e, 0xb3,
|
||||
0x84, 0xa7, 0x1b, 0xa3, 0x31, 0xde, 0x92, 0x34, 0xc7, 0x01, 0x17, 0xfe, 0xcc, 0xa8, 0x30, 0xc0,
|
||||
0xed, 0x78, 0xed, 0x31, 0xd7, 0xb4, 0x25, 0x09, 0xde, 0x66, 0xfc, 0x26, 0xd7, 0xd1, 0x24, 0xec,
|
||||
0xf6, 0x6d, 0xd1, 0x0e, 0x08, 0x17, 0x04, 0xba, 0x4a, 0x5a, 0xfe, 0x52, 0xf3, 0x77, 0x92, 0x17,
|
||||
0xbf, 0x3b, 0xcb, 0x55, 0x9d, 0xe5, 0xaa, 0x6e, 0x09, 0xc5, 0xc3, 0x1c, 0x5b, 0xb4, 0x1c, 0xbd,
|
||||
0x70, 0x3c, 0x66, 0xe1, 0xcf, 0xa9, 0x4b, 0xd9, 0x62, 0xf6, 0x55, 0x8a, 0xed, 0x13, 0xa3, 0x4f,
|
||||
0x65, 0x6e, 0xee, 0xb1, 0x70, 0x04, 0xcb, 0x55, 0x99, 0xe5, 0xea, 0x46, 0x22, 0x70, 0x8c, 0x30,
|
||||
0xb8, 0x53, 0x06, 0xc0, 0x90, 0xe5, 0xea, 0xd3, 0xca, 0x15, 0xd5, 0x94, 0x00, 0x12, 0x41, 0x13,
|
||||
0x88, 0x8c, 0xed, 0x05, 0xbc, 0x70, 0x45, 0x87, 0xe7, 0xaf, 0xce, 0x96, 0xab, 0x10, 0xcb, 0xd5,
|
||||
0xb2, 0x9f, 0x17, 0x30, 0x66, 0x79, 0x1e, 0xe1, 0xcb, 0xdd, 0xc6, 0x46, 0xce, 0x9b, 0xbc, 0xf3,
|
||||
0x89, 0x31, 0x66, 0xd3, 0x7f, 0xd4, 0x72, 0xd5, 0xca, 0x72, 0xf5, 0xba, 0x24, 0x49, 0x92, 0xf4,
|
||||
0x05, 0x52, 0x0d, 0x4e, 0x68, 0xa4, 0x9a, 0xa9, 0x29, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e,
|
||||
0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
219
programs/games/dino/trex.c
Normal file
219
programs/games/dino/trex.c
Normal file
@ -0,0 +1,219 @@
|
||||
#include "trex.h"
|
||||
|
||||
Trex trex;
|
||||
|
||||
CollisionBox trexDuckingCollisionBox = {.x = 1, .y = 18, .width = 55, .height = 25};
|
||||
CollisionBox trexRunningCollisionBox[6] =
|
||||
{
|
||||
{.x = 22, .y = 0, .width = 17, .height = 16},
|
||||
{.x = 1, .y = 18, .width = 30, .height = 9},
|
||||
{.x = 10, .y = 35, .width = 14, .height = 8},
|
||||
{.x = 1, .y = 24, .width = 29, .height = 5},
|
||||
{.x = 5, .y = 30, .width = 21, .height = 4},
|
||||
{.x = 9, .y = 34, .width = 15, .height = 4}
|
||||
};
|
||||
|
||||
TrexAnimFramesEntry trexAnimFrames[5] = {
|
||||
{.frameCount = 2, .frames = {44, 0}, .msPerFrame = 1000./3},
|
||||
{.frameCount = 2, .frames = {88, 132}, .msPerFrame = 1000./12},
|
||||
{.frameCount = 1, .frames = {220}, .msPerFrame = 1000./60},
|
||||
{.frameCount = 1, .frames = {0}, .msPerFrame = 1000./60},
|
||||
{.frameCount = 2, .frames = {264, 323}, .msPerFrame = 1000./8}
|
||||
};
|
||||
|
||||
// T - rex player initaliser
|
||||
// Sets the t - rex to blink at random intervals
|
||||
void trexInit() {
|
||||
trex.xPos = 0;
|
||||
trex.currentFrame = 0;
|
||||
//this.currentAnimFrames = [];
|
||||
trex.blinkDelay = 0;
|
||||
trex.blinkCount = 0;
|
||||
trex.animStartTime = 0;
|
||||
trex.timer = 0;
|
||||
trex.msPerFrame = 1000. / FPS;
|
||||
trex.status = TREX_STATUS_WAITING;
|
||||
|
||||
trex.jumping = false;
|
||||
trex.ducking = false;
|
||||
trex.jumpVelocity = 0;
|
||||
trex.reachedMinHeight = false;
|
||||
trex.speedDrop = false;
|
||||
trex.jumpCount = 0;
|
||||
trex.jumpspotX = 0;
|
||||
|
||||
trex.groundYPos = RUNNER_DEFAULT_HEIGHT - TREX_HEIGHT - RUNNER_BOTTOM_PAD;
|
||||
trex.yPos = trex.groundYPos;
|
||||
trex.minJumpHeight = trex.groundYPos - TREX_MIN_JUMP_HEIGHT;
|
||||
trex.playingIntro = false;
|
||||
|
||||
trexDraw(0, 0);
|
||||
trexUpdate(0, TREX_STATUS_WAITING);
|
||||
}
|
||||
|
||||
// Set the animation status
|
||||
void trexUpdate(int deltaTime, int opt_status) {
|
||||
//printf("trex.status = %d\n", trex.status);
|
||||
trex.timer += deltaTime;
|
||||
// Update the status
|
||||
if (opt_status != -1) {
|
||||
trex.status = opt_status;
|
||||
trex.currentFrame = 0;
|
||||
trex.msPerFrame = trexAnimFrames[opt_status].msPerFrame;
|
||||
trex.currentAnimFrames = trexAnimFrames[opt_status];
|
||||
if (opt_status == TREX_STATUS_WAITING) {
|
||||
trex.animStartTime = getTimeStamp();
|
||||
trexSetBlinkDelay();
|
||||
}
|
||||
}
|
||||
// Game intro animation, T-rex moves in from the left.
|
||||
if (trex.playingIntro) {
|
||||
if (trex.xPos < TREX_START_X_POS) {
|
||||
//printf("trex.xPos = %d\n", trex.xPos);
|
||||
trex.xPos += max((int)round(((double)TREX_START_X_POS / TREX_INTRO_DURATION) * deltaTime), 1);
|
||||
}
|
||||
else {
|
||||
runnerStartGame();
|
||||
}
|
||||
}
|
||||
|
||||
if (trex.status == TREX_STATUS_WAITING) {
|
||||
trexBlink(getTimeStamp());
|
||||
}
|
||||
else {
|
||||
// printf("trex.status = %d\n", trex.status);
|
||||
trexDraw(trex.currentAnimFrames.frames[trex.currentFrame], 0);
|
||||
}
|
||||
|
||||
// Update the frame position.
|
||||
if (trex.timer >= trex.msPerFrame) {
|
||||
trex.currentFrame = trex.currentFrame == trex.currentAnimFrames.frameCount - 1 ? 0 : trex.currentFrame + 1;
|
||||
trex.timer = 0;
|
||||
}
|
||||
|
||||
// Speed drop becomes duck if the down key is still being pressed.
|
||||
if (trex.speedDrop && trex.yPos == trex.groundYPos) {
|
||||
trex.speedDrop = false;
|
||||
trexSetDuck(true);
|
||||
}
|
||||
}
|
||||
|
||||
void trexDraw(int x, int y) {
|
||||
//printf("trexDraw();\n");
|
||||
int sourceWidth = trex.ducking && trex.status != TREX_STATUS_CRASHED ? TREX_WIDTH_DUCK : TREX_WIDTH;
|
||||
int sourceHeight = TREX_HEIGHT;
|
||||
// Adjustments for sprite sheet position.
|
||||
int sourceX = x + ATLAS_TREX_X;
|
||||
int sourceY = y + ATLAS_TREX_Y;
|
||||
|
||||
// Ducking.
|
||||
if (trex.ducking && trex.status != TREX_STATUS_CRASHED) {
|
||||
graphicsBlitAtlasImage(sourceX, sourceY, trex.xPos, trex.yPos, sourceWidth, sourceHeight, false);
|
||||
}
|
||||
else {
|
||||
// Crashed whilst ducking. Trex is standing up so needs adjustment.
|
||||
if (trex.ducking && trex.status == TREX_STATUS_CRASHED) {
|
||||
trex.xPos++;
|
||||
}
|
||||
// Standing / running
|
||||
graphicsBlitAtlasImage(sourceX, sourceY, trex.xPos, trex.yPos, sourceWidth, sourceHeight, false);
|
||||
}
|
||||
}
|
||||
|
||||
void trexSetBlinkDelay() {
|
||||
trex.blinkDelay = (int)ceil(((double)rand()/RAND_MAX)*TREX_BLINK_TIMING);
|
||||
}
|
||||
|
||||
void trexBlink(int time) {
|
||||
//printf("trexBlink(%d)\n", time);
|
||||
int deltaTime = time - trex.animStartTime;
|
||||
if (deltaTime < 0) {
|
||||
deltaTime = DELTA_MS_DEFAULT;
|
||||
}
|
||||
if (deltaTime >= trex.blinkDelay) {
|
||||
trexDraw(trex.currentAnimFrames.frames[trex.currentFrame], 0);
|
||||
if (trex.currentFrame == 1) {
|
||||
// Set new random delay to blink.
|
||||
trexSetBlinkDelay();
|
||||
trex.animStartTime = time;
|
||||
trex.blinkCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise a jump
|
||||
void trexStartJump(double speed) {
|
||||
if (!trex.jumping) {
|
||||
trexUpdate(0, TREX_STATUS_JUMPING);
|
||||
// Tweak the jump velocity based on the speed
|
||||
trex.jumpVelocity = TREX_INITIAL_JUMP_VELOCITY - (speed / 10);
|
||||
trex.jumping = true;
|
||||
trex.reachedMinHeight = false;
|
||||
trex.speedDrop = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Jump is complete, falling down
|
||||
void trexEndJump() {
|
||||
if (trex.reachedMinHeight && trex.jumpVelocity < TREX_DROP_VELOCITY) {
|
||||
trex.jumpVelocity = TREX_DROP_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
// Update frame for a jump
|
||||
void trexUpdateJump(int deltaTime) {
|
||||
double msPerFrame = trexAnimFrames[trex.status].msPerFrame;
|
||||
double framesElapsed = deltaTime / msPerFrame;
|
||||
|
||||
// Speed drop makes Trex fall faster.
|
||||
if (trex.speedDrop) {
|
||||
trex.yPos += (int)round(trex.jumpVelocity * TREX_SPEED_DROP_COEFFICIENT * framesElapsed);
|
||||
}
|
||||
else {
|
||||
trex.yPos += (int)round(trex.jumpVelocity * framesElapsed);
|
||||
}
|
||||
trex.jumpVelocity += TREX_GRAVITY * framesElapsed;
|
||||
// Minimum height has been reached.
|
||||
if (trex.yPos < trex.minJumpHeight || trex.speedDrop) {
|
||||
trex.reachedMinHeight = true;
|
||||
}
|
||||
// Reached max height
|
||||
if (trex.yPos < TREX_MAX_JUMP_HEIGHT || trex.speedDrop) {
|
||||
trexEndJump();
|
||||
}
|
||||
// Back down at ground level. Jump completed.
|
||||
if (trex.yPos > trex.groundYPos) {
|
||||
trexReset();
|
||||
trex.jumpCount++;
|
||||
}
|
||||
trexUpdate(deltaTime, -1);
|
||||
}
|
||||
|
||||
// Set the speed drop.Immediately cancels the current jump
|
||||
void trexSetSpeedDrop() {
|
||||
trex.speedDrop = true;
|
||||
trex.jumpVelocity = 1;
|
||||
}
|
||||
|
||||
void trexSetDuck(bool isDucking) {
|
||||
if (isDucking && trex.status != TREX_STATUS_DUCKING) {
|
||||
trexUpdate(0, TREX_STATUS_DUCKING);
|
||||
trex.ducking = true;
|
||||
}
|
||||
else if (trex.status == TREX_STATUS_DUCKING) {
|
||||
trexUpdate(0, TREX_STATUS_RUNNING);
|
||||
trex.ducking = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the t-rex to running at start of game
|
||||
void trexReset() {
|
||||
trex.yPos = trex.groundYPos;
|
||||
trex.jumpVelocity = 0;
|
||||
trex.jumping = false;
|
||||
trex.ducking = false;
|
||||
trexUpdate(0, TREX_STATUS_RUNNING);
|
||||
//trex.midair = false; TODO: WTF is midair
|
||||
trex.speedDrop = false;
|
||||
trex.jumpCount = 0;
|
||||
}
|
83
programs/games/dino/trex.h
Normal file
83
programs/games/dino/trex.h
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef TREX_H
|
||||
#define TREX_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "collisionbox.h"
|
||||
#include "runner.h"
|
||||
#include "graphics.h"
|
||||
#include "misc.h"
|
||||
|
||||
// Blinking coefficient
|
||||
#define TREX_BLINK_TIMING 7000
|
||||
|
||||
#define TREX_DROP_VELOCITY -5
|
||||
#define TREX_GRAVITY 0.6
|
||||
#define TREX_HEIGHT 47
|
||||
#define TREX_HEIGHT_DUCK 25
|
||||
#define TREX_INITIAL_JUMP_VELOCITY -10
|
||||
#define TREX_INTRO_DURATION 750
|
||||
#define TREX_MAX_JUMP_HEIGHT 30
|
||||
#define TREX_MIN_JUMP_HEIGHT 30
|
||||
#define TREX_SPEED_DROP_COEFFICIENT 3
|
||||
#define TREX_SPRITE_WIDTH 262
|
||||
#define TREX_START_X_POS 25
|
||||
#define TREX_WIDTH 44
|
||||
#define TREX_WIDTH_DUCK 59
|
||||
|
||||
// Animation states
|
||||
typedef enum {
|
||||
TREX_STATUS_WAITING = 0,
|
||||
TREX_STATUS_RUNNING = 1,
|
||||
TREX_STATUS_CRASHED = 2,
|
||||
TREX_STATUS_JUMPING = 3,
|
||||
TREX_STATUS_DUCKING = 4,
|
||||
} TrexStatus;
|
||||
|
||||
typedef struct {
|
||||
int frameCount;
|
||||
int frames[2];
|
||||
double msPerFrame;
|
||||
} TrexAnimFramesEntry;
|
||||
|
||||
typedef struct {
|
||||
int xPos;
|
||||
int yPos;
|
||||
int groundYPos;
|
||||
int currentFrame;
|
||||
TrexAnimFramesEntry currentAnimFrames;
|
||||
int blinkDelay;
|
||||
int blinkCount;
|
||||
int animStartTime;
|
||||
int timer;
|
||||
double msPerFrame;
|
||||
TrexStatus status;
|
||||
bool jumping;
|
||||
bool ducking;
|
||||
double jumpVelocity;
|
||||
bool reachedMinHeight;
|
||||
bool speedDrop;
|
||||
int jumpCount;
|
||||
int jumpspotX;
|
||||
int minJumpHeight;
|
||||
bool playingIntro;
|
||||
} Trex;
|
||||
|
||||
extern CollisionBox trexDuckingCollisionBox;
|
||||
extern CollisionBox trexRunningCollisionBox[6];
|
||||
extern Trex trex;
|
||||
|
||||
void trexInit();
|
||||
void trexUpdate(int deltaTime, int opt_status);
|
||||
void trexDraw(int x, int y);
|
||||
void trexSetBlinkDelay();
|
||||
void trexBlink(int time);
|
||||
void trexStartJump(double speed);
|
||||
void trexEndJump();
|
||||
void trexUpdateJump(int deltaTime);
|
||||
void trexSetSpeedDrop();
|
||||
void trexSetDuck(bool isDucking);
|
||||
void trexReset();
|
||||
|
||||
#endif
|
241
programs/games/dino/ulist.c
Normal file
241
programs/games/dino/ulist.c
Normal file
@ -0,0 +1,241 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "ulist.h"
|
||||
|
||||
Ulist* ulist_create() {
|
||||
Ulist* list = (Ulist*)malloc(sizeof(Ulist));
|
||||
if (list == NULL) {
|
||||
// abort();
|
||||
exit(-1);
|
||||
}
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
list->size = 0;
|
||||
return list;
|
||||
}
|
||||
|
||||
void ulist_destroy(Ulist* list) {
|
||||
Node* current = list->head;
|
||||
Node* next;
|
||||
|
||||
while (current != NULL) {
|
||||
next = current->next;
|
||||
free(current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
free(list);
|
||||
}
|
||||
|
||||
void ulist_push_front(Ulist* list, void* data) {
|
||||
Node* new_node = (Node*)malloc(sizeof(Node));
|
||||
if (new_node == NULL) {
|
||||
// abort();
|
||||
exit(-1);
|
||||
}
|
||||
new_node->data = data;
|
||||
new_node->prev = NULL;
|
||||
new_node->next = list->head;
|
||||
|
||||
if (list->head != NULL) {
|
||||
list->head->prev = new_node;
|
||||
}
|
||||
|
||||
list->head = new_node;
|
||||
|
||||
if (list->tail == NULL) {
|
||||
list->tail = new_node;
|
||||
}
|
||||
|
||||
list->size++;
|
||||
}
|
||||
|
||||
void ulist_push_back(Ulist* list, void* data) {
|
||||
Node* new_node = (Node*)malloc(sizeof(Node));
|
||||
if (new_node == NULL) {
|
||||
// abort();
|
||||
exit(-1);
|
||||
}
|
||||
new_node->data = data;
|
||||
new_node->next = NULL;
|
||||
new_node->prev = list->tail;
|
||||
|
||||
if (list->tail != NULL) {
|
||||
list->tail->next = new_node;
|
||||
}
|
||||
|
||||
list->tail = new_node;
|
||||
|
||||
if (list->head == NULL) {
|
||||
list->head = new_node;
|
||||
}
|
||||
|
||||
list->size++;
|
||||
}
|
||||
|
||||
void ulist_remove(Ulist* list, Node* node) {
|
||||
if (list == NULL || node == NULL) {
|
||||
return;
|
||||
}
|
||||
// Update previous node's next pointer
|
||||
if (node->prev != NULL) {
|
||||
node->prev->next = node->next;
|
||||
}
|
||||
else {
|
||||
// If the node is the head, update the head pointer
|
||||
list->head = node->next;
|
||||
}
|
||||
// Update next node's previous pointer
|
||||
if (node->next != NULL) {
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
else {
|
||||
// If the node is the tail, update the tail pointer
|
||||
list->tail = node->prev;
|
||||
}
|
||||
// Free the memory occupied by the node
|
||||
free(node);
|
||||
list->size--;
|
||||
}
|
||||
|
||||
void ulist_remove_front(Ulist* list) {
|
||||
if (list->head == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node* node_to_remove = list->head;
|
||||
list->head = list->head->next;
|
||||
|
||||
if (list->head != NULL) {
|
||||
list->head->prev = NULL;
|
||||
}
|
||||
else {
|
||||
list->tail = NULL;
|
||||
}
|
||||
|
||||
free(node_to_remove);
|
||||
list->size--;
|
||||
}
|
||||
|
||||
void ulist_splice(Ulist* list, int n) {
|
||||
if (list->size <= n) {
|
||||
return; // No need to splice if the list size is less than or equal to n
|
||||
}
|
||||
int count = list->size - n;
|
||||
while (count > 0) {
|
||||
ulist_remove_back(list);
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
void ulist_remove_back(Ulist* list) {
|
||||
if (list->tail == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node* node_to_remove = list->tail;
|
||||
list->tail = list->tail->prev;
|
||||
|
||||
if (list->tail != NULL) {
|
||||
list->tail->next = NULL;
|
||||
}
|
||||
else {
|
||||
list->head = NULL;
|
||||
}
|
||||
|
||||
free(node_to_remove);
|
||||
list->size--;
|
||||
}
|
||||
|
||||
int ulist_search(Ulist* list, void* data) {
|
||||
Node* current = list->head;
|
||||
int index = 0;
|
||||
|
||||
while (current != NULL) {
|
||||
if (current->data == data) {
|
||||
return index;
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void* ulist_get_front(Ulist* list) {
|
||||
if (list->head == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return list->head->data;
|
||||
}
|
||||
|
||||
void* ulist_get_back(Ulist* list) {
|
||||
if (list->tail == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return list->tail->data;
|
||||
}
|
||||
|
||||
int ulist_size(Ulist* list) {
|
||||
return list->size;
|
||||
}
|
||||
|
||||
void ulist_print(Ulist* list) {
|
||||
Node* current = list->head;
|
||||
|
||||
while (current != NULL) {
|
||||
printf("%p ", current->data);
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void ulist_test() {
|
||||
// Create a new Ulist
|
||||
Ulist* list = ulist_create();
|
||||
|
||||
// Test insertFront
|
||||
int data1 = 10;
|
||||
ulist_push_front(list, &data1);
|
||||
printf("List after inserting 10 at the front: ");
|
||||
ulist_print(list); // Expected output: 10
|
||||
|
||||
// Test insertBack
|
||||
int data2 = 20;
|
||||
ulist_push_back(list, &data2);
|
||||
printf("List after inserting 20 at the back: ");
|
||||
ulist_print(list); // Expected output: 10 20
|
||||
|
||||
// Test removeFront
|
||||
ulist_remove_front(list);
|
||||
printf("List after removing front element: ");
|
||||
ulist_print(list); // Expected output: 20
|
||||
|
||||
// Test removeBack
|
||||
ulist_remove_back(list);
|
||||
printf("List after removing back element: ");
|
||||
ulist_print(list); // Expected output:
|
||||
|
||||
// Test search
|
||||
int data3 = 30;
|
||||
ulist_push_front(list, &data3);
|
||||
printf("Index of 30 in the list: %d\n", ulist_search(list, &data3)); // Expected output: 0
|
||||
|
||||
// Test getFront
|
||||
int* front = (int*)ulist_get_front(list);
|
||||
printf("Front element of the list: %d\n", *front); // Expected output: 30
|
||||
|
||||
// Test getBack
|
||||
int* back = (int*)ulist_get_back(list);
|
||||
printf("Back element of the list: %d\n", *back); // Expected output: 30
|
||||
|
||||
// Test getSize
|
||||
printf("Size of the list: %d\n", ulist_size(list)); // Expected output: 1
|
||||
|
||||
// Destroy the list
|
||||
ulist_destroy(list);
|
||||
}
|
31
programs/games/dino/ulist.h
Normal file
31
programs/games/dino/ulist.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef ULIST_H_
|
||||
#define ULIST_H_
|
||||
|
||||
typedef struct Node {
|
||||
void* data;
|
||||
struct Node* prev;
|
||||
struct Node* next;
|
||||
} Node;
|
||||
|
||||
typedef struct Ulist {
|
||||
Node* head;
|
||||
Node* tail;
|
||||
int size;
|
||||
} Ulist;
|
||||
|
||||
Ulist* ulist_create();
|
||||
void ulist_destroy(Ulist* list);
|
||||
void ulist_push_front(Ulist* list, void* data);
|
||||
void ulist_push_back(Ulist* list, void* data);
|
||||
void ulist_remove(Ulist *list, Node *node);
|
||||
void ulist_remove_front(Ulist* list);
|
||||
void ulist_splice(Ulist* list, int n);
|
||||
void ulist_remove_back(Ulist* list);
|
||||
int ulist_search(Ulist* list, void* data);
|
||||
void* ulist_get_front(Ulist* list);
|
||||
void* ulist_get_back(Ulist* list);
|
||||
int ulist_size(Ulist* list);
|
||||
void ulist_print(Ulist* list);
|
||||
void ulist_test();
|
||||
|
||||
#endif /* ULIST_H_ */
|
2
programs/other/charset_checker/Tupfile.lua
Normal file
2
programs/other/charset_checker/Tupfile.lua
Normal file
@ -0,0 +1,2 @@
|
||||
if tup.getconfig("NO_FASM") ~= "" then return end
|
||||
tup.rule("charset_checker.asm", "fasm %f %o " .. tup.getconfig("KPACK_CMD"), "charchck")
|
621
programs/other/charset_checker/charset_checker.asm
Normal file
621
programs/other/charset_checker/charset_checker.asm
Normal file
@ -0,0 +1,621 @@
|
||||
format binary as ""
|
||||
use32
|
||||
org 0
|
||||
|
||||
; ================================================================
|
||||
|
||||
db 'MENUET01'
|
||||
dd 1
|
||||
dd START
|
||||
dd I_END
|
||||
dd MEM
|
||||
dd STACKTOP
|
||||
dd 0, 0
|
||||
|
||||
; ================================================================
|
||||
|
||||
include '../../macros.inc'
|
||||
|
||||
START: ; start of execution
|
||||
call draw_window ; draw the window
|
||||
|
||||
event_wait:
|
||||
mov eax, 10 ; function 10 : wait until event
|
||||
mcall ; event type is returned in eax
|
||||
|
||||
cmp eax, 1 ; Event redraw request
|
||||
je red ; Expl.: there has been activity on screen and
|
||||
; parts of the applications has to be redrawn.
|
||||
cmp eax, 2 ; Event key in buffer
|
||||
je key ; Expl.: User has pressed a key while the
|
||||
; app is at the top of the window stack.
|
||||
cmp eax, 3 ; Event button in buffer
|
||||
je button ; Expl.: User has pressed one of the
|
||||
; applications buttons.
|
||||
jmp event_wait
|
||||
|
||||
red: ; Redraw event handler
|
||||
call draw_window ; We call the window_draw function and
|
||||
jmp event_wait ; jump back to event_wait
|
||||
|
||||
key: ; Keypress event handler
|
||||
mov eax, 2 ; The key is returned in ah. The key must be
|
||||
mcall ; read and cleared from the system queue.
|
||||
cmp eax, 1 ; Just read the key, ignore it and jump to event_wait.
|
||||
je event_wait
|
||||
mov cl, [reading]
|
||||
cmp cl, 0x00
|
||||
je event_wait
|
||||
mov [char], ah
|
||||
mov [page], 0x00
|
||||
push eax
|
||||
shr ax, 8
|
||||
xor ah, ah
|
||||
mov [char_ascii], ax
|
||||
pop eax
|
||||
shr eax, 16
|
||||
mov [char_scan], ax
|
||||
mov [letter], 0x0000
|
||||
call draw_update
|
||||
jmp event_wait
|
||||
|
||||
button: ; Buttonpress event handler
|
||||
mov eax, 17 ; The button number defined in window_draw
|
||||
mcall
|
||||
|
||||
.close:
|
||||
cmp ah, 1
|
||||
jne .button_a
|
||||
mov eax, -1
|
||||
mcall
|
||||
|
||||
.button_a: ; select character
|
||||
cmp ah, 0x0A
|
||||
jne .button_b
|
||||
mcall 37, 1
|
||||
push eax
|
||||
sub ax, 34
|
||||
mov bl, 24
|
||||
div bl
|
||||
mov cl, al
|
||||
shl cl, 4
|
||||
pop eax
|
||||
shr eax, 16
|
||||
sub ax, 34
|
||||
div bl
|
||||
add cl, al
|
||||
mov [char], cl
|
||||
mov [char_scan], 0x0000
|
||||
call logic_update
|
||||
call draw_update
|
||||
jmp event_wait
|
||||
|
||||
.button_b: ; charset CP866 6x9
|
||||
cmp ah, 0x0B
|
||||
jne .button_c
|
||||
mov [charset], 0x80
|
||||
mov [lb_curr], lb_cp6x9
|
||||
call draw_update
|
||||
jmp event_wait
|
||||
|
||||
.button_c: ; charset CP866 8x16
|
||||
cmp ah, 0x0C
|
||||
jne .button_d
|
||||
mov [charset], 0x90
|
||||
mov [lb_curr], lb_cp8x16
|
||||
call draw_update
|
||||
jmp event_wait
|
||||
|
||||
.button_d: ; charset UTF-16 8x16
|
||||
cmp ah, 0x0D
|
||||
jne .button_e
|
||||
mov [charset], 0xA0
|
||||
mov [lb_curr], lb_utf16
|
||||
call draw_update
|
||||
jmp event_wait
|
||||
|
||||
.button_e: ; charset UTF-8 8x16
|
||||
cmp ah, 0x0E
|
||||
jne .button_f
|
||||
mov [charset], 0xB0
|
||||
mov [lb_curr], lb_utf8
|
||||
call draw_update
|
||||
jmp event_wait
|
||||
|
||||
.button_f: ; charpage reset
|
||||
cmp ah, 0x0F
|
||||
jne .button_10
|
||||
mov [page], 0x00
|
||||
call logic_update
|
||||
call draw_update
|
||||
jmp event_wait
|
||||
|
||||
.button_10: ; charpage decrement
|
||||
cmp ah, 0x10
|
||||
jne .button_11
|
||||
mov ch, [page]
|
||||
dec ch
|
||||
mov [page], ch
|
||||
call logic_update
|
||||
call draw_update
|
||||
jmp event_wait
|
||||
|
||||
.button_11: ; charpage increment
|
||||
cmp ah, 0x11
|
||||
jne .button_12
|
||||
mov ch, [page]
|
||||
inc ch
|
||||
mov [page], ch
|
||||
call logic_update
|
||||
call draw_update
|
||||
jmp event_wait
|
||||
|
||||
.button_12: ; read/stop keyboard input
|
||||
cmp ah, 0x12
|
||||
jne event_wait
|
||||
mov al, 0x01
|
||||
sub al, [reading]
|
||||
mov [reading], al
|
||||
call draw_toggle
|
||||
|
||||
|
||||
jmp event_wait
|
||||
|
||||
; ================================================================
|
||||
|
||||
draw_window:
|
||||
|
||||
mcall 12, 1
|
||||
|
||||
mcall 48, 3, window_colors, 40
|
||||
|
||||
mcall , 4
|
||||
push eax
|
||||
|
||||
mov eax, 0
|
||||
mov ebx, 100 * 65536 + 685
|
||||
mov ecx, 100 * 65536 + 518
|
||||
mov edx, [window_colors.work]
|
||||
add edx, 0x34000000
|
||||
mov edi, title
|
||||
mcall
|
||||
|
||||
pop esi
|
||||
add esi, 495
|
||||
mcall 67, -1, -1, -1,
|
||||
|
||||
call draw_base
|
||||
call draw_update
|
||||
call draw_toggle
|
||||
|
||||
mcall 12, 2
|
||||
|
||||
ret
|
||||
|
||||
; ================================================================
|
||||
|
||||
; unchangeble base - table, headers and buttons
|
||||
draw_base:
|
||||
|
||||
.tables:
|
||||
; both tables background
|
||||
mcall 13, 65536 * 9 + 410, 65536 * 9 + 410, [window_colors.work_light]
|
||||
mcall , 65536 * 428 + 240, 65536 * 9 + 442,
|
||||
|
||||
; 16x16 characters table
|
||||
mcall , 65536 * 8 + 411, 65536 * 8 + 1, [window_colors.work_text]
|
||||
mcall , , 65536 * 33 + 1,
|
||||
mcall , , 65536 * 418 + 1,
|
||||
mcall , 65536 * 8 + 1, 65536 * 8 + 410,
|
||||
mcall , 65536 * 33 + 1, ,
|
||||
mcall , 65536 * 418 + 1, ,
|
||||
|
||||
; single character table
|
||||
mcall , 65536 * 427 + 1, 65536 * 8 + 443,
|
||||
mcall , 65536 * 668 + 1, ,
|
||||
mcall , 65536 * 427 + 242, 65536 * 8 + 1,
|
||||
mcall , , 65536 * 376 + 1,
|
||||
mcall , , 65536 * 401 + 1,
|
||||
mcall , , 65536 * 426 + 1,
|
||||
mcall , , 65536 * 451 + 1,
|
||||
mcall , 65536 * 562 + 1, 65536 * 377 + 75,
|
||||
mcall , 65536 * 619 + 1, ,
|
||||
|
||||
.headers:
|
||||
; horizontal table headers
|
||||
mov eax, 4
|
||||
mov ebx, 65536 * 38 + 14
|
||||
mov ecx, [window_colors.work_text]
|
||||
add ecx, 0x90000000
|
||||
mov esi, 16
|
||||
|
||||
.loop_hx:
|
||||
mov edx, header
|
||||
mcall
|
||||
|
||||
mov dx, [header]
|
||||
add dx, 0x0100
|
||||
|
||||
cmp dx, 0x3A2D
|
||||
jne .hx_af
|
||||
add dx, 0x0700
|
||||
|
||||
.hx_af:
|
||||
mov [header], dx
|
||||
add ebx, 65536 * 24
|
||||
dec esi
|
||||
jnz .loop_hx
|
||||
|
||||
; vertical headers
|
||||
mov ebx, 65536 * 13 + 39
|
||||
mov esi, 16
|
||||
mov [header], 0x2D30
|
||||
|
||||
.loop_hy:
|
||||
mov edx, header
|
||||
mcall
|
||||
|
||||
mov dx, [header]
|
||||
add dx, 0x0001
|
||||
|
||||
cmp dx, 0x2D3A
|
||||
jne .hy_af
|
||||
add dx, 0x0007
|
||||
|
||||
.hy_af:
|
||||
mov [header], dx
|
||||
add ebx, 24
|
||||
dec esi
|
||||
jnz .loop_hy
|
||||
|
||||
; reset headers
|
||||
mov [header], 0x302D
|
||||
|
||||
; single character table headers
|
||||
mcall , 65536 * 579 + 382, , lb_dec,
|
||||
mcall , 65536 * 632 + 382, , lb_hex,
|
||||
mcall , 65536 * 436 + 407, , lb_asci,
|
||||
mcall , 65536 * 436 + 432, , lb_scan,
|
||||
|
||||
.buttons:
|
||||
; button on table to pick single character
|
||||
mcall 8, 65536 * 34 + 384, 65536 * 34 + 384, 0x6000000A,
|
||||
|
||||
; charsets change buttons
|
||||
mcall , 65536 * 8 + 95, 65536 * 459 + 23, 0x0000000B, [window_colors.work_button]
|
||||
mcall , 65536 * 113 + 95, , 0x0000000C,
|
||||
mcall , 65536 * 218 + 95, , 0x0000000D,
|
||||
mcall , 65536 * 323 + 95, , 0x0000000E,
|
||||
|
||||
; page swap buttons
|
||||
mcall , 65536 * 323 + 31, 65536 * 427 + 23, 0x0000000F,
|
||||
mcall , 65536 * 363 + 23, , 0x00000010,
|
||||
mcall , 65536 * 395 + 23, , 0x00000011,
|
||||
|
||||
; charsets change buttons subscriptions
|
||||
mov ecx, [window_colors.work_button_text]
|
||||
add ecx, 0xB0000000
|
||||
mcall 4, 65536 * 20 + 464, , lb_cp6x9
|
||||
mcall , 65536 * 121 + 464, , lb_cp8x16
|
||||
mcall , 65536 * 222 + 464, , lb_utf16
|
||||
mcall , 65536 * 331 + 464, , lb_utf8
|
||||
|
||||
; page swap buttons subscriptions
|
||||
mcall , 65536 * 331 + 432, , bt_res
|
||||
mcall , 65536 * 370 + 432, , bt_dec
|
||||
mcall , 65536 * 403 + 432, , bt_inc
|
||||
|
||||
ret
|
||||
|
||||
; changable data: current charset, charpage, chars, single char and it's codes
|
||||
draw_update:
|
||||
|
||||
; background for letters
|
||||
mcall 13, 65536 * 34 + 384, 65536 * 34 + 384, [window_colors.work_light]
|
||||
|
||||
; current charset and charpage
|
||||
.charpage:
|
||||
; current charpage
|
||||
mov esi, [window_colors.work_text]
|
||||
add esi, 0x50000000
|
||||
mcall 47, 65536 * 2 + 257, page, 0x000D000E, , [window_colors.work_light]
|
||||
|
||||
; current charset
|
||||
mov ecx, [window_colors.work_text]
|
||||
add ecx, 0xD0000000
|
||||
mcall 4, 65536 * 8 + 432, , [lb_curr], , [window_colors.work]
|
||||
|
||||
; 16x16 table of letters
|
||||
.letters:
|
||||
;different coordinates for 6x9 charset
|
||||
mov bl, [charset]
|
||||
cmp bl, 0x80
|
||||
jne .char_big
|
||||
|
||||
.char_sm:
|
||||
mov ebx, 65536 * 44 + 42
|
||||
jmp .char_draw
|
||||
|
||||
.char_big:
|
||||
mov ebx, 65536 * 42 + 39
|
||||
|
||||
.char_draw:
|
||||
mov cl, [charset]
|
||||
shl ecx, 24
|
||||
add ecx, [window_colors.work_text]
|
||||
mov esi, 16
|
||||
|
||||
; letters draw loop
|
||||
.loop_ly:
|
||||
mov edi, 16
|
||||
|
||||
.loop_lx:
|
||||
mov edx, letter
|
||||
|
||||
cmp [charset], 0xB0
|
||||
jne .skip_lx
|
||||
|
||||
;utf 8 to 16
|
||||
xor edx, edx
|
||||
mov dx, [letter]
|
||||
push esi
|
||||
mov esi, letutf
|
||||
call logic_utf16to8
|
||||
pop esi
|
||||
mov edx, letutf
|
||||
|
||||
.skip_lx:
|
||||
|
||||
mcall
|
||||
|
||||
mov dx, [letter]
|
||||
add dx, 0x01
|
||||
mov [letter], dx
|
||||
|
||||
add ebx, 65536 * 24
|
||||
|
||||
dec edi
|
||||
jnz .loop_lx
|
||||
|
||||
; start new row of letters
|
||||
sub ebx, 65536 * 383 + 65512
|
||||
|
||||
dec esi
|
||||
jnz .loop_ly
|
||||
|
||||
; reset letter from 0x0100 to 0x0000
|
||||
mov dx, [letter]
|
||||
dec dh
|
||||
mov [letter], dx
|
||||
|
||||
; highlight of current character in table
|
||||
.highlight:
|
||||
mov al, [char]
|
||||
shr al, 4
|
||||
mov bl, 24
|
||||
mul bl
|
||||
add ax, 34
|
||||
shl eax, 16
|
||||
mov al, 0x01
|
||||
mov ecx, eax
|
||||
push ecx
|
||||
mcall 13, 65536 * 34 + 384, , [window_colors.work_button]
|
||||
add ecx, 65536 * 23
|
||||
mcall
|
||||
|
||||
mov al, [char]
|
||||
and al, 0x0F
|
||||
mov bl, 24
|
||||
mul bl
|
||||
add ax, 34
|
||||
shl eax, 16
|
||||
mov al, 0x01
|
||||
mov ebx, eax
|
||||
mcall 13, , 65536 * 34 + 384, [window_colors.work_button]
|
||||
add ebx, 65536 * 23
|
||||
mcall
|
||||
|
||||
pop ecx
|
||||
add ecx, 23
|
||||
sub ebx, 65535 * 23
|
||||
mcall
|
||||
|
||||
shr ecx, 16
|
||||
mov bx, cx
|
||||
add ebx, 65536 * 8 + 5
|
||||
|
||||
mov cl, [charset]
|
||||
cmp cl, 0xB0
|
||||
jne .check_80
|
||||
mov cl, 0xA0
|
||||
jmp .process
|
||||
|
||||
.check_80:
|
||||
cmp cl, 0x80
|
||||
jne .process
|
||||
add ebx, 65536 * 2 + 3
|
||||
|
||||
.process:
|
||||
shl ecx, 24
|
||||
add ecx, [window_colors.work_button_text]
|
||||
mcall 4, , , char_ascii
|
||||
|
||||
; single character big display
|
||||
.single:
|
||||
|
||||
mcall 13, 65536 * 452 + 192, 65536 * 24 + 336, [window_colors.work_light]
|
||||
mov ah, [page]
|
||||
mov al, [char]
|
||||
mov [char_ascii], ax
|
||||
|
||||
cmp [charset], 0xB0
|
||||
|
||||
jne .skip_sn
|
||||
;utf 8 to 16
|
||||
xor edx, edx
|
||||
mov dx, [char_ascii]
|
||||
push esi
|
||||
mov esi, char_utf
|
||||
call logic_utf16to8
|
||||
pop esi
|
||||
|
||||
mov ecx, 0xF7000000
|
||||
add ecx, [window_colors.work_text]
|
||||
mcall 4, 65536 * 516 + 136, , char_utf, 0, [window_colors.work_light]
|
||||
jmp .codes
|
||||
|
||||
.skip_sn:
|
||||
mov ebx, 65536 * 516 + 136
|
||||
mov cl, [charset]
|
||||
|
||||
cmp cl, 0x80
|
||||
jne .not_80
|
||||
add ebx, 65536 * 12 + 29
|
||||
|
||||
.not_80:
|
||||
add cl, 0x07
|
||||
shl ecx, 24
|
||||
add ecx, [window_colors.work_text]
|
||||
mcall 4, , , char_ascii, 1, [window_colors.work_light]
|
||||
|
||||
; singe character codes
|
||||
.codes:
|
||||
|
||||
mov esi, [window_colors.work_text]
|
||||
add esi, 0x50000000
|
||||
|
||||
xor ecx, ecx
|
||||
|
||||
mov cx, [char_ascii]
|
||||
mcall 47, 0x00050000, , 65536 * 571 + 407, , [window_colors.work_light]
|
||||
mov cx, [char_scan]
|
||||
mcall , , , 65536 * 571 + 432,
|
||||
|
||||
mov cx, [char_ascii]
|
||||
mcall , 0x00040100, , 65536 * 628 + 407,
|
||||
mov cx, [char_scan]
|
||||
mcall , , , 65536 * 628 + 432,
|
||||
|
||||
ret
|
||||
|
||||
; redraw keyboard input toggle button
|
||||
draw_toggle:
|
||||
|
||||
mcall 8, 65536 * 427 + 241, 65536 * 459 + 23, 0x00000012, [window_colors.work_button]
|
||||
|
||||
mov ecx, [window_colors.work_button_text]
|
||||
add ecx, 0xB0000000
|
||||
|
||||
mov al, [reading]
|
||||
cmp al, 0x01
|
||||
|
||||
je .stop
|
||||
mcall 4, 65536 * 472 + 464, , bt_read
|
||||
ret
|
||||
.stop:
|
||||
mcall 4, 65536 * 472 + 464, , bt_stop
|
||||
ret
|
||||
|
||||
; ================================================================
|
||||
|
||||
; update all dependant values
|
||||
logic_update:
|
||||
|
||||
; update [letter] value (first char on current page)
|
||||
mov ax, [letter]
|
||||
mov ah, [page]
|
||||
mov [letter], ax
|
||||
|
||||
; update [char_ascii] value (selected single char)
|
||||
mov ah, [page]
|
||||
mov al, [char]
|
||||
mov [char_ascii], ax
|
||||
|
||||
ret
|
||||
|
||||
; edx = num, esi -> buffer of size 4
|
||||
logic_utf16to8:
|
||||
|
||||
push eax ecx edx
|
||||
xor ecx, ecx
|
||||
mov dword [esi], 0
|
||||
or ecx, 3
|
||||
mov eax, 0x80808000 + 11110000b
|
||||
|
||||
cmp edx, 0x00010000
|
||||
jae @f
|
||||
mov eax, 0x00808000 + 11100000b
|
||||
dec ecx
|
||||
|
||||
cmp edx, 0x00000800
|
||||
jae @f
|
||||
mov eax, 0x00008000 + 11000000b
|
||||
dec ecx
|
||||
|
||||
cmp edx, 0x00000080
|
||||
jae @f
|
||||
mov eax, edx
|
||||
dec ecx
|
||||
|
||||
@@:
|
||||
mov [esi], eax
|
||||
|
||||
@@:
|
||||
mov eax, edx
|
||||
and eax, 0x3F
|
||||
shr edx, 6
|
||||
or byte[esi + ecx], al
|
||||
dec ecx
|
||||
jns @b
|
||||
|
||||
pop edx ecx eax
|
||||
|
||||
ret
|
||||
|
||||
; ================================================================
|
||||
|
||||
title db "Charset Checker 0.3.1", 0
|
||||
|
||||
lb_cp6x9 db "CP866 6x9 ", 0
|
||||
lb_cp8x16 db "CP866 8x16 ", 0
|
||||
lb_utf16 db "UTF-16 8x16", 0
|
||||
lb_utf8 db "UTF-8 8x16 ", 0
|
||||
|
||||
lb_curr dd lb_utf8
|
||||
|
||||
lb_hex db "HEX", 0
|
||||
lb_dec db "DEC", 0
|
||||
lb_asci db "ASCII-code", 0
|
||||
lb_scan db "Scan-code", 0
|
||||
|
||||
bt_res db "00", 0
|
||||
bt_dec db "<", 0
|
||||
bt_inc db ">", 0
|
||||
|
||||
bt_read db "Read keyboard input", 0
|
||||
bt_stop db "Stop keyboard input", 0
|
||||
|
||||
reading db 0x00
|
||||
|
||||
header dw 0x302D, 0 ; "-0" symbols
|
||||
letter dw 0x0000, 0
|
||||
letutf dd 0x00000000, 0
|
||||
|
||||
charset db 0xB0
|
||||
page db 0x00
|
||||
char db 0x00
|
||||
|
||||
char_ascii dw 0x0000, 0
|
||||
char_scan dw 0x0000, 0
|
||||
char_utf dd 0x00000000, 0
|
||||
|
||||
window_colors system_colors
|
||||
|
||||
; ================================================================
|
||||
|
||||
I_END:
|
||||
rb 4096
|
||||
align 16
|
||||
STACKTOP:
|
||||
|
||||
MEM:
|
Loading…
Reference in New Issue
Block a user