summaryrefslogtreecommitdiff
path: root/emu/memory.c
blob: 4ddd8c3b8b0bddaf734b780a485d4054e3dc8626 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include "memory.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static device_vtable_t const memory_vtable = {
	memory_read,
	memory_write,
	device_draw,
	memory_deinit
};

void memory_init( memory_t *memory, memory_type_t type, uint16_t addr, uint16_t size, bool initialize )
{
	device_init( &memory->base, ( type == MEMORY_ROM ) ? "ROM" : "RAM" );

	memory->type = type;
	memory->addr = addr;
	memory->size = size;
	memory->cell = malloc( memory->size );
	if( initialize ) {
		memory_reset( memory );
	}
	
	memory->base.vtable = (device_vtable_t *)&memory_vtable;
}

void memory_copy( memory_t *to, memory_t *from )
{	
	memcpy( to, from, sizeof( memory_t ) );
	device_copy( &to->base, &from->base );

	to->cell = malloc( to->size );
	memcpy( to->cell, from->cell, to->size );
}

void memory_load( memory_t *memory, const char *filename )
{
	if( memory->type == MEMORY_ROM ) {
		FILE *f = fopen( filename, "rb" );
		if( f == NULL ) {
			fprintf( stderr, "ERROR: Unable to open ROM file '%s'\n", filename );
			exit( EXIT_FAILURE );
		}
		fread( &memory->cell[0], memory->size, 1, f );
		fclose( f );
		fprintf( stderr, "INFO: Loaded firmware from '%s' of size %d starting on address %04X\n",
			filename, memory->size, memory->addr );
	} else {
		fprintf( stderr, "ERROR: Cannot load firmware into RAM at address %04X\n", memory->addr );
	}
}

void memory_set( memory_t *memory, uint16_t addr, uint8_t *buf, int bufsize )
{
	memcpy( &memory->cell[addr], buf, bufsize );
}

void memory_reset( memory_t *memory )
{
	memset( memory->cell, 0, memory->size );
}

uint8_t memory_read( void *obj, uint16_t addr )
{
	memory_t *memory = (memory_t *)obj;
	
	return memory->cell[addr-memory->addr];
}

void memory_write( void *obj, uint16_t addr, uint8_t data )
{
	memory_t *memory = (memory_t *)obj;

	if( memory->type & MEMORY_ROM ) {
		// ignore writes to ROM
	} else {
		memory->cell[addr-memory->addr] = data;
	}
}

void memory_deinit( void *obj )
{
	memory_t *memory = (memory_t *)obj;
	
	free( memory->cell );

	device_deinit( &memory->base );
}