diff --git a/Core/CPU.h b/Core/CPU.h index c2074d7a..3394b37f 100644 --- a/Core/CPU.h +++ b/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)); } diff --git a/Core/Console.cpp b/Core/Console.cpp index 6856ec75..8f56bbf1 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -46,7 +46,24 @@ void Console::RunTests() console->Run(); delete console;*/ - vector 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 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; diff --git a/Core/PPU.cpp b/Core/PPU.cpp index 309a1d34..407a96bb 100644 --- a/Core/PPU.cpp +++ b/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; } } diff --git a/Core/PPU.h b/Core/PPU.h index f993a74f..eba052f3 100644 --- a/Core/PPU.h +++ b/Core/PPU.h @@ -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; diff --git a/GUI/MainWindow.cpp b/GUI/MainWindow.cpp index d8341b86..8d3967bd 100644 --- a/GUI/MainWindow.cpp +++ b/GUI/MainWindow.cpp @@ -1,4 +1,6 @@ #include "stdafx.h" +#include +#include #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 };