-
Notifications
You must be signed in to change notification settings - Fork 105
/
memory_mapped.c
146 lines (132 loc) · 4.02 KB
/
memory_mapped.c
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// SPDX-License-Identifier: MIT
#include "config_file/config_file.h"
#include "m68k.h"
#include "platforms/amiga/Gayle.h"
#include <endian.h>
#define CHKRANGE(a, b, c) a >= (unsigned int)b && a < (unsigned int)(b + c)
#define CHKRANGE_ABS(a, b, c) a >= (unsigned int)b && a < (unsigned int) c
static unsigned int target;
extern int ovl;
extern const char *map_type_names[MAPTYPE_NUM];
const char *op_type_names[OP_TYPE_NUM] = {
"BYTE",
"WORD",
"LONGWORD",
"MEM",
};
inline int handle_mapped_read(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type) {
unsigned char *read_addr = NULL;
for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) {
if (cfg->map_type[i] == MAPTYPE_NONE)
continue;
else if (ovl && (cfg->map_type[i] == MAPTYPE_ROM || cfg->map_type[i] == MAPTYPE_RAM_WTC)) {
if (cfg->map_mirror[i] != ((unsigned int)-1) && CHKRANGE(addr, cfg->map_mirror[i], cfg->map_size[i])) {
read_addr = cfg->map_data[i] + ((addr - cfg->map_mirror[i]) % cfg->rom_size[i]);
goto read_value;
}
}
if (CHKRANGE_ABS(addr, cfg->map_offset[i], cfg->map_high[i])) {
switch(cfg->map_type[i]) {
case MAPTYPE_ROM:
read_addr = cfg->map_data[i] + ((addr - cfg->map_offset[i]) % cfg->rom_size[i]);
goto read_value;
break;
case MAPTYPE_RAM:
case MAPTYPE_RAM_WTC:
case MAPTYPE_RAM_NOALLOC:
read_addr = cfg->map_data[i] + (addr - cfg->map_offset[i]);
goto read_value;
break;
case MAPTYPE_REGISTER:
if (cfg->platform && cfg->platform->register_read) {
if (cfg->platform->register_read(addr, type, &target) != -1) {
*val = target;
return 1;
}
}
return -1;
break;
}
}
}
return -1;
read_value:;
switch(type) {
case OP_TYPE_BYTE:
*val = read_addr[0];
return 1;
break;
case OP_TYPE_WORD:
*val = be16toh(((unsigned short *)read_addr)[0]);
return 1;
break;
case OP_TYPE_LONGWORD:
*val = be32toh(((unsigned int *)read_addr)[0]);
return 1;
break;
case OP_TYPE_MEM:
return -1;
break;
}
return 1;
}
inline int handle_mapped_write(struct emulator_config *cfg, unsigned int addr, unsigned int value, unsigned char type) {
int res = -1;
unsigned char *write_addr = NULL;
for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) {
if (cfg->map_type[i] == MAPTYPE_NONE)
continue;
else if (ovl && cfg->map_type[i] == MAPTYPE_RAM_WTC) {
if (cfg->map_mirror[i] != ((unsigned int)-1) && CHKRANGE(addr, cfg->map_mirror[i], cfg->map_size[i])) {
write_addr = cfg->map_data[i] + ((addr - cfg->map_mirror[i]) % cfg->rom_size[i]);
res = -1;
goto write_value;
}
}
else if (CHKRANGE_ABS(addr, cfg->map_offset[i], cfg->map_high[i])) {
switch(cfg->map_type[i]) {
case MAPTYPE_ROM:
return 1;
break;
case MAPTYPE_RAM:
case MAPTYPE_RAM_NOALLOC:
write_addr = cfg->map_data[i] + (addr - cfg->map_offset[i]);
res = 1;
goto write_value;
break;
case MAPTYPE_RAM_WTC:
//printf("Some write to WTC RAM.\n");
write_addr = cfg->map_data[i] + (addr - cfg->map_offset[i]);
res = -1;
goto write_value;
break;
case MAPTYPE_REGISTER:
if (cfg->platform && cfg->platform->register_write) {
return cfg->platform->register_write(addr, value, type);
}
break;
}
}
}
return res;
write_value:;
switch(type) {
case OP_TYPE_BYTE:
write_addr[0] = (unsigned char)value;
return res;
break;
case OP_TYPE_WORD:
((short *)write_addr)[0] = htobe16(value);
return res;
break;
case OP_TYPE_LONGWORD:
((int *)write_addr)[0] = htobe32(value);
return res;
break;
case OP_TYPE_MEM:
return -1;
break;
}
// This should never actually happen.
return res;
}