Compare commits

..

1 Commits

Author SHA1 Message Date
af99b495fe docs(libio): Add enum file funcs section 2024-11-21 20:51:05 +03:00
51 changed files with 135 additions and 5020 deletions

2
.gitignore vendored
View File

@ -7,5 +7,3 @@ ehthumbs_vista.db
### macOS ###
.DS_Store
._*
programs/cmm/cmm.code-workspace
programs/cmm/menu/.gitignore

View File

@ -475,7 +475,6 @@ 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"},
@ -591,7 +590,6 @@ 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"},

View File

@ -1,8 +1,9 @@
[rbmenu]
Processes=cpu
Theme settings=skincfg
Themes=desktop
Background=/sys/media/palitra
System panel=syspanel
Device setup=setup
Shell=shell
[00]
name=KFM2
path=/SYS/FILE MANAGERS/KFM2
@ -21,23 +22,23 @@ y=68
name=EOLITE
path=/SYS/FILE MANAGERS/EOLITE
param=
ico=0
ico=1
x=68
y=0
[03]
name=SHELL
path=SHELL
param=
ico=1
x=-203
y=136
ico=2
x=136
y=0
[04]
name=KFAR
path=/SYS/FILE MANAGERS/KFAR
param=
ico=16
x=136
y=0
x=68
y=68
[05]
name=RDSAVE
path=RDSAVE
@ -63,7 +64,7 @@ y=68
name=KPACK
path=KPACK
param=
ico=99
ico=10
x=-67
y=0
[09]
@ -88,10 +89,10 @@ ico=66
x=-135
y=-67
[0C]
name=TETRIS
path=/SYS/GAMES/TETRIS
name=MBLOCKS
path=/SYS/GAMES/MBLOCKS
param=
ico=47
ico=11
x=-67
y=-135
[0D]
@ -106,8 +107,8 @@ name=15
path=/SYS/GAMES/15
param=
ico=34
x=-67
y=-203
x=-271
y=-67
[0F]
name=DOCPACK
path=DOCPACK
@ -169,8 +170,8 @@ name=FLAPPY-BIRD
path=/SYS/GAMES/FLPYBIRD
param=
ico=49
x=-135
y=-203
x=-271
y=-135
[18]
name=KOSILKA
path=/SYS/GAMES/KOSILKA
@ -214,44 +215,16 @@ ico=6
x=-67
y=136
[1E]
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
y=68
[1F]
name=APP+
path=app_plus
param=
ico=27
x=-203
y=136

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -16,7 +16,6 @@ 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

View File

@ -106,8 +106,8 @@ name=15
path=/SYS/GAMES/15
param=
ico=34
x=-67
y=-203
x=-271
y=-67
[0F]
name=DOCPACK
path=DOCPACK
@ -169,8 +169,8 @@ name=FLAPPY-BIRD
path=/SYS/GAMES/FLPYBIRD
param=
ico=49
x=-135
y=-203
x=-271
y=-135
[18]
name=KOSILKA
path=/SYS/GAMES/KOSILKA
@ -248,10 +248,3 @@ param=
ico=125
x=204
y=136
[23]
name=DINO
path=/sys/games/dino
param=
ico=129
x=-203
y=-203

View File

@ -106,8 +106,8 @@ name=15
path=/SYS/GAMES/15
param=
ico=34
x=-67
y=-203
x=-271
y=-67
[0F]
name=DOCPACK
path=DOCPACK
@ -169,8 +169,8 @@ name=FLAPPY-BIRD
path=/SYS/GAMES/FLPYBIRD
param=
ico=49
x=-135
y=-203
x=-271
y=-135
[18]
name=KOSILKA
path=/SYS/GAMES/KOSILKA
@ -248,10 +248,3 @@ param=
ico=125
x=204
y=136
[23]
name=DINO
path=/sys/games/dino
param=
ico=129
x=-203
y=-203

View File

@ -106,8 +106,8 @@ name=15
path=/SYS/GAMES/15
param=
ico=34
x=-67
y=-203
x=-271
y=-67
[0F]
name=DOCPACK
path=DOCPACK
@ -169,8 +169,8 @@ name=FLAPPY-BIRD
path=/SYS/GAMES/FLPYBIRD
param=
ico=49
x=-135
y=-203
x=-271
y=-135
[18]
name=KOSILKA
path=/SYS/GAMES/KOSILKA
@ -248,10 +248,3 @@ param=
ico=125
x=204
y=136
[23]
name=DINO
path=/sys/games/dino
param=
ico=129
x=-203
y=-203

View File

@ -106,8 +106,8 @@ name=15
path=/SYS/GAMES/15
param=
ico=34
x=-67
y=-203
x=-271
y=-67
[0F]
name=DOCPACK
path=DOCPACK
@ -169,8 +169,8 @@ name=FLAPPY-BIRD
path=/SYS/GAMES/FLPYBIRD
param=
ico=49
x=-135
y=-203
x=-271
y=-135
[18]
name=KOSILKA
path=/SYS/GAMES/KOSILKA
@ -248,10 +248,3 @@ param=
ico=125
x=204
y=136
[23]
name=DINO
path=/sys/games/dino
param=
ico=129
x=-203
y=-203

View File

@ -16,7 +16,6 @@ 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

View File

@ -106,8 +106,8 @@ name=15
path=/SYS/GAMES/15
param=
ico=34
x=-67
y=-203
x=-271
y=-67
[0F]
name=DOCPACK
path=DOCPACK
@ -169,8 +169,8 @@ name=FLAPPY-BIRD
path=/SYS/GAMES/FLPYBIRD
param=
ico=49
x=-135
y=-203
x=-271
y=-135
[18]
name=KOSILKA
path=/SYS/GAMES/KOSILKA
@ -248,10 +248,3 @@ param=
ico=125
x=204
y=136
[23]
name=DINO
path=/sys/games/dino
param=
ico=129
x=-203
y=-203

View File

@ -1,3 +0,0 @@
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")

View File

@ -1,272 +0,0 @@
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 ?

View File

@ -1,178 +0,0 @@
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

View File

@ -1,675 +0,0 @@
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

View File

@ -1,408 +0,0 @@
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:

View File

@ -27,7 +27,6 @@ include '../../proc32.inc'
include '../../peimport.inc'
include '../../fdo.inc'
include '../../struct.inc'
include '../../serial/common.inc'
; USB constants
DEVICE_DESCR_TYPE = 1
@ -61,9 +60,6 @@ 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)
@ -123,7 +119,6 @@ TYPE_230X=7
;strings
my_driver db 'usbother',0
serial_driver db 'SERIAL',0
nomemory_msg db 'K : no memory',13,10,0
; Structures
@ -135,8 +130,8 @@ readBufChunkSize dd ?
writeBufChunkSize dd ?
readBufPtr dd ?
writeBufPtr dd ?
readBufLock dd ?
writeBufLock dd ?
readBufSize dd ?
writeBufSize dd ?
maxPacketSize dd ?
interface dd ?
index dd ?
@ -145,8 +140,6 @@ outEP dd ?
nullP dd ?
lockPID dd ?
next_context dd ?
port_handle dd ?
rx_timer dd ?
ends
struct IOCTL
@ -190,8 +183,6 @@ proc START c, .reason:DWORD, .cmdline:DWORD
xor eax, eax ; initialize return value
cmp [.reason], 1 ; compare the argument
jnz .nothing
invoke GetService, serial_driver
mov [serial_drv_entry], eax
invoke RegUSBDriver, my_driver, service_proc, usb_functions
.nothing:
@ -224,10 +215,6 @@ 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
@ -283,15 +270,6 @@ 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
@ -1035,340 +1013,12 @@ endp
proc DeviceDisconnected stdcall uses ebx esi edi, .device_data:DWORD
DEBUGF 1, 'K : FTDI deleting device data 0x%x\n', [.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
mov eax, [.device_data]
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
@ -1379,17 +1029,6 @@ 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

View File

@ -2,17 +2,17 @@
char file_actions[]=
"Žâªàëâì |Enter
Žâªàëâì á ¯®¬®éìî |Ctrl+Ent
Žâªàëâì á ¯®¬®éìî |CrlEnt
-
Š®¯¨à®¢ âì |Ctrl+C
ë१ âì |Ctrl+X
áâ ¢¨âì |Ctrl+V
Š®¯¨à®¢ âì |Crl+C
ë१ âì |Crl+X
áâ ¢¨âì |Crl+V
-
<EFBFBD>¥à¥¨¬¥­®¢ âì |F2
¤ «¨âì |Del
¢®©á⢠ |F1";
char empty_folder_actions[]=
"‚áâ ¢¨âì |Ctrl+V";
"‚áâ ¢¨âì |Crl+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 ... |Ctrl+Ent
Ava ... |CrlEnt
-
Kopeeri |Ctrl+C
Lõika |Ctrl+X
Aseta |Ctrl+V
Kopeeri |Crl+C
Lõika |Crl+X
Aseta |Crl+V
-
Nimeta ümber |F2
Kustuta |Del
Properties |F1";
char empty_folder_actions[]=
"Aseta |Ctrl+V";
"Aseta |Crl+V";
char burger_menu_items[] =
"New window|Ctrl+N
Open console here|Ctrl+G
@ -44,17 +44,17 @@ About";
#else
char file_actions[]=
"Open |Enter
Open with... |Ctrl+Ent
Open with... |CrlEnt
-
Copy |Ctrl+C
Cut |Ctrl+X
Paste |Ctrl+V
Copy |Crl+C
Cut |Crl+X
Paste |Crl+V
-
Rename |F2
Delete |Del
Properties |F1";
char empty_folder_actions[]=
"Paste |Ctrl+V";
"Paste |Crl+V";
char burger_menu_items[] =
"New window|Ctrl+N
Open console here|Ctrl+G

View File

@ -5,12 +5,8 @@
#include "../lib/list_box.h"
#include "../lib/fs.h"
#define ITEM_H 24
#define ITEM_H 19
#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;
@ -47,9 +43,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 * FONT_WIDTH;
max_hotkey_len *= FONT_WIDTH;
if (max_hotkey_len) max_name_len += FONT_WIDTH*2;
max_name_len = max_name_len * 6;
max_hotkey_len *= 6;
if (max_hotkey_len) max_name_len += 12;
}
void GetMenuItems(dword current_name)
@ -112,14 +108,12 @@ void main()
GetMenuItems(#param);
GetMenuWidths();
menu_w = max_name_len + max_hotkey_len + TEXT_MARGIN + TEXT_MARGIN;//23;
menu_w = max_name_len + max_hotkey_len + 23;
menu_h = GetSeparatorsCount() * SEP_H
+ calc(names.count - GetSeparatorsCount() * ITEM_H);
menu1.count = names.count;
// menu1.SetFont(8, 14, 10011000b);
menu1.SetFont(8, 16, 0x80); // TODO what is third par
// menu1.SetFont(6, 9, 0x80);
menu1.SetFont(6, 9, 0x80);
menu1.SetSizes(2,2, menu_w, menu_h, ITEM_H);
menu1.cur_y = -1;
@ -237,17 +231,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(TEXT_MARGIN+1, item_y + menu1.text_y +1, TEXT_FONT_TYPE,
if (!skin_dark) WriteText(13+1, item_y + menu1.text_y +1, 0x80,
inactive_text_shadow_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));
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));
item_y += ITEM_H;
item_i++;
}
}
if (selected) WriteText(5, selected-1*ITEM_H + menu1.y + menu1.text_y, TEXT_FONT_TYPE, 0xEE0000, "\x10"); // ?
if (selected) WriteText(5, selected-1*ITEM_H + menu1.y + menu1.text_y, 0x80, 0xEE0000, "\x10");
}
void click()

View File

@ -842,19 +842,6 @@ 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)

View File

@ -0,0 +1,59 @@
# 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 |

View File

@ -1,18 +0,0 @@
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)

View File

@ -1,25 +0,0 @@
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");

View File

@ -1,34 +0,0 @@
#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;
}

View File

@ -1,29 +0,0 @@
#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

View File

@ -1,11 +0,0 @@
#ifndef COLLISIONBOX_H
#define COLLISIONBOX_H
typedef struct {
int x;
int y;
int width;
int height;
} CollisionBox;
#endif

View File

@ -1,20 +0,0 @@
#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

View File

@ -1,134 +0,0 @@
#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;
}

View File

@ -1,44 +0,0 @@
#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

View File

@ -1,22 +0,0 @@
#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);
}

View File

@ -1,24 +0,0 @@
#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

View File

@ -1,89 +0,0 @@
#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);
}

View File

@ -1,43 +0,0 @@
#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

View File

@ -1,147 +0,0 @@
#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));
}

View File

@ -1,41 +0,0 @@
#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

View File

@ -1,56 +0,0 @@
#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;
}

View File

@ -1,33 +0,0 @@
#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

View File

@ -1,136 +0,0 @@
#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;
}

View File

@ -1,28 +0,0 @@
#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);
}

View File

@ -1,13 +0,0 @@
#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

View File

@ -1,156 +0,0 @@
#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;
}

View File

@ -1,67 +0,0 @@
#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

View File

@ -1,333 +0,0 @@
#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;
}

View File

@ -1,91 +0,0 @@
#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

View File

@ -1,169 +0,0 @@
// 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
};

View File

@ -1,219 +0,0 @@
#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;
}

View File

@ -1,83 +0,0 @@
#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

View File

@ -1,241 +0,0 @@
#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);
}

View File

@ -1,31 +0,0 @@
#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_ */

View File

@ -1,2 +0,0 @@
if tup.getconfig("NO_FASM") ~= "" then return end
tup.rule("charset_checker.asm", "fasm %f %o " .. tup.getconfig("KPACK_CMD"), "charchck")

View File

@ -1,621 +0,0 @@
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: