mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-18 16:30:29 +00:00
Merge pull request #200 from TomHarte/6502BusHandler
Converts the 6502 into a bus-handler-type template, and makes appropriate adjustments to all 6502 machines
This commit is contained in:
commit
2105597910
@ -10,18 +10,18 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "Cartridges/CartridgeAtari8k.hpp"
|
#include "Cartridges/Atari8k.hpp"
|
||||||
#include "Cartridges/CartridgeAtari16k.hpp"
|
#include "Cartridges/Atari16k.hpp"
|
||||||
#include "Cartridges/CartridgeAtari32k.hpp"
|
#include "Cartridges/Atari32k.hpp"
|
||||||
#include "Cartridges/CartridgeActivisionStack.hpp"
|
#include "Cartridges/ActivisionStack.hpp"
|
||||||
#include "Cartridges/CartridgeCBSRAMPlus.hpp"
|
#include "Cartridges/CBSRAMPlus.hpp"
|
||||||
#include "Cartridges/CartridgeCommaVid.hpp"
|
#include "Cartridges/CommaVid.hpp"
|
||||||
#include "Cartridges/CartridgeMegaBoy.hpp"
|
#include "Cartridges/MegaBoy.hpp"
|
||||||
#include "Cartridges/CartridgeMNetwork.hpp"
|
#include "Cartridges/MNetwork.hpp"
|
||||||
#include "Cartridges/CartridgeParkerBros.hpp"
|
#include "Cartridges/ParkerBros.hpp"
|
||||||
#include "Cartridges/CartridgePitfall2.hpp"
|
#include "Cartridges/Pitfall2.hpp"
|
||||||
#include "Cartridges/CartridgeTigervision.hpp"
|
#include "Cartridges/Tigervision.hpp"
|
||||||
#include "Cartridges/CartridgeUnpaged.hpp"
|
#include "Cartridges/Unpaged.hpp"
|
||||||
|
|
||||||
using namespace Atari2600;
|
using namespace Atari2600;
|
||||||
namespace {
|
namespace {
|
||||||
@ -83,35 +83,35 @@ void Machine::set_switch_is_enabled(Atari2600Switch input, bool state) {
|
|||||||
void Machine::configure_as_target(const StaticAnalyser::Target &target) {
|
void Machine::configure_as_target(const StaticAnalyser::Target &target) {
|
||||||
const std::vector<uint8_t> &rom = target.cartridges.front()->get_segments().front().data;
|
const std::vector<uint8_t> &rom = target.cartridges.front()->get_segments().front().data;
|
||||||
switch(target.atari.paging_model) {
|
switch(target.atari.paging_model) {
|
||||||
case StaticAnalyser::Atari2600PagingModel::ActivisionStack: bus_.reset(new CartridgeActivisionStack(rom)); break;
|
case StaticAnalyser::Atari2600PagingModel::ActivisionStack: bus_.reset(new Cartridge::Cartridge<Cartridge::ActivisionStack>(rom)); break;
|
||||||
case StaticAnalyser::Atari2600PagingModel::CBSRamPlus: bus_.reset(new CartridgeCBSRAMPlus(rom)); break;
|
case StaticAnalyser::Atari2600PagingModel::CBSRamPlus: bus_.reset(new Cartridge::Cartridge<Cartridge::CBSRAMPlus>(rom)); break;
|
||||||
case StaticAnalyser::Atari2600PagingModel::CommaVid: bus_.reset(new CartridgeCommaVid(rom)); break;
|
case StaticAnalyser::Atari2600PagingModel::CommaVid: bus_.reset(new Cartridge::Cartridge<Cartridge::CommaVid>(rom)); break;
|
||||||
case StaticAnalyser::Atari2600PagingModel::MegaBoy: bus_.reset(new CartridgeMegaBoy(rom)); break;
|
case StaticAnalyser::Atari2600PagingModel::MegaBoy: bus_.reset(new Cartridge::Cartridge<Cartridge::MegaBoy>(rom)); break;
|
||||||
case StaticAnalyser::Atari2600PagingModel::MNetwork: bus_.reset(new CartridgeMNetwork(rom)); break;
|
case StaticAnalyser::Atari2600PagingModel::MNetwork: bus_.reset(new Cartridge::Cartridge<Cartridge::MNetwork>(rom)); break;
|
||||||
case StaticAnalyser::Atari2600PagingModel::None: bus_.reset(new CartridgeUnpaged(rom)); break;
|
case StaticAnalyser::Atari2600PagingModel::None: bus_.reset(new Cartridge::Cartridge<Cartridge::Unpaged>(rom)); break;
|
||||||
case StaticAnalyser::Atari2600PagingModel::ParkerBros: bus_.reset(new CartridgeParkerBros(rom)); break;
|
case StaticAnalyser::Atari2600PagingModel::ParkerBros: bus_.reset(new Cartridge::Cartridge<Cartridge::ParkerBros>(rom)); break;
|
||||||
case StaticAnalyser::Atari2600PagingModel::Pitfall2: bus_.reset(new CartridgePitfall2(rom)); break;
|
case StaticAnalyser::Atari2600PagingModel::Pitfall2: bus_.reset(new Cartridge::Cartridge<Cartridge::Pitfall2>(rom)); break;
|
||||||
case StaticAnalyser::Atari2600PagingModel::Tigervision: bus_.reset(new CartridgeTigervision(rom)); break;
|
case StaticAnalyser::Atari2600PagingModel::Tigervision: bus_.reset(new Cartridge::Cartridge<Cartridge::Tigervision>(rom)); break;
|
||||||
|
|
||||||
case StaticAnalyser::Atari2600PagingModel::Atari8k:
|
case StaticAnalyser::Atari2600PagingModel::Atari8k:
|
||||||
if(target.atari.uses_superchip) {
|
if(target.atari.uses_superchip) {
|
||||||
bus_.reset(new CartridgeAtari8kSuperChip(rom));
|
bus_.reset(new Cartridge::Cartridge<Cartridge::Atari8kSuperChip>(rom));
|
||||||
} else {
|
} else {
|
||||||
bus_.reset(new CartridgeAtari8k(rom));
|
bus_.reset(new Cartridge::Cartridge<Cartridge::Atari8k>(rom));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case StaticAnalyser::Atari2600PagingModel::Atari16k:
|
case StaticAnalyser::Atari2600PagingModel::Atari16k:
|
||||||
if(target.atari.uses_superchip) {
|
if(target.atari.uses_superchip) {
|
||||||
bus_.reset(new CartridgeAtari16kSuperChip(rom));
|
bus_.reset(new Cartridge::Cartridge<Cartridge::Atari16kSuperChip>(rom));
|
||||||
} else {
|
} else {
|
||||||
bus_.reset(new CartridgeAtari16k(rom));
|
bus_.reset(new Cartridge::Cartridge<Cartridge::Atari16k>(rom));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case StaticAnalyser::Atari2600PagingModel::Atari32k:
|
case StaticAnalyser::Atari2600PagingModel::Atari32k:
|
||||||
if(target.atari.uses_superchip) {
|
if(target.atari.uses_superchip) {
|
||||||
bus_.reset(new CartridgeAtari32kSuperChip(rom));
|
bus_.reset(new Cartridge::Cartridge<Cartridge::Atari32kSuperChip>(rom));
|
||||||
} else {
|
} else {
|
||||||
bus_.reset(new CartridgeAtari32k(rom));
|
bus_.reset(new Cartridge::Cartridge<Cartridge::Atari32k>(rom));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6,18 +6,18 @@
|
|||||||
// Copyright © 2017 Thomas Harte. All rights reserved.
|
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef Atari2600_CartridgeActivisionStack_hpp
|
#ifndef Atari2600_ActivisionStack_hpp
|
||||||
#define Atari2600_CartridgeActivisionStack_hpp
|
#define Atari2600_ActivisionStack_hpp
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
class CartridgeActivisionStack: public Cartridge<CartridgeActivisionStack> {
|
class ActivisionStack: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeActivisionStack(const std::vector<uint8_t> &rom) :
|
ActivisionStack(uint8_t *rom_base, size_t rom_size) :
|
||||||
Cartridge(rom),
|
BusExtender(rom_base, rom_size),
|
||||||
last_opcode_(0x00) {
|
rom_ptr_(rom_base),
|
||||||
rom_ptr_ = rom_.data();
|
last_opcode_(0x00) {}
|
||||||
}
|
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
if(!(address & 0x1000)) return;
|
if(!(address & 0x1000)) return;
|
||||||
@ -27,9 +27,9 @@ class CartridgeActivisionStack: public Cartridge<CartridgeActivisionStack> {
|
|||||||
// RST or JSR.
|
// RST or JSR.
|
||||||
if(operation == CPU::MOS6502::BusOperation::ReadOpcode && (last_opcode_ == 0x20 || last_opcode_ == 0x60)) {
|
if(operation == CPU::MOS6502::BusOperation::ReadOpcode && (last_opcode_ == 0x20 || last_opcode_ == 0x60)) {
|
||||||
if(address & 0x2000) {
|
if(address & 0x2000) {
|
||||||
rom_ptr_ = rom_.data();
|
rom_ptr_ = rom_base_;
|
||||||
} else {
|
} else {
|
||||||
rom_ptr_ = rom_.data() + 4096;
|
rom_ptr_ = rom_base_ + 4096;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +45,7 @@ class CartridgeActivisionStack: public Cartridge<CartridgeActivisionStack> {
|
|||||||
uint8_t last_opcode_;
|
uint8_t last_opcode_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_CartridgeActivisionStack_hpp */
|
#endif /* Atari2600_CartridgeActivisionStack_hpp */
|
@ -12,19 +12,19 @@
|
|||||||
#include "Cartridge.hpp"
|
#include "Cartridge.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
class CartridgeAtari16k: public Cartridge<CartridgeAtari16k> {
|
class Atari16k: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeAtari16k(const std::vector<uint8_t> &rom) :
|
Atari16k(uint8_t *rom_base, size_t rom_size) :
|
||||||
Cartridge(rom) {
|
BusExtender(rom_base, rom_size),
|
||||||
rom_ptr_ = rom_.data();
|
rom_ptr_(rom_base) {}
|
||||||
}
|
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
address &= 0x1fff;
|
address &= 0x1fff;
|
||||||
if(!(address & 0x1000)) return;
|
if(!(address & 0x1000)) return;
|
||||||
|
|
||||||
if(address >= 0x1ff6 && address <= 0x1ff9) rom_ptr_ = rom_.data() + (address - 0x1ff6) * 4096;
|
if(address >= 0x1ff6 && address <= 0x1ff9) rom_ptr_ = rom_base_ + (address - 0x1ff6) * 4096;
|
||||||
|
|
||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
*value = rom_ptr_[address & 4095];
|
*value = rom_ptr_[address & 4095];
|
||||||
@ -35,18 +35,17 @@ class CartridgeAtari16k: public Cartridge<CartridgeAtari16k> {
|
|||||||
uint8_t *rom_ptr_;
|
uint8_t *rom_ptr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CartridgeAtari16kSuperChip: public Cartridge<CartridgeAtari16kSuperChip> {
|
class Atari16kSuperChip: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeAtari16kSuperChip(const std::vector<uint8_t> &rom) :
|
Atari16kSuperChip(uint8_t *rom_base, size_t rom_size) :
|
||||||
Cartridge(rom) {
|
BusExtender(rom_base, rom_size),
|
||||||
rom_ptr_ = rom_.data();
|
rom_ptr_(rom_base) {}
|
||||||
}
|
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
address &= 0x1fff;
|
address &= 0x1fff;
|
||||||
if(!(address & 0x1000)) return;
|
if(!(address & 0x1000)) return;
|
||||||
|
|
||||||
if(address >= 0x1ff6 && address <= 0x1ff9) rom_ptr_ = rom_.data() + (address - 0x1ff6) * 4096;
|
if(address >= 0x1ff6 && address <= 0x1ff9) rom_ptr_ = rom_base_ + (address - 0x1ff6) * 4096;
|
||||||
|
|
||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
*value = rom_ptr_[address & 4095];
|
*value = rom_ptr_[address & 4095];
|
||||||
@ -61,6 +60,7 @@ class CartridgeAtari16kSuperChip: public Cartridge<CartridgeAtari16kSuperChip> {
|
|||||||
uint8_t ram_[128];
|
uint8_t ram_[128];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_CartridgeAtari16k_hpp */
|
#endif /* Atari2600_CartridgeAtari16k_hpp */
|
@ -12,19 +12,17 @@
|
|||||||
#include "Cartridge.hpp"
|
#include "Cartridge.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
class CartridgeAtari32k: public Cartridge<CartridgeAtari32k> {
|
class Atari32k: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeAtari32k(const std::vector<uint8_t> &rom) :
|
Atari32k(uint8_t *rom_base, size_t rom_size) : BusExtender(rom_base, rom_size), rom_ptr_(rom_base) {}
|
||||||
Cartridge(rom) {
|
|
||||||
rom_ptr_ = rom_.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
address &= 0x1fff;
|
address &= 0x1fff;
|
||||||
if(!(address & 0x1000)) return;
|
if(!(address & 0x1000)) return;
|
||||||
|
|
||||||
if(address >= 0x1ff4 && address <= 0x1ffb) rom_ptr_ = rom_.data() + (address - 0x1ff4) * 4096;
|
if(address >= 0x1ff4 && address <= 0x1ffb) rom_ptr_ = rom_base_ + (address - 0x1ff4) * 4096;
|
||||||
|
|
||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
*value = rom_ptr_[address & 4095];
|
*value = rom_ptr_[address & 4095];
|
||||||
@ -35,18 +33,15 @@ class CartridgeAtari32k: public Cartridge<CartridgeAtari32k> {
|
|||||||
uint8_t *rom_ptr_;
|
uint8_t *rom_ptr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CartridgeAtari32kSuperChip: public Cartridge<CartridgeAtari32kSuperChip> {
|
class Atari32kSuperChip: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeAtari32kSuperChip(const std::vector<uint8_t> &rom) :
|
Atari32kSuperChip(uint8_t *rom_base, size_t rom_size) : BusExtender(rom_base, rom_size), rom_ptr_(rom_base) {}
|
||||||
Cartridge(rom) {
|
|
||||||
rom_ptr_ = rom_.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
address &= 0x1fff;
|
address &= 0x1fff;
|
||||||
if(!(address & 0x1000)) return;
|
if(!(address & 0x1000)) return;
|
||||||
|
|
||||||
if(address >= 0x1ff4 && address <= 0x1ffb) rom_ptr_ = rom_.data() + (address - 0x1ff4) * 4096;
|
if(address >= 0x1ff4 && address <= 0x1ffb) rom_ptr_ = rom_base_ + (address - 0x1ff4) * 4096;
|
||||||
|
|
||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
*value = rom_ptr_[address & 4095];
|
*value = rom_ptr_[address & 4095];
|
||||||
@ -61,6 +56,7 @@ class CartridgeAtari32kSuperChip: public Cartridge<CartridgeAtari32kSuperChip> {
|
|||||||
uint8_t ram_[128];
|
uint8_t ram_[128];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_CartridgeAtari32k_hpp */
|
#endif /* Atari2600_CartridgeAtari32k_hpp */
|
@ -12,20 +12,18 @@
|
|||||||
#include "Cartridge.hpp"
|
#include "Cartridge.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
class CartridgeAtari8k: public Cartridge<CartridgeAtari8k> {
|
class Atari8k: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeAtari8k(const std::vector<uint8_t> &rom) :
|
Atari8k(uint8_t *rom_base, size_t rom_size) : BusExtender(rom_base, rom_size), rom_ptr_(rom_base) {}
|
||||||
Cartridge(rom) {
|
|
||||||
rom_ptr_ = rom_.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
address &= 0x1fff;
|
address &= 0x1fff;
|
||||||
if(!(address & 0x1000)) return;
|
if(!(address & 0x1000)) return;
|
||||||
|
|
||||||
if(address == 0x1ff8) rom_ptr_ = rom_.data();
|
if(address == 0x1ff8) rom_ptr_ = rom_base_;
|
||||||
else if(address == 0x1ff9) rom_ptr_ = rom_.data() + 4096;
|
else if(address == 0x1ff9) rom_ptr_ = rom_base_ + 4096;
|
||||||
|
|
||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
*value = rom_ptr_[address & 4095];
|
*value = rom_ptr_[address & 4095];
|
||||||
@ -36,19 +34,16 @@ class CartridgeAtari8k: public Cartridge<CartridgeAtari8k> {
|
|||||||
uint8_t *rom_ptr_;
|
uint8_t *rom_ptr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CartridgeAtari8kSuperChip: public Cartridge<CartridgeAtari8kSuperChip> {
|
class Atari8kSuperChip: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeAtari8kSuperChip(const std::vector<uint8_t> &rom) :
|
Atari8kSuperChip(uint8_t *rom_base, size_t rom_size) : BusExtender(rom_base, rom_size), rom_ptr_(rom_base) {}
|
||||||
Cartridge(rom) {
|
|
||||||
rom_ptr_ = rom_.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
address &= 0x1fff;
|
address &= 0x1fff;
|
||||||
if(!(address & 0x1000)) return;
|
if(!(address & 0x1000)) return;
|
||||||
|
|
||||||
if(address == 0x1ff8) rom_ptr_ = rom_.data();
|
if(address == 0x1ff8) rom_ptr_ = rom_base_;
|
||||||
if(address == 0x1ff9) rom_ptr_ = rom_.data() + 4096;
|
if(address == 0x1ff9) rom_ptr_ = rom_base_ + 4096;
|
||||||
|
|
||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
*value = rom_ptr_[address & 4095];
|
*value = rom_ptr_[address & 4095];
|
||||||
@ -63,6 +58,7 @@ class CartridgeAtari8kSuperChip: public Cartridge<CartridgeAtari8kSuperChip> {
|
|||||||
uint8_t ram_[128];
|
uint8_t ram_[128];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_CartridgeAtari8k_hpp */
|
#endif /* Atari2600_CartridgeAtari8k_hpp */
|
@ -12,19 +12,17 @@
|
|||||||
#include "Cartridge.hpp"
|
#include "Cartridge.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
class CartridgeCBSRAMPlus: public Cartridge<CartridgeCBSRAMPlus> {
|
class CBSRAMPlus: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeCBSRAMPlus(const std::vector<uint8_t> &rom) :
|
CBSRAMPlus(uint8_t *rom_base, size_t rom_size) : BusExtender(rom_base, rom_size), rom_ptr_(rom_base) {}
|
||||||
Cartridge(rom) {
|
|
||||||
rom_ptr_ = rom_.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
address &= 0x1fff;
|
address &= 0x1fff;
|
||||||
if(!(address & 0x1000)) return;
|
if(!(address & 0x1000)) return;
|
||||||
|
|
||||||
if(address >= 0x1ff8 && address <= 0x1ffa) rom_ptr_ = rom_.data() + (address - 0x1ff8) * 4096;
|
if(address >= 0x1ff8 && address <= 0x1ffa) rom_ptr_ = rom_base_ + (address - 0x1ff8) * 4096;
|
||||||
|
|
||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
*value = rom_ptr_[address & 4095];
|
*value = rom_ptr_[address & 4095];
|
||||||
@ -39,6 +37,7 @@ class CartridgeCBSRAMPlus: public Cartridge<CartridgeCBSRAMPlus> {
|
|||||||
uint8_t ram_[256];
|
uint8_t ram_[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_CartridgeCBSRAMPlus_hpp */
|
#endif /* Atari2600_CartridgeCBSRAMPlus_hpp */
|
@ -13,18 +13,34 @@
|
|||||||
#include "../Bus.hpp"
|
#include "../Bus.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
|
class BusExtender: public CPU::MOS6502::BusHandler {
|
||||||
|
public:
|
||||||
|
BusExtender(uint8_t *rom_base, size_t rom_size) : rom_base_(rom_base), rom_size_(rom_size) {}
|
||||||
|
|
||||||
|
void advance_cycles(int cycles) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t *rom_base_;
|
||||||
|
size_t rom_size_;
|
||||||
|
};
|
||||||
|
|
||||||
template<class T> class Cartridge:
|
template<class T> class Cartridge:
|
||||||
public CPU::MOS6502::Processor<Cartridge<T>>,
|
public CPU::MOS6502::BusHandler,
|
||||||
public Bus {
|
public Bus {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Cartridge(const std::vector<uint8_t> &rom) :
|
Cartridge(const std::vector<uint8_t> &rom) :
|
||||||
rom_(rom) {}
|
m6502_(*this),
|
||||||
|
rom_(rom),
|
||||||
|
bus_extender_(rom_.data(), rom.size()) {
|
||||||
|
// The above works because bus_extender_ is declared after rom_ in the instance storage list;
|
||||||
|
// consider doing something less fragile.
|
||||||
|
}
|
||||||
|
|
||||||
void run_for(const Cycles cycles) { CPU::MOS6502::Processor<Cartridge<T>>::run_for(cycles); }
|
void run_for(const Cycles cycles) { m6502_.run_for(cycles); }
|
||||||
void set_reset_line(bool state) { CPU::MOS6502::Processor<Cartridge<T>>::set_reset_line(state); }
|
void set_reset_line(bool state) { m6502_.set_reset_line(state); }
|
||||||
void advance_cycles(int cycles) {}
|
|
||||||
|
|
||||||
// to satisfy CPU::MOS6502::Processor
|
// to satisfy CPU::MOS6502::Processor
|
||||||
Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
@ -41,11 +57,11 @@ template<class T> class Cartridge:
|
|||||||
cycles_since_speaker_update_ += Cycles(cycles_run_for);
|
cycles_since_speaker_update_ += Cycles(cycles_run_for);
|
||||||
cycles_since_video_update_ += Cycles(cycles_run_for);
|
cycles_since_video_update_ += Cycles(cycles_run_for);
|
||||||
cycles_since_6532_update_ += Cycles(cycles_run_for / 3);
|
cycles_since_6532_update_ += Cycles(cycles_run_for / 3);
|
||||||
static_cast<T *>(this)->advance_cycles(cycles_run_for / 3);
|
bus_extender_.advance_cycles(cycles_run_for / 3);
|
||||||
|
|
||||||
if(operation != CPU::MOS6502::BusOperation::Ready) {
|
if(operation != CPU::MOS6502::BusOperation::Ready) {
|
||||||
// give the cartridge a chance to respond to the bus access
|
// give the cartridge a chance to respond to the bus access
|
||||||
static_cast<T *>(this)->perform_bus_operation(operation, address, value);
|
bus_extender_.perform_bus_operation(operation, address, value);
|
||||||
|
|
||||||
// check for a RIOT RAM access
|
// check for a RIOT RAM access
|
||||||
if((address&0x1280) == 0x80) {
|
if((address&0x1280) == 0x80) {
|
||||||
@ -91,7 +107,7 @@ template<class T> class Cartridge:
|
|||||||
case 0x00: update_video(); tia_->set_sync(*value & 0x02); break;
|
case 0x00: update_video(); tia_->set_sync(*value & 0x02); break;
|
||||||
case 0x01: update_video(); tia_->set_blank(*value & 0x02); break;
|
case 0x01: update_video(); tia_->set_blank(*value & 0x02); break;
|
||||||
|
|
||||||
case 0x02: CPU::MOS6502::Processor<Cartridge<T>>::set_ready_line(true); break;
|
case 0x02: m6502_.set_ready_line(true); break;
|
||||||
case 0x03: update_video(); tia_->reset_horizontal_counter(); break;
|
case 0x03: update_video(); tia_->reset_horizontal_counter(); break;
|
||||||
// TODO: audio will now be out of synchronisation — fix
|
// TODO: audio will now be out of synchronisation — fix
|
||||||
|
|
||||||
@ -156,7 +172,7 @@ template<class T> class Cartridge:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!tia_->get_cycles_until_horizontal_blank(cycles_since_video_update_)) CPU::MOS6502::Processor<Cartridge<T>>::set_ready_line(false);
|
if(!tia_->get_cycles_until_horizontal_blank(cycles_since_video_update_)) m6502_.set_ready_line(false);
|
||||||
|
|
||||||
return Cycles(cycles_run_for / 3);
|
return Cycles(cycles_run_for / 3);
|
||||||
}
|
}
|
||||||
@ -168,9 +184,14 @@ template<class T> class Cartridge:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
CPU::MOS6502::Processor<Cartridge<T>> m6502_;
|
||||||
std::vector<uint8_t> rom_;
|
std::vector<uint8_t> rom_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
T bus_extender_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_Cartridge_hpp */
|
#endif /* Atari2600_Cartridge_hpp */
|
||||||
|
@ -9,12 +9,14 @@
|
|||||||
#ifndef Atari2600_CartridgeCommaVid_hpp
|
#ifndef Atari2600_CartridgeCommaVid_hpp
|
||||||
#define Atari2600_CartridgeCommaVid_hpp
|
#define Atari2600_CartridgeCommaVid_hpp
|
||||||
|
|
||||||
namespace Atari2600 {
|
#include "Cartridge.hpp"
|
||||||
|
|
||||||
class CartridgeCommaVid: public Cartridge<CartridgeCommaVid> {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
|
class CommaVid: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeCommaVid(const std::vector<uint8_t> &rom) :
|
CommaVid(uint8_t *rom_base, size_t rom_size) : BusExtender(rom_base, rom_size) {}
|
||||||
Cartridge(rom) {}
|
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
if(!(address & 0x1000)) return;
|
if(!(address & 0x1000)) return;
|
||||||
@ -30,13 +32,14 @@ class CartridgeCommaVid: public Cartridge<CartridgeCommaVid> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isReadOperation(operation)) *value = rom_[address & 2047];
|
if(isReadOperation(operation)) *value = rom_base_[address & 2047];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t ram_[1024];
|
uint8_t ram_[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_CartridgeCommaVid_hpp */
|
#endif /* Atari2600_CartridgeCommaVid_hpp */
|
@ -12,12 +12,13 @@
|
|||||||
#include "Cartridge.hpp"
|
#include "Cartridge.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
class CartridgeMNetwork: public Cartridge<CartridgeMNetwork> {
|
class MNetwork: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeMNetwork(const std::vector<uint8_t> &rom) :
|
MNetwork(uint8_t *rom_base, size_t rom_size) :
|
||||||
Cartridge(rom) {
|
BusExtender(rom_base, rom_size) {
|
||||||
rom_ptr_[0] = rom_.data() + rom_.size() - 4096;
|
rom_ptr_[0] = rom_base + rom_size_ - 4096;
|
||||||
rom_ptr_[1] = rom_ptr_[0] + 2048;
|
rom_ptr_[1] = rom_ptr_[0] + 2048;
|
||||||
high_ram_ptr_ = high_ram_;
|
high_ram_ptr_ = high_ram_;
|
||||||
}
|
}
|
||||||
@ -27,7 +28,7 @@ class CartridgeMNetwork: public Cartridge<CartridgeMNetwork> {
|
|||||||
if(!(address & 0x1000)) return;
|
if(!(address & 0x1000)) return;
|
||||||
|
|
||||||
if(address >= 0x1fe0 && address <= 0x1fe6) {
|
if(address >= 0x1fe0 && address <= 0x1fe6) {
|
||||||
rom_ptr_[0] = rom_.data() + (address - 0x1fe0) * 2048;
|
rom_ptr_[0] = rom_base_ + (address - 0x1fe0) * 2048;
|
||||||
} else if(address == 0x1fe7) {
|
} else if(address == 0x1fe7) {
|
||||||
rom_ptr_[0] = nullptr;
|
rom_ptr_[0] = nullptr;
|
||||||
} else if(address >= 0x1ff8 && address <= 0x1ffb) {
|
} else if(address >= 0x1ff8 && address <= 0x1ffb) {
|
||||||
@ -54,7 +55,6 @@ class CartridgeMNetwork: public Cartridge<CartridgeMNetwork> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -63,6 +63,7 @@ class CartridgeMNetwork: public Cartridge<CartridgeMNetwork> {
|
|||||||
uint8_t low_ram_[1024], high_ram_[1024];
|
uint8_t low_ram_[1024], high_ram_[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_CartridgeMNetwork_hpp */
|
#endif /* Atari2600_CartridgeMNetwork_hpp */
|
@ -12,13 +12,14 @@
|
|||||||
#include "Cartridge.hpp"
|
#include "Cartridge.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
class CartridgeMegaBoy: public Cartridge<CartridgeMegaBoy> {
|
class MegaBoy: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeMegaBoy(const std::vector<uint8_t> &rom) :
|
MegaBoy(uint8_t *rom_base, size_t rom_size) :
|
||||||
Cartridge(rom),
|
BusExtender(rom_base, rom_size),
|
||||||
|
rom_ptr_(rom_base),
|
||||||
current_page_(0) {
|
current_page_(0) {
|
||||||
rom_ptr_ = rom_.data();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
@ -27,7 +28,7 @@ class CartridgeMegaBoy: public Cartridge<CartridgeMegaBoy> {
|
|||||||
|
|
||||||
if(address == 0x1ff0) {
|
if(address == 0x1ff0) {
|
||||||
current_page_ = (current_page_ + 1) & 15;
|
current_page_ = (current_page_ + 1) & 15;
|
||||||
rom_ptr_ = rom_.data() + current_page_ * 4096;
|
rom_ptr_ = rom_base_ + current_page_ * 4096;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
@ -40,6 +41,7 @@ class CartridgeMegaBoy: public Cartridge<CartridgeMegaBoy> {
|
|||||||
uint8_t current_page_;
|
uint8_t current_page_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CartridgeMegaBoy_h */
|
#endif /* CartridgeMegaBoy_h */
|
@ -12,12 +12,13 @@
|
|||||||
#include "Cartridge.hpp"
|
#include "Cartridge.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
class CartridgeParkerBros: public Cartridge<CartridgeParkerBros> {
|
class ParkerBros: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeParkerBros(const std::vector<uint8_t> &rom) :
|
ParkerBros(uint8_t *rom_base, size_t rom_size) :
|
||||||
Cartridge(rom) {
|
BusExtender(rom_base, rom_size) {
|
||||||
rom_ptr_[0] = rom_.data() + 4096;
|
rom_ptr_[0] = rom_base + 4096;
|
||||||
rom_ptr_[1] = rom_ptr_[0] + 1024;
|
rom_ptr_[1] = rom_ptr_[0] + 1024;
|
||||||
rom_ptr_[2] = rom_ptr_[1] + 1024;
|
rom_ptr_[2] = rom_ptr_[1] + 1024;
|
||||||
rom_ptr_[3] = rom_ptr_[2] + 1024;
|
rom_ptr_[3] = rom_ptr_[2] + 1024;
|
||||||
@ -29,7 +30,7 @@ class CartridgeParkerBros: public Cartridge<CartridgeParkerBros> {
|
|||||||
|
|
||||||
if(address >= 0x1fe0 && address < 0x1ff8) {
|
if(address >= 0x1fe0 && address < 0x1ff8) {
|
||||||
int slot = (address >> 3)&3;
|
int slot = (address >> 3)&3;
|
||||||
rom_ptr_[slot] = rom_.data() + ((address & 7) * 1024);
|
rom_ptr_[slot] = rom_base_ + ((address & 7) * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
@ -41,6 +42,7 @@ class CartridgeParkerBros: public Cartridge<CartridgeParkerBros> {
|
|||||||
uint8_t *rom_ptr_[4];
|
uint8_t *rom_ptr_[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_CartridgeParkerBros_hpp */
|
#endif /* Atari2600_CartridgeParkerBros_hpp */
|
@ -10,17 +10,17 @@
|
|||||||
#define Atari2600_CartridgePitfall2_hpp
|
#define Atari2600_CartridgePitfall2_hpp
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
class CartridgePitfall2: public Cartridge<CartridgePitfall2> {
|
class Pitfall2: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgePitfall2(const std::vector<uint8_t> &rom) :
|
Pitfall2(uint8_t *rom_base, size_t rom_size) :
|
||||||
Cartridge(rom),
|
BusExtender(rom_base, rom_size),
|
||||||
|
rom_ptr_(rom_base),
|
||||||
random_number_generator_(0),
|
random_number_generator_(0),
|
||||||
featcher_address_{0, 0, 0, 0, 0, 0, 0, 0},
|
featcher_address_{0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
mask_{0, 0, 0, 0, 0, 0, 0, 0},
|
mask_{0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
cycles_since_audio_update_(0) {
|
cycles_since_audio_update_(0) {}
|
||||||
rom_ptr_ = rom_.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
void advance_cycles(int cycles) {
|
void advance_cycles(int cycles) {
|
||||||
cycles_since_audio_update_ += cycles;
|
cycles_since_audio_update_ += cycles;
|
||||||
@ -53,11 +53,11 @@ class CartridgePitfall2: public Cartridge<CartridgePitfall2> {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1008: case 0x1009: case 0x100a: case 0x100b: case 0x100c: case 0x100d: case 0x100e: case 0x100f:
|
case 0x1008: case 0x1009: case 0x100a: case 0x100b: case 0x100c: case 0x100d: case 0x100e: case 0x100f:
|
||||||
*value = rom_[8192 + address_for_counter(address & 7)];
|
*value = rom_base_[8192 + address_for_counter(address & 7)];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1010: case 0x1011: case 0x1012: case 0x1013: case 0x1014: case 0x1015: case 0x1016: case 0x1017:
|
case 0x1010: case 0x1011: case 0x1012: case 0x1013: case 0x1014: case 0x1015: case 0x1016: case 0x1017:
|
||||||
*value = rom_[8192 + address_for_counter(address & 7)] & mask_[address & 7];
|
*value = rom_base_[8192 + address_for_counter(address & 7)] & mask_[address & 7];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#pragma mark - Writes
|
#pragma mark - Writes
|
||||||
@ -81,8 +81,8 @@ class CartridgePitfall2: public Cartridge<CartridgePitfall2> {
|
|||||||
|
|
||||||
#pragma mark - Paging
|
#pragma mark - Paging
|
||||||
|
|
||||||
case 0x1ff8: rom_ptr_ = rom_.data(); break;
|
case 0x1ff8: rom_ptr_ = rom_base_; break;
|
||||||
case 0x1ff9: rom_ptr_ = rom_.data() + 4096; break;
|
case 0x1ff9: rom_ptr_ = rom_base_ + 4096; break;
|
||||||
|
|
||||||
#pragma mark - Business as usual
|
#pragma mark - Business as usual
|
||||||
|
|
||||||
@ -128,6 +128,7 @@ class CartridgePitfall2: public Cartridge<CartridgePitfall2> {
|
|||||||
Cycles cycles_since_audio_update_;
|
Cycles cycles_since_audio_update_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_CartridgePitfall2_hpp */
|
#endif /* Atari2600_CartridgePitfall2_hpp */
|
@ -12,19 +12,20 @@
|
|||||||
#include "Cartridge.hpp"
|
#include "Cartridge.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
class CartridgeTigervision: public Cartridge<CartridgeTigervision> {
|
class Tigervision: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeTigervision(const std::vector<uint8_t> &rom) :
|
Tigervision(uint8_t *rom_base, size_t rom_size) :
|
||||||
Cartridge(rom) {
|
BusExtender(rom_base, rom_size) {
|
||||||
rom_ptr_[0] = rom_.data() + rom_.size() - 4096;
|
rom_ptr_[0] = rom_base + rom_size - 4096;
|
||||||
rom_ptr_[1] = rom_ptr_[0] + 2048;
|
rom_ptr_[1] = rom_ptr_[0] + 2048;
|
||||||
}
|
}
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
if((address&0x1fff) == 0x3f) {
|
if((address&0x1fff) == 0x3f) {
|
||||||
int offset = ((*value) * 2048) & (rom_.size() - 1);
|
int offset = ((*value) * 2048) & (rom_size_ - 1);
|
||||||
rom_ptr_[0] = rom_.data() + offset;
|
rom_ptr_[0] = rom_base_ + offset;
|
||||||
return;
|
return;
|
||||||
} else if((address&0x1000) && isReadOperation(operation)) {
|
} else if((address&0x1000) && isReadOperation(operation)) {
|
||||||
*value = rom_ptr_[(address >> 11)&1][address & 2047];
|
*value = rom_ptr_[(address >> 11)&1][address & 2047];
|
||||||
@ -35,6 +36,7 @@ class CartridgeTigervision: public Cartridge<CartridgeTigervision> {
|
|||||||
uint8_t *rom_ptr_[2];
|
uint8_t *rom_ptr_[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_CartridgeTigervision_hpp */
|
#endif /* Atari2600_CartridgeTigervision_hpp */
|
@ -12,19 +12,20 @@
|
|||||||
#include "Cartridge.hpp"
|
#include "Cartridge.hpp"
|
||||||
|
|
||||||
namespace Atari2600 {
|
namespace Atari2600 {
|
||||||
|
namespace Cartridge {
|
||||||
|
|
||||||
class CartridgeUnpaged: public Cartridge<CartridgeUnpaged> {
|
class Unpaged: public BusExtender {
|
||||||
public:
|
public:
|
||||||
CartridgeUnpaged(const std::vector<uint8_t> &rom) :
|
Unpaged(uint8_t *rom_base, size_t rom_size) : BusExtender(rom_base, rom_size) {}
|
||||||
Cartridge(rom) {}
|
|
||||||
|
|
||||||
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
void perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
if(isReadOperation(operation) && (address & 0x1000)) {
|
if(isReadOperation(operation) && (address & 0x1000)) {
|
||||||
*value = rom_[address & (rom_.size() - 1)];
|
*value = rom_base_[address & (rom_size_ - 1)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Atari2600_CartridgeUnpaged_hpp */
|
#endif /* Atari2600_CartridgeUnpaged_hpp */
|
@ -13,6 +13,7 @@
|
|||||||
using namespace Commodore::C1540;
|
using namespace Commodore::C1540;
|
||||||
|
|
||||||
Machine::Machine() :
|
Machine::Machine() :
|
||||||
|
m6502_(*this),
|
||||||
shift_register_(0),
|
shift_register_(0),
|
||||||
Storage::Disk::Controller(1000000, 4, 300),
|
Storage::Disk::Controller(1000000, 4, 300),
|
||||||
serial_port_(new SerialPort),
|
serial_port_(new SerialPort),
|
||||||
@ -80,7 +81,7 @@ void Machine::set_disk(std::shared_ptr<Storage::Disk::Disk> disk) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Machine::run_for(const Cycles cycles) {
|
void Machine::run_for(const Cycles cycles) {
|
||||||
CPU::MOS6502::Processor<Machine>::run_for(cycles);
|
m6502_.run_for(cycles);
|
||||||
set_motor_on(drive_VIA_.get_motor_enabled());
|
set_motor_on(drive_VIA_.get_motor_enabled());
|
||||||
if(drive_VIA_.get_motor_enabled()) // TODO: motor speed up/down
|
if(drive_VIA_.get_motor_enabled()) // TODO: motor speed up/down
|
||||||
Storage::Disk::Controller::run_for(cycles);
|
Storage::Disk::Controller::run_for(cycles);
|
||||||
@ -90,7 +91,7 @@ void Machine::run_for(const Cycles cycles) {
|
|||||||
|
|
||||||
void Machine::mos6522_did_change_interrupt_status(void *mos6522) {
|
void Machine::mos6522_did_change_interrupt_status(void *mos6522) {
|
||||||
// both VIAs are connected to the IRQ line
|
// both VIAs are connected to the IRQ line
|
||||||
set_irq_line(serial_port_VIA_->get_interrupt_line() || drive_VIA_.get_interrupt_line());
|
m6502_.set_irq_line(serial_port_VIA_->get_interrupt_line() || drive_VIA_.get_interrupt_line());
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Disk drive
|
#pragma mark - Disk drive
|
||||||
@ -108,10 +109,10 @@ void Machine::process_input_bit(int value, unsigned int cycles_since_index_hole)
|
|||||||
drive_VIA_.set_data_input((uint8_t)shift_register_);
|
drive_VIA_.set_data_input((uint8_t)shift_register_);
|
||||||
bit_window_offset_ = 0;
|
bit_window_offset_ = 0;
|
||||||
if(drive_VIA_.get_should_set_overflow()) {
|
if(drive_VIA_.get_should_set_overflow()) {
|
||||||
set_overflow_line(true);
|
m6502_.set_overflow_line(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else set_overflow_line(false);
|
else m6502_.set_overflow_line(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the 1540 does not recognise index holes
|
// the 1540 does not recognise index holes
|
||||||
|
@ -120,7 +120,7 @@ class SerialPort : public ::Commodore::Serial::Port {
|
|||||||
Provides an emulation of the C1540.
|
Provides an emulation of the C1540.
|
||||||
*/
|
*/
|
||||||
class Machine:
|
class Machine:
|
||||||
public CPU::MOS6502::Processor<Machine>,
|
public CPU::MOS6502::BusHandler,
|
||||||
public MOS::MOS6522IRQDelegate::Delegate,
|
public MOS::MOS6522IRQDelegate::Delegate,
|
||||||
public DriveVIA::Delegate,
|
public DriveVIA::Delegate,
|
||||||
public Storage::Disk::Controller {
|
public Storage::Disk::Controller {
|
||||||
@ -152,6 +152,8 @@ class Machine:
|
|||||||
void drive_via_did_set_data_density(void *driveVIA, int density);
|
void drive_via_did_set_data_density(void *driveVIA, int density);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CPU::MOS6502::Processor<Machine> m6502_;
|
||||||
|
|
||||||
uint8_t ram_[0x800];
|
uint8_t ram_[0x800];
|
||||||
uint8_t rom_[0x4000];
|
uint8_t rom_[0x4000];
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
using namespace Commodore::Vic20;
|
using namespace Commodore::Vic20;
|
||||||
|
|
||||||
Machine::Machine() :
|
Machine::Machine() :
|
||||||
|
m6502_(*this),
|
||||||
rom_(nullptr),
|
rom_(nullptr),
|
||||||
is_running_at_zero_cost_(false),
|
is_running_at_zero_cost_(false),
|
||||||
tape_(new Storage::Tape::BinaryTapePlayer(1022727)),
|
tape_(new Storage::Tape::BinaryTapePlayer(1022727)),
|
||||||
@ -138,7 +139,7 @@ Cycles Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation, uint
|
|||||||
|
|
||||||
*value = 0x0c; // i.e. NOP abs
|
*value = 0x0c; // i.e. NOP abs
|
||||||
} else if(address == 0xf90b) {
|
} else if(address == 0xf90b) {
|
||||||
uint8_t x = (uint8_t)get_value_of_register(CPU::MOS6502::Register::X);
|
uint8_t x = (uint8_t)m6502_.get_value_of_register(CPU::MOS6502::Register::X);
|
||||||
if(x == 0xe) {
|
if(x == 0xe) {
|
||||||
Storage::Tape::Commodore::Parser parser;
|
Storage::Tape::Commodore::Parser parser;
|
||||||
std::unique_ptr<Storage::Tape::Commodore::Data> data = parser.get_next_data(tape_->get_tape());
|
std::unique_ptr<Storage::Tape::Commodore::Data> data = parser.get_next_data(tape_->get_tape());
|
||||||
@ -159,13 +160,13 @@ Cycles Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation, uint
|
|||||||
|
|
||||||
// set tape status, carry and flag
|
// set tape status, carry and flag
|
||||||
user_basic_memory_[0x90] |= 0x40;
|
user_basic_memory_[0x90] |= 0x40;
|
||||||
uint8_t flags = (uint8_t)get_value_of_register(CPU::MOS6502::Register::Flags);
|
uint8_t flags = (uint8_t)m6502_.get_value_of_register(CPU::MOS6502::Register::Flags);
|
||||||
flags &= ~(uint8_t)(CPU::MOS6502::Flag::Carry | CPU::MOS6502::Flag::Interrupt);
|
flags &= ~(uint8_t)(CPU::MOS6502::Flag::Carry | CPU::MOS6502::Flag::Interrupt);
|
||||||
set_value_of_register(CPU::MOS6502::Register::Flags, flags);
|
m6502_.set_value_of_register(CPU::MOS6502::Register::Flags, flags);
|
||||||
|
|
||||||
// to ensure that execution proceeds to 0xfccf, pretend a NOP was here and
|
// to ensure that execution proceeds to 0xfccf, pretend a NOP was here and
|
||||||
// ensure that the PC leaps to 0xfccf
|
// ensure that the PC leaps to 0xfccf
|
||||||
set_value_of_register(CPU::MOS6502::Register::ProgramCounter, 0xfccf);
|
m6502_.set_value_of_register(CPU::MOS6502::Register::ProgramCounter, 0xfccf);
|
||||||
*value = 0xea; // i.e. NOP implied
|
*value = 0xea; // i.e. NOP implied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,11 +195,15 @@ Cycles Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation, uint
|
|||||||
return Cycles(1);
|
return Cycles(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Machine::run_for(const Cycles cycles) {
|
||||||
|
m6502_.run_for(cycles);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - 6522 delegate
|
#pragma mark - 6522 delegate
|
||||||
|
|
||||||
void Machine::mos6522_did_change_interrupt_status(void *mos6522) {
|
void Machine::mos6522_did_change_interrupt_status(void *mos6522) {
|
||||||
set_nmi_line(user_port_via_->get_interrupt_line());
|
m6502_.set_nmi_line(user_port_via_->get_interrupt_line());
|
||||||
set_irq_line(keyboard_via_->get_interrupt_line());
|
m6502_.set_irq_line(keyboard_via_->get_interrupt_line());
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Setup
|
#pragma mark - Setup
|
||||||
|
@ -139,7 +139,7 @@ class Vic6560: public MOS::MOS6560<Vic6560> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Machine:
|
class Machine:
|
||||||
public CPU::MOS6502::Processor<Machine>,
|
public CPU::MOS6502::BusHandler,
|
||||||
public CRTMachine::Machine,
|
public CRTMachine::Machine,
|
||||||
public MOS::MOS6522IRQDelegate::Delegate,
|
public MOS::MOS6522IRQDelegate::Delegate,
|
||||||
public Utility::TypeRecipient,
|
public Utility::TypeRecipient,
|
||||||
@ -174,7 +174,7 @@ class Machine:
|
|||||||
virtual void close_output();
|
virtual void close_output();
|
||||||
virtual std::shared_ptr<Outputs::CRT::CRT> get_crt() { return mos6560_->get_crt(); }
|
virtual std::shared_ptr<Outputs::CRT::CRT> get_crt() { return mos6560_->get_crt(); }
|
||||||
virtual std::shared_ptr<Outputs::Speaker> get_speaker() { return mos6560_->get_speaker(); }
|
virtual std::shared_ptr<Outputs::Speaker> get_speaker() { return mos6560_->get_speaker(); }
|
||||||
virtual void run_for(const Cycles cycles) { CPU::MOS6502::Processor<Machine>::run_for(cycles); }
|
virtual void run_for(const Cycles cycles);
|
||||||
|
|
||||||
// to satisfy MOS::MOS6522::Delegate
|
// to satisfy MOS::MOS6522::Delegate
|
||||||
virtual void mos6522_did_change_interrupt_status(void *mos6522);
|
virtual void mos6522_did_change_interrupt_status(void *mos6522);
|
||||||
@ -187,6 +187,8 @@ class Machine:
|
|||||||
virtual void tape_did_change_input(Storage::Tape::BinaryTapePlayer *tape);
|
virtual void tape_did_change_input(Storage::Tape::BinaryTapePlayer *tape);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CPU::MOS6502::Processor<Machine> m6502_;
|
||||||
|
|
||||||
uint8_t character_rom_[0x1000];
|
uint8_t character_rom_[0x1000];
|
||||||
uint8_t basic_rom_[0x2000];
|
uint8_t basic_rom_[0x2000];
|
||||||
uint8_t kernel_rom_[0x2000];
|
uint8_t kernel_rom_[0x2000];
|
||||||
|
@ -15,6 +15,7 @@ using namespace Electron;
|
|||||||
#pragma mark - Lifecycle
|
#pragma mark - Lifecycle
|
||||||
|
|
||||||
Machine::Machine() :
|
Machine::Machine() :
|
||||||
|
m6502_(*this),
|
||||||
interrupt_control_(0),
|
interrupt_control_(0),
|
||||||
interrupt_status_(Interrupt::PowerOnReset | Interrupt::TransmitDataEmpty | 0x80),
|
interrupt_status_(Interrupt::PowerOnReset | Interrupt::TransmitDataEmpty | 0x80),
|
||||||
cycles_since_audio_update_(0),
|
cycles_since_audio_update_(0),
|
||||||
@ -61,7 +62,7 @@ void Machine::clear_all_keys() {
|
|||||||
|
|
||||||
void Machine::set_key_state(uint16_t key, bool isPressed) {
|
void Machine::set_key_state(uint16_t key, bool isPressed) {
|
||||||
if(key == KeyBreak) {
|
if(key == KeyBreak) {
|
||||||
set_reset_line(isPressed);
|
m6502_.set_reset_line(isPressed);
|
||||||
} else {
|
} else {
|
||||||
if(isPressed)
|
if(isPressed)
|
||||||
key_states_[key >> 4] |= key&0xf;
|
key_states_[key >> 4] |= key&0xf;
|
||||||
@ -269,7 +270,7 @@ Cycles Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation, uint
|
|||||||
// allow the PC read to return an RTS.
|
// allow the PC read to return an RTS.
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
uint8_t service_call = (uint8_t)get_value_of_register(CPU::MOS6502::Register::X);
|
uint8_t service_call = (uint8_t)m6502_.get_value_of_register(CPU::MOS6502::Register::X);
|
||||||
if(address == 0xf0a8) {
|
if(address == 0xf0a8) {
|
||||||
if(!ram_[0x247] && service_call == 14) {
|
if(!ram_[0x247] && service_call == 14) {
|
||||||
tape_.set_delegate(nullptr);
|
tape_.set_delegate(nullptr);
|
||||||
@ -291,8 +292,8 @@ Cycles Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation, uint
|
|||||||
interrupt_status_ |= tape_.get_interrupt_status();
|
interrupt_status_ |= tape_.get_interrupt_status();
|
||||||
|
|
||||||
fast_load_is_in_data_ = true;
|
fast_load_is_in_data_ = true;
|
||||||
set_value_of_register(CPU::MOS6502::Register::A, 0);
|
m6502_.set_value_of_register(CPU::MOS6502::Register::A, 0);
|
||||||
set_value_of_register(CPU::MOS6502::Register::Y, tape_.get_data_register());
|
m6502_.set_value_of_register(CPU::MOS6502::Register::Y, tape_.get_data_register());
|
||||||
*value = 0x60; // 0x60 is RTS
|
*value = 0x60; // 0x60 is RTS
|
||||||
}
|
}
|
||||||
else *value = os_[address & 16383];
|
else *value = os_[address & 16383];
|
||||||
@ -340,7 +341,7 @@ Cycles Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation, uint
|
|||||||
shift_restart_counter_ -= cycles;
|
shift_restart_counter_ -= cycles;
|
||||||
if(shift_restart_counter_ <= 0) {
|
if(shift_restart_counter_ <= 0) {
|
||||||
shift_restart_counter_ = 0;
|
shift_restart_counter_ = 0;
|
||||||
set_power_on(true);
|
m6502_.set_power_on(true);
|
||||||
set_key_state(KeyShift, true);
|
set_key_state(KeyShift, true);
|
||||||
is_holding_shift_ = true;
|
is_holding_shift_ = true;
|
||||||
}
|
}
|
||||||
@ -355,6 +356,10 @@ void Machine::flush() {
|
|||||||
speaker_->flush();
|
speaker_->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Machine::run_for(const Cycles cycles) {
|
||||||
|
m6502_.run_for(cycles);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Deferred scheduling
|
#pragma mark - Deferred scheduling
|
||||||
|
|
||||||
inline void Machine::update_display() {
|
inline void Machine::update_display() {
|
||||||
@ -393,7 +398,7 @@ inline void Machine::evaluate_interrupts() {
|
|||||||
} else {
|
} else {
|
||||||
interrupt_status_ &= ~1;
|
interrupt_status_ &= ~1;
|
||||||
}
|
}
|
||||||
set_irq_line(interrupt_status_ & 1);
|
m6502_.set_irq_line(interrupt_status_ & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Tape::Delegate
|
#pragma mark - Tape::Delegate
|
||||||
@ -406,7 +411,7 @@ void Machine::tape_did_change_interrupt_status(Tape *tape) {
|
|||||||
#pragma mark - Typer timing
|
#pragma mark - Typer timing
|
||||||
|
|
||||||
HalfCycles Electron::Machine::get_typer_delay() {
|
HalfCycles Electron::Machine::get_typer_delay() {
|
||||||
return get_is_resetting() ? Cycles(625*25*128) : Cycles(0); // wait one second if resetting
|
return m6502_.get_is_resetting() ? Cycles(625*25*128) : Cycles(0); // wait one second if resetting
|
||||||
}
|
}
|
||||||
|
|
||||||
HalfCycles Electron::Machine::get_typer_frequency() {
|
HalfCycles Electron::Machine::get_typer_frequency() {
|
||||||
|
@ -67,7 +67,7 @@ enum Key: uint16_t {
|
|||||||
Acorn Electron.
|
Acorn Electron.
|
||||||
*/
|
*/
|
||||||
class Machine:
|
class Machine:
|
||||||
public CPU::MOS6502::Processor<Machine>,
|
public CPU::MOS6502::BusHandler,
|
||||||
public CRTMachine::Machine,
|
public CRTMachine::Machine,
|
||||||
public Tape::Delegate,
|
public Tape::Delegate,
|
||||||
public Utility::TypeRecipient,
|
public Utility::TypeRecipient,
|
||||||
@ -95,7 +95,7 @@ class Machine:
|
|||||||
virtual void close_output();
|
virtual void close_output();
|
||||||
virtual std::shared_ptr<Outputs::CRT::CRT> get_crt();
|
virtual std::shared_ptr<Outputs::CRT::CRT> get_crt();
|
||||||
virtual std::shared_ptr<Outputs::Speaker> get_speaker();
|
virtual std::shared_ptr<Outputs::Speaker> get_speaker();
|
||||||
virtual void run_for(const Cycles cycles) { CPU::MOS6502::Processor<Machine>::run_for(cycles); }
|
virtual void run_for(const Cycles cycles);
|
||||||
|
|
||||||
// to satisfy Tape::Delegate
|
// to satisfy Tape::Delegate
|
||||||
virtual void tape_did_change_interrupt_status(Tape *tape);
|
virtual void tape_did_change_interrupt_status(Tape *tape);
|
||||||
@ -114,6 +114,8 @@ class Machine:
|
|||||||
inline void clear_interrupt(Interrupt interrupt);
|
inline void clear_interrupt(Interrupt interrupt);
|
||||||
inline void evaluate_interrupts();
|
inline void evaluate_interrupts();
|
||||||
|
|
||||||
|
CPU::MOS6502::Processor<Machine> m6502_;
|
||||||
|
|
||||||
// Things that directly constitute the memory map.
|
// Things that directly constitute the memory map.
|
||||||
uint8_t roms_[16][16384];
|
uint8_t roms_[16][16384];
|
||||||
bool rom_write_masks_[16];
|
bool rom_write_masks_[16];
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
using namespace Oric;
|
using namespace Oric;
|
||||||
|
|
||||||
Machine::Machine() :
|
Machine::Machine() :
|
||||||
|
m6502_(*this),
|
||||||
use_fast_tape_hack_(false),
|
use_fast_tape_hack_(false),
|
||||||
typer_delay_(2500000),
|
typer_delay_(2500000),
|
||||||
keyboard_read_count_(0),
|
keyboard_read_count_(0),
|
||||||
@ -94,8 +95,8 @@ Cycles Machine::perform_bus_operation(CPU::MOS6502::BusOperation operation, uint
|
|||||||
// E6C9 = read byte: return byte in A
|
// E6C9 = read byte: return byte in A
|
||||||
if(address == tape_get_byte_address_ && paged_rom_ == rom_ && use_fast_tape_hack_ && operation == CPU::MOS6502::BusOperation::ReadOpcode && via_.tape->has_tape() && !via_.tape->get_tape()->is_at_end()) {
|
if(address == tape_get_byte_address_ && paged_rom_ == rom_ && use_fast_tape_hack_ && operation == CPU::MOS6502::BusOperation::ReadOpcode && via_.tape->has_tape() && !via_.tape->get_tape()->is_at_end()) {
|
||||||
uint8_t next_byte = via_.tape->get_next_byte(!ram_[tape_speed_address_]);
|
uint8_t next_byte = via_.tape->get_next_byte(!ram_[tape_speed_address_]);
|
||||||
set_value_of_register(CPU::MOS6502::A, next_byte);
|
m6502_.set_value_of_register(CPU::MOS6502::A, next_byte);
|
||||||
set_value_of_register(CPU::MOS6502::Flags, next_byte ? 0 : CPU::MOS6502::Flag::Zero);
|
m6502_.set_value_of_register(CPU::MOS6502::Flags, next_byte ? 0 : CPU::MOS6502::Flag::Zero);
|
||||||
*value = 0x60; // i.e. RTS
|
*value = 0x60; // i.e. RTS
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -171,7 +172,7 @@ void Machine::mos6522_did_change_interrupt_status(void *mos6522) {
|
|||||||
|
|
||||||
void Machine::set_key_state(uint16_t key, bool isPressed) {
|
void Machine::set_key_state(uint16_t key, bool isPressed) {
|
||||||
if(key == KeyNMI) {
|
if(key == KeyNMI) {
|
||||||
set_nmi_line(isPressed);
|
m6502_.set_nmi_line(isPressed);
|
||||||
} else {
|
} else {
|
||||||
if(isPressed)
|
if(isPressed)
|
||||||
keyboard_->rows[key >> 8] |= (key & 0xff);
|
keyboard_->rows[key >> 8] |= (key & 0xff);
|
||||||
@ -206,7 +207,7 @@ std::shared_ptr<Outputs::Speaker> Machine::get_speaker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Machine::run_for(const Cycles cycles) {
|
void Machine::run_for(const Cycles cycles) {
|
||||||
CPU::MOS6502::Processor<Machine>::run_for(cycles);
|
m6502_.run_for(cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - The 6522
|
#pragma mark - The 6522
|
||||||
@ -287,7 +288,7 @@ void Machine::wd1770_did_change_output(WD::WD1770 *wd1770) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Machine::set_interrupt_line() {
|
void Machine::set_interrupt_line() {
|
||||||
set_irq_line(
|
m6502_.set_irq_line(
|
||||||
via_.get_interrupt_line() ||
|
via_.get_interrupt_line() ||
|
||||||
(microdisc_is_enabled_ && microdisc_.get_interrupt_request_line()));
|
(microdisc_is_enabled_ && microdisc_.get_interrupt_request_line()));
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ enum ROM {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Machine:
|
class Machine:
|
||||||
public CPU::MOS6502::Processor<Machine>,
|
public CPU::MOS6502::BusHandler,
|
||||||
public CRTMachine::Machine,
|
public CRTMachine::Machine,
|
||||||
public ConfigurationTarget::Machine,
|
public ConfigurationTarget::Machine,
|
||||||
public MOS::MOS6522IRQDelegate::Delegate,
|
public MOS::MOS6522IRQDelegate::Delegate,
|
||||||
@ -101,6 +101,8 @@ class Machine:
|
|||||||
void wd1770_did_change_output(WD::WD1770 *wd1770);
|
void wd1770_did_change_output(WD::WD1770 *wd1770);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CPU::MOS6502::Processor<Machine> m6502_;
|
||||||
|
|
||||||
// RAM and ROM
|
// RAM and ROM
|
||||||
std::vector<uint8_t> basic11_rom_, basic10_rom_, microdisc_rom_, colour_rom_;
|
std::vector<uint8_t> basic11_rom_, basic10_rom_, microdisc_rom_, colour_rom_;
|
||||||
uint8_t ram_[65536], rom_[16384];
|
uint8_t ram_[65536], rom_[16384];
|
||||||
|
@ -1036,19 +1036,19 @@
|
|||||||
4BEA52651DF3472B007E74F2 /* Speaker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Speaker.hpp; sourceTree = "<group>"; };
|
4BEA52651DF3472B007E74F2 /* Speaker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Speaker.hpp; sourceTree = "<group>"; };
|
||||||
4BEA52671DF34909007E74F2 /* PIA.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PIA.hpp; sourceTree = "<group>"; };
|
4BEA52671DF34909007E74F2 /* PIA.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PIA.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC0811E7E0DF800EE56B2 /* Cartridge.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Cartridge.hpp; sourceTree = "<group>"; };
|
4BEAC0811E7E0DF800EE56B2 /* Cartridge.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Cartridge.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC0821E7E0DF800EE56B2 /* CartridgeActivisionStack.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartridgeActivisionStack.hpp; sourceTree = "<group>"; };
|
4BEAC0821E7E0DF800EE56B2 /* ActivisionStack.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ActivisionStack.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC0831E7E0DF800EE56B2 /* CartridgeAtari16k.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartridgeAtari16k.hpp; sourceTree = "<group>"; };
|
4BEAC0831E7E0DF800EE56B2 /* Atari16k.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Atari16k.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC0841E7E0DF800EE56B2 /* CartridgeAtari32k.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartridgeAtari32k.hpp; sourceTree = "<group>"; };
|
4BEAC0841E7E0DF800EE56B2 /* Atari32k.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Atari32k.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC0851E7E0DF800EE56B2 /* CartridgeAtari8k.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartridgeAtari8k.hpp; sourceTree = "<group>"; };
|
4BEAC0851E7E0DF800EE56B2 /* Atari8k.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Atari8k.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC0861E7E0DF800EE56B2 /* CartridgeCBSRAMPlus.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartridgeCBSRAMPlus.hpp; sourceTree = "<group>"; };
|
4BEAC0861E7E0DF800EE56B2 /* CBSRAMPlus.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CBSRAMPlus.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC0871E7E0DF800EE56B2 /* CartridgeCommaVid.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartridgeCommaVid.hpp; sourceTree = "<group>"; };
|
4BEAC0871E7E0DF800EE56B2 /* CommaVid.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CommaVid.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC0881E7E0DF800EE56B2 /* CartridgeMegaBoy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartridgeMegaBoy.hpp; sourceTree = "<group>"; };
|
4BEAC0881E7E0DF800EE56B2 /* MegaBoy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MegaBoy.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC0891E7E0DF800EE56B2 /* CartridgeMNetwork.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartridgeMNetwork.hpp; sourceTree = "<group>"; };
|
4BEAC0891E7E0DF800EE56B2 /* MNetwork.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MNetwork.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC08A1E7E0DF800EE56B2 /* CartridgeParkerBros.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartridgeParkerBros.hpp; sourceTree = "<group>"; };
|
4BEAC08A1E7E0DF800EE56B2 /* ParkerBros.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ParkerBros.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC08B1E7E0DF800EE56B2 /* CartridgeTigervision.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartridgeTigervision.hpp; sourceTree = "<group>"; };
|
4BEAC08B1E7E0DF800EE56B2 /* Tigervision.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Tigervision.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC08C1E7E0DF800EE56B2 /* CartridgeUnpaged.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartridgeUnpaged.hpp; sourceTree = "<group>"; };
|
4BEAC08C1E7E0DF800EE56B2 /* Unpaged.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Unpaged.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC08D1E7E0E1A00EE56B2 /* Bus.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Bus.hpp; sourceTree = "<group>"; };
|
4BEAC08D1E7E0E1A00EE56B2 /* Bus.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Bus.hpp; sourceTree = "<group>"; };
|
||||||
4BEAC08E1E7E110500EE56B2 /* CartridgePitfall2.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CartridgePitfall2.hpp; sourceTree = "<group>"; };
|
4BEAC08E1E7E110500EE56B2 /* Pitfall2.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Pitfall2.hpp; sourceTree = "<group>"; };
|
||||||
4BEE0A6A1D72496600532C7B /* Cartridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Cartridge.cpp; sourceTree = "<group>"; };
|
4BEE0A6A1D72496600532C7B /* Cartridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Cartridge.cpp; sourceTree = "<group>"; };
|
||||||
4BEE0A6B1D72496600532C7B /* Cartridge.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Cartridge.hpp; sourceTree = "<group>"; };
|
4BEE0A6B1D72496600532C7B /* Cartridge.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Cartridge.hpp; sourceTree = "<group>"; };
|
||||||
4BEE0A6D1D72496600532C7B /* PRG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PRG.cpp; sourceTree = "<group>"; };
|
4BEE0A6D1D72496600532C7B /* PRG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PRG.cpp; sourceTree = "<group>"; };
|
||||||
@ -2216,18 +2216,18 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4BEAC0811E7E0DF800EE56B2 /* Cartridge.hpp */,
|
4BEAC0811E7E0DF800EE56B2 /* Cartridge.hpp */,
|
||||||
4BEAC0821E7E0DF800EE56B2 /* CartridgeActivisionStack.hpp */,
|
4BEAC0821E7E0DF800EE56B2 /* ActivisionStack.hpp */,
|
||||||
4BEAC0831E7E0DF800EE56B2 /* CartridgeAtari16k.hpp */,
|
4BEAC0851E7E0DF800EE56B2 /* Atari8k.hpp */,
|
||||||
4BEAC0841E7E0DF800EE56B2 /* CartridgeAtari32k.hpp */,
|
4BEAC0831E7E0DF800EE56B2 /* Atari16k.hpp */,
|
||||||
4BEAC0851E7E0DF800EE56B2 /* CartridgeAtari8k.hpp */,
|
4BEAC0841E7E0DF800EE56B2 /* Atari32k.hpp */,
|
||||||
4BEAC0861E7E0DF800EE56B2 /* CartridgeCBSRAMPlus.hpp */,
|
4BEAC0861E7E0DF800EE56B2 /* CBSRAMPlus.hpp */,
|
||||||
4BEAC0871E7E0DF800EE56B2 /* CartridgeCommaVid.hpp */,
|
4BEAC0871E7E0DF800EE56B2 /* CommaVid.hpp */,
|
||||||
4BEAC0881E7E0DF800EE56B2 /* CartridgeMegaBoy.hpp */,
|
4BEAC0881E7E0DF800EE56B2 /* MegaBoy.hpp */,
|
||||||
4BEAC0891E7E0DF800EE56B2 /* CartridgeMNetwork.hpp */,
|
4BEAC0891E7E0DF800EE56B2 /* MNetwork.hpp */,
|
||||||
4BEAC08A1E7E0DF800EE56B2 /* CartridgeParkerBros.hpp */,
|
4BEAC08A1E7E0DF800EE56B2 /* ParkerBros.hpp */,
|
||||||
4BEAC08B1E7E0DF800EE56B2 /* CartridgeTigervision.hpp */,
|
4BEAC08E1E7E110500EE56B2 /* Pitfall2.hpp */,
|
||||||
4BEAC08C1E7E0DF800EE56B2 /* CartridgeUnpaged.hpp */,
|
4BEAC08B1E7E0DF800EE56B2 /* Tigervision.hpp */,
|
||||||
4BEAC08E1E7E110500EE56B2 /* CartridgePitfall2.hpp */,
|
4BEAC08C1E7E0DF800EE56B2 /* Unpaged.hpp */,
|
||||||
);
|
);
|
||||||
path = Cartridges;
|
path = Cartridges;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -117,6 +117,14 @@ class ProcessorBase {
|
|||||||
static const MicroOp operations[256][10];
|
static const MicroOp operations[256][10];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BusHandler {
|
||||||
|
public:
|
||||||
|
void flush() {}
|
||||||
|
Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
|
return Cycles(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@abstact An abstract base class for emulation of a 6502 processor via the curiously recurring template pattern/f-bounded polymorphism.
|
@abstact An abstract base class for emulation of a 6502 processor via the curiously recurring template pattern/f-bounded polymorphism.
|
||||||
|
|
||||||
@ -130,6 +138,7 @@ class ProcessorBase {
|
|||||||
*/
|
*/
|
||||||
template <class T> class Processor: public ProcessorBase {
|
template <class T> class Processor: public ProcessorBase {
|
||||||
private:
|
private:
|
||||||
|
T &bus_handler_;
|
||||||
const MicroOp *scheduled_program_counter_;
|
const MicroOp *scheduled_program_counter_;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -261,8 +270,11 @@ template <class T> class Processor: public ProcessorBase {
|
|||||||
return reset;
|
return reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
public:
|
||||||
Processor() :
|
/*!
|
||||||
|
Constructs an instance of the 6502 that will use @c bus_handler for all bus communications.
|
||||||
|
*/
|
||||||
|
Processor(T &bus_handler) :
|
||||||
is_jammed_(false),
|
is_jammed_(false),
|
||||||
ready_line_is_enabled_(false),
|
ready_line_is_enabled_(false),
|
||||||
ready_is_active_(false),
|
ready_is_active_(false),
|
||||||
@ -274,7 +286,8 @@ template <class T> class Processor: public ProcessorBase {
|
|||||||
irq_line_(0),
|
irq_line_(0),
|
||||||
nmi_line_is_enabled_(false),
|
nmi_line_is_enabled_(false),
|
||||||
set_overflow_line_is_enabled_(false),
|
set_overflow_line_is_enabled_(false),
|
||||||
scheduled_program_counter_(nullptr) {
|
scheduled_program_counter_(nullptr),
|
||||||
|
bus_handler_(bus_handler) {
|
||||||
// only the interrupt flag is defined upon reset but get_flags isn't going to
|
// only the interrupt flag is defined upon reset but get_flags isn't going to
|
||||||
// mask the other flags so we need to do that, at least
|
// mask the other flags so we need to do that, at least
|
||||||
carry_flag_ &= Flag::Carry;
|
carry_flag_ &= Flag::Carry;
|
||||||
@ -282,7 +295,6 @@ template <class T> class Processor: public ProcessorBase {
|
|||||||
overflow_flag_ &= Flag::Overflow;
|
overflow_flag_ &= Flag::Overflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
/*!
|
/*!
|
||||||
Runs the 6502 for a supplied number of cycles.
|
Runs the 6502 for a supplied number of cycles.
|
||||||
|
|
||||||
@ -334,7 +346,7 @@ template <class T> class Processor: public ProcessorBase {
|
|||||||
#define bus_access() \
|
#define bus_access() \
|
||||||
interrupt_requests_ = (interrupt_requests_ & ~InterruptRequestFlags::IRQ) | irq_request_history_; \
|
interrupt_requests_ = (interrupt_requests_ & ~InterruptRequestFlags::IRQ) | irq_request_history_; \
|
||||||
irq_request_history_ = irq_line_ & inverse_interrupt_flag_; \
|
irq_request_history_ = irq_line_ & inverse_interrupt_flag_; \
|
||||||
number_of_cycles -= static_cast<T *>(this)->perform_bus_operation(nextBusOperation, busAddress, busValue); \
|
number_of_cycles -= bus_handler_.perform_bus_operation(nextBusOperation, busAddress, busValue); \
|
||||||
nextBusOperation = BusOperation::None; \
|
nextBusOperation = BusOperation::None; \
|
||||||
if(number_of_cycles <= Cycles(0)) break;
|
if(number_of_cycles <= Cycles(0)) break;
|
||||||
|
|
||||||
@ -344,7 +356,7 @@ template <class T> class Processor: public ProcessorBase {
|
|||||||
while(number_of_cycles > Cycles(0)) {
|
while(number_of_cycles > Cycles(0)) {
|
||||||
|
|
||||||
while (ready_is_active_ && number_of_cycles > Cycles(0)) {
|
while (ready_is_active_ && number_of_cycles > Cycles(0)) {
|
||||||
number_of_cycles -= static_cast<T *>(this)->perform_bus_operation(BusOperation::Ready, busAddress, busValue);
|
number_of_cycles -= bus_handler_.perform_bus_operation(BusOperation::Ready, busAddress, busValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ready_is_active_) {
|
if(!ready_is_active_) {
|
||||||
@ -825,16 +837,9 @@ template <class T> class Processor: public ProcessorBase {
|
|||||||
bus_address_ = busAddress;
|
bus_address_ = busAddress;
|
||||||
bus_value_ = busValue;
|
bus_value_ = busValue;
|
||||||
|
|
||||||
static_cast<T *>(this)->flush();
|
bus_handler_.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
Called to announce the end of a run_for period, allowing deferred work to take place.
|
|
||||||
|
|
||||||
Users of the 6502 template may override this.
|
|
||||||
*/
|
|
||||||
void flush() {}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Gets the value of a register.
|
Gets the value of a register.
|
||||||
|
|
||||||
@ -884,8 +889,8 @@ template <class T> class Processor: public ProcessorBase {
|
|||||||
*/
|
*/
|
||||||
void return_from_subroutine() {
|
void return_from_subroutine() {
|
||||||
s_++;
|
s_++;
|
||||||
static_cast<T *>(this)->perform_bus_operation(MOS6502::BusOperation::Read, 0x100 | s_, &pc_.bytes.low); s_++;
|
bus_handler_.perform_bus_operation(MOS6502::BusOperation::Read, 0x100 | s_, &pc_.bytes.low); s_++;
|
||||||
static_cast<T *>(this)->perform_bus_operation(MOS6502::BusOperation::Read, 0x100 | s_, &pc_.bytes.high);
|
bus_handler_.perform_bus_operation(MOS6502::BusOperation::Read, 0x100 | s_, &pc_.bytes.high);
|
||||||
pc_.full++;
|
pc_.full++;
|
||||||
|
|
||||||
if(is_jammed_) {
|
if(is_jammed_) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user