2008-02-20 15:40:31 +00:00

276 lines
6.9 KiB
C
Executable File

/*
* 6502 Memory manager - The TI-NESulator Project
* memory.c - Taken from the Quick6502 project
*
* Created by Manoël Trapier on 18/09/06.
* Copyright 2003-2007 986 Corp. All rights reserved.
*
* $LastChangedDate: 2007-05-02 18:37:41 +0200 (mer, 02 mai 2007) $
* $Author: mtrapier $
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/memory.c $
* $Revision: 50 $
*
*/
#include <stdio.h>
#include "types.h"
#include "../include/memory/manager.h"
/* Private structures */
#define KBYTE * (1024)
/*
* What inside memory manager:
*
* Table of attributes
* Table of original page ptr
* Table of moded page ptr
*
*/
/* Private data */
byte *memory_pages[0x100];
byte memory_pages_attr[0x100];
func_rdhook rdh_table[0x100];
func_wrhook wrh_table[0x100];
//#define DEBUG
#undef DEBUG
#ifdef DEBUG
#define LOG(s) s
#else
#define LOG(s) {}
#endif
/* Public functions */
void set_page_ptr(byte page, byte *ptr)
{
LOG(printf("Set page 0x%X to ptr %p\n", page, ptr));
memory_pages[page] = ptr;
}
void set_page_ptr_1k(byte page, byte *ptr)
{ /* 1k = 4 * 256 */
LOG(printf("Set page(1k) 0x%X to ptr %p\n", page, ptr));
memory_pages[page + 0] = ptr;
memory_pages[page + 1] = ptr + 0x100;
memory_pages[page + 2] = ptr + (0x100 * 2);
memory_pages[page + 3] = ptr + (0x100 * 3);
}
void set_page_ptr_2k(byte page, byte *ptr)
{
LOG(printf("Set page(2k) 0x%X to ptr %p\n", page, ptr));
memory_pages[page + 0] = ptr;
memory_pages[page + 1] = ptr + 0x100;
memory_pages[page + 2] = ptr + (0x100 * 2);
memory_pages[page + 3] = ptr + (0x100 * 3);
memory_pages[page + 4] = ptr + (0x100 * 4);
memory_pages[page + 5] = ptr + (0x100 * 5);
memory_pages[page + 6] = ptr + (0x100 * 6);
memory_pages[page + 7] = ptr + (0x100 * 7);
}
void set_page_ptr_4k(byte page, byte *ptr)
{
LOG(printf("Set page(4k) 0x%X to ptr %p\n", page, ptr));
set_page_ptr_2k(page, ptr);
set_page_ptr_2k(page+((4 KBYTE / 256) / 2), ptr + 2 KBYTE);
}
void set_page_ptr_8k(byte page, byte *ptr)
{
LOG(printf("Set page(8k) 0x%X to ptr %p\n", page, ptr));
set_page_ptr_4k(page, ptr);
set_page_ptr_4k(page+((8 KBYTE / 256) / 2), ptr + 4 KBYTE);
}
void set_page_ptr_16k(byte page, byte *ptr)
{
set_page_ptr_8k(page, ptr);
set_page_ptr_8k(page+((16 KBYTE / 256) / 2), ptr + 8 KBYTE);
}
void set_page_ptr_32k(byte page, byte *ptr)
{
set_page_ptr_16k(page, ptr);
set_page_ptr_16k(page+((32 KBYTE / 256) / 2), ptr + 16 KBYTE);
}
byte *get_page_ptr(byte page)
{
return memory_pages[page];
}
/* Functions to set pages attributes */
void set_page_rd_hook(byte page, func_rdhook func)
{
if (func == NULL)
{
memory_pages_attr[page] &= (~ATTR_PAGE_HAVE_RDHOOK);
if (memory_pages[page] == (byte *)0x01)
memory_pages[page] = NULL;
}
else
{
memory_pages_attr[page] |= ATTR_PAGE_HAVE_RDHOOK;
if (memory_pages[page] == NULL)
memory_pages[page] = (byte *)0x01;
}
rdh_table[page] = func;
}
void set_page_wr_hook(byte page, func_wrhook func)
{
if (func == NULL)
{
memory_pages_attr[page] &= (~ATTR_PAGE_HAVE_WRHOOK);
if (memory_pages[page] == (byte*)0x01)
memory_pages[page] = NULL;
}
else
{
memory_pages_attr[page] |= ATTR_PAGE_HAVE_WRHOOK;
if (memory_pages[page] == NULL)
memory_pages[page] = (byte *)0x01;
}
wrh_table[page] = func;
}
void set_page_readable(byte page, bool value)
{
if (value == true)
memory_pages_attr[page] |= ATTR_PAGE_READABLE;
else
memory_pages_attr[page] &= (~ATTR_PAGE_READABLE);
}
void set_page_writeable(byte page, bool value)
{
if (value == true)
memory_pages_attr[page] |= ATTR_PAGE_WRITEABLE;
else
memory_pages_attr[page] &= (~ATTR_PAGE_WRITEABLE);
}
void set_page_ghost(byte page, bool value, byte ghost)
{
if (value == true)
{
memory_pages_attr[page] = memory_pages_attr[ghost];
rdh_table[page] = rdh_table[ghost];
wrh_table[page] = wrh_table[ghost];
memory_pages[page] = memory_pages[ghost];
}
}
byte get_page_attributes(byte page)
{
return memory_pages_attr[page];
}
func_rdhook get_page_rdhook(byte page)
{
if (memory_pages_attr[page] & ATTR_PAGE_HAVE_RDHOOK)
return rdh_table[page];
return NULL;
}
func_wrhook get_page_wrhook(byte page)
{
if (memory_pages_attr[page] & ATTR_PAGE_HAVE_WRHOOK)
return wrh_table[page];
return NULL;
}
byte ReadMemory(byte page, byte addr)
{
static byte LastRetByte = 0xA5;
byte *page_ptr;
byte attributes;
LOG(printf("Read @ 0x%X-%X\n", page, addr));
/* Est-ce que la page est mappé ? && Est-ce que la page est "readable" ? */
if ((page_ptr = memory_pages[page]) &&
( (attributes = memory_pages_attr[page]) & ATTR_PAGE_READABLE) )
{
LOG(printf("Page is non null & readable\n"));
if ( attributes & ATTR_PAGE_HAVE_RDHOOK )
return ( LastRetByte = rdh_table[page](addr) );
else
return ( LastRetByte = page_ptr[addr] );
}
//printf("Trying to read @ 0x%X-%X\n", page, addr);
return LastRetByte;
}
void WriteMemory(byte page, byte addr, byte value)
{
byte *page_ptr;
byte attributes;
LOG(printf("Write 0x%x @ 0x%X-%X\n", value, page, addr));
/* Est-ce que la page est mappé ? && Est-ce que la page est "writable" ? */
if ( (page_ptr = memory_pages[page]) &&
( (attributes = memory_pages_attr[page]) & ATTR_PAGE_WRITEABLE) )
{
if ( attributes & ATTR_PAGE_HAVE_WRHOOK )
{
#ifdef DETECT_BUS_CONFLICT
if ((page >= 0x80) && (memory_pages[page][addr] != value))
printf("WriteHook: bus conflict at %02X%02X rom:%02X write:%02X\n", page, addr, memory_pages[page][addr], value);
#endif
wrh_table[page](addr, value);
}
else
page_ptr[addr] = value;
}
else { printf("Trying to write 0x%X @ 0x%X-%X\n", value, page, addr); }
}
void DumpMemoryState(FILE *fp)
{
int i;
for (i = 0x00; i < 0x100; i++)
{
fprintf(fp,
"Page 0x%02X : [%c%c%c%c%c%c] RdH:%p WrH:%p ptr:%p\n",
i,
(memory_pages_attr[i]&ATTR_PAGE_HAVE_RDHOOK)?'r':'.',
(memory_pages_attr[i]&ATTR_PAGE_HAVE_WRHOOK)?'w':'.',
(memory_pages_attr[i]&ATTR_PAGE_READABLE)?'R':'.',
(memory_pages_attr[i]&ATTR_PAGE_WRITEABLE)?'W':'.',
(memory_pages_attr[i]&ATTR_PAGE_GHOST)?'G':'.',
(memory_pages_attr[i]&ATTR_PAGE_MAPPED)?'M':'.',
rdh_table[i],
wrh_table[i],
memory_pages[i]
);
}
}
void InitMemory()
{
int page;
for(page = 0 ; page < 0x100 ; page++)
{
set_page_ptr(page,NULL);
memory_pages_attr[page] = 0x00;
}
}