Texture render support (#934)

Technically unimpressive, but I had to go through quite a good amount of
changes. Here is the full changelog to make everything work:

* Ensure `ResetPlatform` is always called to avoid memory leaks
* Add `g_RawVram` to emulate the PS1 VRAM
* ~~The engine will load the optional file `disks/vram.bin`, a RAM dump
from an emulator~~
* SDL2 will create 256x256 textures on-the-fly whenever a specific tpage
is requested via `GetVramTexture`
* The function `GetVramTexture` caches the last called tpage to avoid
tanking the performance
* `GetVramTexture` for only renders 4bpp and 8bpp textures with their
specified palette
* Remove `SDL2_image` as the font is now loaded straight from the VRAM
* Calling `VSync` will call the set callback, which the game uses for
DMA operations
* `MyLoadImage` is not yet implemented, but it is a placeholder to then
interact with `g_RawVram`
* The menu font now uses the texture found in the VRAM
* Plugged a custom version of `LoadFileSim`
* The file `sim_pc.c` is similar to the original game's code but it is
used here to load files from custom paths
* Using F5, F6 or F7 can dump the VRAM content on-screen, respectively
in 16bpp, 8bpp and 4bpp

There are new graphical glitches on the font. In some occasions it
appears black. It seems to be related to a flag in `P_TAG.code`. I plan
to dig into it when I can render entities on screen to avoid potential
mistakes. The same problem is present for the first half of Alucard's
portrait. It seems to be related when a texture is transparent? 🤷

I am not sure why the font is completely corrupted when entering in the
Equip menu. It is hard to understand if I introduced any regression.
Maybe the glitch was always there but it was hidden since I was always
forcing the font texture to be rendered.

EDIT: Implemented `LoadImage`, `SaveImage` and `ClearImage`
This commit is contained in:
Luciano Ciccariello 2024-01-02 00:31:56 +01:00 committed by GitHub
parent 1c0debf74d
commit 0df33d1975
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 717 additions and 347 deletions

View File

@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Install requirements
run: sudo apt-get install build-essential libsdl2-dev libsdl2-image-dev
run: sudo apt-get install build-essential libsdl2-dev
- name: Clone repo
uses: actions/checkout@v3
with:
@ -40,9 +40,6 @@ jobs:
mkdir C:\temp-sdl2
powershell Invoke-WebRequest 'https://github.com/libsdl-org/SDL/releases/download/release-2.28.5/SDL2-devel-2.28.5-VC.zip' -OutFile C:\temp-sdl2\SDL2-devel-2.28.5-VC.zip
7z x C:\temp-sdl2\SDL2-devel-2.28.5-VC.zip -oC:\temp-sdl2
mkdir C:\temp-sdl2_image
powershell Invoke-WebRequest 'https://github.com/libsdl-org/SDL_image/releases/download/release-2.8.1/SDL2_image-devel-2.8.1-VC.zip' -OutFile C:\temp-sdl2_image\SDL2_image-devel-2.8.1-VC.zip
7z x C:\temp-sdl2_image\SDL2_image-devel-2.8.1-VC.zip -oC:\temp-sdl2_image
- name: Configure CMake
run: cmake -B ${{github.workspace}}/cmake_build -DCMAKE_BUILD_TYPE=Release -DSDL2_PATH=C:\temp-sdl2\SDL2-2.28.5 -DSDL2_IMAGE_PATH=C:\temp-sdl2_image\SDL2_image-2.8.1

View File

@ -8,7 +8,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)
set(SOURCE_FILES_PC
src/pc/main.c
@ -17,6 +16,7 @@ set(SOURCE_FILES_PC
src/pc/sotn.c
src/pc/pc.c
src/pc/sdl2.c
src/pc/sim_pc.c
)
if(WIN32)
@ -51,6 +51,7 @@ set(SOURCE_FILES_DRA
src/dra/play.c
src/dra/loading.c
src/dra/pads.c
src/dra/lba_stage.c
src/dra/save_mgr_pre.c
src/dra/save_mgr.c
src/dra/4A538.c
@ -79,7 +80,6 @@ add_executable(${PROJECT_NAME}
target_include_directories(${PROJECT_NAME} PRIVATE
${SDL2_INCLUDE_DIRS}
${SDL2_IMAGE_INCLUDE_DIRS}
include
src/dra
src/pc/3rd
@ -87,7 +87,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE
target_link_libraries(${PROJECT_NAME} PRIVATE
${SDL2_LIBRARIES}
${SDL2_IMAGE_LIBRARIES}
)
target_compile_definitions(${PROJECT_NAME} PRIVATE

View File

@ -6,14 +6,14 @@ LD_PC := ld
CC_FLAGS_PC := -c -g -DVERSION_PC -DPERMUTER -DNON_MATCHING -fno-stack-protector
CC_FLAGS_PC += -DDEMO_KEY_PTR=0
CC_FLAGS_PC += -I$(INCLUDE_DIR) -I$(SRC_DIR)/dra/ -I$(SRC_DIR)/pc/3rd
LD_FLAGS_PC := -fsanitize=address -lc -lm -lSDL2 -lSDL2_image
LD_FLAGS_PC := -fsanitize=address -lc -lm -lSDL2
C_FILES_PC := main.c log.c stubs.c sotn.c
C_FILES_PC := main.c log.c stubs.c sotn.c sim_pc.c
C_FILES_PC += pc.c sdl2.c plat_unix.c
C_FILES_PSX_SDK := libgpu/ext.c
C_FILES_MOCK_SDK := libapi.c libetc.c libgpu.c libgte.c libgs.c libcd.c libcard.c libspu.c libsnd.c cdc.c
C_FILES_3RD := cJSON/cJSON.c
C_FILES_DRA := 42398.c play.c loading.c pads.c
C_FILES_DRA := 42398.c play.c loading.c pads.c lba_stage.c
C_FILES_DRA += save_mgr_pre.c save_mgr.c 4A538.c collider.c demo.c
C_FILES_DRA += lang_us.c menu.c 5D6C4.c 627C4.c 63ED4.c
C_FILES_DRA += 91EBC.c 92F60.c 93290.c 93BDC.c 94F50.c 953A0.c

View File

@ -1,222 +0,0 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
# Copyright 2019 Amine Ben Hassouna <amine.benhassouna@gmail.com>
# Copyright 2000-2019 Kitware, Inc. and Contributors
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of Kitware, Inc. nor the names of Contributors
# may be used to endorse or promote products derived from this
# software without specific prior written permission.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#[=======================================================================[.rst:
FindSDL2_image
--------------
Locate SDL2_image library
This module defines the following 'IMPORTED' target:
::
SDL2::Image
The SDL2_image library, if found.
Have SDL2::Core as a link dependency.
This module will set the following variables in your project:
::
SDL2_IMAGE_LIBRARIES, the name of the library to link against
SDL2_IMAGE_INCLUDE_DIRS, where to find the headers
SDL2_IMAGE_FOUND, if false, do not try to link against
SDL2_IMAGE_VERSION_STRING - human-readable string containing the
version of SDL2_image
This module responds to the following cache variables:
::
SDL2_IMAGE_PATH
Set a custom SDL2_image Library path (default: empty)
SDL2_IMAGE_NO_DEFAULT_PATH
Disable search SDL2_image Library in default path.
If SDL2_IMAGE_PATH (default: ON)
Else (default: OFF)
SDL2_IMAGE_INCLUDE_DIR
SDL2_image headers path.
SDL2_IMAGE_LIBRARY
SDL2_image Library (.dll, .so, .a, etc) path.
Additional Note: If you see an empty SDL2_IMAGE_LIBRARY in your project
configuration, it means CMake did not find your SDL2_image library
(SDL2_image.dll, libsdl2_image.so, etc). Set SDL2_IMAGE_LIBRARY to point
to your SDL2_image library, and configure again. This value is used to
generate the final SDL2_IMAGE_LIBRARIES variable and the SDL2::Image target,
but when this value is unset, SDL2_IMAGE_LIBRARIES and SDL2::Image does not
get created.
$SDL2IMAGEDIR is an environment variable that would correspond to the
./configure --prefix=$SDL2IMAGEDIR used in building SDL2_image.
$SDL2DIR is an environment variable that would correspond to the
./configure --prefix=$SDL2DIR used in building SDL2.
Created by Amine Ben Hassouna:
Adapt FindSDL_image.cmake to SDL2_image (FindSDL2_image.cmake).
Add cache variables for more flexibility:
SDL2_IMAGE_PATH, SDL2_IMAGE_NO_DEFAULT_PATH (for details, see doc above).
Add SDL2 as a required dependency.
Modernize the FindSDL2_image.cmake module by creating a specific target:
SDL2::Image (for details, see doc above).
Original FindSDL_image.cmake module:
Created by Eric Wing. This was influenced by the FindSDL.cmake
module, but with modifications to recognize OS X frameworks and
additional Unix paths (FreeBSD, etc).
#]=======================================================================]
# SDL2 Library required
find_package(SDL2 QUIET)
if(NOT SDL2_FOUND)
set(SDL2_IMAGE_SDL2_NOT_FOUND "Could NOT find SDL2 (SDL2 is required by SDL2_image).")
if(SDL2_image_FIND_REQUIRED)
message(FATAL_ERROR ${SDL2_IMAGE_SDL2_NOT_FOUND})
else()
if(NOT SDL2_image_FIND_QUIETLY)
message(STATUS ${SDL2_IMAGE_SDL2_NOT_FOUND})
endif()
return()
endif()
unset(SDL2_IMAGE_SDL2_NOT_FOUND)
endif()
# Define options for searching SDL2_image Library in a custom path
set(SDL2_IMAGE_PATH "" CACHE STRING "Custom SDL2_image Library path")
set(_SDL2_IMAGE_NO_DEFAULT_PATH OFF)
if(SDL2_IMAGE_PATH)
set(_SDL2_IMAGE_NO_DEFAULT_PATH ON)
endif()
set(SDL2_IMAGE_NO_DEFAULT_PATH ${_SDL2_IMAGE_NO_DEFAULT_PATH}
CACHE BOOL "Disable search SDL2_image Library in default path")
unset(_SDL2_IMAGE_NO_DEFAULT_PATH)
set(SDL2_IMAGE_NO_DEFAULT_PATH_CMD)
if(SDL2_IMAGE_NO_DEFAULT_PATH)
set(SDL2_IMAGE_NO_DEFAULT_PATH_CMD NO_DEFAULT_PATH)
endif()
# Search for the SDL2_image include directory
find_path(SDL2_IMAGE_INCLUDE_DIR SDL_image.h
HINTS
ENV SDL2IMAGEDIR
ENV SDL2DIR
${SDL2_IMAGE_NO_DEFAULT_PATH_CMD}
PATH_SUFFIXES SDL2
# path suffixes to search inside ENV{SDL2DIR}
# and ENV{SDL2IMAGEDIR}
include/SDL2 include
PATHS ${SDL2_IMAGE_PATH}
DOC "Where the SDL2_image headers can be found"
)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(VC_LIB_PATH_SUFFIX lib/x64)
else()
set(VC_LIB_PATH_SUFFIX lib/x86)
endif()
# Search for the SDL2_image library
find_library(SDL2_IMAGE_LIBRARY
NAMES SDL2_image
HINTS
ENV SDL2IMAGEDIR
ENV SDL2DIR
${SDL2_IMAGE_NO_DEFAULT_PATH_CMD}
PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX}
PATHS ${SDL2_IMAGE_PATH}
DOC "Where the SDL2_image Library can be found"
)
# Read SDL2_image version
if(SDL2_IMAGE_INCLUDE_DIR AND EXISTS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h")
file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+[0-9]+$")
string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MAJOR "${SDL2_IMAGE_VERSION_MAJOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MINOR "${SDL2_IMAGE_VERSION_MINOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_PATCH "${SDL2_IMAGE_VERSION_PATCH_LINE}")
set(SDL2_IMAGE_VERSION_STRING ${SDL2_IMAGE_VERSION_MAJOR}.${SDL2_IMAGE_VERSION_MINOR}.${SDL2_IMAGE_VERSION_PATCH})
unset(SDL2_IMAGE_VERSION_MAJOR_LINE)
unset(SDL2_IMAGE_VERSION_MINOR_LINE)
unset(SDL2_IMAGE_VERSION_PATCH_LINE)
unset(SDL2_IMAGE_VERSION_MAJOR)
unset(SDL2_IMAGE_VERSION_MINOR)
unset(SDL2_IMAGE_VERSION_PATCH)
endif()
set(SDL2_IMAGE_LIBRARIES ${SDL2_IMAGE_LIBRARY})
set(SDL2_IMAGE_INCLUDE_DIRS ${SDL2_IMAGE_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_image
REQUIRED_VARS SDL2_IMAGE_LIBRARIES SDL2_IMAGE_INCLUDE_DIRS
VERSION_VAR SDL2_IMAGE_VERSION_STRING)
mark_as_advanced(SDL2_IMAGE_PATH
SDL2_IMAGE_NO_DEFAULT_PATH
SDL2_IMAGE_LIBRARY
SDL2_IMAGE_INCLUDE_DIR)
if(SDL2_IMAGE_FOUND)
# SDL2::Image target
if(SDL2_IMAGE_LIBRARY AND NOT TARGET SDL2::Image)
add_library(SDL2::Image UNKNOWN IMPORTED)
set_target_properties(SDL2::Image PROPERTIES
IMPORTED_LOCATION "${SDL2_IMAGE_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${SDL2_IMAGE_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES SDL2::Core)
endif()
endif()

View File

@ -14,6 +14,10 @@
#define DISP_HEIGHT 256
#define SCREEN_SCALE 2
#define VRAM_W 1024
#define VRAM_H 512
#define VRAM_STRIDE 2048
bool FileRead(bool (*cb)(FILE* file), const char* path);
bool FileStringify(bool (*cb)(const char* content), const char* path);
bool FileUseContent(bool (*cb)(void* content), const char* path);

View File

@ -2,10 +2,8 @@
#include <log.h>
#include <psxsdk/kernel.h>
int VSync(int mode) {
DEBUGF("dummy");
return 0;
}
int MyVSync(int mode);
int VSync(int mode) { return MyVSync(mode); }
long SetRCnt(unsigned long a, unsigned short b, long c) { NOT_IMPLEMENTED; }

View File

@ -8,7 +8,7 @@ void PadInit(int mode) { MyPadInit(mode); }
u_long MyPadRead(int id);
u_long PadRead(int id) { return MyPadRead(id); }
int VSyncCallback(void (*f)()) { NOT_IMPLEMENTED; }
int VSyncCallback(void (*f)()) { return MyVSyncCallback(f); }
int VSyncCallbacks(int ch, void (*f)()) { NOT_IMPLEMENTED; }

View File

@ -25,9 +25,11 @@ void SetDumpFnt(int id) { NOT_IMPLEMENTED; }
void SetDispMask(int mask) { NOT_IMPLEMENTED; }
int ClearImage(RECT* rect, u_char r, u_char g, u_char b) { NOT_IMPLEMENTED; }
int LoadImage(RECT* rect, u_long* p) { NOT_IMPLEMENTED; }
int StoreImage(RECT* rect, u_long* p) { NOT_IMPLEMENTED; }
int ClearImage(RECT* rect, u_char r, u_char g, u_char b) {
return MyClearImage(rect, r, g, b);
}
int LoadImage(RECT* rect, u_long* p) { return MyLoadImage(rect, p); }
int StoreImage(RECT* rect, u_long* p) { return MyStoreImage(rect, p); }
int MoveImage(RECT* rect, int x, int y) { NOT_IMPLEMENTED; }
int MyDrawSync(int mode);

View File

@ -1,35 +1,42 @@
#include <common.h>
#include <log.h>
#include <game.h>
#include <stdlib.h>
#ifdef _MSC_VER
#include <SDL.h>
#include <SDL_image.h>
#else
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#endif
#include "pc.h"
typedef enum {
DEBUG_SDL_NONE,
DEBUG_SDL_SHOW_VRAM_16bpp,
DEBUG_SDL_SHOW_VRAM_8bpp,
DEBUG_SDL_SHOW_VRAM_4bpp,
} DebugSdl;
extern bool g_IsQuitRequested;
extern u16 g_RawVram[VRAM_W * VRAM_H];
SDL_Window* g_Window = NULL;
SDL_Renderer* g_Renderer = NULL;
SDL_AudioSpec g_SdlAudioSpecs = {0};
SDL_AudioDeviceID g_SdlAudioDevice = {0};
SDL_Surface* g_SdlVramSurfaces[0x20];
SDL_Texture* g_SdlVramTextures[0x20];
DebugSdl g_DebugSdl = DEBUG_SDL_NONE;
unsigned int g_Tpage = 0;
static SDL_Texture* g_VramTex = NULL;
static int g_LastVramTexTpage = -1;
static int g_LastVramTexClut = -1;
void ResetPlatform(void);
bool InitPlatform() {
atexit(ResetPlatform);
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
ERRORF("SDL_Init: %s", SDL_GetError());
return false;
}
if (!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)) {
ERRORF("IMG_Init: %s", SDL_GetError());
return false;
}
g_Window = SDL_CreateWindow(
"SOTN", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
DISP_WIDTH * SCREEN_SCALE, DISP_HEIGHT * SCREEN_SCALE,
@ -45,20 +52,27 @@ bool InitPlatform() {
ERRORF("SDL_CreateRenderer: %s", SDL_GetError());
return false;
}
SDL_SetRenderDrawBlendMode(g_Renderer, SDL_BLENDMODE_BLEND);
g_VramTex = SDL_CreateTexture(g_Renderer, SDL_PIXELFORMAT_ABGR1555,
SDL_TEXTUREACCESS_STREAMING, 256, 256);
if (!g_VramTex) {
ERRORF("unable to create VRAM texture: %s", SDL_GetError());
return false;
}
SDL_SetTextureBlendMode(g_VramTex, SDL_BLENDMODE_BLEND);
memset(g_SdlVramSurfaces, 0, sizeof(g_SdlVramSurfaces));
memset(g_SdlVramTextures, 0, sizeof(g_SdlVramTextures));
g_Tpage = 0;
return true;
}
void ResetPlatform() {
for (int i = 0; i < sizeof(g_SdlVramTextures); i++) {
SDL_DestroyTexture(g_SdlVramTextures[i]);
}
for (int i = 0; i < sizeof(g_SdlVramSurfaces); i++) {
SDL_FreeSurface(g_SdlVramSurfaces[i]);
void ResetPlatform(void) {
g_Tpage = 0;
g_LastVramTexTpage = -1;
g_LastVramTexClut = -1;
if (g_VramTex) {
SDL_DestroyTexture(g_VramTex);
g_VramTex = NULL;
}
if (g_Renderer) {
@ -71,52 +85,9 @@ void ResetPlatform() {
g_Window = NULL;
}
IMG_Quit();
SDL_Quit();
}
bool LoadPngToTexture(const char* pngPath, unsigned int textureIndex) {
INFOF("loading '%s' into %d", pngPath, textureIndex);
if (textureIndex >= LEN(g_SdlVramTextures)) {
ERRORF("textureIndex %d out of bound for '%s'", textureIndex, pngPath);
return false;
}
g_SdlVramSurfaces[textureIndex] = IMG_Load(pngPath);
if (!g_SdlVramSurfaces[textureIndex]) {
ERRORF("IMG_Load error: %s", SDL_GetError());
return false;
}
g_SdlVramTextures[textureIndex] = SDL_CreateTextureFromSurface(
g_Renderer, g_SdlVramSurfaces[textureIndex]);
return true;
}
bool InitializeTexture(unsigned int textureIndex) {
if (textureIndex >= LEN(g_SdlVramTextures)) {
ERRORF("textureIndex %d out of bound", textureIndex);
return false;
}
if (g_SdlVramSurfaces[textureIndex] || g_SdlVramTextures[textureIndex]) {
ERRORF("textureIndex %d previously initialized, now replacing it",
textureIndex);
if (g_SdlVramTextures[textureIndex]) {
SDL_DestroyTexture(g_SdlVramTextures[textureIndex]);
}
if (g_SdlVramSurfaces[textureIndex]) {
SDL_FreeSurface(g_SdlVramSurfaces[textureIndex]);
}
}
switch (textureIndex) {
case 0x1E:
return LoadPngToTexture("assets/game/font.png", textureIndex);
}
return false;
}
int MyResetGraph(int arg0) { return 0; }
void MyAudioCallback(void* data, Uint8* buffer, int length);
@ -190,14 +161,141 @@ u_long MyPadRead(int id) {
if (keyb[SDL_SCANCODE_R]) {
pressed |= PAD_R1;
}
g_DebugSdl = DEBUG_SDL_NONE;
if (keyb[SDL_SCANCODE_F5]) {
g_DebugSdl = DEBUG_SDL_SHOW_VRAM_16bpp;
}
if (keyb[SDL_SCANCODE_F6]) {
g_DebugSdl = DEBUG_SDL_SHOW_VRAM_8bpp;
}
if (keyb[SDL_SCANCODE_F7]) {
g_DebugSdl = DEBUG_SDL_SHOW_VRAM_4bpp;
}
break;
}
return pressed;
}
void ShowVram16bpp(void) {
SDL_Texture* t =
SDL_CreateTexture(g_Renderer, SDL_PIXELFORMAT_ABGR1555,
SDL_TEXTUREACCESS_STREAMING, VRAM_W, VRAM_H);
u16* pixels;
int pitch = VRAM_STRIDE;
SDL_LockTexture(t, NULL, (void**)&pixels, &pitch);
if (pitch == VRAM_STRIDE) {
memcpy(pixels, g_RawVram, sizeof(g_RawVram));
} else {
u16* dst = pixels;
u16* src = g_RawVram;
for (int i = 0; i < VRAM_H; i++) {
memcpy(dst, src, VRAM_STRIDE);
dst += pitch >> 1;
src += VRAM_STRIDE >> 1;
}
}
SDL_UnlockTexture(t);
SDL_Rect rsrc = {512, 0, 512, 256};
SDL_Rect rdst = {0, 0, 256, 128};
SDL_RenderCopy(g_Renderer, t, &rsrc, &rdst);
rsrc.y += 256;
rdst.y += 128;
SDL_RenderCopy(g_Renderer, t, &rsrc, &rdst);
SDL_DestroyTexture(t);
}
void ShowVram8bpp(void) {
SDL_Texture* t =
SDL_CreateTexture(g_Renderer, SDL_PIXELFORMAT_RGBA32,
SDL_TEXTUREACCESS_STREAMING, VRAM_W, VRAM_H);
u8* pixels;
int pitch = VRAM_STRIDE;
SDL_LockTexture(t, NULL, (void**)&pixels, &pitch);
u16* src = g_RawVram;
for (int i = 0; i < VRAM_H; i++) {
for (int j = 0; j < VRAM_W; j++) {
u8 ch = src[j];
pixels[j * 4 + 0] = ch;
pixels[j * 4 + 1] = ch;
pixels[j * 4 + 2] = ch;
pixels[j * 4 + 3] = 0xFF;
}
src += VRAM_W;
pixels += pitch;
}
SDL_UnlockTexture(t);
SDL_Rect rsrc = {512, 0, 512, 256};
SDL_Rect rdst = {0, 0, 256, 128};
SDL_RenderCopy(g_Renderer, t, &rsrc, &rdst);
rsrc.y += 256;
rdst.y += 128;
SDL_RenderCopy(g_Renderer, t, &rsrc, &rdst);
SDL_DestroyTexture(t);
}
void ShowVram4bpp(void) {
SDL_Texture* t =
SDL_CreateTexture(g_Renderer, SDL_PIXELFORMAT_RGBA32,
SDL_TEXTUREACCESS_STREAMING, VRAM_W * 2, VRAM_H);
u8* pixels;
int pitch = VRAM_STRIDE;
SDL_LockTexture(t, NULL, (void**)&pixels, &pitch);
u16* src = g_RawVram;
for (int i = 0; i < VRAM_H; i++) {
for (int j = 0; j < VRAM_W; j++) {
u8 ch = src[j];
pixels[j * 8 + 0] = (ch & 0xF) << 4;
pixels[j * 8 + 1] = (ch & 0xF) << 4;
pixels[j * 8 + 2] = (ch & 0xF) << 4;
pixels[j * 8 + 3] = 0xFF;
pixels[j * 8 + 4] = ch & 0xF0;
pixels[j * 8 + 5] = ch & 0xF0;
pixels[j * 8 + 6] = ch & 0xF0;
pixels[j * 8 + 7] = 0xFF;
}
src += VRAM_W;
pixels += pitch;
}
SDL_UnlockTexture(t);
SDL_Rect rsrc = {1024, 0, 1024, 256};
SDL_Rect rdst = {0, 0, 256, 128};
SDL_RenderCopy(g_Renderer, t, &rsrc, &rdst);
rsrc.y += 256;
rdst.y += 128;
SDL_RenderCopy(g_Renderer, t, &rsrc, &rdst);
SDL_DestroyTexture(t);
}
void MyDrawSyncCallback();
int MyDrawSync(int mode) {
switch (g_DebugSdl) {
case DEBUG_SDL_SHOW_VRAM_16bpp:
ShowVram16bpp();
break;
case DEBUG_SDL_SHOW_VRAM_8bpp:
ShowVram8bpp();
break;
case DEBUG_SDL_SHOW_VRAM_4bpp:
ShowVram4bpp();
break;
}
SDL_RenderPresent(g_Renderer);
SDL_RenderSetScale(g_Renderer, SCREEN_SCALE, SCREEN_SCALE);
@ -236,23 +334,77 @@ DISPENV* MyPutDispEnv(DISPENV* env) {
}
void MySetDrawMode(DR_MODE* p, int dfe, int dtd, int tpage, RECT* tw) {
if (tpage >= LEN(g_SdlVramTextures)) {
DEBUGF("tpage %d, how to handle?", tpage);
return false;
}
if (!g_SdlVramTextures[tpage] && !InitializeTexture(tpage)) {
return;
}
g_Tpage = tpage;
}
#define PSX_TEX_U(x) ((float)(x) / 128.0f)
#define PSX_TEX_V(x) ((float)(x) / 128.0f)
SDL_Texture* GetVramTexture(int tpage, int clut) {
u16 pal[256];
if (g_LastVramTexTpage != tpage || g_LastVramTexClut != clut) {
g_LastVramTexTpage = tpage;
g_LastVramTexClut = clut;
u8* src = g_RawVram;
src += (tpage & 0xF) * 128;
src += ((tpage >> 4) & 1) * VRAM_STRIDE * 256;
u16* sourcepal = g_RawVram;
sourcepal += clut * 0x10;
u16* pixels;
int pitch;
SDL_LockTexture(g_VramTex, NULL, (void**)&pixels, &pitch);
int bpp = tpage >> 7;
switch (bpp) {
case 0: // 4bpp
// Hack that rewrites the VRAM to adjust transparent palette colors
memcpy(pal, sourcepal, 0x20);
pal[0] &= ~0x8000; // first color always transparent?
for (int i = 1; i < 16; i++) {
pal[i] |= 0x8000;
}
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 128; j++) {
u8 ch = src[j];
pixels[j * 2 + 0] = pal[ch & 0xF];
pixels[j * 2 + 1] = pal[ch >> 4];
}
pixels += pitch >> 1;
src += VRAM_STRIDE;
}
break;
case 1: // 8 bpp
// Hack that rewrites the VRAM to adjust transparent palette colors
memcpy(pal, sourcepal, 0x200);
pal[0] &= ~0x8000; // first color always transparent?
for (int i = 1; i < 256; i++) {
pal[i] |= 0x8000;
}
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 256; j++) {
pixels[j] = pal[src[j]];
}
pixels += pitch >> 1;
src += VRAM_STRIDE;
}
break;
default:
WARNF("bpp %d not supported", bpp);
break;
}
SDL_UnlockTexture(g_VramTex);
}
return g_VramTex;
}
#define PSX_TEX_U(x) ((float)(x) / 256.0f)
#define PSX_TEX_V(x) ((float)(x) / 256.0f)
void SetSdlVertexSprite(SDL_Vertex* v, SPRT* sprt) {
sprt->r0 = 255;
sprt->g0 = 255;
sprt->b0 = 255;
// u8 blend = sprt->code & 1 ? 0xFF : 0x00;
sprt->r0 |= 255;
sprt->g0 |= 255;
sprt->b0 |= 255;
v[0].position.x = sprt->x0;
v[0].position.y = sprt->y0;
v[0].tex_coord.x = PSX_TEX_U(sprt->u0);
@ -317,38 +469,40 @@ void SetSdlVertexG4(SDL_Vertex* v, POLY_G4* poly) {
v[3] = v[1];
v[5] = v[2];
}
void SetSdlVertexGT4(SDL_Vertex* v, POLY_GT4* poly) {
u8 blend = poly->code & 1 ? 0xFF : 0x00;
v[0].position.x = poly->x0;
v[0].position.y = poly->y0;
v[0].tex_coord.x = PSX_TEX_U(poly->u0);
v[0].tex_coord.y = PSX_TEX_V(poly->v0);
v[0].color.r = poly->r0;
v[0].color.g = poly->g0;
v[0].color.b = poly->b0;
v[0].color.r = poly->r0 | blend;
v[0].color.g = poly->g0 | blend;
v[0].color.b = poly->b0 | blend;
v[0].color.a = 0xFF;
v[1].position.x = poly->x1;
v[1].position.y = poly->y1;
v[1].tex_coord.x = PSX_TEX_U(poly->u1);
v[1].tex_coord.y = PSX_TEX_V(poly->v1);
v[1].color.r = poly->r1;
v[1].color.g = poly->g1;
v[1].color.b = poly->b1;
v[1].color.r = poly->r1 | blend;
v[1].color.g = poly->g1 | blend;
v[1].color.b = poly->b1 | blend;
v[1].color.a = 0xFF;
v[2].position.x = poly->x2;
v[2].position.y = poly->y2;
v[2].tex_coord.x = PSX_TEX_U(poly->u2);
v[2].tex_coord.y = PSX_TEX_V(poly->v2);
v[2].color.r = poly->r2;
v[2].color.g = poly->g2;
v[2].color.b = poly->b2;
v[2].color.r = poly->r2 | blend;
v[2].color.g = poly->g2 | blend;
v[2].color.b = poly->b2 | blend;
v[2].color.a = 0xFF;
v[4].position.x = poly->x3;
v[4].position.y = poly->y3;
v[4].tex_coord.x = PSX_TEX_U(poly->u3);
v[4].tex_coord.y = PSX_TEX_V(poly->v3);
v[4].color.r = poly->r3;
v[4].color.g = poly->g3;
v[4].color.b = poly->b3;
v[4].color.r = poly->r3 | blend;
v[4].color.g = poly->g3 | blend;
v[4].color.b = poly->b3 | blend;
v[4].color.a = 0xFF;
v[3] = v[1];
v[5] = v[2];
@ -393,6 +547,7 @@ void SetSdlVertexPrim(SDL_Vertex* v, Primitive* prim) {
void MyRenderPrimitives(void) {
SDL_Vertex v[6];
SDL_Texture* t = NULL;
for (int i = 0; i < LEN(g_PrimBuf); i++) {
Primitive* prim = &g_PrimBuf[i];
@ -407,8 +562,8 @@ void MyRenderPrimitives(void) {
break;
case PRIM_GT4:
SetSdlVertexPrim(v, prim);
SDL_RenderGeometry(
g_Renderer, g_SdlVramTextures[g_Tpage], v, 6, NULL, 0);
t = GetVramTexture(prim->tpage, D_8003C104[prim->clut]);
SDL_RenderGeometry(g_Renderer, t, v, 6, NULL, 0);
break;
case PRIM_LINE_G2:
SDL_SetRenderDrawColor(
@ -422,10 +577,17 @@ void MyRenderPrimitives(void) {
SetSdlVertexG4(v, &g_CurrentBuffer->polyG4[i]);
SDL_RenderGeometry(g_Renderer, NULL, v, 6, NULL, 0);
}
for (int i = 0; i < g_GpuUsage.gt4; i++) {
POLY_GT4* poly = &g_CurrentBuffer->polyGT4[i];
SetSdlVertexGT4(v, poly);
t = GetVramTexture(poly->tpage, poly->clut);
SDL_RenderGeometry(g_Renderer, t, v, 6, NULL, 0);
}
for (int i = 0; i < g_GpuUsage.sp; i++) {
SetSdlVertexSprite(v, &g_CurrentBuffer->sprite[i]);
SDL_RenderGeometry(
g_Renderer, g_SdlVramTextures[g_Tpage], v, 6, NULL, 0);
SPRT* sp = &g_CurrentBuffer->sprite[i];
SetSdlVertexSprite(v, sp);
t = GetVramTexture(g_Tpage, sp->clut);
SDL_RenderGeometry(g_Renderer, t, v, 6, NULL, 0);
}
for (int i = 0; i < g_GpuUsage.line; i++) {
LINE_G2* poly = &g_CurrentBuffer->lineG2[i];

353
src/pc/sim_pc.c Normal file
View File

@ -0,0 +1,353 @@
#include <dra.h>
#include <log.h>
#include "pc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define VSYNC_UNK_LEN 1024
s32 g_SimVabId = 0;
SimFile D_800A024C[] = {
{"sim:c:\\bin\\f_title1.bin", 13}, {"sim:c:\\bin\\f_game.bin", 1},
{"sim:c:\\bin\\f_title0.bin", 2}, {"sim:c:\\bin\\face.bin", 6},
{"sim:c:\\bin\\arc_f.bin", 8}, {"sim:c:\\bin\\ric.bin", 8},
{"sim:c:\\bin\\f_prolo0.bin", 11}, {"sim:c:\\bin\\f_prolo1.bin", 12},
{"sim:c:\\bin\\gof.bin", 14}, {"sim:c:\\bin\\gob.bin", 15},
{"sim:c:\\bin\\c_gof.bin", 16}, {"sim:c:\\bin\\c_gob.bin", 17},
{"sim:c:\\bin\\f_sel.bin", 2}, {"sim:c:\\bin\\f_game2.bin", 1},
{"sim:c:\\bin\\edf.bin", 21}, {"sim:c:\\bin\\edb.bin", 15},
{"sim:c:\\bin\\c_edf.bin", 16}, {"sim:c:\\bin\\c_edb.bin", 17},
};
const char* D_800A036C[] = {
"sim:c:\\sound\\data\\sd_alk.vh", "sim:c:\\sound\\data\\sd_alk.vb",
"sim:c:\\sound\\data\\sd_rih.vh", "sim:c:\\sound\\data\\sd_rih.vb",
"sim:c:\\sound\\data\\sd_mar.vh", "sim:c:\\sound\\data\\sd_mar.vb",
"sim:c:\\sound\\data\\sd_tuka2.vh", "sim:c:\\sound\\data\\sd_tuka2.vb",
"sim:c:\\sound\\data\\sd_tuka2.vh", "sim:c:\\sound\\data\\sd_tuka2.vb",
"sim:c:\\sound\\data\\sd_tuka1.vh", "sim:c:\\sound\\data\\sd_tuka1.vb",
"sim:c:\\sound\\data\\sd_koa1.vh", "sim:c:\\sound\\data\\sd_koa1.vb",
"sim:c:\\sound\\data\\sd_mak.vh", "sim:c:\\sound\\data\\sd_mak.vb",
"sim:c:\\sound\\data\\sd_tuka2.vh", "sim:c:\\sound\\data\\sd_tuka2.vb",
"sim:c:\\sound\\data\\sd_koa2.vh", "sim:c:\\sound\\data\\sd_koa2.vb",
};
const char* D_800A04AC[] = {
"sim:c:\\sound\\data\\sd_eve1.seq",
"sim:c:\\sound\\data\\sd_eve3.seq",
};
u16 D_800A04CC[] = {
0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
};
u32 D_800A04EC = 0;
u32 D_800A04F0 = 0;
u32 D_800A04F4 = 0;
u32 D_800A04F8 = 0;
u32 D_800A04FC = 0;
RECT D_800A0500 = {112, 32, 128, 1};
RECT D_800A0508 = {368, 32, 128, 1};
void VSyncHandler(void) {
RECT* rect;
D_800A04F4++;
D_800A04F8 = (D_800A04F4 / 4) % 32;
nullsub_10();
if (D_800A04F0) {
return;
}
switch (D_800A04EC) {
case 0:
break;
case 2:
D_80136460[D_800A04FC * 2] |= 0xFF00;
rect = &D_800A0500;
if (g_CurrentBuffer->disp.disp.x == 0) {
rect = &D_800A0508;
}
LoadImage(rect, D_80136460);
if (D_800A04FC < VSYNC_UNK_LEN) {
D_800A04FC++;
}
break;
case 1:
case 3:
D_800A04FC = 0;
D_800A04EC++;
break;
case 4:
D_80136460[D_800A04FC * 2] |= 0x00FF;
rect = &D_800A0500;
if (g_CurrentBuffer->disp.disp.x == 0) {
rect = &D_800A0508;
}
LoadImage(rect, D_80136460);
if (D_800A04FC < VSYNC_UNK_LEN) {
D_800A04FC++;
}
break;
}
D_800A04F0 = 0;
}
void func_800E7D08(void) {
s32 i;
for (i = 0; i < VSYNC_UNK_LEN; i++) {
D_80136460[i] = 0;
D_80136C60[i] = 0;
}
D_800A04EC = 1;
}
void LoadStageTileset(u8* pTilesetData, s32 y) {
RECT rect;
u8* pTilesetDataSrc;
s32 i;
rect.w = 0x20;
rect.h = 0x80;
for (i = 0; i < 0x20; i++) {
pTilesetDataSrc = pTilesetData + 0x2000 * i;
rect.x = D_800AC958[i];
if (i & 2) {
rect.y = y + 0x80;
} else {
rect.y = y;
}
LoadImage(&rect, pTilesetDataSrc);
while (DrawSync(1)) {
}
}
}
s32 LoadFileSimToMem(SimKind kind) {
char pad[0x20];
s32 i;
u32* pDst;
u32* pSrc;
u16* clutAddr;
switch (kind) {
case SIM_STAGE_PRG:
WARNF("TODO: bind g_Api.o to stage %02X", g_StageId);
break;
case SIM_FAMILIAR_CHR:
LoadTPage(SIM_CHR0, 0, 0, 0x2C0, 0x100, 0x100, 0x80);
LoadTPage(SIM_CHR1, 0, 0, 0x2C0, 0x180, 0x80, 0x80);
break;
case SIM_WEAPON0_CHR:
LoadTPage(g_Pix[0], 0, 0, 0x240, 0x100, 0x100, 0x80);
break;
case SIM_WEAPON1_CHR:
LoadTPage(g_Pix[2], 0, 0, 0x240, 0x180, 0x100, 0x80);
break;
case SIM_MONSTER:
LoadTPage(SIM_CHR0, 2, 0, 0x20, 0x100, 0x60, 0x70);
break;
case SIM_1:
LoadStageTileset(STAGE_PRG_PTR, 0x100);
DrawSync(0);
LoadImage(&g_Vram.D_800ACD98, D_800A04CC);
LoadImage(&g_Vram.D_800ACDA8, 0x801C0000);
while (DrawSync(1)) {
}
StoreImage(&g_Vram.D_800ACDA8, g_Clut + 0x1000);
break;
case SIM_STAGE_CHR:
case SIM_11:
LoadStageTileset(SIM_CHR0, 0);
DrawSync(0);
clutAddr = g_Clut;
StoreImage(&g_Vram.D_800ACDB8, clutAddr);
if (kind == 11) {
clutAddr += 0x2000;
StoreImage(&g_Vram.D_800ACDB8, clutAddr);
DrawSync(0);
LoadImage(&g_Vram.D_800ACDB0, clutAddr);
}
break;
case SIM_12:
case SIM_13:
LoadStageTileset(SIM_CHR0, 0x100);
if (kind == 13) {
LoadImage(&g_Vram.D_800ACD98, D_800A04CC);
}
DrawSync(0);
break;
case SIM_VH:
while (SsVabTransCompleted(SS_IMEDIATE) != 1) {
}
if (SsVabOpenHeadSticky(
g_SimFile->addr, g_SimVabId, g_VabAddrs[g_SimVabId]) < 0) {
return -1;
}
break;
case SIM_VB:
if (SsVabTransBodyPartly(SIM_PTR, g_SimFile->size, g_SimVabId) == -1) {
return -1;
}
while (SsVabTransCompleted(SS_IMEDIATE) != 1) {
}
break;
case SIM_SEQ:
if (g_StageId == STAGE_LIB) {
func_80131EBC(aPqes_1, 0x202);
}
if (g_StageId == STAGE_DAI) {
func_80131EBC(aPqes_1, 0x204);
}
break;
case SIM_6:
LoadImage(&g_Vram.D_800ACDC0, STAGE_PRG_PTR);
break;
case SIM_14:
LoadImage(&g_Vram.D_800ACDD0, SIM_PTR);
break;
case SIM_21:
LoadImage(&g_Vram.D_800ACDE0, SIM_PTR);
break;
case SIM_15:
LoadImage(&g_Vram.D_800ACDD8, SIM_PTR);
break;
case SIM_16:
LoadImage(&g_Vram.D_800ACDB8, SIM_PTR);
StoreImage(&g_Vram.D_800ACDB8, g_Clut + 0x2000);
break;
case SIM_17:
LoadImage(&g_Vram.D_800ACDA8, SIM_PTR);
StoreImage(&g_Vram.D_800ACDA8, g_Clut);
break;
}
return 0;
}
bool LoadFilePc(void* content) {
g_SimFile->addr = content;
switch (g_SimFile->kind) { // slowly replacing the original func
case SIM_1:
LoadStageTileset(content, 0x100);
LoadImage(&g_Vram.D_800ACD98, D_800A04CC);
LoadImage(&g_Vram.D_800ACDA8, (u8*)content + 0x40000);
StoreImage(&g_Vram.D_800ACDA8, g_Clut + 0x1000);
break;
case SIM_STAGE_CHR:
LoadStageTileset(content, 0);
break;
default:
if (LoadFileSimToMem(g_SimFile->kind) < 0) {
return false;
}
}
return true;
}
s32 LoadFileSim(s32 fileId, SimFileType type) {
char smolbuf[48];
char buf[128];
s32 fid;
SimFile sim = {0};
switch (type) {
case SimFileType_System:
switch (fileId) {
case 0:
sim.path = "BIN/F_TITLE1.BIN";
break;
case 1:
sim.path = "BIN/F_GAME.BIN";
sim.kind = SIM_1;
break;
case 2:
sim.path = "BIN/F_TITLE0.BIN";
break;
case 4:
sim.path = "BIN/ARC_F.BIN";
break;
default:
WARNF("not implemented for ID %d: %s", fileId, D_800A024C[fileId]);
return -1;
}
break;
case SimFileType_StagePrg:
INFOF("TODO: will load stage '%s'", g_StagesLba[g_StageId].ovlName);
return 0;
case SimFileType_Vh:
case SimFileType_Vb:
sim.kind = type == SimFileType_Vh ? SIM_VH : SIM_VB;
switch (fileId) {
case 0:
sim.path = smolbuf;
snprintf(smolbuf, sizeof(smolbuf), "ST/%s/SD_ZK%s.%s",
g_StagesLba[g_StageId].ovlName,
g_StagesLba[g_StageId].ovlName,
type == SimFileType_Vh ? "VH" : "VB");
break;
case 0x8000:
sim.path = "VAB/SD_ALK.VH";
break;
case 0x8001:
sim.path = "VAB/SD_ALK.VB";
break;
default:
if (fileId & 0x8000) {
WARNF("not implemented for ID %d: %s", fileId,
D_800A036C[fileId & 0x7FFF]);
} else {
WARNF("not implemented for ID %d: %s", fileId,
g_StagesLba[g_StageId].name);
}
return -1;
}
break;
case SimFileType_StageChr:
sim.kind = SIM_STAGE_CHR;
sim.path = smolbuf;
snprintf(smolbuf, sizeof(smolbuf), "ST/%s/F_%s.BIN",
g_StagesLba[g_StageId].ovlName,
g_StagesLba[g_StageId].ovlName);
break;
case SimFileType_Weapon0Prg:
INFOF("TODO: will load weapon 'w0_%03d'", fileId);
return 0;
case SimFileType_Weapon1Prg:
INFOF("TODO: will load weapon 'w1_%03d'", fileId);
return 0;
case SimFileType_Weapon0Chr:
INFOF("TODO: will load weapon 'f0_%03d'", fileId);
return 0;
case SimFileType_Weapon1Chr:
INFOF("TODO: will load weapon 'f1_%03d'", fileId);
return 0;
case SimFileType_FamiliarPrg:
INFOF("TODO: will load weapon 'tt_%03d'", fileId);
return 0;
case SimFileType_FamiliarChr:
INFOF("TODO: will load weapon 'ft_%03d'", fileId);
return 0;
}
if (!sim.path) {
WARNF("unimplemented %d, %d", fileId, type);
return -1;
}
snprintf(buf, sizeof(buf), "disks/us/%s", sim.path);
INFOF("open %s", buf);
g_SimFile = &sim;
if (!FileUseContent(LoadFilePc, buf)) {
ERRORF("failed to load '%s'", buf);
D_800A04EC = 0;
return -1;
}
D_800A04EC = 0;
return 0;
}

View File

@ -5,11 +5,14 @@
#include <cJSON/cJSON.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char g_DummyName[] = "DUMMY\xFF";
const char g_DummyDesc[] = "dummy description";
RelicDesc g_RelicDummy = {g_DummyName, g_DummyDesc, 0, 0, 0};
u16 g_RawVram[VRAM_W * VRAM_H];
GameApi g_ApiInit = {0};
Equipment g_EquipDefs[0x100] = {0};
Accessory g_AccessoryDefs[0x100] = {0};
@ -161,6 +164,7 @@ bool InitGame(void) {
api.unused13C = NULL;
api.o.Update = NULL;
api.o.TestCollisions = StageOvlCb;
api.o.InitRoomEntities = StageOvlCb;
api.o.unk08 = NULL;
api.o.InitRoomEntities = StageOvlCb;
api.o.rooms = NULL;
@ -193,6 +197,20 @@ bool InitGame(void) {
D_80137590 = g_DemoRecordingBuffer;
// forcing g_Vram values while waiting to import the data
g_Vram.D_800ACD98.x = 0x0380;
g_Vram.D_800ACD98.y = 0x0180;
g_Vram.D_800ACD98.w = 0x0010;
g_Vram.D_800ACD98.h = 0x0001;
g_Vram.D_800ACDA0.x = 0;
g_Vram.D_800ACDA0.y = 0;
g_Vram.D_800ACDA0.w = 0x0200;
g_Vram.D_800ACDA0.h = 0x0200;
g_Vram.D_800ACDA8.x = 0;
g_Vram.D_800ACDA8.y = 0x00F0;
g_Vram.D_800ACDA8.w = 0x0100;
g_Vram.D_800ACDA8.h = 0x0010;
return true;
}
@ -201,11 +219,11 @@ void ResetGame(void) { ResetPlatform(); }
MyRenderPrimitives();
void RenderPrimitives(void) {
INFOF("dr :%03x, gt4 :%03x", g_GpuUsage.drawModes, g_GpuUsage.gt4);
INFOF("g4 :%03x, gt3 :%03x", g_GpuUsage.g4, g_GpuUsage.gt3);
INFOF("line:%03x, sp16:%03x", g_GpuUsage.line, g_GpuUsage.sp16);
INFOF("sp :%03x, tile:%03x", g_GpuUsage.sp, g_GpuUsage.tile);
INFOF("env :%03x, prim :%03x", g_GpuUsage.env, g_GpuUsage.env);
DEBUGF("dr :%03x, gt4 :%03x", g_GpuUsage.drawModes, g_GpuUsage.gt4);
DEBUGF("g4 :%03x, gt3 :%03x", g_GpuUsage.g4, g_GpuUsage.gt3);
DEBUGF("line:%03x, sp16:%03x", g_GpuUsage.line, g_GpuUsage.sp16);
DEBUGF("sp :%03x, tile:%03x", g_GpuUsage.sp, g_GpuUsage.tile);
DEBUGF("env :%03x, prim :%03x", g_GpuUsage.env, g_GpuUsage.env);
MyRenderPrimitives();
}
@ -301,7 +319,6 @@ char MyEncodeChar(char ch) {
return ch;
}
const char* AnsiToSotnMenuString(const char* str) {
DEBUGF("%s", str);
size_t end = strlen(str) + 2 + g_MegaMenuStrIndex;
if (end >= LEN(g_MegaMenuStrBuffer)) {
ERRORF(
@ -449,3 +466,56 @@ void InitEnemyDefs(void) {
void InitSubwpnDefs(void) {
//
}
void (*g_VsyncCallback)() = NULL;
int MyVSyncCallback(void (*f)()) { g_VsyncCallback = f; }
int MyVSync(int mode) {
if (g_VsyncCallback) {
g_VsyncCallback();
}
return 0;
}
int MyClearImage(RECT* rect, u_char r, u_char g, u_char b) {
u16* vram = g_RawVram;
vram += rect->x + rect->y * VRAM_W;
for (int i = 0; i < rect->h; i++) {
for (int j = 0; j < rect->w; j++) {
vram[j] = (r >> 3 << 5) | (g >> 3 << 10) | (b >> 3 << 15) | 0x8000;
}
vram += VRAM_W;
}
return 0;
}
int MyLoadImage(RECT* rect, u_long* p) {
DEBUGF("(%X, %X, %X, %X): %p", rect->x, rect->y, rect->w, rect->h, p);
u16* mem = (u16*)p;
u16* vram = g_RawVram;
vram += rect->x + rect->y * VRAM_W;
for (int i = 0; i < rect->h; i++) {
for (int j = 0; j < rect->w; j++) {
vram[j] = *mem++;
}
vram += VRAM_W;
}
return 0;
}
int MyStoreImage(RECT* rect, u_long* p) {
DEBUGF("(%X, %X, %X, %X): %p", rect->x, rect->y, rect->w, rect->h, p);
u16* mem = (u16*)p;
u16* vram = g_RawVram;
vram += rect->x + rect->y * VRAM_W;
for (int i = 0; i < rect->h; i++) {
for (int j = 0; j < rect->w; j++) {
*mem++ = vram[j];
}
vram += VRAM_W;
}
return 0;
}

View File

@ -17,7 +17,6 @@ GameState g_GameState;
Entity g_Entities[TOTAL_ENTITY_COUNT];
unkGraphicsStruct g_unkGraphicsStruct;
Primitive g_PrimBuf[MAX_PRIM_COUNT];
Lba g_StagesLba[0x50];
FgLayer D_8003C708;
s16 D_8003C710;
s16 D_8003C712;
@ -57,7 +56,6 @@ s32 D_80097928;
s32 D_8006C3AC;
s32 D_800978C4;
s32 D_80097C98;
u32 D_800A04F8;
SVECTOR* D_800A3210[1];
SVECTOR* D_800A33A0[1];
SVECTOR* D_800A34C0[18][3];
@ -67,7 +65,7 @@ SVECTOR* D_800A3608[1];
u8 D_800A3728;
MATRIX D_800A37B8;
s16 D_80136308[1];
u16 g_Clut[1];
u16 g_Clut[0x3000];
s32 D_8006C384;
s32 D_8006C388;
MenuNavigation g_MenuNavigation;
@ -149,6 +147,18 @@ PixPattern* D_800C52F8[] = {
};
// dra.h
u16 D_800AC958[] = {
0x0200, 0x0220, 0x0200, 0x0220, 0x0240, 0x0260, 0x0240, 0x0260,
0x0280, 0x02A0, 0x0280, 0x02A0, 0x02C0, 0x02E0, 0x02C0, 0x02E0,
0x0300, 0x0320, 0x0300, 0x0320, 0x0340, 0x0360, 0x0340, 0x0360,
0x0380, 0x03A0, 0x0380, 0x03A0, 0x03C0, 0x03E0, 0x03C0, 0x03E0,
};
s16 D_800AC998[] = {
0x0200, 0x0220, 0x0200, 0x0220, 0x0240, 0x0260, 0x0240, 0x0260,
0x0280, 0x02A0, 0x0280, 0x02A0, 0x02C0, 0x02E0, 0x02C0, 0x02E0,
0x0300, 0x0320, 0x0300, 0x0320, 0x0340, 0x0360, 0x0340, 0x0360,
0x0380, 0x03A0, 0x0380, 0x03A0, 0x03C0, 0x03E0, 0x03C0, 0x03E0,
};
GpuUsage g_GpuMaxUsage;
GpuBuffer* g_BackBuffer;
s32 g_DebugFreeze;
@ -318,6 +328,10 @@ s32 D_8013B5E8;
s32 D_80137994;
s32 D_80139008;
s32 D_801397FC;
SimFile* g_SimFile;
SimFile D_80136450;
s16 D_80136460[0x400];
s16 D_80136C60[0x400];
JosephsCloak g_JosephsCloak;
u8 g_Pix[4][128 * 128 / 2];
@ -481,15 +495,8 @@ void func_8013572C(int sndId, int unk02, int unk04) { NOT_IMPLEMENTED; }
void func_801073C0(void) { NOT_IMPLEMENTED; }
s32 LoadFileSim(s32 fileId, SimFileType type) {
NOT_IMPLEMENTED;
return 0;
}
void func_800EA7CC(void) { NOT_IMPLEMENTED; }
void VSyncHandler(void) { NOT_IMPLEMENTED; }
void RenderEntities(void) { NOT_IMPLEMENTED; }
void RenderTilemap(void) { NOT_IMPLEMENTED; }