OSDN Git Service

197454a707fcf15d586a1250c62a969beb58c6e1
[csp-qt/common_source_project-fm7.git] / source / src / vm / familybasic / memory.cpp
1 /*
2         Nintendo Family BASIC Emulator 'eFamilyBASIC'
3
4         Origin : nester
5         Author : Takeda.Toshiya
6         Date   : 2010.08.11-
7
8         [ memory ]
9 */
10
11 #include "memory.h"
12 #include "ppu.h"
13 #include "../datarec.h"
14 #include "../ym2413.h"
15
16 #define EVENT_DMA_DONE  0
17
18 void MEMORY::initialize()
19 {
20         key_stat = emu->get_key_buffer();
21         joy_stat = emu->get_joy_buffer();
22         
23         // register event
24         register_vline_event(this);
25 }
26
27 void MEMORY::load_rom_image(const _TCHAR *file_name)
28 {
29         FILEIO* fio = new FILEIO();
30         
31         memset(save_ram, 0, sizeof(save_ram));
32         
33         if(fio->Fopen(create_local_path(file_name), FILEIO_READ_BINARY)) {
34                 // create save file name
35                 _TCHAR tmp_file_name[_MAX_PATH];
36                 my_tcscpy_s(tmp_file_name, _MAX_PATH, file_name);
37                 _TCHAR *dot = _tcsstr(tmp_file_name, _T("."));
38                 if(dot != NULL) dot[0] = _T('\0');
39                 my_stprintf_s(save_file_name, _MAX_PATH, _T("%s.SAV"), tmp_file_name);
40         } else {
41                 // for compatibility
42                 fio->Fopen(create_local_path(_T("BASIC.NES")), FILEIO_READ_BINARY);
43                 my_tcscpy_s(save_file_name, _MAX_PATH, _T("BACKUP.BIN"));
44         }
45         if(fio->IsOpened()) {
46                 // read header
47                 fio->Fread(&header, sizeof(header), 1);
48                 // read program rom
49                 rom_size = 0x2000 * header.num_8k_rom_banks();
50                 for(uint32_t bit = 0x80000; bit != 0; bit >>= 1) {
51                         if(rom_size & bit) {
52                                 if(rom_size & (bit - 1)) {
53                                         rom_size = (rom_size | (bit - 1)) + 1;
54                                 }
55                                 break;
56                         }
57                 }
58                 rom = (uint8_t *)calloc(rom_size, 1);
59                 fio->Fread(rom, 0x2000 * header.num_8k_rom_banks(), 1);
60                 fio->Fclose();
61         } else {
62                 memset(&header, 0, sizeof(header));
63                 header.dummy = 2; // 32KB
64                 rom_size = 0x2000 * header.num_8k_rom_banks();
65                 rom = (uint8_t *)calloc(rom_size, 1);
66                 memset(rom, 0xff, 0x2000 * header.num_8k_rom_banks());
67         }
68         if(fio->Fopen(create_local_path(save_file_name), FILEIO_READ_BINARY)) {
69                 fio->Fread(save_ram, sizeof(save_ram), 1);
70                 fio->Fclose();
71         }
72         delete fio;
73         
74         rom_mask = (rom_size / 0x2000) - 1;
75         save_ram_crc32 = get_crc32(save_ram, sizeof(save_ram));
76 }
77
78 void MEMORY::save_backup()
79 {
80         if(save_ram_crc32 != get_crc32(save_ram, sizeof(save_ram))) {
81                 FILEIO* fio = new FILEIO();
82                 if(fio->Fopen(create_local_path(save_file_name), FILEIO_WRITE_BINARY)) {
83                         fio->Fwrite(save_ram, sizeof(save_ram), 1);
84                         fio->Fclose();
85                 }
86                 delete fio;
87         }
88 }
89
90 void MEMORY::release()
91 {
92         if(rom != NULL) {
93                 free(rom);
94                 rom = NULL;
95         }
96         save_backup();
97 }
98
99 void MEMORY::reset()
100 {
101         memset(ram, 0, sizeof(ram));
102         
103         for(int i = 4; i < 8; i++) {
104                 set_rom_bank(i, i);
105         }
106         bank_ptr[3] = save_ram;
107         
108         dma_addr = 0x80;
109         frame_irq_enabled = 0xff;
110         
111         pad_strobe = false;
112         pad1_bits = pad2_bits = 0xff;
113         
114         kb_out = false;
115         kb_scan = 0;
116         
117         mmc5_reset();
118         vrc7_reset();
119 }
120
121 void MEMORY::write_data8(uint32_t addr, uint32_t data)
122 {
123         addr &= 0xffff;
124         
125         if(addr < 0x2000) {
126                 ram[addr & 0x7ff] = data;
127         } else if(addr < 0x4000) {
128                 d_ppu->write_data8(addr, data);
129         } else if(addr == 0x4014) {
130                 // stop cpu
131                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
132                 register_event_by_clock(this, EVENT_DMA_DONE, 514, false, NULL);
133                 // start dma
134                 dma_addr = data << 8;
135                 for(int i = 0; i < 256; i++) {
136                         spr_ram[i] = read_data8(dma_addr | i);
137                 }
138         } else if(addr == 0x4016) {
139                 if(data & 1) {
140                         pad_strobe = true;
141                 } else if(pad_strobe) {
142                         pad_strobe = false;
143                         // joypad #1
144                         pad1_bits = 0;
145                         if(joy_stat[0] & 0x10) pad1_bits |= 0x01;       // A
146                         if(joy_stat[0] & 0x20) pad1_bits |= 0x02;       // B
147                         if(joy_stat[0] & 0x40) pad1_bits |= 0x04;       // SEL
148                         if(joy_stat[0] & 0x80) pad1_bits |= 0x08;       // START
149                         if(joy_stat[0] & 0x01) pad1_bits |= 0x10;       // UP
150                         if(joy_stat[0] & 0x02) pad1_bits |= 0x20;       // DOWN
151                         if(joy_stat[0] & 0x04) pad1_bits |= 0x40;       // LEFT
152                         if(joy_stat[0] & 0x08) pad1_bits |= 0x80;       // RIGHT
153                         // joypad #2
154                         pad2_bits = 0;
155                         if(joy_stat[1] & 0x10) pad2_bits |= 0x01;       // A
156                         if(joy_stat[1] & 0x20) pad2_bits |= 0x02;       // B
157                         if(joy_stat[1] & 0x01) pad2_bits |= 0x10;       // UP
158                         if(joy_stat[1] & 0x02) pad2_bits |= 0x20;       // DOWN
159                         if(joy_stat[1] & 0x04) pad2_bits |= 0x40;       // LEFT
160                         if(joy_stat[1] & 0x08) pad2_bits |= 0x80;       // RIGHT
161                 }
162                 // keyboard
163                 if((data & 0x07) == 0x04) {
164                         if(++kb_scan > 9) {
165                                 kb_scan = 0;
166                         }
167                         kb_out = !kb_out;
168                 } else if((data & 0x07) == 0x05) {
169                         kb_out = false;
170                         kb_scan = 0;
171                 } else if((data & 0x07) == 0x06) {
172                         kb_out = !kb_out;
173                 }
174                 // data recorder (thanks MESS)
175                 if((data & 0x07) == 0x07) {
176                         d_drec->write_signal(SIG_DATAREC_MIC, 1, 1);
177                 } else {
178                         d_drec->write_signal(SIG_DATAREC_MIC, 0, 0);
179                 }
180         } else if(addr < 0x4018) {
181                 if(addr == 0x4017) {
182                         frame_irq_enabled = data;
183                 }
184                 d_apu->write_data8(addr, data);
185         } else if(addr < 0x6000) {
186                 if(header.mapper() == 5) {
187                         mmc5_lo_write(addr, data);
188 //              } else if(header.mapper() == 85) {
189 //                      vrc7_lo_write(addr, data);
190                 }
191         } else if(addr < 0x8000) {
192                 if(header.mapper() == 5) {
193                         mmc5_save_write(addr, data);
194 //              } else if(header.mapper() == 85) {
195 //                      vrc7_save_write(addr, data);
196                 } else {
197                         bank_ptr[3][addr & 0x1fff] = data;
198                 }
199         } else {
200                 if(header.mapper() == 5) {
201                         mmc5_hi_write(addr, data);
202                 } else if(header.mapper() == 85) {
203                         vrc7_hi_write(addr, data);
204                 }
205         }
206 }
207
208 uint32_t MEMORY::read_data8(uint32_t addr)
209 {
210         addr &= 0xffff;
211         
212         if(addr < 0x2000) {
213                 return ram[addr & 0x7ff];
214         } else if(addr < 0x4000) {
215                 return d_ppu->read_data8(addr);
216         } else if(addr == 0x4014) {
217                 return dma_addr >> 8;
218         } else if(addr < 0x4016) {
219                 uint32_t val = d_apu->read_data8(addr);
220                 if(addr == 0x4015 && !(frame_irq_enabled & 0xc0)) {
221                         val |= 0x40;
222                 }
223                 return val;
224         } else if(addr == 0x4016) {
225                 // joypad #1
226                 uint32_t val = pad1_bits & 1;
227                 pad1_bits >>= 1;
228                 // data recorder
229                 val |= d_drec->read_signal(0) ? 2 : 0;
230                 // mic
231                 val |= key_stat[0x7b] ? 4 : 0;  // F12
232                 return val;
233         } else if(addr == 0x4017) {
234                 // joypad #2
235                 uint32_t val = 0xfe | (pad2_bits & 1);
236                 pad2_bits >>= 1;
237                 // keyboard
238                 if(kb_out) {
239                         switch(kb_scan) {
240                         case 1:
241                                 if(key_stat[0x77]) val &= ~0x02;        // F8
242                                 if(key_stat[0x0d]) val &= ~0x04;        // RETURN
243                                 if(key_stat[0xdb]) val &= ~0x08;        // [
244                                 if(key_stat[0xdd]) val &= ~0x10;        // ]
245                                 break;
246                         case 2:
247                                 if(key_stat[0x76]) val &= ~0x02;        // F7
248                                 if(key_stat[0xc0]) val &= ~0x04;        // @
249                                 if(key_stat[0xba]) val &= ~0x08;        // :
250                                 if(key_stat[0xbb]) val &= ~0x10;        // ;
251                                 break;
252                         case 3:
253                                 if(key_stat[0x75]) val &= ~0x02;        // F6
254                                 if(key_stat[0x4f]) val &= ~0x04;        // O
255                                 if(key_stat[0x4c]) val &= ~0x08;        // L
256                                 if(key_stat[0x4b]) val &= ~0x10;        // K
257                                 break;
258                         case 4:
259                                 if(key_stat[0x74]) val &= ~0x02;        // F5
260                                 if(key_stat[0x49]) val &= ~0x04;        // I
261                                 if(key_stat[0x55]) val &= ~0x08;        // U
262                                 if(key_stat[0x4a]) val &= ~0x10;        // J
263                                 break;
264                         case 5:
265                                 if(key_stat[0x73]) val &= ~0x02;        // F4
266                                 if(key_stat[0x59]) val &= ~0x04;        // Y
267                                 if(key_stat[0x47]) val &= ~0x08;        // G
268                                 if(key_stat[0x48]) val &= ~0x10;        // H
269                                 break;
270                         case 6:
271                                 if(key_stat[0x72]) val &= ~0x02;        // F3
272                                 if(key_stat[0x54]) val &= ~0x04;        // T
273                                 if(key_stat[0x52]) val &= ~0x08;        // R
274                                 if(key_stat[0x44]) val &= ~0x10;        // D
275                                 break;
276                         case 7:
277                                 if(key_stat[0x71]) val &= ~0x02;        // F2
278                                 if(key_stat[0x57]) val &= ~0x04;        // W
279                                 if(key_stat[0x53]) val &= ~0x08;        // S
280                                 if(key_stat[0x41]) val &= ~0x10;        // A
281                                 break;
282                         case 8:
283                                 if(key_stat[0x70]) val &= ~0x02;        // F1
284                                 if(key_stat[0x1b]) val &= ~0x04;        // ESC
285                                 if(key_stat[0x51]) val &= ~0x08;        // Q
286                                 if(key_stat[0x11]) val &= ~0x10;        // CTRL
287                                 break;
288                         case 9:
289                                 if(key_stat[0x24]) val &= ~0x02;        // CLS
290                                 if(key_stat[0x26]) val &= ~0x04;        // UP
291                                 if(key_stat[0x27]) val &= ~0x08;        // RIGHT
292                                 if(key_stat[0x25]) val &= ~0x10;        // LEFT
293                                 break;
294                         }
295                 } else {
296                         switch(kb_scan) {
297                         case 1:
298                                 if(key_stat[0x15]) val &= ~0x02;        // KANA
299 //                              if(key_stat[0x10]) val &= ~0x04;        // RSHIFT
300                                 if(key_stat[0xdc]) val &= ~0x08;        // '\\'
301                                 if(key_stat[0x23]) val &= ~0x10;        // STOP
302                                 break;
303                         case 2:
304                                 if(key_stat[0xe2]) val &= ~0x02;        // _
305                                 if(key_stat[0xbf]) val &= ~0x04;        // /
306                                 if(key_stat[0xbd]) val &= ~0x08;        // -
307                                 if(key_stat[0xde]) val &= ~0x10;        // ^
308                                 break;
309                         case 3:
310                                 if(key_stat[0xbe]) val &= ~0x02;        // .
311                                 if(key_stat[0xbc]) val &= ~0x04;        // ,
312                                 if(key_stat[0x50]) val &= ~0x08;        // P
313                                 if(key_stat[0x30]) val &= ~0x10;        // 0
314                                 break;
315                         case 4:
316                                 if(key_stat[0x4d]) val &= ~0x02;        // M
317                                 if(key_stat[0x4e]) val &= ~0x04;        // N
318                                 if(key_stat[0x39]) val &= ~0x08;        // 9
319                                 if(key_stat[0x38]) val &= ~0x10;        // 8
320                                 break;
321                         case 5:
322                                 if(key_stat[0x42]) val &= ~0x02;        // B
323                                 if(key_stat[0x56]) val &= ~0x04;        // V
324                                 if(key_stat[0x37]) val &= ~0x08;        // 7
325                                 if(key_stat[0x36]) val &= ~0x10;        // 6
326                                 break;
327                         case 6:
328                                 if(key_stat[0x46]) val &= ~0x02;        // F
329                                 if(key_stat[0x43]) val &= ~0x04;        // C
330                                 if(key_stat[0x35]) val &= ~0x08;        // 5
331                                 if(key_stat[0x34]) val &= ~0x10;        // 4
332                                 break;
333                         case 7:
334                                 if(key_stat[0x58]) val &= ~0x02;        // X
335                                 if(key_stat[0x5a]) val &= ~0x04;        // Z
336                                 if(key_stat[0x45]) val &= ~0x08;        // E
337                                 if(key_stat[0x33]) val &= ~0x10;        // 3
338                                 break;
339                         case 8:
340                                 if(key_stat[0x10]) val &= ~0x02;        // LSHIFT
341                                 if(key_stat[0x12]) val &= ~0x04;        // GRAPH
342                                 if(key_stat[0x31]) val &= ~0x08;        // 1
343                                 if(key_stat[0x32]) val &= ~0x10;        // 2
344                                 break;
345                         case 9:
346                                 if(key_stat[0x28]) val &= ~0x02;        // DOWN
347                                 if(key_stat[0x20]) val &= ~0x04;        // SPACE
348                                 if(key_stat[0x2e]) val &= ~0x08;        // DEL
349                                 if(key_stat[0x2d]) val &= ~0x10;        // INS
350                                 break;
351                         }
352                 }
353                 return val;
354         } else if(addr < 0x6000) {
355                 if(header.mapper() == 5) {
356                         return mmc5_lo_read(addr);
357 //              } else if(header.mapper() == 85) {
358 //                      return vrc7_lo_read(addr);
359                 } else {
360                         return 0xff;
361                 }
362         } else if(addr < 0x8000) {
363 //              if(header.mapper() == 5) {
364 //                      return mmc5_save_read(addr);
365 //              } else if(header.mapper() == 85) {
366 //                      return vrc7_save_read(addr);
367 //              } else {
368                         return bank_ptr[3][addr & 0x1fff];
369 //              }
370         } else if(addr < 0xa000) {
371                 return bank_ptr[4][addr & 0x1fff];
372         } else if(addr < 0xc000) {
373                 return bank_ptr[5][addr & 0x1fff];
374         } else if(addr < 0xe000) {
375                 return bank_ptr[6][addr & 0x1fff];
376         } else {
377                 return bank_ptr[7][addr & 0x1fff];
378         }
379 }
380
381 void MEMORY::event_vline(int v, int clock)
382 {
383         // 525 -> 262.5
384         if(v & 1) {
385                 return;
386         }
387         v >>= 1;
388         
389         // fram irq
390         if(v == 240 && !(frame_irq_enabled & 0xc0)) {
391                 // pending
392                 d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
393         }
394         
395         // mapper irq
396         if(header.mapper() == 5) {
397                 mmc5_hsync(v);
398         } else if(header.mapper() == 85) {
399                 vrc7_hsync(v);
400         }
401 }
402
403 void MEMORY::event_callback(int event_id, int err)
404 {
405         // dma done
406         d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
407 }
408
409 void MEMORY::set_rom_bank(uint8_t bank, uint32_t bank_num)
410 {
411         bank_ptr[bank] = rom + 0x2000 * (bank_num & rom_mask);
412         banks[bank] = bank_num;
413         
414         // mmc5
415         mmc5_wram_bank[bank] = 8;
416 }
417
418 // mmc5
419
420 void MEMORY::mmc5_reset()
421 {
422         if(header.mapper() == 5) {
423                 mmc5_set_wram_bank(3, 0);
424                 set_rom_bank(4, header.num_8k_rom_banks() - 1);
425                 set_rom_bank(5, header.num_8k_rom_banks() - 1);
426                 set_rom_bank(6, header.num_8k_rom_banks() - 1);
427                 set_rom_bank(7, header.num_8k_rom_banks() - 1);
428                 
429                 for(int i = 0; i < 8; i++) {
430                         mmc5_chr_reg[i][0] = i;
431                         mmc5_chr_reg[i][1] = (i & 0x03) + 4;
432                 }
433                 mmc5_wram_protect0 = 0x02;
434                 mmc5_wram_protect1 = 0x01;
435                 mmc5_prg_size = 3;
436                 mmc5_chr_size = 3;
437                 mmc5_gfx_mode = 0;
438 //              mmc5_split_control = 0;
439 //              mmc5_split_bank = 0;
440                 mmc5_irq_enabled = 0;
441                 mmc5_irq_status = 0;
442                 mmc5_irq_line = 0;
443         }
444 }
445
446 uint32_t MEMORY::mmc5_lo_read(uint32_t addr)
447 {
448         uint8_t data = (uint8_t)(addr >> 8);
449         
450         if(addr == 0x5204) {
451                 data = mmc5_irq_status;
452                 mmc5_irq_status &= ~0x80;
453         } else if(addr == 0x5205) {
454                 data = (uint8_t)(((mmc5_value0 * mmc5_value1) & 0x00ff) >> 0);
455         } else if(addr == 0x5206) {
456                 data = (uint8_t)(((mmc5_value0 * mmc5_value1) & 0xff00) >> 8);
457         } else if(addr >= 0x5c00 && addr < 0x6000) {
458                 if(mmc5_gfx_mode == 2 || mmc5_gfx_mode == 3) {
459                         data = (d_ppu->get_name_tables() + 0x800)[addr & 0x3ff];
460                 }
461         }
462         return data;
463 }
464
465 void MEMORY::mmc5_lo_write(uint32_t addr, uint32_t data)
466 {
467         switch(addr) {
468         case 0x5100:
469                 mmc5_prg_size = data & 0x03;
470                 break;
471         case 0x5101:
472                 mmc5_chr_size = data & 0x03;
473                 break;
474         case 0x5102:
475                 mmc5_wram_protect0 = data & 0x03;
476                 break;
477         case 0x5103:
478                 mmc5_wram_protect1 = data & 0x03;
479                 break;
480         case 0x5104:
481                 mmc5_gfx_mode = data & 0x03;
482                 break;
483         case 0x5105:
484                 for(int i = 0; i < 4; i++) {
485                         d_ppu->set_ppu_bank(8 + i, data & 0x03);
486                         data >>= 2;
487                 }
488                 break;
489         case 0x5106:
490                 for(int i = 0; i < 0x3c0; i++) {
491                         (d_ppu->get_name_tables() + 0xc00)[i] = data;
492                 }
493                 break;
494         case 0x5107:
495                 for(int i = 0x3c0; i < 0x400; i++) {
496                         (d_ppu->get_name_tables() + 0xc00)[i] = 0x55 * (data & 3);
497                 }
498                 break;
499         case 0x5113:
500                 mmc5_set_wram_bank(3, data & 0x07);
501                 break;
502         case 0x5114:
503         case 0x5115:
504         case 0x5116:
505         case 0x5117:
506                 mmc5_set_cpu_bank(addr & 0x07, data);
507                 break;
508         case 0x5120:
509         case 0x5121:
510         case 0x5122:
511         case 0x5123:
512         case 0x5124:
513         case 0x5125:
514         case 0x5126:
515         case 0x5127:
516                 mmc5_chr_reg[addr & 0x07][0] = data;
517                 mmc5_set_ppu_bank(0);
518                 break;
519         case 0x5128:
520         case 0x5129:
521         case 0x512a:
522         case 0x512b:
523                 mmc5_chr_reg[(addr & 0x03) + 0][1] = data;
524                 mmc5_chr_reg[(addr & 0x03) + 4][1] = data;
525                 break;
526         case 0x5200:
527 //              mmc5_split_control = data;
528                 break;
529         case 0x5201:
530 //              mmc5_split_scroll = data;
531                 break;
532         case 0x5202:
533 //              mmc5_split_bank = data & 0x3f;
534                 break;
535         case 0x5203:
536                 mmc5_irq_line = data;
537                 break;
538         case 0x5204:
539                 mmc5_irq_enabled = data;
540                 break;
541         case 0x5205:
542                 mmc5_value0 = data;
543                 break;
544         case 0x5206:
545                 mmc5_value1 = data;
546                 break;
547         default:
548                 if(addr >= 0x5000 && addr <= 0x5015) {
549 //                      d_mmc5->write_io8(addr, data);
550                 } else if(addr >= 0x5c00 && addr <= 0x5fff) {
551                         if(mmc5_gfx_mode != 3) {
552                                 (d_ppu->get_name_tables() + 0x800)[addr & 0x3ff] = data; //(mmc5_irq_status & 0) ? data : 0x40;
553                         }
554                 }
555                 break;
556         }
557 }
558
559 //uint32_t MEMORY::mmc5_save_read(uint32_t addr)
560 //{
561 //      return bank_ptr[3][addr & 0x1fff];
562 //}
563
564 void MEMORY::mmc5_save_write(uint32_t addr, uint32_t data)
565 {
566         if(mmc5_wram_protect0 == 0x02 && mmc5_wram_protect1 == 0x01) {
567                 if(mmc5_wram_bank[3] < 8) {
568                         bank_ptr[3][addr & 0x1fff] = data;
569                 }
570         }
571 }
572
573 void MEMORY::mmc5_hi_write(uint32_t addr, uint32_t data)
574 {
575         if(mmc5_wram_protect0 == 0x02 && mmc5_wram_protect1 == 0x01) {
576                 if(addr < 0xa000) {
577                         if(mmc5_wram_bank[4] < 8) {
578                                 bank_ptr[4][addr & 0x1fff] = data;
579                         }
580                 } else if(addr < 0xc000) {
581                         if(mmc5_wram_bank[5] < 8) {
582                                 bank_ptr[5][addr & 0x1fff] = data;
583                         }
584                 } else if(addr < 0xe000) {
585                         if(mmc5_wram_bank[6] < 8) {
586                                 bank_ptr[6][addr & 0x1fff] = data;
587                         }
588                 } else {
589                         if(mmc5_wram_bank[7] < 8) {
590                                 bank_ptr[7][addr & 0x1fff] = data;
591                         }
592                 }
593         }
594 }
595
596 void MEMORY::mmc5_hsync(int v)
597 {
598         if(v <= 240) {
599                 if(v == mmc5_irq_line) {
600                         if(d_ppu->spr_enabled() && d_ppu->bg_enabled()) {
601                                 mmc5_irq_status |= 0x80;
602                         }
603                 }
604                 if((mmc5_irq_status & 0x80) && (mmc5_irq_enabled & 0x80)) {
605                         d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
606                 }
607         } else {
608                 mmc5_irq_status |= 0x40;
609         }
610 }
611
612 void MEMORY::mmc5_set_cpu_bank(uint8_t bank, uint32_t bank_num)
613 {
614         if(bank_num & 0x80) {
615                 if(mmc5_prg_size == 0) {
616                         if(bank == 7) {
617                                 set_rom_bank(4, (bank_num & 0x7c) + 0);
618                                 set_rom_bank(5, (bank_num & 0x7c) + 1);
619                                 set_rom_bank(6, (bank_num & 0x7c) + 2);
620                                 set_rom_bank(7, (bank_num & 0x7c) + 3);
621                         }
622                 } else if(mmc5_prg_size == 1) {
623                         if(bank == 5) {
624                                 set_rom_bank(4, (bank_num & 0x7e) + 0);
625                                 set_rom_bank(5, (bank_num & 0x7e) + 1);
626                         } else if(bank == 7) {
627                                 set_rom_bank(6, (bank_num & 0x7e) + 0);
628                                 set_rom_bank(7, (bank_num & 0x7e) + 1);
629                         }
630                 } else if(mmc5_prg_size == 2) {
631                         if(bank == 5) {
632                                 set_rom_bank(4, (bank_num & 0x7e) + 0);
633                                 set_rom_bank(5, (bank_num & 0x7e) + 1);
634                         } else if(bank == 6) {
635                                 set_rom_bank(6, bank_num & 0x7f);
636                         } else if(bank == 7) {
637                                 set_rom_bank(7, bank_num & 0x7f);
638                         }
639                 } else if(mmc5_prg_size == 3) {
640                         if(bank == 4) {
641                                 set_rom_bank(4, bank_num & 0x7f);
642                         } else if(bank == 5) {
643                                 set_rom_bank(5, bank_num & 0x7f);
644                         } else if(bank == 6) {
645                                 set_rom_bank(6, bank_num & 0x7f);
646                         } else if(bank == 7) {
647                                 set_rom_bank(7, bank_num & 0x7f);
648                         }
649                 }
650         } else {
651                 if(mmc5_prg_size == 1) {
652                         if(bank == 5) {
653                                 mmc5_set_wram_bank(4, (bank_num & 0x06)+0);
654                                 mmc5_set_wram_bank(5, (bank_num & 0x06)+1);
655                         }
656                 } else if(mmc5_prg_size == 2) {
657                         if(bank == 5) {
658                                 mmc5_set_wram_bank(4, (bank_num & 0x06)+0);
659                                 mmc5_set_wram_bank(5, (bank_num & 0x06)+1);
660                         } else  if(bank == 6)
661                         {
662                                 mmc5_set_wram_bank(6, bank_num & 0x07);
663                         }
664                 } else if(mmc5_prg_size == 3) {
665                         if(bank == 4) {
666                                 mmc5_set_wram_bank(4, bank_num & 0x07);
667                         } else if(bank == 5) {
668                                 mmc5_set_wram_bank(5, bank_num & 0x07);
669                         } else if(bank == 6) {
670                                 mmc5_set_wram_bank(6, bank_num & 0x07);
671                         }
672                 }
673         }
674 }
675
676 void MEMORY::mmc5_set_wram_bank(uint8_t bank, uint32_t bank_num)
677 {
678         if(bank_num < 8) {
679                 bank_ptr[bank] = save_ram + 0x2000 * bank_num;
680                 mmc5_wram_bank[bank] = bank_num;
681         } else {
682                 set_rom_bank(bank, banks[bank]);
683         }
684 }
685
686 void MEMORY::mmc5_set_ppu_bank(uint8_t mode)
687 {
688         if(mmc5_chr_size == 0) {
689                 d_ppu->set_ppu_bank(0, mmc5_chr_reg[7][mode] * 8 + 0);
690                 d_ppu->set_ppu_bank(1, mmc5_chr_reg[7][mode] * 8 + 1);
691                 d_ppu->set_ppu_bank(2, mmc5_chr_reg[7][mode] * 8 + 2);
692                 d_ppu->set_ppu_bank(3, mmc5_chr_reg[7][mode] * 8 + 3);
693                 d_ppu->set_ppu_bank(4, mmc5_chr_reg[7][mode] * 8 + 4);
694                 d_ppu->set_ppu_bank(5, mmc5_chr_reg[7][mode] * 8 + 5);
695                 d_ppu->set_ppu_bank(6, mmc5_chr_reg[7][mode] * 8 + 6);
696                 d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode] * 8 + 7);
697         } else if(mmc5_chr_size == 1) {
698                 d_ppu->set_ppu_bank(0, mmc5_chr_reg[3][mode] * 4 + 0);
699                 d_ppu->set_ppu_bank(1, mmc5_chr_reg[3][mode] * 4 + 1);
700                 d_ppu->set_ppu_bank(2, mmc5_chr_reg[3][mode] * 4 + 2);
701                 d_ppu->set_ppu_bank(3, mmc5_chr_reg[3][mode] * 4 + 3);
702                 d_ppu->set_ppu_bank(4, mmc5_chr_reg[7][mode] * 4 + 0);
703                 d_ppu->set_ppu_bank(5, mmc5_chr_reg[7][mode] * 4 + 1);
704                 d_ppu->set_ppu_bank(6, mmc5_chr_reg[7][mode] * 4 + 2);
705                 d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode] * 4 + 3);
706         } else if(mmc5_chr_size == 2) {
707                 d_ppu->set_ppu_bank(0, mmc5_chr_reg[1][mode] * 2 + 0);
708                 d_ppu->set_ppu_bank(1, mmc5_chr_reg[1][mode] * 2 + 1);
709                 d_ppu->set_ppu_bank(2, mmc5_chr_reg[3][mode] * 2 + 0);
710                 d_ppu->set_ppu_bank(3, mmc5_chr_reg[3][mode] * 2 + 1);
711                 d_ppu->set_ppu_bank(4, mmc5_chr_reg[5][mode] * 2 + 0);
712                 d_ppu->set_ppu_bank(5, mmc5_chr_reg[5][mode] * 2 + 1);
713                 d_ppu->set_ppu_bank(6, mmc5_chr_reg[7][mode] * 2 + 0);
714                 d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode] * 2 + 1);
715         } else {
716                 d_ppu->set_ppu_bank(0, mmc5_chr_reg[0][mode]);
717                 d_ppu->set_ppu_bank(1, mmc5_chr_reg[1][mode]);
718                 d_ppu->set_ppu_bank(2, mmc5_chr_reg[2][mode]);
719                 d_ppu->set_ppu_bank(3, mmc5_chr_reg[3][mode]);
720                 d_ppu->set_ppu_bank(4, mmc5_chr_reg[4][mode]);
721                 d_ppu->set_ppu_bank(5, mmc5_chr_reg[5][mode]);
722                 d_ppu->set_ppu_bank(6, mmc5_chr_reg[6][mode]);
723                 d_ppu->set_ppu_bank(7, mmc5_chr_reg[7][mode]);
724         }
725 }
726
727 uint8_t MEMORY::mmc5_ppu_latch_render(uint8_t mode, uint32_t addr)
728 {
729         uint8_t data = 0;
730         
731         if(mmc5_gfx_mode == 1 && mode == 1) {
732                 // ex gfx mode
733                 uint32_t bank_num = ((d_ppu->get_name_tables() + 0x800)[addr] & 0x3f) << 2;
734                 d_ppu->set_ppu_bank(0, bank_num + 0);
735                 d_ppu->set_ppu_bank(1, bank_num + 1);
736                 d_ppu->set_ppu_bank(2, bank_num + 2);
737                 d_ppu->set_ppu_bank(3, bank_num + 3);
738                 d_ppu->set_ppu_bank(4, bank_num + 0);
739                 d_ppu->set_ppu_bank(5, bank_num + 1);
740                 d_ppu->set_ppu_bank(6, bank_num + 2);
741                 d_ppu->set_ppu_bank(7, bank_num + 3);
742                 data = (((d_ppu->get_name_tables() + 0x800)[addr] & 0xc0) >> 4) | 0x01;
743         } else {
744                 // normal
745                 mmc5_set_ppu_bank(mode);
746         }
747         return data;
748 }
749
750 // vrc7
751
752 void MEMORY::vrc7_reset()
753 {
754         if(header.mapper() == 85) {
755                 vrc7_irq_enabled = 0;
756                 vrc7_irq_counter = 0;
757                 vrc7_irq_latch = 0;
758                 d_opll->write_signal(SIG_YM2413_MUTE, 0, 0);
759                 set_rom_bank(4, 0);
760                 set_rom_bank(5, 1);
761                 set_rom_bank(6, header.num_8k_rom_banks() - 2);
762                 set_rom_bank(7, header.num_8k_rom_banks() - 1);
763         } else {
764                 d_opll->write_signal(SIG_YM2413_MUTE, 1, 1);
765         }
766 }
767
768 //uint32_t MEMORY::vrc7_lo_read(uint32_t addr)
769 //{
770 //      return 0xff;
771 //}
772
773 //void MEMORY::vrc7_lo_write(uint32_t addr, uint32_t data)
774 //{
775 //}
776
777 //uint32_t MEMORY::vrc7_save_read(uint32_t addr)
778 //{
779 //      return bank_ptr[3][addr & 0x1fff];
780 //}
781
782 //void MEMORY::vrc7_save_write(uint32_t addr, uint32_t data)
783 //{
784 //      bank_ptr[3][addr & 0x1fff] = data;
785 //}
786
787 void MEMORY::vrc7_hi_write(uint32_t addr, uint32_t data)
788 {
789         switch(addr & 0xf038) {
790         case 0x8000:
791                 set_rom_bank(4, data);
792                 break;
793         case 0x8008:
794         case 0x8010:
795                 set_rom_bank(5, data);
796                 break;
797         case 0x9000:
798                 set_rom_bank(6, data);
799                 break;
800         case 0x9010:
801         case 0x9030:
802                 d_opll->write_io8(addr >> 5, data);
803                 break;
804         case 0xa000:
805                 d_ppu->set_ppu_bank(0, data);
806                 break;
807         case 0xa008:
808         case 0xa010:
809                 d_ppu->set_ppu_bank(1, data);
810                 break;
811         case 0xb000:
812                 d_ppu->set_ppu_bank(2, data);
813                 break;
814         case 0xb008:
815         case 0xb010:
816                 d_ppu->set_ppu_bank(3, data);
817                 break;
818         case 0xc000:
819                 d_ppu->set_ppu_bank(4, data);
820                 break;
821         case 0xc008:
822         case 0xc010:
823                 d_ppu->set_ppu_bank(5, data);
824                 break;
825         case 0xd000:
826                 d_ppu->set_ppu_bank(6, data);
827                 break;
828         case 0xd008:
829         case 0xd010:
830                 d_ppu->set_ppu_bank(7, data);
831                 break;
832         case 0xe000:
833                 switch(data & 0x03) {
834                 case 0x00:
835                         d_ppu->set_mirroring(MIRROR_VERT);
836                         break;
837                 case 0x01:
838                         d_ppu->set_mirroring(MIRROR_HORIZ);
839                         break;
840                 case 0x02:
841                         d_ppu->set_mirroring(0, 0, 0, 0);
842                         break;
843                 case 0x03:
844                         d_ppu->set_mirroring(1, 1, 1, 1);
845                         break;
846                 }
847                 break;
848         case 0xe008:
849         case 0xe010:
850                 vrc7_irq_latch = data;
851                 break;
852         case 0xf000:
853                 if(data & 0x02) {
854                         vrc7_irq_counter = vrc7_irq_latch;
855                 }
856                 vrc7_irq_enabled = data & 0x03;
857                 break;
858         case 0xf008:
859         case 0xf010:
860                 vrc7_irq_enabled = (vrc7_irq_enabled & 0x01) * 3;
861                 break;
862         }
863 }
864
865 void MEMORY::vrc7_hsync(int v)
866 {
867         if(vrc7_irq_enabled & 0x02) {
868                 if(vrc7_irq_counter == 0xff) {
869                         d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);
870                         vrc7_irq_counter = vrc7_irq_latch;
871                 } else {
872                         vrc7_irq_counter++;
873                 }
874         }
875 }
876
877 #define STATE_VERSION   2
878
879 #include "../../statesub.h"
880
881 void MEMORY::decl_state_header(header_t *p)
882 {
883         DECL_STATE_ENTRY_1D_ARRAY((p->id), 3);  // 'NES'
884         DECL_STATE_ENTRY_UINT8((p->ctrl_z));    // control-z
885         DECL_STATE_ENTRY_UINT8((p->dummy));
886         DECL_STATE_ENTRY_UINT8((p->num_8k_vrom_banks));
887         DECL_STATE_ENTRY_UINT8((p->flags_1));
888         DECL_STATE_ENTRY_UINT8((p->flags_2));
889         DECL_STATE_ENTRY_1D_ARRAY((p->reserved), 1);
890 }
891
892 void MEMORY::decl_state()
893 {
894         enter_decl_state(STATE_VERSION);
895
896         DECL_STATE_ENTRY_STRING(save_file_name, sizeof(save_file_name) / sizeof(_TCHAR));
897         decl_state_header(&header);
898
899         DECL_STATE_ENTRY_UINT32(rom_size);
900 //      DECL_STATE_ENTRY_UINT32(rom_mask);
901         DECL_STATE_ENTRY_VARARRAY_VAR(rom, rom_size);
902         DECL_STATE_ENTRY_1D_ARRAY(ram, sizeof(ram));
903         DECL_STATE_ENTRY_1D_ARRAY(save_ram, sizeof(save_ram));
904         DECL_STATE_ENTRY_UINT32(save_ram_crc32);
905         DECL_STATE_ENTRY_1D_ARRAY(banks, sizeof(banks) / sizeof(uint32_t));
906         DECL_STATE_ENTRY_UINT16(dma_addr);
907         DECL_STATE_ENTRY_UINT8(frame_irq_enabled);
908         DECL_STATE_ENTRY_1D_ARRAY(mmc5_wram_bank, sizeof(mmc5_wram_bank)/ sizeof(uint32_t));
909         DECL_STATE_ENTRY_2D_ARRAY(mmc5_chr_reg, 8, 2);
910         DECL_STATE_ENTRY_UINT32(mmc5_value0);
911         DECL_STATE_ENTRY_UINT32(mmc5_value0);
912         DECL_STATE_ENTRY_UINT8(mmc5_wram_protect0);
913         DECL_STATE_ENTRY_UINT8(mmc5_wram_protect1);
914         DECL_STATE_ENTRY_UINT8(mmc5_prg_size);
915         DECL_STATE_ENTRY_UINT8(mmc5_chr_size);
916         DECL_STATE_ENTRY_UINT8(mmc5_gfx_mode);
917 //      DECL_STATE_ENTRY_UINT8(mmc5_split_control);
918 //      DECL_STATE_ENTRY_UINT8(mmc5_split_bank);
919         DECL_STATE_ENTRY_UINT8(mmc5_irq_enabled);
920         DECL_STATE_ENTRY_UINT8(mmc5_irq_status);
921         DECL_STATE_ENTRY_UINT32(mmc5_irq_line);
922         DECL_STATE_ENTRY_UINT8(vrc7_irq_enabled);
923         DECL_STATE_ENTRY_UINT8(vrc7_irq_counter);
924         DECL_STATE_ENTRY_UINT8(vrc7_irq_latch);
925         DECL_STATE_ENTRY_BOOL(pad_strobe);
926         DECL_STATE_ENTRY_UINT8(pad1_bits);
927         DECL_STATE_ENTRY_UINT8(pad2_bits);
928         DECL_STATE_ENTRY_BOOL(kb_out);
929         DECL_STATE_ENTRY_UINT8(kb_scan);
930
931         leave_decl_state();
932 }
933 void MEMORY::save_state(FILEIO* state_fio)
934 {
935         if(state_entry != NULL) {
936                 state_entry->save_state(state_fio);
937         }
938 //      state_fio->FputUint32(STATE_VERSION);
939 //      state_fio->FputInt32(this_device_id);
940         
941 //      state_fio->Fwrite(save_file_name, sizeof(save_file_name), 1);
942 //      state_fio->Fwrite(&header, sizeof(header), 1);
943 //      state_fio->FputUint32(rom_size);
944 ////    state_fio->FputUint32(rom_mask);
945 //      state_fio->Fwrite(rom, rom_size, 1);
946 //      state_fio->Fwrite(ram, sizeof(ram), 1);
947 //      state_fio->Fwrite(save_ram, sizeof(save_ram), 1);
948 //      state_fio->FputUint32(save_ram_crc32);
949 //      state_fio->Fwrite(banks, sizeof(banks), 1);
950 //      state_fio->FputUint16(dma_addr);
951 //      state_fio->FputUint8(frame_irq_enabled);
952 //      state_fio->Fwrite(mmc5_wram_bank, sizeof(mmc5_wram_bank), 1);
953 //      state_fio->Fwrite(mmc5_chr_reg, sizeof(mmc5_chr_reg), 1);
954 //      state_fio->FputUint32(mmc5_value0);
955 //      state_fio->FputUint32(mmc5_value0);
956 //      state_fio->FputUint8(mmc5_wram_protect0);
957 //      state_fio->FputUint8(mmc5_wram_protect1);
958 //      state_fio->FputUint8(mmc5_prg_size);
959 //      state_fio->FputUint8(mmc5_chr_size);
960 //      state_fio->FputUint8(mmc5_gfx_mode);
961 //      state_fio->FputUint8(mmc5_split_control);
962 //      state_fio->FputUint8(mmc5_split_bank);
963 //      state_fio->FputUint8(mmc5_irq_enabled);
964 //      state_fio->FputUint8(mmc5_irq_status);
965 //      state_fio->FputUint32(mmc5_irq_line);
966 //      state_fio->FputUint8(vrc7_irq_enabled);
967 //      state_fio->FputUint8(vrc7_irq_counter);
968 //      state_fio->FputUint8(vrc7_irq_latch);
969 //      state_fio->FputBool(pad_strobe);
970 //      state_fio->FputUint8(pad1_bits);
971 //      state_fio->FputUint8(pad2_bits);
972 //      state_fio->FputBool(kb_out);
973 //      state_fio->FputUint8(kb_scan);
974 }
975
976 bool MEMORY::load_state(FILEIO* state_fio)
977 {
978         bool mb = false;
979         if(state_entry != NULL) {
980                 mb = state_entry->load_state(state_fio);
981         }
982         if(!mb) return false;
983 //      if(state_fio->FgetUint32() != STATE_VERSION) {
984 //              return false;
985 //      }
986 //      if(state_fio->FgetInt32() != this_device_id) {
987 //              return false;
988 //      }
989 //      state_fio->Fread(save_file_name, sizeof(save_file_name), 1);
990 //      state_fio->Fread(&header, sizeof(header), 1);
991 //      rom_size = state_fio->FgetUint32();
992 ////    rom_mask = state_fio->FgetUint32();
993         rom_mask = (rom_size / 0x2000) - 1;
994 //      if(rom != NULL) {
995 //              free(rom);
996 //      }
997 //      rom = (uint8_t *)malloc(rom_size);
998 //      state_fio->Fread(rom, rom_size, 1);
999 //      state_fio->Fread(ram, sizeof(ram), 1);
1000 //      state_fio->Fread(save_ram, sizeof(save_ram), 1);
1001 //      save_ram_crc32 = state_fio->FgetUint32();
1002 //      state_fio->Fread(banks, sizeof(banks), 1);
1003 //      dma_addr = state_fio->FgetUint16();
1004 //      frame_irq_enabled = state_fio->FgetUint8();
1005 //      state_fio->Fread(mmc5_wram_bank, sizeof(mmc5_wram_bank), 1);
1006 //      state_fio->Fread(mmc5_chr_reg, sizeof(mmc5_chr_reg), 1);
1007 //      mmc5_value0 = state_fio->FgetUint32();
1008 //      mmc5_value0 = state_fio->FgetUint32();
1009 //      mmc5_wram_protect0 = state_fio->FgetUint8();
1010 //      mmc5_wram_protect1 = state_fio->FgetUint8();
1011 //      mmc5_prg_size = state_fio->FgetUint8();
1012 //      mmc5_chr_size = state_fio->FgetUint8();
1013 //      mmc5_gfx_mode = state_fio->FgetUint8();
1014 //      mmc5_split_control = state_fio->FgetUint8();
1015 //      mmc5_split_bank = state_fio->FgetUint8();
1016 //      mmc5_irq_enabled = state_fio->FgetUint8();
1017 //      mmc5_irq_status = state_fio->FgetUint8();
1018 //      mmc5_irq_line = state_fio->FgetUint32();
1019 //      vrc7_irq_enabled = state_fio->FgetUint8();
1020 //      vrc7_irq_counter = state_fio->FgetUint8();
1021 //      vrc7_irq_latch = state_fio->FgetUint8();
1022 //      pad_strobe = state_fio->FgetBool();
1023 //      pad1_bits = state_fio->FgetUint8();
1024 //      pad2_bits = state_fio->FgetUint8();
1025 //      kb_out = state_fio->FgetBool();
1026 //      kb_scan = state_fio->FgetUint8();
1027         
1028         // post process
1029         if(header.mapper() == 5) {
1030                 for(int i = 3; i < 8; i++) {
1031                         mmc5_set_wram_bank(i, mmc5_wram_bank[i]);
1032                 }
1033         } else {
1034                 for(int i = 4; i < 8; i++) {
1035                         set_rom_bank(i, banks[i]);
1036                 }
1037                 bank_ptr[3] = save_ram;
1038         }
1039         return true;
1040 }
1041