Skip to content

Commit

Permalink
Update memory map
Browse files Browse the repository at this point in the history
  • Loading branch information
BlockoS committed Sep 4, 2024
1 parent 513d0e3 commit e83edfc
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 98 deletions.
2 changes: 0 additions & 2 deletions memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ bool memory_create(Memory *memory, size_t length) {
// Releases memory block resources.
void memory_destroy(Memory *memory) {
assert(memory != NULL);
assert(memory->data != NULL);

free(memory->data);
memory->data = NULL;
memory->length = 0;
Expand Down
116 changes: 116 additions & 0 deletions memory_map.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸
¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯
__/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__
\_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_
_> ___/ ¯>__> <<__// __ _/ |> ></ _/> </ ¯ \\__> <<__// /\ // __ _/
_> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ </:. \> \_
|:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::|
|¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯|
|__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _|
\|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/
¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸
¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯
This file is part of Etripator,
copyright (c) 2009--2023 Vincent Cruz.
Etripator 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.
Etripator 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 Etripator. If not, see <http://www.gnu.org/licenses/>.
¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸
¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯
*/
#include "memory_map.h"
#include "message.h"

// Resets memory map.
static void memory_map_clear(MemoryMap *map) {
for(unsigned int i=0; i<PCE_MEMORY_COUNT; i++) {
map->memory[i].length = 0;
map->memory[i].data = NULL;
}
for(unsigned int i=0; i<PCE_MPR_COUNT; i++) {
map->mpr[i] = 0xFFU;
}
for(unsigned int i=0; i<PCE_PAGE_COUNT; i++) {
map->page[i].id = PCE_MEMORY_NONE;
map->page[i].bank = 0;
}
}

// Initializes memory map.
bool memory_map_init(MemoryMap *map) {
bool ret = false;

memory_map_clear(map);

// Allocate main (or work) RAM.
if(!memory_create(&map->memory[PCE_MEMORY_BASE_RAM], PCE_BANK_SIZE)) {
ERROR_MSG("Failed to allocate main memory!");
} else {
// Main RAM is mapped to pages 0xF8 to 0xFB (included).
// Pages 0xF9 to 0xFB mirror page 0xF8. */
for(unsigned int i=0xf8; i<=0xfb; i++) {
map->page[i].id = PCE_MEMORY_BASE_RAM;
map->page[i].bank = 0;
}

// ROM and syscard RAM will be initialized later.
ret = true;
}
return ret;
}

// Releases resources used by the memory map.
void memory_map_destroy(MemoryMap *map) {
assert(map != NULL);
for(unsigned i=0; i<PCE_MEMORY_COUNT; i++) {
memory_destroy(&map->memory[i]);
}
memory_map_clear(map);
}

// Get the memory page associated to a logical address.
uint8_t memory_map_page(MemoryMap* map, uint16_t logical) {
assert(map != NULL);
uint8_t id = (logical >> 13) & 0x07U;
return map->mpr[id];
}

// Reads a single byte from memory.
uint8_t memory_map_read(MemoryMap *map, size_t logical) {
assert(map != NULL);
const uint8_t id = memory_map_page(map, (uint16_t)logical);
const Page *page = &map->page[id];

uint8_t ret = 0xFFU;
if(page->id != PCE_MEMORY_NONE) {
const size_t offset = (logical & 0x1FFFU) + (page->bank * PCE_BANK_SIZE);
const Memory *mem = &map->memory[page->id];
if(offset < mem->length) {
ret = mem->data[offset];
}
}
return ret;
}

// Update mprs.
void memory_map_mpr(MemoryMap *map, const uint8_t mpr[PCE_MPR_COUNT]) {
assert(map != NULL);
for(unsigned int i=0; i<PCE_MPR_COUNT; i++) {
map->mpr[i] = mpr[i];
}
}
98 changes: 51 additions & 47 deletions memorymap.h → memory_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,56 +38,60 @@

#include "memory.h"

/**
* PC Engine memory
*/
/// PC Engine memory blocks.
enum {
PCE_MEM_ROM = 0,
PCE_MEM_BASE_RAM,
PCE_MEM_CD_RAM,
PCE_MEM_SYSCARD_RAM,
PCE_MEM_COUNT
PCE_MEMORY_NONE = -1,
PCE_MEMORY_ROM = 0,
PCE_MEMORY_BASE_RAM,
PCE_MEMORY_CD_RAM,
PCE_MEMORY_SYSCARD_RAM,
PCE_MEMORY_COUNT
};

/**
* PC Engine memory map.
*/
#define PCE_PAGE_COUNT 0x100U

#define PCE_MPR_COUNT 8U

#define PCE_BANK_SIZE 8192U

/// PC Engine memory page description.
typedef struct {
int id; // name the PCE_MEMORY_* enum ?
size_t bank;
} Page;

/// PC Engine memory map.
typedef struct {
Memory mem[PCE_MEM_COUNT];
uint8_t *page[0x100];
uint8_t mpr[8];
} memmap_t;

/**
* Initializes memory map.
* \param map Memory map.
* \return 1 upon success, 0 if an error occured.
*/
int memmap_init(memmap_t *map);
/**
* Releases resources used by the memory map.
* \param map Memory map.
*/
void memmap_destroy(memmap_t *map);
/**
* Get the memory page associated to a logical address.
* \param map Memory map.
* \param logical Logical address.
* \return Memory page.
*/
uint8_t memmap_page(memmap_t* map, uint16_t logical);
/**
* Reads a single byte from memory.
* \param [in] map Memory map.
* \param [in] logical Logical address.
* \return Byte read.
*/
uint8_t memmap_read(memmap_t *map, size_t logical);
/**
* Update mprs.
* \param [in][out] map Memory map.
* \param [in] mpr Memory page registers.
*/
void memmap_mpr(memmap_t *map, const uint8_t *mpr);
Memory memory[PCE_MEMORY_COUNT];
Page page[PCE_PAGE_COUNT];
uint8_t mpr[PCE_MPR_COUNT];
} MemoryMap;

/// Initializes memory map.
/// \param [in out] map Memory map.
/// \return true
/// \return false
bool memory_map_init(MemoryMap *map);

/// Releases resources used by the memory map.
/// \param [in out] map Memory map.
void memory_map_destroy(MemoryMap *map);

/// Get the memory page associated to a logical address.
/// \param [in] map Memory map.
/// \param [in] logical Logical address.
/// \return Memory page.
uint8_t memory_map_page(MemoryMap* map, uint16_t logical);

/// Reads a single byte from memory.
/// \param [in] map Memory map.
/// \param [in] logical Logical address.
/// \return The value stored at the specified logical address.
uint8_t memory_map_read(MemoryMap *map, size_t logical);

/// Update the whole mprs list
/// \param [in out] map Memory map.
/// \param [in] mpr Memory page registers.
void memory_map_mpr(MemoryMap *map, const uint8_t mpr[PCE_MPR_COUNT]);

#endif // ETRIPATOR_MEMORY_MAP_H
12 changes: 12 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,15 @@ add_unit_test(
LIBRARIES cwalk
INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR}
)

add_unit_test(
NAME memory_map
SOURCES
memory_map.c
${PROJECT_SOURCE_DIR}/memory_map.c
${PROJECT_SOURCE_DIR}/memory.c
${PROJECT_SOURCE_DIR}/message.c
${PROJECT_SOURCE_DIR}/message/console.c
LIBRARIES cwalk
INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR}
)
98 changes: 49 additions & 49 deletions memorymap.c → test/memory_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,56 +33,56 @@
¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸
¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯
*/
#include "memorymap.h"
#include "message.h"
/* Initializes memory map. */
int memmap_init(memmap_t *map) {
int i, ret = 0;

memset(map, 0, sizeof(memmap_t)); // [todo] function


/* Allocate main (or work) RAM */
if(!memory_create(&map->mem[PCE_MEM_BASE_RAM], 8192)) {
ERROR_MSG("Failed to allocate main memory!\n");
} else {
/* Main RAM is mapped to pages 0xf8-0xfb (included). */
/* Pages 0xf9 to 0xfb mirror page 0xf8. */
for(i=0xf8; i<=0xfb; i++) {
map->page[i] = &(map->mem[PCE_MEM_BASE_RAM].data[0]);
}

/* ROM and syscard RAM will be initialized later. */

/* Clear mprs. */
memset(map->mpr, 0, 8);
map->mpr[0] = 0xff;
map->mpr[1] = 0xf8;

ret = 1;
}
return ret;
}
/* Releases resources used by the memory map. */
void memmap_destroy(memmap_t *map) {
int i;
for(i=0; i<PCE_MEM_COUNT; i++) {
memory_destroy(&map->mem[i]);
}
memset(map, 0, sizeof(memmap_t));
}
/* Get the memory page associated to a logical address. */
uint8_t memmap_page(memmap_t* map, uint16_t logical) {
uint8_t id = (logical >> 13) & 0x07;
return map->mpr[id];
#include <munit.h>

#include <message.h>
#include <message/console.h>

#include <memory_map.h>

void* setup(const MunitParameter params[] __attribute__((unused)), void* user_data __attribute__((unused))) {
return NULL;
}
/* Reads a single byte from memory. */
uint8_t memmap_read(memmap_t *map, size_t logical) {
uint8_t i = memmap_page(map, (uint16_t)logical);
return (map->page[i]) ? map->page[i][logical & 0x1fff] : 0xff;

void tear_down(void* fixture __attribute__((unused))) {
}
/* Update mprs. */
void memmap_mpr(memmap_t *map, const uint8_t *mpr) {
memcpy(map->mpr, mpr, 8);

MunitResult memory_map_read_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) {
MemoryMap map = {0};

munit_assert_true(memory_map_init(&map));

map.mpr[1] = 0xF8U;

map.memory[PCE_MEMORY_BASE_RAM].data[0x0000] = 0xC5;
map.memory[PCE_MEMORY_BASE_RAM].data[0x0100] = 0x7E;
map.memory[PCE_MEMORY_BASE_RAM].data[0x1000] = 0xA9;

munit_assert_uint8(memory_map_read(&map, 0x2000U), ==, 0xC5);
munit_assert_uint8(memory_map_read(&map, 0x2100U), ==, 0x7E);
munit_assert_uint8(memory_map_read(&map, 0x3000U), ==, 0xA9);

memory_map_destroy(&map);

return MUNIT_OK;
}

static MunitTest memory_map_tests[] = {
{ "/read", memory_map_read_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL },
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
};

static const MunitSuite memory_map_suite = {
"Memory map test suite", memory_map_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE
};

int main (int argc, char* const* argv) {
message_printer_init();
console_message_printer_init();

int ret = munit_suite_main(&memory_map_suite, NULL, argc, argv);

message_printer_destroy();

return ret;
}

0 comments on commit e83edfc

Please sign in to comment.