Input
This commit is contained in:
parent
b1265da7d3
commit
f6e339105a
|
@ -14,6 +14,7 @@ target_sources(
|
||||||
Source/CPU/CPU.cpp
|
Source/CPU/CPU.cpp
|
||||||
Source/CPU/AddressModes.cpp
|
Source/CPU/AddressModes.cpp
|
||||||
Source/CPU/Instructions.cpp
|
Source/CPU/Instructions.cpp
|
||||||
|
Source/Input.cpp
|
||||||
Source/NES.cpp
|
Source/NES.cpp
|
||||||
Source/Platform.cpp
|
Source/Platform.cpp
|
||||||
Source/PPU/PPU.cpp
|
Source/PPU/PPU.cpp
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include "Input.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
void Input::Strobe(uint8_t* but)
|
||||||
|
{
|
||||||
|
if (strobe)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
buttons[i] = but[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Input::Poll()
|
||||||
|
{
|
||||||
|
uint8_t buttonState;
|
||||||
|
|
||||||
|
// Strobe set - return state of A button
|
||||||
|
if (strobe)
|
||||||
|
{
|
||||||
|
buttonState = buttons[Buttons::A];
|
||||||
|
}
|
||||||
|
|
||||||
|
// All 8 bits read - return 1u
|
||||||
|
else if (buttonIndex > Buttons::Right)
|
||||||
|
{
|
||||||
|
buttonState = 1u;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return next bit
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buttonState = buttons[buttonIndex];
|
||||||
|
|
||||||
|
++buttonIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buttonState;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
|
||||||
|
enum Buttons
|
||||||
|
{
|
||||||
|
A = 0,
|
||||||
|
B = 1,
|
||||||
|
Select = 2,
|
||||||
|
Start = 3,
|
||||||
|
Up = 4,
|
||||||
|
Down = 5,
|
||||||
|
Left = 6,
|
||||||
|
Right = 7
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Input
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Strobe(uint8_t* but);
|
||||||
|
uint8_t Poll();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class NES;
|
||||||
|
|
||||||
|
bool strobe{};
|
||||||
|
uint8_t buttonIndex{};
|
||||||
|
uint8_t buttons[8]{};
|
||||||
|
};
|
|
@ -44,7 +44,8 @@ NES::NES()
|
||||||
: cpu(std::make_unique<CPU>()),
|
: cpu(std::make_unique<CPU>()),
|
||||||
ppu(std::make_unique<PPU>()),
|
ppu(std::make_unique<PPU>()),
|
||||||
cartridge(std::make_unique<Cartridge>()),
|
cartridge(std::make_unique<Cartridge>()),
|
||||||
platform(std::make_unique<Platform>("NES", WINDOW_WIDTH, WINDOW_HEIGHT, VIDEO_WIDTH, VIDEO_HEIGHT))
|
platform(std::make_unique<Platform>("NES", WINDOW_WIDTH, WINDOW_HEIGHT, VIDEO_WIDTH, VIDEO_HEIGHT)),
|
||||||
|
input(std::make_unique<Input>())
|
||||||
{
|
{
|
||||||
ppu->nes = this;
|
ppu->nes = this;
|
||||||
|
|
||||||
|
@ -123,10 +124,14 @@ void NES::InsertCartridge(char const* filename)
|
||||||
|
|
||||||
void NES::Run()
|
void NES::Run()
|
||||||
{
|
{
|
||||||
while (!platform->ProcessInput())
|
uint8_t buttons[8]{};
|
||||||
|
|
||||||
|
while (!platform->ProcessInput(buttons))
|
||||||
{
|
{
|
||||||
cpu->Cycle();
|
cpu->Cycle();
|
||||||
|
|
||||||
|
input->Strobe(buttons);
|
||||||
|
|
||||||
uint8_t cpuCyclesTaken = (cpu->cycles - cpu->prevCycles) * 3u;
|
uint8_t cpuCyclesTaken = (cpu->cycles - cpu->prevCycles) * 3u;
|
||||||
|
|
||||||
ppu->Cycle(cpuCyclesTaken);
|
ppu->Cycle(cpuCyclesTaken);
|
||||||
|
@ -166,6 +171,7 @@ void NES::Write(BusSource source, uint16_t address, uint8_t value)
|
||||||
{
|
{
|
||||||
uint16_t index = address & 0x1Fu;
|
uint16_t index = address & 0x1Fu;
|
||||||
|
|
||||||
|
// PPU OAM
|
||||||
if (index == 0x14u)
|
if (index == 0x14u)
|
||||||
{
|
{
|
||||||
uint8_t addrMsb = value;
|
uint8_t addrMsb = value;
|
||||||
|
@ -177,6 +183,20 @@ void NES::Write(BusSource source, uint16_t address, uint8_t value)
|
||||||
ppu->oam[ppu->oamAddr + addrLsb] = Read(BusSource::CPU, addr);
|
ppu->oam[ppu->oamAddr + addrLsb] = Read(BusSource::CPU, addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Controller
|
||||||
|
else if (index == 0x16u)
|
||||||
|
{
|
||||||
|
if (value & 0x1u)
|
||||||
|
{
|
||||||
|
input->strobe = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
input->strobe = false;
|
||||||
|
input->buttonIndex = 0u;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expansion I/O
|
// Expansion I/O
|
||||||
|
@ -253,6 +273,13 @@ uint8_t NES::Read(BusSource source, uint16_t address)
|
||||||
// APU and IO
|
// APU and IO
|
||||||
else if (address < 0x4020u)
|
else if (address < 0x4020u)
|
||||||
{
|
{
|
||||||
|
uint16_t index = address & 0x1Fu;
|
||||||
|
|
||||||
|
// Controller
|
||||||
|
if (index == 0x16u)
|
||||||
|
{
|
||||||
|
byte = input->Poll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expansion I/O
|
// Expansion I/O
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "Cartridge.hpp"
|
#include "Cartridge.hpp"
|
||||||
#include "CPU/CPU.hpp"
|
#include "CPU/CPU.hpp"
|
||||||
|
#include "Input.hpp"
|
||||||
#include "Platform.hpp"
|
#include "Platform.hpp"
|
||||||
#include "PPU/PPU.hpp"
|
#include "PPU/PPU.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -45,6 +46,7 @@ public:
|
||||||
std::unique_ptr<PPU> ppu;
|
std::unique_ptr<PPU> ppu;
|
||||||
std::unique_ptr<Cartridge> cartridge;
|
std::unique_ptr<Cartridge> cartridge;
|
||||||
std::unique_ptr<Platform> platform;
|
std::unique_ptr<Platform> platform;
|
||||||
|
std::unique_ptr<Input> input;
|
||||||
|
|
||||||
bool nmi{};
|
bool nmi{};
|
||||||
Color palette[64];
|
Color palette[64];
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "Platform.hpp"
|
#include "Platform.hpp"
|
||||||
|
#include "Input.hpp"
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ void Platform::Update(void const* buffer, int pitch)
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Platform::ProcessInput()
|
bool Platform::ProcessInput(uint8_t* buttons)
|
||||||
{
|
{
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
|
|
||||||
|
@ -55,6 +56,95 @@ bool Platform::ProcessInput()
|
||||||
quit = true;
|
quit = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SDLK_UP:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::Up] = 1u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_DOWN:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::Down] = 1u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_LEFT:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::Left] = 1u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::Right] = 1u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_LSHIFT:
|
||||||
|
{
|
||||||
|
buttons[Buttons::Select] = 1u;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_RETURN:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::Start] = 1u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_z:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::A] = 1u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_x:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::B] = 1u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_KEYUP:
|
||||||
|
{
|
||||||
|
switch (event.key.keysym.sym)
|
||||||
|
{
|
||||||
|
case SDLK_UP:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::Up] = 0u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_DOWN:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::Down] = 0u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_LEFT:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::Left] = 0u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::Right] = 0u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_LSHIFT:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::Select] = 0u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_RETURN:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::Start] = 0u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_z:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::A] = 0u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDLK_x:
|
||||||
|
{
|
||||||
|
{buttons[Buttons::B] = 0u;}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -62,5 +152,6 @@ bool Platform::ProcessInput()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return quit;
|
return quit;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include "Input.hpp"
|
||||||
|
|
||||||
|
|
||||||
class SDL_Window;
|
class SDL_Window;
|
||||||
|
@ -14,7 +15,7 @@ public:
|
||||||
Platform(char const* title, int windowWidth, int windowHeight, int textureWidth, int textureHeight);
|
Platform(char const* title, int windowWidth, int windowHeight, int textureWidth, int textureHeight);
|
||||||
~Platform();
|
~Platform();
|
||||||
void Update(void const* buffer, int pitch);
|
void Update(void const* buffer, int pitch);
|
||||||
bool ProcessInput();
|
bool ProcessInput(uint8_t* buttons);
|
||||||
|
|
||||||
SDL_Window* window{};
|
SDL_Window* window{};
|
||||||
SDL_Renderer* renderer{};
|
SDL_Renderer* renderer{};
|
||||||
|
|
Loading…
Reference in New Issue