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-11-11 00:08:15 +0100 |
| commit | 7861a52adf92a083bb2aed4c35f98d8035dce032 (patch) | |
| tree | 28cd3c40e4c878f730f5df3c1d93bdf91af490c3 /src/drv | |
| parent | 7fc48e9216ff809da5f8055a50b0be17628ef1df (diff) | |
| download | wnix-7861a52adf92a083bb2aed4c35f98d8035dce032.tar.gz | |
Setup project skeleton
Diffstat (limited to 'src/drv')
145 files changed, 6758 insertions, 0 deletions
diff --git a/src/drv/CMakeLists.txt b/src/drv/CMakeLists.txt new file mode 100644 index 0000000..3306d93 --- /dev/null +++ b/src/drv/CMakeLists.txt @@ -0,0 +1,28 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..7d52511 --- /dev/null +++ b/src/drv/event/CMakeLists.txt @@ -0,0 +1,18 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..5707242 --- /dev/null +++ b/src/drv/event/include/drv/event.h @@ -0,0 +1,49 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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 <sys/types.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, off_t offset, + const struct drv_event_done *done, void *args); + int (*read_nb)(void *buf, size_t n, void *args); + int (*write)(const void *buf, size_t n, 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, mode_t mode, 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..eb8bee0 --- /dev/null +++ b/src/drv/include/drv/drv.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..12b213d --- /dev/null +++ b/src/drv/include/drv/time.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..cdf30ab --- /dev/null +++ b/src/drv/private_include/drv/port.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..da4b7e9 --- /dev/null +++ b/src/drv/private_include/drv/tree.h @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..959e12d --- /dev/null +++ b/src/drv/private_include/drv/types.h @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..08d97c2 --- /dev/null +++ b/src/drv/ps1/CMakeLists.txt @@ -0,0 +1,37 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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(cpu) +add_subdirectory(dma) +add_subdirectory(event) +add_subdirectory(gpu) +add_subdirectory(irq) +add_subdirectory(mc) +add_subdirectory(pad) +add_subdirectory(rcnt) +add_subdirectory(sio) +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 + drv_ps1_sio +) diff --git a/src/drv/ps1/bios/CMakeLists.txt b/src/drv/ps1/bios/CMakeLists.txt new file mode 100644 index 0000000..ebc0937 --- /dev/null +++ b/src/drv/ps1/bios/CMakeLists.txt @@ -0,0 +1,19 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..ca53194 --- /dev/null +++ b/src/drv/ps1/bios/include/drv/ps1/bios.h @@ -0,0 +1,128 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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> +#include <setjmp.h> + +#if __GNUC__ +#define PRINTF_ATTR __attribute__ ((format (__printf__, 1, 2))) +#else +#define PRINTF_ATTR +#endif + +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; +}; + +int EnterCriticalSection(void); +void ExitCriticalSection(void); +void GetConf(uint32_t *events, uint32_t *tcb, void **stacktop); +void SetConf(uint32_t events, uint32_t tcb, void *stacktop); +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); +int Printf(const char *fmt, ...) PRINTF_ATTR; +void SetCustomExitFromException(jmp_buf jmp); +void CdInit(void); +void CdRemove(void); +int SaveState(jmp_buf buf); +void RestoreState(jmp_buf buf, int value); +void ReturnFromException(void); + +#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..67ea62b --- /dev/null +++ b/src/drv/ps1/bios/src/CMakeLists.txt @@ -0,0 +1,38 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 + CdInit.s + CdRemove.s + CloseEvent.s + DisableEvent.s + EnableEvent.s + EnterCriticalSection.s + ExitCriticalSection.s + GetConf.s + OpenEvent.s + Printf.s + RestoreState.s + ReturnFromException.s + SaveState.s + SetConf.s + SetCustomExitFromException.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..18922da --- /dev/null +++ b/src/drv/ps1/bios/src/CdAsyncGetStatus.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..6411e12 --- /dev/null +++ b/src/drv/ps1/bios/src/CdAsyncReadSector.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..529d116 --- /dev/null +++ b/src/drv/ps1/bios/src/CdAsyncSeekL.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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/CdInit.s b/src/drv/ps1/bios/src/CdInit.s new file mode 100644 index 0000000..dcf3474 --- /dev/null +++ b/src/drv/ps1/bios/src/CdInit.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 CdInit + +CdInit: + li $9, 0x54 + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/CdRemove.s b/src/drv/ps1/bios/src/CdRemove.s new file mode 100644 index 0000000..e3bb34d --- /dev/null +++ b/src/drv/ps1/bios/src/CdRemove.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 CdRemove + +CdRemove: + li $9, 0x56 + 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..7dd47e3 --- /dev/null +++ b/src/drv/ps1/bios/src/CloseEvent.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..f32dcf8 --- /dev/null +++ b/src/drv/ps1/bios/src/DisableEvent.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..f6da29d --- /dev/null +++ b/src/drv/ps1/bios/src/EnableEvent.s @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..c8302e0 --- /dev/null +++ b/src/drv/ps1/bios/src/EnterCriticalSection.s @@ -0,0 +1,25 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..198b040 --- /dev/null +++ b/src/drv/ps1/bios/src/ExitCriticalSection.s @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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/GetConf.s b/src/drv/ps1/bios/src/GetConf.s new file mode 100644 index 0000000..927b950 --- /dev/null +++ b/src/drv/ps1/bios/src/GetConf.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 GetConf + +GetConf: + li $9, 0x9d + j 0xa0 + 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..dca7141 --- /dev/null +++ b/src/drv/ps1/bios/src/OpenEvent.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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/Printf.s b/src/drv/ps1/bios/src/Printf.s new file mode 100644 index 0000000..9e0a77f --- /dev/null +++ b/src/drv/ps1/bios/src/Printf.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 Printf + +Printf: + li $9, 0x3f + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/RestoreState.s b/src/drv/ps1/bios/src/RestoreState.s new file mode 100644 index 0000000..c830296 --- /dev/null +++ b/src/drv/ps1/bios/src/RestoreState.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 RestoreState + +RestoreState: + li $9, 0x14 + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/ReturnFromException.s b/src/drv/ps1/bios/src/ReturnFromException.s new file mode 100644 index 0000000..6af3bb3 --- /dev/null +++ b/src/drv/ps1/bios/src/ReturnFromException.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 ReturnFromException + +ReturnFromException: + li $9, 0x17 + j 0xb0 + nop diff --git a/src/drv/ps1/bios/src/SaveState.s b/src/drv/ps1/bios/src/SaveState.s new file mode 100644 index 0000000..eb72ea3 --- /dev/null +++ b/src/drv/ps1/bios/src/SaveState.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 SaveState + +SaveState: + li $9, 0x13 + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/SetConf.s b/src/drv/ps1/bios/src/SetConf.s new file mode 100644 index 0000000..5063667 --- /dev/null +++ b/src/drv/ps1/bios/src/SetConf.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 SetConf + +SetConf: + li $9, 0x9c + j 0xa0 + nop diff --git a/src/drv/ps1/bios/src/SetCustomExitFromException.s b/src/drv/ps1/bios/src/SetCustomExitFromException.s new file mode 100644 index 0000000..75cf8cc --- /dev/null +++ b/src/drv/ps1/bios/src/SetCustomExitFromException.s @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 SetCustomExitFromException + +SetCustomExitFromException: + li $9, 0x19 + 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..af0edab --- /dev/null +++ b/src/drv/ps1/bios/src/TestEvent.s @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..8f58d52 --- /dev/null +++ b/src/drv/ps1/bios/src/WaitEvent.s @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..9b84541 --- /dev/null +++ b/src/drv/ps1/cd/CMakeLists.txt @@ -0,0 +1,27 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 + drv_ps1_event +) 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..ff57622 --- /dev/null +++ b/src/drv/ps1/cd/include/drv/ps1/cd.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..37b2d03 --- /dev/null +++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h @@ -0,0 +1,66 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..0b756de --- /dev/null +++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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/event.h> +#include <drv/ps1/cd/types.h> +#include <drv/ps1/bios.h> +#include <sys/types.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, off_t 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..2d4ae51 --- /dev/null +++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/types.h @@ -0,0 +1,111 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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 <sys/types.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 +{ + 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 endevent, errevent; +}; + +struct cd_req_read +{ + void *buf; + size_t n; + off_t offset; +}; + +struct cd_req +{ + union + { + struct cd_req_read read; + } u; + + int (*f)(void); + struct drv_event_done done; + struct cd_req *next; +}; + +enum {CD_SECTOR_SZ = 2048}; + +struct cd_prv +{ + bool available, sector_read; + int (*next)(void); + int event; + struct cmd cmd; + struct cd_req *head, *tail; + char sector[CD_SECTOR_SZ]; + off_t offset; + + union + { + struct cd_prv_getstat getstat; + struct cd_prv_read read; + } u; +}; + +extern struct cd_prv drv_ps1_cd_prv; + +#endif diff --git a/src/drv/ps1/cd/private_include/drv/ps1/cd/virt/types.h b/src/drv/ps1/cd/private_include/drv/ps1/cd/virt/types.h new file mode 100644 index 0000000..59437c0 --- /dev/null +++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/virt/types.h @@ -0,0 +1,36 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_VIRT_TYPES_H +#define DRV_PS1_CD_VIRT_TYPES_H + +#include <drv/event.h> + +struct drv_ps1_cd +{ + struct drv_event ev; +}; + +struct cd_prv +{ + int (*next)(void); +}; + +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..df5ecca --- /dev/null +++ b/src/drv/ps1/cd/src/CMakeLists.txt @@ -0,0 +1,33 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +if(WNIX_VIRT_CD) + add_subdirectory(virt) +else() + target_sources(drv_ps1_cd PRIVATE + free.c + getstat.c + init.c + next.c + prv.c + read.c + toseekl.c + update.c + write.c + ) +endif() + +target_link_libraries(drv_ps1_cd PRIVATE kprintf) 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..592184a --- /dev/null +++ b/src/drv/ps1/cd/src/ensure_event.c @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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 <drv/ps1/event.h> +#include <stddef.h> + +int drv_ps1_cd_ensure_event(struct cd_prv *const p) +{ + if (p->event) + return 0; + + const int event = drv_ps1_event_open(CLASS_CDROM, SPEC_COMMAND_COMPLETE, + MODE_READY, NULL); + + if (event == -1) + return -1; + + drv_ps1_event_enable(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..ed6f347 --- /dev/null +++ b/src/drv/ps1/cd/src/free.c @@ -0,0 +1,23 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..34bdaf5 --- /dev/null +++ b/src/drv/ps1/cd/src/getstat.c @@ -0,0 +1,70 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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> +#include <drv/ps1/event.h> +#include <kprintf.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 (drv_ps1_event_test(p->event)) + { + p->available = !g->status.bits.shell_open; + + if (!p->head) + return drv_ps1_cd_getstat(); + + return p->head->f(); + } + + return 0; +} + +static int ensure_event(struct cd_prv *const p) +{ + if (p->event) + return 0; + else if ((p->event = drv_ps1_event_open(CLASS_CDROM, SPEC_COMMAND_COMPLETE, + MODE_READY, NULL)) == -1) + return -1; + + drv_ps1_event_enable(p->event); + 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; + + /* TODO: CdAsyncGetStatus is *very* slow (~2.5 seconds / 10k calls) */ + if (ensure_event(p)) + return -1; + else if (!CdAsyncGetStatus(&g->status.byte)) + { + kprintf("%s: CdAsyncGetStatus failed\n", __func__); + 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..b452e82 --- /dev/null +++ b/src/drv/ps1/cd/src/init.c @@ -0,0 +1,42 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..b26633a --- /dev/null +++ b/src/drv/ps1/cd/src/next.c @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_req *const next = p->head->next; + + free(p->head); + + if (next && next->f()) + return -1; + else if (!(p->head = next)) + return drv_ps1_cd_getstat(); + + return 0; +} diff --git a/src/drv/ps1/cd/src/prv.c b/src/drv/ps1/cd/src/prv.c new file mode 100644 index 0000000..61ed4b4 --- /dev/null +++ b/src/drv/ps1/cd/src/prv.c @@ -0,0 +1,22 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..d21cbae --- /dev/null +++ b/src/drv/ps1/cd/src/read.c @@ -0,0 +1,239 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/event.h> +#include <drv/event.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +static int seek(void); + +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; + + drv_ps1_event_disable(read->endevent); + drv_ps1_event_close(read->endevent); + drv_ps1_event_disable(read->errevent); + drv_ps1_event_close(read->errevent); + + if (!error) + { + const struct cd_req_read *const rr = &req->u.read; + const long offset = rr->offset % CD_SECTOR_SZ; + + memcpy(rr->buf, p->sector + offset, rr->n); + + if (!((p->offset += rr->n) % CD_SECTOR_SZ)) + p->sector_read = false; + } + + if (d->f(error, d->args) || drv_ps1_cd_next()) + return -1; + + return 0; +} + +static int wait_read(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + const struct cd_prv_read *const read = &p->u.read; + + if (drv_ps1_event_test(p->event)) + { + p->sector_read = true; + return deliver_event(p, SUCCESS); + } + else if (drv_ps1_event_test(read->errevent) + || drv_ps1_event_test(read->endevent)) + return deliver_event(p, EIO); + + return 0; +} + +static int uncached_read(struct cd_prv *const p) +{ + int endevent, errevent; + struct cd_prv_read *const r = &p->u.read; + const struct CdAsyncReadSector_mode mode = + { + .mode.bits.speed = 1, + }; + + endevent = drv_ps1_event_open(CLASS_CDROM, SPEC_DATA_END, MODE_READY, NULL); + errevent = drv_ps1_event_open(CLASS_CDROM, SPEC_ERROR, MODE_READY, NULL); + + if (endevent == -1 || errevent == -1) + goto failure; + + *r = (const struct cd_prv_read) + { + .endevent = endevent, + .errevent = errevent + }; + + drv_ps1_event_enable(endevent); + drv_ps1_event_enable(errevent); + + if (!CdAsyncReadSector(1, p->sector, mode)) + goto failure; + + p->next = wait_read; + return 0; + +failure: + + if (endevent != -1) + { + drv_ps1_event_disable(endevent); + drv_ps1_event_close(endevent); + } + + if (errevent != -1) + { + drv_ps1_event_disable(errevent); + drv_ps1_event_close(errevent); + } + + return -1; +} + +static int cached_read(struct cd_prv *const p) +{ + struct cd_req *const req = p->head; + struct cd_req_read *const rr = &req->u.read; + const struct drv_event_done *const done = &req->done; + const off_t offset = rr->offset % CD_SECTOR_SZ, + rem = CD_SECTOR_SZ - offset, + n = rr->n > rem ? rem : rr->n; + + memcpy(rr->buf, p->sector + offset, n); + + if (!((p->offset += n) % CD_SECTOR_SZ)) + p->sector_read = false; + + if (done->f(SUCCESS, done->args) || drv_ps1_cd_next()) + return -1; + + return 0; +} + +static int wait_seek(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 struct cd_prv_read *const r = &p->u.read; + + if (drv_ps1_event_test(p->event)) + { + drv_ps1_event_disable(r->errevent); + drv_ps1_event_close(r->errevent); + p->offset = rr->offset; + return uncached_read(p); + } + else if (drv_ps1_event_test(r->errevent)) + return deliver_event(p, EIO); + + return 0; +} + +static int seek(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_prv_read *const r = &p->u.read; + const struct cd_req_read *rr = &p->head->u.read; + const unsigned sector = rr->offset / CD_SECTOR_SZ; + const struct CdAsyncSeekL seekl = drv_ps1_cd_toseekl(sector); + const int errevent = drv_ps1_event_open(CLASS_CDROM, SPEC_ERROR, + MODE_READY, NULL); + + if (errevent == -1) + goto failure; + + *r = (const struct cd_prv_read){.errevent = errevent}; + p->sector_read = false; + drv_ps1_event_enable(errevent); + + if (!CdAsyncSeekL(&seekl)) + goto failure; + + p->next = wait_seek; + return 0; + +failure: + + if (errevent != -1) + { + drv_ps1_event_disable(errevent); + drv_ps1_event_close(errevent); + } + + return -1; +} + +static int start(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 off_t cursect = p->offset / CD_SECTOR_SZ, + tgtsect = rr->offset / CD_SECTOR_SZ; + + if (cursect != tgtsect || !p->sector_read) + return seek(); + + /* TODO: multi-sector reads, make sure cache can really be used */ + return cached_read(p); +} + +int drv_ps1_cd_read(void *const buf, const size_t n, const off_t 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) + { + .f = start, + .done = *done, + .u.read = + { + .offset = offset, + .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/readdebug b/src/drv/ps1/cd/src/readdebug new file mode 100644 index 0000000..b2c09a7 --- /dev/null +++ b/src/drv/ps1/cd/src/readdebug @@ -0,0 +1,253 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/event.h> +#include <drv/event.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + + +#include <drv/ps1/bios.h> + +static int seek(void); + +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; + + drv_ps1_event_disable(read->endevent); + drv_ps1_event_close(read->endevent); + drv_ps1_event_disable(read->errevent); + drv_ps1_event_close(read->errevent); + + if (!error) + { + const struct cd_req_read *const rr = &req->u.read; + const long offset = rr->offset % CD_SECTOR_SZ; + + memcpy(rr->buf, p->sector + offset, rr->n); + + if (!((p->offset += rr->n) % CD_SECTOR_SZ)) + p->sector_read = false; + } + + if (d->f(error, d->args) || drv_ps1_cd_next()) + return -1; + + return 0; +} + +static int wait_read(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + const struct cd_prv_read *const read = &p->u.read; + + if (drv_ps1_event_test(p->event)) + { + p->sector_read = true; + return deliver_event(p, SUCCESS); + } + else if (drv_ps1_event_test(read->errevent) + || drv_ps1_event_test(read->endevent)) + return deliver_event(p, EIO); + + return 0; +} + +static int uncached_read(struct cd_prv *const p) +{ + int endevent, errevent; + struct cd_prv_read *const r = &p->u.read; + const struct CdAsyncReadSector_mode mode = + { + .mode.bits.speed = 1, + }; + + endevent = drv_ps1_event_open(CLASS_CDROM, SPEC_DATA_END, MODE_READY, NULL); + errevent = drv_ps1_event_open(CLASS_CDROM, SPEC_ERROR, MODE_READY, NULL); + + if (endevent == -1 || errevent == -1) + goto failure; + + *r = (const struct cd_prv_read) + { + .endevent = endevent, + .errevent = errevent + }; + + drv_ps1_event_enable(endevent); + drv_ps1_event_enable(errevent); + + Printf("preparing async read\n"); + if (!CdAsyncReadSector(1, p->sector, mode)) + goto failure; + + p->next = wait_read; + return 0; + +failure: + + if (endevent != -1) + { + drv_ps1_event_disable(endevent); + drv_ps1_event_close(endevent); + } + + if (errevent != -1) + { + drv_ps1_event_disable(errevent); + drv_ps1_event_close(errevent); + } + + return -1; +} + +static int cached_read(struct cd_prv *const p) +{ + struct cd_req *const req = p->head; + struct cd_req_read *const rr = &req->u.read; + const struct drv_event_done *const done = &req->done; + const off_t offset = rr->offset % CD_SECTOR_SZ, + rem = CD_SECTOR_SZ - offset, + n = rr->n > rem ? rem : rr->n; + + Printf("Doing %lu-byte cached read from offset %lu to %p\n", + (unsigned long) n, (unsigned long) offset, (void *)rr->buf); + memcpy(rr->buf, p->sector + offset, n); + + if (!((p->offset += n) % CD_SECTOR_SZ)) + p->sector_read = false; + + if (done->f(SUCCESS, done->args) || drv_ps1_cd_next()) + return -1; + + return 0; +} + +static int wait_seek(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 struct cd_prv_read *const r = &p->u.read; + + if (drv_ps1_event_test(p->event)) + { + Printf("finished seeking\n"); + drv_ps1_event_disable(r->errevent); + drv_ps1_event_close(r->errevent); + p->offset = rr->offset; + return uncached_read(p); + } + else if (drv_ps1_event_test(r->errevent)) + { + Printf("failed to seek\n"); + return deliver_event(p, EIO); + } + + return 0; +} + +static int seek(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_prv_read *const r = &p->u.read; + const struct cd_req_read *rr = &p->head->u.read; + const unsigned sector = rr->offset / CD_SECTOR_SZ; + const struct CdAsyncSeekL seekl = drv_ps1_cd_toseekl(sector); + const int errevent = drv_ps1_event_open(CLASS_CDROM, SPEC_ERROR, + MODE_READY, NULL); + + if (errevent == -1) + goto failure; + + *r = (const struct cd_prv_read){.errevent = errevent}; + p->sector_read = false; + drv_ps1_event_enable(errevent); + + Printf("Seeking to offset %lu\n", (unsigned long)rr->offset); + + if (!CdAsyncSeekL(&seekl)) + goto failure; + + p->next = wait_seek; + return 0; + +failure: + + if (errevent != -1) + { + drv_ps1_event_disable(errevent); + drv_ps1_event_close(errevent); + } + + return -1; +} + +static int start(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 off_t cursect = p->offset / CD_SECTOR_SZ, + tgtsect = rr->offset / CD_SECTOR_SZ; + + if (cursect != tgtsect || !p->sector_read) + return seek(); + + /* TODO: multi-sector reads, make sure cache can really be used */ + return cached_read(p); +} + +int drv_ps1_cd_read(void *const buf, const size_t n, const off_t 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) + { + .f = start, + .done = *done, + .u.read = + { + .offset = offset, + .buf = buf, + .n = n + } + }; + + if (!p->head) + p->head = r; + else + p->tail->next = r; + + p->tail = r; + Printf("Added %p {.buf=%p, .n=%lu} to read reqs\n", (void *)p->tail, buf, + (unsigned long)n); + 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..01aa5cb --- /dev/null +++ b/src/drv/ps1/cd/src/send.c @@ -0,0 +1,101 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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 <drv/ps1/event.h> +#include <stdint.h> + +static int wait_event(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (drv_ps1_event_test(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..ee776c9 --- /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 + */ + +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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 unsigned itob(const unsigned 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..148dd87 --- /dev/null +++ b/src/drv/ps1/cd/src/update.c @@ -0,0 +1,47 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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 + }; + + if (ev->status("cd0", &ops, p->available, 0440, ev->args)) + return -1; + + cd->available = p->available; + } + + return 0; +} diff --git a/src/drv/ps1/cd/src/virt/CMakeLists.txt b/src/drv/ps1/cd/src/virt/CMakeLists.txt new file mode 100644 index 0000000..0e5bd1b --- /dev/null +++ b/src/drv/ps1/cd/src/virt/CMakeLists.txt @@ -0,0 +1,25 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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 + init.c + # next.c + # prv.c + # read.c + # update.c + # write.c +) diff --git a/src/drv/ps1/cd/src/virt/init.c b/src/drv/ps1/cd/src/virt/init.c new file mode 100644 index 0000000..204f7fa --- /dev/null +++ b/src/drv/ps1/cd/src/virt/init.c @@ -0,0 +1,41 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/virt/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/write.c b/src/drv/ps1/cd/src/write.c new file mode 100644 index 0000000..ba47993 --- /dev/null +++ b/src/drv/ps1/cd/src/write.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/cpu/CMakeLists.txt b/src/drv/ps1/cpu/CMakeLists.txt new file mode 100644 index 0000000..dafb0cd --- /dev/null +++ b/src/drv/ps1/cpu/CMakeLists.txt @@ -0,0 +1,18 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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_cpu INTERFACE) +target_include_directories(drv_ps1_cpu INTERFACE include) diff --git a/src/drv/ps1/cpu/include/drv/ps1/cpu.h b/src/drv/ps1/cpu/include/drv/ps1/cpu.h new file mode 100644 index 0000000..d951f48 --- /dev/null +++ b/src/drv/ps1/cpu/include/drv/ps1/cpu.h @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_CPU_H +#define DRV_PS1_CPU_H + +#define DRV_PS1_CPU_F 33868800ul + +#endif diff --git a/src/drv/ps1/dma/CMakeLists.txt b/src/drv/ps1/dma/CMakeLists.txt new file mode 100644 index 0000000..0daeee9 --- /dev/null +++ b/src/drv/ps1/dma/CMakeLists.txt @@ -0,0 +1,18 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..9538c3b --- /dev/null +++ b/src/drv/ps1/dma/include/drv/ps1/dma.h @@ -0,0 +1,97 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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/event/CMakeLists.txt b/src/drv/ps1/event/CMakeLists.txt new file mode 100644 index 0000000..2b00aaa --- /dev/null +++ b/src/drv/ps1/event/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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_event) +add_subdirectory(src) +target_include_directories(drv_ps1_event PUBLIC include) +target_link_libraries(drv_ps1_event PUBLIC c drv_ps1_bios) diff --git a/src/drv/ps1/event/include/drv/ps1/event.h b/src/drv/ps1/event/include/drv/ps1/event.h new file mode 100644 index 0000000..2c34b02 --- /dev/null +++ b/src/drv/ps1/event/include/drv/ps1/event.h @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_EVENT_H +#define DRV_PS1_EVENT_H + +#include <drv/ps1/bios.h> + +int drv_ps1_event_open(int class, int spec, int mode, int (*f)(void)); +int drv_ps1_event_test(int event); +int drv_ps1_event_wait(int event); +int drv_ps1_event_enable(int event); +int drv_ps1_event_disable(int event); +int drv_ps1_event_close(int event); + +#endif diff --git a/src/drv/ps1/event/src/CMakeLists.txt b/src/drv/ps1/event/src/CMakeLists.txt new file mode 100644 index 0000000..e741edc --- /dev/null +++ b/src/drv/ps1/event/src/CMakeLists.txt @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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_event PRIVATE + close.c + disable.c + enable.c + open.c + test.c +) diff --git a/src/drv/ps1/event/src/close.c b/src/drv/ps1/event/src/close.c new file mode 100644 index 0000000..01c9a33 --- /dev/null +++ b/src/drv/ps1/event/src/close.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/event.h> +#include <drv/ps1/bios.h> + +int drv_ps1_event_close(const int event) +{ + return CloseEvent(event); +} diff --git a/src/drv/ps1/event/src/disable.c b/src/drv/ps1/event/src/disable.c new file mode 100644 index 0000000..6d32b2b --- /dev/null +++ b/src/drv/ps1/event/src/disable.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/event.h> +#include <drv/ps1/bios.h> + +int drv_ps1_event_disable(const int event) +{ + return DisableEvent(event); +} diff --git a/src/drv/ps1/event/src/enable.c b/src/drv/ps1/event/src/enable.c new file mode 100644 index 0000000..3368ac4 --- /dev/null +++ b/src/drv/ps1/event/src/enable.c @@ -0,0 +1,25 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/event.h> +#include <drv/ps1/bios.h> + +int drv_ps1_event_enable(const int event) +{ + return EnableEvent(event); +} diff --git a/src/drv/ps1/event/src/open.c b/src/drv/ps1/event/src/open.c new file mode 100644 index 0000000..6bb55f1 --- /dev/null +++ b/src/drv/ps1/event/src/open.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/event.h> +#include <drv/ps1/bios.h> + +int drv_ps1_event_open(const int class, const int spec, const int mode, + int (*const f)(void)) +{ + int ret; + + EnterCriticalSection(); + ret = OpenEvent(class, spec, mode, f); + ExitCriticalSection(); + return ret; +} diff --git a/src/drv/ps1/event/src/test.c b/src/drv/ps1/event/src/test.c new file mode 100644 index 0000000..358bd8e --- /dev/null +++ b/src/drv/ps1/event/src/test.c @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/event.h> +#include <drv/ps1/bios.h> + +int drv_ps1_event_test(const int event) +{ + int ret; + + ret = TestEvent(event); + return ret; +} diff --git a/src/drv/ps1/gpu/CMakeLists.txt b/src/drv/ps1/gpu/CMakeLists.txt new file mode 100644 index 0000000..a86ab92 --- /dev/null +++ b/src/drv/ps1/gpu/CMakeLists.txt @@ -0,0 +1,18 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..1afc5f6 --- /dev/null +++ b/src/drv/ps1/gpu/include/drv/ps1/gpu.h @@ -0,0 +1,173 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_FILL_VRAM = 0x02, + 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 w :16, h :16, x :16, y :16, r :8, g :8, b :8, cmd :8; + } fill_vram; + + 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_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..7d92878 --- /dev/null +++ b/src/drv/ps1/include/drv/ps1.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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/irq/CMakeLists.txt b/src/drv/ps1/irq/CMakeLists.txt new file mode 100644 index 0000000..8327cd5 --- /dev/null +++ b/src/drv/ps1/irq/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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_irq) +add_subdirectory(src) +target_include_directories(drv_ps1_irq PUBLIC include PRIVATE private_include) +target_link_libraries(drv_ps1_irq PUBLIC c PRIVATE drv_ps1_bios) diff --git a/src/drv/ps1/irq/include/drv/ps1/irq.h b/src/drv/ps1/irq/include/drv/ps1/irq.h new file mode 100644 index 0000000..0d40c7f --- /dev/null +++ b/src/drv/ps1/irq/include/drv/ps1/irq.h @@ -0,0 +1,64 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_IRQ_H +#define DRV_PS1_IRQ_H + +#include <stdint.h> + +union drv_ps1_statmask +{ + 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_statmask *)I_BASE(0)) +#define I_MASK ((volatile union drv_ps1_statmask *)I_BASE(4)) + +enum drv_ps1_irq +{ + IRQ_VBLANK, + IRQ_GPU, + IRQ_CDROM, + IRQ_DMA, + IRQ_TMR0, + IRQ_TMR1, + IRQ_TMR2, + IRQ_JOYPAD_MEMCARD, + IRQ_SIO, + IRQ_SPU, + IRQ_JOYPAD_IO +}; + +struct drv_ps1_irq_src +{ + int mask; + int (*fn)(void); + struct drv_ps1_irq_src *next; +}; + +int drv_ps1_irq_init(void); +int drv_ps1_irq_set(struct drv_ps1_irq_src *src); + +#endif diff --git a/src/drv/ps1/irq/private_include/drv/ps1/irq/routines.h b/src/drv/ps1/irq/private_include/drv/ps1/irq/routines.h new file mode 100644 index 0000000..39b7448 --- /dev/null +++ b/src/drv/ps1/irq/private_include/drv/ps1/irq/routines.h @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_IRQ_ROUTINES_H +#define DRV_PS1_IRQ_ROUTINES_H + +void drv_ps1_irq_handler(void); + +#endif diff --git a/src/drv/ps1/irq/private_include/drv/ps1/irq/types.h b/src/drv/ps1/irq/private_include/drv/ps1/irq/types.h new file mode 100644 index 0000000..6c5a185 --- /dev/null +++ b/src/drv/ps1/irq/private_include/drv/ps1/irq/types.h @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_IRQ_TYPES_H +#define DRV_PS1_IRQ_TYPES_H + +#include <drv/ps1/irq.h> + +extern struct drv_ps1_irq_src *drv_ps1_irq_head; + +#endif diff --git a/src/drv/ps1/irq/src/CMakeLists.txt b/src/drv/ps1/irq/src/CMakeLists.txt new file mode 100644 index 0000000..3823f4e --- /dev/null +++ b/src/drv/ps1/irq/src/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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_irq PRIVATE + handler.c + head.c + init.c + set.c +) diff --git a/src/drv/ps1/irq/src/handler.c b/src/drv/ps1/irq/src/handler.c new file mode 100644 index 0000000..0861852 --- /dev/null +++ b/src/drv/ps1/irq/src/handler.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/irq.h> +#include <drv/ps1/irq/routines.h> +#include <drv/ps1/irq/types.h> +#include <drv/ps1/bios.h> +#include <stddef.h> + +void drv_ps1_irq_handler(void) +{ + for (struct drv_ps1_irq_src *s = drv_ps1_irq_head; s; s = s->next) + if (I_STAT->mask & s->mask) + s->fn(); + + ReturnFromException(); +} diff --git a/src/drv/ps1/irq/src/head.c b/src/drv/ps1/irq/src/head.c new file mode 100644 index 0000000..cde1fd8 --- /dev/null +++ b/src/drv/ps1/irq/src/head.c @@ -0,0 +1,22 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/irq.h> +#include <drv/ps1/irq/types.h> + +struct drv_ps1_irq_src *drv_ps1_irq_head; diff --git a/src/drv/ps1/irq/src/init.c b/src/drv/ps1/irq/src/init.c new file mode 100644 index 0000000..9e92b01 --- /dev/null +++ b/src/drv/ps1/irq/src/init.c @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/irq.h> +#include <drv/ps1/irq/routines.h> +#include <drv/ps1/bios.h> +#include <setjmp.h> + +int drv_ps1_irq_init(void) +{ + static jmp_buf jmp; + static char stack[128]; + const int critical = EnterCriticalSection(); + + if (SaveState(jmp)) + drv_ps1_irq_handler(); + + jmp->sp = (unsigned)stack + sizeof stack - 4; + SetCustomExitFromException(jmp); + + if (critical) + ExitCriticalSection(); + + return 0; +} diff --git a/src/drv/ps1/irq/src/set.c b/src/drv/ps1/irq/src/set.c new file mode 100644 index 0000000..35c5ed0 --- /dev/null +++ b/src/drv/ps1/irq/src/set.c @@ -0,0 +1,36 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/irq.h> +#include <drv/ps1/irq/types.h> +#include <drv/ps1/bios.h> + +int drv_ps1_irq_set(struct drv_ps1_irq_src *const src) +{ + if (!drv_ps1_irq_head) + drv_ps1_irq_head = src; + else + for (struct drv_ps1_irq_src *s = drv_ps1_irq_head; s; s = s->next) + if (!s->next) + { + s->next = src; + break; + } + + return 0; +} diff --git a/src/drv/ps1/mc/CMakeLists.txt b/src/drv/ps1/mc/CMakeLists.txt new file mode 100644 index 0000000..ef232ef --- /dev/null +++ b/src/drv/ps1/mc/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..2e90776 --- /dev/null +++ b/src/drv/ps1/mc/include/drv/ps1/mc.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..14606e5 --- /dev/null +++ b/src/drv/ps1/mc/private_include/drv/ps1/mc/types.h @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..ae1378c --- /dev/null +++ b/src/drv/ps1/mc/src/CMakeLists.txt @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..bdf54ff --- /dev/null +++ b/src/drv/ps1/mc/src/free.c @@ -0,0 +1,23 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..88be46a --- /dev/null +++ b/src/drv/ps1/mc/src/init.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..866bf94 --- /dev/null +++ b/src/drv/ps1/mc/src/update.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..eb74091 --- /dev/null +++ b/src/drv/ps1/pad/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..9cc2fc6 --- /dev/null +++ b/src/drv/ps1/pad/include/drv/ps1/pad.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..c164a30 --- /dev/null +++ b/src/drv/ps1/pad/private_include/drv/ps1/pad/types.h @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..bfae1a1 --- /dev/null +++ b/src/drv/ps1/pad/src/CMakeLists.txt @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..1498f2d --- /dev/null +++ b/src/drv/ps1/pad/src/free.c @@ -0,0 +1,23 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..8fe3ccb --- /dev/null +++ b/src/drv/ps1/pad/src/init.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..9c9acfe --- /dev/null +++ b/src/drv/ps1/pad/src/update.c @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..35cb14e --- /dev/null +++ b/src/drv/ps1/private_include/drv/ps1/types.h @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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> +#include <drv/ps1/sio.h> + +struct drv_port +{ + struct drv_ps1_mc *mc; + struct drv_ps1_cd *cd; + struct drv_ps1_pad *pad; + struct drv_ps1_sio *sio; +}; + +#endif diff --git a/src/drv/ps1/rcnt/CMakeLists.txt b/src/drv/ps1/rcnt/CMakeLists.txt new file mode 100644 index 0000000..f5b5171 --- /dev/null +++ b/src/drv/ps1/rcnt/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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_irq drv_ps1_event) 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..831012c --- /dev/null +++ b/src/drv/ps1/rcnt/include/drv/ps1/rcnt.h @@ -0,0 +1,45 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..a6c9750 --- /dev/null +++ b/src/drv/ps1/rcnt/private_include/drv/ps1/rcnt/regs.h @@ -0,0 +1,36 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..4e8eb88 --- /dev/null +++ b/src/drv/ps1/rcnt/src/CMakeLists.txt @@ -0,0 +1,19 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..0c4327c --- /dev/null +++ b/src/drv/ps1/rcnt/src/init.c @@ -0,0 +1,62 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/event.h> +#include <drv/ps1/irq.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 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; + } + + ExitCriticalSection(); + + const int event = drv_ps1_event_open(class, SPEC_INTERRUPTED, + MODE_EXECUTE, f); + + if (event == -1) + return -1; + + drv_ps1_event_enable(event); + return 0; +} diff --git a/src/drv/ps1/sio/CMakeLists.txt b/src/drv/ps1/sio/CMakeLists.txt new file mode 100644 index 0000000..f382e08 --- /dev/null +++ b/src/drv/ps1/sio/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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_sio) +add_subdirectory(src) +target_include_directories(drv_ps1_sio PUBLIC include PRIVATE private_include) +target_link_libraries(drv_ps1_sio + PUBLIC c + PRIVATE drv drv_ps1_bios drv_ps1_cpu drv_ps1_irq) diff --git a/src/drv/ps1/sio/include/drv/ps1/sio.h b/src/drv/ps1/sio/include/drv/ps1/sio.h new file mode 100644 index 0000000..3fabadd --- /dev/null +++ b/src/drv/ps1/sio/include/drv/ps1/sio.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_SIO_H +#define DRV_PS1_SIO_H + +#include <drv/event.h> + +struct drv_ps1_sio *drv_ps1_sio_init(const struct drv_event *ev); +int drv_ps1_sio_update(struct drv_ps1_sio *sio); +void drv_ps1_sio_free(struct drv_ps1_sio *sio); + +#endif diff --git a/src/drv/ps1/sio/private_include/drv/ps1/sio/ops.h b/src/drv/ps1/sio/private_include/drv/ps1/sio/ops.h new file mode 100644 index 0000000..a481fa9 --- /dev/null +++ b/src/drv/ps1/sio/private_include/drv/ps1/sio/ops.h @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_SIO_OPS_H +#define DRV_PS1_SIO_OPS_H + +#include <drv/event.h> +#include <sys/types.h> + +int drv_ps1_sio_read(void *buf, size_t n, off_t offset, + const struct drv_event_done *done, void *args); +int drv_ps1_sio_read_nb(void *buf, size_t n, void *args); +int drv_ps1_sio_write(const void *buf, size_t n, + const struct drv_event_done *done, void *args); + +#endif diff --git a/src/drv/ps1/sio/private_include/drv/ps1/sio/regs.h b/src/drv/ps1/sio/private_include/drv/ps1/sio/regs.h new file mode 100644 index 0000000..16b2bca --- /dev/null +++ b/src/drv/ps1/sio/private_include/drv/ps1/sio/regs.h @@ -0,0 +1,136 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_SIO_REGS_H +#define DRV_PS1_SIO_REGS_H + +#include <stdint.h> + +struct sio_tx_data +{ + uint32_t value :8, :24; +}; + +struct sio_rx_data +{ + uint8_t values[4]; +}; + +union sio_stat +{ + struct + { + uint32_t + tx_ready_started :1, + rx_fifo_not_empty :1, + tx_ready_finished :1, + rx_parity_error :1, + rx_fifo_overrun :1, + rx_bad_stp :1, + rx_inverted :1, + dsr :1, + cts :1, + irqreq :1, + :1, + baudrate :15, :6; + } bits; + + uint32_t mask; +}; + +union sio_mode +{ + struct + { + uint16_t + baudrate_mul :2, + len :2, + parity_en :1, + parity_odd :1, + stplen :2, + :8; + } bits; + + uint16_t mask; +}; + +union sio_ctrl +{ + struct + { + uint16_t + tx_en :1, + dtr :1, + rx_en :1, + tx_invert :1, + ack :1, + rts :1, + reset :1, + :1, + rx_int_mode :2, + tx_int_en :1, + rx_int_en :1, + dsr_int_en :1, + :3; + } bits; + + uint16_t mask; +}; + +enum +{ + SIO_CTRL_RX_INT_1, + SIO_CTRL_RX_INT_2, + SIO_CTRL_RX_INT_3, + SIO_CTRL_RX_INT_4 +}; + +enum +{ + SIO_MODE_FACTOR_STOP, + SIO_MODE_FACTOR_MUL1, + SIO_MODE_FACTOR_MUL16, + SIO_MODE_FACTOR_MUL64 +}; + +enum +{ + SIO_MODE_LEN_5, + SIO_MODE_LEN_6, + SIO_MODE_LEN_7, + SIO_MODE_LEN_8 +}; + +enum +{ + SIO_MODE_STP_RESERVED, + SIO_MODE_STP_1, + SIO_MODE_STP_1_5, + SIO_MODE_STP_2, +}; + +#define SIO_BASE 0x1f801050 +#define SIO_REG(n) (SIO_BASE + n) +#define SIO_TX_DATA ((volatile struct sio_tx_data *)SIO_REG(0)) +#define SIO_RX_DATA ((const volatile struct sio_rx_data *)SIO_REG(0)) +#define SIO_STAT ((const volatile union sio_stat *)SIO_REG(4)) +#define SIO_MODE ((volatile union sio_mode *)SIO_REG(8)) +#define SIO_CTRL ((volatile union sio_ctrl *)SIO_REG(10)) +#define SIO_BAUD (*(volatile uint16_t *)SIO_REG(14)) + +#endif diff --git a/src/drv/ps1/sio/private_include/drv/ps1/sio/routines.h b/src/drv/ps1/sio/private_include/drv/ps1/sio/routines.h new file mode 100644 index 0000000..f5b97da --- /dev/null +++ b/src/drv/ps1/sio/private_include/drv/ps1/sio/routines.h @@ -0,0 +1,27 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_SIO_ROUTINES_H +#define DRV_PS1_SIO_ROUTINES_H + +#include <drv/ps1/sio/types.h> + +int drv_ps1_sio_irq(void); +int drv_ps1_sio_next(struct sio_fifo *f); + +#endif diff --git a/src/drv/ps1/sio/private_include/drv/ps1/sio/types.h b/src/drv/ps1/sio/private_include/drv/ps1/sio/types.h new file mode 100644 index 0000000..87dd412 --- /dev/null +++ b/src/drv/ps1/sio/private_include/drv/ps1/sio/types.h @@ -0,0 +1,65 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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_SIO_TYPES_H +#define DRV_PS1_SIO_TYPES_H + +#include <drv/event.h> +#include <stdbool.h> + +struct sio_req +{ + union + { + struct sio_req_r + { + void *buf; + size_t n; + } r; + + struct sio_req_w + { + const void *buf; + size_t n; + } w; + } u; + + int (*f)(void); + struct drv_event_done done; + struct sio_req *next; +}; + +struct sio_fifo +{ + char buf[192]; + size_t proc, pend; + struct sio_req *head, *tail; + int (*next)(void); +}; + +struct drv_ps1_sio +{ + bool init; + int event; + struct sio_fifo rx, tx; + struct drv_event ev; +}; + +extern struct drv_ps1_sio drv_ps1_sio; + +#endif diff --git a/src/drv/ps1/sio/src/CMakeLists.txt b/src/drv/ps1/sio/src/CMakeLists.txt new file mode 100644 index 0000000..1bcf5cf --- /dev/null +++ b/src/drv/ps1/sio/src/CMakeLists.txt @@ -0,0 +1,29 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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_sio PRIVATE + free.c + globals.c + init.c + irq.c + next.c + read.c + read_nb.c + update.c + write.c +) + +target_link_libraries(drv_ps1_sio PRIVATE kprintf) diff --git a/src/drv/ps1/sio/src/free.c b/src/drv/ps1/sio/src/free.c new file mode 100644 index 0000000..5c506d0 --- /dev/null +++ b/src/drv/ps1/sio/src/free.c @@ -0,0 +1,23 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/sio.h> + +void drv_ps1_sio_free(struct drv_ps1_sio *const sio) +{ +} diff --git a/src/drv/ps1/sio/src/globals.c b/src/drv/ps1/sio/src/globals.c new file mode 100644 index 0000000..35c72b8 --- /dev/null +++ b/src/drv/ps1/sio/src/globals.c @@ -0,0 +1,21 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/sio/types.h> + +struct drv_ps1_sio drv_ps1_sio; diff --git a/src/drv/ps1/sio/src/init.c b/src/drv/ps1/sio/src/init.c new file mode 100644 index 0000000..6bf44fc --- /dev/null +++ b/src/drv/ps1/sio/src/init.c @@ -0,0 +1,70 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/sio.h> +#include <drv/ps1/sio/ops.h> +#include <drv/ps1/sio/regs.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/cpu.h> +#include <drv/ps1/irq.h> +#include <drv/event.h> + +struct drv_ps1_sio *drv_ps1_sio_init(const struct drv_event *const ev) +{ + const unsigned long baudrate = 115200ul; + + SIO_CTRL->bits.reset = 1; + SIO_BAUD = DRV_PS1_CPU_F / (16 * baudrate); + SIO_MODE->mask = (const union sio_mode) + { + .bits = + { + .baudrate_mul = SIO_MODE_FACTOR_MUL16, + .stplen = SIO_MODE_STP_1, + .len = SIO_MODE_LEN_8 + } + }.mask; + + SIO_CTRL->mask = (const union sio_ctrl) + { + .bits = + { + .rx_int_mode = SIO_CTRL_RX_INT_1, + .rx_int_en = 1, + .tx_en = 1, + .rx_en = 1, + .rts = 1, + .dtr = 1 + } + }.mask; + + static struct drv_ps1_irq_src src = + { + .mask = 1 << IRQ_SIO, + .fn = drv_ps1_sio_irq + }; + + if (drv_ps1_irq_set(&src)) + return NULL; + + I_MASK->bits.sio = 1; + drv_ps1_sio.ev = *ev; + return &drv_ps1_sio; +} diff --git a/src/drv/ps1/sio/src/irq.c b/src/drv/ps1/sio/src/irq.c new file mode 100644 index 0000000..5a19d83 --- /dev/null +++ b/src/drv/ps1/sio/src/irq.c @@ -0,0 +1,71 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/sio.h> +#include <drv/ps1/sio/ops.h> +#include <drv/ps1/sio/regs.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/cpu.h> +#include <drv/ps1/irq.h> +#include <drv/event.h> + +int irq_sio_overrun; + +static int read_rx(struct sio_fifo *const f) +{ + const unsigned char v = *SIO_RX_DATA->values; + size_t n = f->pend + 1; + + if (n >= sizeof f->buf) + n = 0; + + if (n == f->proc) + { + irq_sio_overrun = 1; + return -1; + } + + f->buf[f->pend = n] = v; + return 0; +} + +volatile unsigned sio_read; +volatile int sw_overrun; + +int drv_ps1_sio_irq(void) +{ + SIO_CTRL->bits.rts = 0; + + while (SIO_STAT->bits.rx_fifo_not_empty) + { + if (read_rx(&drv_ps1_sio.rx)) + { + sw_overrun = 1; + break; + } + + sio_read++; + } + + SIO_CTRL->bits.rts = 1; + I_STAT->bits.sio = 0; + SIO_CTRL->bits.ack = 1; + return 0; +} diff --git a/src/drv/ps1/sio/src/next.c b/src/drv/ps1/sio/src/next.c new file mode 100644 index 0000000..4c330ab --- /dev/null +++ b/src/drv/ps1/sio/src/next.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/sio.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <stddef.h> +#include <stdlib.h> + +int drv_ps1_sio_next(struct sio_fifo *const f) +{ + struct sio_req *const next = f->head->next; + + free(f->head); + + f->next = next ? next->f : NULL; + f->head = next; + return 0; +} diff --git a/src/drv/ps1/sio/src/read.c b/src/drv/ps1/sio/src/read.c new file mode 100644 index 0000000..e13ad29 --- /dev/null +++ b/src/drv/ps1/sio/src/read.c @@ -0,0 +1,125 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/sio/ops.h> +#include <drv/ps1/sio/regs.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/irq.h> +#include <drv/event.h> +#include <kprintf.h> +#include <sys/types.h> +#include <errno.h> +#include <stdlib.h> + +static int load(void); + +static int check(void) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->rx; + struct sio_req *const req = f->head; + struct sio_req_r *const r = &req->u.r; + + if (!r->n) + { + const struct drv_event_done *const d = &req->done; + + if (d->f && d->f(SUCCESS, d->args)) + return -1; + + return drv_ps1_sio_next(f); + } + + f->next = load; + return 0; +} + +static void read_fifo(struct drv_ps1_sio *const s) +{ + struct sio_fifo *const f = &s->rx; + struct sio_req *const req = f->head; + struct sio_req_r *const r = &req->u.r; + char *p = r->buf; + + I_MASK->bits.sio = 0; + SIO_CTRL->bits.rts = 0; + + while (r->n) + { + if (f->pend == f->proc) + break; + + size_t n = f->proc + 1; + + if (n >= sizeof f->buf) + n = 0; + + *p++ = f->buf[f->proc = n]; + r->buf = p; + r->n--; + } + + SIO_CTRL->bits.rts = 1; + I_MASK->bits.sio = 1; +} + +static int load(void) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->rx; + struct sio_req_r *const r = &f->head->u.r; + + read_fifo(s); + + if (!r->n) + f->next = check; + + return 0; +} + +int drv_ps1_sio_read(void *const buf, const size_t n, const off_t offset, + const struct drv_event_done *const done, void *const args) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->rx; + struct sio_req *const req = malloc(sizeof *req); + + if (!req) + return -1; + + *req = (const struct sio_req) + { + .f = load, + .done = *done, + .u.r = + { + .buf = buf, + .n = n + } + }; + + if (!f->head) + f->head = req; + else + f->tail->next = req; + + f->tail = req; + return 0; +} diff --git a/src/drv/ps1/sio/src/read_nb.c b/src/drv/ps1/sio/src/read_nb.c new file mode 100644 index 0000000..755c5cf --- /dev/null +++ b/src/drv/ps1/sio/src/read_nb.c @@ -0,0 +1,61 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/sio/ops.h> +#include <drv/ps1/sio/regs.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/ps1/irq.h> +#include <drv/ps1/bios.h> +#include <drv/event.h> +#include <kprintf.h> +#include <sys/types.h> + +static int read_fifo(char *buf, size_t n) +{ + int ret = 0; + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->rx; + + I_MASK->bits.sio = 0; + SIO_CTRL->bits.rts = 0; + + while (n) + { + if (f->pend == f->proc) + break; + + size_t m = f->proc + 1; + + if (m >= sizeof f->buf) + m = 0; + + *buf++ = f->buf[f->proc = m]; + n--; + ret++; + } + + SIO_CTRL->bits.rts = 1; + I_MASK->bits.sio = 1; + return ret; +} + +int drv_ps1_sio_read_nb(void *const buf, const size_t n, void *const args) +{ + return read_fifo(buf, n); +} diff --git a/src/drv/ps1/sio/src/update.c b/src/drv/ps1/sio/src/update.c new file mode 100644 index 0000000..eac875c --- /dev/null +++ b/src/drv/ps1/sio/src/update.c @@ -0,0 +1,98 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/sio.h> +#include <drv/ps1/sio/ops.h> +#include <drv/ps1/sio/regs.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/event.h> +#include <kprintf.h> +#include <stddef.h> +#include <stdbool.h> + +static int init(struct drv_ps1_sio *const s) +{ + if (s->init) + return 0; + + const struct drv_event *const ev = &s->ev; + static const struct drv_event_ops ops = + { + .read = drv_ps1_sio_read, + .read_nb = drv_ps1_sio_read_nb, + .write = drv_ps1_sio_write + }; + + if (ev->status("ttyS0", &ops, true, 0660, ev->args)) + return -1; + + s->init = true; + return 0; +} + +static int rx(struct drv_ps1_sio *const s) +{ + struct sio_fifo *const f = &s->rx; + + if (f->next) + return f->next(); + else if (f->head) + f->next = f->head->f; + + return 0; +} + +static void write_tx(struct sio_fifo *const f) +{ + if (f->proc == f->pend) + return; + + size_t n = f->proc + 1; + + if (n >= sizeof f->buf) + n = 0; + + SIO_TX_DATA->value = f->buf[f->proc = n]; +} + +static int tx(struct drv_ps1_sio *const s) +{ + struct sio_fifo *const f = &s->tx; + + if (SIO_STAT->bits.tx_ready_started) + write_tx(f); + + if (f->next) + return f->next(); + else if (f->head) + f->next = f->head->f; + + return 0; +} + +int drv_ps1_sio_update(struct drv_ps1_sio *const s) +{ + if (SIO_STAT->bits.rx_fifo_overrun) + SIO_CTRL->bits.ack = 1; + + if (init(s) || rx(s) || tx(s)) + return -1; + + return 0; +} diff --git a/src/drv/ps1/sio/src/write.c b/src/drv/ps1/sio/src/write.c new file mode 100644 index 0000000..942456f --- /dev/null +++ b/src/drv/ps1/sio/src/write.c @@ -0,0 +1,117 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/sio/ops.h> +#include <drv/ps1/sio/routines.h> +#include <drv/ps1/sio/types.h> +#include <drv/ps1/bios.h> +#include <drv/event.h> +#include <kprintf.h> +#include <sys/types.h> +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> + +static int store(void); + +static void write_fifo(struct drv_ps1_sio *const s) +{ + struct sio_fifo *const f = &s->tx; + struct sio_req *const r = f->head; + struct sio_req_w *const w = &r->u.w; + const char *p = w->buf; + + while (w->n) + { + size_t n = f->pend + 1; + + if (n >= sizeof f->buf) + n = 0; + else if (n == f->proc) + break; + + f->buf[f->pend = n] = *p++; + w->buf = p; + w->n--; + } +} + +static int check(void) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->tx; + struct sio_req *const r = f->head; + struct sio_req_w *const w = &r->u.w; + + if (!w->n) + { + const struct drv_event_done *const d = &r->done; + + if (d->f && d->f(SUCCESS, d->args)) + return -1; + + return drv_ps1_sio_next(f); + } + + f->next = store; + return 0; +} + +static int store(void) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->tx; + struct sio_req_w *const w = &f->head->u.w; + + write_fifo(s); + + if (!w->n) + f->next = check; + + return 0; +} + +int drv_ps1_sio_write(const void *const buf, const size_t n, + const struct drv_event_done *const done, void *const args) +{ + struct drv_ps1_sio *const s = &drv_ps1_sio; + struct sio_fifo *const f = &s->tx; + struct sio_req *const req = malloc(sizeof *req); + + if (!req) + return -1; + + *req = (const struct sio_req) + { + .f = store, + .done = *done, + .u.w = + { + .buf = buf, + .n = n + } + }; + + if (!f->head) + f->head = req; + else + f->tail->next = req; + + f->tail = req; + return 0; +} diff --git a/src/drv/ps1/src/CMakeLists.txt b/src/drv/ps1/src/CMakeLists.txt new file mode 100644 index 0000000..34042e3 --- /dev/null +++ b/src/drv/ps1/src/CMakeLists.txt @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..62be1b1 --- /dev/null +++ b/src/drv/ps1/src/free.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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 <drv/ps1/sio.h> + +void drv_ps1_free(struct drv_port *const p) +{ + drv_ps1_mc_free(p->mc); + drv_ps1_cd_free(p->cd); + drv_ps1_pad_free(p->pad); + drv_ps1_sio_free(p->sio); +} diff --git a/src/drv/ps1/src/init.c b/src/drv/ps1/src/init.c new file mode 100644 index 0000000..8ee92a6 --- /dev/null +++ b/src/drv/ps1/src/init.c @@ -0,0 +1,59 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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 <drv/ps1/sio.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; + struct drv_ps1_sio *sio = NULL; + + if (!(mc = drv_ps1_mc_init(ev)) + || !(cd = drv_ps1_cd_init(ev)) + || !(pad = drv_ps1_pad_init(ev)) + || !(sio = drv_ps1_sio_init(ev)) + || !(ret = malloc(sizeof *ret))) + goto failure; + + *ret = (const struct drv_port) + { + .mc = mc, + .cd = cd, + .pad = pad, + .sio = sio + }; + + return ret; + +failure: + drv_ps1_mc_free(mc); + drv_ps1_cd_free(cd); + drv_ps1_pad_free(pad); + drv_ps1_sio_free(sio); + free(mc); + return NULL; +} diff --git a/src/drv/ps1/src/update.c b/src/drv/ps1/src/update.c new file mode 100644 index 0000000..49b22bb --- /dev/null +++ b/src/drv/ps1/src/update.c @@ -0,0 +1,35 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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 <drv/ps1/sio.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) + || drv_ps1_sio_update(p->sio)) + 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..93c0143 --- /dev/null +++ b/src/drv/ps1/time/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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_irq 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..f644b59 --- /dev/null +++ b/src/drv/ps1/time/include/drv/ps1/time.h @@ -0,0 +1,24 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..2e673fb --- /dev/null +++ b/src/drv/ps1/time/private_include/drv/ps1/time/types.h @@ -0,0 +1,26 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..d8ebf38 --- /dev/null +++ b/src/drv/ps1/time/src/CMakeLists.txt @@ -0,0 +1,23 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..de69ff5 --- /dev/null +++ b/src/drv/ps1/time/src/getres.c @@ -0,0 +1,34 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..0fdbfea --- /dev/null +++ b/src/drv/ps1/time/src/gettime.c @@ -0,0 +1,38 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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 <drv/ps1/irq.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; + } + + I_MASK->bits.tmr2 = 0; + *ts = drv_ps1_time; + I_MASK->bits.tmr2 = 1; + 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..2f53665 --- /dev/null +++ b/src/drv/ps1/time/src/globals.c @@ -0,0 +1,22 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..f2ac5fe --- /dev/null +++ b/src/drv/ps1/time/src/settime.c @@ -0,0 +1,37 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..494d8ed --- /dev/null +++ b/src/drv/ps1/time/src/tick.c @@ -0,0 +1,42 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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/irq.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 = 0; + return ret; +} diff --git a/src/drv/src/CMakeLists.txt b/src/drv/src/CMakeLists.txt new file mode 100644 index 0000000..e567c1c --- /dev/null +++ b/src/drv/src/CMakeLists.txt @@ -0,0 +1,22 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..2c324c0 --- /dev/null +++ b/src/drv/src/free.c @@ -0,0 +1,31 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..4b89f15 --- /dev/null +++ b/src/drv/src/init.c @@ -0,0 +1,62 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..d52df3d --- /dev/null +++ b/src/drv/src/tree.c @@ -0,0 +1,51 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..268c2b6 --- /dev/null +++ b/src/drv/src/update.c @@ -0,0 +1,32 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..ee14015 --- /dev/null +++ b/src/drv/tty/CMakeLists.txt @@ -0,0 +1,20 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..27804bf --- /dev/null +++ b/src/drv/tty/include/drv/tty.h @@ -0,0 +1,28 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..a36d68e --- /dev/null +++ b/src/drv/tty/private_include/drv/tty/font.h @@ -0,0 +1,29 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..b50b00a --- /dev/null +++ b/src/drv/tty/private_include/drv/tty/ops.h @@ -0,0 +1,30 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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..38a1108 --- /dev/null +++ b/src/drv/tty/private_include/drv/tty/types.h @@ -0,0 +1,40 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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; + size_t len; +}; + +struct drv_port +{ + bool init; + struct row *rows, *first_row, *last_row, *proc_row; + size_t nrows, ncolumns, last_column, last_proc_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..096b685 --- /dev/null +++ b/src/drv/tty/src/CMakeLists.txt @@ -0,0 +1,27 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..66d5cb4 --- /dev/null +++ b/src/drv/tty/src/free.c @@ -0,0 +1,39 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..53299f4 --- /dev/null +++ b/src/drv/tty/src/init.c @@ -0,0 +1,58 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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..c07a45f --- /dev/null +++ b/src/drv/tty/src/ps1/CMakeLists.txt @@ -0,0 +1,19 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You 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..b7dd03b --- /dev/null +++ b/src/drv/tty/src/ps1/ttyfont_tim.c @@ -0,0 +1,801 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You 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, 0x00, 0x00, 0xff, 0x7f, + 0x2c, 0x34, 0x3e, 0x26, 0xdc, 0x01, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x40, 0x5f, 0x1f, 0x36, 0x9c, 0x03, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x80, 0x00, 0x80, 0x0c, 0x24, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, + 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x01, 0x01, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x10, 0x11, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, + 0x11, 0x01, 0x00, 0x00, 0x00, 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x10, 0x10, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x10, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x10, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x10, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x10, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x10, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x10, 0x01, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x01, 0x10, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x10, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x01, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x10, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x10, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x11, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x11, 0x10, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +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..d1f835a --- /dev/null +++ b/src/drv/tty/src/setdim.c @@ -0,0 +1,62 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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 / 10, rows = h / 16; + 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->proc_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.backup.c b/src/drv/tty/src/update.backup.c new file mode 100644 index 0000000..d072977 --- /dev/null +++ b/src/drv/tty/src/update.backup.c @@ -0,0 +1,125 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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) +{ + if (p->init) + return 0; + + const struct drv_event *const ev = &p->ev; + const struct drv_event_ops ops = + { + .write = drv_tty_write, + .args = p + }; + + if (ev->status("tty", &ops, true, 0666, ev->args)) + return -1; + + p->init = true; + return 0; +} + +static short get_y(const struct drv_port *const p) +{ + const ptrdiff_t r = p->proc_row - p->first_row; + + if (r >= 0) + return r * 16; + + return (((p->rows + p->nrows) - p->first_row) + + (p->proc_row - p->rows)) * 16; +} + +static int prepare(struct drv_port *const p) +{ + struct row *r = p->proc_row; + + if (r == p->last_row) + return 0; + else if (!p->last_proc_column) + { + struct gfx_rect *const rect = gfx_rect_get(); + const short y = get_y(p); + + if (!rect) + return 0; + + gfx_rect_init(rect); + rect->y = y; + rect->w = screen_w; + rect->h = 16; + + if (gfx_rect_sort(rect)) + return -1; + } + + const char c = r->columns[p->last_proc_column]; + + if (c != ' ') + { + struct gfx_sprite *const s = gfx_sprite_get(); + + if (!s || gfx_sprite_clone(&ttyfont_spr, s)) + return 0; + + const short x = p->last_proc_column * 10, y = get_y(p); + const char ch = c - ' '; + const short u = (12 * ch) % ttyfont_spr.w; + const short v = 16 * ((12 * ch) / ttyfont_spr.w); + + /* TODO: replace hardcoded values */ + s->x = x; + s->y = y; + s->w = 12; + s->h = 16; + s->u += u; + s->v += v; + + if (gfx_sprite_sort(s)) + return -1; + } + + if (++p->last_proc_column >= r->len) + { + if (++r - p->rows >= p->nrows) + r = p->rows; + + p->last_proc_column = 0; + } + + p->proc_row = r; + return 0; +} + +int drv_tty_update(struct drv_port *const p) +{ + if (init(p) || prepare(p)) + return -1; + + return 0; +} diff --git a/src/drv/tty/src/update.c b/src/drv/tty/src/update.c new file mode 100644 index 0000000..7c01678 --- /dev/null +++ b/src/drv/tty/src/update.c @@ -0,0 +1,126 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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) +{ + if (p->init) + return 0; + + const struct drv_event *const ev = &p->ev; + const struct drv_event_ops ops = + { + .write = drv_tty_write, + .args = p + }; + + if (ev->status("tty", &ops, true, 0666, ev->args)) + return -1; + + p->init = true; + return 0; +} + +static short get_y(const struct drv_port *const p) +{ + const ptrdiff_t r = p->proc_row - p->first_row; + + if (r >= 0) + return r * 16; + + return (((p->rows + p->nrows) - p->first_row) + + (p->proc_row - p->rows)) * 16; +} + +static int prepare(struct drv_port *const p) +{ + struct row *r = p->proc_row; + + if (r == p->last_row) + return 0; + + struct gfx_rect *const rect = gfx_rect_get(); + const short y = get_y(p); + short x = 0; + + if (!rect) + return 0; + + gfx_rect_init(rect); + rect->y = y; + rect->w = screen_w; + rect->h = 16; + + if (gfx_rect_sort(rect)) + return -1; + + /* TODO: this is a trick to avoid having half-rendered lines. */ + struct gfx_sprite *sprites[64]; + + for (size_t i = 0; i < sizeof sprites / sizeof *sprites; i++) + sprites[i] = gfx_sprite_get(); + + for (const char *c = r->columns; + *c && c - r->columns < p->ncolumns; c++, x += 10) + { + struct gfx_sprite *const s = sprites[c - r->columns]; + + if (*c == ' ') + continue; + + const char ch = *c - ' '; + const short u = (12 * ch) % ttyfont_spr.w; + const short v = 16 * ((12 * ch) / ttyfont_spr.w); + + if (!s || gfx_sprite_clone(&ttyfont_spr, s)) + return 0; + + /* TODO: replace hardcoded values */ + s->x = x; + s->y = y; + s->w = 12; + s->h = 16; + s->u += u; + s->v += v; + + if (gfx_sprite_sort(s)) + return -1; + } + + if (++r - p->rows >= p->nrows) + r = p->rows; + + p->proc_row = r; + return 0; +} + +int drv_tty_update(struct drv_port *const p) +{ + if (init(p) || prepare(p)) + return -1; + + return 0; +} diff --git a/src/drv/tty/src/write.c b/src/drv/tty/src/write.c new file mode 100644 index 0000000..d4a988d --- /dev/null +++ b/src/drv/tty/src/write.c @@ -0,0 +1,70 @@ +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should 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++) + { + struct row *const r = p->last_row; + char *const col = &r->columns[p->last_column]; + + if (*s == '\r') + { + *col = '\0'; + p->last_column = r->len = 0; + } + else + { + if (*s != '\n') + { + *col = *s; + r->len++; + } + else + *col = '\0'; + + if (*s == '\n' || ++p->last_column >= p->ncolumns) + { + if (++p->last_row - p->rows >= p->nrows) + p->last_row = p->rows; + + if (p->last_row == p->first_row) + { + if (++p->first_row - p->rows >= p->nrows) + p->first_row = p->rows; + + p->proc_row = p->first_row; + } + + p->last_column = 0; + } + } + } + + return d->f(SUCCESS, d->args); +} |
