diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2021-07-03 00:49:03 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2022-03-30 08:20:20 +0200 |
| commit | 6b9f686913efc3725b2690033cd4f398e07076ba (patch) | |
| tree | e9aa91a6b9f617d78123ebe7ad272fc42a60d306 /src/gfx | |
| parent | c9e6ae44a9aeb89b3f48f3443d6baa80103f7445 (diff) | |
| download | jancity-6b9f686913efc3725b2690033cd4f398e07076ba.tar.gz | |
Add project source code
Diffstat (limited to 'src/gfx')
| -rw-r--r-- | src/gfx/CMakeLists.txt | 54 | ||||
| -rw-r--r-- | src/gfx/inc/gfx.h | 37 | ||||
| -rw-r--r-- | src/gfx/privinc/gfx_private.h | 22 | ||||
| -rw-r--r-- | src/gfx/ps1/inc/gfx/port.h | 142 | ||||
| -rw-r--r-- | src/gfx/ps1/privinc/ps1/gfx_private.h | 25 | ||||
| -rw-r--r-- | src/gfx/ps1/src/4line.c | 14 | ||||
| -rw-r--r-- | src/gfx/ps1/src/env.c | 42 | ||||
| -rw-r--r-- | src/gfx/ps1/src/heap.c | 19 | ||||
| -rw-r--r-- | src/gfx/ps1/src/init.c | 16 | ||||
| -rw-r--r-- | src/gfx/ps1/src/quad.c | 23 | ||||
| -rw-r--r-- | src/gfx/ps1/src/rect.c | 23 | ||||
| -rw-r--r-- | src/gfx/ps1/src/sort.c | 75 | ||||
| -rw-r--r-- | src/gfx/ps1/src/sprite.c | 244 | ||||
| -rw-r--r-- | src/gfx/sdl-1.2/inc/gfx/port.h | 52 | ||||
| -rw-r--r-- | src/gfx/sdl-1.2/privinc/sdl-1.2/gfx_private.h | 19 | ||||
| -rw-r--r-- | src/gfx/sdl-1.2/src/env.c | 82 | ||||
| -rw-r--r-- | src/gfx/sdl-1.2/src/heap.c | 11 | ||||
| -rw-r--r-- | src/gfx/sdl-1.2/src/line.c | 15 | ||||
| -rw-r--r-- | src/gfx/sdl-1.2/src/quad.c | 18 | ||||
| -rw-r--r-- | src/gfx/sdl-1.2/src/rect.c | 33 | ||||
| -rw-r--r-- | src/gfx/sdl-1.2/src/sort.c | 22 | ||||
| -rw-r--r-- | src/gfx/sdl-1.2/src/sprite.c | 75 | ||||
| -rw-r--r-- | src/gfx/src/heap.c | 56 |
23 files changed, 1119 insertions, 0 deletions
diff --git a/src/gfx/CMakeLists.txt b/src/gfx/CMakeLists.txt new file mode 100644 index 0000000..c449be5 --- /dev/null +++ b/src/gfx/CMakeLists.txt @@ -0,0 +1,54 @@ +set(src "src/heap.c") +set(inc "inc") +set(privinc "privinc") +set(deps util) + +if(PS1_BUILD) + set(src ${src} + "ps1/src/4line.c" + "ps1/src/env.c" + "ps1/src/heap.c" + "ps1/src/init.c" + "ps1/src/rect.c" + "ps1/src/sort.c" + "ps1/src/sprite.c" + "ps1/src/quad.c") + set(inc ${inc} "ps1/inc") + set(privinc ${privinc} "ps1/privinc") + set(privdeps ${privdeps} system) +elseif(SDL1_2_BUILD) + set(inc ${inc} "sdl-1.2/inc") + set(privinc ${privinc} "sdl-1.2/privinc") + set(src ${src} + "sdl-1.2/src/env.c" + "sdl-1.2/src/heap.c" + "sdl-1.2/src/line.c" + "sdl-1.2/src/rect.c" + "sdl-1.2/src/sort.c" + "sdl-1.2/src/sprite.c" + "sdl-1.2/src/quad.c") + set(deps ${deps} SDL) +endif() + +add_library(gfx ${src}) +target_include_directories(gfx PUBLIC ${inc}) +target_include_directories(gfx PRIVATE ${privinc}) +target_link_libraries(gfx PUBLIC ${deps} PRIVATE ${privdeps}) + +if(PS1_BUILD) + 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() +endif() diff --git a/src/gfx/inc/gfx.h b/src/gfx/inc/gfx.h new file mode 100644 index 0000000..0c30911 --- /dev/null +++ b/src/gfx/inc/gfx.h @@ -0,0 +1,37 @@ +#ifndef GFX_H +#define GFX_H + +#include <gfx/port.h> +#include <stdbool.h> +#include <stdio.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +int gfx_init(void); +void gfx_draw(void); +void gfx_sync(void); +void sprite_sort(struct sprite *s); +int sprite_clone(const struct sprite *src, struct sprite *dst); +void quad_sort(struct quad *q); +void rect_sort(struct rect *r); +void stp_4line_sort(struct stp_4line *l); +int sprite_from_fp(struct sprite *s, FILE *f); +struct sprite *sprite_get(void); +struct quad *quad_get(void); +struct rect *rect_get(bool semitrans); +struct stp_4line *stp_4line_get(void); +int quad_from_sprite(const struct sprite *s, struct quad *q); +bool gfx_inside_drawenv(short x, short y, short w, short h); +void gfx_deinit(void); +void sprite_free(struct sprite *src); + +extern int screen_w, screen_h; + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_H */ diff --git a/src/gfx/privinc/gfx_private.h b/src/gfx/privinc/gfx_private.h new file mode 100644 index 0000000..0553362 --- /dev/null +++ b/src/gfx/privinc/gfx_private.h @@ -0,0 +1,22 @@ +#ifndef GFX_PRIVATE_H +#define GFX_PRIVATE_H + +#include <gfx.h> +#include <stddef.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +void rect_init(struct rect *r); +void semitrans_rect_init(struct rect *r); +void stp_4line_init(struct stp_4line *l); +void *gfx_port_heap(size_t *n); +void gfx_reset_heap(void); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_PRIVATE_H */ diff --git a/src/gfx/ps1/inc/gfx/port.h b/src/gfx/ps1/inc/gfx/port.h new file mode 100644 index 0000000..dec00c3 --- /dev/null +++ b/src/gfx/ps1/inc/gfx/port.h @@ -0,0 +1,142 @@ +#ifndef GFX_PS1_H +#define GFX_PS1_H + +#include <util.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* 0-3 Texture page X Base (N*64) (ie. in 64-halfword steps) ;GPUSTAT.0-3 + 4 Texture page Y Base (N*256) (ie. 0 or 256) ;GPUSTAT.4 + 5-6 Semi Transparency (0=B/2+F/2, 1=B+F, 2=B-F, 3=B+F/4) ;GPUSTAT.5-6 + 7-8 Texture page colors (0=4bit, 1=8bit, 2=15bit, 3=Reserved);GPUSTAT.7-8 + 9 Dither 24bit to 15bit (0=Off/strip LSBs, 1=Dither Enabled) ;GPUSTAT.9 + 10 Drawing to display area (0=Prohibited, 1=Allowed) ;GPUSTAT.10 + 11 Texture Disable (0=Normal, 1=Disable if GP1(09h).Bit0=1) ;GPUSTAT.15 + (Above might be chipselect for (absent) second VRAM chip?) + 12 Textured Rectangle X-Flip (BIOS does set this bit on power-up...?) + 13 Textured Rectangle Y-Flip (BIOS does set it equal to GPUSTAT.13...?) + 14-23 Not used (should be 0) + 24-31 Command (E1h)*/ +union gfx_common +{ + struct + { + uint32_t tpagex :4; + uint32_t tpagey :1; + uint32_t stp :2; + uint32_t bpp :2; + uint32_t dither :1; + uint32_t draw_to_disp :1; + uint32_t disable :1; + uint32_t xflip :1; + uint32_t yflip :1; + uint32_t :10; + uint8_t cmd; + } f; + + uint32_t mask; +}; + +union gfx_sznext +{ + struct + { + uint32_t next :24; + uint32_t sz :8; + } f; + + uint32_t cmd_next; +}; + +struct 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 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; + uint32_t g :8; + uint32_t b :8; + uint32_t :8; + + int16_t x, y; + } vertices[4]; + + uint32_t end; +}; + +enum {DRAW_MODE = 0xE1}; + +int sprite_from_file_ex(const char *path, struct sprite *s); + +#define sprite_from_file(path, s) sprite_from_file_ex("cdrom:\\"path";1", s) + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_PS1_H */ diff --git a/src/gfx/ps1/privinc/ps1/gfx_private.h b/src/gfx/ps1/privinc/ps1/gfx_private.h new file mode 100644 index 0000000..fd5a790 --- /dev/null +++ b/src/gfx/ps1/privinc/ps1/gfx_private.h @@ -0,0 +1,25 @@ +#ifndef GFX_PS1_PRIVATE_H +#define GFX_PS1_PRIVATE_H + +#include <gfx.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +enum +{ + SCREEN_W = 368, + SCREEN_H = 240 +}; + +void gfx_swapheap(void); +void gfx_initenvs(void); +void gfx_swapbuffers(void); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_PS1_PRIVATE_H */ diff --git a/src/gfx/ps1/src/4line.c b/src/gfx/ps1/src/4line.c new file mode 100644 index 0000000..955277e --- /dev/null +++ b/src/gfx/ps1/src/4line.c @@ -0,0 +1,14 @@ +#include <gfx.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/env.c b/src/gfx/ps1/src/env.c new file mode 100644 index 0000000..c12002b --- /dev/null +++ b/src/gfx/ps1/src/env.c @@ -0,0 +1,42 @@ +#include <gfx.h> +#include <gfx_private.h> +#include <ps1/gfx_private.h> +#include <psxgpu.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); +} + +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..b67ee3e --- /dev/null +++ b/src/gfx/ps1/src/heap.c @@ -0,0 +1,19 @@ +#include <gfx.h> +#include <gfx_private.h> +#include <stddef.h> + +static unsigned int sel; + +void gfx_swapheap(void) +{ + sel ^= 1; +} + +void *gfx_port_heap(size_t *const n) +{ + enum {HEAP_SZ = 5120, N_HEAPS = 2}; + static char heaps[N_HEAPS][HEAP_SZ]; + + *n = sizeof *heaps / sizeof **heaps; + return heaps[sel]; +} diff --git a/src/gfx/ps1/src/init.c b/src/gfx/ps1/src/init.c new file mode 100644 index 0000000..15ecd3e --- /dev/null +++ b/src/gfx/ps1/src/init.c @@ -0,0 +1,16 @@ +#include <gfx_private.h> +#include <ps1/gfx_private.h> +#include <psxgpu.h> + +void gfx_deinit(void) +{ +} + +int gfx_init(void) +{ + GsInit(); + GsClearMem(); + GsSetVideoMode(SCREEN_W, SCREEN_H, VIDEO_MODE); + gfx_initenvs(); + return 0; +} diff --git a/src/gfx/ps1/src/quad.c b/src/gfx/ps1/src/quad.c new file mode 100644 index 0000000..649426f --- /dev/null +++ b/src/gfx/ps1/src/quad.c @@ -0,0 +1,23 @@ +#include <gfx.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 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/rect.c b/src/gfx/ps1/src/rect.c new file mode 100644 index 0000000..7e593b7 --- /dev/null +++ b/src/gfx/ps1/src/rect.c @@ -0,0 +1,23 @@ +#include <gfx.h> +#include <psxgpu.h> +#include <stdint.h> +#include <string.h> + +static void common_init(struct 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 rect_init(struct rect *const r) +{ + common_init(r); + r->cmd = 0x60; +} + +void semitrans_rect_init(struct 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..5cc14aa --- /dev/null +++ b/src/gfx/ps1/src/sort.c @@ -0,0 +1,75 @@ +#include <gfx.h> +#include <gfx_private.h> +#include <ps1/gfx_private.h> +#include <system/port.h> +#include <psxgpu.h> +#include <stdbool.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 sprite *const s) +{ + add_to_list(&s->sznext); +} + +void quad_sort(struct quad *const q) +{ + add_to_list(&q->sznext); +} + +void rect_sort(struct rect *const r) +{ + add_to_list(&r->sznext); +} + +void stp_4line_sort(struct stp_4line *const l) +{ + add_to_list(&l->sznext); +} + +void 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_sync(); + 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; + gfx_reset_heap(); +} + +void gfx_sync(void) +{ + /* Wait for the GPU to finish drawing primitives. */ + while (!(GPU_CONTROL_PORT & (1 << 0x1a))) + ; + + /* Wait for the GPU to be free. */ + while (!(GPU_CONTROL_PORT & (1 << 0x1c))) + ; + + while (!vblank_set) + ; + + vblank_set = false; +} diff --git a/src/gfx/ps1/src/sprite.c b/src/gfx/ps1/src/sprite.c new file mode 100644 index 0000000..3e35a70 --- /dev/null +++ b/src/gfx/ps1/src/sprite.c @@ -0,0 +1,244 @@ +#include <gfx.h> +#include <psxgpu.h> +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +void sprite_free(struct sprite *const src) +{ +} + +int sprite_clone(const struct sprite *const src, struct sprite *const dst) +{ + *dst = *src; + return 0; +} + +static void sprite_init(struct sprite *const s) +{ + memset(s, 0, sizeof *s); + s->sznext.f.sz = (sizeof *s - sizeof s->sznext) / sizeof (uint32_t); + s->common.f.cmd = DRAW_MODE; + s->cmd = 0x65; +} + +struct tim_pos +{ + uint16_t x, y, w, h; +}; + +static void transfer_init(const struct tim_pos *const p) +{ + while (!(GPU_CONTROL_PORT & (1 << 0x1c))) + ; + + GPU_CONTROL_PORT = 0x04000000; + GPU_DATA_PORT = 0x01000000; + GPU_DATA_PORT = 0xE6000000; + GPU_DATA_PORT = 0xA0000000; + GPU_DATA_PORT = (p->y << 16) | p->x; + GPU_DATA_PORT = (p->h << 16) | p->w; +} + +static int transfer(const size_t sz, FILE *const f) +{ + 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 (!fread(&pix, sizeof pix, 1, f)) + { + fprintf(stderr, "could not read CLUT word %zu/%zu\n", + i, sz / sizeof pix); + return -1; + } + + GPU_DATA_PORT = pix; + } + } + + if (rem) + { + uint32_t pix = 0; + + if (!fread(&pix, rem, 1, f)) + { + fprintf(stderr, "failed reading remaining %zu bytes\n", rem); + return -1; + } + + GPU_DATA_PORT = pix; + } + + return 0; +} + +struct header +{ + uint32_t sz; + struct tim_pos pos; +}; + +static int upload_clut(struct sprite *const s, FILE *const f) +{ + struct header clut; + + if (!fread(&clut, sizeof clut, 1, f)) + { + fprintf(stderr, "no CLUT pos data found\n"); + return -1; + } + + transfer_init(&clut.pos); + + const size_t sz = clut.sz - sizeof clut; + + if (transfer(sz, f)) + 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 sprite *const s, const enum bpp bpp, FILE *const f) +{ + struct header img; + + if (!fread(&img, sizeof img, 1, f)) + { + fprintf(stderr, "could not extract image header\n"); + return -1; + } + + transfer_init(&img.pos); + + const size_t sz = img.sz - sizeof img; + + if (transfer(sz, f)) + 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 sprite_from_fp(struct sprite *const s, FILE *const f) +{ + int ret = -1; + + sprite_init(s); + + struct + { + uint32_t version; + enum bpp bpp :3; + bool has_clut :1; + uint32_t :28; + } h; + + enum {VERSION_ID = 0x10}; + + if (!fread(&h, sizeof h, 1, f)) + { + fprintf(stderr, "TIM header not found\n"); + goto end; + } + else if (h.version != VERSION_ID) + { + fprintf(stderr, "%s: invalid TIM header %#" PRIx32 "\n", h.version); + goto end; + } + else if (h.bpp == BPP_24) + { + fprintf(stderr, "24-bit mode unsupported\n"); + goto end; + } + else if ((h.has_clut && upload_clut(s, f)) + || upload_img(s, h.bpp, f)) + goto end; + + s->common.f.bpp = h.bpp ? __builtin_ctz(h.bpp) + 1 : 0; + ret = 0; + +end: + return ret; +} + +int sprite_from_file_ex(const char *const path, struct sprite *const s) +{ + int ret = -1; + FILE *f = NULL; + + if (!path) + { + errno = EINVAL; + goto end; + } + + f = fopen(path, "rb"); + + if (!f) + { + fprintf(stderr, "could not open %s: %s\n", path, strerror(errno)); + goto end; + } + else if (sprite_from_fp(s, f)) + { + fprintf(stderr, "%s: sprite_from_fp failed\n", path); + goto end; + } + +end: + + if (f) + fclose(f); + + return ret; +} diff --git a/src/gfx/sdl-1.2/inc/gfx/port.h b/src/gfx/sdl-1.2/inc/gfx/port.h new file mode 100644 index 0000000..ec1093e --- /dev/null +++ b/src/gfx/sdl-1.2/inc/gfx/port.h @@ -0,0 +1,52 @@ +#ifndef GFX_SDL_H +#define GFX_SDL_H + +#include <SDL/SDL.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct sprite +{ + SDL_Surface *s; + short x, y, w, h; + unsigned char u, v; +}; + +struct quad +{ + unsigned char r, g, b; + short x0, x1, x2, x3; + short y0, y1, y2, y3; + unsigned char u0, u1, u2, u3; + unsigned char v0, v1, v2, v3; + SDL_Surface *s; +}; + +struct rect +{ + unsigned char r, g, b; + short x, y, w, h; +}; + +struct stp_4line +{ + short x, y; + unsigned char r, g, b; + + struct stp_4line_vtx + { + unsigned char r, g, b; + short x, y; + } vertices[4]; +}; + +SDL_Surface *gfx_port_screen(void); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_SDL_H */ diff --git a/src/gfx/sdl-1.2/privinc/sdl-1.2/gfx_private.h b/src/gfx/sdl-1.2/privinc/sdl-1.2/gfx_private.h new file mode 100644 index 0000000..c067af7 --- /dev/null +++ b/src/gfx/sdl-1.2/privinc/sdl-1.2/gfx_private.h @@ -0,0 +1,19 @@ +#ifndef GFX_SDL_12_PRIVATE_H +#define GFX_SDL_12_PRIVATE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +enum +{ + SCREEN_W = 320, + SCREEN_H = 240 +}; + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_SDL_12_PRIVATE_H */ diff --git a/src/gfx/sdl-1.2/src/env.c b/src/gfx/sdl-1.2/src/env.c new file mode 100644 index 0000000..6589d84 --- /dev/null +++ b/src/gfx/sdl-1.2/src/env.c @@ -0,0 +1,82 @@ +#include <gfx.h> +#include <sdl-1.2/gfx_private.h> +#include <SDL/SDL.h> +#include <stdbool.h> + +int screen_w = SCREEN_W, screen_h = SCREEN_H; +static bool fullscreen; +static SDL_Surface *screen; + +void gfx_deinit(void) +{ + if (screen) + SDL_FreeSurface(screen); + + SDL_QuitSubSystem(SDL_INIT_VIDEO); +} + +static int resize_screen(const int w, const int h, const bool full_screen) +{ + Uint32 flags = SDL_HWSURFACE | SDL_RESIZABLE | SDL_DOUBLEBUF; + + const SDL_VideoInfo *const info = SDL_GetVideoInfo(); + + if (!info) + { + fprintf(stderr, "SDL_GetVideoInfo: %s\n", SDL_GetError()); + return -1; + } + + if (fullscreen) + flags |= SDL_FULLSCREEN; + +#if 0 + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); +#endif + + const int bpp = info->vfmt->BitsPerPixel; + + if (screen) + SDL_FreeSurface(screen); + + if (!(screen = SDL_SetVideoMode(screen_w, screen_h, bpp, flags))) + { + fprintf(stderr, "SDL_SetVideoMode: %s\n", SDL_GetError()); + return -1; + } + + screen_w = w; + screen_h = h; + fullscreen = full_screen; + return 0; +} + +int gfx_init(void) +{ + if (SDL_InitSubSystem(SDL_INIT_VIDEO)) + { + fprintf(stderr, "%s: SDL_InitSubSystem: %s\n", + __func__, SDL_GetError()); + return -1; + } + + return resize_screen(screen_w, screen_h, fullscreen); +} + +bool gfx_inside_drawenv(const short x, const short y, const short w, + const short h) +{ + return (x + w >= 0) + && x < screen_w + && (y + h >= 0) + && y < screen_h; +} + +SDL_Surface *gfx_port_screen(void) +{ + return screen; +} diff --git a/src/gfx/sdl-1.2/src/heap.c b/src/gfx/sdl-1.2/src/heap.c new file mode 100644 index 0000000..b84760a --- /dev/null +++ b/src/gfx/sdl-1.2/src/heap.c @@ -0,0 +1,11 @@ +#include <gfx.h> +#include <gfx_private.h> +#include <stddef.h> + +void *gfx_port_heap(size_t *const n) +{ + static char heap[5120]; + + *n = sizeof heap / sizeof *heap; + return heap; +} diff --git a/src/gfx/sdl-1.2/src/line.c b/src/gfx/sdl-1.2/src/line.c new file mode 100644 index 0000000..aeeda7b --- /dev/null +++ b/src/gfx/sdl-1.2/src/line.c @@ -0,0 +1,15 @@ +#include <gfx.h> +#include <gfx/port.h> +#include <stddef.h> + +void stp_4line_init(struct stp_4line *const l) +{ +} + +void semitrans_stp_4line_init(struct stp_4line *r) +{ +} + +void stp_4line_sort(struct stp_4line *const r) +{ +} diff --git a/src/gfx/sdl-1.2/src/quad.c b/src/gfx/sdl-1.2/src/quad.c new file mode 100644 index 0000000..fe1b39f --- /dev/null +++ b/src/gfx/sdl-1.2/src/quad.c @@ -0,0 +1,18 @@ +#include <gfx.h> +#include <gfx/port.h> +#include <stddef.h> +#include <stdlib.h> + +int quad_from_sprite(const struct sprite *const s, struct quad *const q) +{ + q->s = s->s; + 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; +} + +void quad_sort(struct quad *const q) +{ +} diff --git a/src/gfx/sdl-1.2/src/rect.c b/src/gfx/sdl-1.2/src/rect.c new file mode 100644 index 0000000..ee50378 --- /dev/null +++ b/src/gfx/sdl-1.2/src/rect.c @@ -0,0 +1,33 @@ +#include <gfx.h> +#include <gfx/port.h> +#include <SDL/SDL.h> +#include <stddef.h> +#include <stdlib.h> + +void rect_sort(struct rect *const r) +{ + SDL_Rect rct = + { + .x = r->x, + .y = r->y, + .w = r->w, + .h = r->h + }; + + SDL_Surface *const screen = gfx_port_screen(); + const Uint32 map = SDL_MapRGB(screen->format, r->r, r->g, r->b); + + if (SDL_FillRect(screen, &rct, map)) + { + fprintf(stderr, "SDL_FillRect: %s\n", SDL_GetError()); + return; + } +} + +void semitrans_rect_init(struct rect *const r) +{ +} + +void rect_init(struct rect *const r) +{ +} diff --git a/src/gfx/sdl-1.2/src/sort.c b/src/gfx/sdl-1.2/src/sort.c new file mode 100644 index 0000000..2cc4e75 --- /dev/null +++ b/src/gfx/sdl-1.2/src/sort.c @@ -0,0 +1,22 @@ +#include <gfx.h> +#include <gfx_private.h> +#include <gfx/port.h> +#include <SDL/SDL.h> +#include <stdio.h> + +void gfx_draw(void) +{ + enum {FPS = 50, REFRESH_MS = 1000 / FPS}; + static Uint32 prev; + const Uint32 cur = SDL_GetTicks(); + + if (cur - prev < REFRESH_MS) + SDL_Delay(REFRESH_MS - (cur - prev)); + + prev = SDL_GetTicks(); + + if (SDL_Flip(gfx_port_screen())) + fprintf(stderr, "SDL_Flip: %s\n", SDL_GetError()); + + gfx_reset_heap(); +} diff --git a/src/gfx/sdl-1.2/src/sprite.c b/src/gfx/sdl-1.2/src/sprite.c new file mode 100644 index 0000000..9d65c0d --- /dev/null +++ b/src/gfx/sdl-1.2/src/sprite.c @@ -0,0 +1,75 @@ +#include <gfx.h> +#include <gfx/port.h> +#include <SDL/SDL.h> +#include <stddef.h> +#include <stdlib.h> + +void sprite_free(struct sprite *const s) +{ + if (s && s->s) + SDL_FreeSurface(s->s); +} + +int sprite_clone(const struct sprite *const src, struct sprite *const dst) +{ + *dst = *src; + return 0; +} + +int sprite_from_fp(struct sprite *const s, FILE *const f) +{ + int ret = -1; + SDL_RWops *ops = NULL; + SDL_Surface *ts = NULL; + + if (!(ops = SDL_RWFromFP(f, 0))) + { + fprintf(stderr, "SDL_RWFromFP: %s\n", SDL_GetError()); + goto end; + } + if (!(ts = SDL_LoadBMP_RW(ops, 0))) + { + fprintf(stderr, "SDL_LoadBMP_RW: %s\n", SDL_GetError()); + goto end; + } + /* Magenta as transparent. */ + else if (SDL_SetColorKey(ts, SDL_SRCCOLORKEY, SDL_MapRGB(ts->format, 255, 0, 255))) + { + fprintf(stderr, "SDL_SetColorKey: %s\n", SDL_GetError()); + goto end; + } + else if (!(s->s = SDL_DisplayFormat(ts))) + { + fprintf(stderr, "SDL_DisplayFormat: %s\n", SDL_GetError()); + goto end; + } + + s->w = ts->w; + s->h = ts->h; + ret = 0; + +end: + SDL_FreeRW(ops); + SDL_FreeSurface(ts); + return ret; +} + +void sprite_sort(struct sprite *const s) +{ + SDL_Rect r = + { + .x = s->x, + .y = s->y + }; + + SDL_Rect clip = + { + .x = s->u, + .y = s->v, + .w = s->w, + .h = s->h + }; + + if (SDL_BlitSurface(s->s, &clip, gfx_port_screen(), &r)) + fprintf(stderr, "SDL_BlitSurface: %s\n", SDL_GetError()); +} diff --git a/src/gfx/src/heap.c b/src/gfx/src/heap.c new file mode 100644 index 0000000..40a856c --- /dev/null +++ b/src/gfx/src/heap.c @@ -0,0 +1,56 @@ +#include <gfx.h> +#include <gfx_private.h> +#include <stddef.h> + +static size_t heap_i; + +void gfx_reset_heap(void) +{ + heap_i = 0; +} + +static void *get_element(const size_t sz) +{ + size_t n; + char *ret = gfx_port_heap(&n); + + if (ret && heap_i + sz < n) + { + ret += heap_i; + heap_i += sz; + } + else + return NULL; + + return ret; +} + +struct sprite *sprite_get(void) +{ + return get_element(sizeof (struct sprite)); +} + +struct quad *quad_get(void) +{ + return get_element(sizeof (struct quad)); +} + +struct rect *rect_get(const bool semitrans) +{ + struct rect *const r = get_element(sizeof (struct rect)); + + if (r) + semitrans ? semitrans_rect_init(r) : rect_init(r); + + return r; +} + +struct stp_4line *stp_4line_get(void) +{ + struct stp_4line *const l = get_element(sizeof (struct stp_4line)); + + if (l) + stp_4line_init(l); + + return l; +} |
