2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
12 #define ADDR_MASK (addr_max - 1)
13 #define BANK_MASK (bank_size - 1)
15 void MEMORY::initialize()
17 // allocate tables here to support multiple instances with different address range
18 if(rd_table == NULL) {
19 int64_t bank_num = addr_max / bank_size;
21 rd_dummy = (uint8_t *)malloc(bank_size);
22 wr_dummy = (uint8_t *)malloc(bank_size);
24 rd_table = (bank_t *)calloc(bank_num, sizeof(bank_t));
25 wr_table = (bank_t *)calloc(bank_num, sizeof(bank_t));
27 for(int i = 0; i < bank_num; i++) {
28 rd_table[i].dev = NULL;
29 rd_table[i].memory = rd_dummy;
32 wr_table[i].dev = NULL;
33 wr_table[i].memory = wr_dummy;
36 for(int i = 0;; i++) {
37 if(bank_size == (int64_t)(1 << i)) {
42 memset(rd_dummy, 0xff, bank_size);
46 void MEMORY::release()
54 uint32_t MEMORY::read_data8(uint32_t addr)
56 int bank = (addr & ADDR_MASK) >> addr_shift;
58 if(rd_table[bank].dev != NULL) {
59 return rd_table[bank].dev->read_memory_mapped_io8(addr);
61 return rd_table[bank].memory[addr & BANK_MASK];
65 void MEMORY::write_data8(uint32_t addr, uint32_t data)
67 int bank = (addr & ADDR_MASK) >> addr_shift;
69 if(wr_table[bank].dev != NULL) {
70 wr_table[bank].dev->write_memory_mapped_io8(addr, data);
72 wr_table[bank].memory[addr & BANK_MASK] = data;
76 uint32_t MEMORY::read_data16(uint32_t addr)
78 int bank = (addr & ADDR_MASK) >> addr_shift;
80 if(rd_table[bank].dev != NULL) {
81 return rd_table[bank].dev->read_memory_mapped_io16(addr);
83 int bank1 = ((addr + 1) & ADDR_MASK) >> addr_shift;
85 uint32_t val = read_data8(addr);
86 val |= read_data8(addr + 1) << 8;
89 uint8_t* p = (uint8_t*)(&(rd_table[bank].memory[addr & BANK_MASK]));
91 #if defined(__LITTLE_ENDIAN__)
92 uint16_t* pp = (uint16_t*)p;
93 val = (uint32_t)(*pp);
96 val = (val << 8) | ((uint32_t)(p[1]));
103 void MEMORY::write_data16(uint32_t addr, uint32_t data)
105 int bank = (addr & ADDR_MASK) >> addr_shift;
107 if(wr_table[bank].dev != NULL) {
108 wr_table[bank].dev->write_memory_mapped_io16(addr, data);
110 int bank1 = ((addr + 1) & ADDR_MASK) >> addr_shift;
112 write_data8(addr, data & 0xff);
113 write_data8(addr + 1, (data >> 8) & 0xff);
115 uint8_t* p = (uint8_t*)(&(wr_table[bank].memory[addr & BANK_MASK]));
116 #if defined(__LITTLE_ENDIAN__)
117 uint16_t* pp = (uint16_t*)p;
118 *pp = (uint16_t)data;
121 p[1] = (data >> 8) & 0xff;
127 uint32_t MEMORY::read_data32(uint32_t addr)
129 int bank = (addr & ADDR_MASK) >> addr_shift;
131 if(rd_table[bank].dev != NULL) {
132 return rd_table[bank].dev->read_memory_mapped_io32(addr);
134 int bank1 = ((addr + 3) & ADDR_MASK) >> addr_shift;
136 uint32_t val = read_data16(addr);
137 val |= read_data16(addr + 2) << 16;
140 uint8_t* p = (uint8_t*)(&(rd_table[bank].memory[addr & BANK_MASK]));
142 #if defined(__LITTLE_ENDIAN__)
143 uint32_t* pp = (uint32_t*)p;
146 val = ((uint32_t)p[0]) | (((uint32_t)p[1]) << 8) | (((uint32_t)p[2]) << 16) |(((uint32_t)p[3]) << 24);
153 void MEMORY::write_data32(uint32_t addr, uint32_t data)
155 int bank = (addr & ADDR_MASK) >> addr_shift;
157 if(wr_table[bank].dev != NULL) {
158 wr_table[bank].dev->write_memory_mapped_io32(addr, data);
160 int bank1 = ((addr + 3) & ADDR_MASK) >> addr_shift;
162 write_data16(addr, data & 0xffff);
163 write_data16(addr + 2, (data >> 16) & 0xffff);
165 uint8_t* p = (uint8_t*)(&(wr_table[bank].memory[addr & BANK_MASK]));
166 #if defined(__LITTLE_ENDIAN__)
167 uint32_t* pp = (uint32_t*)p;
171 p[1] = (data >> 8) & 0xff;
172 p[2] = (data >> 16) & 0xff;
173 p[3] = (data >> 24) & 0xff;
179 uint32_t MEMORY::read_data8w(uint32_t addr, int* wait)
181 int bank = (addr & ADDR_MASK) >> addr_shift;
183 *wait = rd_table[bank].wait;
184 if(rd_table[bank].dev != NULL) {
185 return rd_table[bank].dev->read_memory_mapped_io8(addr);
187 return rd_table[bank].memory[addr & BANK_MASK];
191 void MEMORY::write_data8w(uint32_t addr, uint32_t data, int* wait)
193 int bank = (addr & ADDR_MASK) >> addr_shift;
195 *wait = wr_table[bank].wait;
196 if(wr_table[bank].dev != NULL) {
197 wr_table[bank].dev->write_memory_mapped_io8(addr, data);
199 wr_table[bank].memory[addr & BANK_MASK] = data;
203 uint32_t MEMORY::read_data16w(uint32_t addr, int* wait)
206 uint32_t val = read_data8w(addr, &wait_l);
207 val |= read_data8w(addr + 1, &wait_h) << 8;
208 *wait = wait_l + wait_h;
212 void MEMORY::write_data16w(uint32_t addr, uint32_t data, int* wait)
215 write_data8w(addr, data & 0xff, &wait_l);
216 write_data8w(addr + 1, (data >> 8) & 0xff, &wait_h);
217 *wait = wait_l + wait_h;
220 uint32_t MEMORY::read_data32w(uint32_t addr, int* wait)
223 uint32_t val = read_data16w(addr, &wait_l);
224 val |= read_data16w(addr + 2, &wait_h) << 16;
225 *wait = wait_l + wait_h;
229 void MEMORY::write_data32w(uint32_t addr, uint32_t data, int* wait)
232 write_data16w(addr, data & 0xffff, &wait_l);
233 write_data16w(addr + 2, (data >> 16) & 0xffff, &wait_h);
234 *wait = wait_l + wait_h;
237 #ifdef MEMORY_DISABLE_DMA_MMIO
238 uint32_t MEMORY::read_dma_data8(uint32_t addr)
240 int bank = (addr & ADDR_MASK) >> addr_shift;
242 if(rd_table[bank].dev != NULL) {
243 // return rd_table[bank].dev->read_memory_mapped_io8(addr);
246 return rd_table[bank].memory[addr & BANK_MASK];
250 void MEMORY::write_dma_data8(uint32_t addr, uint32_t data)
252 int bank = (addr & ADDR_MASK) >> addr_shift;
254 if(wr_table[bank].dev != NULL) {
255 // wr_table[bank].dev->write_memory_mapped_io8(addr, data);
257 wr_table[bank].memory[addr & BANK_MASK] = data;
261 uint32_t MEMORY::read_dma_data16(uint32_t addr)
263 int bank = (addr & ADDR_MASK) >> addr_shift;
265 if(rd_table[bank].dev != NULL) {
266 // return rd_table[bank].dev->read_memory_mapped_io16(addr);
269 uint32_t val = read_dma_data8(addr);
270 val |= read_dma_data8(addr + 1) << 8;
275 void MEMORY::write_dma_data16(uint32_t addr, uint32_t data)
277 int bank = (addr & ADDR_MASK) >> addr_shift;
279 if(wr_table[bank].dev != NULL) {
280 // wr_table[bank].dev->write_memory_mapped_io16(addr, data);
282 write_dma_data8(addr, data & 0xff);
283 write_dma_data8(addr + 1, (data >> 8) & 0xff);
287 uint32_t MEMORY::read_dma_data32(uint32_t addr)
289 int bank = (addr & ADDR_MASK) >> addr_shift;
291 if(rd_table[bank].dev != NULL) {
292 // return rd_table[bank].dev->read_memory_mapped_io32(addr);
295 uint32_t val = read_dma_data16(addr);
296 val |= read_dma_data16(addr + 2) << 16;
301 void MEMORY::write_dma_data32(uint32_t addr, uint32_t data)
303 int bank = (addr & ADDR_MASK) >> addr_shift;
305 if(wr_table[bank].dev != NULL) {
306 // wr_table[bank].dev->write_memory_mapped_io32(addr, data);
308 write_dma_data16(addr, data & 0xffff);
309 write_dma_data16(addr + 2, (data >> 16) & 0xffff);
316 void MEMORY::set_memory_r(uint32_t start, uint32_t end, uint8_t *memory)
318 MEMORY::initialize(); // subclass may overload initialize()
320 uint32_t start_bank = start >> addr_shift;
321 uint32_t end_bank = end >> addr_shift;
323 for(uint32_t i = start_bank; i <= end_bank; i++) {
324 rd_table[i].dev = NULL;
325 rd_table[i].memory = memory + bank_size * (i - start_bank);
329 void MEMORY::set_memory_w(uint32_t start, uint32_t end, uint8_t *memory)
331 MEMORY::initialize();
333 uint32_t start_bank = start >> addr_shift;
334 uint32_t end_bank = end >> addr_shift;
336 for(uint32_t i = start_bank; i <= end_bank; i++) {
337 wr_table[i].dev = NULL;
338 wr_table[i].memory = memory + bank_size * (i - start_bank);
342 void MEMORY::set_memory_mapped_io_r(uint32_t start, uint32_t end, DEVICE *device)
344 MEMORY::initialize();
346 uint32_t start_bank = start >> addr_shift;
347 uint32_t end_bank = end >> addr_shift;
349 for(uint32_t i = start_bank; i <= end_bank; i++) {
350 rd_table[i].dev = device;
354 void MEMORY::set_memory_mapped_io_w(uint32_t start, uint32_t end, DEVICE *device)
356 MEMORY::initialize();
358 uint32_t start_bank = start >> addr_shift;
359 uint32_t end_bank = end >> addr_shift;
361 for(uint32_t i = start_bank; i <= end_bank; i++) {
362 wr_table[i].dev = device;
366 void MEMORY::set_wait_r(uint32_t start, uint32_t end, int wait)
368 MEMORY::initialize();
370 uint32_t start_bank = start >> addr_shift;
371 uint32_t end_bank = end >> addr_shift;
373 for(uint32_t i = start_bank; i <= end_bank; i++) {
374 rd_table[i].wait = wait;
378 void MEMORY::set_wait_w(uint32_t start, uint32_t end, int wait)
380 MEMORY::initialize();
382 uint32_t start_bank = start >> addr_shift;
383 uint32_t end_bank = end >> addr_shift;
385 for(uint32_t i = start_bank; i <= end_bank; i++) {
386 wr_table[i].wait = wait;
390 void MEMORY::unset_memory_r(uint32_t start, uint32_t end)
392 MEMORY::initialize();
394 uint32_t start_bank = start >> addr_shift;
395 uint32_t end_bank = end >> addr_shift;
397 for(uint32_t i = start_bank; i <= end_bank; i++) {
398 rd_table[i].dev = NULL;
399 rd_table[i].memory = rd_dummy;
403 void MEMORY::unset_memory_w(uint32_t start, uint32_t end)
405 MEMORY::initialize();
407 uint32_t start_bank = start >> addr_shift;
408 uint32_t end_bank = end >> addr_shift;
410 for(uint32_t i = start_bank; i <= end_bank; i++) {
411 wr_table[i].dev = NULL;
412 wr_table[i].memory = wr_dummy;
416 void MEMORY::copy_table_w(uint32_t to, uint32_t start, uint32_t end)
418 MEMORY::initialize();
420 uint32_t start_bank = start >> addr_shift;
421 uint32_t end_bank = end >> addr_shift;
422 uint32_t to_bank = to >> addr_shift;
423 int blocks = (int)(addr_max / bank_size);
425 for(uint32_t i = start_bank; i <= end_bank; i++) {
426 if(to_bank >= blocks) break;
427 wr_table[to_bank].dev = wr_table[i].dev;
428 wr_table[to_bank].memory = wr_table[i].memory;
429 wr_table[to_bank].wait = wr_table[i].wait;
434 void MEMORY::copy_table_r(uint32_t to, uint32_t start, uint32_t end)
436 MEMORY::initialize();
438 uint32_t start_bank = start >> addr_shift;
439 uint32_t end_bank = end >> addr_shift;
440 uint32_t to_bank = to >> addr_shift;
441 int blocks = (int)(addr_max / bank_size);
443 for(uint32_t i = start_bank; i <= end_bank; i++) {
444 if(to_bank >= blocks) break;
445 rd_table[to_bank].dev = rd_table[i].dev;
446 rd_table[to_bank].memory = rd_table[i].memory;
447 rd_table[to_bank].wait = rd_table[i].wait;
454 int MEMORY::read_bios(const _TCHAR *file_name, uint8_t *buffer, int size)
456 FILEIO* fio = new FILEIO();
458 if(fio->Fopen(create_local_path(file_name), FILEIO_READ_BINARY)) {
459 fio->Fread(buffer, size, 1);
460 length = fio->Ftell();
463 out_debug_log("LOADING ROM %s REQ_SIZE=%d PRESENTED_SIZE=%d", create_local_path(file_name), size, length);
468 bool MEMORY::write_bios(const _TCHAR *file_name, uint8_t *buffer, int size)
470 FILEIO* fio = new FILEIO();
473 if(fio->Fopen(create_local_path(file_name), FILEIO_WRITE_BINARY)) {
474 fio->Fwrite(buffer, size, 1);
482 bool MEMORY::read_image(const _TCHAR *file_path, uint8_t *buffer, int size)
484 FILEIO* fio = new FILEIO();
487 if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
488 fio->Fread(buffer, size, 1);
496 bool MEMORY::write_image(const _TCHAR* file_path, uint8_t* buffer, int size)
498 FILEIO* fio = new FILEIO();
501 if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
502 fio->Fwrite(buffer, size, 1);