Mesen-X/Core/BizhawkMovie.cpp

192 lines
4.8 KiB
C++
Raw Normal View History

#include "stdafx.h"
#include "BizhawkMovie.h"
#include "VsControlManager.h"
#include "FDS.h"
2017-04-29 08:29:56 -04:00
#include "PPU.h"
BizhawkMovie::BizhawkMovie()
{
_originalPowerOnState = EmulationSettings::GetRamPowerOnState();
MessageManager::RegisterNotificationListener(this);
}
BizhawkMovie::~BizhawkMovie()
{
MessageManager::UnregisterNotificationListener(this);
EmulationSettings::SetRamPowerOnState(_originalPowerOnState);
}
void BizhawkMovie::ProcessNotification(ConsoleNotificationType type, void* parameter)
{
if(type == ConsoleNotificationType::PpuFrameDone) {
int32_t frameNumber = PPU::GetFrameCount();
2017-05-06 18:35:59 -04:00
if(frameNumber < (int32_t)_systemActionByFrame.size()) {
uint32_t systemAction = _systemActionByFrame[frameNumber];
if(systemAction & 0x01) {
//Power, not implemented yet
}
if(systemAction & 0x02) {
//Reset, not implemented yet
}
if(FDS::GetSideCount()) {
//FDS timings between NesHawk & Mesen are currently significantly different
//So FDS games will always go out of sync
if(systemAction & 0x04) {
FDS::EjectDisk();
} else if(systemAction >= 8) {
systemAction >>= 3;
uint32_t diskNumber = 0;
while(!(systemAction & 0x01)) {
systemAction >>= 1;
diskNumber++;
}
FDS::InsertDisk(diskNumber);
}
} else if(VsControlManager::GetInstance()) {
if(VsControlManager::GetInstance()) {
if(systemAction & 0x04) {
VsControlManager::GetInstance()->InsertCoin(0);
}
if(systemAction & 0x08) {
VsControlManager::GetInstance()->InsertCoin(1);
}
VsControlManager::GetInstance()->SetServiceButtonState(systemAction & 0x10 ? true : false);
}
}
}
}
}
uint8_t BizhawkMovie::GetState(uint8_t port)
{
int32_t frameNumber = PPU::GetFrameCount() - (PPU::GetCurrentScanline() >= 240 ? 0 : 1);
2017-05-06 18:35:59 -04:00
if(frameNumber < (int32_t)_dataByFrame[0].size()) {
return _dataByFrame[port][frameNumber];
} else {
EndMovie();
EmulationSettings::SetRamPowerOnState(_originalPowerOnState);
_isPlaying = false;
return 0;
}
}
bool BizhawkMovie::InitializeGameData(ZipReader & reader)
{
std::stringstream ss = reader.GetStream("Header.txt");
bool result = false;
while(!ss.eof()) {
string line;
std::getline(ss, line);
if(line.compare(0, 4, "SHA1", 4) == 0) {
if(line.size() >= 45) {
HashInfo hashInfo;
hashInfo.Sha1Hash = line.substr(5, 40);
if(Console::LoadROM("", hashInfo)) {
result = true;
}
}
} else if(line.compare(0, 3, "MD5", 3) == 0) {
if(line.size() >= 36) {
HashInfo hashInfo;
hashInfo.PrgChrMd5Hash = line.substr(4, 32);
std::transform(hashInfo.PrgChrMd5Hash.begin(), hashInfo.PrgChrMd5Hash.end(), hashInfo.PrgChrMd5Hash.begin(), ::toupper);
if(Console::LoadROM("", hashInfo)) {
result = true;
}
}
}
}
return result;
}
bool BizhawkMovie::InitializeInputData(ZipReader & reader)
{
const uint8_t orValues[8] = { 0x10, 0x20, 0x40, 0x80, 0x08, 0x04, 0x02, 0x01 };
std::stringstream ss = reader.GetStream("Input Log.txt");
int systemActionCount = 2;
if(FDS::GetSideCount() > 0) {
//Eject disk + Insert Disk #XX
systemActionCount += FDS::GetSideCount() + 1;
} else if(VsControlManager::GetInstance()) {
//Insert coin 1, 2 + service button
systemActionCount += 3;
}
while(!ss.eof()) {
string line;
std::getline(ss, line);
if(line.size() > 0 && line[0] == '|') {
line.erase(std::remove(line.begin(), line.end(), '|'), line.end());
line = line.substr(0, line.size() - 1);
//Read power/reset/FDS/VS/etc. commands
uint32_t systemAction = 0;
for(int i = 0; i < systemActionCount; i++) {
if(line[i] != '.') {
systemAction |= (1 << i);
}
}
_systemActionByFrame.push_back(systemAction);
//Only supports regular controllers (up to 4 of them)
for(int i = 0; i < 8*4; i++) {
uint8_t port = i / 8;
if(port <= 3) {
uint8_t portValue = 0;
2017-05-06 18:35:59 -04:00
for(int j = 0; j < 8 && i + j + systemActionCount < (int)line.size(); j++) {
if(line[i+j+systemActionCount] != '.') {
portValue |= orValues[j];
}
}
i += 7;
_dataByFrame[port].push_back(portValue);
}
}
}
}
return _dataByFrame[0].size() > 0;
}
bool BizhawkMovie::Play(stringstream & filestream, bool autoLoadRom)
{
Console::Pause();
ZipReader reader;
reader.LoadArchive(filestream);
if(InitializeGameData(reader)) {
if(InitializeInputData(reader)) {
//NesHawk initializes memory to 1s
EmulationSettings::SetRamPowerOnState(RamPowerOnState::AllOnes);
Console::Reset(false);
_isPlaying = true;
}
}
Console::Resume();
return _isPlaying;
}
bool BizhawkMovie::IsRecording()
{
return false;
}
bool BizhawkMovie::IsPlaying()
{
return _isPlaying;
}
void BizhawkMovie::RecordState(uint8_t port, uint8_t value)
{
//Not implemented
}
void BizhawkMovie::Record(string filename, bool reset)
{
//Not implemented
}