mirror of
https://github.com/blawar/ooot.git
synced 2024-07-04 18:13:37 +00:00
Added Command Line Arguments (#156)
* Cleaned up the input stuff. * Put all the input related classes into the namespace `hid` and did some further cleanup. * TAS support is now working. Generates `last-run.tas`. * Added *.tas to .gitignore. * Put `hid` into namespace `oot`. * Added a trivial form of compression for TAS files. * End of TAS playback results in end of execution. Added command line arguments: -tas <filename> Selects the TAS file that should be played back -no-graphics Disabled graphics. The window is still open though -fast-forward Disables frame pacing, makes the game run as fast as possible * Window now doesn't open anymore when -no-graphics is provided. However, to make GLideN64 not crash a patch is required (PR for GLideN64 incoming). * Cleanup. Co-authored-by: DaMarkov <DaMarkovZED@gmail.com>
This commit is contained in:
parent
0dec26fce0
commit
63e415c816
|
@ -37,6 +37,8 @@
|
|||
#include "def/z_game_dlftbls.h"
|
||||
#include "def/z_prenmi_buff.h"
|
||||
#include "def/z_play.h" // FORCE
|
||||
#include "../port/controller/tas.h"
|
||||
#include "../port/options.h"
|
||||
|
||||
extern GameStateOverlay gGameStateOverlayTable[6];
|
||||
extern PreNmiBuff* gAppNmiBufferPtr;
|
||||
|
@ -206,6 +208,7 @@ void Graph_TaskSet00(GraphicsContext* gfxCtx) {
|
|||
osSendMesg(&gSchedContext.cmdQ, scTask, OS_MESG_BLOCK);
|
||||
Sched_SendEntryMsg(&gSchedContext);
|
||||
|
||||
if (!oot::config().game().isGraphicsDisabled())
|
||||
gfx_run(task, sizeof(OSTask_t));
|
||||
}
|
||||
|
||||
|
@ -393,12 +396,26 @@ void Graph_ThreadEntry(void* arg0) {
|
|||
GameState_Init(gameState, (GameStateFunc)ovl->init, &gfxCtx);
|
||||
|
||||
while (GameState_IsRunning(gameState) && isRunning()) {
|
||||
//Has the TAS playback completed?
|
||||
if (oot::hid::tas::isTasPlaying() && oot::hid::tas::hasTasEnded())
|
||||
break;
|
||||
|
||||
if (oot::config().game().isGraphicsDisabled())
|
||||
{
|
||||
gfx_start_frame();
|
||||
Graph_Update(&gfxCtx, gameState);
|
||||
gfx_end_frame();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (gfx_start_frame())
|
||||
{
|
||||
Graph_Update(&gfxCtx, gameState);
|
||||
gfx_end_frame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nextOvl = Graph_GetNextGameState(gameState);
|
||||
GameState_Destroy(gameState);
|
||||
|
|
|
@ -117,7 +117,7 @@ void N64Controller::resolveInputs()
|
|||
#define SRAM_SIZE 0x8000//But this in ultra_reimplementation.h?
|
||||
|
||||
//Recording TAS?
|
||||
if (!Tas::isTasPlaying() && oot::config().game().recordTas())
|
||||
if (!tas::isTasPlaying() && oot::config().game().recordTas())
|
||||
{
|
||||
//stream().write((const char*)&m_state, sizeof(m_state));
|
||||
|
||||
|
@ -159,7 +159,7 @@ void N64Controller::resolveInputs()
|
|||
}
|
||||
|
||||
//Playing back a TAS?
|
||||
else if (Tas::isTasPlaying())
|
||||
else if (tas::isTasPlaying())
|
||||
{
|
||||
if (!m_tasFile)
|
||||
{
|
||||
|
@ -188,7 +188,11 @@ void N64Controller::resolveInputs()
|
|||
{
|
||||
//fread(&m_state, sizeof(m_state), 1, m_tasFile);//Uncompressed read
|
||||
StateCompressed compressed;
|
||||
compressed.read(m_tasFile);//Read the compressed state
|
||||
bool end_of_file = compressed.read(m_tasFile);//Read the compressed state
|
||||
|
||||
if (end_of_file)//End of file reached, playback is complete
|
||||
tas::TasEnded();
|
||||
else
|
||||
m_state = compressed;//Uncompress
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,11 +52,13 @@ namespace oot
|
|||
return ret;
|
||||
}
|
||||
|
||||
void read(FILE* in) {
|
||||
fread(&m_isUsed, sizeof(u8), 1, in);//Read the flag
|
||||
bool read(FILE* in) {
|
||||
if (fread(&m_isUsed, sizeof(u8), 1, in) != 1)//Read the flag
|
||||
return true;//End of file reached
|
||||
|
||||
if (m_isUsed)//Is there even any input?
|
||||
fread(&m_data, sizeof(InputFrame), 1, in);//Write the full state
|
||||
return false;
|
||||
}
|
||||
|
||||
void write(FILE* out) {
|
||||
|
|
|
@ -302,7 +302,7 @@ void Keyboard::update()
|
|||
if (state[SDL_SCANCODE_F5] && (m_lastKeyState[SDL_SCANCODE_F5] ^ state[SDL_SCANCODE_F5]))
|
||||
m_state.button |= (uint16_t)Button::U_JPAD | (uint16_t)Button::D_JPAD | (uint16_t)Button::L_JPAD | (uint16_t)Button::R_JPAD;
|
||||
|
||||
if (Tas::isTasPlaying())
|
||||
if (tas::isTasPlaying())
|
||||
return;
|
||||
|
||||
for (const auto& [scancode, input] : m_keyBindings)
|
||||
|
|
|
@ -369,7 +369,7 @@ bool Joypad::updateRebind(Button input)
|
|||
|
||||
void Joypad::update()
|
||||
{
|
||||
if (!m_context || Tas::isTasPlaying())
|
||||
if (!m_context || tas::isTasPlaying())
|
||||
return;
|
||||
|
||||
bool walk = false;
|
||||
|
|
|
@ -4,81 +4,114 @@
|
|||
#include "../options.h"
|
||||
#include "tas.h"
|
||||
|
||||
static u64 g_counter = 0;
|
||||
static bool g_tasPlaying = false;
|
||||
|
||||
using namespace oot::hid;
|
||||
using namespace oot::hid::tas;
|
||||
|
||||
bool g_tasPlaying = false;
|
||||
bool g_tasEnded = false;
|
||||
std::string g_tasFilename;
|
||||
|
||||
|
||||
bool Tas::isTasPlaying()
|
||||
bool oot::hid::tas::isTasPlaying()
|
||||
{
|
||||
return g_tasPlaying;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Tas::playTas(bool enabled)
|
||||
void oot::hid::tas::playTas(bool enable)
|
||||
{
|
||||
g_tasPlaying = enabled;
|
||||
g_tasPlaying = enable;
|
||||
}
|
||||
|
||||
void oot::hid::tas::setTasFileName(const std::string& newFilename)
|
||||
{
|
||||
g_tasFilename = newFilename;
|
||||
}
|
||||
|
||||
std::string oot::hid::tas::getTasFileName()
|
||||
{
|
||||
if (g_tasFilename.empty())
|
||||
g_tasFilename = "last-run.tas";
|
||||
return g_tasFilename;
|
||||
/*std::error_code error;
|
||||
std::filesystem::create_directory(TAS_DIR, error);
|
||||
|
||||
time_t now = time(0);
|
||||
tm* ltm = localtime(&now);
|
||||
|
||||
if (!ltm)
|
||||
return TAS_DIR"/record.tas";
|
||||
|
||||
char buf[64] = { 0 };
|
||||
sprintf(buf, TAS_DIR"/%04d.%02d.%02d-%04d.tas", ltm->tm_year, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour * 60 + ltm->tm_min);
|
||||
return buf;*/
|
||||
}
|
||||
|
||||
void oot::hid::tas::TasEnded()
|
||||
{
|
||||
g_tasEnded = true;
|
||||
}
|
||||
|
||||
bool oot::hid::tas::hasTasEnded()
|
||||
{
|
||||
return g_tasEnded;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Tas::Tas() : N64Controller()
|
||||
/*namespace controller
|
||||
{
|
||||
fp = fopen("last-run.tas", "rb");
|
||||
|
||||
if (fp)
|
||||
class Tas : public Controller
|
||||
{
|
||||
//fread(&oot::config(), 1, sizeof(oot::config()), fp);
|
||||
|
||||
#define SRAM_SIZE 0x8000//But this in ultra_reimplementation.h?
|
||||
|
||||
uint8_t* sram = new uint8_t[SRAM_SIZE];
|
||||
fread(sram, sizeof(uint8_t), SRAM_SIZE, fp);
|
||||
|
||||
FILE* save = nullptr;
|
||||
fopen_s(&save, "oot.sav", "wb");
|
||||
if (save)
|
||||
public:
|
||||
Tas() : Controller()
|
||||
{
|
||||
fwrite(sram, sizeof(uint8_t), SRAM_SIZE, save);
|
||||
fclose(save);
|
||||
}
|
||||
|
||||
delete[] sram;
|
||||
fp = fopen("cont.tas", "rb");
|
||||
|
||||
if(fp != NULL)
|
||||
{
|
||||
fread(&oot::config(), 1, sizeof(oot::config()), fp);
|
||||
g_tasPlaying = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Tas::~Tas()
|
||||
virtual ~Tas()
|
||||
{
|
||||
if(fp)
|
||||
{
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Tas::update()
|
||||
void update()
|
||||
{
|
||||
if (fp)
|
||||
if(fp != NULL)
|
||||
{
|
||||
auto r = fread(&m_state, 1, sizeof(m_state), fp);
|
||||
if (m_state.button)
|
||||
{
|
||||
int x = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
FILE* fp;
|
||||
};
|
||||
} // namespace controller
|
||||
|
||||
Tas::Tas() : Driver()
|
||||
{
|
||||
}
|
||||
|
||||
void Tas::scan()
|
||||
Tas::~Tas()
|
||||
{
|
||||
}
|
||||
|
||||
void Tas::scan(class Controllers* controllers)
|
||||
{
|
||||
if (!size())
|
||||
{
|
||||
auto controller = std::make_shared<Tas>();
|
||||
auto controller = std::make_shared<controller::Tas>();
|
||||
m_controllers.push_back(controller);
|
||||
Players::get().attach(controller, 0);
|
||||
}
|
||||
players().attach(controller, 0);
|
||||
}
|
||||
}*/
|
|
@ -1,26 +1,19 @@
|
|||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include "controllers.h"
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
namespace oot
|
||||
namespace oot::hid
|
||||
{
|
||||
namespace hid
|
||||
namespace tas
|
||||
{
|
||||
class Tas : public N64Controller, public InputDevice
|
||||
{
|
||||
public:
|
||||
static bool isTasPlaying();
|
||||
static void playTas(bool enabled);
|
||||
bool isTasPlaying();
|
||||
void playTas(bool enable);
|
||||
|
||||
Tas();
|
||||
virtual ~Tas();
|
||||
void scan() override;
|
||||
void update();
|
||||
std::string getTasFileName();
|
||||
void setTasFileName(const std::string& newFilename);
|
||||
|
||||
private:
|
||||
FILE* fp = nullptr;
|
||||
};
|
||||
void TasEnded();//Called when the TAS has ended (end of file of .tas file reached)
|
||||
bool hasTasEnded();//Returns true when playback was complete
|
||||
}
|
||||
}
|
|
@ -1,4 +1,8 @@
|
|||
#include "global.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "global.h"
|
||||
#include "options.h"
|
||||
#include "controller/tas.h"
|
||||
#include "ultra64/types.h"
|
||||
#include "ultra64/vi.h"
|
||||
#include "z64audio.h"
|
||||
|
@ -129,7 +133,40 @@ extern f32 gViConfigXScale;
|
|||
extern f32 gViConfigYScale;
|
||||
extern u32 gViConfigFeatures;
|
||||
|
||||
int main() {
|
||||
|
||||
|
||||
void ParseCommandLineArguments(const std::vector<std::string>& commands)
|
||||
{
|
||||
auto size_left = commands.size();
|
||||
for (size_t i = 0; i < commands.size(); i++)
|
||||
{
|
||||
auto& cmd = commands[i];
|
||||
size_left--;
|
||||
|
||||
if (cmd == "-tas" && size_left > 0)
|
||||
{
|
||||
auto tas_filename = std::move(commands[++i]);
|
||||
oot::hid::tas::setTasFileName(tas_filename);
|
||||
oot::hid::tas::playTas(true);
|
||||
}
|
||||
|
||||
else if (cmd == "-no-graphics")
|
||||
oot::config().game().disableGraphics();
|
||||
|
||||
else if (cmd == "-fast-forward")
|
||||
oot::config().game().disableFramePacing();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::vector<std::string> commands;
|
||||
for (int i = 1; i < argc; i++)
|
||||
commands.push_back(argv[i]);
|
||||
|
||||
ParseCommandLineArguments(commands);
|
||||
|
||||
s16* msg;
|
||||
|
||||
|
||||
|
|
|
@ -273,14 +273,29 @@ namespace oot
|
|||
return m_blindowl;
|
||||
}
|
||||
|
||||
bool& Game::isGraphicsDisabled()
|
||||
{
|
||||
return m_disableGraphics;
|
||||
}
|
||||
|
||||
void Game::disableGraphics()
|
||||
{
|
||||
m_disableGraphics = true;
|
||||
}
|
||||
|
||||
bool& Game::disableSound()
|
||||
{
|
||||
return m_disableSound;
|
||||
}
|
||||
|
||||
bool& Game::disableFramePacing()
|
||||
bool Game::isFramePacing()
|
||||
{
|
||||
return m_paceFrames;
|
||||
return !m_paceFramesDisabled;
|
||||
}
|
||||
|
||||
void Game::disableFramePacing()
|
||||
{
|
||||
m_paceFramesDisabled = true;
|
||||
}
|
||||
|
||||
bool& Game::recordTas()
|
||||
|
|
|
@ -172,13 +172,16 @@ namespace oot
|
|||
float framerateScaler() const;
|
||||
u8 framerateScalerInv() const;
|
||||
|
||||
bool& isGraphicsDisabled();
|
||||
void disableGraphics();
|
||||
bool& disableSound();
|
||||
bool& fullscreen();
|
||||
const bool mirror() const;
|
||||
bool& setMirror();
|
||||
bool& blindOwl();
|
||||
|
||||
bool& disableFramePacing();
|
||||
bool isFramePacing();
|
||||
void disableFramePacing();
|
||||
|
||||
bool& recordTas();
|
||||
void recordTas(bool enable);
|
||||
|
@ -187,14 +190,15 @@ namespace oot
|
|||
protected:
|
||||
u8 m_overclock;
|
||||
u8 m_framerate;
|
||||
bool m_disableGraphics;
|
||||
bool m_disableSound;
|
||||
bool m_fullscreen;
|
||||
bool m_mirror;
|
||||
bool m_blindowl;
|
||||
bool m_paceFrames;
|
||||
bool m_paceFramesDisabled;
|
||||
bool m_recordTas;
|
||||
bool m_forceMouse;
|
||||
u8 m_padding[0x40 - 9];
|
||||
u8 m_padding[0x40 - 10];
|
||||
};
|
||||
|
||||
static_assert(sizeof(Game) == 0x40, "Game Incorrect Size");
|
||||
|
|
|
@ -291,9 +291,9 @@ void main_func(void)
|
|||
#endif
|
||||
|
||||
#ifdef _DEBUG//Record TAS to capture bugs and crashes
|
||||
oot::hid::Tas::playTas(true);//Uncomment to play back TAS/crash report from end-users
|
||||
//oot::hid::tas::playTas(true);//Uncomment to play back TAS/crash report from end-users
|
||||
|
||||
if (!oot::hid::Tas::isTasPlaying())
|
||||
if (!oot::hid::tas::isTasPlaying())
|
||||
oot::config().game().recordTas(true);
|
||||
#endif
|
||||
|
||||
|
@ -316,6 +316,7 @@ void main_func(void)
|
|||
//audio_init();
|
||||
//interface_init();
|
||||
|
||||
if (!oot::config().game().isGraphicsDisabled())
|
||||
gWindow = platform::window::create("The Legend of Zelda - Ocarina of Time", false);
|
||||
|
||||
#ifdef USE_F3D
|
||||
|
@ -327,10 +328,15 @@ void main_func(void)
|
|||
|
||||
screen_init(&config);
|
||||
#elif defined(USE_GLIDEN64)
|
||||
if (!oot::config().game().isGraphicsDisabled())
|
||||
{
|
||||
gfx_init("THE LEGEND OF ZELDA", &osViModeNtscLan1);
|
||||
//gfx_fbe_enable(0);//Uncomment to disable frame buffer emulation
|
||||
}
|
||||
#endif
|
||||
if (!oot::config().game().isGraphicsDisabled())
|
||||
gWindow->resize(-1, -1);
|
||||
|
||||
hid_init();
|
||||
|
||||
game_init(NULL);
|
||||
|
@ -452,4 +458,3 @@ void quit()
|
|||
{
|
||||
g_isRunning = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "../window.h"
|
||||
#include <thread>
|
||||
#include "z64.h"
|
||||
#include "../options.h"
|
||||
|
||||
namespace platform::window
|
||||
{
|
||||
|
@ -108,8 +109,10 @@ namespace platform::window
|
|||
bool Base::begin_frame()
|
||||
{
|
||||
handle_events();
|
||||
while(!run_paced_loop())
|
||||
if (oot::config().game().isFramePacing())
|
||||
{
|
||||
while (!run_paced_loop())
|
||||
{}
|
||||
}
|
||||
return !dropped_frame;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user