From 6bef461a5de1dba5bbc745276b0f6d600a80b24a Mon Sep 17 00:00:00 2001 From: Nunuhara Cabbage Date: Fri, 20 Dec 2019 20:18:17 -0800 Subject: [PATCH] Implement SACT2.GetMainSurfaceNumber Sprites are now rendered to an off-screen texture which is then rendered to the screen in gfx_swap. The sprite table in sact_graphics is set up so that sprites[-1] provides access to this off-screen texture. --- gfx_core.h | 1 + hll/SACT2.c | 2 +- sact_graphics.c | 31 +++++++++++++++++++---- video.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 91 insertions(+), 9 deletions(-) diff --git a/gfx_core.h b/gfx_core.h index 2af36eb..18d16b6 100644 --- a/gfx_core.h +++ b/gfx_core.h @@ -66,6 +66,7 @@ struct gfx_render_job { int gfx_init(void); void gfx_fini(void); +Texture *gfx_main_surface(void); void gfx_set_window_size(int w, int h); void gfx_fullscreen(bool on); void gfx_set_wait_vsync(bool wait); diff --git a/hll/SACT2.c b/hll/SACT2.c index 4241e5d..735a063 100644 --- a/hll/SACT2.c +++ b/hll/SACT2.c @@ -42,7 +42,7 @@ hll_defun_inline(GetScreenWidth, config.view_width); // int GetScreenHeight(void) hll_defun_inline(GetScreenHeight, config.view_height); // int GetMainSurfaceNumber(void) -hll_unimplemented(SACT2, GetMainSurfaceNumber); +hll_defun_inline(GetMainSurfaceNumber, -1); // int Update(void) hll_defun_inline(Update, sact_Update()); // int Effect(int nType, int nTime, int nfKey) diff --git a/sact_graphics.c b/sact_graphics.c index 830c99b..78fbc22 100644 --- a/sact_graphics.c +++ b/sact_graphics.c @@ -23,6 +23,8 @@ #include "vm_string.h" #include "utfsjis.h" +static struct sact_sprite *create_sprite(int sp_no, int width, int height, int r, int g, int b, int a); + static struct sact_sprite **sprites = NULL; static int nr_sprites = 0; @@ -31,7 +33,7 @@ TAILQ_HEAD(listhead, sact_sprite) sprite_list = struct sact_sprite *sact_get_sprite(int sp) { - if (sp < 0 || sp >= nr_sprites) + if (sp < -1 || sp >= nr_sprites) return NULL; return sprites[sp]; } @@ -81,10 +83,32 @@ static void sprite_unregister(struct sact_sprite *sp) TAILQ_REMOVE(&sprite_list, sp, entry); } +static void realloc_sprite_table(int n) +{ + int old_nr_sprites = nr_sprites; + nr_sprites = n; + + struct sact_sprite **tmp = xrealloc(sprites-1, sizeof(struct sact_sprite*) * (nr_sprites+1)); + sprites = tmp + 1; + + memset(sprites + old_nr_sprites, 0, sizeof(struct sact_sprite*) * (nr_sprites - old_nr_sprites)); +} + int sact_Init(void) { gfx_init(); gfx_font_init(); + + nr_sprites = 256; + sprites = xmalloc(sizeof(struct sact_sprite*) * 257); + memset(sprites, 0, sizeof(struct sact_sprite*) * 257); + + // create sprite for main_surface + Texture *t = gfx_main_surface(); + struct sact_sprite *sp = create_sprite(0, t->w, t->h, 0, 0, 0, 255); + sp->texture = *t; // XXX: textures normally shouldn't be copied like this... + + sprites++; return 1; } @@ -237,11 +261,8 @@ int sact_SP_GetUnuseNum(int min) return i; } - int old_nr_sprites = nr_sprites; int n = max(min, nr_sprites); - nr_sprites = n + 256; - sprites = xrealloc(sprites, sizeof(struct sact_sprite*) * nr_sprites); - memset(sprites + old_nr_sprites, 0, sizeof(struct sact_sprite*) * (nr_sprites - old_nr_sprites)); + realloc_sprite_table(n + 256); return n; } diff --git a/video.c b/video.c index e501dbd..06c241a 100644 --- a/video.c +++ b/video.c @@ -42,7 +42,7 @@ static GLfloat world_view_transform[16] = { [10] = 2, [12] = -1, - [13] = 1, + [13] = -1, [14] = -1, [15] = 1 }; @@ -52,6 +52,9 @@ struct default_shader { GLuint alpha_mod; } default_shader; +GLuint main_surface_fb; +struct texture main_surface; + void prepare_default_shader(struct gfx_render_job *job, void *data) { struct default_shader *s = (struct default_shader*)job->shader; @@ -133,6 +136,7 @@ static int gl_initialize(void) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + return 0; } @@ -179,6 +183,11 @@ void gfx_fini(void) SDL_Quit(); } +Texture *gfx_main_surface(void) +{ + return &main_surface; +} + void gfx_fullscreen(bool on) { if (on && !sdl.fs_on) { @@ -190,13 +199,37 @@ void gfx_fullscreen(bool on) } } +static void main_surface_init(int w, int h) +{ + gfx_delete_texture(&main_surface); + + + glGenTextures(1, &main_surface.handle); + glBindTexture(GL_TEXTURE_2D, main_surface.handle); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + + main_surface.w = w; + main_surface.h = h; + main_surface.has_alpha = true; + main_surface.alpha_mod = 255; + main_surface.draw_method = DRAW_METHOD_NORMAL; + + glGenFramebuffers(1, &main_surface_fb); + glBindFramebuffer(GL_FRAMEBUFFER, main_surface_fb); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, main_surface.handle, 0); +} + void gfx_set_window_size(int w, int h) { sdl.w = w; sdl.h = h; world_view_transform[0] = 2.0 / w; - world_view_transform[5] = -2.0 / h; + world_view_transform[5] = 2.0 / h; SDL_SetWindowSize(sdl.window, w, h); + main_surface_init(w, h); } void gfx_set_wait_vsync(bool wait) @@ -211,7 +244,34 @@ void gfx_clear(void) void gfx_swap(void) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClear(GL_COLOR_BUFFER_BIT); + + static GLfloat mw_transform[16] = { + [0] = 1, + [5] = 1, + [10] = 1, + [15] = 1 + }; + static GLfloat wv_transform[16] = { + [0] = 2, + [5] = -2, + [10] = 1, + [12] = -1, + [13] = 1, + [15] = 1 + }; + struct gfx_render_job job = { + .shader = &default_shader.s, + .texture = main_surface.handle, + .world_transform = mw_transform, + .view_transform = wv_transform, + .data = &main_surface + }; + gfx_render(&job); + SDL_GL_SwapWindow(sdl.window); + glBindFramebuffer(GL_FRAMEBUFFER, main_surface_fb); } /* @@ -371,7 +431,7 @@ GLuint gfx_set_framebuffer(GLenum target, Texture *t, int x, int y, int w, int h void gfx_reset_framebuffer(GLenum target, GLuint fbo) { - glBindFramebuffer(target, 0); + glBindFramebuffer(target, main_surface_fb); glDeleteFramebuffers(1, &fbo); glViewport(0, 0, sdl.w, sdl.h); }