]> git.sesse.net Git - pistorm/blob - memory_mapped.c
Initial config file+memory map implementation
[pistorm] / memory_mapped.c
1 #include "config_file/config_file.h"
2 #include "Gayle.h"
3 #include <endian.h>
4
5 #define CHKRANGE(a, b, c) a >= (unsigned int)b && a < (unsigned int)(b + c)
6
7 static unsigned int target;
8
9 extern const char *map_type_names[MAPTYPE_NUM];
10 const char *op_type_names[OP_TYPE_NUM] = {
11   "BYTE",
12   "WORD",
13   "LONGWORD",
14   "MEM",
15 };
16
17 int handle_mapped_read(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type, unsigned char mirror) {
18   unsigned char *read_addr = NULL;
19   char handle_regs = 0;
20
21   //printf("Mapped read: %.8x\n", addr);
22
23   for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) {
24     if (cfg->map_type[i] == MAPTYPE_NONE)
25       continue;
26     switch(cfg->map_type[i]) {
27       case MAPTYPE_ROM:
28         if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i]))
29           read_addr = cfg->map_data[i] + (addr - cfg->map_offset[i]);
30         else if (cfg->map_mirror[i] != -1 && mirror && CHKRANGE(addr, cfg->map_mirror[i], cfg->map_size[i]))
31           read_addr = cfg->map_data[i] + (addr - cfg->map_mirror[i]);
32         break;
33       case MAPTYPE_RAM:
34         if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i]))
35           read_addr = cfg->map_data[i] + (addr - cfg->map_offset[i]);
36         break;
37       case MAPTYPE_REGISTER:
38         if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i]))
39           handle_regs = 1;
40         break;
41     }
42
43     if (!read_addr && !handle_regs)
44       continue;
45     
46     if (handle_regs) {
47       if (handle_register_read(addr, type, &target) != -1) {
48         *val = target;
49         return 1;
50       }
51       return -1;
52     }
53     else if (read_addr) {
54       //printf("Read %s from %s (%.8X) (%d)\n", op_type_names[type], map_type_names[cfg->map_type[i]], addr, mirror);
55       //printf("Readaddr: %.8lX (Base %.8lX\n", (uint64_t)(read_addr), (uint64_t)cfg->map_data[i]);
56       switch(type) {
57         case OP_TYPE_BYTE:
58           *val = read_addr[0];
59           //printf("Read val: %.8lX (%d)\n", (uint64_t)val, *val);
60           return 1;
61           break;
62         case OP_TYPE_WORD:
63           *val = be16toh(((unsigned short *)read_addr)[0]);
64           //printf("Read val: %.8lX (%d)\n", (uint64_t)val, *val);
65           return 1;
66           break;
67         case OP_TYPE_LONGWORD:
68           *val = be32toh(((unsigned int *)read_addr)[0]);
69           //printf("Read val: %.8lX (%d)\n", (uint64_t)val, *val);
70           return 1;
71           break;
72         case OP_TYPE_MEM:
73           return -1;
74           break;
75       }
76     }
77   }
78
79   return -1;
80 }
81
82 int handle_mapped_write(struct emulator_config *cfg, unsigned int addr, unsigned int value, unsigned char type, unsigned char mirror) {
83   unsigned char *write_addr = NULL;
84   char handle_regs = 0;
85
86   //printf("Mapped write: %.8x\n", addr);
87
88   for (int i = 0; i < MAX_NUM_MAPPED_ITEMS; i++) {
89     if (cfg->map_type[i] == MAPTYPE_NONE)
90       continue;
91     switch(cfg->map_type[i]) {
92       case MAPTYPE_ROM:
93         if (cfg->map_mirror[i] != -1 && mirror && CHKRANGE(addr, cfg->map_mirror[i], cfg->map_size[i]))
94           return -1;
95         else if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i]))
96           return 1;
97         break;
98       case MAPTYPE_RAM:
99         if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i]))
100           write_addr = cfg->map_data[i] + (addr - cfg->map_offset[i]);
101         break;
102       case MAPTYPE_REGISTER:
103         if (CHKRANGE(addr, cfg->map_offset[i], cfg->map_size[i]))
104           handle_regs = 1;
105         break;
106     }
107
108     if (!write_addr && !handle_regs)
109       continue;
110     
111     if (handle_regs) {
112       return handle_register_write(addr, value, type);
113     }
114     else if (write_addr) {
115       //printf("Write %s to %s (%.8X) (%d)\n", op_type_names[type], map_type_names[cfg->map_type[i]], addr, mirror);
116       //printf("Writeaddr: %.8lX (Base %.8lX\n", (uint64_t)(write_addr), (uint64_t)cfg->map_data[i]);
117       switch(type) {
118         case OP_TYPE_BYTE:
119           write_addr[0] = (unsigned char)value;
120           //printf("Write val: %.8X (%d)\n", (uint32_t)value, value);
121           return 1;
122           break;
123         case OP_TYPE_WORD:
124           ((short *)write_addr)[0] = htobe16(value);
125           //printf("Write val: %.8X (%d)\n", (uint32_t)value, value);
126           return 1;
127           break;
128         case OP_TYPE_LONGWORD:
129           ((int *)write_addr)[0] = htobe32(value);
130           //printf("Write val: %.8X (%d)\n", (uint32_t)value, value);
131           return 1;
132           break;
133         case OP_TYPE_MEM:
134           return -1;
135           break;
136       }
137     }
138   }
139
140   return -1;
141 }