- First commit, working on the cpu
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
nes
|
||||||
192
6502.cpp
Normal file
192
6502.cpp
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
#include "6502.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
namespace cpu6502
|
||||||
|
{
|
||||||
|
static uint32_t clock = 0;
|
||||||
|
static uint32_t t = 0;
|
||||||
|
|
||||||
|
// P register Flags
|
||||||
|
#define fC 0b00000001 // Carry
|
||||||
|
#define fZ 0b00000010 // Zero
|
||||||
|
#define fI 0b00000100 // Interrupt disable
|
||||||
|
#define fD 0b00001000 // Decimal
|
||||||
|
#define fB 0b00010000 // Interrupt type?
|
||||||
|
#define f1 0b00100000 // -Unused-
|
||||||
|
#define fV 0b01000000 // Overflow
|
||||||
|
#define fN 0b10000000 // Negative
|
||||||
|
|
||||||
|
// Jump types
|
||||||
|
#define cUnconditional 255
|
||||||
|
#define cNZ 0
|
||||||
|
#define cZ 1
|
||||||
|
#define cNC 2
|
||||||
|
#define cC 3
|
||||||
|
#define cNN 4
|
||||||
|
#define cN 5
|
||||||
|
#define cNV 6
|
||||||
|
#define cV 7
|
||||||
|
|
||||||
|
// Addressing modes
|
||||||
|
#define aAccumulator 0
|
||||||
|
#define aImmediate 1
|
||||||
|
#define aZeroPage 2
|
||||||
|
#define aZeroPageX 3
|
||||||
|
#define aZeroPageY 4
|
||||||
|
#define aRelative 5
|
||||||
|
#define aIndirect 6
|
||||||
|
#define aIndirectX 7
|
||||||
|
#define aIndirectY 8
|
||||||
|
#define aAbsolute 9
|
||||||
|
#define aAbsoluteX 10
|
||||||
|
#define aAbsoluteY 11
|
||||||
|
|
||||||
|
uint8_t regs[7];
|
||||||
|
|
||||||
|
uint8_t *_rA = ®s[0];
|
||||||
|
uint8_t *_rX = ®s[1];
|
||||||
|
uint8_t *_rY = ®s[2];
|
||||||
|
uint8_t *_rS = ®s[3];
|
||||||
|
uint8_t *_rP = ®s[4];
|
||||||
|
uint16_t *_rPC = (uint16_t*)®s[5];
|
||||||
|
|
||||||
|
#define rA (*_rA)
|
||||||
|
#define rX (*_rX)
|
||||||
|
#define rY (*_rY)
|
||||||
|
#define rS (*_rS)
|
||||||
|
#define rP (*_rP)
|
||||||
|
#define rPC (*_rPC)
|
||||||
|
|
||||||
|
bool reading_m1 = false;
|
||||||
|
|
||||||
|
uint8_t READ_MEM_8(const uint16_t addr, const bool code=false)
|
||||||
|
{
|
||||||
|
if (debug::isbreak(addr, 2)) debug::stop();
|
||||||
|
t+=1; //[TODO]
|
||||||
|
|
||||||
|
const uint8_t tag = mem::getTag(addr);
|
||||||
|
if ( !(tag&MEMTAG_IGNORE) ) {
|
||||||
|
if (!code) {
|
||||||
|
if ( tag & MEMTAG_INST ) {
|
||||||
|
} else {
|
||||||
|
mem::setTag(addr, tag | MEMTAG_DATA);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( (reading_m1) && ( tag & MEMTAG_DATA ) ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reading_m1 = false;
|
||||||
|
return mem::readMem(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t READ_MEM_8()
|
||||||
|
{
|
||||||
|
const uint8_t data = READ_MEM_8(rPC, true);
|
||||||
|
const uint8_t tag = mem::getTag(rPC);
|
||||||
|
if ( !(tag & MEMTAG_IGNORE) ) mem::setTag(rPC, tag | MEMTAG_CODE);
|
||||||
|
rPC++;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t READ_M1()
|
||||||
|
{
|
||||||
|
reading_m1 = true;
|
||||||
|
return READ_MEM_8();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t READ_MEM_16()
|
||||||
|
{
|
||||||
|
const uint8_t L = READ_MEM_8();
|
||||||
|
const uint8_t H = READ_MEM_8();
|
||||||
|
return (H << 8) + L;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t READ_MEM_16(const uint16_t addr)
|
||||||
|
{
|
||||||
|
return READ_MEM_8(addr) + (READ_MEM_8(addr+1) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t WRITE_MEM_8(const uint16_t addr, const uint8_t value)
|
||||||
|
{
|
||||||
|
t+=1; // [TODO]
|
||||||
|
mem::writeMem(addr, value);
|
||||||
|
|
||||||
|
if (debug::isbreak(addr, 4)) debug::stop();
|
||||||
|
debug::setmemmodified(addr);
|
||||||
|
|
||||||
|
const uint8_t tag = mem::getTag(addr);
|
||||||
|
if ( !(tag & MEMTAG_IGNORE) ) {
|
||||||
|
if ( tag & MEMTAG_INST ) {
|
||||||
|
//printf("WARNING! WRITING DATA OVER CODE!!! $%4X\n", addr);
|
||||||
|
//z80debug::stop();
|
||||||
|
} else {
|
||||||
|
mem::setTag(addr, tag | MEMTAG_DATA | MEMTAG_TDATA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WRITE_MEM_16(const uint16_t addr, const uint16_t value)
|
||||||
|
{
|
||||||
|
WRITE_MEM_8(addr, value & 0xff);
|
||||||
|
WRITE_MEM_8(addr+1, (value>>8) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
mem::reset();
|
||||||
|
|
||||||
|
rPC = 0x00;
|
||||||
|
rA = rX = rY = rS = rP = 0xff;
|
||||||
|
t = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void interrupt(uint8_t type)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void BRK()
|
||||||
|
{
|
||||||
|
rPC++;
|
||||||
|
WRITE_MEM_16(0x0100+rS, rPC); rS-=2;
|
||||||
|
WRITE_MEM_8(0x0100+rS, rP|f1|fB); rS--;
|
||||||
|
rP |= fI;
|
||||||
|
rPC = READ_MEM_16(0xfffe);
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ORA(uint8_t addr_mode)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t step()
|
||||||
|
{
|
||||||
|
t = 0;
|
||||||
|
uint16_t current_opcode_address = rPC;
|
||||||
|
const uint8_t opcode = READ_M1();
|
||||||
|
|
||||||
|
uint8_t tag = mem::getTag(current_opcode_address);
|
||||||
|
if ( !(tag & MEMTAG_IGNORE) ) tag = tag | MEMTAG_INST;
|
||||||
|
mem::setTag(current_opcode_address, tag | (!(tag&MEMTAG_TOUCHED) ? MEMTAG_TREPEAT : MEMTAG_TINST) );
|
||||||
|
|
||||||
|
uint16_t tmp;
|
||||||
|
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
case 0x00: BRK(); break;
|
||||||
|
case 0x01: ORA(aIndirectX); break;
|
||||||
|
};
|
||||||
|
|
||||||
|
// [TODO] Gestionar interrupcions
|
||||||
|
|
||||||
|
//debug::setcursor(rPC);
|
||||||
|
//debug::history::store();
|
||||||
|
mem::update_mapped(t);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
10
6502.h
Normal file
10
6502.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace cpu6502
|
||||||
|
{
|
||||||
|
void reset();
|
||||||
|
void interrupt(uint8_t type);
|
||||||
|
uint32_t step();
|
||||||
|
}
|
||||||
17
Makefile
Normal file
17
Makefile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
compile:
|
||||||
|
g++ -g *.cpp -lSDL2 -o nes
|
||||||
|
|
||||||
|
run: compile
|
||||||
|
./nes tetris.gb
|
||||||
|
|
||||||
|
debug: compile
|
||||||
|
gdb --args nes tetris.gb
|
||||||
|
|
||||||
|
debug1: compile
|
||||||
|
gdb -ex run nes
|
||||||
|
|
||||||
|
release:
|
||||||
|
g++ -O3 *.cpp -lSDL2 -o nes
|
||||||
|
|
||||||
|
profile:
|
||||||
|
g++ -g *.cpp -lSDL2 -o nes -pg
|
||||||
10
debug.h
Normal file
10
debug.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace debug
|
||||||
|
{
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
const bool isbreak(uint16_t address, uint8_t type = 1);
|
||||||
|
void setmemmodified(uint16_t address);
|
||||||
|
}
|
||||||
28
mem.h
Normal file
28
mem.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace mem
|
||||||
|
{
|
||||||
|
#define MEMTAG_NONE 0x00
|
||||||
|
#define MEMTAG_DATA 0x01
|
||||||
|
#define MEMTAG_INST 0x02
|
||||||
|
#define MEMTAG_CODE 0x04
|
||||||
|
#define MEMTAG_IGNORE 0x08
|
||||||
|
#define MEMTAG_TDATA 0x10
|
||||||
|
#define MEMTAG_TINST 0x20
|
||||||
|
#define MEMTAG_TREPEAT 0x40
|
||||||
|
#define MEMTAG_MODIFIED 0x80
|
||||||
|
|
||||||
|
#define MEMTAG_KNOWN 0x07
|
||||||
|
#define MEMTAG_TOUCHED 0x70
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
uint8_t readMem(uint16_t address);
|
||||||
|
void writeMem(uint16_t address, uint8_t value);
|
||||||
|
|
||||||
|
uint8_t getTag(uint16_t address);
|
||||||
|
void setTag(uint16_t address, uint8_t value);
|
||||||
|
|
||||||
|
void update_mapped(uint32_t dt);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user