aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2025-07-07 13:22:53 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2025-07-25 14:16:41 +0200
commit14f60e4fd65c42f126eaee7e09cb4251c167c6ed (patch)
tree313b5e16d7d99cf1518c953e2efe5e5fc920dfbf
parent48a61c16eaa6dcfc75d00dba302537ce1492db98 (diff)
wiptty
-rw-r--r--CMakeLists.txt23
-rw-r--r--cmake/FindWASI_SDK.cmake27
-rw-r--r--cmake/ps1.cmake7
-rw-r--r--programs/CMakeLists.txt32
-rw-r--r--programs/initd/CMakeLists.txt21
-rw-r--r--programs/initd/initd.c24
-rw-r--r--programs/wasi-sdk-toolchain.cmake19
-rw-r--r--programs/yes/CMakeLists.txt21
-rw-r--r--programs/yes/yes.c28
-rw-r--r--res/CMakeLists.txt20
-rw-r--r--src/CMakeLists.txt21
-rw-r--r--src/aio/CMakeLists.txt11
-rw-r--r--src/aio/include/aio.h39
-rw-r--r--src/aio/private_include/aio/types.h34
-rw-r--r--src/aio/src/CMakeLists.txt9
-rw-r--r--src/aio/src/free.c (renamed from src/aio/src/close.c)13
-rw-r--r--src/aio/src/mkdir.c137
-rw-r--r--src/aio/src/mount.c175
-rw-r--r--src/aio/src/open.c102
-rw-r--r--src/aio/src/poll.c74
-rw-r--r--src/aio/src/stat.c118
-rw-r--r--src/aio/src/write.c79
-rw-r--r--src/drv/CMakeLists.txt28
-rw-r--r--src/drv/event/CMakeLists.txt18
-rw-r--r--src/drv/event/include/drv/event.h48
-rw-r--r--src/drv/include/drv/drv.h28
-rw-r--r--src/drv/include/drv/time.h28
-rw-r--r--src/drv/private_include/drv/port.h28
-rw-r--r--src/drv/private_include/drv/tree.h31
-rw-r--r--src/drv/private_include/drv/types.h30
-rw-r--r--src/drv/ps1/CMakeLists.txt33
-rw-r--r--src/drv/ps1/bios/CMakeLists.txt19
-rw-r--r--src/drv/ps1/bios/include/drv/ps1/bios.h112
-rw-r--r--src/drv/ps1/bios/src/CMakeLists.txt29
-rw-r--r--src/drv/ps1/bios/src/CdAsyncGetStatus.s21
-rw-r--r--src/drv/ps1/bios/src/CdAsyncReadSector.s21
-rw-r--r--src/drv/ps1/bios/src/CdAsyncSeekL.s21
-rw-r--r--src/drv/ps1/bios/src/CloseEvent.s21
-rw-r--r--src/drv/ps1/bios/src/DisableEvent.s21
-rw-r--r--src/drv/ps1/bios/src/EnableEvent.s23
-rw-r--r--src/drv/ps1/bios/src/EnterCriticalSection.s25
-rw-r--r--src/drv/ps1/bios/src/ExitCriticalSection.s23
-rw-r--r--src/drv/ps1/bios/src/OpenEvent.s21
-rw-r--r--src/drv/ps1/bios/src/TestEvent.s23
-rw-r--r--src/drv/ps1/bios/src/WaitEvent.s23
-rw-r--r--src/drv/ps1/cd/CMakeLists.txt20
-rw-r--r--src/drv/ps1/cd/include/drv/ps1/cd.h28
-rw-r--r--src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h66
-rw-r--r--src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h37
-rw-r--r--src/drv/ps1/cd/private_include/drv/ps1/cd/types.h122
-rw-r--r--src/drv/ps1/cd/src/CMakeLists.txt29
-rw-r--r--src/drv/ps1/cd/src/ensure_event.c40
-rw-r--r--src/drv/ps1/cd/src/free.c23
-rw-r--r--src/drv/ps1/cd/src/getstat.c65
-rw-r--r--src/drv/ps1/cd/src/init.c42
-rw-r--r--src/drv/ps1/cd/src/next.c38
-rw-r--r--src/drv/ps1/cd/src/prv.c22
-rw-r--r--src/drv/ps1/cd/src/read.c155
-rw-r--r--src/drv/ps1/cd/src/seek.c118
-rw-r--r--src/drv/ps1/cd/src/send.c100
-rw-r--r--src/drv/ps1/cd/src/toseekl.c54
-rw-r--r--src/drv/ps1/cd/src/update.c46
-rw-r--r--src/drv/ps1/cd/src/write.c31
-rw-r--r--src/drv/ps1/dma/CMakeLists.txt18
-rw-r--r--src/drv/ps1/dma/include/drv/ps1/dma.h97
-rw-r--r--src/drv/ps1/gpu/CMakeLists.txt18
-rw-r--r--src/drv/ps1/gpu/include/drv/ps1/gpu.h167
-rw-r--r--src/drv/ps1/include/drv/ps1.h28
-rw-r--r--src/drv/ps1/interrupt/CMakeLists.txt19
-rw-r--r--src/drv/ps1/interrupt/include/drv/ps1/interrupt.h39
-rw-r--r--src/drv/ps1/mc/CMakeLists.txt20
-rw-r--r--src/drv/ps1/mc/include/drv/ps1/mc.h28
-rw-r--r--src/drv/ps1/mc/private_include/drv/ps1/mc/types.h37
-rw-r--r--src/drv/ps1/mc/src/CMakeLists.txt21
-rw-r--r--src/drv/ps1/mc/src/free.c23
-rw-r--r--src/drv/ps1/mc/src/init.c34
-rw-r--r--src/drv/ps1/mc/src/update.c26
-rw-r--r--src/drv/ps1/pad/CMakeLists.txt20
-rw-r--r--src/drv/ps1/pad/include/drv/ps1/pad.h28
-rw-r--r--src/drv/ps1/pad/private_include/drv/ps1/pad/types.h29
-rw-r--r--src/drv/ps1/pad/src/CMakeLists.txt21
-rw-r--r--src/drv/ps1/pad/src/free.c23
-rw-r--r--src/drv/ps1/pad/src/init.c34
-rw-r--r--src/drv/ps1/pad/src/update.c26
-rw-r--r--src/drv/ps1/private_include/drv/ps1/types.h33
-rw-r--r--src/drv/ps1/rcnt/CMakeLists.txt22
-rw-r--r--src/drv/ps1/rcnt/include/drv/ps1/rcnt.h45
-rw-r--r--src/drv/ps1/rcnt/private_include/drv/ps1/rcnt/regs.h36
-rw-r--r--src/drv/ps1/rcnt/src/CMakeLists.txt19
-rw-r--r--src/drv/ps1/rcnt/src/init.c59
-rw-r--r--src/drv/ps1/src/CMakeLists.txt21
-rw-r--r--src/drv/ps1/src/free.c24
-rw-r--r--src/drv/ps1/src/init.c53
-rw-r--r--src/drv/ps1/src/update.c33
-rw-r--r--src/drv/ps1/time/CMakeLists.txt22
-rw-r--r--src/drv/ps1/time/include/drv/ps1/time.h24
-rw-r--r--src/drv/ps1/time/private_include/drv/ps1/time/types.h26
-rw-r--r--src/drv/ps1/time/src/CMakeLists.txt23
-rw-r--r--src/drv/ps1/time/src/getres.c34
-rw-r--r--src/drv/ps1/time/src/gettime.c37
-rw-r--r--src/drv/ps1/time/src/globals.c22
-rw-r--r--src/drv/ps1/time/src/settime.c37
-rw-r--r--src/drv/ps1/time/src/tick.c42
-rw-r--r--src/drv/src/CMakeLists.txt22
-rw-r--r--src/drv/src/free.c31
-rw-r--r--src/drv/src/init.c62
-rw-r--r--src/drv/src/tree.c51
-rw-r--r--src/drv/src/update.c32
-rw-r--r--src/drv/tty/CMakeLists.txt20
-rw-r--r--src/drv/tty/include/drv/tty.h28
-rw-r--r--src/drv/tty/private_include/drv/tty/font.h29
-rw-r--r--src/drv/tty/private_include/drv/tty/ops.h30
-rw-r--r--src/drv/tty/private_include/drv/tty/types.h39
-rw-r--r--src/drv/tty/src/CMakeLists.txt27
-rw-r--r--src/drv/tty/src/free.c39
-rw-r--r--src/drv/tty/src/init.c58
-rw-r--r--src/drv/tty/src/ps1/CMakeLists.txt19
-rw-r--r--src/drv/tty/src/ps1/ttyfont_tim.c705
-rw-r--r--src/drv/tty/src/setdim.c62
-rw-r--r--src/drv/tty/src/update.c104
-rw-r--r--src/drv/tty/src/write.c62
-rw-r--r--src/fs/CMakeLists.txt24
-rw-r--r--src/fs/devfs/CMakeLists.txt20
-rw-r--r--src/fs/devfs/include/devfs.h24
-rw-r--r--src/fs/devfs/private_include/devfs/ops.h48
-rw-r--r--src/fs/devfs/private_include/devfs/types.h44
-rw-r--r--src/fs/devfs/src/CMakeLists.txt34
-rw-r--r--src/fs/devfs/src/close.c26
-rw-r--r--src/fs/devfs/src/flags.c25
-rw-r--r--src/fs/devfs/src/mkdir.c28
-rw-r--r--src/fs/devfs/src/mknod.c54
-rw-r--r--src/fs/devfs/src/mount.c59
-rw-r--r--src/fs/devfs/src/open.c57
-rw-r--r--src/fs/devfs/src/ops.c32
-rw-r--r--src/fs/devfs/src/read.c95
-rw-r--r--src/fs/devfs/src/register.c44
-rw-r--r--src/fs/devfs/src/search.c29
-rw-r--r--src/fs/devfs/src/seek.c98
-rw-r--r--src/fs/devfs/src/stat.c30
-rw-r--r--src/fs/devfs/src/status.c30
-rw-r--r--src/fs/devfs/src/unlink.c26
-rw-r--r--src/fs/devfs/src/update.c27
-rw-r--r--src/fs/devfs/src/write.c95
-rw-r--r--src/fs/include/fs/fs.h159
-rw-r--r--src/fs/include/fs/inode.h79
-rw-r--r--src/fs/iso9660/CMakeLists.txt20
-rw-r--r--src/fs/iso9660/include/iso9660.h24
-rw-r--r--src/fs/iso9660/private_include/iso9660/ops.h39
-rw-r--r--src/fs/iso9660/private_include/iso9660/types.h34
-rw-r--r--src/fs/iso9660/src/CMakeLists.txt28
-rw-r--r--src/fs/iso9660/src/close.c26
-rw-r--r--src/fs/iso9660/src/mkdir.c28
-rw-r--r--src/fs/iso9660/src/mount.c196
-rw-r--r--src/fs/iso9660/src/open.c27
-rw-r--r--src/fs/iso9660/src/read.c27
-rw-r--r--src/fs/iso9660/src/register.c44
-rw-r--r--src/fs/iso9660/src/search.c27
-rw-r--r--src/fs/iso9660/src/seek.c27
-rw-r--r--src/fs/iso9660/src/stat.c28
-rw-r--r--src/fs/iso9660/src/write.c28
-rw-r--r--src/fs/private_include/fs/private.h63
-rw-r--r--src/fs/private_include/fs/types.h55
-rw-r--r--src/fs/ramfs/CMakeLists.txt20
-rw-r--r--src/fs/ramfs/include/ramfs.h43
-rw-r--r--src/fs/ramfs/private_include/ramfs/types.h31
-rw-r--r--src/fs/ramfs/src/CMakeLists.txt29
-rw-r--r--src/fs/ramfs/src/close.c25
-rw-r--r--src/fs/ramfs/src/flags.c25
-rw-r--r--src/fs/ramfs/src/free.c31
-rw-r--r--src/fs/ramfs/src/mkdir.c79
-rw-r--r--src/fs/ramfs/src/mknod.c87
-rw-r--r--src/fs/ramfs/src/mount.c69
-rw-r--r--src/fs/ramfs/src/open.c26
-rw-r--r--src/fs/ramfs/src/read.c26
-rw-r--r--src/fs/ramfs/src/search.c150
-rw-r--r--src/fs/ramfs/src/stat.c52
-rw-r--r--src/fs/ramfs/src/write.c26
-rw-r--r--src/fs/rootfs/CMakeLists.txt20
-rw-r--r--src/fs/rootfs/include/rootfs.h24
-rw-r--r--src/fs/rootfs/private_include/rootfs/ops.h42
-rw-r--r--src/fs/rootfs/private_include/rootfs/types.h32
-rw-r--r--src/fs/rootfs/src/CMakeLists.txt28
-rw-r--r--src/fs/rootfs/src/close.c25
-rw-r--r--src/fs/rootfs/src/flags.c26
-rw-r--r--src/fs/rootfs/src/mkdir.c30
-rw-r--r--src/fs/rootfs/src/mount.c42
-rw-r--r--src/fs/rootfs/src/open.c27
-rw-r--r--src/fs/rootfs/src/read.c26
-rw-r--r--src/fs/rootfs/src/register.c43
-rw-r--r--src/fs/rootfs/src/search.c29
-rw-r--r--src/fs/rootfs/src/stat.c28
-rw-r--r--src/fs/rootfs/src/write.c26
-rw-r--r--src/fs/src/CMakeLists.txt30
-rw-r--r--src/fs/src/from_type.c36
-rw-r--r--src/fs/src/headtail.c22
-rw-r--r--src/fs/src/inode/CMakeLists.txt20
-rw-r--r--src/fs/src/inode/free.c31
-rw-r--r--src/fs/src/inode/search.c121
-rw-r--r--src/fs/src/mountpoint.c60
-rw-r--r--src/fs/src/mp_from_path.c40
-rw-r--r--src/fs/src/mps_from_path.c89
-rw-r--r--src/fs/src/next.c59
-rw-r--r--src/fs/src/parent.c33
-rw-r--r--src/fs/src/register.c42
-rw-r--r--src/fs/src/relpath.c43
-rw-r--r--src/fs/src/update.c30
-rw-r--r--src/gfx/CMakeLists.txt25
-rw-r--r--src/gfx/include/gfx/gfx.h48
-rw-r--r--src/gfx/include/gfx/sprite.h32
-rw-r--r--src/gfx/ps1/CMakeLists.txt40
-rw-r--r--src/gfx/ps1/include/gfx/port.h126
-rw-r--r--src/gfx/ps1/private_include/gfx/private.h19
-rw-r--r--src/gfx/ps1/src/4line.c15
-rw-r--r--src/gfx/ps1/src/CMakeLists.txt32
-rw-r--r--src/gfx/ps1/src/add_to_list.c39
-rw-r--r--src/gfx/ps1/src/deinit.c24
-rw-r--r--src/gfx/ps1/src/draw.c70
-rw-r--r--src/gfx/ps1/src/env.c71
-rw-r--r--src/gfx/ps1/src/heap.c73
-rw-r--r--src/gfx/ps1/src/init.c153
-rw-r--r--src/gfx/ps1/src/quad.c24
-rw-r--r--src/gfx/ps1/src/ready.c27
-rw-r--r--src/gfx/ps1/src/rect.c25
-rw-r--r--src/gfx/ps1/src/sort.c73
-rw-r--r--src/gfx/ps1/src/sprite/CMakeLists.txt22
-rw-r--r--src/gfx/ps1/src/sprite/clone.c26
-rw-r--r--src/gfx/ps1/src/sprite/free.c23
-rw-r--r--src/gfx/ps1/src/sprite/load.c191
-rw-r--r--src/gfx/ps1/src/sprite/sort.c26
-rw-r--r--src/gfx/ps1/src/swapenvs.c58
-rw-r--r--src/gfx/ps1/src/vblank.c21
-rw-r--r--src/gfx/sdl-1.2/CMakeLists.txt19
-rw-r--r--src/gfx/sdl-1.2/include/gfx/port.h58
-rw-r--r--src/gfx/sdl-1.2/private_include/gfx/private.h26
-rw-r--r--src/gfx/sdl-1.2/src/CMakeLists.txt23
-rw-r--r--src/gfx/sdl-1.2/src/env.c204
-rw-r--r--src/gfx/sdl-1.2/src/line.c16
-rw-r--r--src/gfx/sdl-1.2/src/quad.c44
-rw-r--r--src/gfx/sdl-1.2/src/rect.c35
-rw-r--r--src/gfx/sdl-1.2/src/sprite.c143
-rw-r--r--src/gfx/src/CMakeLists.txt19
-rw-r--r--src/gfx/src/dim.c21
-rw-r--r--src/init/CMakeLists.txt34
-rw-r--r--src/init/include/init.h27
-rw-r--r--src/init/private_include/init/port.h25
-rw-r--r--src/init/private_include/init/types.h37
-rw-r--r--src/init/ps1/CMakeLists.txt33
-rw-r--r--src/init/ps1/private_include/init/ps1/types.h37
-rw-r--r--src/init/ps1/src/CMakeLists.txt22
-rw-r--r--src/init/ps1/src/boot.c188
-rw-r--r--src/init/ps1/src/globalvars.c21
-rw-r--r--src/init/ps1/src/run.c27
-rw-r--r--src/init/ps1/src/time.c47
-rw-r--r--src/init/src/CMakeLists.txt22
-rw-r--r--src/init/src/boot.c121
-rw-r--r--src/init/src/run.c27
-rw-r--r--src/init/src/vars.c21
-rw-r--r--src/init/src/vfs.c86
-rw-r--r--src/io/CMakeLists.txt20
-rw-r--r--src/io/include/io.h28
-rw-r--r--src/io/src/CMakeLists.txt5
-rw-r--r--src/io/src/mkdir.c40
-rw-r--r--src/io/src/mount.c35
-rw-r--r--src/io/src/write.c27
-rw-r--r--src/kprintf/CMakeLists.txt20
-rw-r--r--src/kprintf/include/kprintf.h24
-rw-r--r--src/kprintf/src/CMakeLists.txt17
-rw-r--r--src/kprintf/src/kprintf.c96
-rw-r--r--src/libc/CMakeLists.txt23
-rw-r--r--src/libc/include/errno.h119
-rw-r--r--src/libc/include/fcntl.h29
-rw-r--r--src/libc/include/inttypes.h34
-rw-r--r--src/libc/include/stdint.h33
-rw-r--r--src/libc/include/stdio.h15
-rw-r--r--src/libc/include/stdlib.h6
-rw-r--r--src/libc/include/string.h23
-rw-r--r--src/libc/include/sys/stat.h40
-rw-r--r--src/libc/include/sys/types.h25
-rw-r--r--src/libc/include/time.h39
-rw-r--r--src/libc/private_include/libc/file.h3
-rw-r--r--src/libc/private_include/libc/malloc.h24
-rw-r--r--src/libc/src/CMakeLists.txt40
-rw-r--r--src/libc/src/abort.c28
-rw-r--r--src/libc/src/calloc.c32
-rw-r--r--src/libc/src/clock_getres.c25
-rw-r--r--src/libc/src/clock_gettime.c25
-rw-r--r--src/libc/src/clock_settime.c25
-rw-r--r--src/libc/src/free.c8
-rw-r--r--src/libc/src/malloc.c29
-rw-r--r--src/libc/src/memset.c18
-rw-r--r--src/libc/src/mkdir.c37
-rw-r--r--src/libc/src/ps1/CMakeLists.txt17
-rw-r--r--src/libc/src/ps1/putchar.c29
-rw-r--r--src/libc/src/puts.c28
-rw-r--r--src/libc/src/realloc.c25
-rw-r--r--src/libc/src/strcmp.c27
-rw-r--r--src/libc/src/strdup.c32
-rw-r--r--src/libc/src/strerror.c100
-rw-r--r--src/libc/src/strncmp.c29
-rw-r--r--src/libc/src/strndup.c32
-rw-r--r--src/libc/src/strrchr.c31
-rw-r--r--src/libc/src/ta_init.c21
-rw-r--r--src/loop/CMakeLists.txt20
-rw-r--r--src/loop/include/loop.h28
-rw-r--r--src/loop/private_include/loop/types.h26
-rw-r--r--src/loop/src/CMakeLists.txt21
-rw-r--r--src/loop/src/add_aio.c43
-rw-r--r--src/loop/src/rm_aio.c48
-rw-r--r--src/loop/src/run.c33
-rw-r--r--src/main.c32
-rw-r--r--src/ps1/CMakeLists.txt22
-rw-r--r--src/ps1/playstation.x2
-rw-r--r--src/ps1/start.c2
-rw-r--r--src/ps1/system.cnf8
-rw-r--r--src/state/CMakeLists.txt18
-rw-r--r--src/state/include/state.h29
316 files changed, 13511 insertions, 114 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9820c84..746b1bf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-# wanix, a Unix-like operating system for WebAssembly
+# wanix, a Unix-like operating system for WebAssembly applications.
# Copyright (C) 2025 Xavier Del Campo Romero
#
# This program is free software: you can redistribute it and/or modify
@@ -24,10 +24,11 @@ ExternalProject_Add(tools
CMAKE_ARGS
-D CMAKE_INSTALL_PREFIX=${TOOLS_PREFIX})
-project(wanix C)
+project(wanix C ASM)
+option(WANIX_BUILD_PROGRAMS "Build userspace programs" ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
-add_compile_options(-mno-gpopt)
+add_compile_options(-mno-gpopt -ffunction-sections -fdata-sections)
if(CMAKE_TOOLCHAIN_FILE MATCHES "ps1")
set(PS1_BUILD 1)
@@ -40,7 +41,7 @@ else()
set(SDL1_2_BUILD 1)
endif()
-add_executable(${PROJECT_NAME} ${exec_flags} "src/main.c")
+add_executable(${PROJECT_NAME} ${exec_flags} src/main.c)
if(SDL1_2_BUILD)
find_package(SDL 1.2 REQUIRED)
@@ -62,12 +63,16 @@ set(cdroot ${CMAKE_BINARY_DIR}/cdimg)
file(MAKE_DIRECTORY ${cdroot})
if(PS1_BUILD)
- include("cmake/ps1.cmake")
+ include(cmake/ps1.cmake)
elseif(WIN9X_BUILD)
- include("cmake/win9x.cmake")
+ include(cmake/win9x.cmake)
elseif(HOST_BUILD)
- include("cmake/host.cmake")
+ include(cmake/host.cmake)
endif()
-add_subdirectory("res")
-add_subdirectory("src")
+add_subdirectory(res)
+add_subdirectory(src)
+
+if(WANIX_BUILD_PROGRAMS)
+ add_subdirectory(programs)
+endif()
diff --git a/cmake/FindWASI_SDK.cmake b/cmake/FindWASI_SDK.cmake
new file mode 100644
index 0000000..037aca6
--- /dev/null
+++ b/cmake/FindWASI_SDK.cmake
@@ -0,0 +1,27 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+find_program(WASI_SDK_CLANG
+ clang
+ PATHS
+ /opt/wasi-sdk/bin
+ ENV WASI_SDK_PATH
+)
+
+include(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(WASI_SDK
+ REQUIRED_VARS WASI_SDK_CLANG)
diff --git a/cmake/ps1.cmake b/cmake/ps1.cmake
index 21d77fa..83bdad7 100644
--- a/cmake/ps1.cmake
+++ b/cmake/ps1.cmake
@@ -29,15 +29,8 @@ set(license $ENV{PSXSDK_PATH}/share/licenses/info${region}.dat)
add_custom_target(bin_cue ALL mkpsxiso ${PROJECT_NAME}.iso ${PROJECT_NAME}.bin
${license} -s DEPENDS iso)
-if(NOT EXISTS "${cdroot}/system.cnf")
- file(COPY "src/ps1/system.cnf" DESTINATION "${cdroot}")
-endif()
-
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(cflags ${cflags} -Og)
else()
set(cflags ${cflags} -Os)
endif()
-
-set(cflags ${cflags} -fshort-enums)
-# libfixmath is already bundled with PSXSDK.
diff --git a/programs/CMakeLists.txt b/programs/CMakeLists.txt
new file mode 100644
index 0000000..36ab64b
--- /dev/null
+++ b/programs/CMakeLists.txt
@@ -0,0 +1,32 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set(programs
+ initd
+ yes
+)
+
+include(ExternalProject)
+
+foreach(p ${programs})
+ ExternalProject_Add(${p}_project
+ SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/${p}
+ CMAKE_ARGS
+ -D CMAKE_TOOLCHAIN_FILE=${CMAKE_CURRENT_LIST_DIR}/wasi-sdk-toolchain.cmake
+ -D CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}
+ -D CMAKE_INSTALL_PREFIX=${cdroot}
+ )
+endforeach()
diff --git a/programs/initd/CMakeLists.txt b/programs/initd/CMakeLists.txt
new file mode 100644
index 0000000..39e19f5
--- /dev/null
+++ b/programs/initd/CMakeLists.txt
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+cmake_minimum_required(VERSION 3.13)
+include(GNUInstallDirs)
+project(initd C)
+add_executable(${PROJECT_NAME} initd.c)
+install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/programs/initd/initd.c b/programs/initd/initd.c
new file mode 100644
index 0000000..63685df
--- /dev/null
+++ b/programs/initd/initd.c
@@ -0,0 +1,24 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+int main(void)
+{
+ return EXIT_FAILURE;
+}
diff --git a/programs/wasi-sdk-toolchain.cmake b/programs/wasi-sdk-toolchain.cmake
new file mode 100644
index 0000000..d29eedd
--- /dev/null
+++ b/programs/wasi-sdk-toolchain.cmake
@@ -0,0 +1,19 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+find_package(WASI_SDK REQUIRED)
+set(CMAKE_C_COMPILER ${WASI_SDK_CLANG})
+set(CMAKE_C_COMPILER_WORKS 1)
diff --git a/programs/yes/CMakeLists.txt b/programs/yes/CMakeLists.txt
new file mode 100644
index 0000000..18c6e22
--- /dev/null
+++ b/programs/yes/CMakeLists.txt
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+cmake_minimum_required(VERSION 3.13)
+include(GNUInstallDirs)
+project(yes C)
+add_executable(${PROJECT_NAME} yes.c)
+install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/programs/yes/yes.c b/programs/yes/yes.c
new file mode 100644
index 0000000..4bd5cf4
--- /dev/null
+++ b/programs/yes/yes.c
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(void)
+{
+ for (;;)
+ puts("y");
+
+ return EXIT_SUCCESS;
+}
diff --git a/res/CMakeLists.txt b/res/CMakeLists.txt
index 8fb119e..b981ac2 100644
--- a/res/CMakeLists.txt
+++ b/res/CMakeLists.txt
@@ -1,10 +1,26 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
include(${CMAKE_CURRENT_LIST_DIR}/functions.cmake)
sprite(NAME font
- X 472
+ X 640
Y 0
BPP 4
- CX 368
+ CX 640
CY 498
TRANSPARENT TRUE)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0f28e58..2eff797 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-# wanix, a Unix-like operating system for WebAssembly
+# wanix, a Unix-like operating system for WebAssembly applications.
# Copyright (C) 2025 Xavier Del Campo Romero
#
# This program is free software: you can redistribute it and/or modify
@@ -15,16 +15,25 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
add_subdirectory(nanowasm)
+add_subdirectory(dynstr)
target_link_libraries(${PROJECT_NAME} PRIVATE nanowasm)
# Avoid C11 since it is not supported by the i386-mingw32 toolchain.
-set(cflags ${cflags} -Wall -ffunction-sections -fdata-sections -pedantic)
+set(cflags ${cflags} -Wall -pedantic)
set(components
aio
+ drv
+ fs
+ gfx
+ init
+ io
+ kprintf
+ loop
)
set(interfaces
+ state
)
if(PS1_BUILD)
@@ -35,10 +44,10 @@ endif()
target_compile_options(${PROJECT_NAME} PUBLIC ${cflags})
target_compile_options(nanowasm PUBLIC ${cflags})
# Dependencies for main.c
-# target_link_libraries(${PROJECT_NAME} PRIVATE)
+target_link_libraries(${PROJECT_NAME} PRIVATE gfx init loop)
foreach(c ${components})
- add_subdirectory("${c}")
+ add_subdirectory(${c})
target_compile_options(${c} PUBLIC ${cflags})
target_compile_features(${c} PUBLIC c_std_99)
set_target_properties(${c} PROPERTIES C_STANDARD 99 C_EXTENSIONS OFF)
@@ -50,9 +59,9 @@ foreach(c ${components})
endforeach()
foreach(i ${interfaces})
- add_subdirectory("${i}")
+ add_subdirectory(${i})
target_compile_options(${i} INTERFACE ${cflags})
- target_link_libraries(${PROJECT_NAME} PRIVATE ${c})
+ target_link_libraries(${i} INTERFACE ${c})
endforeach()
target_link_options(${PROJECT_NAME} PRIVATE -Wl,--gc-sections)
diff --git a/src/aio/CMakeLists.txt b/src/aio/CMakeLists.txt
index 3f4561a..a335457 100644
--- a/src/aio/CMakeLists.txt
+++ b/src/aio/CMakeLists.txt
@@ -1,6 +1,11 @@
set(src
- "src/close.c"
- "src/open.c"
+ src/free.c
+ src/mkdir.c
+ src/mount.c
+ src/open.c
+ src/poll.c
)
add_library(aio ${src})
-target_include_directories(aio PUBLIC "include" PRIVATE "private_include")
+add_subdirectory(src)
+target_include_directories(aio PUBLIC include PRIVATE private_include)
+target_link_libraries(aio PUBLIC fs INTERFACE state)
diff --git a/src/aio/include/aio.h b/src/aio/include/aio.h
index f9f76cb..cea6ee1 100644
--- a/src/aio/include/aio.h
+++ b/src/aio/include/aio.h
@@ -1,5 +1,5 @@
/*
- * wanix, a Unix-like operating system for WebAssembly
+ * wanix, a Unix-like operating system for WebAssembly applications.
* Copyright (C) 2025 Xavier Del Campo Romero
*
* This program is free software: you can redistribute it and/or modify
@@ -19,17 +19,40 @@
#ifndef AIO_H
#define AIO_H
+#include <fs/fs.h>
+#include <sys/types.h>
+#include <state.h>
+#include <stdbool.h>
#include <stddef.h>
-enum
+struct aio_poll
{
- AIO_POLLIN = 1,
- AIO_POLLOUT = 1 << 1
+ const struct aio *aio;
+ bool done;
+ int error;
+ struct aio_poll *prev, *next;
};
-struct aio *aio_open(const char *path, const char *mode);
-int aio_poll(struct aio **io, size_t n);
-int aio_event(const struct aio *io, int ev);
-int aio_close(struct aio *io);
+struct aio_done
+{
+ int (*f)(enum state state, void *args);
+ void *args;
+};
+
+struct aio_mount
+{
+ struct fs_mount mount;
+ const char *type;
+};
+
+struct aio *aio_mount(const struct aio_mount *m, const struct aio_done *d);
+struct aio *aio_mkdir(const struct fs_mkdir *m, const struct aio_done *d);
+struct aio *aio_open(const struct fs_open *o, const struct aio_done *d);
+struct aio *aio_read(const struct fs_read *r, const struct aio_done *d);
+struct aio *aio_write(const struct fs_write *w, const struct aio_done *d);
+struct aio *aio_close(const struct fs_close *c, const struct aio_done *d);
+struct aio *aio_stat(const struct fs_stat *s, const struct aio_done *d);
+int aio_poll(struct aio_poll *p, int ms);
+void aio_free(struct aio *io);
#endif
diff --git a/src/aio/private_include/aio/types.h b/src/aio/private_include/aio/types.h
index 31ee414..32a7545 100644
--- a/src/aio/private_include/aio/types.h
+++ b/src/aio/private_include/aio/types.h
@@ -1,16 +1,32 @@
-#ifndef AIO_PRV_OPEN_H
-#define AIO_PRV_OPEN_H
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
-enum aio_state
-{
- AIO_OK,
- AIO_AGAIN,
- AIO_FATAL
-};
+#ifndef AIO_TYPES_H
+#define AIO_TYPES_H
+
+#include <aio.h>
+#include <fs/fs.h>
struct aio
{
- enum aio_state (*next)(struct aio *);
+ int error;
+ struct fs_ret r;
+ struct aio_done done;
};
#endif
diff --git a/src/aio/src/CMakeLists.txt b/src/aio/src/CMakeLists.txt
new file mode 100644
index 0000000..8848842
--- /dev/null
+++ b/src/aio/src/CMakeLists.txt
@@ -0,0 +1,9 @@
+target_sources(aio PRIVATE
+ free.c
+ mkdir.c
+ mount.c
+ open.c
+ poll.c
+ stat.c
+ write.c
+)
diff --git a/src/aio/src/close.c b/src/aio/src/free.c
index a6067a8..3a84f1b 100644
--- a/src/aio/src/close.c
+++ b/src/aio/src/free.c
@@ -1,5 +1,5 @@
/*
- * wanix, a Unix-like operating system for WebAssembly
+ * wanix, a Unix-like operating system for WebAssembly applications.
* Copyright (C) 2025 Xavier Del Campo Romero
*
* This program is free software: you can redistribute it and/or modify
@@ -17,18 +17,9 @@
*/
#include <aio.h>
-#include <errno.h>
-#include <stdio.h>
#include <stdlib.h>
-int aio_close(struct aio *const aio)
+void aio_free(struct aio *const aio)
{
- if (!aio)
- {
- errno = EINVAL;
- return EOF;
- }
-
free(aio);
- return 0;
}
diff --git a/src/aio/src/mkdir.c b/src/aio/src/mkdir.c
new file mode 100644
index 0000000..3a7fae6
--- /dev/null
+++ b/src/aio/src/mkdir.c
@@ -0,0 +1,137 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <aio.h>
+#include <aio/types.h>
+#include <fs/fs.h>
+#include <fs/inode.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct mkdir
+{
+ struct fs_mkdir mkdir;
+ struct aio_done done;
+ char *path, *parent;
+ struct aio *aio;
+};
+
+static void free_mkdir(struct mkdir *const mk)
+{
+ if (mk)
+ {
+ free(mk->path);
+ free(mk->parent);
+ }
+
+ free(mk);
+}
+
+static int done(const enum state state, void *const args)
+{
+ int ret = 0;
+ struct mkdir *const mk = args;
+ const struct aio_done *const d = &mk->done;
+
+ if (d->f)
+ ret = d->f(state, d->args);
+
+ free_mkdir(mk);
+ return ret;
+}
+
+static int search_done(const enum state state,
+ const char *const relpath, const struct fs_mp *const mp,
+ const union inode_result *const inode, void *const args)
+{
+ struct mkdir *const mk = args;
+ struct aio *const aio = mk->aio;
+ const struct fs *const fs = mp->fs;
+ const char *path = mk->path;
+ struct fs_ret r;
+
+ path += strlen(mp->tgt) + strlen(relpath);
+ mk->mkdir.path = path;
+
+ if (fs->mkdir(&mk->mkdir, mp, inode, &r))
+ goto failure;
+
+ aio->r = r;
+ return 0;
+
+failure:
+ aio->error = errno;
+ aio->done = mk->done;
+ free_mkdir(mk);
+ return -1;
+}
+
+struct aio *aio_mkdir(const struct fs_mkdir *const m,
+ const struct aio_done *const d)
+{
+ struct aio *aio = NULL;
+ struct mkdir *mk = NULL;
+ char *const pathdup = strdup(m->path), *parent = NULL;
+
+ if (!pathdup
+ || !(parent = fs_parent(m->path))
+ || !(mk = malloc(sizeof *mk))
+ || !(aio = malloc(sizeof *aio)))
+ goto failure;
+
+ *mk = (const struct mkdir)
+ {
+ .path = pathdup,
+ .parent = parent,
+ .aio = aio,
+ .mkdir = *m
+ };
+
+ *aio = (const struct aio)
+ {
+ .done =
+ {
+ .args = mk,
+ .f = done
+ }
+ };
+
+ const struct inode_search s =
+ {
+ .path = parent,
+ .done = search_done,
+ .args = mk
+ };
+
+ if (d)
+ mk->done = *d;
+ else if (inode_search(&s, &aio->r))
+ goto failure;
+
+ return aio;
+
+failure:
+ free(mk);
+ free(aio);
+ free(parent);
+ free(pathdup);
+ return NULL;
+}
diff --git a/src/aio/src/mount.c b/src/aio/src/mount.c
new file mode 100644
index 0000000..e90d8de
--- /dev/null
+++ b/src/aio/src/mount.c
@@ -0,0 +1,175 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <aio.h>
+#include <aio/types.h>
+#include <fs/fs.h>
+#include <fs/inode.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct mount
+{
+ char *src, *tgt;
+ struct aio *aio;
+ const struct fs *fs;
+ struct fs_mount mount;
+ struct aio_done done;
+};
+
+static void free_mount(struct mount *const m)
+{
+ if (m)
+ {
+ free(m->src);
+ free(m->tgt);
+ }
+
+ free(m);
+}
+
+static int done(const enum state state, void *const args)
+{
+ int ret = 0;
+ struct mount *const m = args;
+ const struct aio_done *const d = &m->done;
+
+ if (d->f)
+ ret = d->f(state, d->args);
+
+ free_mount(m);
+ return ret;
+}
+
+static int search_done(const enum state s, const char *const relpath,
+ const struct fs_mp *const mp, const union inode_result *const inode,
+ void *const args)
+{
+ struct mount *const m = args;
+ struct aio *const aio = m->aio;
+ const struct fs *const fs = m->fs;
+
+ if (strcmp(m->tgt, "/"))
+ {
+ if (!inode)
+ {
+ aio->error = ENOENT;
+ goto failure;
+ }
+ else if (mp->fs->iops.flags(inode) & INODE_MOUNTPOINT)
+ {
+ aio->error = EBUSY;
+ goto failure;
+ }
+ }
+
+ if (fs->mount(&m->mount, &aio->r))
+ {
+ aio->error = errno;
+ goto failure;
+ }
+
+ return 0;
+
+failure:
+ aio->done = m->done;
+ free_mount(m);
+ return -1;
+}
+
+struct aio *aio_mount(const struct aio_mount *const am,
+ const struct aio_done *const d)
+{
+ struct aio *aio = NULL;
+ const struct fs_mount *const m = &am->mount;
+ const struct fs *const fs = fs_from_type(am->type);
+ char *srcdup = NULL, *tgtdup = NULL;
+ struct mount *pm = NULL;
+ struct fs_mp mp;
+
+ if (!fs)
+ {
+ errno = ENODEV;
+ goto failure;
+ }
+ else if (!m->src && fs->flags & FS_DEV_REQUIRED)
+ {
+ errno = ENOTBLK;
+ goto failure;
+ }
+ else if (!fs_mp_from_path(m->tgt, &mp)
+ && m->src && !strcmp(mp.src, m->src))
+ {
+ errno = EBUSY;
+ goto failure;
+ }
+ else if ((m->src && !(srcdup = strdup(m->src)))
+ || !(tgtdup = strdup(m->tgt))
+ || !(pm = malloc(sizeof *pm))
+ || !(aio = malloc(sizeof *aio)))
+ goto failure;
+
+ const struct inode_search s =
+ {
+ .path = m->tgt,
+ .done = search_done,
+ .args = pm
+ };
+
+ *pm = (const struct mount)
+ {
+ .aio = aio,
+ .src = srcdup,
+ .tgt = tgtdup,
+ .fs = fs,
+ .mount =
+ {
+ .src = srcdup,
+ .tgt = tgtdup,
+ .mode = m->mode,
+ .gid = m->gid,
+ .uid = m->uid
+ }
+ };
+
+ *aio = (const struct aio)
+ {
+ .done =
+ {
+ .f = done,
+ .args = pm
+ }
+ };
+
+ if (inode_search(&s, &aio->r))
+ goto failure;
+
+ if (d)
+ pm->done = *d;
+
+ return aio;
+
+failure:
+ free(tgtdup);
+ free(srcdup);
+ free(pm);
+ free(aio);
+ return NULL;
+}
diff --git a/src/aio/src/open.c b/src/aio/src/open.c
index 89fbbba..f3a84da 100644
--- a/src/aio/src/open.c
+++ b/src/aio/src/open.c
@@ -1,5 +1,5 @@
/*
- * wanix, a Unix-like operating system for WebAssembly
+ * wanix, a Unix-like operating system for WebAssembly applications.
* Copyright (C) 2025 Xavier Del Campo Romero
*
* This program is free software: you can redistribute it and/or modify
@@ -16,18 +16,110 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include <aio.h>
+#include <fs/fs.h>
#include <aio/types.h>
+#include <state.h>
+#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
-struct aio *aio_open(const char *const path, const char *const mode)
+struct open
{
- struct aio *const ret = malloc(sizeof *ret);
+ struct aio *aio;
+ struct fs_open open;
+ struct aio_done done;
+};
- if (!ret)
+static int done(const enum state s, void *const args)
+{
+ struct open *const o = args;
+
+ if (o->done.f)
+ o->done.f(s, o->done.args);
+
+ free(o);
+ return 0;
+}
+
+static enum state open_done(void *const args)
+{
+ return STATE_OK;
+}
+
+static int search_done(const enum state state, const char *const relpath,
+ const struct fs_mp *const mp, const union inode_result *const inode,
+ void *const args)
+{
+ struct open *const o = args;
+ struct aio *const aio = o->aio;
+ const struct fs *const fs = mp->fs;
+
+ if (!inode)
+ {
+ aio->error = ENOENT;
+ goto failure;
+ }
+
+ aio->r = (const struct fs_ret)
+ {
+ .f = open_done,
+ .args = o
+ };
+
+ if (fs->open(&o->open, mp, inode, &aio->r))
+ {
+ aio->error = errno;
+ goto failure;
+ }
+
+ return 0;
+
+failure:
+ aio->done = o->done;
+ return -1;
+}
+
+struct aio *aio_open(const struct fs_open *const op,
+ const struct aio_done *const d)
+{
+ struct aio *aio = NULL;
+ struct open *const o = malloc(sizeof *o);
+
+ if (!o || !(aio = malloc(sizeof *aio)))
goto failure;
+ *o = (const struct open)
+ {
+ .aio = aio,
+ .open = *op
+ };
+
+ *aio = (const struct aio)
+ {
+ .done =
+ {
+ .f = done,
+ .args = o
+ }
+ };
+
+ const struct inode_search s =
+ {
+ .path = op->path,
+ .done = search_done,
+ .args = o
+ };
+
+ if (inode_search(&s, &aio->r))
+ goto failure;
+
+ if (d)
+ o->done = *d;
+
+ return aio;
+
failure:
- free(ret);
+ free(aio);
return NULL;
}
diff --git a/src/aio/src/poll.c b/src/aio/src/poll.c
new file mode 100644
index 0000000..615f2de
--- /dev/null
+++ b/src/aio/src/poll.c
@@ -0,0 +1,74 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <aio.h>
+#include <aio/types.h>
+#include <state.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <time.h>
+
+int aio_poll(struct aio_poll *const poll, int ms)
+{
+ struct timespec init;
+
+ if (ms > 0 && clock_gettime(CLOCK_REALTIME, &init))
+ return -1;
+
+ do
+ {
+ for (struct aio_poll *p = poll; p; p = p->next)
+ {
+ const struct aio *const aio = p->aio;
+ const struct fs_ret *const r = &aio->r;
+ const enum state s = r->f(r->args);
+
+ switch (s)
+ {
+ case STATE_AGAIN:
+ break;
+
+ case STATE_FATAL:
+ p->error = aio->error;
+ /* Fall through */
+ case STATE_OK:
+ {
+ const struct aio_done *const d = &aio->done;
+
+ if (d->f)
+ return d->f(s, d->args) ? -1 : 1;
+
+ p->done = true;
+ return 1;
+ }
+ }
+ }
+
+ if (ms > 0)
+ {
+ struct timespec after;
+
+ if (clock_gettime(CLOCK_REALTIME, &after))
+ return -1;
+
+ /* TODO */
+ }
+ } while (ms);
+
+ return 0;
+}
diff --git a/src/aio/src/stat.c b/src/aio/src/stat.c
new file mode 100644
index 0000000..9a7df76
--- /dev/null
+++ b/src/aio/src/stat.c
@@ -0,0 +1,118 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <aio.h>
+#include <aio/types.h>
+#include <fs/fs.h>
+#include <fs/inode.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct stat_prv
+{
+ struct fs_stat stat;
+ struct aio_done done;
+ struct aio *aio;
+};
+
+static int done(const enum state state, void *const args)
+{
+ int ret = 0;
+ struct stat_prv *const p = args;
+ const struct aio_done *const d = &p->done;
+
+ if (d->f)
+ ret = d->f(state, d->args);
+
+ free(p);
+ return ret;
+}
+
+static int search_done(const enum state s, const char *const relpath,
+ const struct fs_mp *const mp, const union inode_result *const inode,
+ void *const args)
+{
+ struct stat_prv *const p = args;
+ struct aio *const aio = p->aio;
+ const struct fs *const fs = mp->fs;
+
+ if (!inode)
+ {
+ aio->error = ENOENT;
+ goto failure;
+ }
+ else if (fs->stat(&p->stat, mp, inode, &aio->r))
+ {
+ aio->error = errno;
+ goto failure;
+ }
+
+ return 0;
+
+failure:
+ aio->done = p->done;
+ free(p);
+ return -1;
+}
+
+struct aio *aio_stat(const struct fs_stat *const as,
+ const struct aio_done *const d)
+{
+ struct aio *const aio = malloc(sizeof *aio);
+ struct stat_prv *const p = malloc(sizeof *p);
+
+ if (!p || !aio)
+ goto failure;
+
+ const struct inode_search s =
+ {
+ .path = as->path,
+ .done = search_done,
+ .args = p
+ };
+
+ *p = (const struct stat_prv)
+ {
+ .aio = aio,
+ .stat = *as
+ };
+
+ *aio = (const struct aio)
+ {
+ .done =
+ {
+ .f = done,
+ .args = p
+ }
+ };
+
+ if (inode_search(&s, &aio->r))
+ goto failure;
+
+ if (d)
+ p->done = *d;
+
+ return aio;
+
+failure:
+ free(p);
+ free(aio);
+ return NULL;
+}
diff --git a/src/aio/src/write.c b/src/aio/src/write.c
new file mode 100644
index 0000000..116629f
--- /dev/null
+++ b/src/aio/src/write.c
@@ -0,0 +1,79 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <aio.h>
+#include <fs/fs.h>
+#include <aio/types.h>
+#include <state.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+struct write
+{
+ struct aio *aio;
+ struct aio_done done;
+};
+
+static int done(const enum state s, void *const args)
+{
+ struct write *const w = args;
+
+ free(w);
+ return 0;
+}
+
+static enum state write_done(void *const args)
+{
+ return STATE_OK;
+}
+
+struct aio *aio_write(const struct fs_write *const fw,
+ const struct aio_done *const d)
+{
+ struct aio *aio = NULL;
+ struct write *const w = malloc(sizeof *w);
+ struct fs_fd *const fd = fw->fd;
+ const struct fs *const fs = fd->mp->fs;
+
+ if (!w || !(aio = malloc(sizeof *aio)))
+ goto failure;
+
+ *aio = (const struct aio)
+ {
+ .done =
+ {
+ .f = done,
+ .args = w
+ }
+ };
+
+ aio->r = (const struct fs_ret){.f = write_done};
+
+ if (fs->write(fw, &aio->r))
+ goto failure;
+
+ if (d)
+ w->done = *d;
+
+ return aio;
+
+failure:
+ free(w);
+ free(aio);
+ return NULL;
+}
diff --git a/src/drv/CMakeLists.txt b/src/drv/CMakeLists.txt
new file mode 100644
index 0000000..021d556
--- /dev/null
+++ b/src/drv/CMakeLists.txt
@@ -0,0 +1,28 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv)
+add_subdirectory(event)
+add_subdirectory(tty)
+add_subdirectory(src)
+target_include_directories(drv PUBLIC include PRIVATE private_include)
+target_link_libraries(drv PUBLIC drv_event PRIVATE drv_tty)
+
+if(PS1_BUILD)
+ add_subdirectory(ps1)
+ target_compile_definitions(drv PRIVATE DRV_PS1)
+ target_link_libraries(drv PUBLIC drv_ps1_time PRIVATE drv_ps1)
+endif()
diff --git a/src/drv/event/CMakeLists.txt b/src/drv/event/CMakeLists.txt
new file mode 100644
index 0000000..e020f0e
--- /dev/null
+++ b/src/drv/event/CMakeLists.txt
@@ -0,0 +1,18 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv_event INTERFACE)
+target_include_directories(drv_event INTERFACE include)
diff --git a/src/drv/event/include/drv/event.h b/src/drv/event/include/drv/event.h
new file mode 100644
index 0000000..f5ee12c
--- /dev/null
+++ b/src/drv/event/include/drv/event.h
@@ -0,0 +1,48 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_EVENT_H
+#define DRV_EVENT_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+struct drv_event_done
+{
+ int (*f)(int error, void *args);
+ void *args;
+};
+
+struct drv_event_ops
+{
+ int (*read)(void *buf, size_t n, const struct drv_event_done *done,
+ void *args);
+ int (*write)(const void *buf, size_t n, const struct drv_event_done *done,
+ void *args);
+ int (*seek)(long offset, const struct drv_event_done *done, void *args);
+ void *args;
+};
+
+struct drv_event
+{
+ int (*status)(const char *node, const struct drv_event_ops *ops,
+ bool available, void *args);
+ void *args;
+};
+
+#endif
diff --git a/src/drv/include/drv/drv.h b/src/drv/include/drv/drv.h
new file mode 100644
index 0000000..6c7b57e
--- /dev/null
+++ b/src/drv/include/drv/drv.h
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_H
+#define DRV_H
+
+#include <drv/event.h>
+
+struct drv *drv_init(const struct drv_event *ev);
+int drv_update(struct drv *d);
+void drv_free(struct drv *d);
+
+#endif
diff --git a/src/drv/include/drv/time.h b/src/drv/include/drv/time.h
new file mode 100644
index 0000000..ac721a4
--- /dev/null
+++ b/src/drv/include/drv/time.h
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_TIME_H
+#define DRV_TIME_H
+
+#include <time.h>
+
+int drv_time_getres(clockid_t id, struct timespec *ts);
+int drv_time_gettime(clockid_t id, struct timespec *ts);
+int drv_time_settime(clockid_t id, const struct timespec *ts);
+
+#endif
diff --git a/src/drv/private_include/drv/port.h b/src/drv/private_include/drv/port.h
new file mode 100644
index 0000000..fde2a4b
--- /dev/null
+++ b/src/drv/private_include/drv/port.h
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PORT_H
+#define DRV_PORT_H
+
+struct drv_port;
+
+#ifdef DRV_PS1
+#include <drv/ps1.h>
+#endif
+
+#endif
diff --git a/src/drv/private_include/drv/tree.h b/src/drv/private_include/drv/tree.h
new file mode 100644
index 0000000..4dd21a6
--- /dev/null
+++ b/src/drv/private_include/drv/tree.h
@@ -0,0 +1,31 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_TREE_H
+#define DRV_TREE_H
+
+#include <drv/drv.h>
+#include <drv/port.h>
+#include <stddef.h>
+
+extern struct drv_port *(*const drv_tree_init[])(const struct drv_event *);
+extern int (*const drv_tree_update[])(struct drv_port *);
+extern void (*const drv_tree_free[])(struct drv_port *);
+extern const size_t drv_tree_n;
+
+#endif
diff --git a/src/drv/private_include/drv/types.h b/src/drv/private_include/drv/types.h
new file mode 100644
index 0000000..a3a51f2
--- /dev/null
+++ b/src/drv/private_include/drv/types.h
@@ -0,0 +1,30 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_TYPES_H
+#define DRV_TYPES_H
+
+#include <stddef.h>
+
+struct drv
+{
+ struct drv_port **ports;
+ size_t n;
+};
+
+#endif
diff --git a/src/drv/ps1/CMakeLists.txt b/src/drv/ps1/CMakeLists.txt
new file mode 100644
index 0000000..9e408de
--- /dev/null
+++ b/src/drv/ps1/CMakeLists.txt
@@ -0,0 +1,33 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_subdirectory(bios)
+add_subdirectory(cd)
+add_subdirectory(dma)
+add_subdirectory(gpu)
+add_subdirectory(interrupt)
+add_subdirectory(mc)
+add_subdirectory(pad)
+add_subdirectory(rcnt)
+add_subdirectory(time)
+add_library(drv_ps1)
+add_subdirectory(src)
+target_include_directories(drv_ps1 PUBLIC include PRIVATE private_include)
+target_link_libraries(drv_ps1 PUBLIC c drv_event PRIVATE
+ drv_ps1_cd
+ drv_ps1_mc
+ drv_ps1_pad
+)
diff --git a/src/drv/ps1/bios/CMakeLists.txt b/src/drv/ps1/bios/CMakeLists.txt
new file mode 100644
index 0000000..255a27d
--- /dev/null
+++ b/src/drv/ps1/bios/CMakeLists.txt
@@ -0,0 +1,19 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv_ps1_bios)
+add_subdirectory(src)
+target_include_directories(drv_ps1_bios INTERFACE include)
diff --git a/src/drv/ps1/bios/include/drv/ps1/bios.h b/src/drv/ps1/bios/include/drv/ps1/bios.h
new file mode 100644
index 0000000..2686f12
--- /dev/null
+++ b/src/drv/ps1/bios/include/drv/ps1/bios.h
@@ -0,0 +1,112 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef PS1_BIOS_H
+#define PS1_BIOS_H
+
+#include <stdint.h>
+
+enum
+{
+ CLASS_IRQ0 = (long)0xf0000001,
+ CLASS_GPU,
+ CLASS_CDROM,
+ CLASS_DMA,
+ CLASS_RTC0 = (long)0xf2000000,
+ CLASS_RTC1,
+ CLASS_RTC2,
+ CLASS_VBLANK,
+ CLASS_CONTROLLER = (long)0xf0000008,
+ CLASS_SPU,
+ CLASS_PIO,
+ CLASS_SIO
+};
+
+enum
+{
+ MODE_EXECUTE = 0x1000,
+ MODE_READY = 0x2000
+};
+
+enum
+{
+ SPEC_COUNTER_ZERO = 1,
+ SPEC_INTERRUPTED = 1 << 1,
+ SPEC_EOF = 1 << 2,
+ SPEC_FILE_CLOSED = 1 << 3,
+ SPEC_COMMAND_ACK = 1 << 4,
+ SPEC_COMMAND_COMPLETE = 1 << 5,
+ SPEC_DATA_READY = 1 << 6,
+ SPEC_DATA_END = 1 << 7,
+ SPEC_TIMEOUT = 1 << 8,
+ SPEC_UNKNOWN_CMD = 1 << 9,
+ SPEC_END_READ_BUF = 1 << 10,
+ SPEC_END_WRITE_BUF = 1 << 11,
+ SPEC_GENERAL_INTERRUPT = 1 << 12,
+ SPEC_NEW_DEVICE = 1 << 13,
+ SPEC_SYSCALL = 1 << 14,
+ SPEC_ERROR = 1 << 15,
+ SPEC_WRITE_ERROR,
+ SPEC_DOMAIN_ERROR = 0x301,
+ SPEC_RANGE_RNG
+};
+
+struct CdAsyncSeekL
+{
+ uint8_t minutes, seconds, frames;
+};
+
+union SetMode
+{
+ struct
+ {
+ uint8_t cdda :1, autopause :1, report :1, xa_filter :1, ignore :1,
+ whole_sector :1, xa_adpcm :1, speed :1;
+ } bits;
+
+ uint8_t mask;
+};
+
+struct CdAsyncReadSector_mode
+{
+ union SetMode mode;
+ union
+ {
+ struct
+ {
+ uint8_t reads :1, :7;
+ } bits;
+ } read;
+
+ uint16_t reserved;
+};
+
+void EnterCriticalSection(void);
+void ExitCriticalSection(void);
+int OpenEvent(int class, int spec, int mode, int (*f)(void));
+int EnableEvent(int event);
+int DisableEvent(int event);
+int CloseEvent(int event);
+int TestEvent(int event);
+int WaitEvent(int event);
+int CdAsyncGetStatus(uint8_t *response);
+int CdAsyncReadSector(unsigned count, void *dst,
+ struct CdAsyncReadSector_mode mode);
+int CdAsyncSeekL(const struct CdAsyncSeekL *seekl);
+
+#endif
diff --git a/src/drv/ps1/bios/src/CMakeLists.txt b/src/drv/ps1/bios/src/CMakeLists.txt
new file mode 100644
index 0000000..b1ea9cd
--- /dev/null
+++ b/src/drv/ps1/bios/src/CMakeLists.txt
@@ -0,0 +1,29 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(drv_ps1_bios PRIVATE
+ CdAsyncGetStatus.s
+ CdAsyncReadSector.s
+ CdAsyncSeekL.s
+ CloseEvent.s
+ DisableEvent.s
+ EnableEvent.s
+ EnterCriticalSection.s
+ ExitCriticalSection.s
+ OpenEvent.s
+ TestEvent.s
+ WaitEvent.s
+)
diff --git a/src/drv/ps1/bios/src/CdAsyncGetStatus.s b/src/drv/ps1/bios/src/CdAsyncGetStatus.s
new file mode 100644
index 0000000..77464ea
--- /dev/null
+++ b/src/drv/ps1/bios/src/CdAsyncGetStatus.s
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+.global CdAsyncGetStatus
+
+CdAsyncGetStatus:
+ li $9, 0x7c
+ j 0xa0
+ nop
diff --git a/src/drv/ps1/bios/src/CdAsyncReadSector.s b/src/drv/ps1/bios/src/CdAsyncReadSector.s
new file mode 100644
index 0000000..c68b54a
--- /dev/null
+++ b/src/drv/ps1/bios/src/CdAsyncReadSector.s
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+.global CdAsyncReadSector
+
+CdAsyncReadSector:
+ li $9, 0x7e
+ j 0xa0
+ nop
diff --git a/src/drv/ps1/bios/src/CdAsyncSeekL.s b/src/drv/ps1/bios/src/CdAsyncSeekL.s
new file mode 100644
index 0000000..cc20a32
--- /dev/null
+++ b/src/drv/ps1/bios/src/CdAsyncSeekL.s
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+.global CdAsyncSeekL
+
+CdAsyncSeekL:
+ li $9, 0x78
+ j 0xa0
+ nop
diff --git a/src/drv/ps1/bios/src/CloseEvent.s b/src/drv/ps1/bios/src/CloseEvent.s
new file mode 100644
index 0000000..0ade6fa
--- /dev/null
+++ b/src/drv/ps1/bios/src/CloseEvent.s
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+.global CloseEvent
+
+CloseEvent:
+ li $9, 0x9
+ j 0xb0
+ nop
diff --git a/src/drv/ps1/bios/src/DisableEvent.s b/src/drv/ps1/bios/src/DisableEvent.s
new file mode 100644
index 0000000..b2d96ca
--- /dev/null
+++ b/src/drv/ps1/bios/src/DisableEvent.s
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+.global DisableEvent
+
+DisableEvent:
+ li $9, 0xd
+ j 0xb0
+ nop
diff --git a/src/drv/ps1/bios/src/EnableEvent.s b/src/drv/ps1/bios/src/EnableEvent.s
new file mode 100644
index 0000000..bbff315
--- /dev/null
+++ b/src/drv/ps1/bios/src/EnableEvent.s
@@ -0,0 +1,23 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+.text
+
+.global EnableEvent
+
+EnableEvent:
+ li $9, 0xc
+ j 0xb0
+ nop
diff --git a/src/drv/ps1/bios/src/EnterCriticalSection.s b/src/drv/ps1/bios/src/EnterCriticalSection.s
new file mode 100644
index 0000000..ebf2de9
--- /dev/null
+++ b/src/drv/ps1/bios/src/EnterCriticalSection.s
@@ -0,0 +1,25 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+.text
+
+.global EnterCriticalSection
+
+EnterCriticalSection:
+ li $a0, 1
+ syscall
+ nop
+ jr $ra
+ nop
diff --git a/src/drv/ps1/bios/src/ExitCriticalSection.s b/src/drv/ps1/bios/src/ExitCriticalSection.s
new file mode 100644
index 0000000..53f307a
--- /dev/null
+++ b/src/drv/ps1/bios/src/ExitCriticalSection.s
@@ -0,0 +1,23 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+.global ExitCriticalSection
+
+ExitCriticalSection:
+ li $a0, 2
+ syscall
+ nop
+ jr $ra
+ nop
diff --git a/src/drv/ps1/bios/src/OpenEvent.s b/src/drv/ps1/bios/src/OpenEvent.s
new file mode 100644
index 0000000..89cc7d4
--- /dev/null
+++ b/src/drv/ps1/bios/src/OpenEvent.s
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+.global OpenEvent
+
+OpenEvent:
+ li $9, 0x8
+ j 0xb0
+ nop
diff --git a/src/drv/ps1/bios/src/TestEvent.s b/src/drv/ps1/bios/src/TestEvent.s
new file mode 100644
index 0000000..4afe273
--- /dev/null
+++ b/src/drv/ps1/bios/src/TestEvent.s
@@ -0,0 +1,23 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+.text
+
+.global TestEvent
+
+TestEvent:
+ li $9, 0xb
+ j 0xb0
+ nop
diff --git a/src/drv/ps1/bios/src/WaitEvent.s b/src/drv/ps1/bios/src/WaitEvent.s
new file mode 100644
index 0000000..1f2ca97
--- /dev/null
+++ b/src/drv/ps1/bios/src/WaitEvent.s
@@ -0,0 +1,23 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+.text
+
+.global WaitEvent
+
+WaitEvent:
+ li $9, 0xa
+ j 0xb0
+ nop
diff --git a/src/drv/ps1/cd/CMakeLists.txt b/src/drv/ps1/cd/CMakeLists.txt
new file mode 100644
index 0000000..7459bc6
--- /dev/null
+++ b/src/drv/ps1/cd/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv_ps1_cd)
+add_subdirectory(src)
+target_include_directories(drv_ps1_cd PUBLIC include PRIVATE private_include)
+target_link_libraries(drv_ps1_cd PUBLIC c drv_event PRIVATE drv_ps1_bios)
diff --git a/src/drv/ps1/cd/include/drv/ps1/cd.h b/src/drv/ps1/cd/include/drv/ps1/cd.h
new file mode 100644
index 0000000..6bb48f1
--- /dev/null
+++ b/src/drv/ps1/cd/include/drv/ps1/cd.h
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_CD_H
+#define DRV_PS1_CD_H
+
+#include <drv/event.h>
+
+struct drv_ps1_cd *drv_ps1_cd_init(const struct drv_event *ev);
+int drv_ps1_cd_update(struct drv_ps1_cd *cd);
+void drv_ps1_cd_free(struct drv_ps1_cd *cd);
+
+#endif
diff --git a/src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h b/src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h
new file mode 100644
index 0000000..7d15f39
--- /dev/null
+++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h
@@ -0,0 +1,66 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_CD_REGS_H
+#define DRV_PS1_CD_REGS_H
+
+#include <stdint.h>
+
+struct cd_reg_status
+{
+ uint8_t index :2;
+ const uint8_t ADPBUSY :1, PRMEMPT :1, PRMWRDY :1, RSLRRDY :1, DRQSTS :1,
+ BUSYSTS :1;
+};
+
+struct cd_reg_cmd
+{
+ uint8_t cmd;
+};
+
+struct cd_reg_rsp
+{
+ uint8_t rsp;
+};
+
+struct cd_reg_param
+{
+ uint8_t param;
+};
+
+union cd_reg_if
+{
+ const struct
+ {
+ uint8_t response :3, :1, cmd_start :1, :3;
+ } r;
+
+ struct
+ {
+ uint8_t ack: 5, :1, CLRPRM :1, :1;
+ } w;
+};
+
+#define CD_REG(x) (0x1f801800 + (x))
+#define CD_REG_STATUS ((volatile struct cd_reg_status *)CD_REG(0))
+#define CD_REG_CMD ((volatile struct cd_reg_cmd *)CD_REG(1))
+#define CD_REG_RSP ((const volatile struct cd_reg_rsp *)CD_REG(1))
+#define CD_REG_PARAM ((volatile struct cd_reg_param *)CD_REG(2))
+#define CD_REG_IF ((volatile union cd_reg_if *)CD_REG(3))
+
+#endif
diff --git a/src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h b/src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h
new file mode 100644
index 0000000..0fce7dd
--- /dev/null
+++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h
@@ -0,0 +1,37 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_CD_ROUTINES_H
+#define DRV_PS1_CD_ROUTINES_H
+
+#include <drv/ps1/cd/types.h>
+#include <drv/ps1/bios.h>
+#include <stddef.h>
+
+int drv_ps1_cd_send(const struct cmd *cmd);
+int drv_ps1_cd_getstat(void);
+int drv_ps1_cd_read(void *buf, size_t n, const struct drv_event_done *done,
+ void *args);
+int drv_ps1_cd_seek(long offset, const struct drv_event_done *done,
+ void *args);
+int drv_ps1_cd_write(const void *buf, size_t n,
+ const struct drv_event_done *done, void *args);
+int drv_ps1_cd_next(void);
+struct CdAsyncSeekL drv_ps1_cd_toseekl(unsigned i);
+
+#endif
diff --git a/src/drv/ps1/cd/private_include/drv/ps1/cd/types.h b/src/drv/ps1/cd/private_include/drv/ps1/cd/types.h
new file mode 100644
index 0000000..4446305
--- /dev/null
+++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/types.h
@@ -0,0 +1,122 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_CD_TYPES_H
+#define DRV_PS1_CD_TYPES_H
+
+#include <drv/event.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+struct drv_ps1_cd
+{
+ bool available;
+ struct drv_event ev;
+};
+
+struct cmd
+{
+ enum
+ {
+ CMD_SYNC,
+ CMD_GETSTAT,
+ CMD_SETLOC,
+ } cmd;
+
+ union cmd_param
+ {
+ struct cmd_setloc
+ {
+ uint8_t min, sec, sect;
+ } setloc;
+ } params;
+};
+
+struct cd_prv_getstat
+{
+ int event;
+
+ union
+ {
+ struct
+ {
+ uint8_t invalid :1, motor :1, seek_error :1, id_error :1,
+ shell_open :1, reading :1, seeking :1, playing_cdda :1;
+ } bits;
+
+ uint8_t byte;
+ } status;
+};
+
+struct cd_prv_read
+{
+ int event, endevent, errevent;
+};
+
+struct cd_prv_seek
+{
+ int event, errevent;
+};
+
+struct cd_req_read
+{
+ void *buf;
+ size_t n;
+};
+
+struct cd_req_seek
+{
+ long offset;
+};
+
+struct cd_req
+{
+ union
+ {
+ struct cd_req_read read;
+ struct cd_req_seek seek;
+ } u;
+
+ int (*f)(void);
+ struct drv_event_done done;
+ struct cd_req *next;
+};
+
+enum {CD_SECTOR_SZ = 2048};
+
+struct cd_prv
+{
+ bool available, has_cache;
+ int (*next)(void);
+ struct cmd cmd;
+ struct cd_req *head, *tail;
+ char sector[CD_SECTOR_SZ];
+ unsigned offset;
+
+ union
+ {
+ struct cd_prv_getstat getstat;
+ struct cd_prv_read read;
+ struct cd_prv_seek seek;
+ } u;
+};
+
+extern struct cd_prv drv_ps1_cd_prv;
+
+#endif
diff --git a/src/drv/ps1/cd/src/CMakeLists.txt b/src/drv/ps1/cd/src/CMakeLists.txt
new file mode 100644
index 0000000..074671d
--- /dev/null
+++ b/src/drv/ps1/cd/src/CMakeLists.txt
@@ -0,0 +1,29 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(drv_ps1_cd PRIVATE
+ free.c
+ getstat.c
+ init.c
+ next.c
+ prv.c
+ # send.c
+ read.c
+ seek.c
+ toseekl.c
+ update.c
+ write.c
+)
diff --git a/src/drv/ps1/cd/src/ensure_event.c b/src/drv/ps1/cd/src/ensure_event.c
new file mode 100644
index 0000000..5e2f3a0
--- /dev/null
+++ b/src/drv/ps1/cd/src/ensure_event.c
@@ -0,0 +1,40 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/bios.h>
+#include <drv/ps1/cd/types.h>
+#include <stddef.h>
+
+int drv_ps1_cd_ensure_event(struct cd_prv *const p)
+{
+ if (p->event)
+ return 0;
+
+ EnterCriticalSection();
+
+ const int event = OpenEvent(CLASS_CDROM, SPEC_COMMAND_COMPLETE, MODE_READY,
+ NULL);
+
+ ExitCriticalSection();
+
+ if (event == -1)
+ return -1;
+
+ EnableEvent(p->event = event);
+ return 0;
+}
diff --git a/src/drv/ps1/cd/src/free.c b/src/drv/ps1/cd/src/free.c
new file mode 100644
index 0000000..44704d7
--- /dev/null
+++ b/src/drv/ps1/cd/src/free.c
@@ -0,0 +1,23 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/cd.h>
+
+void drv_ps1_cd_free(struct drv_ps1_cd *const cd)
+{
+}
diff --git a/src/drv/ps1/cd/src/getstat.c b/src/drv/ps1/cd/src/getstat.c
new file mode 100644
index 0000000..6268f37
--- /dev/null
+++ b/src/drv/ps1/cd/src/getstat.c
@@ -0,0 +1,65 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/cd/routines.h>
+#include <drv/ps1/bios.h>
+
+static int wait_event(void)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+ struct cd_prv_getstat *const g = &p->u.getstat;
+
+ if (TestEvent(g->event))
+ {
+ p->available = !g->status.bits.shell_open;
+ DisableEvent(g->event);
+ CloseEvent(g->event);
+
+ if (!p->head)
+ return drv_ps1_cd_getstat();
+
+ return p->head->f();
+ }
+
+ return 0;
+}
+
+int drv_ps1_cd_getstat(void)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+ struct cd_prv_getstat *const g = &p->u.getstat;
+
+ EnterCriticalSection();
+
+ const int event = OpenEvent(CLASS_CDROM, SPEC_COMMAND_COMPLETE,
+ MODE_READY, NULL);
+
+ ExitCriticalSection();
+
+ if (event == -1)
+ return -1;
+
+ *g = (const struct cd_prv_getstat){.event = event};
+ EnableEvent(event);
+
+ if (!CdAsyncGetStatus(&g->status.byte))
+ return -1;
+
+ p->next = wait_event;
+ return 0;
+}
diff --git a/src/drv/ps1/cd/src/init.c b/src/drv/ps1/cd/src/init.c
new file mode 100644
index 0000000..896e330
--- /dev/null
+++ b/src/drv/ps1/cd/src/init.c
@@ -0,0 +1,42 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/cd.h>
+#include <drv/ps1/cd/routines.h>
+#include <drv/ps1/cd/types.h>
+#include <drv/event.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+struct drv_ps1_cd *drv_ps1_cd_init(const struct drv_event *const ev)
+{
+ struct drv_ps1_cd *const ret = malloc(sizeof *ret);
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+
+ if (!ret)
+ return NULL;
+ else if (!p->next && drv_ps1_cd_getstat())
+ goto failure;
+
+ *ret = (const struct drv_ps1_cd){.ev = *ev};
+ return ret;
+
+failure:
+ free(ret);
+ return NULL;
+}
diff --git a/src/drv/ps1/cd/src/next.c b/src/drv/ps1/cd/src/next.c
new file mode 100644
index 0000000..0923be9
--- /dev/null
+++ b/src/drv/ps1/cd/src/next.c
@@ -0,0 +1,38 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/cd.h>
+#include <drv/ps1/cd/routines.h>
+#include <drv/ps1/cd/types.h>
+#include <stdlib.h>
+
+int drv_ps1_cd_next(void)
+{
+ int ret = 0;
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+ struct cd_req *const next = p->head->next;
+
+ free(p->head);
+
+ if (next && (ret = next->f()))
+ return -1;
+ else if (!(p->head = next))
+ return drv_ps1_cd_getstat();
+
+ return ret;
+}
diff --git a/src/drv/ps1/cd/src/prv.c b/src/drv/ps1/cd/src/prv.c
new file mode 100644
index 0000000..dd70709
--- /dev/null
+++ b/src/drv/ps1/cd/src/prv.c
@@ -0,0 +1,22 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/cd.h>
+#include <drv/ps1/cd/types.h>
+
+struct cd_prv drv_ps1_cd_prv;
diff --git a/src/drv/ps1/cd/src/read.c b/src/drv/ps1/cd/src/read.c
new file mode 100644
index 0000000..251481e
--- /dev/null
+++ b/src/drv/ps1/cd/src/read.c
@@ -0,0 +1,155 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/cd.h>
+#include <drv/ps1/cd/routines.h>
+#include <drv/ps1/cd/types.h>
+#include <drv/event.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int deliver_event(struct cd_prv *const p, const int error)
+{
+ const struct cd_prv_read *const read = &p->u.read;
+ const struct cd_req *const req = p->head;
+ const struct drv_event_done *const d = &req->done;
+
+ if (!error)
+ {
+ const struct cd_req_read *const rr = &req->u.read;
+ const long offset = p->offset % CD_SECTOR_SZ;
+
+ memcpy(rr->buf, p->sector + offset, rr->n);
+ p->has_cache = true;
+ p->offset += rr->n;
+ }
+
+ if (d->f(error, d->args) || drv_ps1_cd_next())
+ return -1;
+
+ return 0;
+}
+
+static int wait_event(void)
+{
+ int ret = 0;
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+ const struct cd_prv_read *const read = &p->u.read;
+
+ if (TestEvent(read->event))
+ return deliver_event(p, SUCCESS);
+ else if (TestEvent(read->errevent) || TestEvent(read->endevent))
+ return deliver_event(p, EIO);
+
+ return 0;
+}
+
+static int start_read(void)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+ struct cd_prv_read *const r = &p->u.read;
+ const struct cd_req_read *req = &p->head->u.read;
+ const struct CdAsyncReadSector_mode mode =
+ {
+ .mode.bits.speed = 1,
+ };
+
+ EnterCriticalSection();
+
+ const int
+ event = OpenEvent(CLASS_CDROM, SPEC_COMMAND_COMPLETE, MODE_READY, NULL),
+ endevent = OpenEvent(CLASS_CDROM, SPEC_DATA_END, MODE_READY, NULL),
+ errevent = OpenEvent(CLASS_CDROM, SPEC_ERROR, MODE_READY, NULL);
+
+ ExitCriticalSection();
+
+ if (event == -1 || endevent == -1 || errevent == -1)
+ goto failure;
+
+ *r = (const struct cd_prv_read)
+ {
+ .event = event,
+ .endevent = endevent,
+ .errevent = errevent
+ };
+
+ EnableEvent(event);
+ EnableEvent(endevent);
+ EnableEvent(errevent);
+
+ if (!CdAsyncReadSector(1, p->sector, mode))
+ goto failure;
+
+ p->next = wait_event;
+ return 0;
+
+failure:
+ if (event != -1)
+ CloseEvent(event);
+
+ if (endevent != -1)
+ CloseEvent(endevent);
+
+ if (errevent != -1)
+ CloseEvent(errevent);
+
+ return -1;
+}
+
+static int read_cache(void)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+ const struct cd_req *const req = p->head;
+ const struct cd_req_read *const rr = &req->u.read;
+ const long offset = p->offset % CD_SECTOR_SZ;
+
+ memcpy(rr->buf, p->sector + offset, rr->n);
+ p->offset += rr->n;
+ return deliver_event(p, SUCCESS);
+}
+
+int drv_ps1_cd_read(void *const buf, const size_t n,
+ const struct drv_event_done *const done, void *const args)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+ struct cd_req *const r = malloc(sizeof *r);
+
+ if (!r)
+ return -1;
+
+ *r = (const struct cd_req)
+ {
+ .done = *done,
+ /* TODO: multi-sector reads, make sure cache can really be used */
+ .f = p->has_cache ? read_cache : start_read,
+ .u.read =
+ {
+ .buf = buf,
+ .n = n
+ }
+ };
+
+ if (!p->head)
+ p->head = r;
+ else
+ p->tail->next = r;
+
+ p->tail = r;
+ return 0;
+}
diff --git a/src/drv/ps1/cd/src/seek.c b/src/drv/ps1/cd/src/seek.c
new file mode 100644
index 0000000..e26a684
--- /dev/null
+++ b/src/drv/ps1/cd/src/seek.c
@@ -0,0 +1,118 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/cd.h>
+#include <drv/ps1/cd/routines.h>
+#include <drv/ps1/cd/types.h>
+#include <drv/ps1/bios.h>
+#include <drv/event.h>
+#include <errno.h>
+#include <stdlib.h>
+
+static int wait_event(void)
+{
+ int ret = 0;
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+ const struct cd_prv_seek *const s = &p->u.seek;
+ const struct cd_req *const r = p->head;
+ const struct drv_event_done *const d = &r->done;
+
+ if (TestEvent(s->event))
+ {
+ p->offset = r->u.seek.offset;
+
+ if (d->f(0, d->args) || drv_ps1_cd_next())
+ return -1;
+ }
+ else if (TestEvent(s->errevent))
+ {
+ if (d->f(EIO, d->args) || drv_ps1_cd_next())
+ return -1;
+ }
+
+ return 0;
+}
+
+static int seek(void)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+ struct cd_prv_seek *const s = &p->u.seek;
+ const struct cd_req_seek *req = &p->head->u.seek;
+ const unsigned sector = req->offset / CD_SECTOR_SZ;
+ const struct CdAsyncSeekL seekl = drv_ps1_cd_toseekl(sector);
+
+ EnterCriticalSection();
+
+ const int
+ event = OpenEvent(CLASS_CDROM, SPEC_COMMAND_COMPLETE, MODE_READY, NULL),
+ errevent = OpenEvent(CLASS_CDROM, SPEC_ERROR, MODE_READY, NULL);
+
+ ExitCriticalSection();
+
+ if (event == -1 || errevent == -1)
+ goto failure;
+
+ *s = (const struct cd_prv_seek)
+ {
+ .event = event,
+ .errevent = errevent
+ };
+
+ EnableEvent(event);
+ EnableEvent(errevent);
+
+ if (!CdAsyncSeekL(&seekl))
+ goto failure;
+
+ p->next = wait_event;
+ return 0;
+
+failure:
+ if (event != -1)
+ CloseEvent(event);
+
+ if (errevent != -1)
+ CloseEvent(errevent);
+
+ return -1;
+}
+
+int drv_ps1_cd_seek(const long offset, const struct drv_event_done *const done,
+ void *const args)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+ struct cd_req *const r = malloc(sizeof *r);
+
+ if (!r)
+ return -1;
+
+ *r = (const struct cd_req)
+ {
+ .done = *done,
+ .u.seek = offset,
+ .f = seek
+ };
+
+ if (!p->head)
+ p->head = r;
+ else
+ p->tail->next = r;
+
+ p->tail = r;
+ return 0;
+}
diff --git a/src/drv/ps1/cd/src/send.c b/src/drv/ps1/cd/src/send.c
new file mode 100644
index 0000000..76b9730
--- /dev/null
+++ b/src/drv/ps1/cd/src/send.c
@@ -0,0 +1,100 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/cd.h>
+#include <drv/ps1/bios.h>
+#include <drv/ps1/cd/regs.h>
+#include <drv/ps1/cd/routines.h>
+#include <drv/ps1/cd/types.h>
+#include <stdint.h>
+
+static int wait_event(void)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+
+ if (TestEvent(p->event))
+ {
+ const union cd_prv_getstat g = {.status = CD_REG_RSP->rsp};
+
+ p->available = !g.bits.shell_open;
+ }
+
+ return 0;
+}
+
+static void send_params(const struct cd_prv *const p)
+{
+ static const size_t n[] =
+ {
+ [CMD_SETLOC] = sizeof (struct cmd_setloc)
+ };
+
+ const uint8_t cmd = p->cmd.cmd, index = CD_REG_STATUS->index;
+
+ if (cmd < sizeof n / sizeof *n)
+ {
+ const void *const vbuf = &p->cmd.params;
+ const uint8_t *buf = vbuf;
+
+ CD_REG_STATUS->index = 0;
+
+ for (size_t i = 0; i < n[cmd]; i++)
+ CD_REG_PARAM->param = *buf++;
+
+ CD_REG_STATUS->index = index;
+ }
+}
+
+static int send_data(void)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+
+ if (CD_REG_STATUS->BUSYSTS)
+ return 0;
+
+ send_params(p);
+ CD_REG_CMD->cmd = p->cmd.cmd;
+ p->next = wait_event;
+ return 0;
+}
+
+static int reset_param_fifo(void)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+
+ if (CD_REG_STATUS->BUSYSTS)
+ return 0;
+
+ CD_REG_IF->w.ack = 0x1f;
+ CD_REG_STATUS->index = 1;
+ CD_REG_IF->w.CLRPRM = 1;
+ p->next = send_data;
+ return 0;
+}
+
+int drv_ps1_cd_send(const struct cmd *const cmd)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+
+ if (drv_ps1_cd_ensure_event(p))
+ return -1;
+
+ p->cmd = *cmd;
+ p->next = reset_param_fifo;
+ return 0;
+}
diff --git a/src/drv/ps1/cd/src/toseekl.c b/src/drv/ps1/cd/src/toseekl.c
new file mode 100644
index 0000000..df35ff1
--- /dev/null
+++ b/src/drv/ps1/cd/src/toseekl.c
@@ -0,0 +1,54 @@
+/* Original functions from psn00bsdk, commit 5d9aa2d3
+ *
+ * itob extracted from libpsn00b/include/psxcd.h
+ * CdIntToPos (here renamed to drv_ps1_cd_toseekl) extracted from
+ * libpsn00b/psxcd/misc.c
+ *
+ * Original copyright notice:
+ *
+ * PSn00bSDK CD-ROM library
+ * (C) 2020-2023 Lameguy64, spicyjpeg - MPL licensed
+ */
+
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/cd/routines.h>
+#include <drv/ps1/bios.h>
+
+/**
+ * @brief Translates a decimal value to BCD.
+ *
+ * @details Translates a decimal integer in 0-99 range into a BCD format value.
+ */
+static int itob(const int i)
+{
+ return (i / 10 * 16) | (i % 10);
+}
+
+struct CdAsyncSeekL drv_ps1_cd_toseekl(unsigned i)
+{
+ i += 150;
+
+ return (const struct CdAsyncSeekL)
+ {
+ .minutes = itob(i / (75 * 60)),
+ .seconds = itob((i / 75) % 60),
+ .frames = itob(i % 75)
+ };
+}
diff --git a/src/drv/ps1/cd/src/update.c b/src/drv/ps1/cd/src/update.c
new file mode 100644
index 0000000..2c3d2ff
--- /dev/null
+++ b/src/drv/ps1/cd/src/update.c
@@ -0,0 +1,46 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/cd.h>
+#include <drv/ps1/cd/types.h>
+#include <drv/ps1/cd/routines.h>
+#include <drv/event.h>
+#include <stdbool.h>
+
+int drv_ps1_cd_update(struct drv_ps1_cd *const cd)
+{
+ struct cd_prv *const p = &drv_ps1_cd_prv;
+
+ if (p->next())
+ return -1;
+ else if (p->available ^ cd->available)
+ {
+ const struct drv_event *const ev = &cd->ev;
+ static const struct drv_event_ops ops =
+ {
+ .read = drv_ps1_cd_read,
+ .write = drv_ps1_cd_write,
+ .seek = drv_ps1_cd_seek
+ };
+
+ ev->status("cd0", &ops, p->available, ev->args);
+ cd->available = p->available;
+ }
+
+ return 0;
+}
diff --git a/src/drv/ps1/cd/src/write.c b/src/drv/ps1/cd/src/write.c
new file mode 100644
index 0000000..008a13d
--- /dev/null
+++ b/src/drv/ps1/cd/src/write.c
@@ -0,0 +1,31 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/cd.h>
+#include <drv/ps1/cd/routines.h>
+#include <drv/ps1/cd/types.h>
+#include <drv/event.h>
+#include <errno.h>
+
+int drv_ps1_cd_write(const void *const buf, const size_t n,
+ const struct drv_event_done *const done, void *const args)
+{
+ /* TODO: write event callback returning EROFS */
+ errno = EROFS;
+ return -1;
+}
diff --git a/src/drv/ps1/dma/CMakeLists.txt b/src/drv/ps1/dma/CMakeLists.txt
new file mode 100644
index 0000000..689beed
--- /dev/null
+++ b/src/drv/ps1/dma/CMakeLists.txt
@@ -0,0 +1,18 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv_ps1_dma INTERFACE)
+target_include_directories(drv_ps1_dma INTERFACE include)
diff --git a/src/drv/ps1/dma/include/drv/ps1/dma.h b/src/drv/ps1/dma/include/drv/ps1/dma.h
new file mode 100644
index 0000000..8ae1826
--- /dev/null
+++ b/src/drv/ps1/dma/include/drv/ps1/dma.h
@@ -0,0 +1,97 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_DMA_H
+#define DRV_PS1_DMA_H
+
+#include <stdint.h>
+
+union dpcr
+{
+ struct
+ {
+ uint32_t mdecin_prio :3, mdecin_en :1, mdecout_prio :3, mdecout_en :1,
+ gpu_prio :3, gpu_en :1, cdrom_prio :3, cdrom_en :1, spu_prio :3,
+ spu_en :1, pio_prio :3, pio_en :1, otc_prio :3, otc_en :1, :4;
+ } bits;
+
+ uint32_t mask;
+};
+
+union madr
+{
+ struct
+ {
+ uint32_t addr :24, :8;
+ } bits;
+
+ uint32_t mask;
+};
+
+union bcr
+{
+ struct
+ {
+ uint16_t nwords, reserved;
+ } syncmode_0;
+
+ struct
+ {
+ uint16_t blocksz, nblocks;
+ } syncmode_1;
+
+ struct
+ {
+ uint32_t reserved;
+ } syncmode_2;
+
+ uint32_t mask;
+};
+
+enum
+{
+ CHCR_DIR_TO_RAM,
+ CHCR_DIR_FROM_RAM
+};
+
+enum
+{
+ CHCR_SYNC_MODE_ALL,
+ CHCR_SYNC_MODE_BLOCKS,
+ CHCR_SYNC_MODE_LINKED_LIST
+};
+
+union chcr
+{
+ struct
+ {
+ uint32_t dir :1, memstep :1, :6, chopping :1, sync_mode :2, :5,
+ chopping_dma_window_sz :3, :1, chopping_cpu_window_sz :3, :1,
+ start_busy :1, :3, start_trigger :1, :3;
+ } bits;
+
+ uint32_t mask;
+};
+
+#define DMA_BASE(dma, off) ((dma) * 0x10 + 0x1f801080 + (off))
+#define D2_MADR ((volatile union madr *)DMA_BASE(2, 0))
+#define D2_BCR ((volatile union bcr *)DMA_BASE(2, 4))
+#define D2_CHCR ((volatile union chcr *)DMA_BASE(2, 8))
+#define DPCR ((volatile union dpcr *)0x1f8010f0)
+
+#endif
diff --git a/src/drv/ps1/gpu/CMakeLists.txt b/src/drv/ps1/gpu/CMakeLists.txt
new file mode 100644
index 0000000..9dead67
--- /dev/null
+++ b/src/drv/ps1/gpu/CMakeLists.txt
@@ -0,0 +1,18 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv_ps1_gpu INTERFACE)
+target_include_directories(drv_ps1_gpu INTERFACE include)
diff --git a/src/drv/ps1/gpu/include/drv/ps1/gpu.h b/src/drv/ps1/gpu/include/drv/ps1/gpu.h
new file mode 100644
index 0000000..0f64a7f
--- /dev/null
+++ b/src/drv/ps1/gpu/include/drv/ps1/gpu.h
@@ -0,0 +1,167 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_GPU_H
+#define DRV_PS1_GPU_H
+
+#include <stdint.h>
+
+enum
+{
+ GP0_TEXTRECT_VARSZ_OPAQ_RAW = 0x65,
+ GP0_COPY_RECT_CPU_VRAM = 0xa0,
+ GP0_COPY_RECT_VRAM_CPU = 0xc0,
+ GP0_DRAW_MODE = 0xe1,
+ GP0_TEX_WINDOW,
+ GP0_DRAW_AREA_TOP_LEFT,
+ GP0_DRAW_AREA_BOTTOM_RIGHT,
+ GP0_DRAW_OFFSET,
+ GP0_DRAW_MASK_BIT
+};
+
+enum
+{
+ GP1_RESET_GPU,
+ GP1_RESET_CMDBUF,
+ GP1_ACK_IRQ,
+ GP1_DISPLAY_ENABLE,
+ GP1_DMA_DIR,
+ GP1_START_DISPLAY_AREA,
+ GP1_H_DISPLAY_RANGE,
+ GP1_V_DISPLAY_RANGE,
+ GP1_DISPLAY_MODE
+};
+
+enum
+{
+ GP1_DMA_DIR_OFF,
+ GP1_DMA_DIR_FIFO,
+ GP1_DMA_DIR_CPU_TO_GP0,
+ GP1_DMA_DIR_GPUREAD_TO_CPU
+};
+
+union drv_ps1_gpu_gp0
+{
+ uint32_t mask;
+
+ struct
+ {
+ uint32_t :24, cmd :8;
+ } copy_rect;
+
+ struct
+ {
+ uint16_t x, y;
+ } coord;
+
+ struct
+ {
+ uint16_t w, h;
+ } size;
+
+ struct
+ {
+ uint32_t page_x :4, page_y :1, stp :2, bpp :2, dither :1,
+ draw_to_display :1, tex_disable :1, xflip :1, yflip :1, :10,
+ cmd :8;
+ } draw_mode;
+
+ struct
+ {
+ uint32_t mask_x :5, mask_y :5, off_x :5, off_y :5, :4, cmd :8;
+ } tex_window;
+
+ struct
+ {
+ uint32_t x :10, y :9, :5, cmd :8;
+ } draw_area_tl, draw_area_br;
+
+ struct
+ {
+ int32_t x :11, y :11, :2, cmd :8;
+ } offset;
+
+ struct
+ {
+ uint32_t set :1, check :1, :22, cmd :8;
+ } mask_bit;
+};
+
+union drv_ps1_gpu_gp1
+{
+ uint32_t mask;
+
+ struct
+ {
+ uint32_t :24, cmd:8;
+ } reset_gpu, reset_cmdbuf, ack_irq;
+
+ struct
+ {
+ uint32_t disable :1, :23, cmd :8;
+ } display;
+
+ struct
+ {
+ uint32_t dir :2, :22, cmd :8;
+ } dma;
+
+ struct
+ {
+ uint32_t x :10, y :9, :5, cmd :8;
+ } disparea;
+
+ struct
+ {
+ uint32_t x1 :12, x2 :12, cmd :8;
+ } h_display_range;
+
+ struct
+ {
+ uint32_t y1 :10, y2 :10, :4, cmd :8;
+ } v_display_range;
+
+ struct
+ {
+ uint32_t hres :2, vres :1, vmode :1, coldepth :1, vinterlace :1,
+ hres2 :1, reverse :1, :16, cmd :8;
+ } display_mode;
+};
+
+union drv_ps1_gpu_stat
+{
+ struct
+ {
+ uint32_t x_base :4, y_base :1, stp :2, bpp :2, dither :1,
+ draw_to_display :1, set_mask :1, draw_pix :1, interlace :1,
+ reverse :1, disable :1, xres2 :1, xres1 :2, yres :1, vmode :1,
+ coldepth :1, vinterlace :1, display_enable :1, irq_req :1,
+ dma_req :1, ready_cmd :1, ready_send :1, ready_recv :1,
+ ready_dma :1, dma_dir :2, draw_odd :1;
+ } bits;
+
+ uint32_t mask;
+};
+
+#define GPU_BASE 0x1f801810
+#define GPU_REG(x) (GPU_BASE + (x))
+#define GP0 ((volatile union drv_ps1_gpu_gp0 *)GPU_REG(0))
+#define GP1 ((volatile union drv_ps1_gpu_gp1 *)GPU_REG(4))
+#define GPUSTAT ((volatile const union drv_ps1_gpu_stat *)GPU_REG(4))
+
+#endif
diff --git a/src/drv/ps1/include/drv/ps1.h b/src/drv/ps1/include/drv/ps1.h
new file mode 100644
index 0000000..951259a
--- /dev/null
+++ b/src/drv/ps1/include/drv/ps1.h
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_H
+#define DRV_PS1_H
+
+#include <drv/event.h>
+
+struct drv_port *drv_ps1_init(const struct drv_event *ev);
+int drv_ps1_update(struct drv_port *p);
+void drv_ps1_free(struct drv_port *p);
+
+#endif
diff --git a/src/drv/ps1/interrupt/CMakeLists.txt b/src/drv/ps1/interrupt/CMakeLists.txt
new file mode 100644
index 0000000..29becb8
--- /dev/null
+++ b/src/drv/ps1/interrupt/CMakeLists.txt
@@ -0,0 +1,19 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv_ps1_interrupt INTERFACE)
+target_include_directories(drv_ps1_interrupt INTERFACE include)
+target_link_libraries(drv_ps1_interrupt INTERFACE c)
diff --git a/src/drv/ps1/interrupt/include/drv/ps1/interrupt.h b/src/drv/ps1/interrupt/include/drv/ps1/interrupt.h
new file mode 100644
index 0000000..9e0bfb4
--- /dev/null
+++ b/src/drv/ps1/interrupt/include/drv/ps1/interrupt.h
@@ -0,0 +1,39 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_INTERRUPT_H
+#define DRV_PS1_INTERRUPT_H
+
+#include <stdint.h>
+
+union drv_ps1_interrupt
+{
+ struct
+ {
+ uint32_t vblank :1, gpu :1, cdrom :1, dma :1, tmr0 :1, tmr1 :1, tmr2 :1,
+ controller :1, sio :1, spu :1, lightpen :1, :21;
+ } bits;
+
+ uint32_t mask;
+};
+
+#define I_BASE(x) (0x1f801070 + (x))
+#define I_STAT ((volatile union drv_ps1_interrupt *)I_BASE(0))
+#define I_MASK ((volatile union drv_ps1_interrupt *)I_BASE(4))
+
+#endif
diff --git a/src/drv/ps1/mc/CMakeLists.txt b/src/drv/ps1/mc/CMakeLists.txt
new file mode 100644
index 0000000..13ae399
--- /dev/null
+++ b/src/drv/ps1/mc/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv_ps1_mc)
+add_subdirectory(src)
+target_include_directories(drv_ps1_mc PUBLIC include PRIVATE private_include)
+target_link_libraries(drv_ps1_mc PUBLIC c drv_event)
diff --git a/src/drv/ps1/mc/include/drv/ps1/mc.h b/src/drv/ps1/mc/include/drv/ps1/mc.h
new file mode 100644
index 0000000..637bd37
--- /dev/null
+++ b/src/drv/ps1/mc/include/drv/ps1/mc.h
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_MC_H
+#define DRV_PS1_MC_H
+
+#include <drv/event.h>
+
+struct drv_ps1_mc *drv_ps1_mc_init(const struct drv_event *ev);
+int drv_ps1_mc_update(struct drv_ps1_mc *mc);
+void drv_ps1_mc_free(struct drv_ps1_mc *mc);
+
+#endif
diff --git a/src/drv/ps1/mc/private_include/drv/ps1/mc/types.h b/src/drv/ps1/mc/private_include/drv/ps1/mc/types.h
new file mode 100644
index 0000000..920e55a
--- /dev/null
+++ b/src/drv/ps1/mc/private_include/drv/ps1/mc/types.h
@@ -0,0 +1,37 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_MC_TYPES_H
+#define DRV_PS1_MC_TYPES_H
+
+#include <drv/event.h>
+
+struct drv_ps1_mc
+{
+ const struct drv_event *ev;
+};
+
+enum
+{
+ MC_0,
+ MC_1,
+
+ N_MC
+};
+
+#endif
diff --git a/src/drv/ps1/mc/src/CMakeLists.txt b/src/drv/ps1/mc/src/CMakeLists.txt
new file mode 100644
index 0000000..6eb62be
--- /dev/null
+++ b/src/drv/ps1/mc/src/CMakeLists.txt
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(drv_ps1_mc PRIVATE
+ free.c
+ init.c
+ update.c
+)
diff --git a/src/drv/ps1/mc/src/free.c b/src/drv/ps1/mc/src/free.c
new file mode 100644
index 0000000..924e1bf
--- /dev/null
+++ b/src/drv/ps1/mc/src/free.c
@@ -0,0 +1,23 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/mc.h>
+
+void drv_ps1_mc_free(struct drv_ps1_mc *const mc)
+{
+}
diff --git a/src/drv/ps1/mc/src/init.c b/src/drv/ps1/mc/src/init.c
new file mode 100644
index 0000000..4bb034a
--- /dev/null
+++ b/src/drv/ps1/mc/src/init.c
@@ -0,0 +1,34 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/mc.h>
+#include <drv/ps1/mc/types.h>
+#include <drv/event.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+struct drv_ps1_mc *drv_ps1_mc_init(const struct drv_event *const ev)
+{
+ struct drv_ps1_mc *const ret = malloc(sizeof *ret);
+
+ if (!ret)
+ return NULL;
+
+ *ret = (const struct drv_ps1_mc){.ev = ev};
+ return ret;
+}
diff --git a/src/drv/ps1/mc/src/update.c b/src/drv/ps1/mc/src/update.c
new file mode 100644
index 0000000..f4b29d9
--- /dev/null
+++ b/src/drv/ps1/mc/src/update.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/mc.h>
+#include <drv/event.h>
+
+int drv_ps1_mc_update(struct drv_ps1_mc *const mc)
+{
+ /* TODO */
+ return 0;
+}
diff --git a/src/drv/ps1/pad/CMakeLists.txt b/src/drv/ps1/pad/CMakeLists.txt
new file mode 100644
index 0000000..cd25672
--- /dev/null
+++ b/src/drv/ps1/pad/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv_ps1_pad)
+add_subdirectory(src)
+target_include_directories(drv_ps1_pad PUBLIC include PRIVATE private_include)
+target_link_libraries(drv_ps1_pad PUBLIC c drv_event)
diff --git a/src/drv/ps1/pad/include/drv/ps1/pad.h b/src/drv/ps1/pad/include/drv/ps1/pad.h
new file mode 100644
index 0000000..d8070de
--- /dev/null
+++ b/src/drv/ps1/pad/include/drv/ps1/pad.h
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_PAD_H
+#define DRV_PS1_PAD_H
+
+#include <drv/event.h>
+
+struct drv_ps1_pad *drv_ps1_pad_init(const struct drv_event *ev);
+int drv_ps1_pad_update(struct drv_ps1_pad *pad);
+void drv_ps1_pad_free(struct drv_ps1_pad *pad);
+
+#endif
diff --git a/src/drv/ps1/pad/private_include/drv/ps1/pad/types.h b/src/drv/ps1/pad/private_include/drv/ps1/pad/types.h
new file mode 100644
index 0000000..b79e344
--- /dev/null
+++ b/src/drv/ps1/pad/private_include/drv/ps1/pad/types.h
@@ -0,0 +1,29 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_PAD_TYPES_H
+#define DRV_PS1_PAD_TYPES_H
+
+#include <drv/event.h>
+
+struct drv_ps1_pad
+{
+ const struct drv_event *ev;
+};
+
+#endif
diff --git a/src/drv/ps1/pad/src/CMakeLists.txt b/src/drv/ps1/pad/src/CMakeLists.txt
new file mode 100644
index 0000000..9da3661
--- /dev/null
+++ b/src/drv/ps1/pad/src/CMakeLists.txt
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(drv_ps1_pad PRIVATE
+ free.c
+ init.c
+ update.c
+)
diff --git a/src/drv/ps1/pad/src/free.c b/src/drv/ps1/pad/src/free.c
new file mode 100644
index 0000000..925e23a
--- /dev/null
+++ b/src/drv/ps1/pad/src/free.c
@@ -0,0 +1,23 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/pad.h>
+
+void drv_ps1_pad_free(struct drv_ps1_pad *const pad)
+{
+}
diff --git a/src/drv/ps1/pad/src/init.c b/src/drv/ps1/pad/src/init.c
new file mode 100644
index 0000000..3d2bd51
--- /dev/null
+++ b/src/drv/ps1/pad/src/init.c
@@ -0,0 +1,34 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/pad.h>
+#include <drv/ps1/pad/types.h>
+#include <drv/event.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+struct drv_ps1_pad *drv_ps1_pad_init(const struct drv_event *const ev)
+{
+ struct drv_ps1_pad *const ret = malloc(sizeof *ret);
+
+ if (!ret)
+ return NULL;
+
+ *ret = (const struct drv_ps1_pad){.ev = ev};
+ return ret;
+}
diff --git a/src/drv/ps1/pad/src/update.c b/src/drv/ps1/pad/src/update.c
new file mode 100644
index 0000000..35fb7a7
--- /dev/null
+++ b/src/drv/ps1/pad/src/update.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/pad.h>
+#include <drv/event.h>
+
+int drv_ps1_pad_update(struct drv_ps1_pad *const pad)
+{
+ /* TODO */
+ return 0;
+}
diff --git a/src/drv/ps1/private_include/drv/ps1/types.h b/src/drv/ps1/private_include/drv/ps1/types.h
new file mode 100644
index 0000000..ffb3559
--- /dev/null
+++ b/src/drv/ps1/private_include/drv/ps1/types.h
@@ -0,0 +1,33 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_TYPES_H
+#define DRV_PS1_TYPES_H
+
+#include <drv/ps1/cd.h>
+#include <drv/ps1/mc.h>
+#include <drv/ps1/pad.h>
+
+struct drv_port
+{
+ struct drv_ps1_mc *mc;
+ struct drv_ps1_cd *cd;
+ struct drv_ps1_pad *pad;
+};
+
+#endif
diff --git a/src/drv/ps1/rcnt/CMakeLists.txt b/src/drv/ps1/rcnt/CMakeLists.txt
new file mode 100644
index 0000000..65af1a4
--- /dev/null
+++ b/src/drv/ps1/rcnt/CMakeLists.txt
@@ -0,0 +1,22 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv_ps1_rcnt)
+add_subdirectory(src)
+target_include_directories(drv_ps1_rcnt PUBLIC include PRIVATE private_include)
+target_link_libraries(drv_ps1_rcnt
+ PUBLIC c
+ PRIVATE drv_ps1_bios drv_ps1_interrupt)
diff --git a/src/drv/ps1/rcnt/include/drv/ps1/rcnt.h b/src/drv/ps1/rcnt/include/drv/ps1/rcnt.h
new file mode 100644
index 0000000..a4e8e1b
--- /dev/null
+++ b/src/drv/ps1/rcnt/include/drv/ps1/rcnt.h
@@ -0,0 +1,45 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_RCNT_H
+#define DRV_PS1_RCNT_H
+
+#include <stdint.h>
+
+union drv_ps1_rcnt_cfg
+{
+ struct
+ {
+ uint32_t sync_enable :1, sync_mode :2, reset :1, irq_tgt :1,
+ irq_max :1, repeat :1, pulse_toggle :1, clocksrc :2, intreq :1;
+ } bits;
+
+ uint32_t word;
+};
+
+enum drv_ps1_rcnt
+{
+ DRV_PS1_RCNT0,
+ DRV_PS1_RCNT1,
+ DRV_PS1_RCNT2
+};
+
+int drv_ps1_rcnt_init(enum drv_ps1_rcnt rcnt, uint16_t target,
+ const union drv_ps1_rcnt_cfg *cfg, int (*f)(void));
+
+#endif
diff --git a/src/drv/ps1/rcnt/private_include/drv/ps1/rcnt/regs.h b/src/drv/ps1/rcnt/private_include/drv/ps1/rcnt/regs.h
new file mode 100644
index 0000000..443a487
--- /dev/null
+++ b/src/drv/ps1/rcnt/private_include/drv/ps1/rcnt/regs.h
@@ -0,0 +1,36 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_RCNT_REGS_H
+#define DRV_PS1_RCNT_REGS_H
+
+#include <drv/ps1/rcnt.h>
+#include <stdint.h>
+
+struct rcnt_value
+{
+ uint32_t value :16, :16;
+};
+
+#define RCNT_BASE(n) (0x1f801100 + (n << 4))
+#define RCNT_REG(n, m) (RCNT_BASE(n) + m)
+#define RCNT_VALUE(n) ((volatile struct rcnt_value *)RCNT_REG(n, 0))
+#define RCNT_MODE(n) ((volatile union drv_ps1_rcnt_cfg *)RCNT_REG(n, 4))
+#define RCNT_TARGET(n) ((volatile struct rcnt_value *)RCNT_REG(n, 8))
+
+#endif
diff --git a/src/drv/ps1/rcnt/src/CMakeLists.txt b/src/drv/ps1/rcnt/src/CMakeLists.txt
new file mode 100644
index 0000000..0254ed8
--- /dev/null
+++ b/src/drv/ps1/rcnt/src/CMakeLists.txt
@@ -0,0 +1,19 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(drv_ps1_rcnt PRIVATE
+ init.c
+)
diff --git a/src/drv/ps1/rcnt/src/init.c b/src/drv/ps1/rcnt/src/init.c
new file mode 100644
index 0000000..770cd15
--- /dev/null
+++ b/src/drv/ps1/rcnt/src/init.c
@@ -0,0 +1,59 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/rcnt.h>
+#include <drv/ps1/rcnt/regs.h>
+#include <drv/ps1/interrupt.h>
+#include <drv/ps1/bios.h>
+#include <stddef.h>
+#include <stdint.h>
+
+int drv_ps1_rcnt_init(const enum drv_ps1_rcnt rcnt, const uint16_t target,
+ const union drv_ps1_rcnt_cfg *const cfg, int (*const f)(void))
+{
+ int event, class;
+
+ EnterCriticalSection();
+ RCNT_TARGET(rcnt)->value = target;
+ *RCNT_MODE(rcnt) = *cfg;
+
+ switch (rcnt)
+ {
+ case DRV_PS1_RCNT0:
+ I_MASK->bits.tmr0 = 1;
+ class = CLASS_RTC0;
+ break;
+ case DRV_PS1_RCNT1:
+ I_MASK->bits.tmr1 = 1;
+ class = CLASS_RTC1;
+ break;
+ case DRV_PS1_RCNT2:
+ I_MASK->bits.tmr2 = 1;
+ class = CLASS_RTC2;
+ break;
+ }
+
+ event = OpenEvent(class, SPEC_INTERRUPTED, MODE_EXECUTE, f);
+ ExitCriticalSection();
+
+ if (event == -1)
+ return -1;
+
+ EnableEvent(event);
+ return 0;
+}
diff --git a/src/drv/ps1/src/CMakeLists.txt b/src/drv/ps1/src/CMakeLists.txt
new file mode 100644
index 0000000..4694191
--- /dev/null
+++ b/src/drv/ps1/src/CMakeLists.txt
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(drv_ps1 PRIVATE
+ free.c
+ init.c
+ update.c
+)
diff --git a/src/drv/ps1/src/free.c b/src/drv/ps1/src/free.c
new file mode 100644
index 0000000..a1348d6
--- /dev/null
+++ b/src/drv/ps1/src/free.c
@@ -0,0 +1,24 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1.h>
+#include <drv/ps1/types.h>
+
+void drv_ps1_free(struct drv_port *const p)
+{
+}
diff --git a/src/drv/ps1/src/init.c b/src/drv/ps1/src/init.c
new file mode 100644
index 0000000..37a08be
--- /dev/null
+++ b/src/drv/ps1/src/init.c
@@ -0,0 +1,53 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1.h>
+#include <drv/ps1/types.h>
+#include <drv/ps1/cd.h>
+#include <drv/ps1/mc.h>
+#include <drv/ps1/pad.h>
+#include <stdlib.h>
+
+struct drv_port *drv_ps1_init(const struct drv_event *const ev)
+{
+ struct drv_port *ret = NULL;
+ struct drv_ps1_mc *mc = NULL;
+ struct drv_ps1_cd *cd = NULL;
+ struct drv_ps1_pad *pad = NULL;
+
+ if (!(mc = drv_ps1_mc_init(ev))
+ || !(cd = drv_ps1_cd_init(ev))
+ || !(pad = drv_ps1_pad_init(ev))
+ || !(ret = malloc(sizeof *ret)))
+ goto failure;
+
+ *ret = (const struct drv_port)
+ {
+ .mc = mc,
+ .cd = cd,
+ .pad = pad
+ };
+
+ return ret;
+
+failure:
+ drv_ps1_mc_free(mc);
+ drv_ps1_cd_free(cd);
+ drv_ps1_pad_free(pad);
+ free(mc);
+}
diff --git a/src/drv/ps1/src/update.c b/src/drv/ps1/src/update.c
new file mode 100644
index 0000000..c96d9de
--- /dev/null
+++ b/src/drv/ps1/src/update.c
@@ -0,0 +1,33 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1.h>
+#include <drv/ps1/types.h>
+#include <drv/ps1/cd.h>
+#include <drv/ps1/mc.h>
+#include <drv/ps1/pad.h>
+
+int drv_ps1_update(struct drv_port *const p)
+{
+ if (drv_ps1_mc_update(p->mc)
+ || drv_ps1_cd_update(p->cd)
+ || drv_ps1_pad_update(p->pad))
+ return -1;
+
+ return 0;
+}
diff --git a/src/drv/ps1/time/CMakeLists.txt b/src/drv/ps1/time/CMakeLists.txt
new file mode 100644
index 0000000..2746810
--- /dev/null
+++ b/src/drv/ps1/time/CMakeLists.txt
@@ -0,0 +1,22 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv_ps1_time)
+add_subdirectory(src)
+target_include_directories(drv_ps1_time PUBLIC include PRIVATE private_include)
+target_link_libraries(drv_ps1_time
+ PUBLIC c
+ PRIVATE drv drv_ps1_bios drv_ps1_interrupt drv_ps1_rcnt)
diff --git a/src/drv/ps1/time/include/drv/ps1/time.h b/src/drv/ps1/time/include/drv/ps1/time.h
new file mode 100644
index 0000000..d08ff39
--- /dev/null
+++ b/src/drv/ps1/time/include/drv/ps1/time.h
@@ -0,0 +1,24 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_TIME_H
+#define DRV_PS1_TIME_H
+
+int drv_ps1_time_tick(void);
+
+#endif
diff --git a/src/drv/ps1/time/private_include/drv/ps1/time/types.h b/src/drv/ps1/time/private_include/drv/ps1/time/types.h
new file mode 100644
index 0000000..ad420c6
--- /dev/null
+++ b/src/drv/ps1/time/private_include/drv/ps1/time/types.h
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_PS1_TIME_TYPES_H
+#define DRV_PS1_TIME_TYPES_H
+
+#include <time.h>
+
+extern volatile struct timespec drv_ps1_time;
+
+#endif
diff --git a/src/drv/ps1/time/src/CMakeLists.txt b/src/drv/ps1/time/src/CMakeLists.txt
new file mode 100644
index 0000000..0ab540e
--- /dev/null
+++ b/src/drv/ps1/time/src/CMakeLists.txt
@@ -0,0 +1,23 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(drv_ps1_time PRIVATE
+ gettime.c
+ getres.c
+ globals.c
+ settime.c
+ tick.c
+)
diff --git a/src/drv/ps1/time/src/getres.c b/src/drv/ps1/time/src/getres.c
new file mode 100644
index 0000000..8dad204
--- /dev/null
+++ b/src/drv/ps1/time/src/getres.c
@@ -0,0 +1,34 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/time.h>
+#include <errno.h>
+#include <time.h>
+
+int drv_time_getres(const clockid_t id, struct timespec *const ts)
+{
+ if (id != CLOCK_REALTIME)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ else if (ts)
+ *ts = (const struct timespec){.tv_nsec = 1000000};
+
+ return 0;
+}
diff --git a/src/drv/ps1/time/src/gettime.c b/src/drv/ps1/time/src/gettime.c
new file mode 100644
index 0000000..f01030f
--- /dev/null
+++ b/src/drv/ps1/time/src/gettime.c
@@ -0,0 +1,37 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/time.h>
+#include <drv/ps1/time/types.h>
+#include <drv/ps1/bios.h>
+#include <errno.h>
+#include <time.h>
+
+int drv_time_gettime(const clockid_t id, struct timespec *const ts)
+{
+ if (id != CLOCK_REALTIME)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ EnterCriticalSection();
+ *ts = drv_ps1_time;
+ ExitCriticalSection();
+ return 0;
+}
diff --git a/src/drv/ps1/time/src/globals.c b/src/drv/ps1/time/src/globals.c
new file mode 100644
index 0000000..cb2a825
--- /dev/null
+++ b/src/drv/ps1/time/src/globals.c
@@ -0,0 +1,22 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/time/types.h>
+#include <time.h>
+
+volatile struct timespec drv_ps1_time;
diff --git a/src/drv/ps1/time/src/settime.c b/src/drv/ps1/time/src/settime.c
new file mode 100644
index 0000000..25de76f
--- /dev/null
+++ b/src/drv/ps1/time/src/settime.c
@@ -0,0 +1,37 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/time.h>
+#include <drv/ps1/time/types.h>
+#include <drv/ps1/bios.h>
+#include <errno.h>
+#include <time.h>
+
+int drv_time_settime(const clockid_t id, const struct timespec *const ts)
+{
+ if (id != CLOCK_REALTIME)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ EnterCriticalSection();
+ drv_ps1_time = *ts;
+ ExitCriticalSection();
+ return 0;
+}
diff --git a/src/drv/ps1/time/src/tick.c b/src/drv/ps1/time/src/tick.c
new file mode 100644
index 0000000..b80174b
--- /dev/null
+++ b/src/drv/ps1/time/src/tick.c
@@ -0,0 +1,42 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/ps1/time.h>
+#include <drv/ps1/time/types.h>
+#include <drv/ps1/interrupt.h>
+#include <time.h>
+
+int drv_ps1_time_tick(void)
+{
+ int ret = 0;
+ struct timespec ts;
+ volatile struct timespec *const t = &drv_ps1_time;
+
+ if (clock_getres(CLOCK_REALTIME, &ts))
+ ret = -1;
+ else if (t->tv_nsec >= 1000000000 - ts.tv_nsec)
+ {
+ t->tv_sec++;
+ t->tv_nsec = 0;
+ }
+ else
+ t->tv_nsec += ts.tv_nsec;
+
+ I_STAT->bits.tmr2 = 1;
+ return ret;
+}
diff --git a/src/drv/src/CMakeLists.txt b/src/drv/src/CMakeLists.txt
new file mode 100644
index 0000000..591532c
--- /dev/null
+++ b/src/drv/src/CMakeLists.txt
@@ -0,0 +1,22 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(drv PRIVATE
+ free.c
+ init.c
+ tree.c
+ update.c
+)
diff --git a/src/drv/src/free.c b/src/drv/src/free.c
new file mode 100644
index 0000000..37c259c
--- /dev/null
+++ b/src/drv/src/free.c
@@ -0,0 +1,31 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/drv.h>
+#include <drv/tree.h>
+#include <drv/types.h>
+#include <stdlib.h>
+
+void drv_free(struct drv *const d)
+{
+ if (d)
+ for (size_t i = 0; i < d->n; i++)
+ drv_tree_free[i](d->ports[i]);
+
+ free(d);
+}
diff --git a/src/drv/src/init.c b/src/drv/src/init.c
new file mode 100644
index 0000000..7c62aba
--- /dev/null
+++ b/src/drv/src/init.c
@@ -0,0 +1,62 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/drv.h>
+#include <drv/types.h>
+#include <drv/tree.h>
+#include <drv/port.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+struct drv *drv_init(const struct drv_event *const ev)
+{
+ size_t init = 0;
+ struct drv *const ret = malloc(sizeof *ret);
+ struct drv_port **const ports = malloc(drv_tree_n * sizeof *ports);
+
+ if (!ports || !ret)
+ goto failure;
+
+ for (size_t i = 0; i < drv_tree_n; i++, init++)
+ {
+ struct drv_port *const p = drv_tree_init[i](ev);
+
+ if (!p)
+ goto failure;
+
+ ports[i] = p;
+ }
+
+ *ret = (const struct drv)
+ {
+ .ports = ports,
+ .n = drv_tree_n
+ };
+
+ return ret;
+
+failure:
+
+ if (ports)
+ for (size_t i = 0; i < init; i++)
+ drv_tree_free[i](ports[i]);
+
+ free(ports);
+ free(ret);
+ return NULL;
+}
diff --git a/src/drv/src/tree.c b/src/drv/src/tree.c
new file mode 100644
index 0000000..5759ca2
--- /dev/null
+++ b/src/drv/src/tree.c
@@ -0,0 +1,51 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/drv.h>
+#include <drv/tree.h>
+#include <drv/tty.h>
+#include <drv/port.h>
+#include <stddef.h>
+
+struct drv_port *(*const drv_tree_init[])(const struct drv_event *) =
+{
+#if DRV_PS1
+ drv_ps1_init,
+#endif
+ drv_tty_init
+};
+
+enum {N = sizeof drv_tree_init / sizeof *drv_tree_init};
+
+int (*const drv_tree_update[N])(struct drv_port *) =
+{
+#if DRV_PS1
+ drv_ps1_update,
+#endif
+ drv_tty_update
+};
+
+void (*const drv_tree_free[N])(struct drv_port *) =
+{
+#if DRV_PS1
+ drv_ps1_free,
+#endif
+ drv_tty_free
+};
+
+const size_t drv_tree_n = N;
diff --git a/src/drv/src/update.c b/src/drv/src/update.c
new file mode 100644
index 0000000..e1ee921
--- /dev/null
+++ b/src/drv/src/update.c
@@ -0,0 +1,32 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/drv.h>
+#include <drv/tree.h>
+#include <drv/types.h>
+#include <drv/port.h>
+#include <stddef.h>
+
+int drv_update(struct drv *const d)
+{
+ for (size_t i = 0; i < drv_tree_n; i++)
+ if (drv_tree_update[i](d->ports[i]))
+ return -1;
+
+ return 0;
+}
diff --git a/src/drv/tty/CMakeLists.txt b/src/drv/tty/CMakeLists.txt
new file mode 100644
index 0000000..9661134
--- /dev/null
+++ b/src/drv/tty/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(drv_tty)
+add_subdirectory(src)
+target_include_directories(drv_tty PUBLIC include PRIVATE private_include)
+target_link_libraries(drv_tty PUBLIC c PRIVATE gfx drv_event)
diff --git a/src/drv/tty/include/drv/tty.h b/src/drv/tty/include/drv/tty.h
new file mode 100644
index 0000000..49115f5
--- /dev/null
+++ b/src/drv/tty/include/drv/tty.h
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_TTY_H
+#define DRV_TTY_H
+
+#include <drv/event.h>
+
+struct drv_port *drv_tty_init(const struct drv_event *ev);
+int drv_tty_update(struct drv_port *p);
+void drv_tty_free(struct drv_port *p);
+
+#endif
diff --git a/src/drv/tty/private_include/drv/tty/font.h b/src/drv/tty/private_include/drv/tty/font.h
new file mode 100644
index 0000000..60d9740
--- /dev/null
+++ b/src/drv/tty/private_include/drv/tty/font.h
@@ -0,0 +1,29 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_TTY_FONT_H
+#define DRV_TTY_FONT_H
+
+#include <gfx/sprite.h>
+#include <stddef.h>
+
+struct gfx_sprite ttyfont_spr;
+extern const unsigned char ttyfont[];
+extern const size_t ttyfont_size;
+
+#endif
diff --git a/src/drv/tty/private_include/drv/tty/ops.h b/src/drv/tty/private_include/drv/tty/ops.h
new file mode 100644
index 0000000..1d7cbd2
--- /dev/null
+++ b/src/drv/tty/private_include/drv/tty/ops.h
@@ -0,0 +1,30 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_TTY_OPS_H
+#define DRV_TTY_OPS_H
+
+#include <drv/event.h>
+#include <drv/tty/types.h>
+#include <stddef.h>
+
+int drv_tty_write(const void *buf, size_t n, const struct drv_event_done *done,
+ void *args);
+int drv_tty_setdim(struct drv_port *p, unsigned x, unsigned y);
+
+#endif
diff --git a/src/drv/tty/private_include/drv/tty/types.h b/src/drv/tty/private_include/drv/tty/types.h
new file mode 100644
index 0000000..e8fdd40
--- /dev/null
+++ b/src/drv/tty/private_include/drv/tty/types.h
@@ -0,0 +1,39 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DRV_TTY_TYPES_H
+#define DRV_TTY_TYPES_H
+
+#include <drv/event.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+struct row
+{
+ char *columns;
+};
+
+struct drv_port
+{
+ bool init;
+ struct row *rows, *first_row, *last_row;
+ size_t nrows, ncolumns, last_column;
+ struct drv_event ev;
+};
+
+#endif
diff --git a/src/drv/tty/src/CMakeLists.txt b/src/drv/tty/src/CMakeLists.txt
new file mode 100644
index 0000000..d0690c8
--- /dev/null
+++ b/src/drv/tty/src/CMakeLists.txt
@@ -0,0 +1,27 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(drv_tty PRIVATE
+ free.c
+ init.c
+ setdim.c
+ update.c
+ write.c
+)
+
+if(PS1_BUILD)
+ add_subdirectory(ps1)
+endif()
diff --git a/src/drv/tty/src/free.c b/src/drv/tty/src/free.c
new file mode 100644
index 0000000..346e706
--- /dev/null
+++ b/src/drv/tty/src/free.c
@@ -0,0 +1,39 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/event.h>
+#include <drv/tty.h>
+#include <drv/tty/font.h>
+#include <drv/tty/ops.h>
+#include <drv/tty/types.h>
+#include <gfx/gfx.h>
+#include <gfx/sprite.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+void drv_tty_free(struct drv_port *const p)
+{
+ if (!p)
+ return;
+
+ for (size_t i = 0; i < p->nrows; i++)
+ free(p->rows[i].columns);
+
+ free(p->rows);
+ free(p);
+}
diff --git a/src/drv/tty/src/init.c b/src/drv/tty/src/init.c
new file mode 100644
index 0000000..b436cef
--- /dev/null
+++ b/src/drv/tty/src/init.c
@@ -0,0 +1,58 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/event.h>
+#include <drv/tty.h>
+#include <drv/tty/font.h>
+#include <drv/tty/ops.h>
+#include <drv/tty/types.h>
+#include <gfx/gfx.h>
+#include <gfx/sprite.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int load(void *const buf, const size_t n, void *const args)
+{
+ size_t *const off = args;
+
+ memcpy(buf, ttyfont + *off, n);
+ *off += n;
+ return 0;
+}
+
+struct drv_port *drv_tty_init(const struct drv_event *const ev)
+{
+ size_t off = 0;
+ struct drv_port *ret = NULL;
+
+ if (!(ret = malloc(sizeof *ret)))
+ goto failure;
+
+ *ret = (const struct drv_port){.ev = *ev};
+ gfx_sprite_load(&ttyfont_spr, load, &off);
+
+ if (drv_tty_setdim(ret, screen_w, screen_h))
+ goto failure;
+
+ return ret;
+
+failure:
+ drv_tty_free(ret);
+ return NULL;
+}
diff --git a/src/drv/tty/src/ps1/CMakeLists.txt b/src/drv/tty/src/ps1/CMakeLists.txt
new file mode 100644
index 0000000..0dbe9ef
--- /dev/null
+++ b/src/drv/tty/src/ps1/CMakeLists.txt
@@ -0,0 +1,19 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(drv_tty PRIVATE
+ ttyfont_tim.c
+)
diff --git a/src/drv/tty/src/ps1/ttyfont_tim.c b/src/drv/tty/src/ps1/ttyfont_tim.c
new file mode 100644
index 0000000..ebf22d4
--- /dev/null
+++ b/src/drv/tty/src/ps1/ttyfont_tim.c
@@ -0,0 +1,705 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/* Derived from res/font.bmp. See res/orig/LICENSE for details. */
+
+#include <drv/tty/font.h>
+#include <stddef.h>
+
+const unsigned char ttyfont[] = {
+ 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+ 0x80, 0x02, 0xf2, 0x01, 0x10, 0x00, 0x01, 0x00, 0xe7, 0x18, 0x00, 0x00,
+ 0x8e, 0x31, 0x18, 0x7b, 0xff, 0x7f, 0x80, 0x08, 0x42, 0x08, 0x42, 0x08,
+ 0x44, 0x08, 0x42, 0x00, 0x02, 0x10, 0x80, 0x08, 0x42, 0x08, 0x42, 0x08,
+ 0x42, 0x08, 0x42, 0x08, 0x8c, 0x1f, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00,
+ 0x18, 0x00, 0xa8, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22,
+ 0x22, 0x22, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x22, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x22, 0x22, 0x12, 0x11, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x32,
+ 0x24, 0x43, 0x10, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x22,
+ 0x32, 0x20, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22,
+ 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x32, 0x24, 0x11, 0x11, 0x11, 0x21,
+ 0x32, 0x34, 0x10, 0x11, 0x11, 0x21, 0x32, 0x03, 0x12, 0x11, 0x11, 0x21,
+ 0x03, 0x32, 0x10, 0x11, 0x11, 0x32, 0x03, 0x32, 0x03, 0x11, 0x21, 0x32,
+ 0x44, 0x34, 0x20, 0x11, 0x21, 0x22, 0x12, 0x21, 0x22, 0x11, 0x21, 0x32,
+ 0x44, 0x03, 0x12, 0x11, 0x11, 0x11, 0x21, 0x03, 0x11, 0x11, 0x11, 0x21,
+ 0x43, 0x03, 0x10, 0x11, 0x11, 0x21, 0x43, 0x34, 0x10, 0x11, 0x11, 0x11,
+ 0x00, 0x01, 0x10, 0x11, 0x21, 0x42, 0x04, 0x42, 0x04, 0x12, 0x21, 0x43,
+ 0x40, 0x30, 0x03, 0x11, 0x21, 0x44, 0x10, 0x22, 0x03, 0x11, 0x21, 0x43,
+ 0x00, 0x34, 0x10, 0x11, 0x11, 0x11, 0x11, 0x00, 0x11, 0x11, 0x11, 0x21,
+ 0x44, 0x00, 0x11, 0x11, 0x11, 0x21, 0x44, 0x44, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x21, 0x43, 0x44, 0x44, 0x34, 0x10, 0x21, 0x44,
+ 0x40, 0x00, 0x00, 0x11, 0x21, 0x33, 0x20, 0x42, 0x00, 0x11, 0x21, 0x44,
+ 0x20, 0x34, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x44, 0x10, 0x11, 0x11, 0x11, 0x21, 0x44, 0x44, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x21, 0x40, 0x04, 0x40, 0x04, 0x10, 0x21, 0x43,
+ 0x40, 0x20, 0x12, 0x11, 0x21, 0x00, 0x22, 0x04, 0x10, 0x11, 0x21, 0x43,
+ 0x22, 0x04, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x44, 0x10, 0x11, 0x11, 0x11, 0x21, 0x43, 0x34, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x42, 0x04, 0x11, 0x21, 0x30,
+ 0x44, 0x34, 0x20, 0x11, 0x11, 0x21, 0x42, 0x00, 0x11, 0x11, 0x21, 0x42,
+ 0x44, 0x44, 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x44, 0x10, 0x11, 0x11, 0x11, 0x21, 0x42, 0x04, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x21, 0x42, 0x24, 0x42, 0x04, 0x12, 0x11, 0x02,
+ 0x40, 0x40, 0x03, 0x11, 0x11, 0x22, 0x04, 0x20, 0x22, 0x11, 0x21, 0x43,
+ 0x00, 0x40, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x44, 0x10, 0x11, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x21, 0x43, 0x44, 0x44, 0x34, 0x10, 0x21, 0x22,
+ 0x42, 0x40, 0x04, 0x11, 0x21, 0x42, 0x00, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x20, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x44, 0x10, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x21, 0x40, 0x04, 0x40, 0x04, 0x10, 0x21, 0x33,
+ 0x40, 0x40, 0x03, 0x11, 0x21, 0x03, 0x10, 0x32, 0x03, 0x11, 0x21, 0x43,
+ 0x22, 0x42, 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x44, 0x10, 0x11, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x32, 0x03, 0x32, 0x03, 0x11, 0x21, 0x30,
+ 0x44, 0x34, 0x00, 0x11, 0x21, 0x00, 0x11, 0x02, 0x00, 0x11, 0x21, 0x30,
+ 0x44, 0x34, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x44, 0x20, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x02, 0x00, 0x11, 0x11, 0x02,
+ 0x30, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x02,
+ 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x43, 0x03, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x02, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x30, 0x34, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x02, 0x00, 0x10, 0x11, 0x11, 0x21, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x43, 0x03, 0x12, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x22, 0x22, 0x11, 0x11, 0x11, 0x21, 0x30, 0x34, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x22, 0x11, 0x11, 0x22,
+ 0x43, 0x03, 0x12, 0x11, 0x11, 0x11, 0x02, 0x44, 0x10, 0x11, 0x11, 0x22,
+ 0x12, 0x22, 0x12, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x03, 0x11, 0x21, 0x32,
+ 0x00, 0x34, 0x20, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x32,
+ 0x20, 0x32, 0x10, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x42, 0x00, 0x11, 0x21, 0x43,
+ 0x00, 0x44, 0x03, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x02,
+ 0x24, 0x04, 0x10, 0x11, 0x21, 0x22, 0x42, 0x24, 0x22, 0x12, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x04, 0x10, 0x11, 0x21, 0x44,
+ 0x30, 0x44, 0x04, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x21,
+ 0x42, 0x00, 0x11, 0x11, 0x21, 0x43, 0x44, 0x44, 0x34, 0x10, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x32, 0x44, 0x44, 0x03, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x42, 0x00, 0x11, 0x11, 0x21, 0x44,
+ 0x10, 0x40, 0x04, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x22,
+ 0x04, 0x04, 0x10, 0x11, 0x21, 0x43, 0x44, 0x44, 0x34, 0x10, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x04, 0x10, 0x11, 0x11, 0x21, 0x44,
+ 0x34, 0x40, 0x04, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x32,
+ 0x20, 0x30, 0x10, 0x11, 0x21, 0x00, 0x40, 0x04, 0x00, 0x10, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x21, 0x42, 0x00, 0x11, 0x11, 0x11, 0x21, 0x43,
+ 0x04, 0x40, 0x03, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x02,
+ 0x10, 0x02, 0x10, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x22, 0x22, 0x11, 0x11, 0x21, 0x03, 0x10, 0x11, 0x11, 0x11, 0x21, 0x30,
+ 0x04, 0x30, 0x00, 0x11, 0x11, 0x11, 0x22, 0x44, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x02,
+ 0x43, 0x03, 0x10, 0x11, 0x11, 0x21, 0x32, 0x34, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x11, 0x11, 0x11, 0x11,
+ 0x42, 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x32, 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x00, 0x00, 0x11, 0x11, 0x11, 0x21, 0x43, 0x03, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x32, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x02, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x02, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x22,
+ 0x22, 0x22, 0x12, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11,
+ 0x21, 0x22, 0x12, 0x11, 0x21, 0x22, 0x22, 0x22, 0x12, 0x11, 0x11, 0x22,
+ 0x22, 0x22, 0x12, 0x11, 0x21, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x22,
+ 0x22, 0x22, 0x12, 0x11, 0x11, 0x21, 0x32, 0x03, 0x11, 0x11, 0x21, 0x32,
+ 0x44, 0x34, 0x20, 0x11, 0x11, 0x32, 0x44, 0x44, 0x03, 0x11, 0x11, 0x11,
+ 0x22, 0x33, 0x10, 0x11, 0x21, 0x43, 0x44, 0x34, 0x10, 0x11, 0x21, 0x32,
+ 0x44, 0x34, 0x10, 0x11, 0x21, 0x43, 0x44, 0x44, 0x03, 0x11, 0x21, 0x32,
+ 0x44, 0x34, 0x20, 0x11, 0x11, 0x21, 0x43, 0x04, 0x11, 0x11, 0x21, 0x33,
+ 0x00, 0x40, 0x03, 0x11, 0x11, 0x02, 0x00, 0x40, 0x03, 0x11, 0x11, 0x21,
+ 0x32, 0x44, 0x10, 0x11, 0x21, 0x44, 0x00, 0x00, 0x10, 0x11, 0x21, 0x43,
+ 0x00, 0x00, 0x10, 0x11, 0x21, 0x33, 0x00, 0x40, 0x03, 0x11, 0x21, 0x43,
+ 0x00, 0x40, 0x03, 0x11, 0x11, 0x21, 0x40, 0x04, 0x11, 0x11, 0x21, 0x00,
+ 0x20, 0x42, 0x03, 0x11, 0x11, 0x21, 0x22, 0x33, 0x00, 0x11, 0x11, 0x22,
+ 0x43, 0x44, 0x10, 0x11, 0x21, 0x44, 0x20, 0x22, 0x12, 0x11, 0x21, 0x44,
+ 0x20, 0x22, 0x12, 0x11, 0x21, 0x00, 0x20, 0x43, 0x00, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x22, 0x33, 0x00, 0x11, 0x11, 0x21, 0x43, 0x04, 0x10, 0x11, 0x21, 0x32,
+ 0x03, 0x44, 0x10, 0x11, 0x21, 0x43, 0x44, 0x34, 0x20, 0x11, 0x21, 0x44,
+ 0x44, 0x34, 0x20, 0x11, 0x11, 0x11, 0x22, 0x34, 0x10, 0x11, 0x21, 0x43,
+ 0x22, 0x42, 0x03, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x21,
+ 0x32, 0x03, 0x10, 0x11, 0x11, 0x21, 0x00, 0x33, 0x20, 0x11, 0x21, 0x43,
+ 0x20, 0x44, 0x20, 0x11, 0x21, 0x00, 0x00, 0x40, 0x03, 0x11, 0x21, 0x44,
+ 0x00, 0x40, 0x03, 0x11, 0x11, 0x11, 0x32, 0x04, 0x10, 0x11, 0x21, 0x42,
+ 0x44, 0x44, 0x00, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x22,
+ 0x33, 0x00, 0x11, 0x11, 0x11, 0x11, 0x21, 0x40, 0x03, 0x11, 0x21, 0x43,
+ 0x44, 0x44, 0x03, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x11, 0x21, 0x42, 0x03, 0x11, 0x11, 0x21, 0x43,
+ 0x00, 0x40, 0x03, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x21, 0x32,
+ 0x03, 0x10, 0x11, 0x11, 0x21, 0x22, 0x12, 0x40, 0x04, 0x11, 0x21, 0x00,
+ 0x00, 0x44, 0x00, 0x11, 0x21, 0x22, 0x12, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x11, 0x21, 0x43, 0x00, 0x11, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x11, 0x22, 0x42, 0x04, 0x22, 0x11, 0x21, 0x43,
+ 0x20, 0x22, 0x22, 0x11, 0x21, 0x33, 0x20, 0x42, 0x03, 0x11, 0x11, 0x11,
+ 0x21, 0x44, 0x10, 0x11, 0x21, 0x43, 0x20, 0x42, 0x03, 0x11, 0x21, 0x43,
+ 0x22, 0x42, 0x03, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x21, 0x43,
+ 0x22, 0x42, 0x03, 0x11, 0x11, 0x32, 0x44, 0x44, 0x03, 0x11, 0x21, 0x43,
+ 0x44, 0x44, 0x03, 0x11, 0x21, 0x30, 0x44, 0x34, 0x00, 0x11, 0x11, 0x11,
+ 0x21, 0x33, 0x10, 0x11, 0x21, 0x30, 0x44, 0x34, 0x00, 0x11, 0x21, 0x30,
+ 0x44, 0x34, 0x00, 0x11, 0x11, 0x21, 0x33, 0x10, 0x11, 0x11, 0x21, 0x30,
+ 0x44, 0x34, 0x00, 0x11, 0x11, 0x02, 0x00, 0x00, 0x00, 0x11, 0x21, 0x00,
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x02, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
+ 0x21, 0x00, 0x10, 0x11, 0x11, 0x02, 0x00, 0x00, 0x10, 0x11, 0x11, 0x02,
+ 0x00, 0x00, 0x10, 0x11, 0x11, 0x21, 0x00, 0x10, 0x11, 0x11, 0x11, 0x02,
+ 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x12, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22,
+ 0x22, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x12, 0x11, 0x21, 0x22,
+ 0x22, 0x22, 0x22, 0x12, 0x21, 0x32, 0x44, 0x34, 0x20, 0x11, 0x11, 0x11,
+ 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x21, 0x32, 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x32,
+ 0x03, 0x12, 0x11, 0x11, 0x21, 0x32, 0x44, 0x34, 0x20, 0x11, 0x22, 0x43,
+ 0x44, 0x44, 0x34, 0x20, 0x21, 0x43, 0x00, 0x40, 0x03, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x22, 0x43, 0x04, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x32,
+ 0x34, 0x20, 0x11, 0x11, 0x21, 0x43, 0x03, 0x40, 0x03, 0x11, 0x32, 0x24,
+ 0x22, 0x22, 0x42, 0x03, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x11, 0x11,
+ 0x32, 0x03, 0x11, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x11, 0x21,
+ 0x32, 0x44, 0x00, 0x11, 0x11, 0x32, 0x44, 0x44, 0x03, 0x11, 0x11, 0x02,
+ 0x43, 0x03, 0x12, 0x11, 0x21, 0x33, 0x20, 0x42, 0x03, 0x11, 0x42, 0x22,
+ 0x43, 0x34, 0x20, 0x04, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x11, 0x11,
+ 0x02, 0x00, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x11, 0x11, 0x11, 0x22,
+ 0x43, 0x04, 0x10, 0x11, 0x11, 0x02, 0x00, 0x00, 0x00, 0x11, 0x11, 0x21,
+ 0x30, 0x34, 0x20, 0x11, 0x21, 0x00, 0x20, 0x43, 0x00, 0x11, 0x42, 0x42,
+ 0x04, 0x40, 0x03, 0x04, 0x21, 0x43, 0x22, 0x42, 0x04, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x32,
+ 0x44, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x02, 0x44, 0x03, 0x11, 0x11, 0x11, 0x22, 0x34, 0x10, 0x11, 0x42, 0x42,
+ 0x04, 0x42, 0x04, 0x04, 0x21, 0x30, 0x44, 0x44, 0x04, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x32,
+ 0x44, 0x20, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11,
+ 0x22, 0x44, 0x03, 0x11, 0x11, 0x11, 0x32, 0x04, 0x10, 0x11, 0x42, 0x32,
+ 0x24, 0x42, 0x04, 0x04, 0x11, 0x02, 0x00, 0x40, 0x04, 0x11, 0x11, 0x11,
+ 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x02,
+ 0x43, 0x04, 0x12, 0x11, 0x11, 0x32, 0x44, 0x44, 0x03, 0x11, 0x11, 0x21,
+ 0x32, 0x34, 0x00, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x42, 0x02,
+ 0x43, 0x44, 0x44, 0x04, 0x11, 0x22, 0x22, 0x42, 0x03, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x21,
+ 0x30, 0x44, 0x20, 0x11, 0x11, 0x02, 0x00, 0x00, 0x00, 0x11, 0x11, 0x22,
+ 0x43, 0x03, 0x10, 0x11, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x32, 0x24,
+ 0x00, 0x00, 0x20, 0x03, 0x11, 0x32, 0x44, 0x34, 0x00, 0x11, 0x11, 0x11,
+ 0x32, 0x03, 0x11, 0x11, 0x11, 0x11, 0x42, 0x03, 0x11, 0x11, 0x11, 0x11,
+ 0x02, 0x43, 0x04, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x32,
+ 0x34, 0x00, 0x11, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x02, 0x43,
+ 0x44, 0x44, 0x34, 0x00, 0x11, 0x02, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
+ 0x02, 0x00, 0x11, 0x11, 0x11, 0x11, 0x32, 0x00, 0x11, 0x11, 0x11, 0x11,
+ 0x21, 0x30, 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x32,
+ 0x03, 0x10, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x11, 0x11, 0x21, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x02, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x02, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x02,
+ 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x22, 0x22, 0x11, 0x11, 0x21, 0x22,
+ 0x22, 0x22, 0x12, 0x11, 0x11, 0x22, 0x22, 0x22, 0x12, 0x11, 0x21, 0x22,
+ 0x22, 0x22, 0x11, 0x11, 0x21, 0x22, 0x22, 0x22, 0x22, 0x11, 0x21, 0x22,
+ 0x22, 0x22, 0x22, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x21, 0x22,
+ 0x12, 0x22, 0x22, 0x11, 0x11, 0x22, 0x43, 0x03, 0x12, 0x11, 0x21, 0x43,
+ 0x44, 0x34, 0x20, 0x11, 0x21, 0x32, 0x44, 0x34, 0x20, 0x11, 0x21, 0x43,
+ 0x44, 0x03, 0x12, 0x11, 0x21, 0x43, 0x44, 0x44, 0x03, 0x11, 0x21, 0x43,
+ 0x44, 0x44, 0x03, 0x11, 0x21, 0x32, 0x44, 0x44, 0x03, 0x11, 0x21, 0x33,
+ 0x10, 0x32, 0x03, 0x11, 0x21, 0x32, 0x03, 0x33, 0x20, 0x11, 0x21, 0x44,
+ 0x00, 0x40, 0x03, 0x11, 0x21, 0x43, 0x03, 0x30, 0x03, 0x11, 0x21, 0x44,
+ 0x00, 0x33, 0x20, 0x11, 0x21, 0x44, 0x00, 0x00, 0x00, 0x11, 0x21, 0x44,
+ 0x00, 0x00, 0x00, 0x11, 0x21, 0x43, 0x03, 0x00, 0x00, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x43, 0x00, 0x40, 0x03, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x00, 0x02, 0x00, 0x11, 0x21, 0x44,
+ 0x10, 0x40, 0x03, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x21, 0x44,
+ 0x00, 0x00, 0x10, 0x11, 0x21, 0x44, 0x00, 0x11, 0x11, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x22, 0x42, 0x03, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x00, 0x00, 0x10, 0x11, 0x21, 0x44,
+ 0x44, 0x34, 0x10, 0x11, 0x21, 0x44, 0x20, 0x22, 0x22, 0x11, 0x21, 0x44,
+ 0x00, 0x42, 0x04, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x44, 0x44, 0x00, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x44, 0x34, 0x10, 0x11, 0x21, 0x44,
+ 0x00, 0x00, 0x10, 0x11, 0x21, 0x44, 0x20, 0x43, 0x03, 0x11, 0x21, 0x44,
+ 0x44, 0x44, 0x04, 0x11, 0x21, 0x44, 0x22, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x00, 0x40, 0x03, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x00, 0x00, 0x10, 0x11, 0x21, 0x44,
+ 0x10, 0x11, 0x11, 0x11, 0x21, 0x44, 0x20, 0x40, 0x04, 0x11, 0x21, 0x44,
+ 0x00, 0x40, 0x04, 0x11, 0x21, 0x44, 0x44, 0x44, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x02, 0x22, 0x22, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x03, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x21, 0x44,
+ 0x10, 0x11, 0x11, 0x11, 0x21, 0x44, 0x00, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x00, 0x40, 0x04, 0x11, 0x21, 0x44,
+ 0x22, 0x42, 0x03, 0x11, 0x21, 0x43, 0x23, 0x32, 0x03, 0x11, 0x21, 0x44,
+ 0x20, 0x33, 0x00, 0x11, 0x21, 0x44, 0x00, 0x00, 0x00, 0x11, 0x21, 0x44,
+ 0x10, 0x11, 0x11, 0x11, 0x21, 0x43, 0x03, 0x40, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x33, 0x10, 0x32, 0x03, 0x11, 0x21, 0x43,
+ 0x44, 0x34, 0x00, 0x11, 0x21, 0x30, 0x44, 0x34, 0x00, 0x11, 0x21, 0x43,
+ 0x44, 0x03, 0x10, 0x11, 0x21, 0x43, 0x44, 0x44, 0x03, 0x11, 0x21, 0x33,
+ 0x10, 0x11, 0x11, 0x11, 0x21, 0x30, 0x44, 0x44, 0x03, 0x11, 0x21, 0x33,
+ 0x10, 0x32, 0x03, 0x11, 0x21, 0x00, 0x10, 0x02, 0x00, 0x11, 0x21, 0x00,
+ 0x00, 0x00, 0x10, 0x11, 0x11, 0x02, 0x00, 0x00, 0x10, 0x11, 0x21, 0x00,
+ 0x00, 0x00, 0x11, 0x11, 0x21, 0x00, 0x00, 0x00, 0x00, 0x11, 0x21, 0x00,
+ 0x10, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x00, 0x00, 0x11, 0x21, 0x00,
+ 0x10, 0x02, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11,
+ 0x11, 0x22, 0x22, 0x11, 0x21, 0x22, 0x12, 0x22, 0x22, 0x11, 0x11, 0x22,
+ 0x22, 0x11, 0x11, 0x11, 0x21, 0x22, 0x11, 0x21, 0x22, 0x11, 0x21, 0x22,
+ 0x12, 0x22, 0x22, 0x11, 0x11, 0x22, 0x22, 0x22, 0x12, 0x11, 0x21, 0x22,
+ 0x22, 0x22, 0x12, 0x11, 0x11, 0x32, 0x44, 0x44, 0x03, 0x11, 0x11, 0x11,
+ 0x11, 0x32, 0x03, 0x11, 0x21, 0x33, 0x10, 0x32, 0x03, 0x11, 0x11, 0x32,
+ 0x03, 0x11, 0x11, 0x11, 0x21, 0x03, 0x12, 0x22, 0x03, 0x11, 0x21, 0x33,
+ 0x10, 0x32, 0x03, 0x11, 0x21, 0x32, 0x44, 0x34, 0x20, 0x11, 0x21, 0x43,
+ 0x44, 0x34, 0x20, 0x11, 0x11, 0x02, 0x40, 0x04, 0x00, 0x11, 0x11, 0x11,
+ 0x11, 0x42, 0x04, 0x11, 0x21, 0x44, 0x20, 0x42, 0x03, 0x11, 0x11, 0x42,
+ 0x04, 0x11, 0x11, 0x11, 0x21, 0x34, 0x20, 0x32, 0x04, 0x11, 0x21, 0x44,
+ 0x20, 0x42, 0x04, 0x11, 0x21, 0x43, 0x00, 0x40, 0x03, 0x11, 0x21, 0x44,
+ 0x00, 0x40, 0x03, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x42, 0x04, 0x11, 0x21, 0x44, 0x00, 0x33, 0x00, 0x11, 0x11, 0x42,
+ 0x04, 0x11, 0x11, 0x11, 0x21, 0x44, 0x23, 0x43, 0x04, 0x11, 0x21, 0x44,
+ 0x03, 0x42, 0x04, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x42, 0x04, 0x11, 0x21, 0x44, 0x44, 0x04, 0x12, 0x11, 0x11, 0x42,
+ 0x04, 0x11, 0x11, 0x11, 0x21, 0x44, 0x44, 0x44, 0x04, 0x11, 0x21, 0x44,
+ 0x34, 0x40, 0x04, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x22, 0x42, 0x03, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x42, 0x04, 0x11, 0x21, 0x44, 0x00, 0x33, 0x20, 0x11, 0x11, 0x42,
+ 0x04, 0x11, 0x11, 0x11, 0x21, 0x44, 0x30, 0x40, 0x04, 0x11, 0x21, 0x44,
+ 0x44, 0x44, 0x04, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x44, 0x34, 0x00, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x21, 0x22,
+ 0x12, 0x42, 0x04, 0x11, 0x21, 0x44, 0x00, 0x40, 0x03, 0x11, 0x11, 0x42,
+ 0x04, 0x11, 0x11, 0x11, 0x21, 0x44, 0x00, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x30, 0x44, 0x04, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x21, 0x33,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x10, 0x40, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x00, 0x43, 0x04, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x11, 0x11, 0x11, 0x11, 0x22, 0x42, 0x04, 0x22, 0x11, 0x21, 0x43,
+ 0x20, 0x42, 0x03, 0x11, 0x21, 0x44, 0x10, 0x40, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x22, 0x22, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x20, 0x40, 0x04, 0x11, 0x21, 0x43, 0x22, 0x42, 0x03, 0x11, 0x21, 0x44,
+ 0x10, 0x11, 0x11, 0x11, 0x11, 0x32, 0x44, 0x44, 0x03, 0x11, 0x21, 0x30,
+ 0x44, 0x34, 0x00, 0x11, 0x21, 0x33, 0x10, 0x30, 0x03, 0x11, 0x11, 0x42,
+ 0x44, 0x44, 0x03, 0x11, 0x21, 0x33, 0x10, 0x32, 0x03, 0x11, 0x21, 0x33,
+ 0x10, 0x32, 0x03, 0x11, 0x21, 0x30, 0x44, 0x34, 0x00, 0x11, 0x21, 0x33,
+ 0x10, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x00, 0x00, 0x11, 0x11, 0x02,
+ 0x00, 0x00, 0x10, 0x11, 0x21, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x02,
+ 0x00, 0x00, 0x00, 0x11, 0x21, 0x00, 0x10, 0x02, 0x00, 0x11, 0x21, 0x00,
+ 0x10, 0x02, 0x00, 0x11, 0x11, 0x02, 0x00, 0x00, 0x10, 0x11, 0x21, 0x00,
+ 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x12, 0x11, 0x21, 0x22,
+ 0x22, 0x22, 0x12, 0x11, 0x11, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x22,
+ 0x22, 0x22, 0x22, 0x11, 0x21, 0x22, 0x12, 0x22, 0x22, 0x11, 0x21, 0x22,
+ 0x12, 0x22, 0x22, 0x11, 0x21, 0x22, 0x12, 0x22, 0x22, 0x11, 0x21, 0x22,
+ 0x12, 0x22, 0x22, 0x11, 0x21, 0x32, 0x44, 0x34, 0x20, 0x11, 0x21, 0x43,
+ 0x44, 0x34, 0x20, 0x11, 0x21, 0x32, 0x44, 0x03, 0x12, 0x11, 0x11, 0x32,
+ 0x44, 0x44, 0x03, 0x11, 0x21, 0x33, 0x10, 0x32, 0x03, 0x11, 0x21, 0x33,
+ 0x10, 0x32, 0x03, 0x11, 0x21, 0x33, 0x10, 0x32, 0x03, 0x11, 0x21, 0x33,
+ 0x10, 0x32, 0x03, 0x11, 0x21, 0x43, 0x00, 0x42, 0x03, 0x11, 0x21, 0x44,
+ 0x00, 0x42, 0x03, 0x11, 0x21, 0x43, 0x00, 0x33, 0x10, 0x11, 0x11, 0x02,
+ 0x40, 0x04, 0x00, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x20, 0x00, 0x10, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x20, 0x42, 0x04, 0x11, 0x21, 0x43,
+ 0x00, 0x42, 0x03, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x43, 0x20, 0x22, 0x12, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x44, 0x30, 0x42, 0x04, 0x11, 0x21, 0x30,
+ 0x23, 0x33, 0x00, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x22, 0x43, 0x03, 0x11, 0x21, 0x30, 0x44, 0x34, 0x20, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x00, 0x42, 0x04, 0x11, 0x21, 0x44, 0x44, 0x44, 0x04, 0x11, 0x11, 0x02,
+ 0x44, 0x04, 0x10, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x44,
+ 0x44, 0x24, 0x00, 0x11, 0x11, 0x02, 0x00, 0x40, 0x03, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x43,
+ 0x23, 0x43, 0x03, 0x11, 0x21, 0x44, 0x44, 0x44, 0x04, 0x11, 0x21, 0x32,
+ 0x03, 0x33, 0x00, 0x11, 0x21, 0x44, 0x20, 0x42, 0x03, 0x11, 0x21, 0x44,
+ 0x30, 0x34, 0x02, 0x11, 0x21, 0x22, 0x12, 0x40, 0x04, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x44, 0x10, 0x42, 0x04, 0x11, 0x21, 0x30,
+ 0x44, 0x34, 0x00, 0x11, 0x21, 0x44, 0x03, 0x43, 0x04, 0x11, 0x21, 0x43,
+ 0x00, 0x40, 0x03, 0x11, 0x21, 0x43, 0x32, 0x44, 0x02, 0x11, 0x21, 0x44,
+ 0x00, 0x43, 0x23, 0x11, 0x21, 0x33, 0x00, 0x40, 0x03, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x43, 0x00, 0x42, 0x03, 0x11, 0x11, 0x02,
+ 0x43, 0x03, 0x10, 0x11, 0x21, 0x44, 0x00, 0x40, 0x04, 0x11, 0x21, 0x44,
+ 0x10, 0x42, 0x04, 0x11, 0x21, 0x30, 0x34, 0x30, 0x23, 0x11, 0x21, 0x33,
+ 0x20, 0x30, 0x03, 0x11, 0x21, 0x30, 0x44, 0x34, 0x00, 0x11, 0x11, 0x11,
+ 0x32, 0x03, 0x11, 0x11, 0x21, 0x30, 0x44, 0x34, 0x00, 0x11, 0x11, 0x21,
+ 0x30, 0x00, 0x11, 0x11, 0x21, 0x33, 0x10, 0x30, 0x03, 0x11, 0x21, 0x33,
+ 0x10, 0x32, 0x03, 0x11, 0x11, 0x02, 0x00, 0x02, 0x00, 0x11, 0x21, 0x00,
+ 0x10, 0x02, 0x00, 0x11, 0x11, 0x02, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
+ 0x02, 0x00, 0x11, 0x11, 0x11, 0x02, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
+ 0x02, 0x10, 0x11, 0x11, 0x21, 0x00, 0x10, 0x00, 0x00, 0x11, 0x21, 0x00,
+ 0x10, 0x02, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x22, 0x22, 0x12, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x22, 0x22, 0x12, 0x11, 0x11, 0x11,
+ 0x22, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x22, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x21, 0x22,
+ 0x22, 0x22, 0x22, 0x11, 0x11, 0x21, 0x43, 0x34, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x43, 0x34, 0x10, 0x11, 0x11, 0x21,
+ 0x42, 0x20, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x03, 0x12, 0x11, 0x11, 0x11, 0x32, 0x03, 0x32, 0x03, 0x11, 0x21, 0x43,
+ 0x44, 0x44, 0x03, 0x11, 0x11, 0x21, 0x44, 0x00, 0x10, 0x11, 0x21, 0x22,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x00, 0x44, 0x10, 0x11, 0x11, 0x22,
+ 0x04, 0x04, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x40, 0x20, 0x11, 0x11, 0x11, 0x42, 0x04, 0x42, 0x04, 0x11, 0x21, 0x00,
+ 0x00, 0x40, 0x04, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x21, 0x03,
+ 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x42,
+ 0x20, 0x30, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x02, 0x04, 0x12, 0x11, 0x11, 0x32, 0x04, 0x42, 0x03, 0x11, 0x11, 0x11,
+ 0x22, 0x43, 0x03, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x21, 0x40,
+ 0x20, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x02,
+ 0x10, 0x02, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x21, 0x30, 0x10, 0x11, 0x11, 0x02, 0x43, 0x34, 0x00, 0x11, 0x11, 0x21,
+ 0x32, 0x34, 0x00, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x02,
+ 0x04, 0x12, 0x11, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x02, 0x10, 0x11, 0x11, 0x21, 0x40, 0x04, 0x10, 0x11, 0x11, 0x22,
+ 0x43, 0x03, 0x10, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x21,
+ 0x40, 0x20, 0x11, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x21, 0x32,
+ 0x34, 0x00, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x02, 0x04, 0x12, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x21, 0x43,
+ 0x03, 0x10, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x21, 0x40, 0x20, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x21, 0x44,
+ 0x20, 0x22, 0x22, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x02, 0x03, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x21, 0x43,
+ 0x44, 0x44, 0x03, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x21, 0x00, 0x11, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x11, 0x11, 0x21, 0x00,
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x21, 0x44, 0x20, 0x12, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x22, 0x44, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x43, 0x34, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x43, 0x34, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x32, 0x44, 0x44, 0x03, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x22, 0x22, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22,
+ 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22,
+ 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x32, 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x32, 0x34, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x32,
+ 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x32,
+ 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x43, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x42,
+ 0x04, 0x11, 0x11, 0x11, 0x11, 0x21, 0x22, 0x22, 0x12, 0x11, 0x11, 0x42,
+ 0x04, 0x11, 0x11, 0x11, 0x11, 0x21, 0x22, 0x22, 0x12, 0x11, 0x11, 0x21,
+ 0x22, 0x42, 0x04, 0x11, 0x11, 0x21, 0x22, 0x22, 0x12, 0x11, 0x11, 0x22,
+ 0x44, 0x20, 0x12, 0x11, 0x11, 0x21, 0x22, 0x22, 0x22, 0x11, 0x11, 0x42,
+ 0x04, 0x11, 0x11, 0x11, 0x11, 0x22, 0x43, 0x34, 0x20, 0x11, 0x11, 0x42,
+ 0x04, 0x22, 0x12, 0x11, 0x11, 0x22, 0x43, 0x34, 0x20, 0x11, 0x11, 0x22,
+ 0x43, 0x44, 0x04, 0x11, 0x11, 0x22, 0x43, 0x34, 0x20, 0x11, 0x11, 0x32,
+ 0x44, 0x34, 0x10, 0x11, 0x11, 0x22, 0x43, 0x44, 0x03, 0x11, 0x11, 0x42,
+ 0x04, 0x22, 0x12, 0x11, 0x11, 0x42, 0x04, 0x40, 0x03, 0x11, 0x11, 0x42,
+ 0x44, 0x34, 0x20, 0x11, 0x11, 0x32, 0x04, 0x30, 0x03, 0x11, 0x11, 0x32,
+ 0x04, 0x40, 0x04, 0x11, 0x11, 0x32, 0x04, 0x40, 0x03, 0x11, 0x11, 0x02,
+ 0x44, 0x00, 0x10, 0x11, 0x11, 0x32, 0x04, 0x40, 0x04, 0x11, 0x11, 0x42,
+ 0x44, 0x34, 0x20, 0x11, 0x11, 0x42, 0x04, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x40, 0x03, 0x11, 0x11, 0x42, 0x04, 0x22, 0x22, 0x11, 0x11, 0x42,
+ 0x04, 0x40, 0x04, 0x11, 0x11, 0x42, 0x44, 0x44, 0x03, 0x11, 0x11, 0x21,
+ 0x44, 0x10, 0x11, 0x11, 0x11, 0x42, 0x04, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x40, 0x03, 0x11, 0x11, 0x32, 0x24, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x42, 0x03, 0x11, 0x11, 0x32, 0x24, 0x32, 0x03, 0x11, 0x11, 0x32,
+ 0x04, 0x40, 0x04, 0x11, 0x11, 0x32, 0x04, 0x00, 0x00, 0x11, 0x11, 0x21,
+ 0x44, 0x10, 0x11, 0x11, 0x11, 0x32, 0x24, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x42, 0x04, 0x11, 0x11, 0x02, 0x43, 0x44, 0x03, 0x11, 0x11, 0x32,
+ 0x44, 0x34, 0x00, 0x11, 0x11, 0x02, 0x43, 0x34, 0x00, 0x11, 0x11, 0x02,
+ 0x43, 0x44, 0x03, 0x11, 0x11, 0x02, 0x43, 0x34, 0x10, 0x11, 0x11, 0x21,
+ 0x33, 0x10, 0x11, 0x11, 0x11, 0x22, 0x43, 0x44, 0x04, 0x11, 0x11, 0x32,
+ 0x03, 0x32, 0x03, 0x11, 0x11, 0x21, 0x00, 0x00, 0x00, 0x11, 0x11, 0x02,
+ 0x00, 0x00, 0x10, 0x11, 0x11, 0x21, 0x00, 0x00, 0x10, 0x11, 0x11, 0x21,
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x21, 0x00, 0x00, 0x10, 0x11, 0x11, 0x21,
+ 0x00, 0x10, 0x11, 0x11, 0x11, 0x22, 0x22, 0x42, 0x03, 0x11, 0x11, 0x02,
+ 0x00, 0x02, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x32, 0x44, 0x34, 0x00, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x22, 0x22, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x43, 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x32, 0x03, 0x11, 0x11, 0x42, 0x04, 0x22, 0x22, 0x11, 0x11, 0x21,
+ 0x40, 0x04, 0x11, 0x11, 0x21, 0x22, 0x22, 0x22, 0x12, 0x11, 0x11, 0x22,
+ 0x22, 0x22, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x22, 0x22, 0x11, 0x11, 0x42, 0x04, 0x32, 0x03, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x43, 0x44, 0x34, 0x20, 0x11, 0x11, 0x32,
+ 0x44, 0x34, 0x20, 0x11, 0x11, 0x21, 0x22, 0x22, 0x12, 0x11, 0x11, 0x21,
+ 0x22, 0x22, 0x12, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x32, 0x03, 0x11, 0x11, 0x42, 0x24, 0x33, 0x00, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x44, 0x40, 0x42, 0x03, 0x11, 0x11, 0x42,
+ 0x04, 0x42, 0x03, 0x11, 0x11, 0x22, 0x43, 0x34, 0x20, 0x11, 0x11, 0x22,
+ 0x43, 0x34, 0x20, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x42, 0x04, 0x11, 0x11, 0x42, 0x44, 0x04, 0x10, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x44, 0x40, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x42, 0x04, 0x11, 0x11, 0x32, 0x04, 0x40, 0x03, 0x11, 0x11, 0x32,
+ 0x04, 0x40, 0x03, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x42, 0x04, 0x11, 0x11, 0x42, 0x04, 0x33, 0x20, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x44, 0x30, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x42, 0x04, 0x11, 0x11, 0x42, 0x04, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x42, 0x04, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x42, 0x04, 0x11, 0x11, 0x42, 0x04, 0x42, 0x03, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x21, 0x44, 0x00, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x42, 0x04, 0x11, 0x11, 0x32, 0x24, 0x42, 0x03, 0x11, 0x11, 0x42,
+ 0x24, 0x42, 0x03, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x11, 0x22,
+ 0x22, 0x42, 0x04, 0x11, 0x11, 0x32, 0x03, 0x32, 0x03, 0x11, 0x11, 0x11,
+ 0x32, 0x03, 0x11, 0x11, 0x21, 0x33, 0x10, 0x32, 0x03, 0x11, 0x11, 0x32,
+ 0x03, 0x32, 0x03, 0x11, 0x11, 0x02, 0x43, 0x34, 0x00, 0x11, 0x11, 0x42,
+ 0x44, 0x34, 0x00, 0x11, 0x11, 0x11, 0x02, 0x00, 0x11, 0x11, 0x11, 0x32,
+ 0x03, 0x42, 0x03, 0x11, 0x11, 0x02, 0x00, 0x02, 0x00, 0x11, 0x11, 0x11,
+ 0x02, 0x00, 0x11, 0x11, 0x21, 0x00, 0x10, 0x02, 0x00, 0x11, 0x11, 0x02,
+ 0x00, 0x02, 0x00, 0x11, 0x11, 0x21, 0x00, 0x00, 0x10, 0x11, 0x11, 0x42,
+ 0x04, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x02,
+ 0x43, 0x34, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x32,
+ 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21,
+ 0x00, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x02,
+ 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x22,
+ 0x12, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22,
+ 0x22, 0x22, 0x12, 0x11, 0x11, 0x21, 0x22, 0x22, 0x12, 0x11, 0x11, 0x21,
+ 0x32, 0x03, 0x12, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x22,
+ 0x22, 0x22, 0x22, 0x11, 0x21, 0x22, 0x12, 0x22, 0x22, 0x11, 0x21, 0x33,
+ 0x10, 0x32, 0x03, 0x11, 0x11, 0x21, 0x22, 0x22, 0x12, 0x11, 0x11, 0x32,
+ 0x23, 0x34, 0x10, 0x11, 0x11, 0x22, 0x43, 0x34, 0x10, 0x11, 0x11, 0x21,
+ 0x43, 0x34, 0x10, 0x11, 0x11, 0x32, 0x03, 0x32, 0x03, 0x11, 0x11, 0x32,
+ 0x03, 0x32, 0x03, 0x11, 0x21, 0x33, 0x10, 0x32, 0x03, 0x11, 0x21, 0x43,
+ 0x20, 0x42, 0x03, 0x11, 0x11, 0x22, 0x43, 0x34, 0x20, 0x11, 0x11, 0x42,
+ 0x34, 0x00, 0x10, 0x11, 0x11, 0x32, 0x04, 0x00, 0x10, 0x11, 0x11, 0x21,
+ 0x40, 0x04, 0x10, 0x11, 0x11, 0x42, 0x04, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x42, 0x04, 0x11, 0x21, 0x44, 0x20, 0x42, 0x04, 0x11, 0x21, 0x30,
+ 0x23, 0x33, 0x00, 0x11, 0x11, 0x32, 0x04, 0x40, 0x03, 0x11, 0x11, 0x42,
+ 0x04, 0x10, 0x11, 0x11, 0x11, 0x32, 0x44, 0x03, 0x12, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x11, 0x42, 0x04, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x42, 0x04, 0x11, 0x21, 0x44, 0x30, 0x42, 0x04, 0x11, 0x11, 0x22,
+ 0x44, 0x04, 0x10, 0x11, 0x11, 0x42, 0x04, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x11, 0x11, 0x11, 0x11, 0x02, 0x43, 0x34, 0x10, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x11, 0x11, 0x11, 0x42, 0x04, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x24, 0x42, 0x03, 0x11, 0x21, 0x44, 0x40, 0x42, 0x04, 0x11, 0x21, 0x32,
+ 0x03, 0x33, 0x00, 0x11, 0x11, 0x32, 0x24, 0x42, 0x04, 0x11, 0x11, 0x42,
+ 0x04, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x34, 0x10, 0x11, 0x11, 0x11,
+ 0x42, 0x04, 0x10, 0x11, 0x11, 0x32, 0x04, 0x42, 0x04, 0x11, 0x11, 0x32,
+ 0x24, 0x33, 0x00, 0x11, 0x21, 0x44, 0x30, 0x42, 0x03, 0x11, 0x21, 0x43,
+ 0x00, 0x40, 0x03, 0x11, 0x11, 0x02, 0x43, 0x44, 0x04, 0x11, 0x11, 0x32,
+ 0x03, 0x11, 0x11, 0x11, 0x11, 0x32, 0x44, 0x03, 0x10, 0x11, 0x11, 0x11,
+ 0x32, 0x34, 0x10, 0x11, 0x11, 0x02, 0x43, 0x44, 0x03, 0x11, 0x11, 0x02,
+ 0x43, 0x03, 0x10, 0x11, 0x21, 0x43, 0x03, 0x33, 0x00, 0x11, 0x21, 0x33,
+ 0x10, 0x32, 0x03, 0x11, 0x11, 0x21, 0x00, 0x40, 0x04, 0x11, 0x11, 0x02,
+ 0x00, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,
+ 0x02, 0x00, 0x10, 0x11, 0x11, 0x21, 0x00, 0x00, 0x00, 0x11, 0x11, 0x21,
+ 0x00, 0x00, 0x11, 0x11, 0x21, 0x00, 0x00, 0x00, 0x10, 0x11, 0x21, 0x00,
+ 0x10, 0x02, 0x00, 0x11, 0x11, 0x11, 0x11, 0x32, 0x03, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x12, 0x11, 0x11, 0x11,
+ 0x22, 0x12, 0x11, 0x11, 0x11, 0x22, 0x22, 0x12, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x32, 0x34, 0x10, 0x11, 0x11, 0x11,
+ 0x32, 0x10, 0x11, 0x11, 0x11, 0x32, 0x34, 0x20, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x43, 0x03, 0x10, 0x11, 0x11, 0x11,
+ 0x42, 0x10, 0x11, 0x11, 0x11, 0x02, 0x43, 0x03, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22,
+ 0x22, 0x22, 0x22, 0x11, 0x11, 0x21, 0x44, 0x00, 0x11, 0x11, 0x11, 0x11,
+ 0x42, 0x10, 0x11, 0x11, 0x11, 0x21, 0x40, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x32,
+ 0x44, 0x44, 0x03, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x42, 0x10, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x32, 0x03, 0x32, 0x03, 0x11, 0x11, 0x02,
+ 0x00, 0x42, 0x03, 0x11, 0x11, 0x22, 0x44, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x42, 0x10, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x12, 0x11, 0x11, 0x21,
+ 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x42, 0x04, 0x11, 0x11, 0x11,
+ 0x22, 0x33, 0x00, 0x11, 0x11, 0x42, 0x04, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x42, 0x10, 0x11, 0x11, 0x11, 0x11, 0x02, 0x44, 0x10, 0x11, 0x11, 0x22,
+ 0x34, 0x20, 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x42, 0x04, 0x11, 0x11, 0x21,
+ 0x32, 0x03, 0x10, 0x11, 0x11, 0x42, 0x04, 0x12, 0x11, 0x11, 0x11, 0x11,
+ 0x42, 0x10, 0x11, 0x11, 0x11, 0x11, 0x22, 0x44, 0x10, 0x11, 0x11, 0x32,
+ 0x00, 0x43, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x32, 0x04, 0x42, 0x04, 0x11, 0x11, 0x22,
+ 0x33, 0x00, 0x11, 0x11, 0x11, 0x02, 0x44, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x42, 0x10, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x10, 0x11, 0x11, 0x02,
+ 0x20, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x02, 0x43, 0x44, 0x04, 0x11, 0x11, 0x32,
+ 0x04, 0x22, 0x22, 0x11, 0x11, 0x21, 0x44, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x42, 0x10, 0x11, 0x11, 0x11, 0x11, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x00, 0x42, 0x03, 0x11, 0x11, 0x32,
+ 0x44, 0x44, 0x03, 0x11, 0x11, 0x21, 0x44, 0x20, 0x11, 0x11, 0x11, 0x11,
+ 0x42, 0x10, 0x11, 0x11, 0x11, 0x21, 0x42, 0x04, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x33, 0x00, 0x11, 0x11, 0x02,
+ 0x00, 0x00, 0x00, 0x11, 0x11, 0x21, 0x43, 0x03, 0x12, 0x11, 0x11, 0x11,
+ 0x42, 0x10, 0x11, 0x11, 0x11, 0x22, 0x43, 0x03, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x32, 0x44, 0x03, 0x10, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x21, 0x30, 0x34, 0x10, 0x11, 0x11, 0x11,
+ 0x32, 0x10, 0x11, 0x11, 0x11, 0x32, 0x34, 0x00, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x02, 0x00, 0x10, 0x11, 0x11, 0x11,
+ 0x02, 0x10, 0x11, 0x11, 0x11, 0x02, 0x00, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11
+};
+
+const size_t ttyfont_size = sizeof ttyfont;
diff --git a/src/drv/tty/src/setdim.c b/src/drv/tty/src/setdim.c
new file mode 100644
index 0000000..3170197
--- /dev/null
+++ b/src/drv/tty/src/setdim.c
@@ -0,0 +1,62 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/event.h>
+#include <drv/tty.h>
+#include <drv/tty/font.h>
+#include <drv/tty/ops.h>
+#include <drv/tty/types.h>
+#include <gfx/gfx.h>
+#include <gfx/sprite.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+int drv_tty_setdim(struct drv_port *const p, const unsigned w, const unsigned h)
+{
+ const unsigned columns = w / 8, rows = h / 14;
+ struct row *const prs = malloc(rows * sizeof *prs);
+
+ if (!prs)
+ goto failure;
+
+ for (unsigned i = 0; i < rows; i++)
+ *(prs + i) = (const struct row){0};
+
+ for (unsigned i = 0; i < rows; i++)
+ {
+ struct row *const p = &prs[i];
+ char *const c = malloc(columns);
+
+ if (!c)
+ goto failure;
+
+ p->columns = c;
+ }
+
+ p->first_row = p->last_row = p->rows = prs;
+ p->nrows = rows;
+ p->ncolumns = columns;
+ return 0;
+
+failure:
+ for (unsigned i = 0; i < rows; i++)
+ free(prs[i].columns);
+
+ free(prs);
+ return -1;
+}
diff --git a/src/drv/tty/src/update.c b/src/drv/tty/src/update.c
new file mode 100644
index 0000000..b65f3f0
--- /dev/null
+++ b/src/drv/tty/src/update.c
@@ -0,0 +1,104 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/event.h>
+#include <drv/tty.h>
+#include <drv/tty/font.h>
+#include <drv/tty/ops.h>
+#include <drv/tty/types.h>
+#include <gfx/gfx.h>
+#include <gfx/sprite.h>
+#include <stdbool.h>
+
+static int init(struct drv_port *const p)
+{
+ const struct drv_event *const ev = &p->ev;
+ const struct drv_event_ops ops =
+ {
+ .write = drv_tty_write,
+ .args = p
+ };
+
+ if (p->init)
+ return 0;
+ else if (ev->status("tty", &ops, true, ev->args))
+ return -1;
+
+ p->init = true;
+ return 0;
+}
+
+static int draw(struct drv_port *const p)
+{
+ short y = 0;
+ const struct row *r = p->first_row, *last = p->last_row + 1;
+
+ if (last - p->rows >= p->nrows)
+ last = p->rows;
+
+ for (;;)
+ {
+ short x = 0;
+
+ for (const char *c = r->columns;
+ *c && c - r->columns < p->ncolumns; c++, x += 8)
+ {
+ if (*c == ' ')
+ continue;
+
+ struct gfx_sprite *const s = gfx_sprite_get();
+ const char ch = *c - '!';
+ const short u = (12 * ch) % ttyfont_spr.w;
+ const short v = 14 * ((12 * ch) / ttyfont_spr.w);
+
+ if (!s || gfx_sprite_clone(&ttyfont_spr, s))
+ return -1;
+
+ /* TODO: replace hardcoded values */
+ s->x = x;
+ s->y = y;
+ s->w = 12;
+ s->h = 14;
+ s->u += u;
+ s->v += v;
+
+ if (gfx_sprite_sort(s))
+ return -1;
+ }
+
+ if (++r - p->rows >= p->nrows)
+ r = p->rows;
+
+ if (r == last)
+ break;
+
+ y += 14;
+ }
+
+ return gfx_draw();
+}
+
+int drv_tty_update(struct drv_port *const p)
+{
+ if (init(p))
+ return -1;
+ else if (!gfx_ready())
+ return 0;
+
+ return draw(p);
+}
diff --git a/src/drv/tty/src/write.c b/src/drv/tty/src/write.c
new file mode 100644
index 0000000..6af6113
--- /dev/null
+++ b/src/drv/tty/src/write.c
@@ -0,0 +1,62 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <drv/event.h>
+#include <drv/tty.h>
+#include <drv/tty/types.h>
+#include <drv/tty/ops.h>
+#include <errno.h>
+#include <stddef.h>
+
+int drv_tty_write(const void *const buf, const size_t n,
+ const struct drv_event_done *const d, void *const args)
+{
+ struct drv_port *const p = args;
+
+ for (const char *s = buf; s - (const char *)buf < n; s++)
+ {
+ char *const col = &p->last_row->columns[p->last_column];
+
+ if (*s == '\r')
+ {
+ *col = '\0';
+ p->last_column = 0;
+ }
+ else
+ {
+ if (*s != '\n')
+ *col = *s;
+
+ if (*s == '\n' || ++p->last_column >= p->ncolumns - 1)
+ {
+ if (++p->last_row - p->rows >= p->nrows)
+ {
+ p->last_row = p->rows;
+
+ if (++p->first_row - p->rows >= p->nrows)
+ p->first_row = p->rows;
+ }
+
+ col[p->last_column] = '\0';
+ p->last_column = 0;
+ }
+ }
+ }
+
+ return d->f(SUCCESS, d->args);
+}
diff --git a/src/fs/CMakeLists.txt b/src/fs/CMakeLists.txt
new file mode 100644
index 0000000..d08b64e
--- /dev/null
+++ b/src/fs/CMakeLists.txt
@@ -0,0 +1,24 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(fs)
+add_subdirectory(src)
+target_include_directories(fs PUBLIC include PRIVATE private_include)
+target_link_libraries(fs PUBLIC state)
+add_subdirectory(devfs)
+add_subdirectory(iso9660)
+add_subdirectory(ramfs)
+add_subdirectory(rootfs)
diff --git a/src/fs/devfs/CMakeLists.txt b/src/fs/devfs/CMakeLists.txt
new file mode 100644
index 0000000..7305bdf
--- /dev/null
+++ b/src/fs/devfs/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(devfs)
+add_subdirectory(src)
+target_include_directories(devfs PUBLIC include PRIVATE private_include)
+target_link_libraries(devfs PUBLIC state c PRIVATE fs drv ramfs)
diff --git a/src/fs/devfs/include/devfs.h b/src/fs/devfs/include/devfs.h
new file mode 100644
index 0000000..d9634fc
--- /dev/null
+++ b/src/fs/devfs/include/devfs.h
@@ -0,0 +1,24 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DEVFS_H
+#define DEVFS_H
+
+int devfs_register(void);
+
+#endif
diff --git a/src/fs/devfs/private_include/devfs/ops.h b/src/fs/devfs/private_include/devfs/ops.h
new file mode 100644
index 0000000..f7c4e5b
--- /dev/null
+++ b/src/fs/devfs/private_include/devfs/ops.h
@@ -0,0 +1,48 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DEVFS_OPS_H
+#define DEVFS_OPS_H
+
+#include <fs/fs.h>
+#include <drv/event.h>
+#include <stdbool.h>
+
+int devfs_mount(const struct fs_mount *m, struct fs_ret *r);
+int devfs_mkdir(const struct fs_mkdir *m, const struct fs_mp *mp,
+ const union inode_result *i, struct fs_ret *r);
+int devfs_open(const struct fs_open *o, const struct fs_mp *mp,
+ const union inode_result *i, struct fs_ret *r);
+int devfs_read(const struct fs_read *r, struct fs_ret *ret);
+int devfs_write(const struct fs_write *w, struct fs_ret *r);
+int devfs_stat(const struct fs_stat *s, const struct fs_mp *mp,
+ const union inode_result *i, struct fs_ret *r);
+int devfs_close(const struct fs_close *c, struct fs_ret *r);
+int devfs_seek(const struct fs_seek *s, struct fs_ret *r);
+int devfs_search(const char *path, const struct fs_mp *mp,
+ union inode_result *inode, struct fs_ret *r);
+int devfs_status(const char *node, const struct drv_event_ops *const ops,
+ bool available, void *args);
+int devfs_flags(const union inode_result *i);
+int devfs_update(struct fs_mp_prv *pr);
+int devfs_mknod(const char *path, mode_t mode, dev_t dev,
+ const struct drv_event_ops *const ops, struct fs_mp_prv *mp);
+int devfs_unlink(const char *path, struct fs_mp_prv *mp);
+const struct devfs_ops *devfs_ops(const struct fs_mp_prv *pr, const char *node);
+
+#endif
diff --git a/src/fs/devfs/private_include/devfs/types.h b/src/fs/devfs/private_include/devfs/types.h
new file mode 100644
index 0000000..698ccac
--- /dev/null
+++ b/src/fs/devfs/private_include/devfs/types.h
@@ -0,0 +1,44 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef DEVFS_TYPES_H
+#define DEVFS_TYPES_H
+
+#include <fs/fs.h>
+#include <fs/inode.h>
+#include <drv/drv.h>
+#include <drv/event.h>
+#include <ramfs.h>
+
+struct devfs_ops
+{
+ char *node;
+ struct drv_event_ops ops;
+ struct devfs_ops *prev, *next;
+};
+
+struct fs_mp_prv
+{
+ struct ramfs *rfs;
+ struct drv *drv;
+ struct devfs_ops *head, *tail;
+};
+
+extern const struct fs devfs;
+
+#endif
diff --git a/src/fs/devfs/src/CMakeLists.txt b/src/fs/devfs/src/CMakeLists.txt
new file mode 100644
index 0000000..7db8c9f
--- /dev/null
+++ b/src/fs/devfs/src/CMakeLists.txt
@@ -0,0 +1,34 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(devfs PRIVATE
+ close.c
+ flags.c
+ mount.c
+ mkdir.c
+ mknod.c
+ open.c
+ ops.c
+ stat.c
+ read.c
+ register.c
+ search.c
+ seek.c
+ status.c
+ unlink.c
+ update.c
+ write.c
+)
diff --git a/src/fs/devfs/src/close.c b/src/fs/devfs/src/close.c
new file mode 100644
index 0000000..0277b96
--- /dev/null
+++ b/src/fs/devfs/src/close.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/ops.h>
+#include <fs/fs.h>
+
+int devfs_close(const struct fs_close *const c, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/devfs/src/flags.c b/src/fs/devfs/src/flags.c
new file mode 100644
index 0000000..b99bb8c
--- /dev/null
+++ b/src/fs/devfs/src/flags.c
@@ -0,0 +1,25 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/ops.h>
+
+int devfs_flags(const union inode_result *const i)
+{
+ return i->memi->flags;
+}
diff --git a/src/fs/devfs/src/mkdir.c b/src/fs/devfs/src/mkdir.c
new file mode 100644
index 0000000..9aa74b3
--- /dev/null
+++ b/src/fs/devfs/src/mkdir.c
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/ops.h>
+#include <fs/fs.h>
+#include <fs/inode.h>
+
+int devfs_mkdir(const struct fs_mkdir *m, const struct fs_mp *const mp,
+ const union inode_result *const i, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/devfs/src/mknod.c b/src/fs/devfs/src/mknod.c
new file mode 100644
index 0000000..8d13075
--- /dev/null
+++ b/src/fs/devfs/src/mknod.c
@@ -0,0 +1,54 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs/ops.h>
+#include <devfs/types.h>
+#include <fs/inode.h>
+#include <ramfs.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+int devfs_mknod(const char *const node, const mode_t mode, const dev_t dev,
+ const struct drv_event_ops *const ops, struct fs_mp_prv *const pr)
+{
+ struct devfs_ops *dops = NULL;
+ char *const nodedup = strdup(node);
+
+ if (!nodedup
+ || !(dops = malloc(sizeof *dops))
+ || ramfs_mknod(node, mode, dev, pr->rfs))
+ goto failure;
+
+ *dops = (const struct devfs_ops){.node = nodedup, .ops = *ops};
+
+ if (!pr->head)
+ pr->head = dops;
+ else
+ {
+ dops->prev = pr->tail;
+ pr->tail->next = dops;
+ }
+
+ pr->tail = dops;
+ return 0;
+
+failure:
+ free(dops);
+ return -1;
+}
diff --git a/src/fs/devfs/src/mount.c b/src/fs/devfs/src/mount.c
new file mode 100644
index 0000000..cff4779
--- /dev/null
+++ b/src/fs/devfs/src/mount.c
@@ -0,0 +1,59 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/ops.h>
+#include <devfs/types.h>
+#include <drv/drv.h>
+#include <fs/fs.h>
+#include <ramfs.h>
+#include <stdlib.h>
+
+int devfs_mount(const struct fs_mount *const m, struct fs_ret *const r)
+{
+ struct drv *drv = NULL;
+ struct fs_mp_prv *p = NULL;
+ struct ramfs *const rfs = ramfs_mount(m, r);
+
+ if (!rfs || !(p = malloc(sizeof *p)))
+ goto failure;
+
+ const struct drv_event ev =
+ {
+ .status = devfs_status,
+ .args = p
+ };
+
+ if (!(drv = drv_init(&ev))
+ || fs_mountpoint(m->src, m->tgt, &devfs, devfs_update, p))
+ goto failure;
+
+ *p = (const struct fs_mp_prv)
+ {
+ .drv = drv,
+ .rfs = rfs
+ };
+
+ return 0;
+
+failure:
+ drv_free(drv);
+ free(p);
+ ramfs_free(rfs);
+ return -1;
+}
diff --git a/src/fs/devfs/src/open.c b/src/fs/devfs/src/open.c
new file mode 100644
index 0000000..b9bd3f7
--- /dev/null
+++ b/src/fs/devfs/src/open.c
@@ -0,0 +1,57 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/types.h>
+#include <devfs/ops.h>
+#include <fs/fs.h>
+#include <state.h>
+#include <stdlib.h>
+
+struct open
+{
+ struct fs_ret *pr, r;
+};
+
+static enum state done(void *const args)
+{
+ struct open *const op = args;
+
+ *op->pr = op->r;
+ free(op);
+ return STATE_AGAIN;
+}
+
+int devfs_open(const struct fs_open *const o, const struct fs_mp *const mp,
+ const union inode_result *const inode, struct fs_ret *const r)
+{
+ struct open *const op = malloc(sizeof *op);
+
+ if (!op)
+ return -1;
+
+ *op = (const struct open){.pr = r, .r = *r};
+ *o->fd = (const struct fs_fd)
+ {
+ .inode = *inode,
+ .mp = mp
+ };
+
+ *r = (const struct fs_ret){.f = done, .args = op};
+ return 0;
+}
diff --git a/src/fs/devfs/src/ops.c b/src/fs/devfs/src/ops.c
new file mode 100644
index 0000000..1cd4a15
--- /dev/null
+++ b/src/fs/devfs/src/ops.c
@@ -0,0 +1,32 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/ops.h>
+#include <devfs/types.h>
+#include <string.h>
+
+const struct devfs_ops *devfs_ops(const struct fs_mp_prv *const pr,
+ const char *const node)
+{
+ for (struct devfs_ops *o = pr->head; o; o = o->next)
+ if (!strcmp(o->node, node))
+ return o;
+
+ return NULL;
+}
diff --git a/src/fs/devfs/src/read.c b/src/fs/devfs/src/read.c
new file mode 100644
index 0000000..0bc19f0
--- /dev/null
+++ b/src/fs/devfs/src/read.c
@@ -0,0 +1,95 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/ops.h>
+#include <devfs/types.h>
+#include <fs/fs.h>
+#include <state.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+struct read
+{
+ bool done;
+ struct fs_fd *fd;
+ struct fs_ret *pr, r;
+};
+
+static int done(const int error, void *const args)
+{
+ struct read *const re = args;
+
+ re->done = true;
+ return 0;
+}
+
+static enum state wait(void *const args)
+{
+ struct read *const re = args;
+
+ if (!re->done)
+ return STATE_AGAIN;
+
+ *re->pr = re->r;
+ free(re);
+ return STATE_AGAIN;
+}
+
+int devfs_read(const struct fs_read *const fr, struct fs_ret *const r)
+{
+ struct fs_fd *const fd = fr->fd;
+ const struct fs_mp *const mp = fd->mp;
+ const struct inode *const inode = fd->inode.memi;
+ const struct devfs_ops *const o = devfs_ops(mp->prv, inode->name);
+ struct read *const re = malloc(sizeof *re);
+
+ if (!re)
+ goto failure;
+ else if (!o)
+ {
+ errno = ENOENT;
+ goto failure;
+ }
+
+ *re = (const struct read)
+ {
+ .fd = fd,
+ .pr = r,
+ .r = *r
+ };
+
+ const struct drv_event_done d =
+ {
+ .f = done,
+ .args = re
+ };
+
+ const struct drv_event_ops *const ops = &o->ops;
+
+ if (ops->read(fr->buf, fr->n, &d, ops->args))
+ goto failure;
+
+ *r = (const struct fs_ret){.f = wait, .args = re};
+ return 0;
+
+failure:
+ free(re);
+ return -1;
+}
diff --git a/src/fs/devfs/src/register.c b/src/fs/devfs/src/register.c
new file mode 100644
index 0000000..46dcdb6
--- /dev/null
+++ b/src/fs/devfs/src/register.c
@@ -0,0 +1,44 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/ops.h>
+#include <fs/fs.h>
+
+const struct fs devfs =
+{
+ .type = "devfs",
+ .mount = devfs_mount,
+ .stat = devfs_stat,
+ .mkdir = devfs_mkdir,
+ .open = devfs_open,
+ .read = devfs_read,
+ .write = devfs_write,
+ .close = devfs_close,
+ .seek = devfs_seek,
+ .iops =
+ {
+ .search = devfs_search,
+ .flags = devfs_flags
+ }
+};
+
+int devfs_register(void)
+{
+ return fs_register(&devfs);
+}
diff --git a/src/fs/devfs/src/search.c b/src/fs/devfs/src/search.c
new file mode 100644
index 0000000..22a4e92
--- /dev/null
+++ b/src/fs/devfs/src/search.c
@@ -0,0 +1,29 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/ops.h>
+#include <devfs/types.h>
+#include <fs/fs.h>
+#include <ramfs.h>
+
+int devfs_search(const char *const path, const struct fs_mp *const mp,
+ union inode_result *const inode, struct fs_ret *const r)
+{
+ return ramfs_search(path, mp->prv->rfs, inode, r);
+}
diff --git a/src/fs/devfs/src/seek.c b/src/fs/devfs/src/seek.c
new file mode 100644
index 0000000..d955e70
--- /dev/null
+++ b/src/fs/devfs/src/seek.c
@@ -0,0 +1,98 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/ops.h>
+#include <devfs/types.h>
+#include <fs/fs.h>
+#include <state.h>
+#include <errno.h>
+#include <stdlib.h>
+
+struct seek
+{
+ bool done;
+ struct fs_fd *fd;
+ struct fs_ret *pr, r;
+};
+
+static int done(int error, void *const args)
+{
+ struct seek *const s = args;
+ struct fs_fd *const fd = s->fd;
+
+ if (error)
+ fd->error = error;
+
+ s->done = true;
+ return 0;
+}
+
+static enum state wait(void *const args)
+{
+ struct seek *const s = args;
+
+ if (!s->done)
+ return STATE_AGAIN;
+
+ *s->pr = s->r;
+ free(s);
+ return STATE_AGAIN;
+}
+
+int devfs_seek(const struct fs_seek *const fs, struct fs_ret *const r)
+{
+ struct fs_fd *const fd = fs->fd;
+ const struct fs_mp *const mp = fd->mp;
+ const struct inode *const inode = fd->inode.memi;
+ const struct devfs_ops *const o = devfs_ops(mp->prv, inode->name);
+ struct seek *const s = malloc(sizeof *s);
+
+ if (!s)
+ goto failure;
+ else if (!o)
+ {
+ errno = ENOENT;
+ goto failure;
+ }
+
+ *s = (const struct seek)
+ {
+ .fd = fd,
+ .pr = r,
+ .r = *r
+ };
+
+ const struct drv_event_done d =
+ {
+ .f = done,
+ .args = s
+ };
+
+ const struct drv_event_ops *const ops = &o->ops;
+
+ if (ops->seek(fs->offset, &d, fd))
+ goto failure;
+
+ *r = (const struct fs_ret){.f = wait, .args = s};
+ return 0;
+
+failure:
+ free(s);
+ return -1;
+}
diff --git a/src/fs/devfs/src/stat.c b/src/fs/devfs/src/stat.c
new file mode 100644
index 0000000..dff4d3c
--- /dev/null
+++ b/src/fs/devfs/src/stat.c
@@ -0,0 +1,30 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/ops.h>
+#include <devfs/types.h>
+#include <fs/fs.h>
+#include <fs/inode.h>
+#include <ramfs.h>
+
+int devfs_stat(const struct fs_stat *const s, const struct fs_mp *const mp,
+ const union inode_result *const i, struct fs_ret *const r)
+{
+ return ramfs_stat(s, mp->prv->rfs, i, r);
+}
diff --git a/src/fs/devfs/src/status.c b/src/fs/devfs/src/status.c
new file mode 100644
index 0000000..8a4d1e1
--- /dev/null
+++ b/src/fs/devfs/src/status.c
@@ -0,0 +1,30 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs/ops.h>
+#include <drv/event.h>
+#include <stdbool.h>
+
+int devfs_status(const char *const node, const struct drv_event_ops *const ops,
+ const bool available, void *const args)
+{
+ struct fs_mp_prv *const mp = args;
+
+ return available ? devfs_mknod(node, 0755, 0, ops, mp)
+ : devfs_unlink(node, mp);
+}
diff --git a/src/fs/devfs/src/unlink.c b/src/fs/devfs/src/unlink.c
new file mode 100644
index 0000000..d03fd68
--- /dev/null
+++ b/src/fs/devfs/src/unlink.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs/ops.h>
+#include <sys/types.h>
+#include <errno.h>
+
+int devfs_unlink(const char *const node, struct fs_mp_prv *const mp)
+{
+ return -1;
+}
diff --git a/src/fs/devfs/src/update.c b/src/fs/devfs/src/update.c
new file mode 100644
index 0000000..2a0a879
--- /dev/null
+++ b/src/fs/devfs/src/update.c
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/types.h>
+#include <devfs/ops.h>
+#include <drv/drv.h>
+
+int devfs_update(struct fs_mp_prv *const pr)
+{
+ return drv_update(pr->drv);
+}
diff --git a/src/fs/devfs/src/write.c b/src/fs/devfs/src/write.c
new file mode 100644
index 0000000..759751e
--- /dev/null
+++ b/src/fs/devfs/src/write.c
@@ -0,0 +1,95 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <devfs.h>
+#include <devfs/ops.h>
+#include <devfs/types.h>
+#include <fs/fs.h>
+#include <state.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+struct write
+{
+ bool done;
+ struct fs_fd *fd;
+ struct fs_ret *pr, r;
+};
+
+static int done(const int error, void *const args)
+{
+ struct write *const w = args;
+
+ w->done = true;
+ return 0;
+}
+
+static enum state wait(void *const args)
+{
+ struct write *const w = args;
+
+ if (!w->done)
+ return STATE_AGAIN;
+
+ *w->pr = w->r;
+ free(w);
+ return STATE_AGAIN;
+}
+
+int devfs_write(const struct fs_write *const fw, struct fs_ret *const r)
+{
+ struct fs_fd *const fd = fw->fd;
+ const struct fs_mp *const mp = fd->mp;
+ const struct inode *const inode = fd->inode.memi;
+ const struct devfs_ops *const o = devfs_ops(mp->prv, inode->name);
+ struct write *const w = malloc(sizeof *w);
+
+ if (!w)
+ goto failure;
+ else if (!o)
+ {
+ errno = ENOENT;
+ goto failure;
+ }
+
+ *w = (const struct write)
+ {
+ .fd = fd,
+ .pr = r,
+ .r = *r
+ };
+
+ const struct drv_event_done d =
+ {
+ .f = done,
+ .args = w
+ };
+
+ const struct drv_event_ops *const ops = &o->ops;
+
+ if (ops->write(fw->buf, fw->n, &d, ops->args))
+ goto failure;
+
+ *r = (const struct fs_ret){.f = wait, .args = w};
+ return 0;
+
+failure:
+ free(w);
+ return -1;
+}
diff --git a/src/fs/include/fs/fs.h b/src/fs/include/fs/fs.h
new file mode 100644
index 0000000..c66ce97
--- /dev/null
+++ b/src/fs/include/fs/fs.h
@@ -0,0 +1,159 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef FS_H
+#define FS_H
+
+#include <fs/inode.h>
+#include <state.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+struct fs_mountpoint;
+struct fs_mp_prv;
+struct fs_fd_prv;
+
+struct fs_stat
+{
+ const char *path;
+ struct stat *sb;
+ uid_t uid;
+ gid_t gid;
+};
+
+struct fs_mkdir
+{
+ const char *path;
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+};
+
+struct fs_mount
+{
+ const char *src, *tgt;
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+};
+
+struct fs_umount
+{
+ const char *tgt;
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+};
+
+struct fs_open
+{
+ const char *path;
+ struct fs_fd *fd;
+ int flags;
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+};
+
+struct fs_close
+{
+ struct fs_fd *fd;
+};
+
+struct fs_read
+{
+ struct fs_fd *fd;
+ void *buf;
+ size_t n;
+};
+
+struct fs_write
+{
+ struct fs_fd *fd;
+ const void *buf;
+ size_t n;
+};
+
+struct fs_seek
+{
+ struct fs_fd *fd;
+ long offset;
+};
+
+struct fs_ret
+{
+ enum state (*f)(void *args);
+ void *args;
+};
+
+enum
+{
+ FS_DEV_REQUIRED = 1
+};
+
+struct fs
+{
+ const char *type;
+ int flags;
+ int (*mount)(const struct fs_mount *, struct fs_ret *);
+ int (*umount)(const struct fs_umount *, struct fs_ret *);
+ int (*stat)(const struct fs_stat *, const struct fs_mp *,
+ const union inode_result *, struct fs_ret *);
+ int (*mkdir)(const struct fs_mkdir *, const struct fs_mp *,
+ const union inode_result *, struct fs_ret *);
+ int (*open)(const struct fs_open *, const struct fs_mp *,
+ const union inode_result *, struct fs_ret *);
+ int (*close)(const struct fs_close *, struct fs_ret *);
+ int (*read)(const struct fs_read *, struct fs_ret *);
+ int (*write)(const struct fs_write *, struct fs_ret *);
+ int (*seek)(const struct fs_seek *, struct fs_ret *);
+ struct inode_ops iops;
+};
+
+struct fs_mp
+{
+ const char *src, *tgt;
+ const struct fs *fs;
+ struct fs_mp_prv *prv;
+};
+
+struct fs_fd
+{
+ long offset;
+ int error;
+ const struct fs_mp *mp;
+ union inode_result inode;
+ struct fs_fd_prv *prv;
+};
+
+typedef int (*fs_update_fn)(struct fs_mp_prv *);
+
+int fs_register(const struct fs *fs);
+int fs_update(void);
+int fs_mountpoint(const char *src, const char *tgt, const struct fs *fs,
+ fs_update_fn fn, struct fs_mp_prv *pr);
+const struct fs *fs_from_type(const char *type);
+int fs_mp_from_path(const char *path, struct fs_mp *mp);
+struct fs_mp *fs_mps_from_path(const char *path, size_t *n);
+const char *fs_relpath(const char *path);
+char *fs_parent(const char *path);
+int fs_next(const char *path, char **next, size_t *i);
+
+#endif
diff --git a/src/fs/include/fs/inode.h b/src/fs/include/fs/inode.h
new file mode 100644
index 0000000..914564b
--- /dev/null
+++ b/src/fs/include/fs/inode.h
@@ -0,0 +1,79 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef FS_INODE_H
+#define FS_INODE_H
+
+#include <state.h>
+#include <sys/types.h>
+#include <time.h>
+
+struct fs;
+struct fs_mp;
+struct fs_ret;
+struct inode_prv;
+
+enum
+{
+ INODE_DIR = 1,
+ INODE_REGFILE = 1 << 1,
+ INODE_BLOCKDEV = 1 << 2,
+ INODE_MOUNTPOINT = 1 << 3,
+};
+
+struct inode
+{
+ char *name;
+ int flags;
+ ino_t ino;
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+ struct timespec atim, mtim, ctim;
+ struct inode *parent, *child, *left, *right;
+ struct inode_prv *prv;
+};
+
+union inode_result
+{
+ struct inode cachei, *memi;
+};
+
+typedef int (*inode_search_done)(enum state state, const char *relpath,
+ const struct fs_mp *mp, const union inode_result *inode, void *args);
+
+struct inode_search
+{
+ const char *path;
+ inode_search_done done;
+ void *args;
+};
+
+struct inode_ops
+{
+ int (*search)(const char *path, const struct fs_mp *mp,
+ union inode_result *inode, struct fs_ret *r);
+ int (*reserve)(const struct inode *i, void *args, struct fs_ret *r);
+ int (*flags)(const union inode_result *i);
+};
+
+int inode_search(const struct inode_search *s, struct fs_ret *r);
+void inode_search_free(struct inode_search *s);
+void inode_free(struct inode *i);
+
+#endif
diff --git a/src/fs/iso9660/CMakeLists.txt b/src/fs/iso9660/CMakeLists.txt
new file mode 100644
index 0000000..67b56cf
--- /dev/null
+++ b/src/fs/iso9660/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(iso9660)
+add_subdirectory(src)
+target_include_directories(iso9660 PUBLIC include PRIVATE private_include)
+target_link_libraries(iso9660 PUBLIC c PRIVATE fs kprintf state)
diff --git a/src/fs/iso9660/include/iso9660.h b/src/fs/iso9660/include/iso9660.h
new file mode 100644
index 0000000..f5ee681
--- /dev/null
+++ b/src/fs/iso9660/include/iso9660.h
@@ -0,0 +1,24 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef ISO9660_H
+#define ISO9660_H
+
+int iso9660_register(void);
+
+#endif
diff --git a/src/fs/iso9660/private_include/iso9660/ops.h b/src/fs/iso9660/private_include/iso9660/ops.h
new file mode 100644
index 0000000..64cd798
--- /dev/null
+++ b/src/fs/iso9660/private_include/iso9660/ops.h
@@ -0,0 +1,39 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef ISO9660_OPS_H
+#define ISO9660_OPS_H
+
+#include <fs/fs.h>
+#include <fs/inode.h>
+
+int iso9660_mount(const struct fs_mount *m, struct fs_ret *r);
+int iso9660_mkdir(const struct fs_mkdir *m, const struct fs_mp *mp,
+ const union inode_result *i, struct fs_ret *r);
+int iso9660_open(const struct fs_open *o, const struct fs_mp *mp,
+ const union inode_result *i, struct fs_ret *r);
+int iso9660_read(const struct fs_read *r, struct fs_ret *ret);
+int iso9660_write(const struct fs_write *w, struct fs_ret *r);
+int iso9660_stat(const struct fs_stat *s, const struct fs_mp *mp,
+ const union inode_result *inode, struct fs_ret *r);
+int iso9660_seek(const struct fs_seek *s, struct fs_ret *r);
+int iso9660_close(const struct fs_close *c, struct fs_ret *r);
+int iso9660_search(const char *path, const struct fs_mp *prv,
+ union inode_result *inode, struct fs_ret *r);
+
+#endif
diff --git a/src/fs/iso9660/private_include/iso9660/types.h b/src/fs/iso9660/private_include/iso9660/types.h
new file mode 100644
index 0000000..89cd1d3
--- /dev/null
+++ b/src/fs/iso9660/private_include/iso9660/types.h
@@ -0,0 +1,34 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef ISO9660_TYPES_H
+#define ISO9660_TYPES_H
+
+#include <fs/fs.h>
+#include <fs/inode.h>
+
+struct fs_mp_prv
+{
+ int dummy;
+};
+
+enum {ISO9660_SECTOR_SZ = 2048};
+
+extern const struct fs iso9660;
+
+#endif
diff --git a/src/fs/iso9660/src/CMakeLists.txt b/src/fs/iso9660/src/CMakeLists.txt
new file mode 100644
index 0000000..97dd80b
--- /dev/null
+++ b/src/fs/iso9660/src/CMakeLists.txt
@@ -0,0 +1,28 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(iso9660 PRIVATE
+ close.c
+ mount.c
+ mkdir.c
+ open.c
+ stat.c
+ read.c
+ register.c
+ search.c
+ seek.c
+ write.c
+)
diff --git a/src/fs/iso9660/src/close.c b/src/fs/iso9660/src/close.c
new file mode 100644
index 0000000..dc80117
--- /dev/null
+++ b/src/fs/iso9660/src/close.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <iso9660.h>
+#include <iso9660/ops.h>
+#include <fs/fs.h>
+
+int iso9660_close(const struct fs_close *const c, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/iso9660/src/mkdir.c b/src/fs/iso9660/src/mkdir.c
new file mode 100644
index 0000000..e3d91ce
--- /dev/null
+++ b/src/fs/iso9660/src/mkdir.c
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <iso9660.h>
+#include <iso9660/ops.h>
+#include <fs/fs.h>
+#include <fs/inode.h>
+
+int iso9660_mkdir(const struct fs_mkdir *const m, const struct fs_mp *const mp,
+ const union inode_result *const inode, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/iso9660/src/mount.c b/src/fs/iso9660/src/mount.c
new file mode 100644
index 0000000..aeddcc5
--- /dev/null
+++ b/src/fs/iso9660/src/mount.c
@@ -0,0 +1,196 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <iso9660.h>
+#include <iso9660/ops.h>
+#include <iso9660/types.h>
+#include <fs/fs.h>
+#include <kprintf.h>
+#include <state.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct mount
+{
+ char *path, header[sizeof "CD001"];
+ struct fs_fd fd;
+ struct fs_ret *r;
+ struct fs_mount mount;
+ const struct fs_mp *mp;
+};
+
+static void free_mount(struct mount *const m)
+{
+ if (!m)
+ return;
+
+ const struct fs_close c = {.fd = &m->fd};
+
+ m->mp->fs->close(&c, m->r);
+ free(m->path);
+ free(m);
+}
+
+static enum state check_header(void *const args)
+{
+ struct mount *const m = args;
+ static const char header[] = {1, 'C', 'D', '0', '0', '1'};
+
+ if (memcmp(m->header, header, sizeof header))
+ {
+ kprintf("invalid header");
+ free_mount(m);
+ return STATE_FATAL;
+ }
+
+ free_mount(m);
+ return STATE_OK;
+}
+
+static enum state read_header(void *const args)
+{
+ struct mount *const m = args;
+ struct fs_fd *const fd = &m->fd;
+ const struct fs_read r =
+ {
+ .buf = m->header,
+ .n = sizeof m->header,
+ .fd = fd
+ };
+
+ if (fd->error)
+ {
+ errno = fd->error;
+ goto failure;
+ }
+
+ *m->r = (const struct fs_ret)
+ {
+ .f = check_header,
+ .args = m
+ };
+
+ if (m->mp->fs->read(&r, m->r))
+ goto failure;
+
+ return STATE_AGAIN;
+
+failure:
+ free_mount(m);
+ return STATE_FATAL;
+}
+
+static enum state seek_header(void *const args)
+{
+ struct mount *const m = args;
+ const struct fs_mp *const mp = m->mp;
+ const struct fs_seek s =
+ {
+ .fd = &m->fd,
+ .offset = 16 * ISO9660_SECTOR_SZ
+ };
+
+ *m->r = (const struct fs_ret)
+ {
+ .args = m,
+ .f = read_header
+ };
+
+ if (mp->fs->seek(&s, m->r))
+ goto failure;
+
+ return STATE_AGAIN;
+
+failure:
+ free_mount(m);
+ return STATE_FATAL;
+}
+
+static int search_done(const enum state state, const char *const relpath,
+ const struct fs_mp *const mp, const union inode_result *const inode,
+ void *const args)
+{
+ struct mount *const m = args;
+ const struct fs_mount *const fm = &m->mount;
+
+ if (!inode)
+ {
+ errno = ENOENT;
+ goto failure;
+ }
+
+ const struct fs_open o =
+ {
+ .fd = &m->fd,
+ .gid = fm->gid,
+ .uid = fm->uid,
+ .mode = fm->mode,
+ .path = relpath
+ };
+
+ *m->r = (const struct fs_ret)
+ {
+ .args = m,
+ .f = seek_header
+ };
+
+ if (mp->fs->open(&o, mp, inode, m->r))
+ goto failure;
+
+ m->mp = mp;
+ return 0;
+
+failure:
+ free_mount(m);
+ return -1;
+}
+
+int iso9660_mount(const struct fs_mount *const fm, struct fs_ret *const r)
+{
+ char *tgtdup = NULL;
+ struct mount *const m = malloc(sizeof *m);
+
+ if (!m || !(tgtdup = strdup(fm->tgt)))
+ goto failure;
+
+ *m = (const struct mount)
+ {
+ .path = tgtdup,
+ .mount = *fm,
+ .r = r
+ };
+
+ const struct inode_search s =
+ {
+ .args = m,
+ .path = fm->src,
+ .done = search_done
+ };
+
+ if (inode_search(&s, r))
+ goto failure;
+
+ return 0;
+
+failure:
+ free(tgtdup);
+ free(m);
+ return -1;
+}
diff --git a/src/fs/iso9660/src/open.c b/src/fs/iso9660/src/open.c
new file mode 100644
index 0000000..b7c78ef
--- /dev/null
+++ b/src/fs/iso9660/src/open.c
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <iso9660.h>
+#include <iso9660/ops.h>
+#include <fs/fs.h>
+
+int iso9660_open(const struct fs_open *const o, const struct fs_mp *const mp,
+ const union inode_result *const inode, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/iso9660/src/read.c b/src/fs/iso9660/src/read.c
new file mode 100644
index 0000000..7a8569f
--- /dev/null
+++ b/src/fs/iso9660/src/read.c
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <iso9660.h>
+#include <iso9660/ops.h>
+#include <fs/fs.h>
+#include <stddef.h>
+
+int iso9660_read(const struct fs_read *const r, struct fs_ret *const ret)
+{
+ return -1;
+}
diff --git a/src/fs/iso9660/src/register.c b/src/fs/iso9660/src/register.c
new file mode 100644
index 0000000..2b69651
--- /dev/null
+++ b/src/fs/iso9660/src/register.c
@@ -0,0 +1,44 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <iso9660.h>
+#include <iso9660/ops.h>
+#include <fs/fs.h>
+
+const struct fs iso9660 =
+{
+ .type = "iso9660",
+ .flags = FS_DEV_REQUIRED,
+ .mount = iso9660_mount,
+ .stat = iso9660_stat,
+ .mkdir = iso9660_mkdir,
+ .open = iso9660_open,
+ .read = iso9660_read,
+ .write = iso9660_write,
+ .close = iso9660_close,
+ .seek = iso9660_seek,
+ .iops =
+ {
+ .search = iso9660_search
+ }
+};
+
+int iso9660_register(void)
+{
+ return fs_register(&iso9660);
+}
diff --git a/src/fs/iso9660/src/search.c b/src/fs/iso9660/src/search.c
new file mode 100644
index 0000000..c6d1208
--- /dev/null
+++ b/src/fs/iso9660/src/search.c
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <iso9660.h>
+#include <iso9660/ops.h>
+#include <fs/fs.h>
+
+int iso9660_search(const char *const path, const struct fs_mp *const mp,
+ union inode_result *const inode, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/iso9660/src/seek.c b/src/fs/iso9660/src/seek.c
new file mode 100644
index 0000000..c78bb52
--- /dev/null
+++ b/src/fs/iso9660/src/seek.c
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <iso9660.h>
+#include <iso9660/ops.h>
+#include <iso9660/types.h>
+#include <fs/fs.h>
+
+int iso9660_seek(const struct fs_seek *const s, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/iso9660/src/stat.c b/src/fs/iso9660/src/stat.c
new file mode 100644
index 0000000..e5905e4
--- /dev/null
+++ b/src/fs/iso9660/src/stat.c
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <iso9660.h>
+#include <iso9660/ops.h>
+#include <fs/fs.h>
+#include <sys/stat.h>
+
+int iso9660_stat(const struct fs_stat *const s, const struct fs_mp *const mp,
+ const union inode_result *const inode, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/iso9660/src/write.c b/src/fs/iso9660/src/write.c
new file mode 100644
index 0000000..b7baa93
--- /dev/null
+++ b/src/fs/iso9660/src/write.c
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <iso9660.h>
+#include <iso9660/ops.h>
+#include <fs/fs.h>
+#include <errno.h>
+
+int iso9660_write(const struct fs_write *const w, struct fs_ret *const r)
+{
+ errno = EROFS;
+ return -1;
+}
diff --git a/src/fs/private_include/fs/private.h b/src/fs/private_include/fs/private.h
new file mode 100644
index 0000000..327ded3
--- /dev/null
+++ b/src/fs/private_include/fs/private.h
@@ -0,0 +1,63 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef FS_TYPES_H
+#define FS_TYPES_H
+
+#include <fs/fs.h>
+#include <fs/inode.h>
+#include <state.h>
+#include <sys/types.h>
+
+struct fs_fd_prv;
+
+struct fs_register
+{
+ const struct fs *fs;
+ struct fs_register *next;
+};
+
+struct fs_mountpoint
+{
+ char *src, *tgt;
+ const struct fs *fs;
+ struct fs_mp_prv *prv;
+ struct fs_mountpoint *next;
+ fs_update_fn update;
+};
+
+struct fs_add
+{
+ char *src, *tgt;
+ struct inode_search *search;
+ struct inode *inode;
+ mode_t mode;
+ const struct fs *fs;
+ enum state (*next)(struct fs_add *);
+};
+
+struct fs_fd
+{
+ long off;
+ struct fs_fd_prv *prv;
+};
+
+extern struct fs_register *fs_rhead, *fs_rtail;
+extern struct fs_mountpoint *fs_mphead, *fs_mptail;
+
+#endif
diff --git a/src/fs/private_include/fs/types.h b/src/fs/private_include/fs/types.h
new file mode 100644
index 0000000..fe1eb01
--- /dev/null
+++ b/src/fs/private_include/fs/types.h
@@ -0,0 +1,55 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef FS_TYPES_H
+#define FS_TYPES_H
+
+#include <fs/fs.h>
+#include <fs/inode.h>
+#include <state.h>
+#include <sys/types.h>
+
+struct fs_register
+{
+ const struct fs *fs;
+ struct fs_register *next;
+};
+
+struct fs_mountpoint
+{
+ char *src, *tgt;
+ const struct fs *fs;
+ struct fs_mp_prv *prv;
+ struct fs_mountpoint *next;
+ fs_update_fn update;
+};
+
+struct fs_add
+{
+ char *src, *tgt;
+ struct inode_search *search;
+ struct inode *inode;
+ mode_t mode;
+ const struct fs *fs;
+ enum state (*next)(struct fs_add *);
+};
+
+extern struct fs_register *fs_rhead, *fs_rtail;
+extern struct fs_mountpoint *fs_mphead, *fs_mptail;
+
+#endif
diff --git a/src/fs/ramfs/CMakeLists.txt b/src/fs/ramfs/CMakeLists.txt
new file mode 100644
index 0000000..9581c99
--- /dev/null
+++ b/src/fs/ramfs/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(ramfs)
+add_subdirectory(src)
+target_include_directories(ramfs PUBLIC include PRIVATE private_include)
+target_link_libraries(ramfs PUBLIC state c PRIVATE fs drv)
diff --git a/src/fs/ramfs/include/ramfs.h b/src/fs/ramfs/include/ramfs.h
new file mode 100644
index 0000000..36be39c
--- /dev/null
+++ b/src/fs/ramfs/include/ramfs.h
@@ -0,0 +1,43 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef RAMFS_H
+#define RAMFS_H
+
+#include <fs/fs.h>
+#include <fs/inode.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stddef.h>
+
+struct ramfs *ramfs_mount(const struct fs_mount *m, struct fs_ret *r);
+int ramfs_mkdir(const struct fs_mkdir *m, struct ramfs *rfs,
+ const union inode_result *i, struct fs_ret *r);
+int ramfs_open(const struct fs_open *o, struct inode *i, struct fs_ret *r);
+int ramfs_read(const struct fs_read *r, struct fs_ret *ret);
+int ramfs_write(const struct fs_write *w, struct fs_ret *r);
+int ramfs_stat(const struct fs_stat *s, const struct ramfs *rfs,
+ const union inode_result *inode, struct fs_ret *r);
+int ramfs_close(const struct fs_close *c, struct fs_ret *r);
+int ramfs_search(const char *path, const struct ramfs *rfs,
+ union inode_result *inode, struct fs_ret *r);
+int ramfs_flags(const union inode_result *i);
+int ramfs_mknod(const char *node, mode_t mode, dev_t dev, struct ramfs *rfs);
+void ramfs_free(struct ramfs *rfs);
+
+#endif
diff --git a/src/fs/ramfs/private_include/ramfs/types.h b/src/fs/ramfs/private_include/ramfs/types.h
new file mode 100644
index 0000000..975ff9a
--- /dev/null
+++ b/src/fs/ramfs/private_include/ramfs/types.h
@@ -0,0 +1,31 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef RAMFS_TYPES_H
+#define RAMFS_TYPES_H
+
+#include <fs/fs.h>
+#include <fs/inode.h>
+
+struct ramfs
+{
+ struct inode *root;
+ ino_t ino;
+};
+
+#endif
diff --git a/src/fs/ramfs/src/CMakeLists.txt b/src/fs/ramfs/src/CMakeLists.txt
new file mode 100644
index 0000000..904e22d
--- /dev/null
+++ b/src/fs/ramfs/src/CMakeLists.txt
@@ -0,0 +1,29 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(ramfs PRIVATE
+ close.c
+ free.c
+ flags.c
+ mount.c
+ mkdir.c
+ mknod.c
+ open.c
+ stat.c
+ read.c
+ search.c
+ write.c
+)
diff --git a/src/fs/ramfs/src/close.c b/src/fs/ramfs/src/close.c
new file mode 100644
index 0000000..9d85319
--- /dev/null
+++ b/src/fs/ramfs/src/close.c
@@ -0,0 +1,25 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ramfs.h>
+#include <fs/fs.h>
+
+int ramfs_close(const struct fs_close *const c, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/ramfs/src/flags.c b/src/fs/ramfs/src/flags.c
new file mode 100644
index 0000000..1453c5c
--- /dev/null
+++ b/src/fs/ramfs/src/flags.c
@@ -0,0 +1,25 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ramfs.h>
+#include <fs/inode.h>
+
+int ramfs_flags(const union inode_result *const i)
+{
+ return i->memi->flags;
+}
diff --git a/src/fs/ramfs/src/free.c b/src/fs/ramfs/src/free.c
new file mode 100644
index 0000000..39b9bc4
--- /dev/null
+++ b/src/fs/ramfs/src/free.c
@@ -0,0 +1,31 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ramfs.h>
+#include <ramfs/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+void ramfs_free(struct ramfs *const r)
+{
+ if (!r)
+ return;
+
+ inode_free(r->root);
+ free(r);
+}
diff --git a/src/fs/ramfs/src/mkdir.c b/src/fs/ramfs/src/mkdir.c
new file mode 100644
index 0000000..fef39ef
--- /dev/null
+++ b/src/fs/ramfs/src/mkdir.c
@@ -0,0 +1,79 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ramfs.h>
+#include <ramfs/types.h>
+#include <fs/fs.h>
+#include <fs/inode.h>
+#include <state.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+static enum state done(void *const args)
+{
+ return STATE_OK;
+}
+
+int ramfs_mkdir(const struct fs_mkdir *const m, struct ramfs *const rfs,
+ const union inode_result *const inode, struct fs_ret *const r)
+{
+ struct timespec ts;
+ struct inode *ni = NULL;
+ struct inode *const parent = inode->memi;
+ char *const name = strdup(m->path);
+
+ if (!name
+ || clock_gettime(CLOCK_REALTIME, &ts)
+ || !(ni = malloc(sizeof *ni)))
+ goto failure;
+
+ *ni = (const struct inode)
+ {
+ .name = name,
+ .mode = m->mode,
+ .uid = m->uid,
+ .gid = m->gid,
+ .flags = INODE_DIR,
+ .atim = ts,
+ .ctim = ts,
+ .mtim = ts,
+ .ino = rfs->ino++,
+ .parent = parent
+ };
+
+ if (!parent->child)
+ parent->child = ni;
+ else
+ for (struct inode *i = parent->child; i; i = i->right)
+ if (!i->right)
+ {
+ i->right = ni;
+ ni->left = i;
+ break;
+ }
+
+ parent->atim = parent->mtim = ts;
+ *r = (const struct fs_ret){.f = done};
+ return 0;
+
+failure:
+ free(ni);
+ free(name);
+ return -1;
+}
diff --git a/src/fs/ramfs/src/mknod.c b/src/fs/ramfs/src/mknod.c
new file mode 100644
index 0000000..2ad9fd7
--- /dev/null
+++ b/src/fs/ramfs/src/mknod.c
@@ -0,0 +1,87 @@
+
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ramfs.h>
+#include <ramfs/types.h>
+#include <fs/inode.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+static struct inode *find(const char *const node, struct inode *const root)
+{
+ for (struct inode *c = root->child; c; c = c->right)
+ if (!strcmp(c->name, node))
+ return c;
+
+ return NULL;
+}
+
+int ramfs_mknod(const char *const node, const mode_t mode, const dev_t dev,
+ struct ramfs *const rfs)
+{
+ struct inode *const r = rfs->root,
+ *const inode = find(node, r),
+ *newinode = NULL;
+ char *nodedup = NULL;
+ struct timespec ts;
+
+ if (inode)
+ {
+ errno = EEXIST;
+ goto failure;
+ }
+ else if (clock_gettime(CLOCK_REALTIME, &ts)
+ || !(nodedup = strdup(node))
+ || !(newinode = malloc(sizeof *newinode)))
+ goto failure;
+
+ *newinode = (const struct inode)
+ {
+ .atim = ts,
+ .ctim = ts,
+ .mtim = ts,
+ .flags = INODE_BLOCKDEV,
+ .mode = mode,
+ .parent = rfs->root,
+ .name = nodedup
+ };
+
+ if (!r->child)
+ r->child = newinode;
+ else
+ for (struct inode *c = r->child; c; c = c->right)
+ if (!c->right)
+ {
+ c->right = newinode;
+ newinode->left = c;
+ break;
+ }
+
+ r->atim = r->mtim = ts;
+ return 0;
+
+failure:
+ free(nodedup);
+ free(newinode);
+ return -1;
+}
diff --git a/src/fs/ramfs/src/mount.c b/src/fs/ramfs/src/mount.c
new file mode 100644
index 0000000..09c4685
--- /dev/null
+++ b/src/fs/ramfs/src/mount.c
@@ -0,0 +1,69 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ramfs.h>
+#include <ramfs/types.h>
+#include <fs/fs.h>
+#include <state.h>
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+static enum state mount(void *const args)
+{
+ return STATE_OK;
+}
+
+struct ramfs *ramfs_mount(const struct fs_mount *const m,
+ struct fs_ret *const r)
+{
+ struct ramfs *ret = NULL;
+ struct timespec ts;
+ char *const name = strdup("/");
+ struct inode *root = NULL;
+
+ if (!name
+ || clock_gettime(CLOCK_REALTIME, &ts)
+ || !(root = malloc(sizeof *root))
+ || !(ret = malloc(sizeof *ret)))
+ goto failure;
+
+ *root = (const struct inode)
+ {
+ .name = name,
+ .mode = m->mode,
+ .uid = m->uid,
+ .gid = m->gid,
+ .atim = ts,
+ .mtim = ts,
+ .ctim = ts
+ };
+
+ *ret = (const struct ramfs){.root = root};
+ *r = (const struct fs_ret){.f = mount};
+ ret->ino++;
+ return ret;
+
+failure:
+ free(root);
+ free(ret);
+ free(name);
+ return NULL;
+}
diff --git a/src/fs/ramfs/src/open.c b/src/fs/ramfs/src/open.c
new file mode 100644
index 0000000..1140b58
--- /dev/null
+++ b/src/fs/ramfs/src/open.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ramfs.h>
+#include <fs/fs.h>
+
+int ramfs_open(const struct fs_open *const o,struct inode *const i,
+ struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/ramfs/src/read.c b/src/fs/ramfs/src/read.c
new file mode 100644
index 0000000..77d6287
--- /dev/null
+++ b/src/fs/ramfs/src/read.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ramfs.h>
+#include <fs/fs.h>
+#include <stddef.h>
+
+int ramfs_read(const struct fs_read *const r, struct fs_ret *const ret)
+{
+ return -1;
+}
diff --git a/src/fs/ramfs/src/search.c b/src/fs/ramfs/src/search.c
new file mode 100644
index 0000000..2c8f35a
--- /dev/null
+++ b/src/fs/ramfs/src/search.c
@@ -0,0 +1,150 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ramfs.h>
+#include <ramfs/types.h>
+#include <fs/fs.h>
+#include <state.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct search
+{
+ union inode_result *inode;
+ const struct ramfs *rfs;
+ struct fs_ret r, *pr;
+ const char *path;
+};
+
+static void free_search(struct search *const s)
+{
+ free(s);
+}
+
+static int find_node(const char *const path, struct inode **const out,
+ size_t *const i)
+{
+ int ret = -1;
+ char *node;
+ struct inode *volatile const inode = *out;
+
+ if (fs_next(path, &node, i))
+ return -1;
+ else if (!strcmp(inode->name, node))
+ {
+ if (*i >= strlen(path))
+ {
+ free(node);
+ return 1;
+ }
+
+ *out = inode->child;
+ }
+ else
+ {
+ bool found = false;
+
+ for (struct inode *in = inode->right; in; in = in->right)
+ if (!strcmp(in->name, node))
+ {
+ if (*i >= strlen(path))
+ {
+ *out = in;
+ free(node);
+ return 1;
+ }
+
+ *out = in->child;
+ found = true;
+ break;
+ }
+
+ if (!found)
+ goto end;
+ }
+
+ ret = 0;
+
+end:
+ if (ret == -1)
+ {
+ volatile int a = 0;
+
+ a++;
+ }
+
+ free(node);
+ return ret;
+}
+
+static enum state search(void *const args)
+{
+ enum state ret = STATE_FATAL;
+ struct search *const s = args;
+ struct inode *inode = s->rfs->root;
+ size_t i = 0;
+
+ for (;;)
+ {
+ const int n = find_node(s->path, &inode, &i);
+
+ if (n < 0)
+ goto end;
+ else if (n > 0)
+ break;
+ }
+
+ s->inode->memi = inode;
+ *s->pr = s->r;
+ ret = STATE_AGAIN;
+
+end:
+ free_search(s);
+ return ret;
+}
+
+int ramfs_search(const char *const path, const struct ramfs *const rfs,
+ union inode_result *const inode, struct fs_ret *const r)
+{
+ struct search *s = malloc(sizeof *s);
+
+ if (!s)
+ goto failure;
+
+ *s = (const struct search)
+ {
+ .inode = inode,
+ .path = path,
+ .rfs = rfs,
+ .r = *r,
+ .pr = r
+ };
+
+ *r = (const struct fs_ret)
+ {
+ .f = search,
+ .args = s
+ };
+
+ return 0;
+
+failure:
+ free(s);
+ return -1;
+}
diff --git a/src/fs/ramfs/src/stat.c b/src/fs/ramfs/src/stat.c
new file mode 100644
index 0000000..c5498d9
--- /dev/null
+++ b/src/fs/ramfs/src/stat.c
@@ -0,0 +1,52 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ramfs.h>
+#include <fs/fs.h>
+#include <state.h>
+#include <sys/stat.h>
+
+static enum state done(void *const args)
+{
+ return STATE_OK;
+}
+
+int ramfs_stat(const struct fs_stat *const s, const struct ramfs *const rfs,
+ const union inode_result *const inode, struct fs_ret *const r)
+{
+ const struct inode *const i = inode->memi;
+
+ *s->sb = (const struct stat)
+ {
+ .st_atim = i->atim,
+ .st_ctim = i->ctim,
+ .st_mtim = i->mtim,
+ .st_blksize = 1,
+ .st_ino = i->ino,
+ .st_uid = i->uid,
+ .st_gid = i->gid,
+ .st_mode = i->mode
+ };
+
+ *r = (const struct fs_ret)
+ {
+ .f = done
+ };
+
+ return 0;
+}
diff --git a/src/fs/ramfs/src/write.c b/src/fs/ramfs/src/write.c
new file mode 100644
index 0000000..94b18cc
--- /dev/null
+++ b/src/fs/ramfs/src/write.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <ramfs.h>
+#include <fs/fs.h>
+#include <stddef.h>
+
+int ramfs_write(const struct fs_write *const w, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/rootfs/CMakeLists.txt b/src/fs/rootfs/CMakeLists.txt
new file mode 100644
index 0000000..b32fd82
--- /dev/null
+++ b/src/fs/rootfs/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(rootfs)
+add_subdirectory(src)
+target_include_directories(rootfs PUBLIC include PRIVATE private_include)
+target_link_libraries(rootfs PUBLIC state c PRIVATE fs ramfs)
diff --git a/src/fs/rootfs/include/rootfs.h b/src/fs/rootfs/include/rootfs.h
new file mode 100644
index 0000000..c218b1c
--- /dev/null
+++ b/src/fs/rootfs/include/rootfs.h
@@ -0,0 +1,24 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef ROOTFS_H
+#define ROOTFS_H
+
+int rootfs_register(void);
+
+#endif
diff --git a/src/fs/rootfs/private_include/rootfs/ops.h b/src/fs/rootfs/private_include/rootfs/ops.h
new file mode 100644
index 0000000..356e740
--- /dev/null
+++ b/src/fs/rootfs/private_include/rootfs/ops.h
@@ -0,0 +1,42 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef ROOTFS_OPS_H
+#define ROOTFS_OPS_H
+
+#include <fs/fs.h>
+#include <fs/inode.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stddef.h>
+
+int rootfs_mount(const struct fs_mount *m, struct fs_ret *r);
+int rootfs_mkdir(const struct fs_mkdir *m, const struct fs_mp *mp,
+ const union inode_result *i, struct fs_ret *r);
+int rootfs_open(const struct fs_open *o, const struct fs_mp *mp,
+ const union inode_result *i, struct fs_ret *r);
+int rootfs_read(const struct fs_read *r, struct fs_ret *ret);
+int rootfs_write(const struct fs_write *w, struct fs_ret *r);
+int rootfs_stat(const struct fs_stat *s, const struct fs_mp *mp,
+ const union inode_result *inode, struct fs_ret *r);
+int rootfs_close(const struct fs_close *c, struct fs_ret *r);
+int rootfs_search(const char *path, const struct fs_mp *mp,
+ union inode_result *inode, struct fs_ret *r);
+int rootfs_flags(const union inode_result *i);
+
+#endif
diff --git a/src/fs/rootfs/private_include/rootfs/types.h b/src/fs/rootfs/private_include/rootfs/types.h
new file mode 100644
index 0000000..1ce40aa
--- /dev/null
+++ b/src/fs/rootfs/private_include/rootfs/types.h
@@ -0,0 +1,32 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef ROOTFS_TYPES_H
+#define ROOTFS_TYPES_H
+
+#include <fs/fs.h>
+#include <ramfs.h>
+
+struct fs_mp_prv
+{
+ struct ramfs *rfs;
+};
+
+extern const struct fs rootfs;
+
+#endif
diff --git a/src/fs/rootfs/src/CMakeLists.txt b/src/fs/rootfs/src/CMakeLists.txt
new file mode 100644
index 0000000..b7fdcdb
--- /dev/null
+++ b/src/fs/rootfs/src/CMakeLists.txt
@@ -0,0 +1,28 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(rootfs PRIVATE
+ close.c
+ flags.c
+ mount.c
+ mkdir.c
+ open.c
+ stat.c
+ read.c
+ register.c
+ search.c
+ write.c
+)
diff --git a/src/fs/rootfs/src/close.c b/src/fs/rootfs/src/close.c
new file mode 100644
index 0000000..51a7c45
--- /dev/null
+++ b/src/fs/rootfs/src/close.c
@@ -0,0 +1,25 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <rootfs.h>
+#include <fs/fs.h>
+
+int rootfs_close(const struct fs_close *const c, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/rootfs/src/flags.c b/src/fs/rootfs/src/flags.c
new file mode 100644
index 0000000..06496bb
--- /dev/null
+++ b/src/fs/rootfs/src/flags.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <rootfs.h>
+#include <rootfs/ops.h>
+#include <fs/inode.h>
+
+int rootfs_flags(const union inode_result *const i)
+{
+ return i->memi->flags;
+}
diff --git a/src/fs/rootfs/src/mkdir.c b/src/fs/rootfs/src/mkdir.c
new file mode 100644
index 0000000..7136477
--- /dev/null
+++ b/src/fs/rootfs/src/mkdir.c
@@ -0,0 +1,30 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <rootfs.h>
+#include <rootfs/ops.h>
+#include <rootfs/types.h>
+#include <fs/fs.h>
+#include <fs/inode.h>
+#include <ramfs.h>
+
+int rootfs_mkdir(const struct fs_mkdir *const m, const struct fs_mp *const mp,
+ const union inode_result *const inode, struct fs_ret *const r)
+{
+ return ramfs_mkdir(m, mp->prv->rfs, inode, r);
+}
diff --git a/src/fs/rootfs/src/mount.c b/src/fs/rootfs/src/mount.c
new file mode 100644
index 0000000..f421918
--- /dev/null
+++ b/src/fs/rootfs/src/mount.c
@@ -0,0 +1,42 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <rootfs.h>
+#include <rootfs/types.h>
+#include <ramfs.h>
+#include <fs/fs.h>
+#include <stdlib.h>
+
+int rootfs_mount(const struct fs_mount *const m, struct fs_ret *const r)
+{
+ struct ramfs *rfs = NULL;
+ struct fs_mp_prv *const p = malloc(sizeof *p);
+
+ if (!p
+ || !(rfs = ramfs_mount(m, r))
+ || fs_mountpoint(m->src, m->tgt, &rootfs, NULL, p))
+ goto failure;
+
+ *p = (const struct fs_mp_prv){.rfs = rfs};
+ return 0;
+
+failure:
+ ramfs_free(rfs);
+ free(p);
+ return -1;
+}
diff --git a/src/fs/rootfs/src/open.c b/src/fs/rootfs/src/open.c
new file mode 100644
index 0000000..6fea301
--- /dev/null
+++ b/src/fs/rootfs/src/open.c
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <rootfs.h>
+#include <rootfs/ops.h>
+#include <fs/fs.h>
+
+int rootfs_open(const struct fs_open *const o, const struct fs_mp *const mp,
+ const union inode_result *const i, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/rootfs/src/read.c b/src/fs/rootfs/src/read.c
new file mode 100644
index 0000000..d2cb757
--- /dev/null
+++ b/src/fs/rootfs/src/read.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <rootfs.h>
+#include <fs/fs.h>
+#include <stddef.h>
+
+int rootfs_read(const struct fs_read *const r, struct fs_ret *const ret)
+{
+ return -1;
+}
diff --git a/src/fs/rootfs/src/register.c b/src/fs/rootfs/src/register.c
new file mode 100644
index 0000000..e578cf7
--- /dev/null
+++ b/src/fs/rootfs/src/register.c
@@ -0,0 +1,43 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <rootfs.h>
+#include <rootfs/ops.h>
+#include <fs/fs.h>
+
+const struct fs rootfs =
+{
+ .type = "rootfs",
+ .mount = rootfs_mount,
+ .stat = rootfs_stat,
+ .mkdir = rootfs_mkdir,
+ .open = rootfs_open,
+ .read = rootfs_read,
+ .write = rootfs_write,
+ .close = rootfs_close,
+ .iops =
+ {
+ .search = rootfs_search,
+ .flags = rootfs_flags
+ }
+};
+
+int rootfs_register(void)
+{
+ return fs_register(&rootfs);
+}
diff --git a/src/fs/rootfs/src/search.c b/src/fs/rootfs/src/search.c
new file mode 100644
index 0000000..3675f0a
--- /dev/null
+++ b/src/fs/rootfs/src/search.c
@@ -0,0 +1,29 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <rootfs.h>
+#include <rootfs/ops.h>
+#include <rootfs/types.h>
+#include <fs/fs.h>
+#include <ramfs.h>
+
+int rootfs_search(const char *const path, const struct fs_mp *const mp,
+ union inode_result *const inode, struct fs_ret *const r)
+{
+ return ramfs_search(path, mp->prv->rfs, inode, r);
+}
diff --git a/src/fs/rootfs/src/stat.c b/src/fs/rootfs/src/stat.c
new file mode 100644
index 0000000..2eff55c
--- /dev/null
+++ b/src/fs/rootfs/src/stat.c
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <rootfs.h>
+#include <rootfs/ops.h>
+#include <fs/fs.h>
+#include <sys/stat.h>
+
+int rootfs_stat(const struct fs_stat *const s, const struct fs_mp *const mp,
+ const union inode_result *const inode, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/rootfs/src/write.c b/src/fs/rootfs/src/write.c
new file mode 100644
index 0000000..53b9704
--- /dev/null
+++ b/src/fs/rootfs/src/write.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <rootfs.h>
+#include <fs/fs.h>
+#include <stddef.h>
+
+int rootfs_write(const struct fs_write *const w, struct fs_ret *const r)
+{
+ return -1;
+}
diff --git a/src/fs/src/CMakeLists.txt b/src/fs/src/CMakeLists.txt
new file mode 100644
index 0000000..7f2c7a5
--- /dev/null
+++ b/src/fs/src/CMakeLists.txt
@@ -0,0 +1,30 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(fs PRIVATE
+ from_type.c
+ headtail.c
+ mountpoint.c
+ mp_from_path.c
+ mps_from_path.c
+ parent.c
+ register.c
+ relpath.c
+ update.c
+ next.c
+)
+
+add_subdirectory(inode)
diff --git a/src/fs/src/from_type.c b/src/fs/src/from_type.c
new file mode 100644
index 0000000..b836cdd
--- /dev/null
+++ b/src/fs/src/from_type.c
@@ -0,0 +1,36 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/fs.h>
+#include <fs/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+const struct fs *fs_from_type(const char *const type)
+{
+ for (const struct fs_register *r = fs_rhead; r; r = r->next)
+ {
+ const struct fs *const fs = r->fs;
+
+ if (!strcmp(type, fs->type))
+ return fs;
+ }
+
+ return NULL;
+}
diff --git a/src/fs/src/headtail.c b/src/fs/src/headtail.c
new file mode 100644
index 0000000..f5eaf79
--- /dev/null
+++ b/src/fs/src/headtail.c
@@ -0,0 +1,22 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/types.h>
+
+struct fs_register *fs_rhead, *fs_rtail;
+struct fs_mountpoint *fs_mphead, *fs_mptail;
diff --git a/src/fs/src/inode/CMakeLists.txt b/src/fs/src/inode/CMakeLists.txt
new file mode 100644
index 0000000..1b0e0fd
--- /dev/null
+++ b/src/fs/src/inode/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(fs PRIVATE
+ free.c
+ search.c
+)
diff --git a/src/fs/src/inode/free.c b/src/fs/src/inode/free.c
new file mode 100644
index 0000000..0ff18f2
--- /dev/null
+++ b/src/fs/src/inode/free.c
@@ -0,0 +1,31 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/inode.h>
+#include <stdlib.h>
+
+void inode_free(struct inode *const i)
+{
+ if (i)
+ {
+ inode_free(i->child);
+ free(i->name);
+ }
+
+ free(i);
+}
diff --git a/src/fs/src/inode/search.c b/src/fs/src/inode/search.c
new file mode 100644
index 0000000..09b38a1
--- /dev/null
+++ b/src/fs/src/inode/search.c
@@ -0,0 +1,121 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/inode.h>
+#include <fs/fs.h>
+#include <fs/types.h>
+#include <state.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct search
+{
+ struct fs_mp *mp;
+ size_t n, mp_i;
+ struct fs_ret *r;
+ union inode_result inode;
+ struct inode_search search;
+};
+
+static void free_search(struct search *const s)
+{
+ free(s);
+}
+
+static enum state search_mp(struct search *const s)
+{
+ const struct inode_search *const is = &s->search;
+ const struct fs_mp *const cur = &s->mp[s->mp_i],
+ *const next = s->mp_i + 1 < s->n ?
+ &s->mp[s->mp_i + 1] : NULL;
+ const struct fs *const fs = cur->fs;
+ const char *relpath = next ? next->tgt : is->path;
+
+ for (size_t i = 0; i < s->mp_i; i++)
+ relpath += strlen(s->mp[s->mp_i].tgt);
+
+ if (fs && fs->iops.search(relpath, cur, &s->inode, s->r))
+ return STATE_FATAL;
+
+ s->mp_i++;
+ return STATE_AGAIN;
+}
+
+static enum state search(void *const args)
+{
+ struct search *const s = args;
+ const struct inode_search *const is = &s->search;
+
+ if (!s->mp)
+ {
+ const int ret = is->done(STATE_FATAL, NULL, NULL, NULL, is->args);
+
+ free_search(s);
+ return ret ? STATE_FATAL : STATE_AGAIN;
+ }
+ else if (s->mp_i < s->n)
+ return search_mp(s);
+ else
+ {
+ const char *relpath = is->path;
+
+ for (size_t i = 0; i < s->n; i++)
+ relpath += strlen(s->mp[i].tgt);
+
+ const int ret = is->done(STATE_OK, relpath, &s->mp[s->n - 1],
+ &s->inode, is->args);
+
+ free_search(s);
+ return ret ? STATE_FATAL : STATE_AGAIN;
+ }
+
+ return STATE_FATAL;
+}
+
+int inode_search(const struct inode_search *const is, struct fs_ret *const r)
+{
+ struct search *s = NULL;
+ size_t n;
+ /* Do not check for errors yet. */
+ struct fs_mp *const mp = fs_mps_from_path(is->path, &n);
+
+ if (!(s = malloc(sizeof *s)))
+ goto failure;
+
+ *s = (const struct search)
+ {
+ .search = *is,
+ .mp = mp,
+ .n = n,
+ .r = r
+ };
+
+ *r = (const struct fs_ret)
+ {
+ .f = search,
+ .args = s
+ };
+
+ return 0;
+
+failure:
+ free(s);
+ free(mp);
+ return -1;
+}
diff --git a/src/fs/src/mountpoint.c b/src/fs/src/mountpoint.c
new file mode 100644
index 0000000..6ae5a0e
--- /dev/null
+++ b/src/fs/src/mountpoint.c
@@ -0,0 +1,60 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/fs.h>
+#include <fs/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+int fs_mountpoint(const char *const src, const char *const tgt,
+ const struct fs *const fs, const fs_update_fn fn,
+ struct fs_mp_prv *const pr)
+{
+ struct fs_mountpoint *m = NULL;
+ char *srcdup = NULL, *const tgtdup = strdup(tgt);
+
+ if (!tgtdup)
+ goto failure;
+ else if (src && !(srcdup = strdup(src)))
+ goto failure;
+ else if (!(m = malloc(sizeof *m)))
+ goto failure;
+
+ *m = (const struct fs_mountpoint)
+ {
+ .src = srcdup,
+ .tgt = tgtdup,
+ .update = fn,
+ .fs = fs,
+ .prv = pr
+ };
+
+ if (!fs_mphead)
+ fs_mphead = m;
+ else if (fs_mptail)
+ fs_mptail->next = m;
+
+ fs_mptail = m;
+ return 0;
+
+failure:
+ free(srcdup);
+ free(tgtdup);
+ free(m);
+ return -1;
+}
diff --git a/src/fs/src/mp_from_path.c b/src/fs/src/mp_from_path.c
new file mode 100644
index 0000000..5e69ea6
--- /dev/null
+++ b/src/fs/src/mp_from_path.c
@@ -0,0 +1,40 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/fs.h>
+#include <fs/types.h>
+#include <string.h>
+
+int fs_mp_from_path(const char *const path, struct fs_mp *const mp)
+{
+ for (const struct fs_mountpoint *p = fs_mphead; p; p = p->next)
+ if (!strcmp(path, p->tgt))
+ {
+ *mp = (const struct fs_mp)
+ {
+ .fs = p->fs,
+ .prv = p->prv,
+ .src = p->src,
+ .tgt= p->tgt
+ };
+
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/src/fs/src/mps_from_path.c b/src/fs/src/mps_from_path.c
new file mode 100644
index 0000000..a3d5510
--- /dev/null
+++ b/src/fs/src/mps_from_path.c
@@ -0,0 +1,89 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/fs.h>
+#include <fs/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+static struct fs_mp *find(const char *const path, size_t *const out)
+{
+ struct fs_mp *ret = NULL;
+ size_t n = 0;
+
+ for (const struct fs_mountpoint *p = fs_mphead; p; p = p->next)
+ {
+ const size_t len = strlen(p->tgt);
+
+ if (!strncmp(p->tgt, path, len))
+ {
+ const size_t sz = n + 1;
+ struct fs_mp *const m = realloc(ret, sz * sizeof *m);
+
+ if (!m)
+ goto failure;
+
+ m[n++] = (const struct fs_mp)
+ {
+ .fs = p->fs,
+ .prv = p->prv,
+ .src = p->src,
+ .tgt = p->tgt
+ };
+
+ ret = m;
+ }
+ }
+
+ *out = n;
+ return ret;
+
+failure:
+ free(ret);
+ return NULL;
+}
+
+static void sort(struct fs_mp *const m, const size_t n)
+{
+ for (size_t i = 1; i < n; i++)
+ {
+ struct fs_mp am = m[i];
+ const size_t len = strlen(am.tgt);
+ size_t j = i;
+
+ while (j && len < strlen(m[j - 1].tgt))
+ {
+ m[j] = m [j - 1];
+ j--;
+ }
+
+ m[j] = am;
+ }
+}
+
+struct fs_mp *fs_mps_from_path(const char *const path, size_t *const n)
+{
+ struct fs_mp *const ret = find(path, n);
+
+ if (!ret)
+ return NULL;
+
+ sort(ret, *n);
+ return ret;
+}
diff --git a/src/fs/src/next.c b/src/fs/src/next.c
new file mode 100644
index 0000000..dac2352
--- /dev/null
+++ b/src/fs/src/next.c
@@ -0,0 +1,59 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/fs.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+int fs_next(const char *const path, char **const out, size_t *const i)
+{
+ char *next = NULL;
+
+ if (*i >= strlen(path))
+ goto failure;
+
+ const char *const s = &path[*i];
+
+ if (*s == '/')
+ {
+ if (!(next = strdup("/")))
+ goto failure;
+
+ (*i)++;
+ *out = next;
+ return 0;
+ }
+
+ const char *sep = strchr(s, '/');
+ next = sep ? strndup(s, sep - s) : strdup(s);
+
+ if (!next)
+ goto failure;
+ else if (sep)
+ while (*sep && *sep == '/')
+ sep++;
+
+ *i += sep ? sep - s : strlen(s);
+ *out = next;
+ return 0;
+
+failure:
+ free(next);
+ return -1;
+}
diff --git a/src/fs/src/parent.c b/src/fs/src/parent.c
new file mode 100644
index 0000000..34ed0ab
--- /dev/null
+++ b/src/fs/src/parent.c
@@ -0,0 +1,33 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/fs.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *fs_parent(const char *const path)
+{
+ char *ret = NULL;
+ const char *const sep = strrchr(path, '/');
+
+ if (!sep || !(ret = strndup(path, sep - path + 1)))
+ return NULL;
+
+ return ret;
+}
diff --git a/src/fs/src/register.c b/src/fs/src/register.c
new file mode 100644
index 0000000..a503d2a
--- /dev/null
+++ b/src/fs/src/register.c
@@ -0,0 +1,42 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/fs.h>
+#include <fs/types.h>
+#include <stdlib.h>
+
+int fs_register(const struct fs *const fs)
+{
+ struct fs_register *const r = malloc(sizeof *r);
+
+ if (!r)
+ return -1;
+ else if (!fs_rhead)
+ fs_rhead = r;
+ else if (fs_rtail)
+ fs_rtail->next = r;
+
+ fs_rtail = r;
+
+ *r = (const struct fs_register)
+ {
+ .fs = fs
+ };
+
+ return 0;
+}
diff --git a/src/fs/src/relpath.c b/src/fs/src/relpath.c
new file mode 100644
index 0000000..e7414c2
--- /dev/null
+++ b/src/fs/src/relpath.c
@@ -0,0 +1,43 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/fs.h>
+#include <fs/types.h>
+#include <string.h>
+
+const char *fs_relpath(const char *const path)
+{
+ size_t lastn = 0;
+ const struct fs_mountpoint *mp = NULL;
+
+ for (const struct fs_mountpoint *m = fs_mphead; m; m = m->next)
+ {
+ const size_t n = strlen(m->tgt);
+
+ if (!strncmp(m->tgt, path, n) && lastn < n)
+ {
+ lastn = n;
+ mp = m;
+ }
+ }
+
+ if (!mp)
+ return NULL;
+
+ return path + strlen(mp->tgt);
+}
diff --git a/src/fs/src/update.c b/src/fs/src/update.c
new file mode 100644
index 0000000..5f47eb3
--- /dev/null
+++ b/src/fs/src/update.c
@@ -0,0 +1,30 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <fs/fs.h>
+#include <fs/types.h>
+#include <stddef.h>
+
+int fs_update(void)
+{
+ for (const struct fs_mountpoint *m = fs_mphead; m; m = m->next)
+ if (m->update && m->update(m->prv))
+ return -1;
+
+ return 0;
+}
diff --git a/src/gfx/CMakeLists.txt b/src/gfx/CMakeLists.txt
new file mode 100644
index 0000000..acb07d2
--- /dev/null
+++ b/src/gfx/CMakeLists.txt
@@ -0,0 +1,25 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(gfx)
+add_subdirectory(src)
+target_include_directories(gfx PUBLIC include)
+
+if(PS1_BUILD)
+ add_subdirectory(ps1)
+elseif(SDL1_2_BUILD)
+ add_subdirectory(sdl-1.2)
+endif()
diff --git a/src/gfx/include/gfx/gfx.h b/src/gfx/include/gfx/gfx.h
new file mode 100644
index 0000000..95c602a
--- /dev/null
+++ b/src/gfx/include/gfx/gfx.h
@@ -0,0 +1,48 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GFX_H
+#define GFX_H
+
+#include <gfx/port.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+int gfx_init(void);
+int gfx_draw(void);
+bool gfx_ready(void);
+int gfx_toggle_fullscreen(void);
+int gfx_set_fullscreen(short w, short h);
+bool gfx_fullscreen_available(void);
+bool gfx_fullscreen(void);
+int gfx_display_size(short *w, short *h);
+
+void gfx_rect_init(struct gfx_rect *r);
+void semitrans_rect_init(struct gfx_rect *r);
+void stp_4line_init(struct stp_4line *l);
+void quad_sort(struct quad *q);
+void gfx_rect_sort(struct gfx_rect *r);
+void stp_4line_sort(struct stp_4line *l);
+int sprite_from_fp(struct gfx_sprite *s, FILE *f);
+int quad_from_sprite(const struct gfx_sprite *s, struct quad *q);
+bool gfx_inside_drawenv(short x, short y, short w, short h);
+void gfx_deinit(void);
+
+extern int screen_w, screen_h;
+
+#endif /* GFX_H */
diff --git a/src/gfx/include/gfx/sprite.h b/src/gfx/include/gfx/sprite.h
new file mode 100644
index 0000000..9746524
--- /dev/null
+++ b/src/gfx/include/gfx/sprite.h
@@ -0,0 +1,32 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GFX_SPRITE_H
+#define GFX_SPRITE_H
+
+#include <gfx/port.h>
+#include <stddef.h>
+
+typedef int (*gfx_read)(void *buf, size_t n, void *args);
+
+int gfx_sprite_load(struct gfx_sprite *s, gfx_read r, void *args);
+int gfx_sprite_sort(struct gfx_sprite *s);
+int gfx_sprite_clone(const struct gfx_sprite *src, struct gfx_sprite *dst);
+void gfx_sprite_free(struct gfx_sprite *s);
+
+#endif
diff --git a/src/gfx/ps1/CMakeLists.txt b/src/gfx/ps1/CMakeLists.txt
new file mode 100644
index 0000000..1de20a7
--- /dev/null
+++ b/src/gfx/ps1/CMakeLists.txt
@@ -0,0 +1,40 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_subdirectory(src)
+target_include_directories(gfx PUBLIC include PRIVATE private_include)
+target_link_libraries(gfx PRIVATE
+ drv_ps1_bios
+ drv_ps1_dma
+ drv_ps1_interrupt
+ drv_ps1_gpu
+)
+
+set(modes VMODE_PAL VMODE_NTSC)
+
+if(VIDEO_MODE)
+ if(NOT "${VIDEO_MODE}" IN_LIST modes)
+ message(FATAL_ERROR "Invalid video mode ${VIDEO_MODE}. Available options:\n"
+ "${modes}\n"
+ "Run CMake again using one of the available video modes e.g.: cmake .. -DVIDEO_MODE=VMODE_PAL")
+ endif()
+
+ target_compile_definitions(gfx PRIVATE VIDEO_MODE=${VIDEO_MODE})
+else()
+ message(FATAL_ERROR "Please define video mode. Available options:\n"
+ "${modes}\n"
+ "Run CMake again using one of the available video modes e.g.: cmake .. -DVIDEO_MODE=VMODE_PAL")
+endif()
diff --git a/src/gfx/ps1/include/gfx/port.h b/src/gfx/ps1/include/gfx/port.h
new file mode 100644
index 0000000..2e609d1
--- /dev/null
+++ b/src/gfx/ps1/include/gfx/port.h
@@ -0,0 +1,126 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GFX_PS1_H
+#define GFX_PS1_H
+
+#include <stdint.h>
+
+union gfx_common
+{
+ struct
+ {
+ uint32_t tpagex :4, tpagey :1, stp :2, bpp :2, dither :1,
+ draw_to_disp :1, disable :1, xflip :1, yflip :1, :10;
+ uint8_t cmd;
+ } f;
+
+ uint32_t mask;
+};
+
+union gfx_sznext
+{
+ struct
+ {
+ uint32_t next :24, sz :8;
+ } f;
+
+ uint32_t cmd_next;
+};
+
+struct gfx_sprite
+{
+ union gfx_sznext sznext;
+ union gfx_common common;
+ uint8_t r, g, b;
+ uint8_t cmd;
+ int16_t x, y;
+ uint8_t u, v;
+ uint16_t clutid;
+ uint16_t w, h;
+};
+
+struct quad
+{
+ union gfx_sznext sznext;
+ uint8_t r, g, b;
+ uint8_t cmd;
+ int16_t x0, y0;
+ uint8_t u0, v0;
+ uint16_t clutid;
+ int16_t x1, y1;
+ uint8_t u1, v1;
+
+ union
+ {
+ struct
+ {
+ /* 0-8 Same as GP0(E1h).Bit0-8. */
+ uint16_t lb :9;
+ uint16_t :2;
+ /* 11 Same as GP0(E1h).Bit11. */
+ uint16_t hb :1;
+ uint16_t :4;
+ } bit;
+
+ uint16_t mask;
+ } tpage;
+
+ int16_t x2, y2;
+ uint8_t u2, v2;
+ uint16_t :16;
+ int16_t x3, y3;
+ uint8_t u3, v3;
+ uint16_t :16;
+};
+
+struct gfx_rect
+{
+ union gfx_sznext sznext;
+ union gfx_common common;
+ uint8_t r, g, b;
+ uint8_t cmd;
+ int16_t x, y;
+ uint16_t w, h;
+};
+
+struct stp_4line
+{
+ union gfx_sznext sznext;
+ union gfx_common common;
+ uint8_t r, g, b;
+ uint8_t cmd;
+ int16_t x, y;
+
+ struct stp_4line_vtx
+ {
+ uint32_t r :8, g :8, b :8, :8;
+ int16_t x, y;
+ } vertices[4];
+
+ uint32_t end;
+};
+
+void gfx_add_to_list(union gfx_sznext *p);
+void *gfx_heap_top(void);
+struct gfx_sprite *gfx_sprite_get(void);
+struct quad *quad_get(void);
+struct gfx_rect *rect_get(void);
+struct stp_4line *stp_4line_get(void);
+
+#endif
diff --git a/src/gfx/ps1/private_include/gfx/private.h b/src/gfx/ps1/private_include/gfx/private.h
new file mode 100644
index 0000000..72d8f39
--- /dev/null
+++ b/src/gfx/ps1/private_include/gfx/private.h
@@ -0,0 +1,19 @@
+#ifndef GFX_PS1_PRIVATE_H
+#define GFX_PS1_PRIVATE_H
+
+#include <gfx/gfx.h>
+
+enum
+{
+ SCREEN_W = 640,
+ SCREEN_H = 480
+};
+
+void gfx_swapheap(void);
+void gfx_initenvs(void);
+void gfx_swapbuffers(void);
+void gfx_swapenvs(void);
+
+extern int gfx_vblank_ev;
+
+#endif
diff --git a/src/gfx/ps1/src/4line.c b/src/gfx/ps1/src/4line.c
new file mode 100644
index 0000000..766eb2d
--- /dev/null
+++ b/src/gfx/ps1/src/4line.c
@@ -0,0 +1,15 @@
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <psxgpu.h>
+#include <stdint.h>
+#include <string.h>
+
+void stp_4line_init(struct stp_4line *const l)
+{
+ memset(l, 0, sizeof *l);
+ l->sznext.f.sz = (sizeof *l - sizeof l->sznext) / sizeof (uint32_t);
+ l->common.f.cmd = DRAW_MODE;
+ l->cmd = 0x5A;
+ enum {TERMINATION_CODE = 0x55555555};
+ l->end = TERMINATION_CODE;
+}
diff --git a/src/gfx/ps1/src/CMakeLists.txt b/src/gfx/ps1/src/CMakeLists.txt
new file mode 100644
index 0000000..418bd3b
--- /dev/null
+++ b/src/gfx/ps1/src/CMakeLists.txt
@@ -0,0 +1,32 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(gfx PRIVATE
+ # 4line.c
+ # env.c
+ draw.c
+ heap.c
+ init.c
+ ready.c
+ swapenvs.c
+ # quad.c
+ # rect.c
+ # sort.c
+ # sprite.c
+ vblank.c
+)
+
+add_subdirectory(sprite)
diff --git a/src/gfx/ps1/src/add_to_list.c b/src/gfx/ps1/src/add_to_list.c
new file mode 100644
index 0000000..dff4910
--- /dev/null
+++ b/src/gfx/ps1/src/add_to_list.c
@@ -0,0 +1,39 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <stddef.h>
+#include <stdint.h>
+
+static union gfx_sznext *first, *last;
+
+void gfx_add_to_list(union gfx_sznext *const p)
+{
+ if (!first)
+ first = p;
+ else if (last)
+ last->f.next = (uint32_t)p;
+
+ last = p;
+}
+
+void *gfx_heap_top(void)
+{
+ return first;
+}
diff --git a/src/gfx/ps1/src/deinit.c b/src/gfx/ps1/src/deinit.c
new file mode 100644
index 0000000..ccf6c2d
--- /dev/null
+++ b/src/gfx/ps1/src/deinit.c
@@ -0,0 +1,24 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+
+void gfx_deinit(void)
+{
+}
diff --git a/src/gfx/ps1/src/draw.c b/src/gfx/ps1/src/draw.c
new file mode 100644
index 0000000..40abdf7
--- /dev/null
+++ b/src/gfx/ps1/src/draw.c
@@ -0,0 +1,70 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <drv/ps1/dma.h>
+#include <drv/ps1/gpu.h>
+
+static union gfx_sznext *first, *last;
+
+void gfx_add_to_list(union gfx_sznext *const p)
+{
+ if (!first)
+ first = p;
+ else if (last)
+ last->f.next = (uint32_t)p;
+
+ last = p;
+}
+
+int gfx_draw(void)
+{
+ static union gfx_sznext term = {.cmd_next = 0xffffff};
+
+ gfx_add_to_list(&term);
+
+ if (SCREEN_W != 640)
+ gfx_swapenvs();
+
+ gfx_swapheap();
+
+ GP1->mask = (const union drv_ps1_gpu_gp1)
+ {
+ .dma =
+ {
+ .cmd = GP1_DMA_DIR,
+ .dir = GP1_DMA_DIR_CPU_TO_GP0
+ }
+ }.mask;
+
+ D2_MADR->mask = (uint32_t)first;
+ D2_BCR->syncmode_2.reserved = 0;
+ D2_CHCR->mask = (const union chcr)
+ {
+ .bits =
+ {
+ .sync_mode = CHCR_SYNC_MODE_LINKED_LIST,
+ .dir = CHCR_DIR_FROM_RAM,
+ .start_busy = 1
+ }
+ }.mask;
+
+ first = NULL;
+ return 0;
+}
diff --git a/src/gfx/ps1/src/env.c b/src/gfx/ps1/src/env.c
new file mode 100644
index 0000000..100f366
--- /dev/null
+++ b/src/gfx/ps1/src/env.c
@@ -0,0 +1,71 @@
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <psxgpu.h>
+#include <errno.h>
+#include <stdbool.h>
+
+static GsDispEnv dispenv;
+enum {ENV_Y = SCREEN_H + 16};
+
+static GsDrawEnv drawenv =
+{
+ .y = ENV_Y,
+ .w = SCREEN_W,
+ .h = SCREEN_H
+};
+
+int screen_w = SCREEN_W, screen_h = SCREEN_H;
+
+void gfx_swapbuffers(void)
+{
+ const short y = drawenv.y;
+
+ drawenv.y = dispenv.y;
+ dispenv.y = y;
+ GsSetDrawEnv(&drawenv);
+ GsSetDispEnv(&dispenv);
+}
+
+void gfx_initenvs(void)
+{
+ GsSetDrawEnv(&drawenv);
+ GsSetDispEnv(&dispenv);
+}
+
+int gfx_toggle_fullscreen(void)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+int gfx_set_fullscreen(const short w, const short h)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+bool gfx_fullscreen_available(void)
+{
+ return false;
+}
+
+bool gfx_fullscreen(void)
+{
+ return true;
+}
+
+int gfx_display_size(short *const w, short *const h)
+{
+ *w = SCREEN_W;
+ *h = SCREEN_H;
+ return 0;
+}
+
+bool gfx_inside_drawenv(const short x, const short y, const short w,
+ const short h)
+{
+ return (x + w >= 0)
+ && x < drawenv.w
+ && (y + h >= 0)
+ && y < drawenv.h;
+}
diff --git a/src/gfx/ps1/src/heap.c b/src/gfx/ps1/src/heap.c
new file mode 100644
index 0000000..feb95c9
--- /dev/null
+++ b/src/gfx/ps1/src/heap.c
@@ -0,0 +1,73 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <stddef.h>
+
+static unsigned int sel;
+static size_t heap_i;
+
+void gfx_swapheap(void)
+{
+ sel ^= 1;
+ heap_i = 0;
+}
+
+static void *get_element(const size_t sz)
+{
+ enum {HEAP_SZ = 49152, N_HEAPS = 2};
+ static char heaps[N_HEAPS][HEAP_SZ];
+ const size_t new_sz = heap_i + sz;
+ void *ret = NULL;
+
+ if (new_sz < sizeof *heaps / sizeof **heaps)
+ {
+ ret = &heaps[sel][heap_i];
+ heap_i += sz;
+ }
+ else
+ {
+ static volatile int a;
+
+ a++;
+ return NULL;
+ }
+
+ return ret;
+}
+
+struct gfx_sprite *gfx_sprite_get(void)
+{
+ return get_element(sizeof (struct gfx_sprite));
+}
+
+struct quad *quad_get(void)
+{
+ return get_element(sizeof (struct quad));
+}
+
+struct gfx_rect *rect_get(void)
+{
+ return get_element(sizeof (struct gfx_rect));
+}
+
+struct stp_4line *stp_4line_get(void)
+{
+ return get_element(sizeof (struct stp_4line));
+}
diff --git a/src/gfx/ps1/src/init.c b/src/gfx/ps1/src/init.c
new file mode 100644
index 0000000..3a94f32
--- /dev/null
+++ b/src/gfx/ps1/src/init.c
@@ -0,0 +1,153 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <drv/ps1/bios.h>
+#include <drv/ps1/dma.h>
+#include <drv/ps1/gpu.h>
+#include <drv/ps1/interrupt.h>
+#include <stddef.h>
+
+struct res
+{
+ int hres, hres2, vres, interlace;
+};
+
+static void getres(const short w, struct res *const r)
+{
+ *r = (const struct res){0};
+
+ switch (w)
+ {
+ case 320:
+ r->hres = 1;
+ break;
+ case 368:
+ r->hres2 = 1;
+ break;
+ case 512:
+ r->hres = 2;
+ break;
+ case 640:
+ r->hres = 3;
+ r->vres = 1;
+ r->interlace = 1;
+ break;
+ }
+}
+
+int gfx_init(void)
+{
+ const union dpcr dpcr = {.bits.gpu_en = 1};
+ const int event = OpenEvent(CLASS_VBLANK, SPEC_INTERRUPTED, MODE_READY,
+ NULL);
+
+ if (event == -1)
+ return -1;
+
+ DPCR->mask |= dpcr.mask;
+ GP1->mask = (const union drv_ps1_gpu_gp1)
+ {
+ .dma =
+ {
+ .cmd = GP1_DMA_DIR,
+ .dir = GP1_DMA_DIR_CPU_TO_GP0
+ }
+ }.mask;
+
+ GP1->mask = (const union drv_ps1_gpu_gp1)
+ {
+ .display =
+ {
+ .cmd = GP1_DISPLAY_ENABLE,
+ }
+ }.mask;
+
+ GP0->mask = (const union drv_ps1_gpu_gp0)
+ {.draw_mode.cmd = GP0_DRAW_MODE}.mask;
+
+ GP0->mask = (const union drv_ps1_gpu_gp0)
+ {.tex_window.cmd = GP0_TEX_WINDOW}.mask;
+
+ GP0->mask = (const union drv_ps1_gpu_gp0)
+ {.draw_area_tl.cmd = GP0_DRAW_AREA_TOP_LEFT}.mask;
+
+ GP0->mask = (const union drv_ps1_gpu_gp0)
+ {
+ .draw_area_br =
+ {
+ .cmd = GP0_DRAW_AREA_BOTTOM_RIGHT,
+ .x = SCREEN_W - 1,
+ .y = SCREEN_H - 1,
+ }
+ }.mask;
+
+ GP1->mask = (const union drv_ps1_gpu_gp1)
+ {
+ .h_display_range =
+ {
+ .cmd = GP1_H_DISPLAY_RANGE,
+ .x1 = 0x260,
+ .x2 = 0x260 + 320 * 8
+ }
+ }.mask;
+
+#if 0
+ GP1->mask = (const union drv_ps1_gpu_gp1)
+ {
+ .v_display_range =
+ {
+ .cmd = GP1_V_DISPLAY_RANGE,
+#if VIDEO_MODE == VMODE_PAL
+ .y1 = 0xa3,
+ .y2 = 0xa3 + (SCREEN_H / 2)
+#elif VIDEO_MODE == VMODE_NTSC
+ .y1 = 0x88 - (224 / 2),
+ .y2 = 0x88 + (224 / 2)
+#endif
+ }
+ }.mask;
+#else
+ GP1->mask = 0x06C4E24E;
+ GP1->mask = 0x07040010;
+#endif
+
+ struct res r;
+
+ getres(SCREEN_W, &r);
+
+ GP1->mask = (const union drv_ps1_gpu_gp1)
+ {
+ .display_mode =
+ {
+ .cmd = GP1_DISPLAY_MODE,
+ .hres = r.hres,
+ .hres2 = r.hres2,
+ .vres = r.vres,
+ .vinterlace = r.interlace,
+#if VIDEO_MODE == VMODE_PAL
+ .vmode = 1
+#endif
+ }
+ }.mask;
+
+ I_MASK->bits.vblank = 1;
+ EnableEvent(gfx_vblank_ev = event);
+ return 0;
+}
diff --git a/src/gfx/ps1/src/quad.c b/src/gfx/ps1/src/quad.c
new file mode 100644
index 0000000..bfabee2
--- /dev/null
+++ b/src/gfx/ps1/src/quad.c
@@ -0,0 +1,24 @@
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <gfx/port.h>
+#include <stdint.h>
+#include <string.h>
+
+static void quad_init(struct quad *const q)
+{
+ memset(q, 0, sizeof *q);
+ q->sznext.f.sz = (sizeof *q - sizeof q->sznext) / sizeof (uint32_t);
+ q->cmd = 0x2d;
+}
+
+int quad_from_sprite(const struct gfx_sprite *const s, struct quad *const q)
+{
+ quad_init(q);
+ q->tpage.mask = s->common.mask;
+ q->clutid = s->clutid;
+ q->u0 = q->u2 = s->u;
+ q->v0 = q->v1 = s->v;
+ q->u1 = q->u3 = s->u + s->w - 1;
+ q->v2 = q->v3 = s->v + s->h - 1;
+ return 0;
+}
diff --git a/src/gfx/ps1/src/ready.c b/src/gfx/ps1/src/ready.c
new file mode 100644
index 0000000..0e17cdb
--- /dev/null
+++ b/src/gfx/ps1/src/ready.c
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <drv/ps1/bios.h>
+#include <stdbool.h>
+
+bool gfx_ready(void)
+{
+ return TestEvent(gfx_vblank_ev);
+}
diff --git a/src/gfx/ps1/src/rect.c b/src/gfx/ps1/src/rect.c
new file mode 100644
index 0000000..57b1b2a
--- /dev/null
+++ b/src/gfx/ps1/src/rect.c
@@ -0,0 +1,25 @@
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <psxgpu.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+static void common_init(struct gfx_rect *const r)
+{
+ memset(r, 0, sizeof *r);
+ r->sznext.f.sz = (sizeof *r - sizeof r->sznext) / sizeof (uint32_t);
+ r->common.f.cmd = DRAW_MODE;
+}
+
+void gfx_rect_init(struct gfx_rect *const r)
+{
+ common_init(r);
+ r->cmd = 0x60;
+}
+
+void semitrans_rect_init(struct gfx_rect *const r)
+{
+ common_init(r);
+ r->cmd = 0x62;
+}
diff --git a/src/gfx/ps1/src/sort.c b/src/gfx/ps1/src/sort.c
new file mode 100644
index 0000000..5c1c278
--- /dev/null
+++ b/src/gfx/ps1/src/sort.c
@@ -0,0 +1,73 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <drv/ps1/bios.h>
+#include <stddef.h>
+#include <stdint.h>
+
+static union gfx_sznext *first, *last;
+
+static void add_to_list(union gfx_sznext *const p)
+{
+ if (!first)
+ first = p;
+ else if (last)
+ last->f.next = (uint32_t)p;
+
+ last = p;
+}
+
+void sprite_sort(struct gfx_sprite *const s)
+{
+ add_to_list(&s->sznext);
+}
+
+void quad_sort(struct quad *const q)
+{
+ add_to_list(&q->sznext);
+}
+
+void gfx_rect_sort(struct gfx_rect *const r)
+{
+ add_to_list(&r->sznext);
+}
+
+void stp_4line_sort(struct stp_4line *const l)
+{
+ add_to_list(&l->sznext);
+}
+
+int gfx_draw(void)
+{
+ static union gfx_sznext term = {.cmd_next = 0xffffff};
+
+ add_to_list(&term);
+
+ void gpu_ctrl(unsigned int command, unsigned int param);
+
+ gfx_swapbuffers();
+ gfx_swapheap();
+ gpu_ctrl(4, 2);
+ D2_MADR = (uint32_t)first;
+ D2_BCR = 0;
+ D2_CHCR = (1 << 0xa) | 1 | (1 << 0x18);
+ first = NULL;
+ return 0;
+}
diff --git a/src/gfx/ps1/src/sprite/CMakeLists.txt b/src/gfx/ps1/src/sprite/CMakeLists.txt
new file mode 100644
index 0000000..b42d699
--- /dev/null
+++ b/src/gfx/ps1/src/sprite/CMakeLists.txt
@@ -0,0 +1,22 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(gfx PRIVATE
+ clone.c
+ free.c
+ load.c
+ sort.c
+)
diff --git a/src/gfx/ps1/src/sprite/clone.c b/src/gfx/ps1/src/sprite/clone.c
new file mode 100644
index 0000000..30d0d32
--- /dev/null
+++ b/src/gfx/ps1/src/sprite/clone.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+
+int gfx_sprite_clone(const struct gfx_sprite *const src,
+ struct gfx_sprite *const dst)
+{
+ *dst = *src;
+ return 0;
+}
diff --git a/src/gfx/ps1/src/sprite/free.c b/src/gfx/ps1/src/sprite/free.c
new file mode 100644
index 0000000..3b3d984
--- /dev/null
+++ b/src/gfx/ps1/src/sprite/free.c
@@ -0,0 +1,23 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+
+void sprite_free(struct gfx_sprite *const src)
+{
+}
diff --git a/src/gfx/ps1/src/sprite/load.c b/src/gfx/ps1/src/sprite/load.c
new file mode 100644
index 0000000..7664017
--- /dev/null
+++ b/src/gfx/ps1/src/sprite/load.c
@@ -0,0 +1,191 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+#include <gfx/sprite.h>
+#include <gfx/private.h>
+#include <drv/ps1/gpu.h>
+#include <stdint.h>
+
+static void init(struct gfx_sprite *const s)
+{
+ *s = (const struct gfx_sprite){0};
+ s->sznext.f.sz = (sizeof *s - sizeof s->sznext) / sizeof (uint32_t);
+ s->common.f.cmd = GP0_DRAW_MODE;
+ s->cmd = GP0_TEXTRECT_VARSZ_OPAQ_RAW;
+}
+
+struct tim_pos
+{
+ uint16_t x, y, w, h;
+};
+
+static void transfer_init(const struct tim_pos *const p)
+{
+ while (!GPUSTAT->bits.ready_cmd)
+ ;
+
+ GP0->mask = (const union drv_ps1_gpu_gp0)
+ {.copy_rect.cmd = GP0_COPY_RECT_CPU_VRAM}.mask;
+ GP0->mask = (const union drv_ps1_gpu_gp0)
+ {.coord = {.x = p->x, .y = p->y}}.mask;
+ GP0->mask = (const union drv_ps1_gpu_gp0)
+ {.size = {.w = p->w, .h = p->h}}.mask;
+}
+
+static int transfer(const size_t sz, const gfx_read r, void *const args)
+{
+ const size_t rem = sz % sizeof (uint32_t);
+
+ if (sz >= sizeof (uint32_t))
+ {
+ for (size_t i = 0; i < sz / sizeof (uint32_t); i++)
+ {
+ uint32_t pix;
+
+ if (r(&pix, sizeof pix, args))
+ return -1;
+
+ GP0->mask = pix;
+ }
+ }
+
+ if (rem)
+ {
+ uint32_t pix = 0;
+
+ if (r(&pix, rem, args))
+ return -1;
+
+ GP0->mask = pix;
+ }
+
+ return 0;
+}
+
+struct header
+{
+ uint32_t sz;
+ struct tim_pos pos;
+};
+
+static short get_clutid(const short x, const short y)
+{
+ return (x & 0x3ff) >> 4 | (y & 0x1ff) << 6;
+}
+
+static int upload_clut(struct gfx_sprite *const s, const gfx_read r,
+ void *const args)
+{
+ struct header clut;
+
+ if (r(&clut, sizeof clut, args))
+ return -1;
+
+ transfer_init(&clut.pos);
+
+ const size_t sz = clut.sz - sizeof clut;
+
+ if (transfer(sz, r, args))
+ return -1;
+
+ s->clutid = get_clutid(clut.pos.x, clut.pos.y);
+ return 0;
+}
+
+enum bpp
+{
+ BPP_4 = 0,
+ BPP_8 = 1,
+ BPP_16 = 2,
+ BPP_24 = 4
+};
+
+static int upload_img(struct gfx_sprite *const s, const enum bpp bpp,
+ const gfx_read r, void *const args)
+{
+ struct header img;
+
+ if (r(&img, sizeof img, args))
+ return -1;
+
+ transfer_init(&img.pos);
+
+ const size_t sz = img.sz - sizeof img;
+
+ if (transfer(sz, r, args))
+ return -1;
+
+ enum
+ {
+ VRAM_X = 1024,
+ VRAM_Y = 512,
+ TPAGE_WIDTH = 64
+ };
+
+ s->common.f.tpagex = img.pos.x / TPAGE_WIDTH;
+ s->common.f.tpagey = img.pos.y / (VRAM_Y / 2);
+ s->u = img.pos.x % TPAGE_WIDTH;
+ s->v = img.pos.y % (VRAM_Y / 2);
+
+ switch (bpp)
+ {
+ case BPP_4:
+ s->w = img.pos.w * 4;
+ s->u <<= 2;
+ break;
+
+ case BPP_8:
+ s->w = img.pos.w * 2;
+ s->u <<= 1;
+ break;
+
+ case BPP_16:
+ s->w = img.pos.w;
+ break;
+
+ case BPP_24:
+ s->w = img.pos.w + (img.pos.w / 2);
+ break;
+ }
+
+ s->h = img.pos.h;
+ return 0;
+}
+
+int gfx_sprite_load(struct gfx_sprite *s, const gfx_read r, void *const args)
+{
+ init(s);
+
+ struct
+ {
+ uint32_t version, bpp :3, has_clut :1, :28;
+ } h;
+
+ enum {VERSION_ID = 0x10};
+
+ if (r(&h, sizeof h, args)
+ || h.version != VERSION_ID
+ || h.bpp == BPP_24
+ || (h.has_clut && upload_clut(s, r, args))
+ || upload_img(s, h.bpp, r, args))
+ return -1;
+
+ s->common.f.bpp = h.bpp ? __builtin_ctz(h.bpp) + 1 : 0;
+ return 0;
+}
diff --git a/src/gfx/ps1/src/sprite/sort.c b/src/gfx/ps1/src/sprite/sort.c
new file mode 100644
index 0000000..76fc214
--- /dev/null
+++ b/src/gfx/ps1/src/sprite/sort.c
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+#include <gfx/port.h>
+
+int gfx_sprite_sort(struct gfx_sprite *const s)
+{
+ gfx_add_to_list(&s->sznext);
+ return 0;
+}
diff --git a/src/gfx/ps1/src/swapenvs.c b/src/gfx/ps1/src/swapenvs.c
new file mode 100644
index 0000000..9e120ad
--- /dev/null
+++ b/src/gfx/ps1/src/swapenvs.c
@@ -0,0 +1,58 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <drv/ps1/gpu.h>
+
+void gfx_swapenvs(void)
+{
+ static short dispenv, drawenv = 256;
+ const short y = dispenv;
+
+ dispenv = drawenv;
+ drawenv = y;
+
+ GP0->mask = (const union drv_ps1_gpu_gp0)
+ {
+ .draw_area_tl =
+ {
+ .cmd = GP0_DRAW_AREA_TOP_LEFT,
+ .y = drawenv
+ }
+ }.mask;
+
+ GP0->mask = (const union drv_ps1_gpu_gp0)
+ {
+ .draw_area_br =
+ {
+ .cmd = GP0_DRAW_AREA_BOTTOM_RIGHT,
+ .x = SCREEN_W - 1,
+ .y = drawenv + SCREEN_H - 1,
+ }
+ }.mask;
+
+ GP1->mask = (const union drv_ps1_gpu_gp1)
+ {
+ .disparea =
+ {
+ .cmd = GP1_START_DISPLAY_AREA,
+ .y = dispenv
+ }
+ }.mask;
+}
diff --git a/src/gfx/ps1/src/vblank.c b/src/gfx/ps1/src/vblank.c
new file mode 100644
index 0000000..cc445c7
--- /dev/null
+++ b/src/gfx/ps1/src/vblank.c
@@ -0,0 +1,21 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/private.h>
+
+int gfx_vblank_ev;
diff --git a/src/gfx/sdl-1.2/CMakeLists.txt b/src/gfx/sdl-1.2/CMakeLists.txt
new file mode 100644
index 0000000..11d2245
--- /dev/null
+++ b/src/gfx/sdl-1.2/CMakeLists.txt
@@ -0,0 +1,19 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_subdirectory(src)
+target_include_directories(gfx PUBLIC include PRIVATE private_include)
+target_link_libraries(gfx PUBLIC SDL::SDL PRIVATE SDL::SDL_gfx)
diff --git a/src/gfx/sdl-1.2/include/gfx/port.h b/src/gfx/sdl-1.2/include/gfx/port.h
new file mode 100644
index 0000000..bf94a38
--- /dev/null
+++ b/src/gfx/sdl-1.2/include/gfx/port.h
@@ -0,0 +1,58 @@
+#ifndef GFX_SDL_H
+#define GFX_SDL_H
+
+#include <SDL.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+struct gfx_sprite
+{
+ SDL_Surface *s, *s_x;
+ short x, y, w, h;
+ unsigned char u, v;
+ bool transparent;
+};
+
+struct quad
+{
+ unsigned char r, g, b;
+ short x0, x1, x2, x3;
+ short y0, y1, y2, y3;
+ unsigned char u0, u1, u2, u3;
+ unsigned char v0, v1, v2, v3;
+ short w, h;
+ bool transparent;
+ SDL_Surface *s, *s_x;
+};
+
+struct gfx_rect
+{
+ unsigned char r, g, b;
+ short x, y, w, h;
+ bool stp;
+};
+
+struct stp_4line
+{
+ short x, y;
+ unsigned char r, g, b;
+
+ struct stp_4line_vtx
+ {
+ unsigned char r, g, b;
+ short x, y;
+ } vertices[4];
+};
+
+#define common_get_or_ret(t, x, ret) \
+ struct t x##__, *const x = &x##__
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_SDL_H */
diff --git a/src/gfx/sdl-1.2/private_include/gfx/private.h b/src/gfx/sdl-1.2/private_include/gfx/private.h
new file mode 100644
index 0000000..e1af764
--- /dev/null
+++ b/src/gfx/sdl-1.2/private_include/gfx/private.h
@@ -0,0 +1,26 @@
+#ifndef GFX_SDL_12_PRIVATE_H
+#define GFX_SDL_12_PRIVATE_H
+
+#include <gfx/gfx.h>
+#include <SDL.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+enum
+{
+ SCREEN_W = 320,
+ SCREEN_H = 240
+};
+
+int sprite_screen_resize_ev(struct gfx_sprite *s);
+void gfx_register_sprite(struct gfx_sprite *s);
+SDL_Surface *gfx_screen(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_SDL_12_PRIVATE_H */
diff --git a/src/gfx/sdl-1.2/src/CMakeLists.txt b/src/gfx/sdl-1.2/src/CMakeLists.txt
new file mode 100644
index 0000000..4cef50b
--- /dev/null
+++ b/src/gfx/sdl-1.2/src/CMakeLists.txt
@@ -0,0 +1,23 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(gfx PRIVATE
+ env.c
+ line.c
+ quad.c
+ rect.c
+ sprite.c
+)
diff --git a/src/gfx/sdl-1.2/src/env.c b/src/gfx/sdl-1.2/src/env.c
new file mode 100644
index 0000000..2a51b97
--- /dev/null
+++ b/src/gfx/sdl-1.2/src/env.c
@@ -0,0 +1,204 @@
+#include <gfx/gfx.h>
+#include <gfx/private.h>
+#include <sdl-1.2/gfx/private.h>
+#include <SDL.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int screen_w = SCREEN_W, screen_h = SCREEN_H;
+static bool fullscreen;
+static SDL_Surface *screen;
+static struct gfx_sprite **list;
+static size_t list_len;
+
+void gfx_deinit(void)
+{
+ /* screen should be already freed by SDL_Quit. */
+ free(list);
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+}
+
+static struct
+{
+ int w, h;
+} display, windowed;
+
+void gfx_register_sprite(struct gfx_sprite *const s)
+{
+ list = realloc(list, (list_len + 1) * sizeof *list);
+
+ if (list)
+ list[list_len++] = s;
+}
+
+static int resize_screen(int w, int h, const bool full_screen)
+{
+ Uint32 flags = SDL_HWSURFACE | SDL_RESIZABLE | SDL_ANYFORMAT | SDL_DOUBLEBUF;
+
+ const SDL_VideoInfo *const info = SDL_GetVideoInfo();
+
+ if (!info)
+ {
+ fprintf(stderr, "SDL_GetVideoInfo: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ static bool init;
+
+ if (!init)
+ {
+ display.w = info->current_w;
+ display.h = info->current_h;
+ init = true;
+ }
+
+ if (fullscreen)
+ {
+ flags |= SDL_FULLSCREEN;
+ w = display.w;
+ h = display.h;
+ }
+ else
+ {
+ windowed.w = w;
+ windowed.h = h;
+ }
+
+ int bpp = info->vfmt->BitsPerPixel;
+
+ if (screen)
+ SDL_FreeSurface(screen);
+
+ const int max_bpp = SDL_VideoModeOK(w, h, 0, flags);
+
+ if (max_bpp < 0)
+ {
+ fprintf(stderr, "SDL_VideoModeOK: %s\n", SDL_GetError());
+ return -1;
+ }
+ else if (bpp > max_bpp)
+ bpp = max_bpp;
+
+ if (!(screen = SDL_SetVideoMode(w, h, 0, flags)))
+ {
+ fprintf(stderr, "SDL_SetVideoMode: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ for (size_t i = 0; i < list_len; i++)
+ if (sprite_screen_resize_ev(list[i]))
+ return -1;
+
+ screen_w = w;
+ screen_h = h;
+ fullscreen = full_screen;
+ return 0;
+}
+
+SDL_Surface *gfx_screen(void)
+{
+ return screen;
+}
+
+int gfx_display_size(short *const w, short *const h)
+{
+ *w = display.w;
+ *h = display.h;
+ return 0;
+}
+
+int gfx_init(void)
+{
+ if (SDL_InitSubSystem(SDL_INIT_VIDEO))
+ {
+ fprintf(stderr, "%s: SDL_InitSubSystem: %s\n",
+ __func__, SDL_GetError());
+ return -1;
+ }
+
+ return resize_screen(screen_w, screen_h, fullscreen);
+}
+
+bool gfx_inside_drawenv(const short x, const short y, const short w,
+ const short h)
+{
+ return (x + w >= 0)
+ && x < screen_w
+ && (y + h >= 0)
+ && y < screen_h;
+}
+
+static int get_resize_events(void)
+{
+ int n;
+ SDL_Event ev;
+
+ while ((n = SDL_PeepEvents(&ev, 1, SDL_GETEVENT,
+ SDL_VIDEORESIZEMASK)) > 0)
+ {
+ if (ev.type == SDL_VIDEORESIZE)
+ {
+ const SDL_ResizeEvent *const res = &ev.resize;
+
+ if (resize_screen(res->w, res->h, false))
+ return -1;
+ }
+ }
+
+ if (n < 0)
+ {
+ fprintf(stderr, "%s: SDL_PeepEvents: %s\n",
+ __func__, SDL_GetError());
+ return -1;
+ }
+
+ return 0;
+}
+
+int gfx_toggle_fullscreen(void)
+{
+ fullscreen ^= true;
+
+ const int w = fullscreen ? display.w : windowed.w;
+ const int h = fullscreen ? display.h : windowed.h;
+
+ return resize_screen(w, h, fullscreen);
+}
+
+int gfx_set_fullscreen(const short w, const short h)
+{
+ return resize_screen(display.w = w, display.h = h, fullscreen = true);
+}
+
+bool gfx_fullscreen_available(void)
+{
+ return true;
+}
+
+bool gfx_fullscreen(void)
+{
+ return fullscreen;
+}
+
+int gfx_draw(void)
+{
+ enum {FPS = 50, REFRESH_MS = 1000 / FPS};
+ static Uint32 prev;
+ const Uint32 cur = SDL_GetTicks();
+
+ if (cur - prev < REFRESH_MS)
+ SDL_Delay(REFRESH_MS - (cur - prev));
+
+ prev = SDL_GetTicks();
+
+ if (SDL_Flip(screen))
+ {
+ fprintf(stderr, "SDL_Flip: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ get_resize_events();
+ return 0;
+}
diff --git a/src/gfx/sdl-1.2/src/line.c b/src/gfx/sdl-1.2/src/line.c
new file mode 100644
index 0000000..b06a414
--- /dev/null
+++ b/src/gfx/sdl-1.2/src/line.c
@@ -0,0 +1,16 @@
+#include <gfx/gfx.h>
+#include <gfx/port.h>
+#include <sdl-1.2/gfx/private.h>
+#include <stddef.h>
+
+void stp_4line_init(struct stp_4line *const l)
+{
+}
+
+void semitrans_stp_4line_init(struct stp_4line *r)
+{
+}
+
+void stp_4line_sort(struct stp_4line *const r)
+{
+}
diff --git a/src/gfx/sdl-1.2/src/quad.c b/src/gfx/sdl-1.2/src/quad.c
new file mode 100644
index 0000000..1617a8b
--- /dev/null
+++ b/src/gfx/sdl-1.2/src/quad.c
@@ -0,0 +1,44 @@
+#include <gfx/gfx.h>
+#include <gfx/port.h>
+#include <sdl-1.2/gfx/private.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+int quad_from_sprite(const struct gfx_sprite *const s, struct quad *const q)
+{
+ q->s = s->s;
+ q->s_x = s->s_x;
+ q->u0 = q->u2 = s->u;
+ q->v0 = q->v1 = s->v;
+ q->u1 = q->u3 = s->u + s->w - 1;
+ q->v2 = q->v3 = s->v + s->h - 1;
+ q->w = s->w;
+ q->h = s->h;
+ return 0;
+}
+
+void quad_sort(struct quad *const q)
+{
+ const bool xflip = q->x0 > q->x1;
+
+ SDL_Rect r =
+ {
+ .x = xflip ? q->x1 : q->x0,
+ .y = q->y0
+ };
+
+ const short w = q->u1 - q->u0 + 1, h = q->v2 - q->v0 + 1;
+
+ SDL_Rect clip =
+ {
+ .x = xflip ? q->w - q->u0 - w: q->u0,
+ .y = q->v0,
+ .w = w,
+ .h = h
+ };
+
+ SDL_Surface *const s = xflip ? q->s_x : q->s;
+
+ if (SDL_BlitSurface(s, &clip, gfx_screen(), &r))
+ fprintf(stderr, "SDL_BlitSurface: %s\n", SDL_GetError());
+}
diff --git a/src/gfx/sdl-1.2/src/rect.c b/src/gfx/sdl-1.2/src/rect.c
new file mode 100644
index 0000000..57a2ab3
--- /dev/null
+++ b/src/gfx/sdl-1.2/src/rect.c
@@ -0,0 +1,35 @@
+#include <gfx/gfx.h>
+#include <gfx/port.h>
+#include <sdl-1.2/gfx/private.h>
+#include <SDL.h>
+
+void gfx_rect_sort(struct gfx_rect *const r)
+{
+ SDL_Rect rct =
+ {
+ .x = r->x,
+ .y = r->y,
+ .w = r->w,
+ .h = r->h
+ };
+
+ SDL_Surface *const screen = gfx_screen();
+ const Uint32 map = SDL_MapRGB(screen->format, r->r, r->g, r->b);
+
+ if (SDL_FillRect(screen, &rct, map))
+ {
+ fprintf(stderr, "SDL_FillRect: %s\n", SDL_GetError());
+ return;
+ }
+}
+
+void gfx_rect_init(struct gfx_rect *const r)
+{
+ *r = (const struct gfx_rect){0};
+}
+
+void semitrans_rect_init(struct gfx_rect *const r)
+{
+ gfx_rect_init(r);
+ r->stp = true;
+}
diff --git a/src/gfx/sdl-1.2/src/sprite.c b/src/gfx/sdl-1.2/src/sprite.c
new file mode 100644
index 0000000..086e2b5
--- /dev/null
+++ b/src/gfx/sdl-1.2/src/sprite.c
@@ -0,0 +1,143 @@
+#include <gfx/gfx.h>
+#include <gfx/port.h>
+#include <header.h>
+#include <sdl-1.2/gfx/private.h>
+#include <SDL.h>
+#include <SDL_rotozoom.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+void sprite_free(struct gfx_sprite *const s)
+{
+ if (s && s->s)
+ SDL_FreeSurface(s->s);
+}
+
+int sprite_clone(const struct gfx_sprite *const src, struct gfx_sprite *const dst)
+{
+ *dst = *src;
+ return 0;
+}
+
+static int set_transparent(SDL_Surface *const s)
+{
+ /* Magenta as transparent. */
+ const Uint32 map = SDL_MapRGB(s->format, 255, 0, 255);
+ const int ret = SDL_SetColorKey(s, SDL_SRCCOLORKEY | SDL_RLEACCEL, map);
+
+ if (ret)
+ fprintf(stderr, "SDL_SetColorKey: %s\n", SDL_GetError());
+
+ return ret;
+}
+
+int sprite_screen_resize_ev(struct gfx_sprite *const s)
+{
+ int ret = -1;
+ SDL_Surface *const old = s->s, *const old_x = s->s_x;
+
+ if (s->transparent && (set_transparent(old) || set_transparent(old_x)))
+ goto end;
+ else if (!(s->s = SDL_DisplayFormat(old)))
+ {
+ fprintf(stderr, "SDL_DisplayFormat: %s\n", SDL_GetError());
+ goto end;
+ }
+ else if (!(s->s_x = SDL_DisplayFormat(old_x)))
+ {
+ fprintf(stderr, "SDL_DisplayFormat: %s\n", SDL_GetError());
+ goto end;
+ }
+
+ ret = 0;
+
+end:
+ SDL_FreeSurface(old);
+ SDL_FreeSurface(old_x);
+ return ret;
+}
+
+static int load_header(struct gfx_sprite *const s, FILE *const f)
+{
+ if (header_load_bool(f, "transparent", &s->transparent))
+ return -1;
+
+ return 0;
+}
+
+static int load_bitmap(struct gfx_sprite *const s, FILE *const f)
+{
+ int ret = -1;
+ SDL_RWops *ops = NULL;
+ SDL_Surface *ts = NULL, *zs = NULL;
+
+ if (!(ops = SDL_RWFromFP(f, 0)))
+ {
+ fprintf(stderr, "SDL_RWFromFP: %s\n", SDL_GetError());
+ goto end;
+ }
+ else if (!(ts = SDL_LoadBMP_RW(ops, 0)))
+ {
+ fprintf(stderr, "SDL_LoadBMP_RW: %s\n", SDL_GetError());
+ goto end;
+ }
+ else if (!(zs = zoomSurface(ts, -1, 1, 0)))
+ {
+ fprintf(stderr, "zoomSurface: %s\n", SDL_GetError());
+ goto end;
+ }
+ else if (s->transparent && (set_transparent(ts) || set_transparent(zs)))
+ goto end;
+ else if (!(s->s = SDL_DisplayFormat(ts)))
+ {
+ fprintf(stderr, "SDL_DisplayFormat: %s\n", SDL_GetError());
+ goto end;
+ }
+ else if (!(s->s_x = SDL_DisplayFormat(zs)))
+ {
+ fprintf(stderr, "SDL_DisplayFormat: %s\n", SDL_GetError());
+ goto end;
+ }
+
+ gfx_register_sprite(s);
+ s->w = ts->w;
+ s->h = ts->h;
+ ret = 0;
+
+end:
+ SDL_FreeRW(ops);
+ SDL_FreeSurface(ts);
+ SDL_FreeSurface(zs);
+ return ret;
+}
+
+int sprite_from_fp(struct gfx_sprite *const s, FILE *const f)
+{
+ *s = (const struct gfx_sprite){0};
+
+ if (load_header(s, f) || load_bitmap(s, f))
+ return -1;
+
+ return 0;
+}
+
+void sprite_sort(struct gfx_sprite *const s)
+{
+ SDL_Rect r =
+ {
+ .x = s->x,
+ .y = s->y
+ };
+
+ SDL_Rect clip =
+ {
+ .x = s->u,
+ .y = s->v,
+ .w = s->w,
+ .h = s->h
+ };
+
+ if (SDL_BlitSurface(s->s, &clip, gfx_screen(), &r))
+ fprintf(stderr, "SDL_BlitSurface: %s\n", SDL_GetError());
+}
diff --git a/src/gfx/src/CMakeLists.txt b/src/gfx/src/CMakeLists.txt
new file mode 100644
index 0000000..3b3cac2
--- /dev/null
+++ b/src/gfx/src/CMakeLists.txt
@@ -0,0 +1,19 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(gfx PRIVATE
+ dim.c
+)
diff --git a/src/gfx/src/dim.c b/src/gfx/src/dim.c
new file mode 100644
index 0000000..674da9c
--- /dev/null
+++ b/src/gfx/src/dim.c
@@ -0,0 +1,21 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <gfx/private.h>
+
+int screen_w = SCREEN_W, screen_h = SCREEN_H;
diff --git a/src/init/CMakeLists.txt b/src/init/CMakeLists.txt
new file mode 100644
index 0000000..5cac77d
--- /dev/null
+++ b/src/init/CMakeLists.txt
@@ -0,0 +1,34 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(init)
+add_subdirectory(src)
+target_include_directories(init PUBLIC include PRIVATE private_include)
+target_link_libraries(init PRIVATE
+ aio
+ devfs
+ drv
+ io
+ kprintf
+ loop
+ rootfs
+ iso9660
+)
+
+if(PS1_BUILD)
+ add_subdirectory(ps1)
+ target_link_libraries(init PRIVATE init_ps1)
+endif()
diff --git a/src/init/include/init.h b/src/init/include/init.h
new file mode 100644
index 0000000..510245d
--- /dev/null
+++ b/src/init/include/init.h
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef INIT_H
+#define INIT_H
+
+int init_time(void);
+int init_boot(void);
+int init_vfs(void);
+int init_run(void);
+
+#endif
diff --git a/src/init/private_include/init/port.h b/src/init/private_include/init/port.h
new file mode 100644
index 0000000..f36ae5d
--- /dev/null
+++ b/src/init/private_include/init/port.h
@@ -0,0 +1,25 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef INIT_PORT_H
+#define INIT_PORT_H
+
+int init_port_boot(void);
+int init_port_run(void);
+
+#endif
diff --git a/src/init/private_include/init/types.h b/src/init/private_include/init/types.h
new file mode 100644
index 0000000..f875caf
--- /dev/null
+++ b/src/init/private_include/init/types.h
@@ -0,0 +1,37 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef INIT_TYPES_H
+#define INIT_TYPES_H
+
+#include <aio.h>
+#include <sys/stat.h>
+#include <time.h>
+
+struct init
+{
+ struct aio *aio;
+ struct stat sb;
+ unsigned retries;
+ struct timespec last_retry;
+ int (*next)(struct init *);
+};
+
+extern struct init init_vars;
+
+#endif
diff --git a/src/init/ps1/CMakeLists.txt b/src/init/ps1/CMakeLists.txt
new file mode 100644
index 0000000..2cdc2de
--- /dev/null
+++ b/src/init/ps1/CMakeLists.txt
@@ -0,0 +1,33 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(init_ps1)
+add_subdirectory(src)
+target_include_directories(init_ps1 PRIVATE private_include)
+target_link_libraries(init_ps1
+ PUBLIC
+ c
+ init
+ PRIVATE
+ aio
+ drv_ps1_bios
+ drv_ps1_rcnt
+ drv_ps1_time
+ iso9660
+ kprintf
+ loop
+ state
+)
diff --git a/src/init/ps1/private_include/init/ps1/types.h b/src/init/ps1/private_include/init/ps1/types.h
new file mode 100644
index 0000000..118f37b
--- /dev/null
+++ b/src/init/ps1/private_include/init/ps1/types.h
@@ -0,0 +1,37 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef INIT_PS1_TYPES_H
+#define INIT_PS1_TYPES_H
+
+#include <aio.h>
+#include <sys/stat.h>
+#include <time.h>
+
+struct init_ps1
+{
+ struct aio *aio;
+ struct stat *sb;
+ unsigned retries;
+ struct timespec last_retry;
+ int (*next)(struct init_ps1 *);
+};
+
+extern struct init_ps1 init_ps1;
+
+#endif
diff --git a/src/init/ps1/src/CMakeLists.txt b/src/init/ps1/src/CMakeLists.txt
new file mode 100644
index 0000000..5a4af14
--- /dev/null
+++ b/src/init/ps1/src/CMakeLists.txt
@@ -0,0 +1,22 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(init_ps1 PRIVATE
+ boot.c
+ globalvars.c
+ run.c
+ time.c
+)
diff --git a/src/init/ps1/src/boot.c b/src/init/ps1/src/boot.c
new file mode 100644
index 0000000..9b42d47
--- /dev/null
+++ b/src/init/ps1/src/boot.c
@@ -0,0 +1,188 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init.h>
+#include <init/ps1/types.h>
+#include <aio.h>
+#include <iso9660.h>
+#include <kprintf.h>
+#include <loop.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <state.h>
+#include <time.h>
+
+struct mount
+{
+ struct aio *aio;
+};
+
+enum {RETRIES = 5};
+
+static int retry(struct init_ps1 *);
+
+static int mount_done(const enum state state, void *const args)
+{
+ struct mount *const m = args;
+
+ loop_rm_aio(m->aio);
+ aio_free(m->aio);
+ free(m);
+
+ if (state)
+ kprintf("Failed to mount ISO9660 filesystem\n");
+ else
+ kprintf("ISO996 filesystem mounted successfully\n");
+
+ return 0;
+}
+
+static int mount_cd(struct init_ps1 *const p)
+{
+ struct aio *aio = NULL;
+ struct mount *const m = malloc(sizeof *m);
+
+ if (!m)
+ goto failure;
+
+ const struct aio_mount fm =
+ {
+ .mount =
+ {
+ .src = "/dev/cd0",
+ .tgt = "/mnt/cdrom",
+ .mode = 0755
+ },
+
+ .type = "iso9660"
+ };
+
+ const struct aio_done d =
+ {
+ .args = m,
+ .f = mount_done
+ };
+
+ if (!(aio = aio_mount(&fm, &d)) || loop_add_aio(aio))
+ goto failure;
+
+ *m = (const struct mount){.aio = aio};
+ p->next = NULL;
+ kprintf("Mounting ISO996 filesystem from %s to %s\n",
+ fm.mount.src, fm.mount.tgt);
+ return 0;
+
+failure:
+ aio_free(aio);
+ free(m);
+ kprintf("Failed to mount ISO996 filesystem from %s to %s\n",
+ fm.mount.src, fm.mount.tgt);
+ return -1;
+}
+
+static int wait_retry(struct init_ps1 *const p)
+{
+ struct timespec ts;
+ const time_t last = p->last_retry.tv_sec, timeout = 5;
+
+ if (clock_gettime(CLOCK_REALTIME, &ts))
+ return -1;
+ else if (ts.tv_sec - last >= timeout)
+ p->next = retry;
+
+ return 0;
+}
+
+static int stat_done(const enum state s, void *const args)
+{
+ int ret = 0;
+ struct init_ps1 *const p = args;
+
+ if (s)
+ {
+ struct timespec ts;
+
+ if (!--p->retries || clock_gettime(CLOCK_REALTIME, &ts))
+ {
+ ret = -1;
+ goto end;
+ }
+
+ p->last_retry = ts;
+ p->next = wait_retry;
+ }
+ else
+ {
+ p->next = mount_cd;
+ kprintf("Successfully initialized CD-ROM (took %u attempts)\n",
+ RETRIES - p->retries + 1);
+ }
+
+end:
+ loop_rm_aio(p->aio);
+ aio_free(p->aio);
+ free(p->sb);
+ return ret;
+}
+
+static int retry(struct init_ps1 *const p)
+{
+ struct aio *aio = NULL;
+ struct stat *const sb = malloc(sizeof *sb);
+
+ if (!sb)
+ goto failure;
+
+ const struct fs_stat s = {.path = "/dev/cd0", .sb = sb};
+ const struct aio_done d = {.f = stat_done, .args = p};
+ const unsigned retries = p->retries;
+
+ if (!(aio = aio_stat(&s, &d)) || loop_add_aio(aio))
+ goto failure;
+
+ *p = (const struct init_ps1)
+ {
+ .aio = aio,
+ .sb = sb,
+ .retries = retries,
+ .last_retry = {.tv_sec = (time_t)-1}
+ };
+
+ kprintf("Initializing CD-ROM to %s (attempt %u)\n", s.path,
+ RETRIES - p->retries + 1);
+ return 0;
+
+failure:
+ free(aio);
+ free(sb);
+ return -1;
+}
+
+int init_port_boot(void)
+{
+ if (iso9660_register())
+ return -1;
+
+ init_ps1 = (const struct init_ps1)
+ {
+ .retries = RETRIES,
+ .next = retry
+ };
+
+ return 0;
+}
diff --git a/src/init/ps1/src/globalvars.c b/src/init/ps1/src/globalvars.c
new file mode 100644
index 0000000..6d4d2aa
--- /dev/null
+++ b/src/init/ps1/src/globalvars.c
@@ -0,0 +1,21 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init/ps1/types.h>
+
+struct init_ps1 init_ps1;
diff --git a/src/init/ps1/src/run.c b/src/init/ps1/src/run.c
new file mode 100644
index 0000000..a0d022f
--- /dev/null
+++ b/src/init/ps1/src/run.c
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init.h>
+#include <init/ps1/types.h>
+
+int init_port_run(void)
+{
+ struct init_ps1 *const p = &init_ps1;
+
+ return p->next ? p->next(p) : 0;
+}
diff --git a/src/init/ps1/src/time.c b/src/init/ps1/src/time.c
new file mode 100644
index 0000000..72183c0
--- /dev/null
+++ b/src/init/ps1/src/time.c
@@ -0,0 +1,47 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init.h>
+#include <init/ps1/types.h>
+#include <drv/ps1/bios.h>
+#include <drv/ps1/rcnt.h>
+#include <drv/ps1/time.h>
+#include <time.h>
+
+int init_time(void)
+{
+ struct timespec ts;
+ const union drv_ps1_rcnt_cfg cfg =
+ {
+ .bits =
+ {
+ .reset = 1,
+ .repeat = 1,
+ .irq_tgt = 1,
+ .clocksrc = 3
+ }
+ };
+
+ if (clock_getres(CLOCK_REALTIME, &ts))
+ return -1;
+
+ const unsigned fcpu = 33000000;
+ const uint16_t target = (fcpu / 8) / (ts.tv_nsec / 1000);
+
+ return drv_ps1_rcnt_init(DRV_PS1_RCNT2, target, &cfg, drv_ps1_time_tick);
+}
diff --git a/src/init/src/CMakeLists.txt b/src/init/src/CMakeLists.txt
new file mode 100644
index 0000000..fd1c1e7
--- /dev/null
+++ b/src/init/src/CMakeLists.txt
@@ -0,0 +1,22 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(init PRIVATE
+ boot.c
+ run.c
+ vars.c
+ vfs.c
+)
diff --git a/src/init/src/boot.c b/src/init/src/boot.c
new file mode 100644
index 0000000..98352c2
--- /dev/null
+++ b/src/init/src/boot.c
@@ -0,0 +1,121 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init.h>
+#include <init/port.h>
+#include <init/types.h>
+#include <aio.h>
+#include <kprintf.h>
+#include <loop.h>
+#include <stdlib.h>
+#include <time.h>
+
+static int retry(struct init *);
+enum {RETRIES = 5};
+
+static int run(struct init *const init)
+{
+ return init_port_run();
+}
+
+static int init_port(struct init *const init)
+{
+ kprintf("tty initilization successful (took %u attempts)\n",
+ RETRIES - init->retries + 1);
+
+ if (init_port_boot())
+ return -1;
+
+ init->next = run;
+ return 0;
+}
+
+static int wait_retry(struct init *const init)
+{
+ struct timespec ts;
+ const time_t last = init->last_retry.tv_sec, timeout = 5;
+
+ if (clock_gettime(CLOCK_REALTIME, &ts))
+ return -1;
+ else if (ts.tv_sec - last >= timeout)
+ init->next = retry;
+
+ return 0;
+}
+
+static int stat_done(const enum state s, void *const args)
+{
+ int ret = 0;
+ struct init *const init = args;
+
+ if (s)
+ {
+ struct timespec ts;
+
+ if (!--init->retries || clock_gettime(CLOCK_REALTIME, &ts))
+ {
+ ret = -1;
+ goto end;
+ }
+
+ init->last_retry = ts;
+ init->next = wait_retry;
+ }
+ else
+ init->next = init_port;
+
+end:
+ loop_rm_aio(init->aio);
+ aio_free(init->aio);
+ return ret;
+}
+
+static int retry(struct init *const init)
+{
+ struct aio *aio = NULL;
+ const struct fs_stat s = {.path = "/dev/tty", .sb = &init->sb};
+ const struct aio_done d = {.f = stat_done, .args = init};
+ const unsigned retries = init->retries;
+
+ if (!(aio = aio_stat(&s, &d)) || loop_add_aio(aio))
+ goto failure;
+
+ *init = (const struct init)
+ {
+ .aio = aio,
+ .retries = retries,
+ .last_retry = {.tv_sec = (time_t)-1}
+ };
+
+ return 0;
+
+failure:
+ free(aio);
+ return -1;
+}
+
+int init_boot(void)
+{
+ init_vars = (const struct init)
+ {
+ .retries = RETRIES,
+ .next = retry
+ };
+
+ return 0;
+}
diff --git a/src/init/src/run.c b/src/init/src/run.c
new file mode 100644
index 0000000..835efd3
--- /dev/null
+++ b/src/init/src/run.c
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init.h>
+#include <init/types.h>
+
+int init_run(void)
+{
+ struct init *const p = &init_vars;
+
+ return p->next ? p->next(p) : 0;
+}
diff --git a/src/init/src/vars.c b/src/init/src/vars.c
new file mode 100644
index 0000000..ca5ff01
--- /dev/null
+++ b/src/init/src/vars.c
@@ -0,0 +1,21 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init/types.h>
+
+struct init init_vars;
diff --git a/src/init/src/vfs.c b/src/init/src/vfs.c
new file mode 100644
index 0000000..cf7dd3d
--- /dev/null
+++ b/src/init/src/vfs.c
@@ -0,0 +1,86 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <init.h>
+#include <aio.h>
+#include <drv/drv.h>
+#include <io.h>
+#include <devfs.h>
+#include <rootfs.h>
+#include <iso9660.h>
+#include <sys/stat.h>
+#include <stddef.h>
+
+int init_vfs(void)
+{
+ const struct aio_mount m[] =
+ {
+ {
+ .mount =
+ {
+ .tgt = "/",
+ .mode = 0755
+ },
+
+ .type = "rootfs"
+ },
+
+ {
+ .mount =
+ {
+ .tgt = "/dev",
+ .mode = 0755
+ },
+
+ .type = "devfs"
+ }
+ };
+
+ const struct fs_mkdir mk[] =
+ {
+ {
+ .path = "/dev",
+ .mode = 0755
+ },
+
+ {
+ .path = "/mnt",
+ .mode = 0755
+ },
+
+ {
+ .path = "/mnt/cdrom",
+ .mode = 0755
+ }
+ };
+
+ if (rootfs_register()
+ || devfs_register()
+ || io_mount(m))
+ return -1;
+
+ for (size_t i = 0; i < sizeof mk / sizeof *mk; i++)
+ if (io_mkdir(&mk[i]))
+ return -1;
+
+ for (size_t i = 1; i < sizeof m / sizeof *m; i++)
+ if (io_mount(&m[i]))
+ return -1;
+
+ return 0;
+}
diff --git a/src/io/CMakeLists.txt b/src/io/CMakeLists.txt
new file mode 100644
index 0000000..62a5e13
--- /dev/null
+++ b/src/io/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(io)
+add_subdirectory(src)
+target_include_directories(io PUBLIC include)
+target_link_libraries(io PUBLIC aio)
diff --git a/src/io/include/io.h b/src/io/include/io.h
new file mode 100644
index 0000000..498ae03
--- /dev/null
+++ b/src/io/include/io.h
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef IO_H
+#define IO_H
+
+#include <aio.h>
+#include <sys/types.h>
+
+int io_mkdir(const struct fs_mkdir *m);
+int io_mount(const struct aio_mount *m);
+
+#endif
diff --git a/src/io/src/CMakeLists.txt b/src/io/src/CMakeLists.txt
new file mode 100644
index 0000000..63fd031
--- /dev/null
+++ b/src/io/src/CMakeLists.txt
@@ -0,0 +1,5 @@
+target_sources(io PRIVATE
+ mkdir.c
+ mount.c
+ write.c
+)
diff --git a/src/io/src/mkdir.c b/src/io/src/mkdir.c
new file mode 100644
index 0000000..4f97031
--- /dev/null
+++ b/src/io/src/mkdir.c
@@ -0,0 +1,40 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <io.h>
+#include <aio.h>
+#include <fs/fs.h>
+#include <errno.h>
+
+int io_mkdir(const struct fs_mkdir *const m)
+{
+ int ret = 0;
+ struct aio *const aio = aio_mkdir(m, NULL);
+ struct aio_poll p = {.aio = aio};
+
+ if (!aio || aio_poll(&p, -1) < 0 || p.error)
+ {
+ ret = -1;
+
+ if (p.error)
+ errno = p.error;
+ }
+
+ aio_free(aio);
+ return ret;
+}
diff --git a/src/io/src/mount.c b/src/io/src/mount.c
new file mode 100644
index 0000000..b885ac7
--- /dev/null
+++ b/src/io/src/mount.c
@@ -0,0 +1,35 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <io.h>
+#include <aio.h>
+#include <fs/fs.h>
+#include <stddef.h>
+
+int io_mount(const struct aio_mount *const m)
+{
+ int ret = 0;
+ struct aio *const aio = aio_mount(m, NULL);
+ struct aio_poll p = {.aio = aio};
+
+ if (!aio || aio_poll(&p, -1) < 0 || p.error)
+ ret = -1;
+
+ aio_free(aio);
+ return ret;
+}
diff --git a/src/io/src/write.c b/src/io/src/write.c
new file mode 100644
index 0000000..82bafe0
--- /dev/null
+++ b/src/io/src/write.c
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <io.h>
+#include <aio.h>
+#include <fs/fs.h>
+#include <stddef.h>
+
+int io_write(const char *const path, const void *const buf, const size_t n)
+{
+ return -1;
+}
diff --git a/src/kprintf/CMakeLists.txt b/src/kprintf/CMakeLists.txt
new file mode 100644
index 0000000..b847938
--- /dev/null
+++ b/src/kprintf/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(kprintf ${src})
+add_subdirectory(src)
+target_include_directories(kprintf PUBLIC include PRIVATE private_include)
+target_link_libraries(kprintf PUBLIC c PRIVATE aio)
diff --git a/src/kprintf/include/kprintf.h b/src/kprintf/include/kprintf.h
new file mode 100644
index 0000000..606adc1
--- /dev/null
+++ b/src/kprintf/include/kprintf.h
@@ -0,0 +1,24 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef KPRINTF_H
+#define KPRINTF_H
+
+int kprintf(const char *fmt, ...);
+
+#endif
diff --git a/src/kprintf/src/CMakeLists.txt b/src/kprintf/src/CMakeLists.txt
new file mode 100644
index 0000000..abd972e
--- /dev/null
+++ b/src/kprintf/src/CMakeLists.txt
@@ -0,0 +1,17 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(kprintf PRIVATE kprintf.c)
diff --git a/src/kprintf/src/kprintf.c b/src/kprintf/src/kprintf.c
new file mode 100644
index 0000000..d5504fe
--- /dev/null
+++ b/src/kprintf/src/kprintf.c
@@ -0,0 +1,96 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <kprintf.h>
+#include <aio.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+static void writechar(const char c, void *const args)
+{
+ static char buf[128];
+ static size_t bufi;
+ struct fs_fd *fd = args;
+ struct aio *aio = NULL;
+
+ buf[bufi++] = c;
+
+ if (c == '\n' || bufi >= sizeof buf - 1)
+ {
+ const struct fs_write w =
+ {
+ .buf = buf,
+ .fd = fd,
+ .n = bufi
+ };
+
+ if (!(aio = aio_write(&w, NULL)))
+ goto end;
+
+ struct aio_poll p = (const struct aio_poll){.aio = aio};
+
+ aio_poll(&p, -1);
+ bufi = 0;
+ }
+
+end:
+ aio_free(aio);
+}
+
+int kprintf(const char *const fmt, ...)
+{
+ va_list ap;
+ struct fs_fd fd;
+ struct timespec ts;
+ const struct fs_open o =
+ {
+ .fd = &fd,
+ .path = "/dev/tty",
+ .mode = O_WRONLY
+ };
+
+ struct aio *aio_op = NULL;
+
+ va_start(ap, fmt);
+
+ if (clock_gettime(CLOCK_REALTIME, &ts))
+ goto failure;
+
+ if (!(aio_op = aio_open(&o, NULL)))
+ goto failure;
+
+ struct aio_poll p = {.aio = aio_op};
+
+ if (aio_poll(&p, -1) < 0
+ || p.error
+ || fctprintf(writechar, &fd, "[%lld.%03ld] ", ts.tv_sec,
+ ts.tv_nsec / 1000000) < 0
+ || fctvprintf(writechar, &fd, fmt, ap) < 0)
+ goto failure;
+
+ va_end(ap);
+ return 0;
+
+failure:
+ aio_free(aio_op);
+ va_end(ap);
+ return -1;
+}
diff --git a/src/libc/CMakeLists.txt b/src/libc/CMakeLists.txt
index 952df35..e0663cf 100644
--- a/src/libc/CMakeLists.txt
+++ b/src/libc/CMakeLists.txt
@@ -1,4 +1,4 @@
-# wanix, a Unix-like operating system for WebAssembly
+# wanix, a Unix-like operating system for WebAssembly applications.
# Copyright (C) 2025 Xavier Del Campo Romero
#
# This program is free software: you can redistribute it and/or modify
@@ -15,16 +15,15 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
set(src
- "src/errno.c"
- "src/free.c"
- "src/malloc.c"
- "src/memcmp.c"
- "src/memcpy.c"
- "src/memset.c"
- "src/strchr.c"
- "src/streams.c"
- "src/strerror.c"
- "src/strlen.c"
+ printf/printf.c
+ tinyalloc/tinyalloc.c
)
add_library(c ${src})
-target_include_directories(c PUBLIC "include" PRIVATE "private_include")
+add_subdirectory(src)
+target_include_directories(c PUBLIC include printf
+ PRIVATE private_include tinyalloc)
+target_link_libraries(c PRIVATE aio fs drv)
+
+if(PS1_BUILD)
+ add_subdirectory(src/ps1)
+endif()
diff --git a/src/libc/include/errno.h b/src/libc/include/errno.h
index 0456645..60037ef 100644
--- a/src/libc/include/errno.h
+++ b/src/libc/include/errno.h
@@ -1,3 +1,21 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
#ifndef _ERRNO_H
#define _ERRNO_H
@@ -5,7 +23,7 @@ extern int errno;
enum
{
- OK,
+ SUCCESS,
EPERM,
ENOENT,
ESRCH,
@@ -38,6 +56,105 @@ enum
EROFS,
EMLINK,
EPIPE,
+ EDOM,
+ ERANGE,
+ EDEADLK,
+ ENAMETOOLONG,
+ ENOLCK,
+ ENOSYS,
+ ENOTEMPTY,
+ ELOOP,
+ ENOMSG,
+ EIDRM,
+ ECHRNG,
+ EL2NSYNC,
+ EL3HLT,
+ EL3RST,
+ ELNRNG,
+ EUNATCH,
+ ENOCSI,
+ EL2HLT,
+ EBADE,
+ EBADR,
+ EXFULL,
+ ENOANO,
+ EBADRQC,
+ EBADSLT,
+ EBFONT,
+ ENOSTR,
+ ENODATA,
+ ETIME,
+ ENOSR,
+ ENONET,
+ ENOPKG,
+ EREMOTE,
+ ENOLINK,
+ EADV,
+ ESRMNT,
+ ECOMM,
+ EPROTO,
+ EMULTIHOP,
+ EDOTDOT,
+ EBADMSG,
+ EOVERFLOW,
+ ENOTUNIQ,
+ EBADFD,
+ EREMCHG,
+ ELIBACC,
+ ELIBBAD,
+ ELIBSCN,
+ ELIBMAX,
+ ELIBEXEC,
+ EILSEQ,
+ ERESTART,
+ ESTRPIPE,
+ EUSERS,
+ ENOTSOCK,
+ EDESTADDRREQ,
+ EMSGSIZE,
+ EPROTOTYPE,
+ ENOPROTOOPT,
+ EPROTONOSUPPORT,
+ ESOCKTNOSUPPORT,
+ ENOTSUP,
+ EPFNOSUPPORT,
+ EAFNOSUPPORT,
+ EADDRINUSE,
+ EADDRNOTAVAIL,
+ ENETDOWN,
+ ENETUNREACH,
+ ENETRESET,
+ ECONNABORTED,
+ ECONNRESET,
+ ENOBUFS,
+ EISCONN,
+ ENOTCONN,
+ ESHUTDOWN,
+ ETOOMANYREFS,
+ ETIMEDOUT,
+ ECONNREFUSED,
+ EHOSTDOWN,
+ EHOSTUNREACH,
+ EALREADY,
+ EINPROGRESS,
+ ESTALE,
+ EUCLEAN,
+ ENOTNAM,
+ ENAVAIL,
+ EISNAM,
+ EREMOTEIO,
+ EDQUOT,
+ ENOMEDIUM,
+ EMEDIUMTYPE,
+ ECANCELED,
+ ENOKEY,
+ EKEYEXPIRED,
+ EKEYREVOKED,
+ EKEYREJECTED,
+ EOWNERDEAD,
+ ENOTRECOVERABLE,
+ ERFKILL,
+ EHWPOISON
};
#endif
diff --git a/src/libc/include/fcntl.h b/src/libc/include/fcntl.h
new file mode 100644
index 0000000..9713a9f
--- /dev/null
+++ b/src/libc/include/fcntl.h
@@ -0,0 +1,29 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef _FCNTL_H
+#define _FCNTL_H
+
+enum
+{
+ O_RDONLY = 1,
+ O_WRONLY = 1 << 1,
+ O_RDWR = O_RDONLY | O_WRONLY
+};
+
+#endif
diff --git a/src/libc/include/inttypes.h b/src/libc/include/inttypes.h
new file mode 100644
index 0000000..f07e94b
--- /dev/null
+++ b/src/libc/include/inttypes.h
@@ -0,0 +1,34 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+#ifndef _INTTYPES_H
+#define _INTTYPES_H
+
+#define PRIu8 "hhu"
+#define PRIu16 "hu"
+#define PRIu32 "lu"
+#define PRIu64 "llu"
+#define PRIi8 "hhd"
+#define PRIi16 "hd"
+#define PRIi32 "ld"
+#define PRIi64 "lld"
+#define PRIx8 "hhx"
+#define PRIx16 "hx"
+#define PRIx32 "lx"
+#define PRIx64 "llx"
+
+#endif
diff --git a/src/libc/include/stdint.h b/src/libc/include/stdint.h
new file mode 100644
index 0000000..d2701b1
--- /dev/null
+++ b/src/libc/include/stdint.h
@@ -0,0 +1,33 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef _STDINT_H
+#define _STDINT_H
+
+typedef unsigned char uint8_t, uint_least8_t;
+typedef signed char int8_t, int_least8_t;
+typedef unsigned short uint16_t, uint_least16_t;
+typedef short int16_t, int_least16_t;
+typedef unsigned uintptr_t, uint32_t, uint_least32_t, uint_fast8_t,
+ uint_fast16_t, uint_fast32_t;
+typedef int intptr_t, int32_t, int_least32_t, int_fast8_t, int_fast16_t,
+ int_fast32_t;
+typedef unsigned long long uint64_t, uint_least64_t, uint_fast64_t, uintmax_t;
+typedef long long int64_t, int_least64_t, int_fast64_t, intmax_t;
+
+#endif
diff --git a/src/libc/include/stdio.h b/src/libc/include/stdio.h
index 1d0e27c..7c6504a 100644
--- a/src/libc/include/stdio.h
+++ b/src/libc/include/stdio.h
@@ -1,5 +1,5 @@
/*
- * wanix, a Unix-like operating system for WebAssembly
+ * wanix, a Unix-like operating system for WebAssembly applications.
* Copyright (C) 2025 Xavier Del Campo Romero
*
* This program is free software: you can redistribute it and/or modify
@@ -19,17 +19,14 @@
#ifndef _STDIO_H
#define _STDIO_H
-enum
-{
- EOF = -1
-};
-
+enum {EOF = -1};
typedef struct __file FILE;
-FILE *fopen(const char *__path, const char *__mode);
-int printf(const char *__fmt, ...);
-int fprintf(FILE *__stream, const char *__fmt, ...);
+int puts(const char *__s);
+int putchar(int __c);
extern FILE *stdin, *stdout, *stderr;
+#include <printf.h>
+
#endif
diff --git a/src/libc/include/stdlib.h b/src/libc/include/stdlib.h
index 4065f1c..0d2fee7 100644
--- a/src/libc/include/stdlib.h
+++ b/src/libc/include/stdlib.h
@@ -1,5 +1,5 @@
/*
- * wanix, a Unix-like operating system for WebAssembly
+ * wanix, a Unix-like operating system for WebAssembly applications.
* Copyright (C) 2025 Xavier Del Campo Romero
*
* This program is free software: you can redistribute it and/or modify
@@ -24,8 +24,12 @@
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
+#define abort() __abort(__FILE__, __LINE__)
+
void *malloc(size_t __n);
void *calloc(size_t __nemb, size_t __size);
+void *realloc(void *__ptr, size_t __size);
void free(void *__p);
+void __abort(const char *__file, int __lineno);
#endif
diff --git a/src/libc/include/string.h b/src/libc/include/string.h
index 20c9cf3..0a7b7f2 100644
--- a/src/libc/include/string.h
+++ b/src/libc/include/string.h
@@ -1,3 +1,21 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
#ifndef _STRING_H
#define _STRING_H
@@ -7,7 +25,12 @@ int memcmp(const void *__s1, const void *__s2, size_t __n);
void *memcpy(void *__dst, const void *__src, size_t __n);
void *memset(void *__dst, int __c, size_t __n);
char *strchr(const char *__s, int __n);
+int strcmp(const char *__a, const char *__b);
+char *strdup(const char *__s);
+int strncmp(const char *__a, const char *__b, size_t __n);
+char *strndup(const char *__s, size_t __n);
char *strerror(int errnum);
size_t strlen(const char *__s);
+char *strrchr(const char *__s, int __c);
#endif
diff --git a/src/libc/include/sys/stat.h b/src/libc/include/sys/stat.h
new file mode 100644
index 0000000..0a5dd23
--- /dev/null
+++ b/src/libc/include/sys/stat.h
@@ -0,0 +1,40 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SYS_STAT_H
+#define _SYS_STAT_H
+
+#include <sys/types.h>
+#include <time.h>
+
+struct stat
+{
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ off_t st_size;
+ struct timespec st_atim, st_mtim, st_ctim;
+ blksize_t st_blksize;
+ blkcnt_t st_blocks;
+};
+
+#endif
diff --git a/src/libc/include/sys/types.h b/src/libc/include/sys/types.h
new file mode 100644
index 0000000..3175740
--- /dev/null
+++ b/src/libc/include/sys/types.h
@@ -0,0 +1,25 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SYS_TYPES_H
+#define _SYS_TYPES_H
+
+typedef unsigned dev_t, mode_t, nlink_t, uid_t, gid_t, blksize_t, blkcnt_t;
+typedef unsigned long ino_t, off_t;
+
+#endif
diff --git a/src/libc/include/time.h b/src/libc/include/time.h
new file mode 100644
index 0000000..99a8e6c
--- /dev/null
+++ b/src/libc/include/time.h
@@ -0,0 +1,39 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TIME_H
+#define _TIME_H
+
+typedef enum
+{
+ CLOCK_REALTIME
+} clockid_t;
+
+typedef long long time_t;
+
+struct timespec
+{
+ time_t tv_sec;
+ long tv_nsec;
+};
+
+int clock_getres(clockid_t __id, struct timespec *__ts);
+int clock_gettime(clockid_t __id, struct timespec *__ts);
+int clock_settime(clockid_t __id, const struct timespec *__ts);
+
+#endif
diff --git a/src/libc/private_include/libc/file.h b/src/libc/private_include/libc/file.h
index 3ba554c..2a55ced 100644
--- a/src/libc/private_include/libc/file.h
+++ b/src/libc/private_include/libc/file.h
@@ -1,6 +1,8 @@
#ifndef LIBC_FILE_H
#define LIBC_FILE_H
+#include <aio.h>
+
enum
{
STDIN_FILENO,
@@ -10,6 +12,7 @@ enum
struct __file
{
+ struct aio *aio;
};
#endif
diff --git a/src/libc/private_include/libc/malloc.h b/src/libc/private_include/libc/malloc.h
new file mode 100644
index 0000000..3662496
--- /dev/null
+++ b/src/libc/private_include/libc/malloc.h
@@ -0,0 +1,24 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef LIBC_MALLOC_H
+#define LIBC_MALLOC_H
+
+extern int __malloc_ta_init;
+
+#endif
diff --git a/src/libc/src/CMakeLists.txt b/src/libc/src/CMakeLists.txt
new file mode 100644
index 0000000..8fa0428
--- /dev/null
+++ b/src/libc/src/CMakeLists.txt
@@ -0,0 +1,40 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(c PRIVATE
+ abort.c
+ calloc.c
+ clock_getres.c
+ clock_gettime.c
+ clock_settime.c
+ errno.c
+ free.c
+ malloc.c
+ memcmp.c
+ memcpy.c
+ memset.c
+ realloc.c
+ strchr.c
+ strcmp.c
+ strdup.c
+ streams.c
+ strerror.c
+ strlen.c
+ strncmp.c
+ strndup.c
+ strrchr.c
+ ta_init.c
+)
diff --git a/src/libc/src/abort.c b/src/libc/src/abort.c
new file mode 100644
index 0000000..9dc31a8
--- /dev/null
+++ b/src/libc/src/abort.c
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+void __abort(const char *const filename, const int lineno)
+{
+ printf("%s:%d: aborted\n", filename, lineno);
+
+ for (;;)
+ ;
+}
diff --git a/src/libc/src/calloc.c b/src/libc/src/calloc.c
new file mode 100644
index 0000000..5d1c24f
--- /dev/null
+++ b/src/libc/src/calloc.c
@@ -0,0 +1,32 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+void *calloc(const size_t nemb, const size_t size)
+{
+ const size_t n = nemb * size;
+ void *const ret = malloc(n);
+
+ if (ret)
+ memset(ret, 0, n);
+
+ return ret;
+}
diff --git a/src/libc/src/clock_getres.c b/src/libc/src/clock_getres.c
new file mode 100644
index 0000000..bbd719e
--- /dev/null
+++ b/src/libc/src/clock_getres.c
@@ -0,0 +1,25 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <time.h>
+#include <drv/time.h>
+
+int clock_getres(const clockid_t id, struct timespec *const ts)
+{
+ return drv_time_getres(id, ts);
+}
diff --git a/src/libc/src/clock_gettime.c b/src/libc/src/clock_gettime.c
new file mode 100644
index 0000000..8e38f01
--- /dev/null
+++ b/src/libc/src/clock_gettime.c
@@ -0,0 +1,25 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <time.h>
+#include <drv/time.h>
+
+int clock_gettime(const clockid_t id, struct timespec *const ts)
+{
+ return drv_time_gettime(id, ts);
+}
diff --git a/src/libc/src/clock_settime.c b/src/libc/src/clock_settime.c
new file mode 100644
index 0000000..17a64bc
--- /dev/null
+++ b/src/libc/src/clock_settime.c
@@ -0,0 +1,25 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <time.h>
+#include <drv/time.h>
+
+int clock_settime(const clockid_t id, const struct timespec *const ts)
+{
+ return drv_time_settime(id, ts);
+}
diff --git a/src/libc/src/free.c b/src/libc/src/free.c
index d89a80a..1aa9f4d 100644
--- a/src/libc/src/free.c
+++ b/src/libc/src/free.c
@@ -1,5 +1,5 @@
/*
- * wanix, a Unix-like operating system for WebAssembly
+ * wanix, a Unix-like operating system for WebAssembly applications.
* Copyright (C) 2025 Xavier Del Campo Romero
*
* This program is free software: you can redistribute it and/or modify
@@ -16,8 +16,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include <tinyalloc.h>
+#include <libc/malloc.h>
#include <stdlib.h>
void free(void *const ptr)
{
+ if (!ptr)
+ return;
+ else if (!__malloc_ta_init || !ta_free(ptr))
+ abort();
}
diff --git a/src/libc/src/malloc.c b/src/libc/src/malloc.c
index aa5ff31..4955af5 100644
--- a/src/libc/src/malloc.c
+++ b/src/libc/src/malloc.c
@@ -1,5 +1,5 @@
/*
- * wanix, a Unix-like operating system for WebAssembly
+ * wanix, a Unix-like operating system for WebAssembly applications.
* Copyright (C) 2025 Xavier Del Campo Romero
*
* This program is free software: you can redistribute it and/or modify
@@ -17,9 +17,32 @@
*/
#include <stdlib.h>
+#include <libc/malloc.h>
+#include <errno.h>
+#include <tinyalloc.h>
+#include <stdint.h>
#include <stddef.h>
-void *malloc(const size_t __n)
+void *malloc(const size_t n)
{
- return NULL;
+ extern char __bss_end[], __ram_end[];
+
+ if (!__malloc_ta_init)
+ {
+ enum {BLOCKSZ = 256};
+ const size_t blocks = (__ram_end - __bss_end + 1) / BLOCKSZ;
+
+ /* README.md states 16 is a "good default value". */
+ if (!ta_init(__bss_end, __ram_end, blocks, 16, sizeof (intmax_t)))
+ abort();
+
+ __malloc_ta_init = 1;
+ }
+
+ void *const ret = ta_alloc(n);
+
+ if (!ret)
+ errno = ENOMEM;
+
+ return ret;
}
diff --git a/src/libc/src/memset.c b/src/libc/src/memset.c
index 90eb611..653eb76 100644
--- a/src/libc/src/memset.c
+++ b/src/libc/src/memset.c
@@ -1,3 +1,21 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
#include <string.h>
#include <stddef.h>
diff --git a/src/libc/src/mkdir.c b/src/libc/src/mkdir.c
new file mode 100644
index 0000000..8e9209a
--- /dev/null
+++ b/src/libc/src/mkdir.c
@@ -0,0 +1,37 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <sys/stat.h>
+#include <aio.h>
+
+int mkdir(const char *const path, const mode_t m)
+{
+ const struct aio_mkdir mk =
+ {
+ .path = path,
+ .mode = m
+ };
+
+ struct aio *const aio = aio_mkdir(&mk);
+ const struct aio_poll p = {.aio = aio};
+
+ if (!aio || aio_poll(&p, 1, -1) < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/src/libc/src/ps1/CMakeLists.txt b/src/libc/src/ps1/CMakeLists.txt
new file mode 100644
index 0000000..1cf3d2d
--- /dev/null
+++ b/src/libc/src/ps1/CMakeLists.txt
@@ -0,0 +1,17 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(c PRIVATE "putchar.c")
diff --git a/src/libc/src/ps1/putchar.c b/src/libc/src/ps1/putchar.c
new file mode 100644
index 0000000..085a37e
--- /dev/null
+++ b/src/libc/src/ps1/putchar.c
@@ -0,0 +1,29 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+int putchar(const int c)
+{
+ return EOF;
+}
+
+void _putchar(const char c)
+{
+ putchar(c);
+}
diff --git a/src/libc/src/puts.c b/src/libc/src/puts.c
new file mode 100644
index 0000000..0c22ed7
--- /dev/null
+++ b/src/libc/src/puts.c
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+int puts(const char *s)
+{
+ for (; *s; s++)
+ if (putchar(*s) < 0)
+ return -1;
+
+ return putchar('\n');
+}
diff --git a/src/libc/src/realloc.c b/src/libc/src/realloc.c
new file mode 100644
index 0000000..2d830ab
--- /dev/null
+++ b/src/libc/src/realloc.c
@@ -0,0 +1,25 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <tinyalloc.h>
+#include <stdlib.h>
+
+void *realloc(void *const ptr, const size_t size)
+{
+ return ta_realloc(ptr, size);
+}
diff --git a/src/libc/src/strcmp.c b/src/libc/src/strcmp.c
new file mode 100644
index 0000000..dfd66b2
--- /dev/null
+++ b/src/libc/src/strcmp.c
@@ -0,0 +1,27 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+
+int strcmp(const char *a, const char *b)
+{
+ while (*a && *b && *a++ == *b++)
+ ;
+
+ return !!*a || !!*b;
+}
diff --git a/src/libc/src/strdup.c b/src/libc/src/strdup.c
new file mode 100644
index 0000000..71993de
--- /dev/null
+++ b/src/libc/src/strdup.c
@@ -0,0 +1,32 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+char *strdup(const char *const s)
+{
+ const size_t n = strlen(s) + 1;
+ char *const ret = malloc(n);
+
+ if (!ret)
+ return NULL;
+
+ memcpy(ret, s, n);
+ return ret;
+}
diff --git a/src/libc/src/strerror.c b/src/libc/src/strerror.c
index 6444e98..4ccd924 100644
--- a/src/libc/src/strerror.c
+++ b/src/libc/src/strerror.c
@@ -5,6 +5,7 @@ char *strerror(const int errnum)
{
static const char *const s[] =
{
+ [0] = "Success",
[EPERM] = "Operation not permitted",
[ENOENT] = "No such file or directory",
[ESRCH] = "No such process",
@@ -37,6 +38,105 @@ char *strerror(const int errnum)
[EROFS] = "Read-only file system",
[EMLINK] = "Too many links",
[EPIPE] = "Broken pipe",
+ [EDOM] = "Numerical argument out of domain",
+ [ERANGE] = "Numerical result out of range",
+ [EDEADLK] = "Resource deadlock avoided",
+ [ENAMETOOLONG] = "File name too long",
+ [ENOLCK] = "No locks available",
+ [ENOSYS] = "Function not implemented",
+ [ENOTEMPTY] = "Directory not empty",
+ [ELOOP] = "Too many levels of symbolic links",
+ [ENOMSG] = "No message of desired type",
+ [EIDRM] = "Identifier removed",
+ [ECHRNG] = "Channel number out of range",
+ [EL2NSYNC] = "Level 2 not synchronized",
+ [EL3HLT] = "Level 3 halted",
+ [EL3RST] = "Level 3 reset",
+ [ELNRNG] = "Link number out of range",
+ [EUNATCH] = "Protocol driver not attached",
+ [ENOCSI] = "No CSI structure available",
+ [EL2HLT] = "Level 2 halted",
+ [EBADE] = "Invalid exchange",
+ [EBADR] = "Invalid request descriptor",
+ [EXFULL] = "Exchange full",
+ [ENOANO] = "No anode",
+ [EBADRQC] = "Invalid request code",
+ [EBADSLT] = "Invalid slot",
+ [EBFONT] = "Bad font file format",
+ [ENOSTR] = "Device not a stream",
+ [ENODATA] = "No data available",
+ [ETIME] = "Timer expired",
+ [ENOSR] = "Out of streams resources",
+ [ENONET] = "Machine is not on the network",
+ [ENOPKG] = "Package not installed",
+ [EREMOTE] = "Object is remote",
+ [ENOLINK] = "Link has been severed",
+ [EADV] = "Advertise error",
+ [ESRMNT] = "Srmount error",
+ [ECOMM] = "Communication error on send",
+ [EPROTO] = "Protocol error",
+ [EMULTIHOP] = "Multihop attempted",
+ [EDOTDOT] = "RFS specific error",
+ [EBADMSG] = "Bad message",
+ [EOVERFLOW] = "Value too large for defined data type",
+ [ENOTUNIQ] = "Name not unique on network",
+ [EBADFD] = "File descriptor in bad state",
+ [EREMCHG] = "Remote address changed",
+ [ELIBACC] = "Can not access a needed shared library",
+ [ELIBBAD] = "Accessing a corrupted shared library",
+ [ELIBSCN] = ".lib section in a.out corrupted",
+ [ELIBMAX] = "Attempting to link in too many shared libraries",
+ [ELIBEXEC] = "Cannot exec a shared library directly",
+ [EILSEQ] = "Invalid or incomplete multibyte or wide character",
+ [ERESTART] = "Interrupted system call should be restarted",
+ [ESTRPIPE] = "Streams pipe error",
+ [EUSERS] = "Too many users",
+ [ENOTSOCK] = "Socket operation on non-socket",
+ [EDESTADDRREQ] = "Destination address required",
+ [EMSGSIZE] = "Message too long",
+ [EPROTOTYPE] = "Protocol wrong type for socket",
+ [ENOPROTOOPT] = "Protocol not available",
+ [EPROTONOSUPPORT] = "Protocol not supported",
+ [ESOCKTNOSUPPORT] = "Socket type not supported",
+ [ENOTSUP] = "Operation not supported",
+ [EPFNOSUPPORT] = "Protocol family not supported",
+ [EAFNOSUPPORT] = "Address family not supported by protocol",
+ [EADDRINUSE] = "Address already in use",
+ [EADDRNOTAVAIL] = "Cannot assign requested address",
+ [ENETDOWN] = "Network is down",
+ [ENETUNREACH] = "Network is unreachable",
+ [ENETRESET] = "Network dropped connection on reset",
+ [ECONNABORTED] = "Software caused connection abort",
+ [ECONNRESET] = "Connection reset by peer",
+ [ENOBUFS] = "No buffer space available",
+ [EISCONN] = "Transport endpoint is already connected",
+ [ENOTCONN] = "Transport endpoint is not connected",
+ [ESHUTDOWN] = "Cannot send after transport endpoint shutdown",
+ [ETOOMANYREFS] = "Too many references: cannot splice",
+ [ETIMEDOUT] = "Connection timed out",
+ [ECONNREFUSED] = "Connection refused",
+ [EHOSTDOWN] = "Host is down",
+ [EHOSTUNREACH] = "No route to host",
+ [EALREADY] = "Operation already in progress",
+ [EINPROGRESS] = "Operation now in progress",
+ [ESTALE] = "Stale file handle",
+ [EUCLEAN] = "Structure needs cleaning",
+ [ENOTNAM] = "Not a XENIX named type file",
+ [ENAVAIL] = "No XENIX semaphores available",
+ [EISNAM] = "Is a named type file",
+ [EREMOTEIO] = "Remote I/O error",
+ [EDQUOT] = "Disk quota exceeded",
+ [ENOMEDIUM] = "No medium found",
+ [EMEDIUMTYPE] = "Wrong medium type",
+ [ECANCELED] = "Operation canceled",
+ [ENOKEY] = "Required key not available",
+ [EKEYEXPIRED] = "Key has expired",
+ [EKEYREVOKED] = "Key has been revoked",
+ [EKEYREJECTED] = "Key was rejected by service",
+ [EOWNERDEAD] = "Owner died",
+ [ENOTRECOVERABLE] = "State not recoverable",
+ [ERFKILL] = "Operation not possible due to RF-kill",
+ [EHWPOISON] = "Memory page has hardware error",
};
if (errnum < 0 || errnum >= sizeof s / sizeof *s)
diff --git a/src/libc/src/strncmp.c b/src/libc/src/strncmp.c
new file mode 100644
index 0000000..c7ba771
--- /dev/null
+++ b/src/libc/src/strncmp.c
@@ -0,0 +1,29 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stddef.h>
+
+int strncmp(const char *a, const char *b, const size_t n)
+{
+ for (size_t i = 0; i < n; i++)
+ if (*a && *b && *a++ != *b++)
+ return -1;
+
+ return 0;
+}
diff --git a/src/libc/src/strndup.c b/src/libc/src/strndup.c
new file mode 100644
index 0000000..d35a42e
--- /dev/null
+++ b/src/libc/src/strndup.c
@@ -0,0 +1,32 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+char *strndup(const char *const s, const size_t n)
+{
+ char *const ret = malloc(n + 1);
+
+ if (!ret)
+ return NULL;
+
+ memcpy(ret, s, n);
+ ret[n] = '\0';
+ return ret;
+}
diff --git a/src/libc/src/strrchr.c b/src/libc/src/strrchr.c
new file mode 100644
index 0000000..e18a4c0
--- /dev/null
+++ b/src/libc/src/strrchr.c
@@ -0,0 +1,31 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stddef.h>
+
+char *strrchr(const char *s, const int c)
+{
+ const size_t len = strlen(s);
+
+ for (size_t i = len; i <= len; i--)
+ if (s[i] == c)
+ return (char *)&s[i];
+
+ return NULL;
+}
diff --git a/src/libc/src/ta_init.c b/src/libc/src/ta_init.c
new file mode 100644
index 0000000..b38e45e
--- /dev/null
+++ b/src/libc/src/ta_init.c
@@ -0,0 +1,21 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <libc/malloc.h>
+
+int __malloc_ta_init;
diff --git a/src/loop/CMakeLists.txt b/src/loop/CMakeLists.txt
new file mode 100644
index 0000000..4645d01
--- /dev/null
+++ b/src/loop/CMakeLists.txt
@@ -0,0 +1,20 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(loop)
+add_subdirectory(src)
+target_include_directories(loop PUBLIC include PRIVATE private_include)
+target_link_libraries(loop PUBLIC aio PRIVATE fs init)
diff --git a/src/loop/include/loop.h b/src/loop/include/loop.h
new file mode 100644
index 0000000..dd833d1
--- /dev/null
+++ b/src/loop/include/loop.h
@@ -0,0 +1,28 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef LOOP_H
+#define LOOP_H
+
+#include <aio.h>
+
+int loop_run(void);
+int loop_add_aio(struct aio *a);
+int loop_rm_aio(struct aio *a);
+
+#endif
diff --git a/src/loop/private_include/loop/types.h b/src/loop/private_include/loop/types.h
new file mode 100644
index 0000000..d42a042
--- /dev/null
+++ b/src/loop/private_include/loop/types.h
@@ -0,0 +1,26 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef LOOP_TYPES_H
+#define LOOP_TYPES_H
+
+#include <aio.h>
+
+struct aio_poll *loop_aio_head, *loop_aio_tail;
+
+#endif
diff --git a/src/loop/src/CMakeLists.txt b/src/loop/src/CMakeLists.txt
new file mode 100644
index 0000000..ab55275
--- /dev/null
+++ b/src/loop/src/CMakeLists.txt
@@ -0,0 +1,21 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+target_sources(loop PRIVATE
+ add_aio.c
+ rm_aio.c
+ run.c
+)
diff --git a/src/loop/src/add_aio.c b/src/loop/src/add_aio.c
new file mode 100644
index 0000000..8174acc
--- /dev/null
+++ b/src/loop/src/add_aio.c
@@ -0,0 +1,43 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <loop.h>
+#include <loop/types.h>
+#include <aio.h>
+#include <stdlib.h>
+
+int loop_add_aio(struct aio *const a)
+{
+ struct aio_poll *const p = malloc(sizeof *p);
+
+ if (!p)
+ return -1;
+
+ *p = (const struct aio_poll){.aio = a};
+
+ if (!loop_aio_head)
+ loop_aio_head = p;
+ else if (loop_aio_tail)
+ {
+ loop_aio_tail->next = p;
+ p->prev = loop_aio_tail;
+ }
+
+ loop_aio_tail = p;
+ return 0;
+}
diff --git a/src/loop/src/rm_aio.c b/src/loop/src/rm_aio.c
new file mode 100644
index 0000000..b6c678a
--- /dev/null
+++ b/src/loop/src/rm_aio.c
@@ -0,0 +1,48 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <loop.h>
+#include <loop/types.h>
+#include <aio.h>
+#include <stdlib.h>
+
+int loop_rm_aio(struct aio *const aio)
+{
+ for (struct aio_poll *p = loop_aio_head; p; p = p->next)
+ if (p->aio == aio)
+ {
+ struct aio_poll *const prev = p->prev, *const next = p->next;
+
+ if (!prev)
+ {
+ loop_aio_head = next;
+
+ if (next)
+ next->prev = NULL;
+ }
+ else if ((prev->next = next))
+ next->prev = prev;
+ else
+ loop_aio_tail = prev;
+
+ free(p);
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/src/loop/src/run.c b/src/loop/src/run.c
new file mode 100644
index 0000000..666aa33
--- /dev/null
+++ b/src/loop/src/run.c
@@ -0,0 +1,33 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <loop.h>
+#include <loop/types.h>
+#include <aio.h>
+#include <fs/fs.h>
+#include <init.h>
+
+int loop_run(void)
+{
+ if (fs_update()
+ || aio_poll(loop_aio_head, 0) < 0
+ || init_run())
+ return -1;
+
+ return 0;
+}
diff --git a/src/main.c b/src/main.c
index 99d4c95..0d38aba 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,5 @@
/*
- * wanix, a Unix-like operating system for WebAssembly
+ * wanix, a Unix-like operating system for WebAssembly applications.
* Copyright (C) 2025 Xavier Del Campo Romero
*
* This program is free software: you can redistribute it and/or modify
@@ -16,31 +16,19 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-#include <aio.h>
-#include <errno.h>
-#include <stdio.h>
+#include <init.h>
+#include <gfx/gfx.h>
+#include <loop.h>
#include <stdlib.h>
-#include <string.h>
int main(void)
{
- int ret = EXIT_FAILURE;
- struct aio *aio = aio_open("/media/cdrom/", "rb");
+ if (init_time() || gfx_init() || init_boot() || init_vfs())
+ return EXIT_FAILURE;
- if (!aio)
- {
- fprintf(stderr, "%s: aio_open failed: %s\n", __func__, strerror(errno));
- goto end;
- }
+ for (;;)
+ if (loop_run())
+ return EXIT_FAILURE;
- ret = EXIT_SUCCESS;
-
-end:
- if (aio && aio_close(aio))
- {
- fprintf(stderr, "%s: aio_close failed: %s\n", __func__, strerror(errno));
- ret = EXIT_FAILURE;
- }
-
- return ret;
+ return EXIT_SUCCESS;
}
diff --git a/src/ps1/CMakeLists.txt b/src/ps1/CMakeLists.txt
index 6ba4543..c455ef3 100644
--- a/src/ps1/CMakeLists.txt
+++ b/src/ps1/CMakeLists.txt
@@ -1,5 +1,27 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
target_link_libraries(${PROJECT_NAME} PRIVATE c)
target_link_libraries(nanowasm PRIVATE c)
+target_link_libraries(dynstr PRIVATE c)
target_sources(${PROJECT_NAME} PRIVATE start.c)
target_link_options(${PROJECT_NAME} PRIVATE
-T${CMAKE_CURRENT_LIST_DIR}/playstation.x)
+add_custom_target(system_cnf ALL
+ ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_CURRENT_LIST_DIR}/system.cnf ${cdroot}
+)
+add_dependencies(iso system_cnf)
diff --git a/src/ps1/playstation.x b/src/ps1/playstation.x
index 00a1a74..71a4c34 100644
--- a/src/ps1/playstation.x
+++ b/src/ps1/playstation.x
@@ -68,5 +68,7 @@ SECTIONS
__bss_start = ADDR(.bss);
__bss_end = ADDR(.bss) + SIZEOF(.bss);
+ __ram_end = 0x8020FFFF;
+
__scratchpad = 0x1f800000;
}
diff --git a/src/ps1/start.c b/src/ps1/start.c
index 09ca6c9..c5558fe 100644
--- a/src/ps1/start.c
+++ b/src/ps1/start.c
@@ -1,7 +1,7 @@
__attribute__((__section__(".text.startup"))) void _start(void)
{
int main(void);
- extern char *__bss_start, *__bss_end;
+ extern char __bss_start[], __bss_end[];
for (char *s = __bss_start; s < __bss_end; s++)
*s = 0;
diff --git a/src/ps1/system.cnf b/src/ps1/system.cnf
index 1c3aebe..8f875bf 100644
--- a/src/ps1/system.cnf
+++ b/src/ps1/system.cnf
@@ -1,4 +1,4 @@
-BOOT = cdrom:\wanix.exe;1
-TCB = 1
-EVENT = 8
-STACK = 801FF800
+BOOT = cdrom:\wanix.exe;1
+TCB = 1
+EVENT = 16
+STACK = 801FF800
diff --git a/src/state/CMakeLists.txt b/src/state/CMakeLists.txt
new file mode 100644
index 0000000..a208361
--- /dev/null
+++ b/src/state/CMakeLists.txt
@@ -0,0 +1,18 @@
+# wanix, a Unix-like operating system for WebAssembly applications.
+# Copyright (C) 2025 Xavier Del Campo Romero
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+add_library(state INTERFACE)
+target_include_directories(state INTERFACE include)
diff --git a/src/state/include/state.h b/src/state/include/state.h
new file mode 100644
index 0000000..8b93a65
--- /dev/null
+++ b/src/state/include/state.h
@@ -0,0 +1,29 @@
+/*
+ * wanix, a Unix-like operating system for WebAssembly applications.
+ * Copyright (C) 2025 Xavier Del Campo Romero
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef STATE_H
+#define STATE_H
+
+enum state
+{
+ STATE_OK,
+ STATE_AGAIN,
+ STATE_FATAL
+};
+
+#endif