Skip to content

Commit c94c7a9

Browse files
KalixtanLukeUsher
authored andcommitted
Added My vision Core
1 parent ee6a7fe commit c94c7a9

32 files changed

+970
-1
lines changed

ares/GNUmakefile

+4
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ ifneq ($(filter $(cores),cv),)
7777
include $(ares.path)/cv/GNUmakefile
7878
endif
7979

80+
ifneq ($(filter $(cores),myvision),)
81+
include $(ares.path)/myvision/GNUmakefile
82+
endif
83+
8084
ifneq ($(filter $(cores),gb),)
8185
include $(ares.path)/gb/GNUmakefile
8286
endif

ares/myvision/GNUmakefile

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
ares.components += z80
2+
ares.components += tms9918
3+
ares.components += ay38910
4+
5+
ares.objects += ares-myvision-cpu
6+
ares.objects += ares-myvision-vdp
7+
ares.objects += ares-myvision-psg
8+
ares.objects += ares-myvision-system
9+
ares.objects += ares-myvision-cartridge
10+
11+
$(object.path)/ares-myvision-cpu.o: $(ares.path)/myvision/cpu/cpu.cpp
12+
$(object.path)/ares-myvision-vdp.o: $(ares.path)/myvision/vdp/vdp.cpp
13+
$(object.path)/ares-myvision-psg.o: $(ares.path)/myvision/psg/psg.cpp
14+
$(object.path)/ares-myvision-system.o: $(ares.path)/myvision/system/system.cpp
15+
$(object.path)/ares-myvision-cartridge.o: $(ares.path)/myvision/cartridge/cartridge.cpp

ares/myvision/cartridge/cartridge.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include <myvision/myvision.hpp>
2+
3+
namespace ares::MyVision {
4+
5+
Cartridge& cartridge = cartridgeSlot.cartridge;
6+
#include "slot.cpp"
7+
#include "serialization.cpp"
8+
9+
auto Cartridge::allocate(Node::Port parent) -> Node::Peripheral {
10+
return node = parent->append<Node::Peripheral>(string{system.name(), " Cartridge"});
11+
}
12+
13+
auto Cartridge::connect() -> void {
14+
if(!node->setPak(pak = platform->pak(node))) return;
15+
16+
information = {};
17+
information.title = pak->attribute("title");
18+
19+
if(auto fp = pak->read("program.rom")) {
20+
rom.allocate(fp->size());
21+
rom.load(fp);
22+
}
23+
24+
power();
25+
}
26+
27+
auto Cartridge::disconnect() -> void {
28+
if(!node) return;
29+
rom.reset();
30+
pak.reset();
31+
node.reset();
32+
}
33+
34+
auto Cartridge::save() -> void {
35+
}
36+
37+
auto Cartridge::power() -> void {
38+
}
39+
40+
auto Cartridge::read(n16 address) -> n8 {
41+
if(address >= rom.size()) return 0xff;
42+
return rom.read(address);
43+
}
44+
45+
}

ares/myvision/cartridge/cartridge.hpp

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
struct Cartridge {
2+
Node::Peripheral node;
3+
VFS::Pak pak;
4+
5+
auto title() const -> string { return information.title; }
6+
7+
//cartridge.cpp
8+
auto allocate(Node::Port) -> Node::Peripheral;
9+
auto connect() -> void;
10+
auto disconnect() -> void;
11+
12+
auto save() -> void;
13+
auto power() -> void;
14+
15+
auto read(n16 address) -> n8;
16+
17+
//serialization.cpp
18+
auto serialize(serializer&) -> void;
19+
20+
private:
21+
struct Information {
22+
string title;
23+
} information;
24+
25+
Memory::Readable<n8> rom;
26+
};
27+
28+
#include "slot.hpp"
29+
extern Cartridge& cartridge;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
auto Cartridge::serialize(serializer& s) -> void {
2+
}

ares/myvision/cartridge/slot.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
CartridgeSlot cartridgeSlot{"Cartridge Slot"};
2+
3+
CartridgeSlot::CartridgeSlot(string name) : name(name) {
4+
}
5+
6+
auto CartridgeSlot::load(Node::Object parent) -> void {
7+
port = parent->append<Node::Port>(name);
8+
port->setFamily(system.name());
9+
port->setType("Cartridge");
10+
port->setAllocate([&](auto name) { return cartridge.allocate(port); });
11+
port->setConnect([&] { return cartridge.connect(); });
12+
port->setDisconnect([&] { return cartridge.disconnect(); });
13+
}
14+
15+
auto CartridgeSlot::unload() -> void {
16+
cartridge.disconnect();
17+
port = {};
18+
}

ares/myvision/cartridge/slot.hpp

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
struct CartridgeSlot {
2+
Node::Port port;
3+
Cartridge cartridge;
4+
5+
//slot.cpp
6+
CartridgeSlot(string name);
7+
auto load(Node::Object) -> void;
8+
auto unload() -> void;
9+
10+
const string name;
11+
};
12+
13+
extern CartridgeSlot cartridgeSlot;

ares/myvision/cpu/cpu.cpp

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include <myvision/myvision.hpp>
2+
3+
namespace ares::MyVision {
4+
5+
CPU cpu;
6+
#include "memory.cpp"
7+
#include "debugger.cpp"
8+
#include "serialization.cpp"
9+
10+
auto CPU::load(Node::Object parent) -> void {
11+
ram.allocate(0x10000);
12+
13+
node = parent->append<Node::Object>("CPU");
14+
15+
debugger.load(node);
16+
}
17+
18+
auto CPU::unload() -> void {
19+
ram.reset();
20+
node = {};
21+
debugger = {};
22+
}
23+
24+
auto CPU::main() -> void {
25+
if(state.nmiPending) {
26+
state.nmiPending = 0; //edge-sensitive
27+
debugger.interrupt("NMI");
28+
nmi();
29+
}
30+
31+
if(state.irqLine) {
32+
//level-sensitive
33+
debugger.interrupt("IRQ");
34+
irq();
35+
}
36+
37+
debugger.instruction();
38+
instruction();
39+
}
40+
41+
auto CPU::step(uint clocks) -> void {
42+
Thread::step(clocks);
43+
Thread::synchronize();
44+
}
45+
46+
auto CPU::setNMI(bool value) -> void {
47+
if(!state.nmiLine && value) state.nmiPending = 1;
48+
state.nmiLine = value;
49+
}
50+
51+
auto CPU::setIRQ(bool value) -> void {
52+
state.irqLine = value;
53+
}
54+
55+
auto CPU::power() -> void {
56+
Z80::bus = this;
57+
Z80::power();
58+
Thread::create(Constants::Colorburst::NTSC, {&CPU::main, this});
59+
60+
PC = 0x0000; //reset vector address
61+
state = {};
62+
ram.fill(0);
63+
}
64+
65+
}

ares/myvision/cpu/cpu.hpp

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
struct CPU : Z80, Z80::Bus, Thread {
2+
Node::Object node;
3+
Memory::Writable<n8> ram;
4+
5+
struct Debugger {
6+
//debugger.cpp
7+
auto load(Node::Object) -> void;
8+
auto instruction() -> void;
9+
auto interrupt(string_view) -> void;
10+
11+
struct Memory {
12+
Node::Debugger::Memory ram;
13+
} memory;
14+
15+
struct Tracer {
16+
Node::Debugger::Tracer::Instruction instruction;
17+
Node::Debugger::Tracer::Notification interrupt;
18+
} tracer;
19+
} debugger;
20+
21+
auto synchronizing() const -> bool override { return scheduler.synchronizing(); }
22+
23+
//cpu.cpp
24+
auto load(Node::Object) -> void;
25+
auto unload() -> void;
26+
27+
auto main() -> void;
28+
auto step(u32 clocks) -> void override;
29+
30+
auto setNMI(bool value) -> void;
31+
auto setIRQ(bool value) -> void;
32+
33+
auto power() -> void;
34+
35+
//memory.cpp
36+
auto read(n16 address) -> n8 override;
37+
auto write(n16 address, n8 data) -> void override;
38+
39+
auto in(n16 address) -> n8 override;
40+
auto out(n16 address, n8 data) -> void override;
41+
42+
//serialization.cpp
43+
auto serialize(serializer&) -> void;
44+
45+
private:
46+
struct State {
47+
bool nmiPending = 0;
48+
bool nmiLine = 0;
49+
bool irqLine = 0;
50+
} state;
51+
};
52+
53+
extern CPU cpu;

ares/myvision/cpu/debugger.cpp

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
auto CPU::Debugger::load(Node::Object parent) -> void {
2+
memory.ram = parent->append<Node::Debugger::Memory>("CPU RAM");
3+
memory.ram->setSize(cpu.ram.size());
4+
memory.ram->setRead([&](u32 address) -> u8 {
5+
return cpu.ram[address];
6+
});
7+
memory.ram->setWrite([&](u32 address, u8 data) -> void {
8+
cpu.ram[address] = data;
9+
});
10+
11+
//memory.expansion = parent->append<Node::Debugger::Memory>("CPU EXPRAM");
12+
//memory.expansion->setSize(cpu.expansion.size());
13+
//memory.expansion->setRead([&](u32 address) -> u8 {
14+
// return cpu.expansion[address];
15+
//});
16+
//memory.expansion->setWrite([&](u32 address, u8 data) -> void {
17+
// cpu.expansion[address] = data;
18+
//});
19+
20+
tracer.instruction = parent->append<Node::Debugger::Tracer::Instruction>("Instruction", "CPU");
21+
tracer.instruction->setAddressBits(16);
22+
23+
tracer.interrupt = parent->append<Node::Debugger::Tracer::Notification>("Interrupt", "CPU");
24+
}
25+
26+
auto CPU::Debugger::instruction() -> void {
27+
if(tracer.instruction->enabled() && tracer.instruction->address(cpu.PC)) {
28+
tracer.instruction->notify(cpu.disassembleInstruction(), cpu.disassembleContext());
29+
}
30+
}
31+
32+
auto CPU::Debugger::interrupt(string_view type) -> void {
33+
if(tracer.interrupt->enabled()) {
34+
tracer.interrupt->notify(type);
35+
}
36+
}

ares/myvision/cpu/memory.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
auto CPU::read(n16 address) -> n8 {
2+
3+
// VIDEO
4+
if (address == 0xe000) return vdp.data();
5+
if (address == 0xe002) return vdp.status();
6+
7+
// MAIN
8+
if (address < 0x6000) return cartridge.read(address);
9+
if (address >= 0xa000 && address <= 0xa800) return ram.read(address - 0xa000);
10+
11+
return 0;
12+
}
13+
14+
auto CPU::write(n16 address, n8 data) -> void {
15+
16+
// VIDEO
17+
if (address == 0xe000) return vdp.data(data);
18+
if (address == 0xe002) return vdp.control(data);
19+
20+
// MAIN
21+
if (address < 0x6000) return; // ALL RETAIL GAMES ARE WRITE ONLY
22+
if (address >= 0xa000 && address <= 0xffff) return ram.write(address - 0xa000, data);
23+
24+
return;
25+
}
26+
27+
auto CPU::out(n16 address, n8 data) -> void {
28+
address &= 0xff;
29+
if (address == 0x00) {
30+
return psg.select(data);
31+
}
32+
if (address == 0x01) {
33+
return psg.write(data);
34+
}
35+
}
36+
37+
auto CPU::in(n16 address) -> n8 {
38+
address &= 0xff;
39+
if (address == 0x02) {
40+
return psg.read();
41+
}
42+
43+
return 0xff;
44+
}

ares/myvision/cpu/serialization.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
auto CPU::serialize(serializer& s) -> void {
2+
Z80::serialize(s);
3+
Thread::serialize(s);
4+
s(ram);
5+
s(state.nmiPending);
6+
s(state.nmiLine);
7+
s(state.irqLine);
8+
}

ares/myvision/myvision.hpp

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
//started: 2023-07-19
3+
4+
#include <ares/ares.hpp>
5+
6+
#include <component/processor/z80/z80.hpp>
7+
#include <component/video/tms9918/tms9918.hpp>
8+
#include <component/audio/ay38910/ay38910.hpp>
9+
10+
namespace ares::MyVision {
11+
#include <ares/inline.hpp>
12+
auto enumerate() -> vector<string>;
13+
auto load(Node::System& node, string name) -> bool;
14+
15+
#include <myvision/cpu/cpu.hpp>
16+
#include <myvision/vdp/vdp.hpp>
17+
#include <myvision/psg/psg.hpp>
18+
19+
#include <myvision/system/system.hpp>
20+
#include <myvision/cartridge/cartridge.hpp>
21+
}

0 commit comments

Comments
 (0)