Added console window, bug fixes based on tests
This commit is contained in:
parent
608c9a03cf
commit
cc674a7467
5 changed files with 121 additions and 36 deletions
69
Core/CPU.h
69
Core/CPU.h
|
@ -107,7 +107,7 @@ private:
|
|||
return _memoryManager->ReadWord(addr);
|
||||
}
|
||||
|
||||
void SetRegister(uint8_t ®, int8_t value) {
|
||||
void SetRegister(uint8_t ®, 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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
13
Core/PPU.cpp
13
Core/PPU.cpp
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
|
Loading…
Add table
Reference in a new issue