diff --git a/.github/workflows/build_saturn.yml b/.github/workflows/build_saturn.yml index 7750e3556..e7103690b 100644 --- a/.github/workflows/build_saturn.yml +++ b/.github/workflows/build_saturn.yml @@ -21,7 +21,8 @@ jobs: - name: Compile Saturn build id: compile run: | - pacman -S curl + apt-get update + apt-get -y install curl make saturn - uses: ./.github/actions/notify_failure diff --git a/src/Graphics_Saturn.c b/src/Graphics_Saturn.c index f10bb6ab4..0924a7355 100644 --- a/src/Graphics_Saturn.c +++ b/src/Graphics_Saturn.c @@ -1,494 +1,498 @@ -#include "Core.h" -#if defined CC_BUILD_SATURN -#include "_GraphicsBase.h" -#include "Errors.h" -#include "Window.h" -#include -#include -#include -#include - - -#define SCREEN_WIDTH 320 -#define SCREEN_HEIGHT 224 - -#define PRIMITIVE_DRAW_MODE_NORMAL (0) -#define PRIMITIVE_DRAW_MODE_MESH (1) -#define PRIMITIVE_DRAW_MODE_SHADOW (2) -#define PRIMITIVE_DRAW_MODE_HALF_LUMINANCE (3) -#define PRIMITIVE_DRAW_MODE_HALF_TRANSPARENT (4) -#define PRIMITIVE_DRAW_MODE_GOURAUD_SHADING (5) -#define PRIMITIVE_DRAW_MODE_GOURAUD_HALF_LUM (6) -#define PRIMITIVE_DRAW_MODE_GOURAUD_HALF_TRANS (7) -#define PRIMITIVE_DRAW_MODE_COUNT (8) - -#define PRIMITIVE_COLOR RGB1555(1, 31, 0, 31) - -#define CMDS_COUNT 400 - -static PackedCol clear_color; -static vdp1_cmdt_t cmdts_all[CMDS_COUNT]; -static int cmdts_count; -static vdp1_vram_partitions_t _vdp1_vram_partitions; - -static vdp1_cmdt_t* NextPrimitive(void) { - if (cmdts_count >= CMDS_COUNT) Logger_Abort("Too many VDP1 commands"); - return &cmdts_all[cmdts_count++]; -} - -static vdp1_cmdt_draw_mode_t _primitive_draw_mode = { - .raw = 0x0000 -}; - -static int16_vec2_t clear_points[4]; - - -// TODO: how to use VDP1 erase ?? -static void UpdateVDP1Env(void) { - vdp1_env_t env; - vdp1_env_default_init(&env); - - int R = PackedCol_R(clear_color); - int G = PackedCol_G(clear_color); - int B = PackedCol_B(clear_color); - env.erase_color = RGB1555(1, R >> 3, G >> 3, B >> 3); - - vdp1_env_set(&env); -} - -// TODO: should be SCREEN_WIDTH/2 instead ? -static void _primitive_init(void) { - clear_points[0].x = 0; - clear_points[0].y = SCREEN_WIDTH - 1; - - clear_points[1].x = SCREEN_WIDTH - 1; - clear_points[1].y = SCREEN_HEIGHT - 1; - - clear_points[2].x = SCREEN_HEIGHT - 1; - clear_points[2].y = 0; - - clear_points[3].x = 0; - clear_points[3].y = 0; -} - -static GfxResourceID white_square; -void Gfx_RestoreState(void) { - InitDefaultResources(); - - // 2x2 dummy white texture - struct Bitmap bmp; - BitmapCol pixels[4] = { BitmapColor_RGB(255, 0, 0), BITMAPCOLOR_WHITE, BITMAPCOLOR_WHITE, BITMAPCOLOR_WHITE }; - Bitmap_Init(bmp, 2, 2, pixels); - white_square = Gfx_CreateTexture(&bmp, 0, false); -} - -void Gfx_FreeState(void) { - FreeDefaultResources(); - Gfx_DeleteTexture(&white_square); -} - -void Gfx_Create(void) { - if (!Gfx.Created) { - vdp1_vram_partitions_get(&_vdp1_vram_partitions); - // TODO less ram for gourad base - vdp2_scrn_back_color_set(VDP2_VRAM_ADDR(3, 0x01FFFE), - RGB1555(1, 0, 3, 15)); - vdp2_sprite_priority_set(0, 6); - - UpdateVDP1Env(); - _primitive_init(); - } - - Gfx.MinTexWidth = 8; - Gfx.MinTexHeight = 8; - Gfx.MaxTexWidth = 128; - Gfx.MaxTexHeight = 128; - Gfx.Created = true; -} - -void Gfx_Free(void) { - Gfx_FreeState(); -} - - -/*########################################################################################################################* -*---------------------------------------------------------Textures--------------------------------------------------------* -*#########################################################################################################################*/ -#define BGRA8_to_SATURN(src) \ - ((src[2] & 0xF8) >> 3) | ((src[1] & 0xF8) << 2) | ((src[0] & 0xF8) << 7) | ((src[3] & 0x80) << 8) - -static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { - cc_uint16* tmp = Mem_TryAlloc(bmp->width * bmp->height, 2); - if (!tmp) return NULL; - - for (int y = 0; y < bmp->height; y++) - { - cc_uint32* src = bmp->scan0 + y * rowWidth; - cc_uint16* dst = tmp + y * bmp->width; - - for (int x = 0; x < bmp->width; x++) - { - cc_uint8* color = (cc_uint8*)&src[x]; - dst[x] = BGRA8_to_SATURN(color); - } - } - - scu_dma_transfer(0, _vdp1_vram_partitions.texture_base, tmp, bmp->width * bmp->height * 2); - scu_dma_transfer_wait(0); - Mem_Free(tmp); - return (void*)1; -} - -void Gfx_BindTexture(GfxResourceID texId) { -} - -void Gfx_DeleteTexture(GfxResourceID* texId) { -} - -void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { - // TODO -} - -void Gfx_EnableMipmaps(void) { } -void Gfx_DisableMipmaps(void) { } - - -/*########################################################################################################################* -*------------------------------------------------------State management---------------------------------------------------* -*#########################################################################################################################*/ -void Gfx_SetFog(cc_bool enabled) { } -void Gfx_SetFogCol(PackedCol col) { } -void Gfx_SetFogDensity(float value) { } -void Gfx_SetFogEnd(float value) { } -void Gfx_SetFogMode(FogFunc func) { } - -void Gfx_SetFaceCulling(cc_bool enabled) { - // TODO -} - -static void SetAlphaTest(cc_bool enabled) { -} - -static void SetAlphaBlend(cc_bool enabled) { -} - -void Gfx_SetAlphaArgBlend(cc_bool enabled) { } - -void Gfx_ClearBuffers(GfxBuffers buffers) { -} - -void Gfx_ClearColor(PackedCol color) { - if (color == clear_color) return; - - clear_color = color; - UpdateVDP1Env(); -} - -void Gfx_SetDepthTest(cc_bool enabled) { -} - -void Gfx_SetDepthWrite(cc_bool enabled) { - // TODO -} - -static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { - // TODO -} - -void Gfx_DepthOnlyRendering(cc_bool depthOnly) { - cc_bool enabled = !depthOnly; - SetColorWrite(enabled & gfx_colorMask[0], enabled & gfx_colorMask[1], - enabled & gfx_colorMask[2], enabled & gfx_colorMask[3]); -} - - -/*########################################################################################################################* -*-------------------------------------------------------Index buffers-----------------------------------------------------* -*#########################################################################################################################*/ -GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { - return (void*)1; -} - -void Gfx_BindIb(GfxResourceID ib) { } -void Gfx_DeleteIb(GfxResourceID* ib) { } - - -/*########################################################################################################################* -*-------------------------------------------------------Vertex buffers----------------------------------------------------* -*#########################################################################################################################*/ -static void* gfx_vertices; - -static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { - return Mem_TryAlloc(count, strideSizes[fmt]); -} - -void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } - -void Gfx_DeleteVb(GfxResourceID* vb) { - GfxResourceID data = *vb; - if (data) Mem_Free(data); - *vb = 0; -} - -void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { - return vb; -} - -void Gfx_UnlockVb(GfxResourceID vb) { - gfx_vertices = vb; -} - - -static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { - return Mem_TryAlloc(maxVertices, strideSizes[fmt]); -} - -void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } - -void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { - return vb; -} - -void Gfx_UnlockDynamicVb(GfxResourceID vb) { - gfx_vertices = vb; -} - -void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } - - -/*########################################################################################################################* -*---------------------------------------------------------Matrices--------------------------------------------------------* -*#########################################################################################################################*/ -static struct Matrix _view, _proj, mvp; - -void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { - if (type == MATRIX_VIEW) _view = *matrix; - if (type == MATRIX_PROJECTION) _proj = *matrix; - - Matrix_Mul(&mvp, &_view, &_proj); -} - -void Gfx_LoadIdentityMatrix(MatrixType type) { - Gfx_LoadMatrix(type, &Matrix_Identity); -} - -void Gfx_EnableTextureOffset(float x, float y) { - // TODO -} - -void Gfx_DisableTextureOffset(void) { - // TODO -} - -void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float zNear, float zFar) { - /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterrh */ - /* The simplified calculation below uses: L = 0, R = width, T = 0, B = height */ - /* NOTE: This calculation is shared with Direct3D 11 backend */ - *matrix = Matrix_Identity; - - matrix->row1.x = 2.0f / width; - matrix->row2.y = -2.0f / height; - matrix->row3.z = 1.0f / (zNear - zFar); - - matrix->row4.x = -1.0f; - matrix->row4.y = 1.0f; - matrix->row4.z = zNear / (zNear - zFar); -} - -static float Cotangent(float x) { return Math_CosF(x) / Math_SinF(x); } -void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, float zFar) { - float zNear = 0.01f; - /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovrh */ - float c = Cotangent(0.5f * fov); - *matrix = Matrix_Identity; - - matrix->row1.x = c / aspect; - matrix->row2.y = c; - matrix->row3.z = zFar / (zNear - zFar); - matrix->row3.w = -1.0f; - matrix->row4.z = (zNear * zFar) / (zNear - zFar); - matrix->row4.w = 0.0f; -} - - -/*########################################################################################################################* -*---------------------------------------------------------Rendering-------------------------------------------------------* -*#########################################################################################################################*/ -void Gfx_SetVertexFormat(VertexFormat fmt) { - gfx_format = fmt; - gfx_stride = strideSizes[fmt]; -} - -void Gfx_DrawVb_Lines(int verticesCount) { - -} - -static void Transform(Vec3* result, struct VertexTextured* a, const struct Matrix* mat) { - /* a could be pointing to result - therefore can't directly assign X/Y/Z */ - float x = a->x * mat->row1.x + a->y * mat->row2.x + a->z * mat->row3.x + mat->row4.x; - float y = a->x * mat->row1.y + a->y * mat->row2.y + a->z * mat->row3.y + mat->row4.y; - float z = a->x * mat->row1.z + a->y * mat->row2.z + a->z * mat->row3.z + mat->row4.z; - float w = a->x * mat->row1.w + a->y * mat->row2.w + a->z * mat->row3.w + mat->row4.w; - - result->x = (x/w) * (320/2); - result->y = (y/w) * -(224/2); - result->z = (z/w) * 1024; -} - -#define IsPointCulled(vec) vec.x < -10000 || vec.x > 10000 || vec.y < -10000 || vec.y > 10000 || vec.z < 0 || vec.z > 1024 - -static void DrawTexturedQuads2D(int verticesCount, int startVertex) { - for (int i = 0; i < verticesCount; i += 4) - { - struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i; - - int16_vec2_t points[4]; - points[0].x = v[0].x; points[0].y = v[0].y; - points[1].x = v[1].x; points[1].y = v[1].y; - points[2].x = v[2].x; points[2].y = v[2].y; - points[3].x = v[3].x; points[3].y = v[3].y; - - int R = PackedCol_R(v->Col); - int G = PackedCol_G(v->Col); - int B = PackedCol_B(v->Col); - - vdp1_cmdt_t* cmd; - - cmd = NextPrimitive(); - vdp1_cmdt_polygon_set(cmd); - vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); - vdp1_cmdt_draw_mode_set(cmd, _primitive_draw_mode); - vdp1_cmdt_vtx_set(cmd, points); - } -} - -static void DrawTexturedQuads3D(int verticesCount, int startVertex) { - for (int i = 0; i < verticesCount; i += 4) - { - struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i; - - Vec3 coords[4]; - Transform(&coords[0], &v[0], &mvp); - Transform(&coords[1], &v[1], &mvp); - Transform(&coords[2], &v[2], &mvp); - Transform(&coords[3], &v[3], &mvp); - - int16_vec2_t points[4]; - points[0].x = coords[0].x; points[0].y = coords[0].y; - points[1].x = coords[1].x; points[1].y = coords[1].y; - points[2].x = coords[2].x; points[2].y = coords[2].y; - points[3].x = coords[3].x; points[3].y = coords[3].y; - - if (IsPointCulled(coords[0])) continue; - if (IsPointCulled(coords[1])) continue; - if (IsPointCulled(coords[2])) continue; - if (IsPointCulled(coords[3])) continue; - - int R = PackedCol_R(v->Col); - int G = PackedCol_G(v->Col); - int B = PackedCol_B(v->Col); - - vdp1_cmdt_t* cmd; - - cmd = NextPrimitive(); - vdp1_cmdt_polygon_set(cmd); - vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); - vdp1_cmdt_draw_mode_set(cmd, _primitive_draw_mode); - vdp1_cmdt_vtx_set(cmd, points); - } -} - -void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - DrawTexturedQuads3D(verticesCount, startVertex); - } -} - -void Gfx_DrawVb_IndexedTris(int verticesCount) { - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - DrawTexturedQuads3D(verticesCount, 0); - } -} - -void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { - DrawTexturedQuads3D(verticesCount, startVertex); -} - - -/*########################################################################################################################* -*---------------------------------------------------------Other/Misc------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Gfx_TakeScreenshot(struct Stream* output) { - return ERR_NOT_SUPPORTED; -} - -cc_bool Gfx_WarnIfNecessary(void) { - return false; -} - -void Gfx_BeginFrame(void) { - Platform_LogConst("FRAME BEG"); - cmdts_count = 0; - - static const int16_vec2_t system_clip_coord = { SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 }; - static const int16_vec2_t local_coord_center = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 }; - - vdp1_cmdt_t* cmd; - - cmd = NextPrimitive(); - vdp1_cmdt_system_clip_coord_set(cmd); - vdp1_cmdt_vtx_system_clip_coord_set(cmd, system_clip_coord); - - cmd = NextPrimitive(); - vdp1_cmdt_local_coord_set(cmd); - vdp1_cmdt_vtx_local_coord_set(cmd, local_coord_center); - - int R = PackedCol_R(clear_color); - int G = PackedCol_G(clear_color); - int B = PackedCol_B(clear_color); - - cmd = NextPrimitive(); - vdp1_cmdt_polygon_set(cmd); - vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); // TODO VDP1 erase - vdp1_cmdt_draw_mode_set(cmd, _primitive_draw_mode); - vdp1_cmdt_vtx_set(cmd, clear_points); -} - -void Gfx_EndFrame(void) { - Platform_LogConst("FRAME END"); - vdp1_cmdt_t* cmd; - - cmd = NextPrimitive(); - vdp1_cmdt_end_set(cmd); - - vdp1_cmdt_list_t cmdt_list; - cmdt_list.cmdts = cmdts_all; - cmdt_list.count = cmdts_count; - vdp1_sync_cmdt_list_put(&cmdt_list, 0); - - vdp1_sync_render(); - vdp1_sync(); - vdp2_sync(); - vdp2_sync_wait(); - - if (gfx_minFrameMs) LimitFPS(); -} - -void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) { - gfx_minFrameMs = minFrameMs; - gfx_vsync = vsync; -} - -void Gfx_OnWindowResize(void) { - // TODO -} - -void Gfx_SetViewport(int x, int y, int w, int h) { } - -void Gfx_GetApiInfo(cc_string* info) { - String_AppendConst(info, "-- Using Saturn --\n"); - PrintMaxTextureInfo(info); -} - -cc_bool Gfx_TryRestoreContext(void) { return true; } -#endif +#include "Core.h" +#if defined CC_BUILD_SATURN +#include "_GraphicsBase.h" +#include "Errors.h" +#include "Window.h" +#include +#include +#include +#include + + +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 224 + +#define PRIMITIVE_DRAW_MODE_NORMAL (0) +#define PRIMITIVE_DRAW_MODE_MESH (1) +#define PRIMITIVE_DRAW_MODE_SHADOW (2) +#define PRIMITIVE_DRAW_MODE_HALF_LUMINANCE (3) +#define PRIMITIVE_DRAW_MODE_HALF_TRANSPARENT (4) +#define PRIMITIVE_DRAW_MODE_GOURAUD_SHADING (5) +#define PRIMITIVE_DRAW_MODE_GOURAUD_HALF_LUM (6) +#define PRIMITIVE_DRAW_MODE_GOURAUD_HALF_TRANS (7) +#define PRIMITIVE_DRAW_MODE_COUNT (8) + +#define PRIMITIVE_COLOR RGB1555(1, 31, 0, 31) + +#define CMDS_COUNT 400 + +static PackedCol clear_color; +static vdp1_cmdt_t cmdts_all[CMDS_COUNT]; +static int cmdts_count; +static vdp1_vram_partitions_t _vdp1_vram_partitions; + +static vdp1_cmdt_t* NextPrimitive(void) { + if (cmdts_count >= CMDS_COUNT) Logger_Abort("Too many VDP1 commands"); + return &cmdts_all[cmdts_count++]; +} + +static vdp1_cmdt_draw_mode_t _primitive_draw_mode = { + .raw = 0x0000 +}; + +static int16_vec2_t clear_points[4]; + + +// TODO: how to use VDP1 erase ?? +static void UpdateVDP1Env(void) { + vdp1_env_t env; + vdp1_env_default_init(&env); + + int R = PackedCol_R(clear_color); + int G = PackedCol_G(clear_color); + int B = PackedCol_B(clear_color); + env.erase_color = RGB1555(1, R >> 3, G >> 3, B >> 3); + + vdp1_env_set(&env); +} + +// TODO: should be SCREEN_WIDTH/2 instead ? +static void _primitive_init(void) { + clear_points[0].x = 0; + clear_points[0].y = SCREEN_WIDTH - 1; + + clear_points[1].x = SCREEN_WIDTH - 1; + clear_points[1].y = SCREEN_HEIGHT - 1; + + clear_points[2].x = SCREEN_HEIGHT - 1; + clear_points[2].y = 0; + + clear_points[3].x = 0; + clear_points[3].y = 0; +} + +static GfxResourceID white_square; +void Gfx_RestoreState(void) { + InitDefaultResources(); + + // 2x2 dummy white texture + struct Bitmap bmp; + BitmapCol pixels[4] = { BitmapColor_RGB(255, 0, 0), BITMAPCOLOR_WHITE, BITMAPCOLOR_WHITE, BITMAPCOLOR_WHITE }; + Bitmap_Init(bmp, 2, 2, pixels); + white_square = Gfx_CreateTexture(&bmp, 0, false); +} + +void Gfx_FreeState(void) { + FreeDefaultResources(); + Gfx_DeleteTexture(&white_square); +} + +void Gfx_Create(void) { + if (!Gfx.Created) { + vdp1_vram_partitions_get(&_vdp1_vram_partitions); + // TODO less ram for gourad base + vdp2_scrn_back_color_set(VDP2_VRAM_ADDR(3, 0x01FFFE), + RGB1555(1, 0, 3, 15)); + vdp2_sprite_priority_set(0, 6); + + UpdateVDP1Env(); + _primitive_init(); + } + + Gfx.MinTexWidth = 8; + Gfx.MinTexHeight = 8; + Gfx.MaxTexWidth = 128; + Gfx.MaxTexHeight = 128; + Gfx.Created = true; +} + +void Gfx_Free(void) { + Gfx_FreeState(); +} + + +/*########################################################################################################################* +*---------------------------------------------------------Textures--------------------------------------------------------* +*#########################################################################################################################*/ +#define BGRA8_to_SATURN(src) \ + ((src[2] & 0xF8) >> 3) | ((src[1] & 0xF8) << 2) | ((src[0] & 0xF8) << 7) | ((src[3] & 0x80) << 8) + +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { + cc_uint16* tmp = Mem_TryAlloc(bmp->width * bmp->height, 2); + if (!tmp) return NULL; + + for (int y = 0; y < bmp->height; y++) + { + cc_uint32* src = bmp->scan0 + y * rowWidth; + cc_uint16* dst = tmp + y * bmp->width; + + for (int x = 0; x < bmp->width; x++) + { + cc_uint8* color = (cc_uint8*)&src[x]; + dst[x] = BGRA8_to_SATURN(color); + } + } + + scu_dma_transfer(0, _vdp1_vram_partitions.texture_base, tmp, bmp->width * bmp->height * 2); + scu_dma_transfer_wait(0); + Mem_Free(tmp); + return (void*)1; +} + +void Gfx_BindTexture(GfxResourceID texId) { +} + +void Gfx_DeleteTexture(GfxResourceID* texId) { +} + +void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { + // TODO +} + +void Gfx_EnableMipmaps(void) { } +void Gfx_DisableMipmaps(void) { } + + +/*########################################################################################################################* +*------------------------------------------------------State management---------------------------------------------------* +*#########################################################################################################################*/ +void Gfx_SetFog(cc_bool enabled) { } +void Gfx_SetFogCol(PackedCol col) { } +void Gfx_SetFogDensity(float value) { } +void Gfx_SetFogEnd(float value) { } +void Gfx_SetFogMode(FogFunc func) { } + +void Gfx_SetFaceCulling(cc_bool enabled) { + // TODO +} + +static void SetAlphaTest(cc_bool enabled) { +} + +static void SetAlphaBlend(cc_bool enabled) { +} + +void Gfx_SetAlphaArgBlend(cc_bool enabled) { } + +void Gfx_ClearBuffers(GfxBuffers buffers) { +} + +void Gfx_ClearColor(PackedCol color) { + if (color == clear_color) return; + + clear_color = color; + UpdateVDP1Env(); +} + +void Gfx_SetDepthTest(cc_bool enabled) { +} + +void Gfx_SetDepthWrite(cc_bool enabled) { + // TODO +} + +static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { + // TODO +} + +void Gfx_DepthOnlyRendering(cc_bool depthOnly) { + cc_bool enabled = !depthOnly; + SetColorWrite(enabled & gfx_colorMask[0], enabled & gfx_colorMask[1], + enabled & gfx_colorMask[2], enabled & gfx_colorMask[3]); +} + + +/*########################################################################################################################* +*-------------------------------------------------------Index buffers-----------------------------------------------------* +*#########################################################################################################################*/ +GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { + return (void*)1; +} + +void Gfx_BindIb(GfxResourceID ib) { } +void Gfx_DeleteIb(GfxResourceID* ib) { } + + +/*########################################################################################################################* +*-------------------------------------------------------Vertex buffers----------------------------------------------------* +*#########################################################################################################################*/ +static void* gfx_vertices; + +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { + return Mem_TryAlloc(count, strideSizes[fmt]); +} + +void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } + +void Gfx_DeleteVb(GfxResourceID* vb) { + GfxResourceID data = *vb; + if (data) Mem_Free(data); + *vb = 0; +} + +void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { + return vb; +} + +void Gfx_UnlockVb(GfxResourceID vb) { + gfx_vertices = vb; +} + + +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return Mem_TryAlloc(maxVertices, strideSizes[fmt]); +} + +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + return vb; +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { + gfx_vertices = vb; +} + +void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } + + +/*########################################################################################################################* +*---------------------------------------------------------Matrices--------------------------------------------------------* +*#########################################################################################################################*/ +static struct Matrix _view, _proj, mvp; + +void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { + if (type == MATRIX_VIEW) _view = *matrix; + if (type == MATRIX_PROJECTION) _proj = *matrix; + + Matrix_Mul(&mvp, &_view, &_proj); +} + +void Gfx_LoadIdentityMatrix(MatrixType type) { + Gfx_LoadMatrix(type, &Matrix_Identity); +} + +void Gfx_EnableTextureOffset(float x, float y) { + // TODO +} + +void Gfx_DisableTextureOffset(void) { + // TODO +} + +void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float zNear, float zFar) { + /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterrh */ + /* The simplified calculation below uses: L = 0, R = width, T = 0, B = height */ + /* NOTE: This calculation is shared with Direct3D 11 backend */ + *matrix = Matrix_Identity; + + matrix->row1.x = 2.0f / width; + matrix->row2.y = -2.0f / height; + matrix->row3.z = 1.0f / (zNear - zFar); + + matrix->row4.x = -1.0f; + matrix->row4.y = 1.0f; + matrix->row4.z = zNear / (zNear - zFar); +} + +static float Cotangent(float x) { return Math_CosF(x) / Math_SinF(x); } +void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, float zFar) { + float zNear = 0.01f; + /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovrh */ + float c = Cotangent(0.5f * fov); + *matrix = Matrix_Identity; + + matrix->row1.x = c / aspect; + matrix->row2.y = c; + matrix->row3.z = zFar / (zNear - zFar); + matrix->row3.w = -1.0f; + matrix->row4.z = (zNear * zFar) / (zNear - zFar); + matrix->row4.w = 0.0f; +} + + +/*########################################################################################################################* +*---------------------------------------------------------Rendering-------------------------------------------------------* +*#########################################################################################################################*/ +void Gfx_SetVertexFormat(VertexFormat fmt) { + gfx_format = fmt; + gfx_stride = strideSizes[fmt]; +} + +void Gfx_DrawVb_Lines(int verticesCount) { + +} + +static void Transform(Vec3* result, struct VertexTextured* a, const struct Matrix* mat) { + /* a could be pointing to result - therefore can't directly assign X/Y/Z */ + float x = a->x * mat->row1.x + a->y * mat->row2.x + a->z * mat->row3.x + mat->row4.x; + float y = a->x * mat->row1.y + a->y * mat->row2.y + a->z * mat->row3.y + mat->row4.y; + float z = a->x * mat->row1.z + a->y * mat->row2.z + a->z * mat->row3.z + mat->row4.z; + float w = a->x * mat->row1.w + a->y * mat->row2.w + a->z * mat->row3.w + mat->row4.w; + + result->x = (x/w) * (SCREEN_WIDTH / 2); + result->y = (y/w) * -(SCREEN_HEIGHT / 2); + result->z = (z/w) * 1024; +} + +#define IsPointCulled(vec) vec.x < -10000 || vec.x > 10000 || vec.y < -10000 || vec.y > 10000 || vec.z < 0 || vec.z > 1024 + +static void DrawTexturedQuads2D(int verticesCount, int startVertex) { + for (int i = 0; i < verticesCount; i += 4) + { + struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i; + + int16_vec2_t points[4]; + points[0].x = (int)v[0].x - SCREEN_WIDTH / 2; points[0].y = (int)v[0].y - SCREEN_HEIGHT / 2; + points[1].x = (int)v[1].x - SCREEN_WIDTH / 2; points[1].y = (int)v[1].y - SCREEN_HEIGHT / 2; + points[2].x = (int)v[2].x - SCREEN_WIDTH / 2; points[2].y = (int)v[2].y - SCREEN_HEIGHT / 2; + points[3].x = (int)v[3].x - SCREEN_WIDTH / 2; points[3].y = (int)v[3].y - SCREEN_HEIGHT / 2; + + int R = PackedCol_R(v->Col); + int G = PackedCol_G(v->Col); + int B = PackedCol_B(v->Col); + + vdp1_cmdt_t* cmd; + + cmd = NextPrimitive(); + vdp1_cmdt_polygon_set(cmd); + vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); + vdp1_cmdt_draw_mode_set(cmd, _primitive_draw_mode); + vdp1_cmdt_vtx_set(cmd, points); + } +} + +static void DrawTexturedQuads3D(int verticesCount, int startVertex) { + for (int i = 0; i < verticesCount; i += 4) + { + struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i; + + Vec3 coords[4]; + Transform(&coords[0], &v[0], &mvp); + Transform(&coords[1], &v[1], &mvp); + Transform(&coords[2], &v[2], &mvp); + Transform(&coords[3], &v[3], &mvp); + + int16_vec2_t points[4]; + points[0].x = coords[0].x; points[0].y = coords[0].y; + points[1].x = coords[1].x; points[1].y = coords[1].y; + points[2].x = coords[2].x; points[2].y = coords[2].y; + points[3].x = coords[3].x; points[3].y = coords[3].y; + + if (IsPointCulled(coords[0])) continue; + if (IsPointCulled(coords[1])) continue; + if (IsPointCulled(coords[2])) continue; + if (IsPointCulled(coords[3])) continue; + + int R = PackedCol_R(v->Col); + int G = PackedCol_G(v->Col); + int B = PackedCol_B(v->Col); + + vdp1_cmdt_t* cmd; + + cmd = NextPrimitive(); + vdp1_cmdt_polygon_set(cmd); + vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); + vdp1_cmdt_draw_mode_set(cmd, _primitive_draw_mode); + vdp1_cmdt_vtx_set(cmd, points); + } +} + +void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { + if (gfx_rendering2D && gfx_format == VERTEX_FORMAT_TEXTURED) { + DrawTexturedQuads2D(verticesCount, startVertex); + } else if (gfx_format == VERTEX_FORMAT_TEXTURED) { + DrawTexturedQuads3D(verticesCount, startVertex); + } +} + +void Gfx_DrawVb_IndexedTris(int verticesCount) { + if (gfx_rendering2D && gfx_format == VERTEX_FORMAT_TEXTURED) { + DrawTexturedQuads2D(verticesCount, 0); + } else if (gfx_format == VERTEX_FORMAT_TEXTURED) { + DrawTexturedQuads3D(verticesCount, 0); + } +} + +void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { + DrawTexturedQuads3D(verticesCount, startVertex); +} + + +/*########################################################################################################################* +*---------------------------------------------------------Other/Misc------------------------------------------------------* +*#########################################################################################################################*/ +cc_result Gfx_TakeScreenshot(struct Stream* output) { + return ERR_NOT_SUPPORTED; +} + +cc_bool Gfx_WarnIfNecessary(void) { + return false; +} + +void Gfx_BeginFrame(void) { + Platform_LogConst("FRAME BEG"); + cmdts_count = 0; + + static const int16_vec2_t system_clip_coord = { SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 }; + static const int16_vec2_t local_coord_center = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 }; + + vdp1_cmdt_t* cmd; + + cmd = NextPrimitive(); + vdp1_cmdt_system_clip_coord_set(cmd); + vdp1_cmdt_vtx_system_clip_coord_set(cmd, system_clip_coord); + + cmd = NextPrimitive(); + vdp1_cmdt_local_coord_set(cmd); + vdp1_cmdt_vtx_local_coord_set(cmd, local_coord_center); + + int R = PackedCol_R(clear_color); + int G = PackedCol_G(clear_color); + int B = PackedCol_B(clear_color); + + cmd = NextPrimitive(); + vdp1_cmdt_polygon_set(cmd); + vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); // TODO VDP1 erase + vdp1_cmdt_draw_mode_set(cmd, _primitive_draw_mode); + vdp1_cmdt_vtx_set(cmd, clear_points); +} + +void Gfx_EndFrame(void) { + Platform_LogConst("FRAME END"); + vdp1_cmdt_t* cmd; + + cmd = NextPrimitive(); + vdp1_cmdt_end_set(cmd); + + vdp1_cmdt_list_t cmdt_list; + cmdt_list.cmdts = cmdts_all; + cmdt_list.count = cmdts_count; + vdp1_sync_cmdt_list_put(&cmdt_list, 0); + + vdp1_sync_render(); + vdp1_sync(); + vdp2_sync(); + vdp2_sync_wait(); + + if (gfx_minFrameMs) LimitFPS(); +} + +void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) { + gfx_minFrameMs = minFrameMs; + gfx_vsync = vsync; +} + +void Gfx_OnWindowResize(void) { + // TODO +} + +void Gfx_SetViewport(int x, int y, int w, int h) { } + +void Gfx_GetApiInfo(cc_string* info) { + String_AppendConst(info, "-- Using Saturn --\n"); + PrintMaxTextureInfo(info); +} + +cc_bool Gfx_TryRestoreContext(void) { return true; } +#endif diff --git a/src/Platform_Saturn.c b/src/Platform_Saturn.c index a39079407..449d72c69 100644 --- a/src/Platform_Saturn.c +++ b/src/Platform_Saturn.c @@ -64,13 +64,17 @@ cc_uint64 Stopwatch_Measure(void) { cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { if (end < beg) return 0; - return (end - beg); // TODO measure time + cc_uint32 delta = end - beg; + + // TODO still wrong?? and overflows?? and PAL detection ??? + return (delta * 1000) / CPU_FRT_NTSC_320_128_COUNT_1MS; } static void ovf_handler(void) { overflow_count++; } static void Stopwatch_Init(void) { - cpu_frt_init(CPU_FRT_CLOCK_DIV_8); + //cpu_frt_init(CPU_FRT_CLOCK_DIV_8); + cpu_frt_init(CPU_FRT_CLOCK_DIV_128); cpu_frt_ovi_set(ovf_handler); cpu_frt_interrupt_priority_set(15); diff --git a/src/Window_Web.c b/src/Window_Web.c index b16358a8f..64b753bc0 100644 --- a/src/Window_Web.c +++ b/src/Window_Web.c @@ -252,7 +252,8 @@ static int MapNativeKey(int k, int l) { case DOM_VK_VOLUME_DOWN: return CCKEY_VOLUME_DOWN; case DOM_VK_VOLUME_UP: return CCKEY_VOLUME_UP; - case 173: return CCKEY_VOLUME_MUTE; + /* Chrome specific keys */ + /*case 173: return CCKEY_VOLUME_MUTE; same as DOM_VK_HYPHEN_MINUS */ case 174: return CCKEY_VOLUME_DOWN; case 175: return CCKEY_VOLUME_UP; case 176: return CCKEY_MEDIA_NEXT; diff --git a/src/Window_Win.c b/src/Window_Win.c index f1cf66e32..8124559d4 100644 --- a/src/Window_Win.c +++ b/src/Window_Win.c @@ -52,7 +52,7 @@ static int win_totalWidth, win_totalHeight; /* Size of window including titlebar static cc_bool is_ansiWindow, grabCursor; static int windowX, windowY; -static const cc_uint8 key_map[14 * 16] = { +static const cc_uint8 key_map[] = { /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, CCKEY_BACKSPACE, CCKEY_TAB, 0, 0, CCKEY_F5, CCKEY_ENTER, 0, 0, /* 10 */ 0, 0, 0, CCKEY_PAUSE, CCKEY_CAPSLOCK, 0, 0, 0, 0, 0, 0, CCKEY_ESCAPE, 0, 0, 0, 0, /* 20 */ CCKEY_SPACE, CCKEY_PAGEUP, CCKEY_PAGEDOWN, CCKEY_END, CCKEY_HOME, CCKEY_LEFT, CCKEY_UP, CCKEY_RIGHT, CCKEY_DOWN, 0, CCKEY_PRINTSCREEN, 0, CCKEY_PRINTSCREEN, CCKEY_INSERT, CCKEY_DELETE, 0,