|
|
|
#include "pixelGameEngine.h"
|
|
|
|
#include "Polygon.h"
|
|
|
|
#include <stack>
|
|
|
|
#include <bitset>
|
|
|
|
|
|
|
|
using namespace olc;
|
|
|
|
|
|
|
|
#define WIDTH 640
|
|
|
|
#define HEIGHT 480
|
|
|
|
|
|
|
|
class Chip8Emulator : public olc::PixelGameEngine
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Chip8Emulator()
|
|
|
|
{
|
|
|
|
sAppName = "CHIP-8!";
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
std::array<uint8_t,4096>memory={
|
|
|
|
0,0,0,0,0,0,0,0,0,0,
|
|
|
|
0,0,0,0,0,0,0,0,0,0,
|
|
|
|
0,0,0,0,0,0,0,0,0,0,
|
|
|
|
0,0,0,0,0,0,0,0,0,0,
|
|
|
|
0,0,0,0,0,0,0,0,0,0,
|
|
|
|
0,0,0,0,0,0,0,0,0,0,
|
|
|
|
0,0,0,0,0,0,0,0,0,0,
|
|
|
|
0,0,0,0,0,0,0,0,0,0,
|
|
|
|
0,0,0,0,0,0,0,0,0,0,
|
|
|
|
//Font starts at 0x50
|
|
|
|
0xF0,0x90,0x90,0x90,0xF0, // 0
|
|
|
|
0x20,0x60,0x20,0x20,0x70, // 1
|
|
|
|
0xF0,0x10,0xF0,0x80,0xF0, // 2
|
|
|
|
0xF0,0x10,0xF0,0x10,0xF0, // 3
|
|
|
|
0x90,0x90,0xF0,0x10,0x10, // 4
|
|
|
|
0xF0,0x80,0xF0,0x10,0xF0, // 5
|
|
|
|
0xF0,0x80,0xF0,0x90,0xF0, // 6
|
|
|
|
0xF0,0x10,0x20,0x40,0x40, // 7
|
|
|
|
0xF0,0x90,0xF0,0x90,0xF0, // 8
|
|
|
|
0xF0,0x90,0xF0,0x10,0xF0, // 9
|
|
|
|
0xF0,0x90,0xF0,0x90,0x90, // A
|
|
|
|
0xE0,0x90,0xE0,0x90,0xE0, // B
|
|
|
|
0xF0,0x80,0x80,0x80,0xF0, // C
|
|
|
|
0xE0,0x90,0x90,0x90,0xE0, // D
|
|
|
|
0xF0,0x80,0xF0,0x80,0xF0, // E
|
|
|
|
0xF0,0x80,0xF0,0x80,0x80 // F
|
|
|
|
};
|
|
|
|
std::array<bool,2048>display;
|
|
|
|
std::stack<uint8_t>stack;
|
|
|
|
float pulse=0;
|
|
|
|
uint8_t delay_timer,sound_timer;
|
|
|
|
uint16_t pc=0x200;
|
|
|
|
uint16_t index; //One 16-bit index register called “I” which is used to point at locations in memory
|
|
|
|
std::array<uint8_t,16>reg;
|
|
|
|
|
|
|
|
std::string Display8(int number){
|
|
|
|
std::bitset<8>numb(number);
|
|
|
|
return numb.to_string();
|
|
|
|
}
|
|
|
|
std::string Display16(int number){
|
|
|
|
std::bitset<16>numb(number);
|
|
|
|
return numb.to_string();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool OnUserCreate() override
|
|
|
|
{
|
|
|
|
memory[0x200]=0x60;
|
|
|
|
memory[0x201]=0x0A;
|
|
|
|
memory[0x202]=0x70;
|
|
|
|
memory[0x203]=0x04;
|
|
|
|
memory[0x204]=0x12;
|
|
|
|
memory[0x205]=0x00;
|
|
|
|
//0x200 program start
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OnUserUpdate(float fElapsedTime) override
|
|
|
|
{
|
|
|
|
pulse+=fElapsedTime;
|
|
|
|
if (pulse>=1/60.f){
|
|
|
|
if (delay_timer>0){
|
|
|
|
delay_timer--;
|
|
|
|
}
|
|
|
|
if (sound_timer>0){
|
|
|
|
sound_timer--;
|
|
|
|
}
|
|
|
|
pulse-=1/60.f;
|
|
|
|
|
|
|
|
for (int i=0;i<10;i++){
|
|
|
|
|
|
|
|
//FETCH
|
|
|
|
uint16_t opcode = memory[pc]<<8|memory[pc+1];
|
|
|
|
pc+=2;
|
|
|
|
|
|
|
|
//DECODE
|
|
|
|
uint8_t nibble1 = opcode>>12;
|
|
|
|
uint8_t X = opcode>>8&0xF;
|
|
|
|
uint8_t Y = opcode>>4&0xF;
|
|
|
|
uint8_t N = opcode&0xF;
|
|
|
|
uint8_t NN = opcode&0x00FF;
|
|
|
|
uint16_t NNN = opcode&0x0FFF;
|
|
|
|
std::cout<<"Opcode 0x"<<std::hex<<opcode<<std::dec<<": "<<Display8(nibble1)<<", "<<Display8(X)<<"/"<<Display8(Y)<<"/"<<Display8(N)<<"/"<<Display8(NN)<<"/"<<Display16(NNN)<<std::endl;
|
|
|
|
switch(nibble1){
|
|
|
|
case 0x0:{
|
|
|
|
switch (NNN){
|
|
|
|
case 0x0E0:{ //Clear screen.
|
|
|
|
for (int i=0;i<display.size();i++){
|
|
|
|
display[i]=0;
|
|
|
|
}
|
|
|
|
}break;
|
|
|
|
}
|
|
|
|
}break;
|
|
|
|
case 0x1:{ //Jump.
|
|
|
|
pc=NNN;
|
|
|
|
}break;
|
|
|
|
case 0x2:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
case 0x3:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
case 0x4:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
case 0x5:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
case 0x6:{ //Set the register X to NN.
|
|
|
|
reg[X]=NN;
|
|
|
|
std::cout<<(int)reg[X]<<std::endl;
|
|
|
|
}break;
|
|
|
|
case 0x7:{ //Add w/no carry
|
|
|
|
reg[X]+=NN;
|
|
|
|
std::cout<<(int)reg[X]<<std::endl;
|
|
|
|
}break;
|
|
|
|
case 0x8:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
case 0x9:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
case 0xA:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
case 0xB:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
case 0xC:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
case 0xD:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
case 0xE:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
case 0xF:{
|
|
|
|
|
|
|
|
}break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Clear(VERY_DARK_BLUE);
|
|
|
|
for (int x=0;x<ScreenWidth();x++){
|
|
|
|
for (int y=0;y<ScreenHeight();y++){
|
|
|
|
Draw({x,y},display[y*ScreenWidth()+x]?WHITE:BLACK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool OnUserDestroy()override{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
Chip8Emulator demo;
|
|
|
|
if (demo.Construct(64, 32, 10, 10))
|
|
|
|
demo.Start();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|