diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-07-07 13:22:53 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-07-25 14:16:41 +0200 |
| commit | 14f60e4fd65c42f126eaee7e09cb4251c167c6ed (patch) | |
| tree | 313b5e16d7d99cf1518c953e2efe5e5fc920dfbf | |
| parent | 48a61c16eaa6dcfc75d00dba302537ce1492db98 (diff) | |
wiptty
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; +} @@ -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 |
