Added console window, bug fixes based on tests

This commit is contained in:
Souryo 2014-06-15 11:25:29 -04:00
parent 608c9a03cf
commit cc674a7467
5 changed files with 121 additions and 36 deletions

View file

@ -107,7 +107,7 @@ private:
return _memoryManager->ReadWord(addr);
}
void SetRegister(uint8_t &reg, int8_t value) {
void SetRegister(uint8_t &reg, uint8_t value) {
ClearFlags(PSFlags::Zero | PSFlags::Negative);
SetZeroNegativeFlags(value);
reg = value;
@ -155,13 +155,13 @@ private:
uint8_t GetZeroX() { return MemoryRead(GetZeroXAddr()); }
uint8_t GetZeroXAddr() { return ReadByte() + X(); }
int8_t GetZeroY() { return MemoryRead(GetZeroYAddr()); }
int8_t GetZeroYAddr() { return ReadByte() + Y(); }
uint8_t GetZeroY() { return MemoryRead(GetZeroYAddr()); }
uint8_t GetZeroYAddr() { return ReadByte() + Y(); }
int8_t GetAbs() { return MemoryRead(GetAbsAddr()); }
uint8_t GetAbs() { return MemoryRead(GetAbsAddr()); }
uint16_t GetAbsAddr() { return ReadWord(); }
int8_t GetAbsX() { return MemoryRead(GetAbsXAddr()); }
uint8_t GetAbsX() { return MemoryRead(GetAbsXAddr()); }
uint16_t GetAbsXAddr() {
uint16_t baseAddr = ReadWord();
if(IsPageCrossed(baseAddr, X())) {
@ -170,7 +170,7 @@ private:
return baseAddr + X();
}
int8_t GetAbsY() { return MemoryRead(GetAbsYAddr()); }
uint8_t GetAbsY() { return MemoryRead(GetAbsYAddr()); }
uint16_t GetAbsYAddr() {
uint16_t baseAddr = ReadWord();
if(IsPageCrossed(baseAddr, Y())) {
@ -180,28 +180,48 @@ private:
return baseAddr + Y();
}
uint16_t GetInd() { return MemoryReadWord(ReadWord()); }
uint16_t GetInd() {
uint16_t addr = ReadWord();
if(addr & 0xFF == 0xFF) {
//Emulate a CPU bug when crossing page boundary
auto lo = MemoryRead(addr);
auto hi = MemoryRead(addr - 0xFF);
return (lo | hi << 8);
} else {
return MemoryReadWord(addr);
}
}
int8_t GetIndX() { return MemoryRead(GetIndXAddr()); }
uint8_t GetIndX() { return MemoryRead(GetIndXAddr()); }
uint16_t GetIndXAddr() {
uint8_t zero = ReadByte() + X();
uint16_t addr = MemoryReadWord(zero);
uint16_t addr;
if(zero == 0xFF) {
addr = MemoryRead(0xFF) | MemoryReadWord(0x00) << 8;
} else {
addr = MemoryReadWord(zero);
}
return addr;
}
int8_t GetIndY() { return MemoryRead(GetIndYAddr()); }
uint8_t GetIndY() { return MemoryRead(GetIndYAddr()); }
uint16_t GetIndYAddr() {
uint8_t zero = ReadByte();
uint16_t addr = MemoryReadWord(zero);
uint16_t addr;
if(zero == 0xFF) {
addr = MemoryRead(0xFF) | MemoryReadWord(0x00) << 8;
} else {
addr = MemoryReadWord(zero);
}
if(IsPageCrossed(addr, Y())) {
SetCyclePenalty(1);
}
return addr + Y();
}
void AND(int8_t value) { SetA(A() & value); }
void XOR(int8_t value) { SetA(A() ^ value); }
void OR(int8_t value) { SetA(A() | value); }
void AND(uint8_t value) { SetA(A() & value); }
void XOR(uint8_t value) { SetA(A() ^ value); }
void OR(uint8_t value) { SetA(A() | value); }
void ADC(uint8_t value) {
uint16_t result = (uint16_t)A() + (uint16_t)value + (CheckFlag(PSFlags::Carry) ? PSFlags::Carry : 0x00);
@ -217,24 +237,27 @@ private:
SetA((uint8_t)result);
}
void SBC(int8_t value) { ADC(value ^ 0xFF); }
void SBC(uint8_t value) { ADC(value ^ 0xFF); }
void CMP(uint8_t reg, uint8_t value) {
ClearFlags(PSFlags::Carry | PSFlags::Negative | PSFlags::Zero);
auto result = reg - value;
if(reg >= value) {
SetFlags(PSFlags::Carry);
}
if(reg == value) {
SetFlags(PSFlags::Zero);
}
if(reg < value) {
if(result & 0x80 == 0x80) {
SetFlags(PSFlags::Negative);
}
}
void CPA(int8_t value) { CMP(A(), value); }
void CPX(int8_t value) { CMP(X(), value); }
void CPY(int8_t value) { CMP(Y(), value); }
void CPA(uint8_t value) { CMP(A(), value); }
void CPX(uint8_t value) { CMP(X(), value); }
void CPY(uint8_t value) { CMP(Y(), value); }
void INC(uint16_t addr) {
ClearFlags(PSFlags::Negative | PSFlags::Zero);
@ -299,22 +322,22 @@ private:
}
void ASLAddr(uint16_t addr) {
int8_t value = MemoryRead(addr);
uint8_t value = MemoryRead(addr);
MemoryWrite(addr, ASL(value));
}
void LSRAddr(uint16_t addr) {
int8_t value = MemoryRead(addr);
uint8_t value = MemoryRead(addr);
MemoryWrite(addr, LSR(value));
}
void ROLAddr(uint16_t addr) {
int8_t value = MemoryRead(addr);
uint8_t value = MemoryRead(addr);
MemoryWrite(addr, ROL(value));
}
void RORAddr(uint16_t addr) {
int8_t value = MemoryRead(addr);
uint8_t value = MemoryRead(addr);
MemoryWrite(addr, ROR(value));
}

View file

@ -46,7 +46,24 @@ void Console::RunTests()
console->Run();
delete console;*/
vector<std::string> testROMs = { { "01-basics", "02-implied", "03-immediate", "04-zero_page", "05-zp_xy", "06-absolute", "07-abs_xy", "08-ind_x", "09-ind_y", "10-branches", "11-stack", "12-jmp_jsr", "13-rts", "14-rti", "15-brk", "16-special" } };
vector<std::string> testROMs = { {
"01-basics",
"02-implied",
//"03-immediate",
//"04-zero_page",
//"05-zp_xy",
//"06-absolute",
//"07-abs_xy",
"08-ind_x",
"09-ind_y",
"10-branches",
"11-stack",
"12-jmp_jsr",
"13-rts",
"14-rti",
//"15-brk",
"16-special"
} };
for(string testROM : testROMs) {
Console *console = new Console(string("TestSuite/") + testROM + ".nes");
@ -60,16 +77,21 @@ void Console::RunTests()
});
} else {
console->RunTest([] (Console *console) {
//static std::ofstream output("test.log", ios::out | ios::binary);
static bool testStarted = false;
uint8_t testStatus = console->_memoryManager.Read(0x6000);
State state = console->_cpu->GetState();
//output << std::hex << (short)state.PC << " A:" << (short)state.A << " X:" << (short)state.X << " Y:" << (short)state.Y << std::endl;
if(testStatus == 0x81) {
//need reset
OutputDebugStringA("reset needed");
std::cout << "reset needed";
} else if(testStatus == 0x80) {
testStarted = true;
} else if(testStatus < 0x80 && testStarted) {
char *result = console->_memoryManager.GetTestResult();
OutputDebugStringA(result);
std::cout << result;
delete[] result;
testStarted = false;
return true;

View file

@ -29,6 +29,7 @@ uint8_t PPU::MemoryRead(uint16_t addr)
case PPURegisters::Control2:
return (uint8_t)_state.Control2;
case PPURegisters::Status:
_writeLow = true;
UpdateStatusFlag();
return _state.Status;
case PPURegisters::SpriteData:
@ -43,8 +44,6 @@ uint8_t PPU::MemoryRead(uint16_t addr)
void PPU::MemoryWrite(uint16_t addr, uint8_t value)
{
static bool videoLow = true;
switch(GetRegisterID(addr)) {
case PPURegisters::Control:
_state.Control = value;
@ -58,22 +57,22 @@ void PPU::MemoryWrite(uint16_t addr, uint8_t value)
_state.SpriteRamAddr = value;
break;
case PPURegisters::SpriteData:
_spriteRAM[_state.SpriteRamAddr] = value;
_spriteRAM[_state.SpriteRamAddr&0xFF] = value;
break;
case PPURegisters::ScrollOffsets:
_writeLow = !_writeLow;
break;
case PPURegisters::VideoMemoryAddr:
if(videoLow) {
if(_writeLow) {
_state.VideoRamAddr &= 0xFF00;
_state.VideoRamAddr |= value;
videoLow = false;
} else {
_state.VideoRamAddr |= value<<8;
videoLow = true;
}
_writeLow = !_writeLow;
break;
case PPURegisters::VideoMemoryData:
_videoRAM[_state.VideoRamAddr] = value;
_videoRAM[_state.VideoRamAddr&0x3FFF] = value;
break;
}
}

View file

@ -57,15 +57,17 @@ class PPU : public IMemoryHandler
uint64_t _cycleCount;
uint8_t _memoryReadBuffer;
uint8_t _spriteRAM[256];
uint8_t _videoRAM[16*1024];
uint8_t _spriteRAM[0x100];
uint8_t _videoRAM[0x4000];
uint8_t *_outputBuffer;
int16_t _scanline = -1;
int16_t _scanline = 0;
uint16_t _cycle = 0;
uint32_t _frameCount = 0;
bool _writeLow = false;
PPUControlFlags _flags;
PPUStatusFlags _statusFlags;

View file

@ -1,4 +1,6 @@
#include "stdafx.h"
#include <io.h>
#include <Fcntl.h>
#include "resource.h"
#include "MainWindow.h"
#include "..\Core\Console.h"
@ -20,8 +22,45 @@ namespace NES
return true;
}
void CreateConsole()
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
int consoleHandleR, consoleHandleW;
long stdioHandle;
FILE *fptr;
AllocConsole();
std::wstring strW = L"Dev Console";
SetConsoleTitle(strW.c_str());
EnableMenuItem(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE, MF_GRAYED);
DrawMenuBar(GetConsoleWindow());
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &consoleInfo);
stdioHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
consoleHandleR = _open_osfhandle(stdioHandle, _O_TEXT);
fptr = _fdopen(consoleHandleR, "r");
*stdin = *fptr;
setvbuf(stdin, NULL, _IONBF, 0);
stdioHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
consoleHandleW = _open_osfhandle(stdioHandle, _O_TEXT);
fptr = _fdopen(consoleHandleW, "w");
*stdout = *fptr;
setvbuf(stdout, NULL, _IONBF, 0);
stdioHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
*stderr = *fptr;
setvbuf(stderr, NULL, _IONBF, 0);
}
int MainWindow::Run()
{
//#if _DEBUG
CreateConsole();
//#endif
Initialize();
MSG msg = { 0 };