Add 120 star tas benchmark

This commit is contained in:
a
2025-07-14 10:50:47 -04:00
parent a0872a30c4
commit 5cbbe624d3
8 changed files with 128 additions and 18 deletions

View File

@@ -5,14 +5,43 @@ include util.mk
# Default target
default: all
# Preprocessor definitions
DEFINES :=
# Use Libdragon IPL3
# WARNING: This CAN and WILL break certain (most) emulators.
# Use if you care about console or ares boot times.
LIBDRAGON_IPL3 := 0
LIBDRAGON_IPL3 ?= 0
# Preprocessor definitions
DEFINES :=
# Build types
# debug - Debug build
# general - General release build
# final - Final release build with no crash screen, game will reset upon exception.
RELEASE ?= debug
# Benchmark build
# Builds a benchmark build that runs a 120 star TAS for automated verification.
# This setting is also in include/cfg/benchmark.h, but provided here as well for automation purposes.
BENCHMARK ?= 0
ifeq ($(BENCHMARK), 1)
DEFINES += CFG_BENCHMARK=1
RELEASE = general
endif
ifeq ($(RELEASE), debug)
OPT_FLAGS := -Og -ggdb3
DEFINES += _DEBUG=1
else ifeq ($(RELEASE), general)
OPT_FLAGS := -Os -ggdb3
else ifeq ($(RELEASE), final)
OPT_FLAGS := -Os
else
$(error Invalid build release setting.)
endif
ifeq ($(LIBDRAGON_IPL3), 1)
DEFINES += LIBDRAGON_IPL3=1
@@ -87,17 +116,9 @@ else ifeq ($(GRUCODE),f3dzex) # Fast3DZEX (2.0J / Animal Forest - Dōbutsu no Mo
DEFINES += F3DZEX_GBI_2=1 F3DEX_GBI_2=1 F3DEX_GBI_SHARED=1
endif
NON_MATCHING := 1
MIPSISET := -mips3
OPT_FLAGS := -Os
# NON_MATCHING - whether to build a matching, identical copy of the ROM
# 1 - enable some alternate, more portable code that does not produce a matching ROM
# 0 - build a matching ROM
NON_MATCHING ?= 0
$(eval $(call validate-option,NON_MATCHING,0 1))
NON_MATCHING := 1
ifeq ($(TARGET_N64),0)
NON_MATCHING := 1
endif
@@ -140,6 +161,7 @@ ifeq ($(filter clean distclean,$(MAKECMDGOALS)),)
else
$(info IPL: Nintendo IPL3)
endif
$(info Build type: $(RELEASE))
$(info =======================)
endif
@@ -306,7 +328,7 @@ endif
# C compiler options
CFLAGS = -G 0 $(TARGET_CFLAGS) $(DEF_INC_CFLAGS) $(foreach i,$(INCLUDE_DIRS),--embed-dir=$(i))
CFLAGS += -std=gnu23 -fno-inline-functions -Wno-unused-variable -mno-shared -march=vr4300 -mfix4300 -mabi=32 -mhard-float -mdivide-breaks -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-PIC -mno-abicalls -fno-strict-aliasing -ffreestanding -fwrapv -Wall -Wextra
CFLAGS += -std=gnu23 -fno-inline -Wno-unused-variable -mno-shared -march=vr4300 -mfix4300 -mabi=32 -mhard-float -mdivide-breaks -fno-unsafe-math-optimizations -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-PIC -mno-abicalls -fno-strict-aliasing -ffreestanding -fwrapv -Wall -Wextra
CFLAGS += -Wno-missing-braces -Wno-maybe-uninitialized
ASFLAGS := -march=vr4300 -mabi=32 $(foreach i,$(INCLUDE_DIRS),-I$(i)) $(foreach d,$(DEFINES),--defsym $(d))

BIN
data/benchmark_replay.m64 Normal file

Binary file not shown.

8
include/cfg/benchmark.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
/*
* Enables a basic performance benchmark over the vanilla game by replaying the 2012
* 120 star TAS.
*/
// #define CFG_BENCHMARK

View File

@@ -41,7 +41,7 @@ CC := $(CROSS)gcc
WARNINGS := -Wall -Wextra -Wno-format-security -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-builtin-declaration-mismatch
WARNINGS += -Wno-int-conversion -Wno-incompatible-pointer-types -Wno-implicit-function-declaration # TODO: Try adjusting code to remove these
CFLAGS := -std=gnu23 -G 0 -c -nostdinc -march=vr4300 -mfix4300 -mabi=32 -mno-abicalls -mdivide-breaks -fno-PIC -fno-common -ffreestanding -fbuiltin -fno-builtin-sinf -fno-builtin-cosf -funsigned-char $(WARNINGS)
CFLAGS := -std=gnu23 -G 0 -c -fno-inline -nostdinc -march=vr4300 -mfix4300 -mabi=32 -mno-abicalls -mdivide-breaks -fno-PIC -fno-common -ffreestanding -fbuiltin -fno-builtin-sinf -fno-builtin-cosf -funsigned-char $(WARNINGS)
CFLAGS += -fno-strict-aliasing # TODO: Try adjusting code to remove this
ASFLAGS := -w -nostdinc -c -G 0 -march=vr4300 -mabi=32 -mgp32 -mfp32 -DMIPSEB -D_LANGUAGE_ASSEMBLY -D_MIPS_SIM=1 -D_ULTRA64
CPPFLAGS = -DMODERN_CC -D_MIPS_SZLONG=32 -D__USE_ISOC99 $(GBIDEFINE) $(VERSION_DEFINE) $(DEBUGFLAG)

48
src/game/benchmark.c Normal file
View File

@@ -0,0 +1,48 @@
#include <ultra64.h>
#include "cfg/benchmark.h"
#include "game_init.h"
#include "n64-stdio.h"
#ifdef CFG_BENCHMARK
#define REPLAY_FILE "data/benchmark_replay.m64"
#define REPLAY_HEADER_SIZE 0x400
#define REPLAY_FRAME_SIZE sizeof(ReplayContPad)
typedef struct {
u16 button;
s8 stickX;
s8 stickY;
} ReplayContPad;
static alignas(32) u8 replayData[] = {
#embed REPLAY_FILE
};
static u8 *replayDataPtr = &replayData[0] + REPLAY_HEADER_SIZE;
static u8 *replayDataEnd = &replayData[0] + (sizeof(replayData));
static u32 benchmarkFrame = 0;
void replay_contpad(OSContPad *pad) {
ReplayContPad *input = (ReplayContPad *) replayDataPtr;
if (replayDataPtr >= replayDataEnd) {
return;
}
pad->button = input->button;
pad->stick_x = input->stickX;
pad->stick_y = input->stickY;
replayDataPtr += REPLAY_FRAME_SIZE;
}
void replay_print_stats() {
OSTime finalTime = osGetTime();
n64_printf("BENCHMARK END\n");
n64_printf("Time to complete: %llu us\n", OS_CYCLES_TO_USEC(finalTime));
n64_printf("Average FPS: %.2f", (f32)gGlobalTimer * 1000000.0f / OS_CYCLES_TO_USEC(finalTime));
}
#endif

6
src/game/benchmark.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#define REPLAY_CONTPAD_BITS 0xF0
void replay_contpad(OSContPad *pad);
void replay_print_stats();

View File

@@ -1,5 +1,7 @@
#include <ultra64.h>
#include "cfg/benchmark.h"
#include "sm64.h"
#include "gfx_dimensions.h"
#include "audio/external.h"
@@ -20,6 +22,8 @@
#include "segment_symbols.h"
#include "rumble_init.h"
#include "benchmark.h"
// First 3 controller slots
struct Controller gControllers[3];
@@ -525,15 +529,23 @@ void run_demo_inputs(void) {
*/
void read_controller_inputs(void) {
s32 i;
#ifndef CFG_BENCHMARK
// If any controllers are plugged in, update the controller information.
if (gControllerBits) {
osRecvMesg(&gSIEventMesgQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
osContGetReadData(&gControllerPads[0]);
#if ENABLE_RUMBLE
#if ENABLE_RUMBLE
release_rumble_pak_control();
#endif
#endif
}
#else
osRecvMesg(&gSIEventMesgQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
replay_contpad(&gControllerPads[0]);
#if ENABLE_RUMBLE
release_rumble_pak_control();
#endif
#endif
run_demo_inputs();
for (i = 0; i < 2; i++) {
@@ -579,10 +591,15 @@ void init_controllers(void) {
// Set controller 1 to point to the set of status/pads for input 1 and
// init the controllers.
#ifndef CFG_BENCHMARK
gControllers[0].statusData = &gControllerStatuses[0];
gControllers[0].controllerData = &gControllerPads[0];
osContInit(&gSIEventMesgQueue, &gControllerBits, &gControllerStatuses[0]);
#else
gControllers[0].statusData = &gControllerStatuses[0];
gControllers[0].controllerData = &gControllerPads[0];
gControllerBits = REPLAY_CONTPAD_BITS;
#endif
// Strangely enough, the EEPROM probe for save data is done in this function.
// Save Pak detection?
gEepromProbe = osEepromProbe(&gSIEventMesgQueue);

View File

@@ -1,5 +1,7 @@
#include <PR/ultratypes.h>
#include "cfg/benchmark.h"
#include "sm64.h"
#include "geo_misc.h"
@@ -14,6 +16,7 @@
#include "init/memory.h"
#include "object_list_processor.h"
#include "rendering_graph_node.h"
#include "benchmark.h"
#include "save_file.h"
#include "segment2.h"
@@ -199,6 +202,12 @@ Gfx *geo_exec_cake_end_screen(s32 callContext, struct GraphNode *node, UNUSED f3
Gfx *displayList = NULL;
Gfx *displayListHead = NULL;
#ifdef CFG_BENCHMARK
if (callContext == GEO_CONTEXT_AREA_LOAD) {
replay_print_stats();
}
#endif
if (callContext == GEO_CONTEXT_RENDER) {
displayList = alloc_display_list(3 * sizeof(*displayList));
displayListHead = displayList;