mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2025-04-02 10:31:51 -04:00
The homebrew module
The homebrew module offers configurable ports useful to homebrew game developers. By reading and writing to new ports at configurable addresses, a rom may * write to stdout * write to stderr * exit the emulator with a given exit status These can be used to create automated test suites.
This commit is contained in:
parent
6baed9b36a
commit
b8e4f1f501
12 changed files with 875 additions and 7 deletions
|
@ -150,6 +150,7 @@ nestopia_SOURCES = \
|
|||
source/core/NstCartridge.hpp \
|
||||
source/core/NstStream.cpp \
|
||||
source/core/NstCheats.hpp \
|
||||
source/core/NstHomebrew.hpp \
|
||||
source/core/vssystem/NstVsSystem.hpp \
|
||||
source/core/vssystem/NstVsRbiBaseball.hpp \
|
||||
source/core/vssystem/NstVsSuperXevious.cpp \
|
||||
|
@ -199,6 +200,7 @@ nestopia_SOURCES = \
|
|||
source/core/api/NstApiEmulator.hpp \
|
||||
source/core/api/NstApiVideo.cpp \
|
||||
source/core/api/NstApiCheats.cpp \
|
||||
source/core/api/NstApiHomebrew.cpp \
|
||||
source/core/api/NstApiMovie.hpp \
|
||||
source/core/api/NstApiCartridge.cpp \
|
||||
source/core/api/NstApi.hpp \
|
||||
|
@ -221,6 +223,7 @@ nestopia_SOURCES = \
|
|||
source/core/api/NstApiFds.hpp \
|
||||
source/core/api/NstApiVideo.hpp \
|
||||
source/core/api/NstApiCheats.hpp \
|
||||
source/core/api/NstApiHomebrew.hpp \
|
||||
source/core/api/NstApiBarcodeReader.cpp \
|
||||
source/core/api/NstApiInput.hpp \
|
||||
source/core/api/NstApiInput.cpp \
|
||||
|
@ -234,6 +237,7 @@ nestopia_SOURCES = \
|
|||
source/core/NstFpuPrecision.hpp \
|
||||
source/core/NstRam.hpp \
|
||||
source/core/NstCheats.cpp \
|
||||
source/core/NstHomebrew.cpp \
|
||||
source/core/NstZlib.cpp \
|
||||
source/core/NstStream.hpp \
|
||||
source/core/NstBase.hpp \
|
||||
|
@ -703,6 +707,8 @@ nestopia_SOURCES += \
|
|||
source/common/nstcommon.h \
|
||||
source/common/cheats.cpp \
|
||||
source/common/cheats.h \
|
||||
source/common/homebrew.cpp \
|
||||
source/common/homebrew.h \
|
||||
source/common/cli.cpp \
|
||||
source/common/cli.h \
|
||||
source/common/config.cpp \
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
* Nestopia UE
|
||||
*
|
||||
* Copyright (C) 2012-2016 R. Danbrook
|
||||
*
|
||||
* Copyright (C) 2018-2018 Phil Smith
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
|
@ -136,8 +137,12 @@ void config_file_write(const char *nstdir) {
|
|||
fprintf(fp, "last_folder=%s\n", conf.misc_last_folder);
|
||||
fprintf(fp, "; 0=0x00, 1=0xFF, 2=Random\n");
|
||||
fprintf(fp, "power_state=%d\n", conf.misc_power_state);
|
||||
fprintf(fp, "overclock=%d\n", conf.misc_overclock);
|
||||
|
||||
fprintf(fp, "overclock=%d\n\n", conf.misc_overclock);
|
||||
fprintf(fp, "; Valid values are -1 (disabled) or 0 to 65535.\n");
|
||||
fprintf(fp, "homebrew_exit=%d\n", conf.misc_homebrew_exit);
|
||||
fprintf(fp, "homebrew_stdout=%d\n", conf.misc_homebrew_stdout);
|
||||
fprintf(fp, "homebrew_stderr=%d\n", conf.misc_homebrew_stderr);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
else {
|
||||
|
@ -207,6 +212,9 @@ void config_set_default() {
|
|||
conf.misc_last_folder = NULL;
|
||||
conf.misc_power_state = 0;
|
||||
conf.misc_overclock = false;
|
||||
conf.misc_homebrew_exit = -1;
|
||||
conf.misc_homebrew_stdout = -1;
|
||||
conf.misc_homebrew_stderr = -1;
|
||||
}
|
||||
|
||||
static int config_match(void* user, const char* section, const char* name, const char* value) {
|
||||
|
@ -273,7 +281,10 @@ static int config_match(void* user, const char* section, const char* name, const
|
|||
else if (MATCH("misc", "last_folder")) { pconfig->misc_last_folder = strdup(value); }
|
||||
else if (MATCH("misc", "power_state")) { pconfig->misc_power_state = atoi(value); }
|
||||
else if (MATCH("misc", "overclock")) { pconfig->misc_overclock = atoi(value); }
|
||||
|
||||
else if (MATCH("misc", "homebrew_exit")) { pconfig->misc_homebrew_exit = atoi(value); }
|
||||
else if (MATCH("misc", "homebrew_stdout")) { pconfig->misc_homebrew_stdout = atoi(value); }
|
||||
else if (MATCH("misc", "homebrew_stderr")) { pconfig->misc_homebrew_stderr = atoi(value); }
|
||||
|
||||
else { return 0; }
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -63,6 +63,9 @@ typedef struct {
|
|||
char* misc_last_folder;
|
||||
int misc_power_state;
|
||||
bool misc_overclock;
|
||||
int misc_homebrew_exit;
|
||||
int misc_homebrew_stdout;
|
||||
int misc_homebrew_stderr;
|
||||
} settings_t;
|
||||
|
||||
void config_file_read(const char *nstdir);
|
||||
|
|
46
source/common/homebrew.cpp
Normal file
46
source/common/homebrew.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Nestopia UE
|
||||
*
|
||||
* Copyright (C) 2018-2018 Phil Smith
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "homebrew.h"
|
||||
|
||||
extern Emulator emulator;
|
||||
|
||||
void nst_homebrew_init() {
|
||||
Homebrew homebrew(emulator);
|
||||
homebrew.ClearPorts();
|
||||
|
||||
if (conf.misc_homebrew_exit != -1)
|
||||
{
|
||||
homebrew.SetExitPort(conf.misc_homebrew_exit);
|
||||
}
|
||||
|
||||
if (conf.misc_homebrew_stdout != -1)
|
||||
{
|
||||
homebrew.SetStdOutPort(conf.misc_homebrew_stdout);
|
||||
}
|
||||
|
||||
if (conf.misc_homebrew_stderr != -1)
|
||||
{
|
||||
homebrew.SetStdErrPort(conf.misc_homebrew_stderr);
|
||||
}
|
||||
}
|
33
source/common/homebrew.h
Normal file
33
source/common/homebrew.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Nestopia UE
|
||||
*
|
||||
* Copyright (C) 2018-2018 Phil Smith
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HOMEBREW_H_
|
||||
#define _HOMEBREW_H_
|
||||
|
||||
#include "core/api/NstApiEmulator.hpp"
|
||||
#include "core/api/NstApiHomebrew.hpp"
|
||||
|
||||
using namespace Nes::Api;
|
||||
|
||||
void nst_homebrew_init();
|
||||
|
||||
#endif
|
|
@ -3,7 +3,8 @@
|
|||
*
|
||||
* Copyright (C) 2007-2008 R. Belmont
|
||||
* Copyright (C) 2012-2018 R. Danbrook
|
||||
*
|
||||
* Copyright (C) 2018-2018 Phil Smith
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
|
@ -46,6 +47,7 @@
|
|||
#include "nstcommon.h"
|
||||
#include "config.h"
|
||||
#include "cheats.h"
|
||||
#include "homebrew.h"
|
||||
#include "input.h"
|
||||
#include "audio.h"
|
||||
#include "video.h"
|
||||
|
@ -890,7 +892,8 @@ void nst_play() {
|
|||
audio_init();
|
||||
nst_input_init();
|
||||
nst_cheats_init(nstpaths.cheatpath);
|
||||
|
||||
nst_homebrew_init();
|
||||
|
||||
cNstVideo = new Video::Output;
|
||||
cNstSound = new Sound::Output;
|
||||
cNstPads = new Input::Controllers;
|
||||
|
|
307
source/core/NstHomebrew.cpp
Normal file
307
source/core/NstHomebrew.cpp
Normal file
|
@ -0,0 +1,307 @@
|
|||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Nestopia - NES/Famicom emulator written in C++
|
||||
//
|
||||
// Copyright (C) 2018-2018 Phil Smith
|
||||
//
|
||||
// This file is part of Nestopia.
|
||||
//
|
||||
// Nestopia is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Nestopia is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Nestopia; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include "NstCpu.hpp"
|
||||
#include "NstHomebrew.hpp"
|
||||
|
||||
namespace Nes
|
||||
{
|
||||
namespace Core
|
||||
{
|
||||
#ifdef NST_MSVC_OPTIMIZE
|
||||
#pragma optimize("s", on)
|
||||
#endif
|
||||
|
||||
Homebrew::Homebrew(Cpu& c)
|
||||
: cpu(c)
|
||||
, exitAddress(0)
|
||||
, exitSet(false)
|
||||
, exitPort(NULL)
|
||||
, stdOutAddress(0)
|
||||
, stdOutSet(false)
|
||||
, stdOutPort(NULL)
|
||||
, stdErrAddress(0)
|
||||
, stdErrSet(false)
|
||||
, stdErrPort(NULL)
|
||||
{}
|
||||
|
||||
Homebrew::~Homebrew()
|
||||
{
|
||||
ClearPorts();
|
||||
}
|
||||
|
||||
void Homebrew::Reset()
|
||||
{
|
||||
ActivateExitPort();
|
||||
ActivateStdOutPort();
|
||||
ActivateStdErrPort();
|
||||
}
|
||||
|
||||
void Homebrew::ClearPorts()
|
||||
{
|
||||
ClearExitPort();
|
||||
ClearStdOutPort();
|
||||
ClearStdErrPort();
|
||||
}
|
||||
|
||||
Result Homebrew::SetExitPort
|
||||
(
|
||||
const word address,
|
||||
const bool activate
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
exitSet
|
||||
&& exitAddress == address
|
||||
&& (!activate || exitPort != NULL)
|
||||
)
|
||||
return RESULT_NOP;
|
||||
|
||||
ClearExitPort();
|
||||
|
||||
exitAddress = address;
|
||||
exitSet = true;
|
||||
|
||||
if (activate)
|
||||
return ActivateExitPort();
|
||||
else
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
Result Homebrew::ClearExitPort()
|
||||
{
|
||||
exitSet = false;
|
||||
|
||||
if (exitPort != NULL)
|
||||
{
|
||||
cpu.Unlink
|
||||
(
|
||||
exitAddress,
|
||||
this,
|
||||
&Homebrew::Peek_Exit,
|
||||
&Homebrew::Poke_Exit
|
||||
);
|
||||
exitPort = NULL;
|
||||
return RESULT_OK;
|
||||
}
|
||||
else
|
||||
return RESULT_NOP;
|
||||
}
|
||||
|
||||
Result Homebrew::SetStdOutPort
|
||||
(
|
||||
const word address,
|
||||
const bool activate
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
stdOutSet
|
||||
&& stdOutAddress == address
|
||||
&& (!activate || stdOutPort != NULL)
|
||||
)
|
||||
return RESULT_NOP;
|
||||
|
||||
ClearStdOutPort();
|
||||
|
||||
stdOutAddress = address;
|
||||
stdOutSet = true;
|
||||
|
||||
if (activate)
|
||||
return ActivateStdOutPort();
|
||||
else
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
Result Homebrew::ClearStdOutPort()
|
||||
{
|
||||
stdOutSet = false;
|
||||
|
||||
if (stdOutPort != NULL)
|
||||
{
|
||||
cpu.Unlink
|
||||
(
|
||||
stdOutAddress,
|
||||
this,
|
||||
&Homebrew::Peek_StdOut,
|
||||
&Homebrew::Poke_StdOut
|
||||
);
|
||||
stdOutPort = NULL;
|
||||
return RESULT_OK;
|
||||
}
|
||||
else
|
||||
return RESULT_NOP;
|
||||
}
|
||||
|
||||
Result Homebrew::SetStdErrPort
|
||||
(
|
||||
const word address,
|
||||
const bool activate
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
stdErrSet
|
||||
&& stdErrAddress == address
|
||||
&& (!activate || stdErrPort != NULL)
|
||||
)
|
||||
return RESULT_NOP;
|
||||
|
||||
ClearStdErrPort();
|
||||
|
||||
stdErrAddress = address;
|
||||
stdErrSet = true;
|
||||
|
||||
if (activate)
|
||||
return ActivateStdErrPort();
|
||||
else
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
Result Homebrew::ClearStdErrPort()
|
||||
{
|
||||
stdErrSet = false;
|
||||
|
||||
if (stdErrPort != NULL)
|
||||
{
|
||||
cpu.Unlink
|
||||
(
|
||||
stdErrAddress,
|
||||
this,
|
||||
&Homebrew::Peek_StdErr,
|
||||
&Homebrew::Poke_StdErr
|
||||
);
|
||||
stdErrPort = NULL;
|
||||
return RESULT_OK;
|
||||
}
|
||||
else
|
||||
return RESULT_NOP;
|
||||
}
|
||||
|
||||
dword Homebrew::NumPorts() const
|
||||
{
|
||||
return (exitPort != NULL ? 1 : 0)
|
||||
+ (stdOutPort != NULL ? 1 : 0)
|
||||
+ (stdErrPort != NULL ? 1 : 0);
|
||||
}
|
||||
|
||||
#ifdef NST_MSVC_OPTIMIZE
|
||||
#pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
NES_PEEK_A(Homebrew,Exit)
|
||||
{
|
||||
return exitPort->Peek( address );
|
||||
}
|
||||
|
||||
NES_POKE_D(Homebrew,Exit)
|
||||
{
|
||||
std::exit( data );
|
||||
}
|
||||
|
||||
NES_PEEK_A(Homebrew,StdOut)
|
||||
{
|
||||
return stdOutPort->Peek( address );
|
||||
}
|
||||
|
||||
NES_POKE_D(Homebrew,StdOut)
|
||||
{
|
||||
std::cout << (static_cast<unsigned char>(data & 0xFF));
|
||||
|
||||
if (data == '\n')
|
||||
std::cout << std::flush;
|
||||
}
|
||||
|
||||
NES_PEEK_A(Homebrew,StdErr)
|
||||
{
|
||||
return stdErrPort->Peek( address );
|
||||
}
|
||||
|
||||
NES_POKE_D(Homebrew,StdErr)
|
||||
{
|
||||
std::cerr << (static_cast<unsigned char>(data & 0xFF));
|
||||
|
||||
if (data == '\n')
|
||||
std::cerr << std::flush;
|
||||
}
|
||||
|
||||
Result Homebrew::ActivateExitPort()
|
||||
{
|
||||
if (exitSet && exitPort == NULL)
|
||||
{
|
||||
exitPort = cpu.Link
|
||||
(
|
||||
exitAddress,
|
||||
Cpu::LEVEL_HIGH,
|
||||
this,
|
||||
&Homebrew::Peek_Exit,
|
||||
&Homebrew::Poke_Exit
|
||||
);
|
||||
return RESULT_OK;
|
||||
}
|
||||
else
|
||||
return RESULT_NOP;
|
||||
}
|
||||
|
||||
Result Homebrew::ActivateStdOutPort()
|
||||
{
|
||||
if (stdOutSet && stdOutPort == NULL)
|
||||
{
|
||||
stdOutPort = cpu.Link
|
||||
(
|
||||
stdOutAddress,
|
||||
Cpu::LEVEL_HIGH,
|
||||
this,
|
||||
&Homebrew::Peek_StdOut,
|
||||
&Homebrew::Poke_StdOut
|
||||
);
|
||||
return RESULT_OK;
|
||||
}
|
||||
else
|
||||
return RESULT_NOP;
|
||||
}
|
||||
|
||||
Result Homebrew::ActivateStdErrPort()
|
||||
{
|
||||
if (stdErrSet && stdErrPort == NULL)
|
||||
{
|
||||
stdErrPort = cpu.Link
|
||||
(
|
||||
stdErrAddress,
|
||||
Cpu::LEVEL_HIGH,
|
||||
this,
|
||||
&Homebrew::Peek_StdErr,
|
||||
&Homebrew::Poke_StdErr
|
||||
);
|
||||
return RESULT_OK;
|
||||
}
|
||||
else
|
||||
return RESULT_NOP;
|
||||
}
|
||||
}
|
||||
}
|
93
source/core/NstHomebrew.hpp
Normal file
93
source/core/NstHomebrew.hpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Nestopia - NES/Famicom emulator written in C++
|
||||
//
|
||||
// Copyright (C) 2018-2018 Phil Smith
|
||||
//
|
||||
// This file is part of Nestopia.
|
||||
//
|
||||
// Nestopia is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Nestopia is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Nestopia; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef NST_HOMEBREW_H
|
||||
#define NST_HOMEBREW_H
|
||||
|
||||
#ifndef NST_VECTOR_H
|
||||
#include "NstVector.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef NST_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace Nes
|
||||
{
|
||||
namespace Core
|
||||
{
|
||||
class Homebrew
|
||||
{
|
||||
public:
|
||||
|
||||
explicit Homebrew(Cpu&);
|
||||
~Homebrew();
|
||||
|
||||
void Reset();
|
||||
void ClearPorts();
|
||||
|
||||
Result SetExitPort (word,bool);
|
||||
Result ClearExitPort ();
|
||||
|
||||
Result SetStdOutPort (word,bool);
|
||||
Result ClearStdOutPort ();
|
||||
|
||||
Result SetStdErrPort (word,bool);
|
||||
Result ClearStdErrPort ();
|
||||
|
||||
dword NumPorts () const;
|
||||
|
||||
private:
|
||||
|
||||
NES_DECL_PEEK( Exit );
|
||||
NES_DECL_POKE( Exit );
|
||||
|
||||
NES_DECL_PEEK( StdOut );
|
||||
NES_DECL_POKE( StdOut );
|
||||
|
||||
NES_DECL_PEEK( StdErr );
|
||||
NES_DECL_POKE( StdErr );
|
||||
|
||||
Result ActivateExitPort ();
|
||||
Result ActivateStdOutPort ();
|
||||
Result ActivateStdErrPort ();
|
||||
|
||||
Cpu& cpu;
|
||||
|
||||
word exitAddress;
|
||||
ibool exitSet;
|
||||
const Io::Port* exitPort;
|
||||
|
||||
word stdOutAddress;
|
||||
ibool stdOutSet;
|
||||
const Io::Port* stdOutPort;
|
||||
|
||||
word stdErrAddress;
|
||||
ibool stdErrSet;
|
||||
const Io::Port* stdErrPort;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -3,6 +3,7 @@
|
|||
// Nestopia - NES/Famicom emulator written in C++
|
||||
//
|
||||
// Copyright (C) 2003-2008 Martin Freij
|
||||
// Copyright (C) 2018-2018 Phil Smith
|
||||
//
|
||||
// This file is part of Nestopia.
|
||||
//
|
||||
|
@ -25,6 +26,7 @@
|
|||
#include "NstMachine.hpp"
|
||||
#include "NstCartridge.hpp"
|
||||
#include "NstCheats.hpp"
|
||||
#include "NstHomebrew.hpp"
|
||||
#include "NstNsf.hpp"
|
||||
#include "NstImageDatabase.hpp"
|
||||
#include "input/NstInpDevice.hpp"
|
||||
|
@ -49,6 +51,7 @@ namespace Nes
|
|||
expPort (new Input::Device( cpu )),
|
||||
image (NULL),
|
||||
cheats (NULL),
|
||||
homebrew (NULL),
|
||||
imageDatabase (NULL),
|
||||
ppu (cpu)
|
||||
{
|
||||
|
@ -60,6 +63,7 @@ namespace Nes
|
|||
|
||||
delete imageDatabase;
|
||||
delete cheats;
|
||||
delete homebrew;
|
||||
delete expPort;
|
||||
|
||||
for (uint ports=extPort->NumPorts(), i=0; i < ports; ++i)
|
||||
|
@ -294,6 +298,9 @@ namespace Nes
|
|||
if (cheats)
|
||||
cheats->Reset();
|
||||
|
||||
if (homebrew)
|
||||
homebrew->Reset();
|
||||
|
||||
tracker.Reset();
|
||||
}
|
||||
else
|
||||
|
@ -513,7 +520,7 @@ namespace Nes
|
|||
|
||||
cpu.ExecuteFrame( sound );
|
||||
ppu.EndFrame();
|
||||
|
||||
|
||||
renderer.bgColor = ppu.output.bgColor;
|
||||
|
||||
if (video)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// Nestopia - NES/Famicom emulator written in C++
|
||||
//
|
||||
// Copyright (C) 2003-2008 Martin Freij
|
||||
// Copyright (C) 2018-2018 Phil Smith
|
||||
//
|
||||
// This file is part of Nestopia.
|
||||
//
|
||||
|
@ -58,6 +59,7 @@ namespace Nes
|
|||
|
||||
class Image;
|
||||
class Cheats;
|
||||
class Homebrew;
|
||||
class ImageDatabase;
|
||||
|
||||
class Machine
|
||||
|
@ -128,6 +130,7 @@ namespace Nes
|
|||
Input::Device* expPort;
|
||||
Image* image;
|
||||
Cheats* cheats;
|
||||
Homebrew* homebrew;
|
||||
ImageDatabase* imageDatabase;
|
||||
Tracker tracker;
|
||||
Ppu ppu;
|
||||
|
|
225
source/core/api/NstApiHomebrew.cpp
Normal file
225
source/core/api/NstApiHomebrew.cpp
Normal file
|
@ -0,0 +1,225 @@
|
|||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Nestopia - NES/Famicom emulator written in C++
|
||||
//
|
||||
// Copyright (C) 2018-2018 Phil Smith
|
||||
//
|
||||
// This file is part of Nestopia.
|
||||
//
|
||||
// Nestopia is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Nestopia is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Nestopia; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <new>
|
||||
#include "../NstMachine.hpp"
|
||||
#include "../NstHomebrew.hpp"
|
||||
#include "NstApiHomebrew.hpp"
|
||||
#include "NstApiMachine.hpp"
|
||||
|
||||
namespace Nes
|
||||
{
|
||||
namespace Api
|
||||
{
|
||||
#ifdef NST_MSVC_OPTIMIZE
|
||||
#pragma optimize("s", on)
|
||||
#endif
|
||||
|
||||
Result Homebrew::SetExitPort(ushort address) throw()
|
||||
{
|
||||
if (emulator.tracker.IsLocked( true ))
|
||||
return RESULT_ERR_NOT_READY;
|
||||
|
||||
try
|
||||
{
|
||||
if (emulator.homebrew == NULL)
|
||||
emulator.homebrew = new Core::Homebrew( emulator.cpu );
|
||||
|
||||
return emulator.tracker.TryResync
|
||||
(
|
||||
emulator.homebrew->SetExitPort
|
||||
(
|
||||
address,
|
||||
emulator.Is(Machine::GAME)
|
||||
),
|
||||
true
|
||||
);
|
||||
}
|
||||
catch (const std::bad_alloc&)
|
||||
{
|
||||
return RESULT_ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return RESULT_ERR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
Result Homebrew::ClearExitPort() throw()
|
||||
{
|
||||
if (emulator.tracker.IsLocked( true ))
|
||||
return RESULT_ERR_NOT_READY;
|
||||
|
||||
if (!emulator.homebrew)
|
||||
return RESULT_ERR_INVALID_PARAM;
|
||||
|
||||
const Result result = emulator.tracker.TryResync
|
||||
(
|
||||
emulator.homebrew->ClearExitPort(),
|
||||
true
|
||||
);
|
||||
|
||||
if (!emulator.homebrew->NumPorts())
|
||||
{
|
||||
delete emulator.homebrew;
|
||||
emulator.homebrew = NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result Homebrew::SetStdOutPort(ushort address) throw()
|
||||
{
|
||||
if (emulator.tracker.IsLocked( true ))
|
||||
return RESULT_ERR_NOT_READY;
|
||||
|
||||
try
|
||||
{
|
||||
if (emulator.homebrew == NULL)
|
||||
emulator.homebrew = new Core::Homebrew( emulator.cpu );
|
||||
|
||||
return emulator.tracker.TryResync
|
||||
(
|
||||
emulator.homebrew->SetStdOutPort
|
||||
(
|
||||
address,
|
||||
emulator.Is(Machine::GAME)
|
||||
),
|
||||
true
|
||||
);
|
||||
}
|
||||
catch (const std::bad_alloc&)
|
||||
{
|
||||
return RESULT_ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return RESULT_ERR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
Result Homebrew::ClearStdOutPort() throw()
|
||||
{
|
||||
if (emulator.tracker.IsLocked( true ))
|
||||
return RESULT_ERR_NOT_READY;
|
||||
|
||||
if (!emulator.homebrew)
|
||||
return RESULT_ERR_INVALID_PARAM;
|
||||
|
||||
const Result result = emulator.tracker.TryResync
|
||||
(
|
||||
emulator.homebrew->ClearStdOutPort(),
|
||||
true
|
||||
);
|
||||
|
||||
if (!emulator.homebrew->NumPorts())
|
||||
{
|
||||
delete emulator.homebrew;
|
||||
emulator.homebrew = NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result Homebrew::SetStdErrPort(ushort address) throw()
|
||||
{
|
||||
if (emulator.tracker.IsLocked( true ))
|
||||
return RESULT_ERR_NOT_READY;
|
||||
|
||||
try
|
||||
{
|
||||
if (emulator.homebrew == NULL)
|
||||
emulator.homebrew = new Core::Homebrew( emulator.cpu );
|
||||
|
||||
return emulator.tracker.TryResync
|
||||
(
|
||||
emulator.homebrew->SetStdErrPort
|
||||
(
|
||||
address,
|
||||
emulator.Is(Machine::GAME)
|
||||
),
|
||||
true
|
||||
);
|
||||
}
|
||||
catch (const std::bad_alloc&)
|
||||
{
|
||||
return RESULT_ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return RESULT_ERR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
Result Homebrew::ClearStdErrPort() throw()
|
||||
{
|
||||
if (emulator.tracker.IsLocked( true ))
|
||||
return RESULT_ERR_NOT_READY;
|
||||
|
||||
if (!emulator.homebrew)
|
||||
return RESULT_ERR_INVALID_PARAM;
|
||||
|
||||
const Result result = emulator.tracker.TryResync
|
||||
(
|
||||
emulator.homebrew->ClearStdErrPort(),
|
||||
true
|
||||
);
|
||||
|
||||
if (!emulator.homebrew->NumPorts())
|
||||
{
|
||||
delete emulator.homebrew;
|
||||
emulator.homebrew = NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ulong Homebrew::NumPorts() const throw()
|
||||
{
|
||||
return emulator.homebrew ? emulator.homebrew->NumPorts() : 0;
|
||||
}
|
||||
|
||||
Result Homebrew::ClearPorts() throw()
|
||||
{
|
||||
if (emulator.tracker.IsLocked( true ))
|
||||
return RESULT_ERR_NOT_READY;
|
||||
|
||||
if (!emulator.homebrew)
|
||||
return RESULT_NOP;
|
||||
|
||||
if (emulator.homebrew->NumPorts())
|
||||
emulator.tracker.Resync( true );
|
||||
|
||||
delete emulator.homebrew;
|
||||
emulator.homebrew = NULL;
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
#ifdef NST_MSVC_OPTIMIZE
|
||||
#pragma optimize("", on)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
131
source/core/api/NstApiHomebrew.hpp
Normal file
131
source/core/api/NstApiHomebrew.hpp
Normal file
|
@ -0,0 +1,131 @@
|
|||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Nestopia - NES/Famicom emulator written in C++
|
||||
//
|
||||
// Copyright (C) 2018-2018 Phil Smith
|
||||
//
|
||||
// This file is part of Nestopia.
|
||||
//
|
||||
// Nestopia is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Nestopia is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Nestopia; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef NST_API_HOMEBREW_H
|
||||
#define NST_API_HOMEBREW_H
|
||||
|
||||
#include "NstApi.hpp"
|
||||
|
||||
#ifdef NST_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if NST_ICC >= 810
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 444 )
|
||||
#elif NST_MSVC >= 1200
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4512 )
|
||||
#endif
|
||||
|
||||
namespace Nes
|
||||
{
|
||||
namespace Api
|
||||
{
|
||||
/**
|
||||
* Homebrew interface.
|
||||
*/
|
||||
class Homebrew : public Base
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Interface constructor.
|
||||
*
|
||||
* @param instance emulator instance
|
||||
*/
|
||||
template<typename T>
|
||||
Homebrew(T& instance)
|
||||
: Base(instance) {}
|
||||
|
||||
/**
|
||||
* Sets the exit port.
|
||||
*
|
||||
* @param address exit port address,
|
||||
* any previous exit port will be removed
|
||||
* @return result code
|
||||
*/
|
||||
Result SetExitPort(ushort address) throw();
|
||||
|
||||
/**
|
||||
* Removes the exit port.
|
||||
*
|
||||
* @return result code
|
||||
*/
|
||||
Result ClearExitPort() throw();
|
||||
|
||||
/**
|
||||
* Sets the standard out port.
|
||||
*
|
||||
* @param address standard out port address,
|
||||
* any previous standard out port will be removed
|
||||
* @return result code
|
||||
*/
|
||||
Result SetStdOutPort(ushort address) throw();
|
||||
|
||||
/**
|
||||
* Removes the standard out port.
|
||||
*
|
||||
* @return result code
|
||||
*/
|
||||
Result ClearStdOutPort() throw();
|
||||
|
||||
/**
|
||||
* Sets the standard error port.
|
||||
*
|
||||
* @param address standard error port address,
|
||||
* any previous standard error port will be removed
|
||||
* @return result code
|
||||
*/
|
||||
Result SetStdErrPort(ushort address) throw();
|
||||
|
||||
/**
|
||||
* Removes the standard error port.
|
||||
*
|
||||
* @return result code
|
||||
*/
|
||||
Result ClearStdErrPort() throw();
|
||||
|
||||
/**
|
||||
* Returns current number of ports.
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
ulong NumPorts() const throw();
|
||||
|
||||
/**
|
||||
* Removes all existing ports.
|
||||
*
|
||||
* @return result code
|
||||
*/
|
||||
Result ClearPorts() throw();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#if NST_MSVC >= 1200 || NST_ICC >= 810
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue