2011-09-21 22:53:41 +00:00
|
|
|
/**
|
|
|
|
** Supermodel
|
|
|
|
** A Sega Model 3 Arcade Emulator.
|
|
|
|
** Copyright 2011 Bart Trzynadlowski, Nik Henson
|
|
|
|
**
|
|
|
|
** This file is part of Supermodel.
|
|
|
|
**
|
|
|
|
** Supermodel 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 3 of the License, or (at your option)
|
|
|
|
** any later version.
|
|
|
|
**
|
|
|
|
** Supermodel 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 Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
**/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* IO.cpp
|
|
|
|
*/
|
|
|
|
|
2011-06-27 22:55:03 +00:00
|
|
|
#ifdef SUPERMODEL_DEBUGGER
|
|
|
|
|
|
|
|
#include "CPUDebug.h"
|
|
|
|
#include "IO.h"
|
|
|
|
#include "Watch.h"
|
|
|
|
|
|
|
|
namespace Debugger
|
|
|
|
{
|
|
|
|
CIO::CIO(CCPUDebug *ioCPU, const char *ioName, const char *ioGroup, unsigned ioDataSize) :
|
|
|
|
cpu(ioCPU), name(ioName), group(ioGroup), dataSize(ioDataSize),
|
|
|
|
watch(NULL), inCount(0), outCount(0), lastIn(0), lastOut(0), last(&lastIn)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CIO::CheckInput(UINT64 data)
|
|
|
|
{
|
|
|
|
inCount++;
|
|
|
|
RecordInput(data);
|
|
|
|
|
|
|
|
// Check watch, if any
|
|
|
|
return watch != NULL && watch->CheckInput(this, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CIO::CheckOutput(UINT64 data)
|
|
|
|
{
|
|
|
|
outCount++;
|
|
|
|
RecordOutput(data);
|
|
|
|
|
|
|
|
// Check watch, if any
|
|
|
|
return watch != NULL && watch->CheckOutput(this, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
CSimpleWatch *CIO::AddSimpleWatch(bool trigInput, bool trigOutput)
|
|
|
|
{
|
|
|
|
CSimpleWatch *sWatch = new CSimpleWatch(cpu, this, trigInput, trigOutput);
|
|
|
|
cpu->AddWatch(sWatch);
|
|
|
|
return sWatch;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCountWatch *CIO::AddCountWatch(bool trigInput, bool trigOutput, unsigned count)
|
|
|
|
{
|
|
|
|
CCountWatch *cWatch = new CCountWatch(cpu, this, trigInput, trigOutput, count);
|
|
|
|
cpu->AddWatch(cWatch);
|
|
|
|
return cWatch;
|
|
|
|
}
|
|
|
|
|
|
|
|
CMatchWatch *CIO::AddMatchWatch(bool trigInput, bool trigOutput, vector<UINT64> &dataSeq)
|
|
|
|
{
|
|
|
|
CMatchWatch *mWatch = new CMatchWatch(cpu, this, trigInput, trigOutput, dataSeq);
|
|
|
|
cpu->AddWatch(mWatch);
|
|
|
|
return mWatch;
|
|
|
|
}
|
|
|
|
|
|
|
|
CPrintWatch *CIO::AddPrintWatch(bool trigInput, bool trigOutput)
|
|
|
|
{
|
|
|
|
CPrintWatch *pWatch = new CPrintWatch(cpu, this, trigInput, trigOutput);
|
|
|
|
cpu->AddWatch(pWatch);
|
|
|
|
return pWatch;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCaptureWatch *CIO::AddCaptureWatch(bool trigInput, bool trigOutput, unsigned maxLen)
|
|
|
|
{
|
|
|
|
CCaptureWatch *cWatch = new CCaptureWatch(cpu, this, trigInput, trigOutput, maxLen);
|
|
|
|
cpu->AddWatch(cWatch);
|
|
|
|
return cWatch;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CIO::RemoveWatch()
|
|
|
|
{
|
|
|
|
return watch != NULL && cpu->RemoveWatch(watch);
|
|
|
|
}
|
|
|
|
|
|
|
|
CPortIO::CPortIO(CCPUDebug *ioCPU, const char *ioName, const char *ioGroup, unsigned ioDataSize, UINT16 ioPortNum) :
|
|
|
|
CIO(ioCPU, ioName, ioGroup, ioDataSize), portNum(ioPortNum), label(NULL)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPortIO::AddLabel(const char *pLabel)
|
|
|
|
{
|
|
|
|
strncpy(labelStr, pLabel, MAX_LABEL_LENGTH);
|
|
|
|
labelStr[MAX_LABEL_LENGTH] = '\0';
|
|
|
|
label = labelStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPortIO::RemoveLabel()
|
|
|
|
{
|
|
|
|
label = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPortIO::GetLocation(char *str)
|
|
|
|
{
|
|
|
|
if (name != NULL)
|
2011-09-18 21:59:23 +00:00
|
|
|
strcpy(str, name);
|
2011-06-27 22:55:03 +00:00
|
|
|
else
|
|
|
|
sprintf(str, "port %u", portNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT64 CPortIO::Read()
|
|
|
|
{
|
|
|
|
UINT64 data = cpu->ReadPort(portNum);
|
|
|
|
RecordInput(data);
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CPortIO::Write(UINT64 data)
|
|
|
|
{
|
|
|
|
if (!cpu->WritePort(portNum, data))
|
|
|
|
return false;
|
|
|
|
RecordOutput(data);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
CMappedIO::CMappedIO(CCPUDebug *ioCPU, const char *ioName, const char *ioGroup, unsigned ioDataSize, UINT32 ioAddr) :
|
|
|
|
CIO(ioCPU, ioName, ioGroup, ioDataSize), CAddressRef(ioCPU, ioAddr, ioDataSize)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CMappedIO::CheckInput(UINT32 cAddr, unsigned cDataSize, UINT64 data)
|
|
|
|
{
|
|
|
|
// Take care with input that was not aligned with mapped I/O address and size
|
|
|
|
UINT64 sData = CDebugger::GetSlottedData(cAddr, cDataSize, data, addr, dataSize);
|
|
|
|
return CIO::CheckInput(sData);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CMappedIO::CheckOutput(UINT32 cAddr, unsigned cDataSize, UINT64 data)
|
|
|
|
{
|
|
|
|
// Take care with output that was not aligned with mapped I/O address and size
|
|
|
|
UINT64 sData = CDebugger::GetSlottedData(cAddr, cDataSize, data, addr, dataSize);
|
|
|
|
return CIO::CheckOutput(sData);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMappedIO::AddLabel(const char *label)
|
|
|
|
{
|
|
|
|
CIO::cpu->AddLabel(addr, label);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMappedIO::RemoveLabel()
|
|
|
|
{
|
|
|
|
CIO::cpu->RemoveLabel(addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMappedIO::GetLocation(char *str)
|
|
|
|
{
|
|
|
|
CIO::cpu->FormatAddress(str, addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT64 CMappedIO::Read()
|
|
|
|
{
|
|
|
|
UINT64 data = CIO::cpu->ReadMem(addr, dataSize);
|
|
|
|
RecordInput(data);
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CMappedIO::Write(UINT64 data)
|
|
|
|
{
|
|
|
|
if (!CIO::cpu->WriteMem(addr, dataSize, data))
|
|
|
|
return false;
|
|
|
|
RecordOutput(data);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // SUPERMODEL_DEBUGGER
|