mirror of
https://github.com/zoriya/ComSquare.git
synced 2026-06-01 09:45:25 +00:00
Finishing to clean tests and adding the start of the bus logger
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Created by anonymus-raccoon on 1/23/20.
|
||||
//
|
||||
|
||||
#include "AMemory.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace ComSquare::Memory
|
||||
{
|
||||
void AMemory::setMemoryRegion(uint24_t start, uint24_t end)
|
||||
{
|
||||
this->_start = start;
|
||||
this->_end = end;
|
||||
}
|
||||
|
||||
bool AMemory::hasMemoryAt(uint24_t addr)
|
||||
{
|
||||
return this->_start <= addr && addr <= this->_end;
|
||||
}
|
||||
|
||||
uint32_t AMemory::getStart()
|
||||
{
|
||||
return this->_start;
|
||||
}
|
||||
|
||||
bool AMemory::isMirror()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<AMemory> AMemory::getMirrored()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string AMemory::getValueName(uint24_t)
|
||||
{
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
// Created by anonymus-raccoon on 1/23/20.
|
||||
//
|
||||
|
||||
#ifndef COMSQUARE_IMEMORY_HPP
|
||||
#define COMSQUARE_IMEMORY_HPP
|
||||
#ifndef COMSQUARE_AMEMORY_HPP
|
||||
#define COMSQUARE_AMEMORY_HPP
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace ComSquare::Memory
|
||||
{
|
||||
//! @brief Common interface implemented by all components mapping memory.
|
||||
class IMemory {
|
||||
class AMemory {
|
||||
private:
|
||||
//! @brief The starting address mapped to this component.
|
||||
uint24_t _start = 0;
|
||||
@@ -34,7 +34,7 @@ namespace ComSquare::Memory
|
||||
//! @brief Change starting and ending points of this mapped memory.
|
||||
//! @param start The first address mapped to this component.
|
||||
//! @param end The last address mapped to this component.
|
||||
//! @warning The start/end address should be a continuous range. You can't map address 0x0 and 0x2 but not 0x1. To do that, use two IMemory.
|
||||
//! @warning The start/end address should be a continuous range. You can't map address 0x0 and 0x2 but not 0x1. To do that, use two AMemory.
|
||||
void setMemoryRegion(uint24_t start, uint24_t end);
|
||||
//! @brief Return true if this component has mapped the address.
|
||||
//! @param addr The address to check.
|
||||
@@ -46,14 +46,17 @@ namespace ComSquare::Memory
|
||||
//! @brief Check if this memory is a mirror or not.
|
||||
//! @return True if this memory is a mirror. False otherwise.
|
||||
virtual bool isMirror();
|
||||
//! @brief Get the name of this accessor (used for debug purpose)
|
||||
virtual std::string getName() = 0;
|
||||
//! @brief Get the name of the data at the address
|
||||
//! @param addr The address (in local space)
|
||||
virtual std::string getValueName(uint24_t addr);
|
||||
//! @brief Return the memory accessor this accessor mirror if any
|
||||
//! @return nullptr if isMirror is false, the source otherwise.
|
||||
virtual std::shared_ptr<IMemory> getMirrored();
|
||||
// TODO add destructors everywhere
|
||||
// TODO rename this as an abstract.
|
||||
virtual ~IMemory() = default;
|
||||
virtual std::shared_ptr<AMemory> getMirrored();
|
||||
virtual ~AMemory() = default;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif //COMSQUARE_IMEMORY_HPP
|
||||
#endif //COMSQUARE_AMEMORY_HPP
|
||||
@@ -3,12 +3,12 @@
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include "IRectangleMemory.hpp"
|
||||
#include "ARectangleMemory.hpp"
|
||||
#include "../Exceptions/InvalidAddress.hpp"
|
||||
|
||||
namespace ComSquare::Memory
|
||||
{
|
||||
uint8_t IRectangleMemory::read(uint24_t addr)
|
||||
uint8_t ARectangleMemory::read(uint24_t addr)
|
||||
{
|
||||
addr += this->getStart();
|
||||
uint8_t bank = addr >> 16u;
|
||||
@@ -25,7 +25,7 @@ namespace ComSquare::Memory
|
||||
return this->read_internal(page);
|
||||
}
|
||||
|
||||
void IRectangleMemory::write(uint24_t addr, uint8_t data)
|
||||
void ARectangleMemory::write(uint24_t addr, uint8_t data)
|
||||
{
|
||||
addr += this->getStart();
|
||||
uint8_t bank = addr >> 16u;
|
||||
@@ -42,7 +42,7 @@ namespace ComSquare::Memory
|
||||
this->write_internal(page, data);
|
||||
}
|
||||
|
||||
bool IRectangleMemory::hasMemoryAt(uint24_t addr)
|
||||
bool ARectangleMemory::hasMemoryAt(uint24_t addr)
|
||||
{
|
||||
uint8_t bank = addr >> 16u;
|
||||
uint16_t page = addr;
|
||||
@@ -53,12 +53,12 @@ namespace ComSquare::Memory
|
||||
return false;
|
||||
}
|
||||
|
||||
uint24_t IRectangleMemory::getStart()
|
||||
uint24_t ARectangleMemory::getStart()
|
||||
{
|
||||
return (this->_startBank << 16u) + this->_startPage;
|
||||
}
|
||||
|
||||
void IRectangleMemory::setMemoryRegion(uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage)
|
||||
void ARectangleMemory::setMemoryRegion(uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage)
|
||||
{
|
||||
this->_startBank = startBank;
|
||||
this->_endBank = endBank;
|
||||
@@ -2,16 +2,16 @@
|
||||
// Created by anonymus-raccoon on 1/29/20.
|
||||
//
|
||||
|
||||
#ifndef COMSQUARE_IRECTANGLEMEMORY_HPP
|
||||
#define COMSQUARE_IRECTANGLEMEMORY_HPP
|
||||
#ifndef COMSQUARE_ARECTANGLEMEMORY_HPP
|
||||
#define COMSQUARE_ARECTANGLEMEMORY_HPP
|
||||
|
||||
|
||||
#include "IMemory.hpp"
|
||||
#include "AMemory.hpp"
|
||||
|
||||
namespace ComSquare::Memory
|
||||
{
|
||||
//! @brief Superset of the IMemory to map non continuous rectangle to the memory. (A rectangle that spam across more than one bank but that does not start at 0000 or end at FFFF).
|
||||
class IRectangleMemory : public IMemory {
|
||||
//! @brief Superset of the AMemory to map non continuous rectangle to the memory. (A rectangle that spam across more than one bank but that does not start at 0000 or end at FFFF).
|
||||
class ARectangleMemory : public AMemory {
|
||||
private:
|
||||
//! @brief The first bank to map to.
|
||||
uint8_t _startBank = 0;
|
||||
@@ -22,22 +22,22 @@ namespace ComSquare::Memory
|
||||
//! @brief The last address of each bank to map.
|
||||
uint16_t _endPage = 0;
|
||||
public:
|
||||
//! @brief Read data from the component using the same method as the basic IMemory.
|
||||
//! @brief Read data from the component using the same method as the basic AMemory.
|
||||
//! @param addr The global 24 bits address. This method is responsible of mapping to the component's read.
|
||||
//! @throw InvalidAddress if the address is not mapped to the component.
|
||||
//! @return Return the data at the address given as parameter.
|
||||
uint8_t read(uint24_t addr) override;
|
||||
//! @brief Write data to this component using the same method as the basic IMemory.
|
||||
//! @brief Write data to this component using the same method as the basic AMemory.
|
||||
//! @param addr The global 24 bits address. This method is responsible of mapping to the component's write.
|
||||
//! @param data The new data to write.
|
||||
//! @throw InvalidAddress if the address is not mapped to the component.
|
||||
void write(uint24_t addr, uint8_t data) override;
|
||||
//! @brief Internal component read. Implement this as you would implement a basic IMemory's read.
|
||||
//! @brief Internal component read. Implement this as you would implement a basic AMemory's read.
|
||||
//! @param addr The local address to read from. 0x0 refer to the first byte of your data and the address is in the component's space. That means that you can consider this address as continuous
|
||||
//! @throw This function should thrown an InvalidAddress for address that are not mapped to the component.
|
||||
//! @return Return the data at the address given as parameter.
|
||||
virtual uint8_t read_internal(uint24_t addr) = 0;
|
||||
//! @brief Internal component write. Implement this as you would implement a basic IMemory's write.
|
||||
//! @brief Internal component write. Implement this as you would implement a basic AMemory's write.
|
||||
//! @param addr The local address to write to. 0x0 refer to the first byte of your data and the address is in the component's space. That means that you can consider this address as continuous
|
||||
//! @param data The new data to write.
|
||||
//! @throw This function should thrown an InvalidAddress for address that are not mapped to the component.
|
||||
@@ -59,4 +59,4 @@ namespace ComSquare::Memory
|
||||
};
|
||||
}
|
||||
|
||||
#endif //COMSQUARE_IRECTANGLEMEMORY_HPP
|
||||
#endif //COMSQUARE_ARECTANGLEMEMORY_HPP
|
||||
@@ -1,35 +0,0 @@
|
||||
//
|
||||
// Created by anonymus-raccoon on 1/23/20.
|
||||
//
|
||||
|
||||
#include "IMemory.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace ComSquare::Memory
|
||||
{
|
||||
void IMemory::setMemoryRegion(uint24_t start, uint24_t end)
|
||||
{
|
||||
this->_start = start;
|
||||
this->_end = end;
|
||||
}
|
||||
|
||||
bool IMemory::hasMemoryAt(uint24_t addr)
|
||||
{
|
||||
return this->_start <= addr && addr <= this->_end;
|
||||
}
|
||||
|
||||
uint32_t IMemory::getStart()
|
||||
{
|
||||
return this->_start;
|
||||
}
|
||||
|
||||
bool IMemory::isMirror()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<IMemory> IMemory::getMirrored()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,9 @@
|
||||
|
||||
namespace ComSquare::Memory
|
||||
{
|
||||
std::shared_ptr<IMemory> MemoryBus::getAccessor(uint24_t addr)
|
||||
std::shared_ptr<AMemory> MemoryBus::getAccessor(uint24_t addr)
|
||||
{
|
||||
auto it = std::find_if(this->_memoryAccessors.begin(), this->_memoryAccessors.end(), [addr](std::shared_ptr<IMemory> &accessor)
|
||||
auto it = std::find_if(this->_memoryAccessors.begin(), this->_memoryAccessors.end(), [addr](std::shared_ptr<AMemory> &accessor)
|
||||
{
|
||||
return accessor->hasMemoryAt(addr);
|
||||
});
|
||||
@@ -24,7 +24,7 @@ namespace ComSquare::Memory
|
||||
|
||||
uint8_t MemoryBus::read(uint24_t addr)
|
||||
{
|
||||
std::shared_ptr<IMemory> handler = this->getAccessor(addr);
|
||||
std::shared_ptr<AMemory> handler = this->getAccessor(addr);
|
||||
|
||||
if (!handler) {
|
||||
std::cout << "Unknown memory accessor for address " << std::hex << addr << ". Using open bus." << std::endl;
|
||||
@@ -37,7 +37,7 @@ namespace ComSquare::Memory
|
||||
|
||||
void MemoryBus::write(uint24_t addr, uint8_t data)
|
||||
{
|
||||
std::shared_ptr<IMemory> handler = this->getAccessor(addr);
|
||||
std::shared_ptr<AMemory> handler = this->getAccessor(addr);
|
||||
|
||||
if (!handler) {
|
||||
std::cout << "Unknown memory accessor for address " << std::hex << addr << ". Warning, it was a write." << std::endl;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "IMemory.hpp"
|
||||
#include "AMemory.hpp"
|
||||
|
||||
namespace ComSquare
|
||||
{
|
||||
@@ -20,7 +20,7 @@ namespace ComSquare
|
||||
class MemoryBus {
|
||||
private:
|
||||
//! @brief The list of components registered inside the bus. Every components that can read/write to a public address should be in this vector.
|
||||
std::vector<std::shared_ptr<IMemory>> _memoryAccessors;
|
||||
std::vector<std::shared_ptr<AMemory>> _memoryAccessors;
|
||||
|
||||
//! @brief The last value read via the memory bus.
|
||||
uint8_t _openBus = 0;
|
||||
@@ -39,12 +39,12 @@ namespace ComSquare
|
||||
//! @brief Read data at a global address.
|
||||
//! @param addr The address to read from.
|
||||
//! @return The value that the component returned for this address. If the address was mapped to ram, it simply returned the value. If the address was mapped to a register the component returned the register.
|
||||
uint8_t read(uint24_t addr);
|
||||
virtual uint8_t read(uint24_t addr);
|
||||
|
||||
//! @brief Write a data to a global address.
|
||||
//! @param addr The address to write to.
|
||||
//! @param data The data to write.
|
||||
void write(uint24_t addr, uint8_t data);
|
||||
virtual void write(uint24_t addr, uint8_t data);
|
||||
|
||||
//! @brief Map components to the address space using the currently loaded cartridge to set the right mapping mode.
|
||||
//! @param console All the components.
|
||||
@@ -53,7 +53,7 @@ namespace ComSquare
|
||||
//! @brief Helper function to get the components that is responsible of read/write at an address.
|
||||
//! @param addr The address you want to look for.
|
||||
//! @return The components responsible for the address param or nullptr if none was found.
|
||||
std::shared_ptr<IMemory> getAccessor(uint24_t addr);
|
||||
std::shared_ptr<AMemory> getAccessor(uint24_t addr);
|
||||
|
||||
//! @brief Return true if the Bus is overloaded with debugging features.
|
||||
virtual bool isDebugger();
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace ComSquare::Memory
|
||||
{
|
||||
MemoryShadow::MemoryShadow(std::shared_ptr<IMemory> initial, uint24_t start, uint24_t end)
|
||||
MemoryShadow::MemoryShadow(std::shared_ptr<AMemory> initial, uint24_t start, uint24_t end)
|
||||
: _initial(std::move(initial))
|
||||
{
|
||||
this->setMemoryRegion(start, end);
|
||||
@@ -29,8 +29,13 @@ namespace ComSquare::Memory
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<IMemory> MemoryShadow::getMirrored()
|
||||
std::shared_ptr<AMemory> MemoryShadow::getMirrored()
|
||||
{
|
||||
return this->_initial;
|
||||
}
|
||||
|
||||
std::string MemoryShadow::getName()
|
||||
{
|
||||
return this->_initial->getName();
|
||||
}
|
||||
}
|
||||
@@ -6,37 +6,39 @@
|
||||
#define COMSQUARE_MEMORYSHADOW_HPP
|
||||
|
||||
#include <memory>
|
||||
#include "IMemory.hpp"
|
||||
#include "AMemory.hpp"
|
||||
|
||||
namespace ComSquare::Memory
|
||||
{
|
||||
class MemoryShadow : public IMemory {
|
||||
class MemoryShadow : public AMemory {
|
||||
private:
|
||||
//! @brief Memory to shadow from.
|
||||
std::shared_ptr<IMemory> _initial;
|
||||
std::shared_ptr<AMemory> _initial;
|
||||
public:
|
||||
//! @brief Create a shadow for the memory given as parameter.
|
||||
explicit MemoryShadow(std::shared_ptr<IMemory> initial, uint24_t start, uint24_t end);
|
||||
explicit MemoryShadow(std::shared_ptr<AMemory> initial, uint24_t start, uint24_t end);
|
||||
MemoryShadow(const MemoryShadow &) = default;
|
||||
MemoryShadow &operator=(const MemoryShadow &) = default;
|
||||
~MemoryShadow() = default;
|
||||
|
||||
//! @brief Read from the initial IMemory given.
|
||||
//! @param addr The address to read from. The address 0x0 should refer to the first byte of the initial IMemory.
|
||||
//! @throw InvalidAddress will be thrown if the address is more than the size of the initial IMemory.
|
||||
//! @brief Read from the initial AMemory given.
|
||||
//! @param addr The address to read from. The address 0x0 should refer to the first byte of the initial AMemory.
|
||||
//! @throw InvalidAddress will be thrown if the address is more than the size of the initial AMemory.
|
||||
//! @return Return the data at the address.
|
||||
uint8_t read(uint24_t addr) override;
|
||||
//! @brief Write data to the ram.
|
||||
//! @param addr The address to write to. The address 0x0 should refer to the first byte of the initial IMemory.
|
||||
//! @param addr The address to write to. The address 0x0 should refer to the first byte of the initial AMemory.
|
||||
//! @param data The data to write.
|
||||
//! @throw InvalidAddress will be thrown if the address is more than the size of the initial IMemory.
|
||||
//! @throw InvalidAddress will be thrown if the address is more than the size of the initial AMemory.
|
||||
void write(uint24_t addr, uint8_t data) override;
|
||||
//! @brief Check if this memory is a mirror or not.
|
||||
//! @return True if this memory is a mirror. False otherwise.
|
||||
bool isMirror() override;
|
||||
//! @brief Get the name of this accessor (used for debug purpose)
|
||||
std::string getName() override;
|
||||
//! @brief Return the memory accessor this accessor mirror if any
|
||||
//! @return nullptr if isMirror is false, the source otherwise.
|
||||
std::shared_ptr<IMemory> getMirrored() override;
|
||||
std::shared_ptr<AMemory> getMirrored() override;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace ComSquare::Memory
|
||||
{
|
||||
RectangleShadow::RectangleShadow(std::shared_ptr<IRectangleMemory> initial, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage)
|
||||
RectangleShadow::RectangleShadow(std::shared_ptr<ARectangleMemory> initial, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage)
|
||||
: _initial(std::move(initial))
|
||||
{
|
||||
this->setMemoryRegion(startBank, endBank, startPage, endPage);
|
||||
@@ -38,8 +38,13 @@ namespace ComSquare::Memory
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<IMemory> RectangleShadow::getMirrored()
|
||||
std::shared_ptr<AMemory> RectangleShadow::getMirrored()
|
||||
{
|
||||
return this->_initial;
|
||||
}
|
||||
|
||||
std::string RectangleShadow::getName()
|
||||
{
|
||||
return this->_initial->getName();
|
||||
}
|
||||
}
|
||||
@@ -6,30 +6,30 @@
|
||||
#define COMSQUARE_RECTANGLESHADOW_HPP
|
||||
|
||||
#include <memory>
|
||||
#include "IRectangleMemory.hpp"
|
||||
#include "ARectangleMemory.hpp"
|
||||
#include "MemoryShadow.hpp"
|
||||
|
||||
namespace ComSquare::Memory
|
||||
{
|
||||
class RectangleShadow : public IRectangleMemory {
|
||||
class RectangleShadow : public ARectangleMemory {
|
||||
private:
|
||||
//! @brief Memory to shadow from.
|
||||
std::shared_ptr<IRectangleMemory> _initial;
|
||||
std::shared_ptr<ARectangleMemory> _initial;
|
||||
//! @brief The number of banks to add to the memory before accessing it from the initial data.
|
||||
uint8_t _bankOffset = 0;
|
||||
public:
|
||||
//! @brief Create a shadow for the memory given as parameter.
|
||||
explicit RectangleShadow(std::shared_ptr<IRectangleMemory> initial, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage);
|
||||
explicit RectangleShadow(std::shared_ptr<ARectangleMemory> initial, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage);
|
||||
RectangleShadow(const RectangleShadow &) = default;
|
||||
RectangleShadow &operator=(const RectangleShadow &) = default;
|
||||
~RectangleShadow() = default;
|
||||
|
||||
//! @brief Internal component read. Implement this as you would implement a basic IMemory's read.
|
||||
//! @brief Internal component read. Implement this as you would implement a basic AMemory's read.
|
||||
//! @param addr The local address to read from. 0x0 refer to the first byte of your data and the address is in the component's space. That means that you can consider this address as continuous
|
||||
//! @throw This function should thrown an InvalidAddress for address that are not mapped to the component.
|
||||
//! @return Return the data at the address given as parameter.
|
||||
uint8_t read_internal(uint24_t addr) override;
|
||||
//! @brief Internal component write. Implement this as you would implement a basic IMemory's write.
|
||||
//! @brief Internal component write. Implement this as you would implement a basic AMemory's write.
|
||||
//! @param addr The local address to write to. 0x0 refer to the first byte of your data and the address is in the component's space. That means that you can consider this address as continuous
|
||||
//! @param data The new data to write.
|
||||
//! @throw This function should thrown an InvalidAddress for address that are not mapped to the component.
|
||||
@@ -37,9 +37,11 @@ namespace ComSquare::Memory
|
||||
//! @brief Check if this memory is a mirror or not.
|
||||
//! @return True if this memory is a mirror. False otherwise.
|
||||
bool isMirror() override;
|
||||
//! @brief Get the name of this accessor (used for debug purpose)
|
||||
std::string getName() override;
|
||||
//! @brief Return the memory accessor this accessor mirror if any
|
||||
//! @return nullptr if isMirror is false, the source otherwise.
|
||||
std::shared_ptr<IMemory> getMirrored() override;
|
||||
std::shared_ptr<AMemory> getMirrored() override;
|
||||
|
||||
RectangleShadow *setBankOffset(uint8_t bankOffset);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user