mirror of
https://github.com/dingusdev/dingusppc.git
synced 2026-04-25 19:18:34 +00:00
Move devices into dedicated subdirectories.
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-20 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <devices/memctrl/memctrlbase.h>
|
||||
|
||||
#include <algorithm> // to shut up MSVC errors (:
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
MemCtrlBase::~MemCtrlBase() {
|
||||
for (auto& entry : address_map) {
|
||||
if (entry)
|
||||
delete(entry);
|
||||
}
|
||||
|
||||
for (auto& reg : mem_regions) {
|
||||
if (reg)
|
||||
delete (reg);
|
||||
}
|
||||
this->mem_regions.clear();
|
||||
this->address_map.clear();
|
||||
}
|
||||
|
||||
|
||||
AddressMapEntry* MemCtrlBase::find_range(uint32_t addr) {
|
||||
for (auto& entry : address_map) {
|
||||
if (addr >= entry->start && addr <= entry->end)
|
||||
return entry;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::add_mem_region(
|
||||
uint32_t start_addr, uint32_t size, uint32_t dest_addr, uint32_t type, uint8_t init_val = 0) {
|
||||
AddressMapEntry *entry;
|
||||
|
||||
/* error if a memory region for the given range already exists */
|
||||
if (find_range(start_addr) || find_range(start_addr + size))
|
||||
return false;
|
||||
|
||||
uint8_t* reg_content = new uint8_t[size];
|
||||
|
||||
this->mem_regions.push_back(reg_content);
|
||||
|
||||
entry = new AddressMapEntry;
|
||||
|
||||
entry->start = start_addr;
|
||||
entry->end = start_addr + size - 1;
|
||||
entry->mirror = dest_addr;
|
||||
entry->type = type;
|
||||
entry->devobj = 0;
|
||||
entry->mem_ptr = reg_content;
|
||||
|
||||
this->address_map.push_back(entry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::add_rom_region(uint32_t start_addr, uint32_t size) {
|
||||
return add_mem_region(start_addr, size, 0, RT_ROM);
|
||||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::add_ram_region(uint32_t start_addr, uint32_t size) {
|
||||
return add_mem_region(start_addr, size, 0, RT_RAM);
|
||||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::add_mem_mirror(uint32_t start_addr, uint32_t dest_addr) {
|
||||
AddressMapEntry *entry, *ref_entry;
|
||||
|
||||
ref_entry = find_range(dest_addr);
|
||||
if (!ref_entry)
|
||||
return false;
|
||||
|
||||
entry = new AddressMapEntry;
|
||||
|
||||
entry->start = start_addr;
|
||||
entry->end = start_addr + (ref_entry->end - ref_entry->start);
|
||||
entry->mirror = dest_addr;
|
||||
entry->type = ref_entry->type | RT_MIRROR;
|
||||
entry->devobj = 0;
|
||||
entry->mem_ptr = ref_entry->mem_ptr;
|
||||
|
||||
this->address_map.push_back(entry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::set_data(uint32_t reg_addr, const uint8_t* data, uint32_t size) {
|
||||
AddressMapEntry* ref_entry;
|
||||
uint32_t cpy_size;
|
||||
|
||||
ref_entry = find_range(reg_addr);
|
||||
if (!ref_entry)
|
||||
return false;
|
||||
|
||||
cpy_size = std::min(ref_entry->end - ref_entry->start + 1, size);
|
||||
memcpy(ref_entry->mem_ptr, data, cpy_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice* dev_instance) {
|
||||
AddressMapEntry *entry;
|
||||
|
||||
/* error if another region for the given range already exists */
|
||||
if (find_range(start_addr) || find_range(start_addr + size - 1))
|
||||
return false;
|
||||
|
||||
entry = new AddressMapEntry;
|
||||
|
||||
entry->start = start_addr;
|
||||
entry->end = start_addr + size - 1;
|
||||
entry->mirror = 0;
|
||||
entry->type = RT_MMIO;
|
||||
entry->devobj = dev_instance;
|
||||
entry->mem_ptr = 0;
|
||||
|
||||
this->address_map.push_back(entry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AddressMapEntry* MemCtrlBase::find_rom_region()
|
||||
{
|
||||
for (auto& entry : address_map) {
|
||||
if (entry->type == RT_ROM) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
Reference in New Issue
Block a user