mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-11-23 04:19:50 +00:00
CMake: generate linker script fragments for segments
* Animations * Levels * Dynamic models * Strings Started to hook this up to the linker. There are still some errors to fix.
This commit is contained in:
parent
1df470e87b
commit
13db5ddc5e
@ -33,14 +33,17 @@ add_library(platform INTERFACE)
|
||||
find_package(Libultra REQUIRED)
|
||||
target_link_libraries(platform INTERFACE libultra::libultra)
|
||||
target_compile_definitions(platform INTERFACE F3DEX_GBI_2)
|
||||
target_include_directories(platform INTERFACE
|
||||
"${PROJECT_SOURCE_DIR}/src"
|
||||
)
|
||||
|
||||
add_subdirectory(${ASM_DIR})
|
||||
add_subdirectory(${ASSETS_DIR})
|
||||
add_subdirectory(${SRC_DIR})
|
||||
add_subdirectory(${VPK_DIR})
|
||||
|
||||
add_library(code_segment OBJECT)
|
||||
target_link_libraries(code_segment
|
||||
add_library(code_segment STATIC)
|
||||
target_link_libraries(code_segment PRIVATE
|
||||
platform
|
||||
|
||||
engine
|
||||
@ -51,3 +54,46 @@ target_link_libraries(code_segment
|
||||
sound_lookup_tables
|
||||
string_lookup_tables
|
||||
)
|
||||
|
||||
add_executable(portal)
|
||||
target_link_libraries(portal PRIVATE
|
||||
asm_sources
|
||||
code_segment
|
||||
levels
|
||||
models_dynamic
|
||||
string_data_tables
|
||||
)
|
||||
|
||||
if (N64)
|
||||
# Generate linker script
|
||||
set(INPUT_LINKER_SCRIPT "${PROJECT_SOURCE_DIR}/portal.ld")
|
||||
set(OUTPUT_LINKER_SCRIPT "${LINKER_SCRIPT_DIR}/portal.ld")
|
||||
add_custom_command(
|
||||
DEPENDS
|
||||
${INPUT_LINKER_SCRIPT}
|
||||
anims_linker_script
|
||||
level_linker_script
|
||||
models_dynamic_linker_script
|
||||
string_linker_script
|
||||
OUTPUT
|
||||
${OUTPUT_LINKER_SCRIPT}
|
||||
COMMAND
|
||||
${CMAKE_CPP} -P -Wall -Werror
|
||||
-I${LINKER_SCRIPT_DIR}
|
||||
-o ${OUTPUT_LINKER_SCRIPT} ${INPUT_LINKER_SCRIPT}
|
||||
COMMENT
|
||||
"Generating $<PATH:RELATIVE_PATH,${OUTPUT_LINKER_SCRIPT},${PROJECT_SOURCE_DIR}>"
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(linker_script
|
||||
DEPENDS ${OUTPUT_LINKER_SCRIPT}
|
||||
)
|
||||
add_dependencies(portal linker_script)
|
||||
|
||||
# Link
|
||||
set(LINKER_MAP_FILE "${LINKER_SCRIPT_DIR}/portal.map")
|
||||
target_link_options(portal PRIVATE
|
||||
-T ${OUTPUT_LINKER_SCRIPT}
|
||||
-Map ${LINKER_MAP_FILE}
|
||||
)
|
||||
endif()
|
||||
|
@ -3,15 +3,20 @@
|
||||
####################
|
||||
|
||||
set(ASM_FILES
|
||||
boot.s
|
||||
entry.s
|
||||
rom_header.s
|
||||
sound_data.s
|
||||
)
|
||||
|
||||
add_library(asm_sources INTERFACE)
|
||||
add_library(asm_sources OBJECT)
|
||||
add_dependencies(asm_sources
|
||||
sound_data_tables
|
||||
)
|
||||
target_sources(asm_sources INTERFACE
|
||||
target_sources(asm_sources PRIVATE
|
||||
${ASM_FILES}
|
||||
)
|
||||
target_compile_definitions(asm_sources PRIVATE
|
||||
# TODO
|
||||
#BOOT_CODE=...
|
||||
)
|
||||
|
@ -1,6 +1,6 @@
|
||||
set(VALVE_INTRO_VIDEO "${VPK_DIR}/Portal/hl2/media/valve.bik")
|
||||
|
||||
if(NOT EXISTS ${VALVE_INTRO_VIDEO})
|
||||
if (NOT EXISTS ${VALVE_INTRO_VIDEO})
|
||||
# The Mac release of Portal uses a .mov instead of a .bik
|
||||
string(REPLACE ".mov" ".bik" VALVE_INTRO_VIDEO_MAC "${VALVE_INTRO_VIDEO}")
|
||||
|
||||
@ -26,6 +26,7 @@ set(SCENE_SCALE 128)
|
||||
|
||||
# Tools for asset conversion
|
||||
set(CONVERT_ASSET "${PROJECT_SOURCE_DIR}/tools/convert_asset.py")
|
||||
set(GEN_SEGMENT_LD "${PROJECT_SOURCE_DIR}/tools/generate_segment_ld.js")
|
||||
set(EXPORT_FBX "${PROJECT_SOURCE_DIR}/tools/models/export_fbx.py")
|
||||
set(MODEL_LIST_UTILS "${PROJECT_SOURCE_DIR}/tools/models/model_list_utils.js")
|
||||
|
||||
@ -34,3 +35,27 @@ add_subdirectory(models)
|
||||
add_subdirectory(sound)
|
||||
add_subdirectory(test_chambers)
|
||||
add_subdirectory(translations)
|
||||
|
||||
# For linking model and level animations
|
||||
set(ANIMS_LINKER_SCRIPT "${LINKER_SCRIPT_DIR}/anims.ld")
|
||||
add_custom_command(
|
||||
DEPENDS
|
||||
${GEN_SEGMENT_LD}
|
||||
OUTPUT
|
||||
${ANIMS_LINKER_SCRIPT}
|
||||
COMMAND
|
||||
${NodeJs_EXECUTABLE} ${GEN_SEGMENT_LD}
|
||||
--single-segment-name animation_segment
|
||||
${ANIMS_LINKER_SCRIPT}
|
||||
0x0D000000
|
||||
"$<LIST:FILTER,$<TARGET_OBJECTS:models_dynamic>,INCLUDE,_anim\..+$>"
|
||||
"$<LIST:FILTER,$<TARGET_OBJECTS:levels>,INCLUDE,_anim\..+$>"
|
||||
COMMENT
|
||||
"Generating $<PATH:RELATIVE_PATH,${ANIMS_LINKER_SCRIPT},${PROJECT_SOURCE_DIR}>"
|
||||
COMMAND_EXPAND_LISTS
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(anims_linker_script
|
||||
DEPENDS ${ANIMS_LINKER_SCRIPT}
|
||||
)
|
||||
|
@ -98,7 +98,7 @@ function(_add_texture_convert_command INPUT_FILE OUTPUT_FILE)
|
||||
set(OUTPUT_FILE "${PAK_MATERIALS_DIR}/${OUTPUT_FILE}.png")
|
||||
set(ARGS "${ARGN}")
|
||||
|
||||
if(NOT ARGS)
|
||||
if (NOT ARGS)
|
||||
get_source_file_property(FILE_ARGS ${INPUT_FILE} ARGS)
|
||||
if (FILE_ARGS)
|
||||
set(ARGS "${FILE_ARGS}")
|
||||
|
@ -222,7 +222,7 @@ foreach(MODEL ${MODELS})
|
||||
_add_model_export_command(${MODEL} MODEL_FBX)
|
||||
_add_model_generate_command(${MODEL} ${MODEL_FBX} GENERATED_FILES)
|
||||
|
||||
if(MODEL IN_LIST DYNAMIC_MODELS)
|
||||
if (MODEL IN_LIST DYNAMIC_MODELS)
|
||||
list(APPEND DYNAMIC_MODEL_GENERATED_FILES ${GENERATED_FILES})
|
||||
else()
|
||||
list(APPEND STATIC_MODEL_GENERATED_FILES ${GENERATED_FILES})
|
||||
@ -235,6 +235,30 @@ add_custom_target(models
|
||||
DEPENDS ${MODEL_GENERATED_FILES}
|
||||
)
|
||||
|
||||
add_library(models_static OBJECT)
|
||||
add_dependencies(models_static
|
||||
materials
|
||||
models
|
||||
)
|
||||
target_sources(models_static PRIVATE
|
||||
${STATIC_MODEL_GENERATED_FILES}
|
||||
)
|
||||
target_link_libraries(models_static PRIVATE
|
||||
platform
|
||||
)
|
||||
|
||||
add_library(models_dynamic OBJECT)
|
||||
add_dependencies(models_dynamic
|
||||
materials
|
||||
models
|
||||
)
|
||||
target_sources(models_dynamic PRIVATE
|
||||
${DYNAMIC_MODEL_GENERATED_FILES}
|
||||
)
|
||||
target_link_libraries(models_dynamic PRIVATE
|
||||
platform
|
||||
)
|
||||
|
||||
# Add commands for generating dynamic model lists
|
||||
|
||||
set(MODEL_GENERATED_HEADERS ${MODEL_GENERATED_FILES})
|
||||
@ -254,8 +278,8 @@ foreach(GENERATED_HEADER ${MODEL_GENERATED_HEADERS})
|
||||
OUTPUT_VARIABLE MODEL_NAME
|
||||
)
|
||||
|
||||
if(MODEL_NAME IN_LIST DYNAMIC_MODELS)
|
||||
if(MODEL_NAME IN_LIST ANIMATED_MODELS)
|
||||
if (MODEL_NAME IN_LIST DYNAMIC_MODELS)
|
||||
if (MODEL_NAME IN_LIST ANIMATED_MODELS)
|
||||
list(APPEND DYNAMIC_ANIMATED_MODEL_HEADERS ${GENERATED_HEADER})
|
||||
else()
|
||||
list(APPEND DYNAMIC_MODEL_HEADERS ${GENERATED_HEADER})
|
||||
@ -316,8 +340,25 @@ target_sources(model_lists INTERFACE
|
||||
${MODEL_LIST_FILES}
|
||||
)
|
||||
|
||||
add_library(models_static INTERFACE)
|
||||
add_dependencies(models_static models)
|
||||
target_sources(models_static INTERFACE
|
||||
${STATIC_MODEL_GENERATED_FILES}
|
||||
# Add command for generating dynamic model linker script fragment
|
||||
|
||||
set(DYNAMIC_MODELS_LINKER_SCRIPT "${LINKER_SCRIPT_DIR}/dynamic_models.ld")
|
||||
add_custom_command(
|
||||
DEPENDS
|
||||
${GEN_SEGMENT_LD}
|
||||
OUTPUT
|
||||
${DYNAMIC_MODELS_LINKER_SCRIPT}
|
||||
COMMAND
|
||||
${NodeJs_EXECUTABLE} ${GEN_SEGMENT_LD}
|
||||
${DYNAMIC_MODELS_LINKER_SCRIPT}
|
||||
0x03000000
|
||||
"$<LIST:FILTER,$<TARGET_OBJECTS:models_dynamic>,INCLUDE,_geo\..+$>"
|
||||
COMMENT
|
||||
"Generating $<PATH:RELATIVE_PATH,${DYNAMIC_MODELS_LINKER_SCRIPT},${PROJECT_SOURCE_DIR}>"
|
||||
COMMAND_EXPAND_LISTS
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(models_dynamic_linker_script
|
||||
DEPENDS ${DYNAMIC_MODELS_LINKER_SCRIPT}
|
||||
)
|
||||
|
@ -272,7 +272,7 @@ function(_add_sound_transform_command SOUND_SCRIPT OUTPUT_LIST)
|
||||
set(INPUT_FILE "${PAK_SOUND_DIR}/${SOUND_NAME}.wav")
|
||||
set(OUTPUT_FILE "${PROJECT_BINARY_DIR}/${RELATIVE_CURRENT_DIR}/${SOUND_NAME}.wav")
|
||||
|
||||
if(SOUND_SCRIPT MATCHES ".*\.jsox")
|
||||
if (SOUND_SCRIPT MATCHES ".*\.jsox")
|
||||
_add_sound_transform_command_jsox(${SOUND_SCRIPT} ${INPUT_FILE} ${OUTPUT_FILE})
|
||||
else()
|
||||
_add_sound_transform_command_sox(${SOUND_SCRIPT} ${INPUT_FILE} ${OUTPUT_FILE})
|
||||
@ -411,7 +411,7 @@ foreach(CONVERTED_SOUND ${SOUNDS_CONVERTED})
|
||||
)
|
||||
|
||||
# Only include the sound if an instrument bank doesn't already do so
|
||||
if(NOT INS_BANK IN_LIST INSTRUMENT_BANKS)
|
||||
if (NOT INS_BANK IN_LIST INSTRUMENT_BANKS)
|
||||
list(APPEND SOUND_TABLE_INPUTS ${CONVERTED_SOUND})
|
||||
endif()
|
||||
endforeach()
|
||||
|
@ -154,6 +154,18 @@ add_custom_target(generated_levels
|
||||
DEPENDS ${LEVEL_GENERATED_FILES}
|
||||
)
|
||||
|
||||
add_library(levels OBJECT)
|
||||
add_dependencies(levels
|
||||
materials
|
||||
generated_levels
|
||||
)
|
||||
target_sources(levels PRIVATE
|
||||
${LEVEL_GENERATED_FILES}
|
||||
)
|
||||
target_link_libraries(levels PRIVATE
|
||||
platform
|
||||
)
|
||||
|
||||
# Add command for generating level list header
|
||||
|
||||
set(LEVEL_GENERATED_HEADERS ${LEVEL_GENERATED_FILES})
|
||||
@ -187,3 +199,26 @@ add_dependencies(level_list generated_level_list)
|
||||
target_sources(level_list INTERFACE
|
||||
${LEVEL_LIST}
|
||||
)
|
||||
|
||||
# Add command for generating level linker script fragment
|
||||
|
||||
set(LEVEL_LINKER_SCRIPT "${LINKER_SCRIPT_DIR}/levels.ld")
|
||||
add_custom_command(
|
||||
DEPENDS
|
||||
${GEN_SEGMENT_LD}
|
||||
OUTPUT
|
||||
${LEVEL_LINKER_SCRIPT}
|
||||
COMMAND
|
||||
${NodeJs_EXECUTABLE} ${GEN_SEGMENT_LD}
|
||||
${LEVEL_LINKER_SCRIPT}
|
||||
0x02000000
|
||||
"$<LIST:FILTER,$<TARGET_OBJECTS:levels>,INCLUDE,_geo\..+$>"
|
||||
COMMENT
|
||||
"Generating $<PATH:RELATIVE_PATH,${LEVEL_LINKER_SCRIPT},${PROJECT_SOURCE_DIR}>"
|
||||
COMMAND_EXPAND_LISTS
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(level_linker_script
|
||||
DEPENDS ${LEVEL_LINKER_SCRIPT}
|
||||
)
|
||||
|
@ -75,9 +75,9 @@ add_custom_target(strings
|
||||
${STRING_DATA_TABLE_FILES}
|
||||
)
|
||||
|
||||
add_library(string_data_tables INTERFACE)
|
||||
add_library(string_data_tables OBJECT)
|
||||
add_dependencies(string_data_tables strings)
|
||||
target_sources(string_data_tables INTERFACE
|
||||
target_sources(string_data_tables PRIVATE
|
||||
${STRING_DATA_TABLE_FILES}
|
||||
)
|
||||
|
||||
@ -86,3 +86,27 @@ add_dependencies(string_lookup_tables strings)
|
||||
target_sources(string_lookup_tables INTERFACE
|
||||
${STRING_LOOKUP_TABLE_FILES}
|
||||
)
|
||||
|
||||
# Add command for generating strings linker script fragment
|
||||
|
||||
set(STRING_LINKER_SCRIPT "${LINKER_SCRIPT_DIR}/subtitles.ld")
|
||||
add_custom_command(
|
||||
DEPENDS
|
||||
${GEN_SEGMENT_LD}
|
||||
OUTPUT
|
||||
${STRING_LINKER_SCRIPT}
|
||||
COMMAND
|
||||
${NodeJs_EXECUTABLE} ${GEN_SEGMENT_LD}
|
||||
--alignment 16
|
||||
${STRING_LINKER_SCRIPT}
|
||||
0x04000000
|
||||
"$<TARGET_OBJECTS:string_data_tables>"
|
||||
COMMENT
|
||||
"Generating $<PATH:RELATIVE_PATH,${STRING_LINKER_SCRIPT},${PROJECT_SOURCE_DIR}>"
|
||||
COMMAND_EXPAND_LISTS
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(string_linker_script
|
||||
DEPENDS ${STRING_LINKER_SCRIPT}
|
||||
)
|
||||
|
@ -24,6 +24,7 @@ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
find_program(CMAKE_ASM_COMPILER ${N64_TOOLCHAIN_PREFIX}gcc REQUIRED)
|
||||
find_program(CMAKE_C_COMPILER ${N64_TOOLCHAIN_PREFIX}gcc REQUIRED)
|
||||
find_program(CMAKE_CPP ${N64_TOOLCHAIN_PREFIX}cpp REQUIRED)
|
||||
find_program(CMAKE_CXX_COMPILER ${N64_TOOLCHAIN_PREFIX}g++ REQUIRED)
|
||||
find_program(CMAKE_LINKER ${N64_TOOLCHAIN_PREFIX}ld REQUIRED)
|
||||
|
||||
|
12
portal.ld
12
portal.ld
@ -1,5 +1,5 @@
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
|
||||
OUTPUT_ARCH(mips)
|
||||
OUTPUT_ARCH("mips")
|
||||
|
||||
#define BEGIN_SEG(name, addr) \
|
||||
_##name##SegmentStart = ADDR(.name); \
|
||||
@ -26,15 +26,15 @@ SECTIONS
|
||||
|
||||
BEGIN_SEG(boot, 0x04000000)
|
||||
{
|
||||
*asm/rom_header.*(.text);
|
||||
*asm/boot.*(.text);
|
||||
*/rom_header.*(.text);
|
||||
*/boot.*(.text);
|
||||
}
|
||||
END_SEG(boot)
|
||||
|
||||
BEGIN_SEG(code, 0x80000400) SUBALIGN(16)
|
||||
{
|
||||
/* code */
|
||||
*asm/entry.*(.text);
|
||||
*/entry.*(.text);
|
||||
CODE_SEGMENT(.text);
|
||||
RSP_OBJ(.text);
|
||||
GSP_OBJ(.text);
|
||||
@ -68,8 +68,8 @@ SECTIONS
|
||||
|
||||
BEGIN_SEG(sound_data, __romPos)
|
||||
{
|
||||
*asm/sound_data.*(.data);
|
||||
*asm/sound_data.*(.bss);
|
||||
*/sound_data.*(.data);
|
||||
*/sound_data.*(.bss);
|
||||
}
|
||||
END_SEG(sound_data)
|
||||
|
||||
|
@ -73,7 +73,7 @@ target_include_directories(skeletool64 PRIVATE
|
||||
${LUA_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(skeletool64
|
||||
target_link_libraries(skeletool64 PRIVATE
|
||||
assimp::assimp
|
||||
cimg::cimg
|
||||
PNG::PNG
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "string.h"
|
||||
|
||||
size_t strLength(char* s) {
|
||||
int size = 0;
|
||||
size_t size = 0;
|
||||
|
||||
while (*s++ != '\0') {
|
||||
++size;
|
||||
|
@ -10,7 +10,7 @@ function sanitize(s) {
|
||||
|
||||
function generateSegmentNameFromObject(objectPath) {
|
||||
const { name } = path.parse(objectPath);
|
||||
return sanitize(name);
|
||||
return sanitize(name.split('.')[0]);
|
||||
}
|
||||
|
||||
function generateSegmentContent(objectPath) {
|
||||
@ -58,6 +58,11 @@ const [outputLinkerScript, loadAddress, ...objectPaths] = positionals;
|
||||
const singleSegmentName = values['single-segment-name'];
|
||||
const alignment = values['alignment'];
|
||||
|
||||
const outputParentDir = path.dirname(outputLinkerScript);
|
||||
if (!fs.existsSync(outputParentDir)) {
|
||||
fs.mkdirSync(outputParentDir, { recursive: true });
|
||||
}
|
||||
|
||||
const output = singleSegmentName ?
|
||||
generateSegment(singleSegmentName, loadAddress, alignment, objectPaths) :
|
||||
generateMultiSegments(loadAddress, alignment, objectPaths);
|
||||
|
Loading…
Reference in New Issue
Block a user