diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-07-07 13:22:53 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-07-25 14:16:41 +0200 |
| commit | 14f60e4fd65c42f126eaee7e09cb4251c167c6ed (patch) | |
| tree | 313b5e16d7d99cf1518c953e2efe5e5fc920dfbf /src/gfx/ps1 | |
| parent | 48a61c16eaa6dcfc75d00dba302537ce1492db98 (diff) | |
| download | wnix-tty.tar.gz | |
wiptty
Diffstat (limited to 'src/gfx/ps1')
| -rw-r--r-- | src/gfx/ps1/CMakeLists.txt | 40 | ||||
| -rw-r--r-- | src/gfx/ps1/include/gfx/port.h | 126 | ||||
| -rw-r--r-- | src/gfx/ps1/private_include/gfx/private.h | 19 | ||||
| -rw-r--r-- | src/gfx/ps1/src/4line.c | 15 | ||||
| -rw-r--r-- | src/gfx/ps1/src/CMakeLists.txt | 32 | ||||
| -rw-r--r-- | src/gfx/ps1/src/add_to_list.c | 39 | ||||
| -rw-r--r-- | src/gfx/ps1/src/deinit.c | 24 | ||||
| -rw-r--r-- | src/gfx/ps1/src/draw.c | 70 | ||||
| -rw-r--r-- | src/gfx/ps1/src/env.c | 71 | ||||
| -rw-r--r-- | src/gfx/ps1/src/heap.c | 73 | ||||
| -rw-r--r-- | src/gfx/ps1/src/init.c | 153 | ||||
| -rw-r--r-- | src/gfx/ps1/src/quad.c | 24 | ||||
| -rw-r--r-- | src/gfx/ps1/src/ready.c | 27 | ||||
| -rw-r--r-- | src/gfx/ps1/src/rect.c | 25 | ||||
| -rw-r--r-- | src/gfx/ps1/src/sort.c | 73 | ||||
| -rw-r--r-- | src/gfx/ps1/src/sprite/CMakeLists.txt | 22 | ||||
| -rw-r--r-- | src/gfx/ps1/src/sprite/clone.c | 26 | ||||
| -rw-r--r-- | src/gfx/ps1/src/sprite/free.c | 23 | ||||
| -rw-r--r-- | src/gfx/ps1/src/sprite/load.c | 191 | ||||
| -rw-r--r-- | src/gfx/ps1/src/sprite/sort.c | 26 | ||||
| -rw-r--r-- | src/gfx/ps1/src/swapenvs.c | 58 | ||||
| -rw-r--r-- | src/gfx/ps1/src/vblank.c | 21 |
22 files changed, 1178 insertions, 0 deletions
diff --git a/src/gfx/ps1/CMakeLists.txt b/src/gfx/ps1/CMakeLists.txt new file mode 100644 index 0000000..1de20a7 --- /dev/null +++ b/src/gfx/ps1/CMakeLists.txt @@ -0,0 +1,40 @@ +# wanix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_subdirectory(src) +target_include_directories(gfx PUBLIC include PRIVATE private_include) +target_link_libraries(gfx PRIVATE + drv_ps1_bios + drv_ps1_dma + drv_ps1_interrupt + drv_ps1_gpu +) + +set(modes VMODE_PAL VMODE_NTSC) + +if(VIDEO_MODE) + if(NOT "${VIDEO_MODE}" IN_LIST modes) + message(FATAL_ERROR "Invalid video mode ${VIDEO_MODE}. Available options:\n" + "${modes}\n" + "Run CMake again using one of the available video modes e.g.: cmake .. -DVIDEO_MODE=VMODE_PAL") + endif() + + target_compile_definitions(gfx PRIVATE VIDEO_MODE=${VIDEO_MODE}) +else() + message(FATAL_ERROR "Please define video mode. Available options:\n" + "${modes}\n" + "Run CMake again using one of the available video modes e.g.: cmake .. -DVIDEO_MODE=VMODE_PAL") +endif() diff --git a/src/gfx/ps1/include/gfx/port.h b/src/gfx/ps1/include/gfx/port.h new file mode 100644 index 0000000..2e609d1 --- /dev/null +++ b/src/gfx/ps1/include/gfx/port.h @@ -0,0 +1,126 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef GFX_PS1_H +#define GFX_PS1_H + +#include <stdint.h> + +union gfx_common +{ + struct + { + uint32_t tpagex :4, tpagey :1, stp :2, bpp :2, dither :1, + draw_to_disp :1, disable :1, xflip :1, yflip :1, :10; + uint8_t cmd; + } f; + + uint32_t mask; +}; + +union gfx_sznext +{ + struct + { + uint32_t next :24, sz :8; + } f; + + uint32_t cmd_next; +}; + +struct gfx_sprite +{ + union gfx_sznext sznext; + union gfx_common common; + uint8_t r, g, b; + uint8_t cmd; + int16_t x, y; + uint8_t u, v; + uint16_t clutid; + uint16_t w, h; +}; + +struct quad +{ + union gfx_sznext sznext; + uint8_t r, g, b; + uint8_t cmd; + int16_t x0, y0; + uint8_t u0, v0; + uint16_t clutid; + int16_t x1, y1; + uint8_t u1, v1; + + union + { + struct + { + /* 0-8 Same as GP0(E1h).Bit0-8. */ + uint16_t lb :9; + uint16_t :2; + /* 11 Same as GP0(E1h).Bit11. */ + uint16_t hb :1; + uint16_t :4; + } bit; + + uint16_t mask; + } tpage; + + int16_t x2, y2; + uint8_t u2, v2; + uint16_t :16; + int16_t x3, y3; + uint8_t u3, v3; + uint16_t :16; +}; + +struct gfx_rect +{ + union gfx_sznext sznext; + union gfx_common common; + uint8_t r, g, b; + uint8_t cmd; + int16_t x, y; + uint16_t w, h; +}; + +struct stp_4line +{ + union gfx_sznext sznext; + union gfx_common common; + uint8_t r, g, b; + uint8_t cmd; + int16_t x, y; + + struct stp_4line_vtx + { + uint32_t r :8, g :8, b :8, :8; + int16_t x, y; + } vertices[4]; + + uint32_t end; +}; + +void gfx_add_to_list(union gfx_sznext *p); +void *gfx_heap_top(void); +struct gfx_sprite *gfx_sprite_get(void); +struct quad *quad_get(void); +struct gfx_rect *rect_get(void); +struct stp_4line *stp_4line_get(void); + +#endif diff --git a/src/gfx/ps1/private_include/gfx/private.h b/src/gfx/ps1/private_include/gfx/private.h new file mode 100644 index 0000000..72d8f39 --- /dev/null +++ b/src/gfx/ps1/private_include/gfx/private.h @@ -0,0 +1,19 @@ +#ifndef GFX_PS1_PRIVATE_H +#define GFX_PS1_PRIVATE_H + +#include <gfx/gfx.h> + +enum +{ + SCREEN_W = 640, + SCREEN_H = 480 +}; + +void gfx_swapheap(void); +void gfx_initenvs(void); +void gfx_swapbuffers(void); +void gfx_swapenvs(void); + +extern int gfx_vblank_ev; + +#endif diff --git a/src/gfx/ps1/src/4line.c b/src/gfx/ps1/src/4line.c new file mode 100644 index 0000000..766eb2d --- /dev/null +++ b/src/gfx/ps1/src/4line.c @@ -0,0 +1,15 @@ +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <psxgpu.h> +#include <stdint.h> +#include <string.h> + +void stp_4line_init(struct stp_4line *const l) +{ + memset(l, 0, sizeof *l); + l->sznext.f.sz = (sizeof *l - sizeof l->sznext) / sizeof (uint32_t); + l->common.f.cmd = DRAW_MODE; + l->cmd = 0x5A; + enum {TERMINATION_CODE = 0x55555555}; + l->end = TERMINATION_CODE; +} diff --git a/src/gfx/ps1/src/CMakeLists.txt b/src/gfx/ps1/src/CMakeLists.txt new file mode 100644 index 0000000..418bd3b --- /dev/null +++ b/src/gfx/ps1/src/CMakeLists.txt @@ -0,0 +1,32 @@ +# wanix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(gfx PRIVATE + # 4line.c + # env.c + draw.c + heap.c + init.c + ready.c + swapenvs.c + # quad.c + # rect.c + # sort.c + # sprite.c + vblank.c +) + +add_subdirectory(sprite) diff --git a/src/gfx/ps1/src/add_to_list.c b/src/gfx/ps1/src/add_to_list.c new file mode 100644 index 0000000..dff4910 --- /dev/null +++ b/src/gfx/ps1/src/add_to_list.c @@ -0,0 +1,39 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <stddef.h> +#include <stdint.h> + +static union gfx_sznext *first, *last; + +void gfx_add_to_list(union gfx_sznext *const p) +{ + if (!first) + first = p; + else if (last) + last->f.next = (uint32_t)p; + + last = p; +} + +void *gfx_heap_top(void) +{ + return first; +} diff --git a/src/gfx/ps1/src/deinit.c b/src/gfx/ps1/src/deinit.c new file mode 100644 index 0000000..ccf6c2d --- /dev/null +++ b/src/gfx/ps1/src/deinit.c @@ -0,0 +1,24 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> + +void gfx_deinit(void) +{ +} diff --git a/src/gfx/ps1/src/draw.c b/src/gfx/ps1/src/draw.c new file mode 100644 index 0000000..40abdf7 --- /dev/null +++ b/src/gfx/ps1/src/draw.c @@ -0,0 +1,70 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <drv/ps1/dma.h> +#include <drv/ps1/gpu.h> + +static union gfx_sznext *first, *last; + +void gfx_add_to_list(union gfx_sznext *const p) +{ + if (!first) + first = p; + else if (last) + last->f.next = (uint32_t)p; + + last = p; +} + +int gfx_draw(void) +{ + static union gfx_sznext term = {.cmd_next = 0xffffff}; + + gfx_add_to_list(&term); + + if (SCREEN_W != 640) + gfx_swapenvs(); + + gfx_swapheap(); + + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .dma = + { + .cmd = GP1_DMA_DIR, + .dir = GP1_DMA_DIR_CPU_TO_GP0 + } + }.mask; + + D2_MADR->mask = (uint32_t)first; + D2_BCR->syncmode_2.reserved = 0; + D2_CHCR->mask = (const union chcr) + { + .bits = + { + .sync_mode = CHCR_SYNC_MODE_LINKED_LIST, + .dir = CHCR_DIR_FROM_RAM, + .start_busy = 1 + } + }.mask; + + first = NULL; + return 0; +} diff --git a/src/gfx/ps1/src/env.c b/src/gfx/ps1/src/env.c new file mode 100644 index 0000000..100f366 --- /dev/null +++ b/src/gfx/ps1/src/env.c @@ -0,0 +1,71 @@ +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <psxgpu.h> +#include <errno.h> +#include <stdbool.h> + +static GsDispEnv dispenv; +enum {ENV_Y = SCREEN_H + 16}; + +static GsDrawEnv drawenv = +{ + .y = ENV_Y, + .w = SCREEN_W, + .h = SCREEN_H +}; + +int screen_w = SCREEN_W, screen_h = SCREEN_H; + +void gfx_swapbuffers(void) +{ + const short y = drawenv.y; + + drawenv.y = dispenv.y; + dispenv.y = y; + GsSetDrawEnv(&drawenv); + GsSetDispEnv(&dispenv); +} + +void gfx_initenvs(void) +{ + GsSetDrawEnv(&drawenv); + GsSetDispEnv(&dispenv); +} + +int gfx_toggle_fullscreen(void) +{ + errno = ENOTSUP; + return -1; +} + +int gfx_set_fullscreen(const short w, const short h) +{ + errno = ENOTSUP; + return -1; +} + +bool gfx_fullscreen_available(void) +{ + return false; +} + +bool gfx_fullscreen(void) +{ + return true; +} + +int gfx_display_size(short *const w, short *const h) +{ + *w = SCREEN_W; + *h = SCREEN_H; + return 0; +} + +bool gfx_inside_drawenv(const short x, const short y, const short w, + const short h) +{ + return (x + w >= 0) + && x < drawenv.w + && (y + h >= 0) + && y < drawenv.h; +} diff --git a/src/gfx/ps1/src/heap.c b/src/gfx/ps1/src/heap.c new file mode 100644 index 0000000..feb95c9 --- /dev/null +++ b/src/gfx/ps1/src/heap.c @@ -0,0 +1,73 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <stddef.h> + +static unsigned int sel; +static size_t heap_i; + +void gfx_swapheap(void) +{ + sel ^= 1; + heap_i = 0; +} + +static void *get_element(const size_t sz) +{ + enum {HEAP_SZ = 49152, N_HEAPS = 2}; + static char heaps[N_HEAPS][HEAP_SZ]; + const size_t new_sz = heap_i + sz; + void *ret = NULL; + + if (new_sz < sizeof *heaps / sizeof **heaps) + { + ret = &heaps[sel][heap_i]; + heap_i += sz; + } + else + { + static volatile int a; + + a++; + return NULL; + } + + return ret; +} + +struct gfx_sprite *gfx_sprite_get(void) +{ + return get_element(sizeof (struct gfx_sprite)); +} + +struct quad *quad_get(void) +{ + return get_element(sizeof (struct quad)); +} + +struct gfx_rect *rect_get(void) +{ + return get_element(sizeof (struct gfx_rect)); +} + +struct stp_4line *stp_4line_get(void) +{ + return get_element(sizeof (struct stp_4line)); +} diff --git a/src/gfx/ps1/src/init.c b/src/gfx/ps1/src/init.c new file mode 100644 index 0000000..3a94f32 --- /dev/null +++ b/src/gfx/ps1/src/init.c @@ -0,0 +1,153 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/dma.h> +#include <drv/ps1/gpu.h> +#include <drv/ps1/interrupt.h> +#include <stddef.h> + +struct res +{ + int hres, hres2, vres, interlace; +}; + +static void getres(const short w, struct res *const r) +{ + *r = (const struct res){0}; + + switch (w) + { + case 320: + r->hres = 1; + break; + case 368: + r->hres2 = 1; + break; + case 512: + r->hres = 2; + break; + case 640: + r->hres = 3; + r->vres = 1; + r->interlace = 1; + break; + } +} + +int gfx_init(void) +{ + const union dpcr dpcr = {.bits.gpu_en = 1}; + const int event = OpenEvent(CLASS_VBLANK, SPEC_INTERRUPTED, MODE_READY, + NULL); + + if (event == -1) + return -1; + + DPCR->mask |= dpcr.mask; + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .dma = + { + .cmd = GP1_DMA_DIR, + .dir = GP1_DMA_DIR_CPU_TO_GP0 + } + }.mask; + + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .display = + { + .cmd = GP1_DISPLAY_ENABLE, + } + }.mask; + + GP0->mask = (const union drv_ps1_gpu_gp0) + {.draw_mode.cmd = GP0_DRAW_MODE}.mask; + + GP0->mask = (const union drv_ps1_gpu_gp0) + {.tex_window.cmd = GP0_TEX_WINDOW}.mask; + + GP0->mask = (const union drv_ps1_gpu_gp0) + {.draw_area_tl.cmd = GP0_DRAW_AREA_TOP_LEFT}.mask; + + GP0->mask = (const union drv_ps1_gpu_gp0) + { + .draw_area_br = + { + .cmd = GP0_DRAW_AREA_BOTTOM_RIGHT, + .x = SCREEN_W - 1, + .y = SCREEN_H - 1, + } + }.mask; + + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .h_display_range = + { + .cmd = GP1_H_DISPLAY_RANGE, + .x1 = 0x260, + .x2 = 0x260 + 320 * 8 + } + }.mask; + +#if 0 + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .v_display_range = + { + .cmd = GP1_V_DISPLAY_RANGE, +#if VIDEO_MODE == VMODE_PAL + .y1 = 0xa3, + .y2 = 0xa3 + (SCREEN_H / 2) +#elif VIDEO_MODE == VMODE_NTSC + .y1 = 0x88 - (224 / 2), + .y2 = 0x88 + (224 / 2) +#endif + } + }.mask; +#else + GP1->mask = 0x06C4E24E; + GP1->mask = 0x07040010; +#endif + + struct res r; + + getres(SCREEN_W, &r); + + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .display_mode = + { + .cmd = GP1_DISPLAY_MODE, + .hres = r.hres, + .hres2 = r.hres2, + .vres = r.vres, + .vinterlace = r.interlace, +#if VIDEO_MODE == VMODE_PAL + .vmode = 1 +#endif + } + }.mask; + + I_MASK->bits.vblank = 1; + EnableEvent(gfx_vblank_ev = event); + return 0; +} diff --git a/src/gfx/ps1/src/quad.c b/src/gfx/ps1/src/quad.c new file mode 100644 index 0000000..bfabee2 --- /dev/null +++ b/src/gfx/ps1/src/quad.c @@ -0,0 +1,24 @@ +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <gfx/port.h> +#include <stdint.h> +#include <string.h> + +static void quad_init(struct quad *const q) +{ + memset(q, 0, sizeof *q); + q->sznext.f.sz = (sizeof *q - sizeof q->sznext) / sizeof (uint32_t); + q->cmd = 0x2d; +} + +int quad_from_sprite(const struct gfx_sprite *const s, struct quad *const q) +{ + quad_init(q); + q->tpage.mask = s->common.mask; + q->clutid = s->clutid; + q->u0 = q->u2 = s->u; + q->v0 = q->v1 = s->v; + q->u1 = q->u3 = s->u + s->w - 1; + q->v2 = q->v3 = s->v + s->h - 1; + return 0; +} diff --git a/src/gfx/ps1/src/ready.c b/src/gfx/ps1/src/ready.c new file mode 100644 index 0000000..0e17cdb --- /dev/null +++ b/src/gfx/ps1/src/ready.c @@ -0,0 +1,27 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <drv/ps1/bios.h> +#include <stdbool.h> + +bool gfx_ready(void) +{ + return TestEvent(gfx_vblank_ev); +} diff --git a/src/gfx/ps1/src/rect.c b/src/gfx/ps1/src/rect.c new file mode 100644 index 0000000..57b1b2a --- /dev/null +++ b/src/gfx/ps1/src/rect.c @@ -0,0 +1,25 @@ +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <psxgpu.h> +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +static void common_init(struct gfx_rect *const r) +{ + memset(r, 0, sizeof *r); + r->sznext.f.sz = (sizeof *r - sizeof r->sznext) / sizeof (uint32_t); + r->common.f.cmd = DRAW_MODE; +} + +void gfx_rect_init(struct gfx_rect *const r) +{ + common_init(r); + r->cmd = 0x60; +} + +void semitrans_rect_init(struct gfx_rect *const r) +{ + common_init(r); + r->cmd = 0x62; +} diff --git a/src/gfx/ps1/src/sort.c b/src/gfx/ps1/src/sort.c new file mode 100644 index 0000000..5c1c278 --- /dev/null +++ b/src/gfx/ps1/src/sort.c @@ -0,0 +1,73 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <drv/ps1/bios.h> +#include <stddef.h> +#include <stdint.h> + +static union gfx_sznext *first, *last; + +static void add_to_list(union gfx_sznext *const p) +{ + if (!first) + first = p; + else if (last) + last->f.next = (uint32_t)p; + + last = p; +} + +void sprite_sort(struct gfx_sprite *const s) +{ + add_to_list(&s->sznext); +} + +void quad_sort(struct quad *const q) +{ + add_to_list(&q->sznext); +} + +void gfx_rect_sort(struct gfx_rect *const r) +{ + add_to_list(&r->sznext); +} + +void stp_4line_sort(struct stp_4line *const l) +{ + add_to_list(&l->sznext); +} + +int gfx_draw(void) +{ + static union gfx_sznext term = {.cmd_next = 0xffffff}; + + add_to_list(&term); + + void gpu_ctrl(unsigned int command, unsigned int param); + + gfx_swapbuffers(); + gfx_swapheap(); + gpu_ctrl(4, 2); + D2_MADR = (uint32_t)first; + D2_BCR = 0; + D2_CHCR = (1 << 0xa) | 1 | (1 << 0x18); + first = NULL; + return 0; +} diff --git a/src/gfx/ps1/src/sprite/CMakeLists.txt b/src/gfx/ps1/src/sprite/CMakeLists.txt new file mode 100644 index 0000000..b42d699 --- /dev/null +++ b/src/gfx/ps1/src/sprite/CMakeLists.txt @@ -0,0 +1,22 @@ +# wanix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(gfx PRIVATE + clone.c + free.c + load.c + sort.c +) diff --git a/src/gfx/ps1/src/sprite/clone.c b/src/gfx/ps1/src/sprite/clone.c new file mode 100644 index 0000000..30d0d32 --- /dev/null +++ b/src/gfx/ps1/src/sprite/clone.c @@ -0,0 +1,26 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> + +int gfx_sprite_clone(const struct gfx_sprite *const src, + struct gfx_sprite *const dst) +{ + *dst = *src; + return 0; +} diff --git a/src/gfx/ps1/src/sprite/free.c b/src/gfx/ps1/src/sprite/free.c new file mode 100644 index 0000000..3b3d984 --- /dev/null +++ b/src/gfx/ps1/src/sprite/free.c @@ -0,0 +1,23 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> + +void sprite_free(struct gfx_sprite *const src) +{ +} diff --git a/src/gfx/ps1/src/sprite/load.c b/src/gfx/ps1/src/sprite/load.c new file mode 100644 index 0000000..7664017 --- /dev/null +++ b/src/gfx/ps1/src/sprite/load.c @@ -0,0 +1,191 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/sprite.h> +#include <gfx/private.h> +#include <drv/ps1/gpu.h> +#include <stdint.h> + +static void init(struct gfx_sprite *const s) +{ + *s = (const struct gfx_sprite){0}; + s->sznext.f.sz = (sizeof *s - sizeof s->sznext) / sizeof (uint32_t); + s->common.f.cmd = GP0_DRAW_MODE; + s->cmd = GP0_TEXTRECT_VARSZ_OPAQ_RAW; +} + +struct tim_pos +{ + uint16_t x, y, w, h; +}; + +static void transfer_init(const struct tim_pos *const p) +{ + while (!GPUSTAT->bits.ready_cmd) + ; + + GP0->mask = (const union drv_ps1_gpu_gp0) + {.copy_rect.cmd = GP0_COPY_RECT_CPU_VRAM}.mask; + GP0->mask = (const union drv_ps1_gpu_gp0) + {.coord = {.x = p->x, .y = p->y}}.mask; + GP0->mask = (const union drv_ps1_gpu_gp0) + {.size = {.w = p->w, .h = p->h}}.mask; +} + +static int transfer(const size_t sz, const gfx_read r, void *const args) +{ + const size_t rem = sz % sizeof (uint32_t); + + if (sz >= sizeof (uint32_t)) + { + for (size_t i = 0; i < sz / sizeof (uint32_t); i++) + { + uint32_t pix; + + if (r(&pix, sizeof pix, args)) + return -1; + + GP0->mask = pix; + } + } + + if (rem) + { + uint32_t pix = 0; + + if (r(&pix, rem, args)) + return -1; + + GP0->mask = pix; + } + + return 0; +} + +struct header +{ + uint32_t sz; + struct tim_pos pos; +}; + +static short get_clutid(const short x, const short y) +{ + return (x & 0x3ff) >> 4 | (y & 0x1ff) << 6; +} + +static int upload_clut(struct gfx_sprite *const s, const gfx_read r, + void *const args) +{ + struct header clut; + + if (r(&clut, sizeof clut, args)) + return -1; + + transfer_init(&clut.pos); + + const size_t sz = clut.sz - sizeof clut; + + if (transfer(sz, r, args)) + return -1; + + s->clutid = get_clutid(clut.pos.x, clut.pos.y); + return 0; +} + +enum bpp +{ + BPP_4 = 0, + BPP_8 = 1, + BPP_16 = 2, + BPP_24 = 4 +}; + +static int upload_img(struct gfx_sprite *const s, const enum bpp bpp, + const gfx_read r, void *const args) +{ + struct header img; + + if (r(&img, sizeof img, args)) + return -1; + + transfer_init(&img.pos); + + const size_t sz = img.sz - sizeof img; + + if (transfer(sz, r, args)) + return -1; + + enum + { + VRAM_X = 1024, + VRAM_Y = 512, + TPAGE_WIDTH = 64 + }; + + s->common.f.tpagex = img.pos.x / TPAGE_WIDTH; + s->common.f.tpagey = img.pos.y / (VRAM_Y / 2); + s->u = img.pos.x % TPAGE_WIDTH; + s->v = img.pos.y % (VRAM_Y / 2); + + switch (bpp) + { + case BPP_4: + s->w = img.pos.w * 4; + s->u <<= 2; + break; + + case BPP_8: + s->w = img.pos.w * 2; + s->u <<= 1; + break; + + case BPP_16: + s->w = img.pos.w; + break; + + case BPP_24: + s->w = img.pos.w + (img.pos.w / 2); + break; + } + + s->h = img.pos.h; + return 0; +} + +int gfx_sprite_load(struct gfx_sprite *s, const gfx_read r, void *const args) +{ + init(s); + + struct + { + uint32_t version, bpp :3, has_clut :1, :28; + } h; + + enum {VERSION_ID = 0x10}; + + if (r(&h, sizeof h, args) + || h.version != VERSION_ID + || h.bpp == BPP_24 + || (h.has_clut && upload_clut(s, r, args)) + || upload_img(s, h.bpp, r, args)) + return -1; + + s->common.f.bpp = h.bpp ? __builtin_ctz(h.bpp) + 1 : 0; + return 0; +} diff --git a/src/gfx/ps1/src/sprite/sort.c b/src/gfx/ps1/src/sprite/sort.c new file mode 100644 index 0000000..76fc214 --- /dev/null +++ b/src/gfx/ps1/src/sprite/sort.c @@ -0,0 +1,26 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/port.h> + +int gfx_sprite_sort(struct gfx_sprite *const s) +{ + gfx_add_to_list(&s->sznext); + return 0; +} diff --git a/src/gfx/ps1/src/swapenvs.c b/src/gfx/ps1/src/swapenvs.c new file mode 100644 index 0000000..9e120ad --- /dev/null +++ b/src/gfx/ps1/src/swapenvs.c @@ -0,0 +1,58 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/gfx.h> +#include <gfx/private.h> +#include <drv/ps1/gpu.h> + +void gfx_swapenvs(void) +{ + static short dispenv, drawenv = 256; + const short y = dispenv; + + dispenv = drawenv; + drawenv = y; + + GP0->mask = (const union drv_ps1_gpu_gp0) + { + .draw_area_tl = + { + .cmd = GP0_DRAW_AREA_TOP_LEFT, + .y = drawenv + } + }.mask; + + GP0->mask = (const union drv_ps1_gpu_gp0) + { + .draw_area_br = + { + .cmd = GP0_DRAW_AREA_BOTTOM_RIGHT, + .x = SCREEN_W - 1, + .y = drawenv + SCREEN_H - 1, + } + }.mask; + + GP1->mask = (const union drv_ps1_gpu_gp1) + { + .disparea = + { + .cmd = GP1_START_DISPLAY_AREA, + .y = dispenv + } + }.mask; +} diff --git a/src/gfx/ps1/src/vblank.c b/src/gfx/ps1/src/vblank.c new file mode 100644 index 0000000..cc445c7 --- /dev/null +++ b/src/gfx/ps1/src/vblank.c @@ -0,0 +1,21 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <gfx/private.h> + +int gfx_vblank_ev; |
