OSDN Git Service

[INITIAL] Import 20141226 version of http://homepage3.nifty.com/takeda-toshiya/common...
[csp-qt/common_source_project-fm7.git] / source / src / vm / familybasic / memory.cpp
1 /*\r
2         Nintendo Family BASIC Emulator 'eFamilyBASIC'\r
3 \r
4         Origin : nester\r
5         Author : Takeda.Toshiya\r
6         Date   : 2010.08.11-\r
7 \r
8         [ memory ]\r
9 */\r
10 \r
11 #include "memory.h"\r
12 #include "../datarec.h"\r
13 #include "../../fileio.h"\r
14 \r
15 #define EVENT_DMA_DONE  0\r
16 \r
17 void MEMORY::initialize()\r
18 {\r
19         memset(ram, 0, sizeof(ram));\r
20         \r
21         key_stat = emu->key_buffer();\r
22         joy_stat = emu->joy_buffer();\r
23         \r
24         // register event\r
25         register_vline_event(this);\r
26 }\r
27 \r
28 void MEMORY::load_rom_image(_TCHAR *file_name)\r
29 {\r
30         FILEIO* fio = new FILEIO();\r
31         bool file_open = false;\r
32         \r
33         if(fio->Fopen(emu->bios_path(file_name), FILEIO_READ_BINARY)) {\r
34                 file_open = true;\r
35                 // create save file name\r
36                 _TCHAR tmp_file_name[_MAX_PATH];\r
37                 _tcscpy(tmp_file_name, file_name);\r
38                 _TCHAR *dot = _tcsstr(tmp_file_name, _T("."));\r
39                 if(dot != NULL) dot[0] = _T('\0');\r
40                 _stprintf(save_file_name, _T("%s.SAV"), tmp_file_name);\r
41         } else {\r
42                 // for compatibility\r
43                 if(fio->Fopen(emu->bios_path(_T("BASIC.NES")), FILEIO_READ_BINARY)) {\r
44                         file_open = true;\r
45                 }\r
46                 _tcscpy(save_file_name, _T("BACKUP.BIN"));\r
47         }\r
48         if(file_open) {\r
49                 // read header\r
50                 fio->Fread(header, sizeof(header), 1);\r
51                 // read program rom (max 32kb)\r
52                 fio->Fread(rom, 0x4000, 1);\r
53                 memcpy(rom + 0x4000, rom, 0x4000);\r
54                 fio->Fread(rom + 0x4000, 0x4000, 1);\r
55                 fio->Fclose();\r
56         } else {\r
57                 memset(header, 0, sizeof(header));\r
58                 memset(rom, 0xff, sizeof(rom));\r
59         }\r
60         if(fio->Fopen(emu->bios_path(save_file_name), FILEIO_READ_BINARY)) {\r
61                 fio->Fread(save_ram, sizeof(save_ram), 1);\r
62                 fio->Fclose();\r
63         } else {\r
64                 memset(save_ram, 0, sizeof(save_ram));\r
65         }\r
66         delete fio;\r
67         \r
68         save_ram_crc32 = getcrc32(save_ram, sizeof(save_ram));\r
69 }\r
70 \r
71 void MEMORY::save_backup()\r
72 {\r
73         if(save_ram_crc32 != getcrc32(save_ram, sizeof(save_ram))) {\r
74                 FILEIO* fio = new FILEIO();\r
75                 if(fio->Fopen(emu->bios_path(save_file_name), FILEIO_WRITE_BINARY)) {\r
76                         fio->Fwrite(save_ram, sizeof(save_ram), 1);\r
77                         fio->Fclose();\r
78                 }\r
79                 delete fio;\r
80         }\r
81 }\r
82 \r
83 void MEMORY::release()\r
84 {\r
85         save_backup();\r
86 }\r
87 \r
88 void MEMORY::reset()\r
89 {\r
90         dma_addr = 0x80;\r
91         frame_irq_enabled = 0xff;\r
92         \r
93         pad_strobe = false;\r
94         pad1_bits = pad2_bits = 0xff;\r
95         \r
96         kb_out = false;\r
97         kb_scan = 0;\r
98 }\r
99 \r
100 void MEMORY::write_data8(uint32 addr, uint32 data)\r
101 {\r
102         addr &= 0xffff;\r
103 \r
104         if(addr < 0x2000) {\r
105                 ram[addr & 0x7ff] = data;\r
106         } else if(addr < 0x4000) {\r
107                 d_ppu->write_data8(addr, data);\r
108         } else if(addr == 0x4014) {\r
109                 // stop cpu\r
110                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);\r
111                 register_event_by_clock(this, EVENT_DMA_DONE, 514, false, NULL);\r
112                 // start dma\r
113                 dma_addr = data << 8;\r
114                 for(int i = 0; i < 256; i++) {\r
115                         spr_ram[i] = read_data8(dma_addr | i);\r
116                 }\r
117         } else if(addr == 0x4016) {\r
118                 if(data & 1) {\r
119                         pad_strobe = true;\r
120                 } else if(pad_strobe) {\r
121                         pad_strobe = false;\r
122                         // joypad #1\r
123                         pad1_bits = 0;\r
124                         if(joy_stat[0] & 0x10) pad1_bits |= 0x01;       // A\r
125                         if(joy_stat[0] & 0x20) pad1_bits |= 0x02;       // B\r
126                         if(joy_stat[0] & 0x40) pad1_bits |= 0x04;       // SEL\r
127                         if(joy_stat[0] & 0x80) pad1_bits |= 0x08;       // START\r
128                         if(joy_stat[0] & 0x01) pad1_bits |= 0x10;       // UP\r
129                         if(joy_stat[0] & 0x02) pad1_bits |= 0x20;       // DOWN\r
130                         if(joy_stat[0] & 0x04) pad1_bits |= 0x40;       // LEFT\r
131                         if(joy_stat[0] & 0x08) pad1_bits |= 0x80;       // RIGHT\r
132                         // joypad #2\r
133                         pad2_bits = 0;\r
134                         if(joy_stat[1] & 0x10) pad2_bits |= 0x01;       // A\r
135                         if(joy_stat[1] & 0x20) pad2_bits |= 0x02;       // B\r
136                         if(joy_stat[1] & 0x01) pad2_bits |= 0x10;       // UP\r
137                         if(joy_stat[1] & 0x02) pad2_bits |= 0x20;       // DOWN\r
138                         if(joy_stat[1] & 0x04) pad2_bits |= 0x40;       // LEFT\r
139                         if(joy_stat[1] & 0x08) pad2_bits |= 0x80;       // RIGHT\r
140                 }\r
141                 // keyboard\r
142                 if((data & 0x07) == 0x04) {\r
143                         if(++kb_scan > 9) {\r
144                                 kb_scan = 0;\r
145                         }\r
146                         kb_out = !kb_out;\r
147                 } else if((data & 0x07) == 0x05) {\r
148                         kb_out = false;\r
149                         kb_scan = 0;\r
150                 } else if((data & 0x07) == 0x06) {\r
151                         kb_out = !kb_out;\r
152                 }\r
153                 // data recorder\r
154                 d_drec->write_signal(SIG_DATAREC_OUT, data, 2);\r
155         } else if(addr < 0x4018) {\r
156                 if(addr == 0x4017) {\r
157                         frame_irq_enabled = data;\r
158                 }\r
159                 d_apu->write_data8(addr, data);\r
160         } else if(addr < 0x6000) {\r
161                 // mapper independent\r
162         } else if(addr < 0x8000) {\r
163                 save_ram[addr & 0x1fff] = data;\r
164         } else {\r
165                 // mapper independent\r
166         }\r
167 }\r
168 \r
169 uint32 MEMORY::read_data8(uint32 addr)\r
170 {\r
171         addr &= 0xffff;\r
172 \r
173         if(addr < 0x2000) {\r
174                 return ram[addr & 0x7ff];\r
175         } else if(addr < 0x4000) {\r
176                 return d_ppu->read_data8(addr);\r
177         } else if(addr == 0x4014) {\r
178                 return dma_addr >> 8;\r
179         } else if(addr < 0x4016) {\r
180                 uint32 val = d_apu->read_data8(addr);\r
181                 if(addr == 0x4015 && !(frame_irq_enabled & 0xc0)) {\r
182                         val |= 0x40;\r
183                 }\r
184                 return val;\r
185         } else if(addr == 0x4016) {\r
186                 // joypad #1\r
187                 uint32 val = pad1_bits & 1;\r
188                 pad1_bits >>= 1;\r
189                 // data recorder\r
190                 val |= d_drec->read_signal(0) ? 2 : 0;\r
191                 // mic\r
192                 val |= key_stat[0x7b] ? 4 : 0;  // F12\r
193                 return val;\r
194         } else if(addr == 0x4017) {\r
195                 // joypad #2\r
196                 uint32 val = 0xfe | (pad2_bits & 1);\r
197                 pad2_bits >>= 1;\r
198                 // keyboard\r
199                 if(kb_out) {\r
200                         switch(kb_scan) {\r
201                         case 1:\r
202                                 if(key_stat[0x77]) val &= ~0x02;        // F8\r
203                                 if(key_stat[0x0d]) val &= ~0x04;        // RETURN\r
204                                 if(key_stat[0xdb]) val &= ~0x08;        // [\r
205                                 if(key_stat[0xdd]) val &= ~0x10;        // ]\r
206                                 break;\r
207                         case 2:\r
208                                 if(key_stat[0x76]) val &= ~0x02;        // F7\r
209                                 if(key_stat[0xc0]) val &= ~0x04;        // @\r
210                                 if(key_stat[0xba]) val &= ~0x08;        // :\r
211                                 if(key_stat[0xbb]) val &= ~0x10;        // ;\r
212                                 break;\r
213                         case 3:\r
214                                 if(key_stat[0x75]) val &= ~0x02;        // F6\r
215                                 if(key_stat[0x4f]) val &= ~0x04;        // O\r
216                                 if(key_stat[0x4c]) val &= ~0x08;        // L\r
217                                 if(key_stat[0x4b]) val &= ~0x10;        // K\r
218                                 break;\r
219                         case 4:\r
220                                 if(key_stat[0x74]) val &= ~0x02;        // F5\r
221                                 if(key_stat[0x49]) val &= ~0x04;        // I\r
222                                 if(key_stat[0x55]) val &= ~0x08;        // U\r
223                                 if(key_stat[0x4a]) val &= ~0x10;        // J\r
224                                 break;\r
225                         case 5:\r
226                                 if(key_stat[0x73]) val &= ~0x02;        // F4\r
227                                 if(key_stat[0x59]) val &= ~0x04;        // Y\r
228                                 if(key_stat[0x47]) val &= ~0x08;        // G\r
229                                 if(key_stat[0x48]) val &= ~0x10;        // H\r
230                                 break;\r
231                         case 6:\r
232                                 if(key_stat[0x72]) val &= ~0x02;        // F3\r
233                                 if(key_stat[0x54]) val &= ~0x04;        // T\r
234                                 if(key_stat[0x52]) val &= ~0x08;        // R\r
235                                 if(key_stat[0x44]) val &= ~0x10;        // D\r
236                                 break;\r
237                         case 7:\r
238                                 if(key_stat[0x71]) val &= ~0x02;        // F2\r
239                                 if(key_stat[0x57]) val &= ~0x04;        // W\r
240                                 if(key_stat[0x53]) val &= ~0x08;        // S\r
241                                 if(key_stat[0x41]) val &= ~0x10;        // A\r
242                                 break;\r
243                         case 8:\r
244                                 if(key_stat[0x70]) val &= ~0x02;        // F1\r
245                                 if(key_stat[0x1b]) val &= ~0x04;        // ESC\r
246                                 if(key_stat[0x51]) val &= ~0x08;        // Q\r
247                                 if(key_stat[0x11]) val &= ~0x10;        // CTRL\r
248                                 break;\r
249                         case 9:\r
250                                 if(key_stat[0x24]) val &= ~0x02;        // CLS\r
251                                 if(key_stat[0x26]) val &= ~0x04;        // UP\r
252                                 if(key_stat[0x27]) val &= ~0x08;        // RIGHT\r
253                                 if(key_stat[0x25]) val &= ~0x10;        // LEFT\r
254                                 break;\r
255                         }\r
256                 } else {\r
257                         switch(kb_scan) {\r
258                         case 1:\r
259                                 if(key_stat[0x15]) val &= ~0x02;        // KANA\r
260 //                              if(key_stat[0x10]) val &= ~0x04;        // RSHIFT\r
261                                 if(key_stat[0xdc]) val &= ~0x08;        // '\\'\r
262                                 if(key_stat[0x23]) val &= ~0x10;        // STOP\r
263                                 break;\r
264                         case 2:\r
265                                 if(key_stat[0xe2]) val &= ~0x02;        // _\r
266                                 if(key_stat[0xbf]) val &= ~0x04;        // /\r
267                                 if(key_stat[0xbd]) val &= ~0x08;        // -\r
268                                 if(key_stat[0xde]) val &= ~0x10;        // ^\r
269                                 break;\r
270                         case 3:\r
271                                 if(key_stat[0xbe]) val &= ~0x02;        // .\r
272                                 if(key_stat[0xbc]) val &= ~0x04;        // ,\r
273                                 if(key_stat[0x50]) val &= ~0x08;        // P\r
274                                 if(key_stat[0x30]) val &= ~0x10;        // 0\r
275                                 break;\r
276                         case 4:\r
277                                 if(key_stat[0x4d]) val &= ~0x02;        // M\r
278                                 if(key_stat[0x4e]) val &= ~0x04;        // N\r
279                                 if(key_stat[0x39]) val &= ~0x08;        // 9\r
280                                 if(key_stat[0x38]) val &= ~0x10;        // 8\r
281                                 break;\r
282                         case 5:\r
283                                 if(key_stat[0x42]) val &= ~0x02;        // B\r
284                                 if(key_stat[0x56]) val &= ~0x04;        // V\r
285                                 if(key_stat[0x37]) val &= ~0x08;        // 7\r
286                                 if(key_stat[0x36]) val &= ~0x10;        // 6\r
287                                 break;\r
288                         case 6:\r
289                                 if(key_stat[0x46]) val &= ~0x02;        // F\r
290                                 if(key_stat[0x43]) val &= ~0x04;        // C\r
291                                 if(key_stat[0x35]) val &= ~0x08;        // 5\r
292                                 if(key_stat[0x34]) val &= ~0x10;        // 4\r
293                                 break;\r
294                         case 7:\r
295                                 if(key_stat[0x58]) val &= ~0x02;        // X\r
296                                 if(key_stat[0x5a]) val &= ~0x04;        // Z\r
297                                 if(key_stat[0x45]) val &= ~0x08;        // E\r
298                                 if(key_stat[0x33]) val &= ~0x10;        // 3\r
299                                 break;\r
300                         case 8:\r
301                                 if(key_stat[0x10]) val &= ~0x02;        // LSHIFT\r
302                                 if(key_stat[0x12]) val &= ~0x04;        // GRAPH\r
303                                 if(key_stat[0x31]) val &= ~0x08;        // 1\r
304                                 if(key_stat[0x32]) val &= ~0x10;        // 2\r
305                                 break;\r
306                         case 9:\r
307                                 if(key_stat[0x28]) val &= ~0x02;        // DOWN\r
308                                 if(key_stat[0x20]) val &= ~0x04;        // SPACE\r
309                                 if(key_stat[0x2e]) val &= ~0x08;        // DEL\r
310                                 if(key_stat[0x2d]) val &= ~0x10;        // INS\r
311                                 break;\r
312                         }\r
313                 }\r
314                 return val;\r
315         } else if(addr < 0x6000) {\r
316                 // mapper independent\r
317                 return 0xff;\r
318         } else if(addr < 0x8000) {\r
319                 return save_ram[addr & 0x1fff];\r
320         } else {\r
321                 return rom[addr & 0x7fff];\r
322         }\r
323 }\r
324 \r
325 void MEMORY::event_vline(int v, int clock)\r
326 {\r
327         // fram irq\r
328         if(v == 240 && !(frame_irq_enabled & 0xc0)) {\r
329                 // pending\r
330                 d_cpu->write_signal(SIG_CPU_IRQ, 1, 1);\r
331         }\r
332 }\r
333 \r
334 void MEMORY::event_callback(int event_id, int err)\r
335 {\r
336         // dma done\r
337         d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);\r
338 }\r
339 \r
340 \r