new level editor tech

This commit is contained in:
Niko 2024-07-08 20:41:42 -04:00
parent b3307b1f68
commit 9d1fae33a6
13 changed files with 774 additions and 0 deletions

View File

@ -0,0 +1,15 @@
[to-do] generate source code pseudo-auto
First build with ./build.bat,
this generates .lev file
Then run textures/start.bat,
this patches .lev and generates .vrm
Boot retail game in duckstation
Go to Time Trial Crash Cove
Pause
Use "sendToDuck.bat"
Restart Race (from pause)
[to-do] need to load VRAM file

View File

@ -0,0 +1 @@
python ../../../../../tools/mod-builder/main.py

View File

@ -0,0 +1,4 @@
// sets lev to bigfile 221
926, 221, 0x8009f6fc, 0x0, src/Lev221.c
926, 222, 0x8009f6fc, 0x0, src/dataVRAM.bin

View File

@ -0,0 +1 @@
..\Automate\LevelUploader\x64\Debug\LevelUploader.exe %cd%\textures\data.lev

View File

@ -0,0 +1,362 @@
// Only for generating LEV files
#pragma GCC diagnostic ignored "-Wint-conversion"
#pragma GCC diagnostic ignored "-Woverride-init"
#pragma GCC diagnostic ignored "-Woverflow"
#include <common.h>
#include "../../levelBuilder.h"
#define NUM_BLOCKS 20
struct LevelFile
{
void* ptrMap;
struct Level level;
struct mesh_info mInfo;
struct IconGroup4 test_texture;
struct SpawnType1 spawnType1;
struct CheckpointNode noderespawnsthing[16];
struct QuadBlock quadBlock[NUM_BLOCKS];
struct LevVertex levVertex[NUM_BLOCKS*9];
struct BSP bsp[3];
struct PVS pvs;
int visBitIndex[4];
struct VisMem visMem;
// leave empty
// DstMemcpy must be big for PVS to copy into,
// RenderList must be big enough for 2 pointers to all BSP nodes
int VisMem_bitIndex_DstMemcpyP1[8];
int VisMem_bspList_RenderListP1[3*2];
int VisMem_bitIndex_DstMemcpyP2[8];
int VisMem_bspList_RenderListP2[3*2];
int VisMem_bitIndex_DstMemcpyP3[8];
int VisMem_bspList_RenderListP3[3*2];
int VisMem_bitIndex_DstMemcpyP4[8];
int VisMem_bspList_RenderListP4[3*2];
int map[(3)+1];
};
struct LevelFile file =
{
.ptrMap = LEV_OFFSETOF(map[0]),
.level =
{
.ptr_mesh_info = LEV_OFFSETOF(mInfo),
.visMem = LEV_OFFSETOF(visMem),
// the game will add +0x400 to the yaw of spawn positions automatically
// we should probably look into why this even happens...
.DriverSpawn[0].pos = {0,0,0},
.DriverSpawn[0].rot = {0,0-0x400,0},
.DriverSpawn[1].pos = {0,0,0},
.DriverSpawn[1].rot = {0,0-0x400,0},
.DriverSpawn[2].pos = {0,0,0},
.DriverSpawn[2].rot = {0,0-0x400,0},
.DriverSpawn[3].pos = {0,0,0},
.DriverSpawn[3].rot = {0,0-0x400,0},
.ptrSpawnType1 = LEV_OFFSETOF(spawnType1),
.configFlags = 1,
.glowGradient[0] =
{
.pointFrom = -0xF0,
.pointTo = -0x10,
.colorFrom = 0x8000,
.colorTo = 0,
},
// amount of respawn points in the track
// and pointer to respawn data itself
.cnt_restart_points = 16,
.ptr_restart_points = LEV_OFFSETOF(noderespawnsthing[0]),
},
// pointers and amounts of variables
.mInfo =
{
.numQuadBlock = NUM_BLOCKS,
.numVertex = NUM_BLOCKS*9, // not really used
.unk1 = 0, // idk, fine to leave null
.ptrQuadBlockArray = LEV_OFFSETOF(quadBlock[0]),
.ptrVertexArray = LEV_OFFSETOF(levVertex[0]),
.unk2 = 0, // idk, fine to leave null
.bspRoot = LEV_OFFSETOF(bsp[0]),
.numBspNodes = 3,
},
// quadblock texture type
// see IconGroup4 in namespace_Decal.h
.test_texture =
{
.far = ImageName_Blend(512, 0, 32, 128, 32, 32, BPP_4, ADD), // very far
.middle = ImageName_Blend(512, 0, 32, 128, 32, 32, BPP_4, ADD), // far
.near = ImageName_Blend(512, 0, 32, 128, 32, 32, BPP_4, ADD), // close
.mosaic = ImageName_Blend(512, 0, 32, 128, 32, 32, BPP_4, ADD), // close
},
// this must exist, or else camera fly-in checks for "count" without nullptr check, and crashes dereferencing nullptr on real PSX
.spawnType1 =
{
.count = 0,
},
// automatically-generated quadblock insertions courtesy of pngtotrack.py
NEW_BLOCK(0, test_texture, 0x0000, 0x0000, NULL, 0x1800, (0xFFFFFF)),NEW_BLOCK(1, test_texture, 0x0300, 0x0000, NULL, 0x1800, (0x000000)),
NEW_BLOCK(2, test_texture, -0x300, 0x0300, NULL, 0x1800, RGBtoBGR(0x804000)),NEW_BLOCK(3, test_texture, 0x0000, 0x0300, NULL, 0x1800, (0xFFFFFF)),NEW_BLOCK(4, test_texture, 0x0300, 0x0300, NULL, 0x1800, RGBtoBGR(0x804000)),NEW_BLOCK(5, test_texture, 0x0600, 0x0300, NULL, 0x1800, RGBtoBGR(0x804000)),
NEW_BLOCK(6, test_texture, -0x300, 0x0600, NULL, 0x1800, RGBtoBGR(0x804000)), NEW_BLOCK(7, test_texture, 0x0600, 0x0600, NULL, 0x1800, RGBtoBGR(0x804000)),
NEW_BLOCK(8, test_texture, -0x300, 0x0900, NULL, 0x1800, RGBtoBGR(0x804000)), NEW_BLOCK(9, test_texture, 0x0600, 0x0900, NULL, 0x1800, RGBtoBGR(0x804000)),
NEW_BLOCK(10, test_texture, -0x300, 0x0c00, NULL, 0x1800, RGBtoBGR(0x804000)), NEW_BLOCK(11, test_texture, 0x0600, 0x0c00, NULL, 0x1800, RGBtoBGR(0x804000)),
NEW_BLOCK(12, test_texture, -0x300, 0x0f00, NULL, 0x1800, RGBtoBGR(0x804000)), NEW_BLOCK(13, test_texture, 0x0600, 0x0f00, NULL, 0x1800, RGBtoBGR(0x804000)),
NEW_BLOCK(14, test_texture, -0x300, 0x1200, NULL, 0x1800, RGBtoBGR(0x804000)),NEW_BLOCK(15, test_texture, 0x0000, 0x1200, NULL, 0x1800, RGBtoBGR(0x804000)),NEW_BLOCK(16, test_texture, 0x0300, 0x1200, NULL, 0x1800, RGBtoBGR(0x804000)),NEW_BLOCK(17, test_texture, 0x0600, 0x1200, NULL, 0x1800, RGBtoBGR(0x804000)),
NEW_BLOCK(18, test_texture, 0x0000, 0x1500, NULL, 0x1800, RGBtoBGR(0x804000)),NEW_BLOCK(19, test_texture, 0x0300, 0x1500, NULL, 0x1800, RGBtoBGR(0x804000)),
/*
00 01
02 03 04 05
06 07
08 09
10 11
12 13
14 15 16 17
18 19
*/
// checkpoint and respawn indices
// starts at 2 and ends at 3, which are the first and last quadblocks in terms of progression respectively
// 0, 1, 18, and 19 aren't used for progression
.quadBlock[2].checkpointIndex = 0,
.quadBlock[6].checkpointIndex = 1,
.quadBlock[8].checkpointIndex = 2,
.quadBlock[10].checkpointIndex = 3,
.quadBlock[12].checkpointIndex = 4,
.quadBlock[14].checkpointIndex = 5,
.quadBlock[15].checkpointIndex = 6,
.quadBlock[16].checkpointIndex = 7,
.quadBlock[17].checkpointIndex = 8,
.quadBlock[13].checkpointIndex = 9,
.quadBlock[11].checkpointIndex = 10,
.quadBlock[9].checkpointIndex = 11,
.quadBlock[7].checkpointIndex = 12,
.quadBlock[5].checkpointIndex = 13,
.quadBlock[4].checkpointIndex = 14,
.quadBlock[3].checkpointIndex = 15,
// checkpoint and respawn data, split into 16 nodes
// the positions of each node are the same as certain quadblocks
.noderespawnsthing =
{
[0] =
{
.pos = {-0x300, 0, 0x300}, // same as quadblock 2
.distToFinish = 0x200*15,
.nextIndex_forward = 1,
.nextIndex_left = -1,
.nextIndex_backward = 15,
.nextIndex_right = -1,
},
[1] =
{
.pos = {-0x300, 0, 0x600}, // same as quadblock 6
.distToFinish = 0x200*14,
.nextIndex_forward = 2,
.nextIndex_left = -1,
.nextIndex_backward = 0,
.nextIndex_right = -1,
},
[2] =
{
.pos = {-0x300, 0, 0x300*3}, // same as quadblock 8
.distToFinish = 0x200*13,
.nextIndex_forward = 3,
.nextIndex_left = -1,
.nextIndex_backward = 1,
.nextIndex_right = -1,
},
[3] =
{
.pos = {-0x300, 0, 0x300*4}, // same as quadblock 10
.distToFinish = 0x200*12,
.nextIndex_forward = 4,
.nextIndex_left = -1,
.nextIndex_backward = 2,
.nextIndex_right = -1,
},
[4] =
{
.pos = {-0x300, 0, 0x300*5}, // same as quadblock 12
.distToFinish = 0x200*11,
.nextIndex_forward = 5,
.nextIndex_left = -1,
.nextIndex_backward = 3,
.nextIndex_right = -1,
},
[5] =
{
.pos = {-0x300, 0, 0x300*6}, // same as quadblock 14
.distToFinish = 0x200*10,
.nextIndex_forward = 6,
.nextIndex_left = -1,
.nextIndex_backward = 4,
.nextIndex_right = -1,
},
[6] =
{
.pos = {0, 0, 0x300*6}, // same as quadblock 15
.distToFinish = 0x200*9,
.nextIndex_forward = 7,
.nextIndex_left = -1,
.nextIndex_backward = 5,
.nextIndex_right = -1,
},
[7] =
{
.pos = {0x300, 0, 0x300*6}, // same as quadblock 16
.distToFinish = 0x200*8,
.nextIndex_forward = 8,
.nextIndex_left = -1,
.nextIndex_backward = 6,
.nextIndex_right = -1,
},
[8] =
{
.pos = {0x600, 0, 0x300*6}, // same as quadblock 17
.distToFinish = 0x200*7,
.nextIndex_forward = 9,
.nextIndex_left = -1,
.nextIndex_backward = 7,
.nextIndex_right = -1,
},
[9] =
{
.pos = {0x600, 0, 0x300*5}, // same as quadblock 13
.distToFinish = 0x200*6,
.nextIndex_forward = 10,
.nextIndex_left = -1,
.nextIndex_backward = 8,
.nextIndex_right = -1,
},
[10] =
{
.pos = {0x600, 0, 0x300*4}, // same as quadblock 11
.distToFinish = 0x200*5,
.nextIndex_forward = 11,
.nextIndex_left = -1,
.nextIndex_backward = 9,
.nextIndex_right = -1,
},
[11] =
{
.pos = {0x600, 0, 0x300*3}, // same as quadblock 9
.distToFinish = 0x200*4,
.nextIndex_forward = 12,
.nextIndex_left = -1,
.nextIndex_backward = 10,
.nextIndex_right = -1,
},
[12] =
{
.pos = {0x600, 0, 0x300*2}, // same as quadblock 7
.distToFinish = 0x200*3,
.nextIndex_forward = 13,
.nextIndex_left = -1,
.nextIndex_backward = 11,
.nextIndex_right = -1,
},
[13] =
{
.pos = {0x600, 0, 0x300*1}, // same as quadblock 5
.distToFinish = 0x200*2,
.nextIndex_forward = 14,
.nextIndex_left = -1,
.nextIndex_backward = 12,
.nextIndex_right = -1,
},
[14] =
{
.pos = {0x300, 0, 0x300*1}, // same as quadblock 4
.distToFinish = 0x200*1,
.nextIndex_forward = 15,
.nextIndex_left = -1,
.nextIndex_backward = 13,
.nextIndex_right = -1,
},
[15] =
{
.pos = {0, 0, 0x300*1}, // same as quadblock 3
.distToFinish = 0x200*0,
.nextIndex_forward = 0,
.nextIndex_left = -1,
.nextIndex_backward = 14,
.nextIndex_right = -1,
},
},
// ========== bsp ======================
.bsp =
{
// root node
BSP_BRANCH(0, SPLIT_Z, 0x1, 0x2),
// bsp[1], start with quadblock[0], 2 quadblocks
BSP_LEAF(1, 0, 2),
// bsp[2], start with quadblock[2], 18 quadblocks
BSP_LEAF(2, 2, 18),
},
.pvs =
{
.visLeafSrc = LEV_OFFSETOF(visBitIndex[0]),
.visFaceSrc = LEV_OFFSETOF(visBitIndex[0]),
.visInstSrc = 0,
.visExtraSrc = 0,
},
.visBitIndex =
{
// all 0xFFFFFFFFFFFF
-1, -1, -1, -1
},
.visMem =
{
// P1
.visLeafList[0] = LEV_OFFSETOF(VisMem_bitIndex_DstMemcpyP1[0]),
.visFaceList[0] = LEV_OFFSETOF(VisMem_bitIndex_DstMemcpyP1[4]),
.bspList[0] = LEV_OFFSETOF(VisMem_bspList_RenderListP1[0]),
// P2
.visLeafList[1] = LEV_OFFSETOF(VisMem_bitIndex_DstMemcpyP2[0]),
.visFaceList[1] = LEV_OFFSETOF(VisMem_bitIndex_DstMemcpyP2[4]),
.bspList[1] = LEV_OFFSETOF(VisMem_bspList_RenderListP2[0]),
// P3
.visLeafList[2] = LEV_OFFSETOF(VisMem_bitIndex_DstMemcpyP3[0]),
.visFaceList[2] = LEV_OFFSETOF(VisMem_bitIndex_DstMemcpyP3[4]),
.bspList[2] = LEV_OFFSETOF(VisMem_bspList_RenderListP3[0]),
// P4
.visLeafList[3] = LEV_OFFSETOF(VisMem_bitIndex_DstMemcpyP4[0]),
.visFaceList[3] = LEV_OFFSETOF(VisMem_bitIndex_DstMemcpyP4[4]),
.bspList[3] = LEV_OFFSETOF(VisMem_bspList_RenderListP4[0]),
},
.map =
{
(2)<<2,
LEV_OFFSETOF(pvs.visLeafSrc),
LEV_OFFSETOF(pvs.visFaceSrc),
},
};

View File

@ -0,0 +1,6 @@
data
data.lev
data.vrm
data.vrm.bkp
debug_vram_first.bmp
debug_vram_latest.bmp

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

View File

@ -0,0 +1,25 @@
@echo off
cd %~dp0
:: Get Newest Level File
copy ..\output\Lev221c.bin .\data.lev
:: Get Blank VRAM File
copy ..\..\Automate\blankVRAM_dontErase.vrm .\data.vrm
:: Patch Level with Automation
..\..\Automate\LevelPatcher\Debug\LevelPatcher.exe %cd%\data.lev
:: Generate Layout
..\..\Automate\model_reader.exe .\data.lev
:: Generate VRAM
..\..\Automate\vrmtool.exe .\data.vrm
:: Submit Level File
copy .\data.lev ..\output\Lev221c.bin
:: Submit VRAM File
copy .\data.vrm ..\src\dataVRAM.bin
pause

View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34714.143
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LevelUploader", "LevelUploader\LevelUploader.vcxproj", "{790AB99C-0121-4286-99FA-1EE5B3611DD1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{790AB99C-0121-4286-99FA-1EE5B3611DD1}.Debug|x64.ActiveCfg = Debug|x64
{790AB99C-0121-4286-99FA-1EE5B3611DD1}.Debug|x64.Build.0 = Debug|x64
{790AB99C-0121-4286-99FA-1EE5B3611DD1}.Debug|x86.ActiveCfg = Debug|Win32
{790AB99C-0121-4286-99FA-1EE5B3611DD1}.Debug|x86.Build.0 = Debug|Win32
{790AB99C-0121-4286-99FA-1EE5B3611DD1}.Release|x64.ActiveCfg = Release|x64
{790AB99C-0121-4286-99FA-1EE5B3611DD1}.Release|x64.Build.0 = Release|x64
{790AB99C-0121-4286-99FA-1EE5B3611DD1}.Release|x86.ActiveCfg = Release|Win32
{790AB99C-0121-4286-99FA-1EE5B3611DD1}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9205B891-8640-41E3-9614-D14BC9009A39}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{790ab99c-0121-4286-99fa-1ee5b3611dd1}</ProjectGuid>
<RootNamespace>LevelUploader</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LocalDebuggerCommandArguments>
</LocalDebuggerCommandArguments>
<LocalDebuggerEnvironment>
</LocalDebuggerEnvironment>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommandArguments>C:\Users\Niko\Desktop\CTR\psx-modding-toolchain\games\CTR-ModSDK\mods\Levels\2024_NewSetup\textures\data.lev</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,158 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* pBuf;
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
// for EnumProcessModules
#pragma comment(lib, "psapi.lib")
void DECOMP_LOAD_RunPtrMap(char* origin, int* patchArr, int numPtrs, int dstAddr)
{
for (int i = 0; i < numPtrs; i++)
{
*(int*)&origin[patchArr[i]] += dstAddr;
}
}
struct DramPointerMap
{
int numBytes;
//int offsets[0];
};
#define DRAM_GETOFFSETS(x) \
((char*)x + sizeof(struct DramPointerMap))
void UploadToDuck(char** argv)
{
printf("%s\n", argv[1]);
FILE* f = fopen(argv[1], "rb");
fseek(f, 0, SEEK_END);
int size = ftell(f);
rewind(f);
// read to 2mb on PS1
fread(&pBuf[0x200000], size, 1, f);
fclose(f);
char* fileBuf = &pBuf[0x200000];
int ptrMapOffset = *(int*)&fileBuf[0];
char* realFileBuf = &fileBuf[4];
struct DramPointerMap* dpm = &realFileBuf[ptrMapOffset];
DECOMP_LOAD_RunPtrMap(
realFileBuf,
(int*)DRAM_GETOFFSETS(dpm),
dpm->numBytes >> 2,
0x80200004);
// set level file pointer
*(int*)&pBuf[(0x80096b20 + 0x160) & 0xffffff] = 0x80200004;
printf("Here\n");
system("pause");
exit(0);
}
int main(int argc, char** argv)
{
int numDuckInstances = 0;
char* duckTemplate = "duckstation";
int duckPID = -1;
// copy from
// https://learn.microsoft.com/en-us/windows/win32/psapi/enumerating-all-processes
DWORD aProcesses[1024], cbNeeded, cProcesses;
EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded);
cProcesses = cbNeeded / sizeof(DWORD);
for (int i = 0; i < cProcesses; i++)
{
DWORD processID = aProcesses[i];
if (processID != 0)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
if (NULL != hProcess)
{
HMODULE hMod;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
{
TCHAR szProcessName[MAX_PATH];
GetModuleBaseNameA(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR));
char* procName = (char*)&szProcessName[0];
if (
(*(int*)&procName[0] == *(int*)&duckTemplate[0]) &&
(*(int*)&procName[4] == *(int*)&duckTemplate[4])
)
{
numDuckInstances++;
duckPID = processID;
}
}
}
}
}
if (numDuckInstances == 0)
{
printf("Error: DuckStation is not running!\n\n");
system("pause");
exit(0);
}
else printf("Client: DuckStation detected\n");
char pidStr[16];
if (numDuckInstances > 1)
{
printf("Warning: Multiple DuckStations detected\n");
printf("Please enter the PID manually\n\n");
printf("Input.: DuckStation PID: ");
scanf_s("%s", pidStr, (int)sizeof(pidStr));
}
else
{
sprintf_s(pidStr, 100, "%d", duckPID);
}
char duckName[100];
sprintf_s(duckName, 100, "duckstation_%s", pidStr);
TCHAR duckNameT[100];
swprintf(duckNameT, 100, L"%hs", duckName);
// 8 MB RAM
const unsigned int size = 0x800000;
HANDLE hFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, duckNameT);
pBuf = (char*)MapViewOfFile(hFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size);
if (pBuf == 0)
{
printf("Error: Failed to open DuckStation!\n\n");
system("pause");
system("cls");
main(argc, argv);
}
UploadToDuck(argv);
}