OSDN Git Service

[VM][WIP] Pre-process to apply new state framework.Still not buildable.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mz2500 / memory.cpp
1 /*
2         SHARP MZ-2500 Emulator 'EmuZ-2500'
3
4         Author : Takeda.Toshiya
5         Date   : 2006.11.24 -
6
7         [ memory ]
8 */
9
10 #include "memory.h"
11
12 #define PAGE_TYPE_NORMAL        0
13 #define PAGE_TYPE_VRAM          1
14 #define PAGE_TYPE_KANJI         2
15 #define PAGE_TYPE_DIC           3
16 #define PAGE_TYPE_MODIFY        4
17
18 #define SET_BANK(s, e, w, r) { \
19         int sb = (s) >> 11, eb = (e) >> 11; \
20         for(int i = sb; i <= eb; i++) { \
21                 if((w) == wdmy) { \
22                         wbank[i] = wdmy; \
23                 } else { \
24                         wbank[i] = (w) + 0x800 * (i - sb); \
25                 } \
26                 if((r) == rdmy) { \
27                         rbank[i] = rdmy; \
28                 } else { \
29                         rbank[i] = (r) + 0x800 * (i - sb); \
30                 } \
31         } \
32 }
33
34 void MEMORY::initialize()
35 {
36         // init memory
37         memset(ram, 0, sizeof(ram));
38         memset(vram, 0, sizeof(vram));
39         memset(tvram, 0, sizeof(tvram));
40         memset(pcg, 0, sizeof(pcg));
41         memset(ipl, 0xff, sizeof(ipl));
42         memset(kanji, 0xff, sizeof(kanji));
43         memset(dic, 0xff, sizeof(dic));
44         memset(phone, 0xff, sizeof(phone));
45         memset(rdmy, 0xff, sizeof(rdmy));
46         
47         // load rom images
48         FILEIO* fio = new FILEIO();
49         if(fio->Fopen(create_local_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
50                 fio->Fread(ipl, sizeof(ipl), 1);
51                 fio->Fclose();
52         }
53         if(fio->Fopen(create_local_path(_T("KANJI.ROM")), FILEIO_READ_BINARY)) {
54                 fio->Fread(kanji, sizeof(kanji), 1);
55                 fio->Fclose();
56         }
57         if(fio->Fopen(create_local_path(_T("DICT.ROM")), FILEIO_READ_BINARY)) {
58                 fio->Fread(dic, sizeof(dic), 1);
59                 fio->Fclose();
60         }
61         if(fio->Fopen(create_local_path(_T("PHONE.ROM")), FILEIO_READ_BINARY)) {
62                 fio->Fread(phone, sizeof(phone), 1);
63                 fio->Fclose();
64         }
65         delete fio;
66 }
67
68 // NOTE: IPL reset is done at system boot
69
70 void MEMORY::reset()
71 {
72         // ipl reset
73         bank = 0;
74         set_map(0x34);
75         set_map(0x35);
76         set_map(0x36);
77         set_map(0x37);
78         set_map(0x04);
79         set_map(0x05);
80         set_map(0x06);
81         set_map(0x07);
82         
83         // reset crtc signals
84         blank = hblank = vblank = busreq = false;
85         extra_wait = 0;
86 }
87
88 void MEMORY::special_reset()
89 {
90         // reset
91         bank = 0;
92         set_map(0x00);
93         set_map(0x01);
94         set_map(0x02);
95         set_map(0x03);
96         set_map(0x04);
97         set_map(0x05);
98         set_map(0x06);
99         set_map(0x07);
100         
101         // reset crtc signals
102         blank = hblank = vblank = busreq = false;
103         extra_wait = 0;
104 }
105
106 void MEMORY::write_data8_tmp(int b, uint32_t addr, uint32_t data)
107 {
108         if(is_vram[b] && !blank) {
109                 // vram wait
110                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
111                 busreq = true;
112         }
113         if(page_type[b] == PAGE_TYPE_MODIFY) {
114                 // read write modify
115                 if(page[b] == 0x30) {
116                         d_crtc->write_data8((addr & 0x1fff) + 0x0000, data);
117                 } else if(page[b] == 0x31) {
118                         d_crtc->write_data8((addr & 0x1fff) + 0x2000, data);
119                 } else if(page[b] == 0x32) {
120                         d_crtc->write_data8((addr & 0x1fff) + 0x4000, data);
121                 } else {
122                         d_crtc->write_data8((addr & 0x1fff) + 0x6000, data);
123                 }
124                 return;
125         }
126         wbank[addr >> 11][addr & 0x7ff] = data;
127 }
128
129 uint32_t MEMORY::read_data8_tmp(int b, uint32_t addr)
130 {
131         if(is_vram[b] && !blank) {
132                 // vram wait
133                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
134                 busreq = true;
135         }
136         if(page_type[b] == PAGE_TYPE_MODIFY) {
137                 // read write modify
138                 if(page[b] == 0x30) {
139                         return d_crtc->read_data8((addr & 0x1fff) + 0x0000);
140                 } else if(page[b] == 0x31) {
141                         return d_crtc->read_data8((addr & 0x1fff) + 0x2000);
142                 } else if(page[b] == 0x32) {
143                         return d_crtc->read_data8((addr & 0x1fff) + 0x4000);
144                 } else {
145                         return d_crtc->read_data8((addr & 0x1fff) + 0x6000);
146                 }
147         }
148         return rbank[addr >> 11][addr & 0x7ff];
149 }
150
151
152 void MEMORY::write_data8(uint32_t addr, uint32_t data)
153 {
154         addr &= 0xffff;
155         int b = addr >> 13;
156         write_data8_tmp(b, addr, data);
157 }
158
159 uint32_t MEMORY::read_data8(uint32_t addr)
160 {
161         addr &= 0xffff;
162         int b = addr >> 13;
163         return read_data8_tmp(b, addr);
164 }
165
166 void MEMORY::write_data8w(uint32_t addr, uint32_t data, int* wait)
167 {
168         addr &= 0xffff;
169         int b = addr >> 13;
170         write_data8_tmp(b, addr, data);
171         
172         if(busreq) {
173                 *wait = 0;
174                 extra_wait += page_wait[b];
175         } else {
176                 *wait = page_wait[b] + extra_wait;
177                 extra_wait = 0;
178         }
179 }
180
181 uint32_t MEMORY::read_data8w(uint32_t addr, int* wait)
182 {
183         addr &= 0xffff;
184         int b = addr >> 13;
185         uint32_t data = read_data8_tmp(b, addr);
186         
187         if(busreq) {
188                 *wait = 0;
189                 extra_wait += page_wait[b];
190         } else {
191                 *wait = page_wait[b] + extra_wait;
192                 extra_wait = 0;
193         }
194         return data;
195 }
196
197 uint32_t MEMORY::fetch_op(uint32_t addr, int* wait)
198 {
199         *wait = 1;
200         return read_data8(addr);
201 }
202
203 void MEMORY::write_io8(uint32_t addr, uint32_t data)
204 {
205         switch(addr & 0xff) {
206         case 0xb4:
207                 // map bank
208                 bank = data & 7;
209                 break;
210         case 0xb5:
211                 // map reg
212                 set_map(data & 0x3f);
213                 break;
214         case 0xce:
215                 // dictionary bank
216                 dic_bank = data & 0x1f;
217                 for(int i = 0; i < 8; i++) {
218                         if(page_type[i] == PAGE_TYPE_DIC) {
219                                 SET_BANK(i * 0x2000,  i * 0x2000 + 0x1fff, wdmy, dic + dic_bank * 0x2000);
220                         }
221                 }
222                 break;
223         case 0xcf:
224                 // kanji bank
225                 kanji_bank = data;
226                 for(int i = 0; i < 8; i++) {
227                         if(page_type[i] == PAGE_TYPE_KANJI) {
228                                 if(kanji_bank & 0x80) {
229                                         SET_BANK(i * 0x2000,  i * 0x2000 + 0x7ff, wdmy, kanji + (kanji_bank & 0x7f) * 0x800);
230                                 } else {
231                                         SET_BANK(i * 0x2000,  i * 0x2000 + 0x7ff, pcg, pcg);
232                                 }
233                         }
234                 }
235                 break;
236         }
237 }
238
239 uint32_t MEMORY::read_io8(uint32_t addr)
240 {
241         switch(addr & 0xff) {
242         case 0xb4:
243                 // map bank
244                 return bank;
245         case 0xb5:
246                 // map reg
247                 uint32_t val = page[bank];
248                 bank = (bank + 1) & 7;
249                 return val;
250         }
251         return 0xff;
252 }
253
254 void MEMORY::write_signal(int id, uint32_t data, uint32_t mask)
255 {
256         if(id == SIG_MEMORY_HBLANK) {
257                 hblank = ((data & mask) != 0);
258         } else if(id == SIG_MEMORY_VBLANK) {
259                 vblank = ((data & mask) != 0);
260         }
261         
262         // if blank, disable busreq
263         bool next = hblank || vblank;
264         if(!blank && next && busreq) {
265                 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
266                 busreq = false;
267         }
268         blank = next;
269 }
270
271 void MEMORY::set_map(uint8_t data)
272 {
273         int base = bank * 0x2000;
274         
275         page_wait[bank] = 0;
276         is_vram[bank] = false;
277         if(data <= 0x1f) {
278                 // main ram
279                 SET_BANK(base,  base + 0x1fff, ram + data * 0x2000, ram + data * 0x2000);
280                 page_type[bank] = PAGE_TYPE_NORMAL;
281         } else if(0x20 <= data && data <= 0x2f) {
282                 // vram
283                 static const int ofs_table[] = {0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0c, 0x0d, 0x02, 0x03, 0x06, 0x07, 0x0a, 0x0b, 0x0e, 0x0f};
284                 int ofs = ofs_table[data - 0x20] * 0x2000;
285                 SET_BANK(base,  base + 0x1fff, vram + ofs, vram + ofs);
286                 page_type[bank] = PAGE_TYPE_VRAM;
287                 page_wait[bank] = 1;
288                 is_vram[bank] = true;
289         } else if(0x30 <= data && data <= 0x33) {
290                 // read modify write
291                 SET_BANK(base,  base + 0x1fff, wdmy, rdmy);
292                 page_type[bank] = PAGE_TYPE_MODIFY;
293                 page_wait[bank] = 2;
294                 is_vram[bank] = true;
295         } else if(0x34 <= data && data <= 0x37) {
296                 // ipl rom
297                 SET_BANK(base,  base + 0x1fff, wdmy, ipl + (data - 0x34) * 0x2000);
298                 page_type[bank] = PAGE_TYPE_NORMAL;
299         } else if(data == 0x38) {
300                 // text vram
301                 SET_BANK(base         ,  base + 0x17ff, tvram, tvram);
302                 SET_BANK(base + 0x1800,  base + 0x1fff, wdmy, rdmy);
303                 page_type[bank] = PAGE_TYPE_VRAM;
304                 page_wait[bank] = 1;
305                 is_vram[bank] = true;
306         } else if(data == 0x39) {
307                 // kanji rom, pcg
308                 SET_BANK(base,  base + 0x1fff, pcg, pcg);
309                 if(kanji_bank & 0x80) {
310                         SET_BANK(base,  base + 0x7ff, wdmy, kanji + (kanji_bank & 0x7f) * 0x800);
311                 }
312                 page_type[bank] = PAGE_TYPE_KANJI;
313                 page_wait[bank] = 2;
314         } else if(data == 0x3a) {
315                 // dictionary rom
316                 SET_BANK(base,  base + 0x1fff, wdmy, dic + dic_bank * 0x2000);
317                 page_type[bank] = PAGE_TYPE_DIC;
318         } else if(0x3c <= data && data <= 0x3f) {
319                 // phone rom
320                 SET_BANK(base,  base + 0x1fff, wdmy, phone + (data - 0x3c) * 0x2000);
321                 page_type[bank] = PAGE_TYPE_NORMAL;
322         } else {
323                 // n.c
324                 SET_BANK(base,  base + 0x1fff, wdmy, rdmy);
325                 page_type[bank] = PAGE_TYPE_NORMAL;
326         }
327         page[bank] = data;
328         bank = (bank + 1) & 7;
329 }
330
331 #define STATE_VERSION   1
332
333 #include "../../statesub.h"
334
335 void MEMORY::decl_state()
336 {
337         enter_decl_state(STATE_VERSION);
338
339         DECL_STATE_ENTRY_1D_ARRAY(ram, sizeof(ram));
340         DECL_STATE_ENTRY_1D_ARRAY(vram, sizeof(vram));
341         DECL_STATE_ENTRY_1D_ARRAY(tvram, sizeof(tvram));
342         DECL_STATE_ENTRY_1D_ARRAY(pcg, sizeof(pcg));
343         DECL_STATE_ENTRY_UINT8(bank);
344         DECL_STATE_ENTRY_1D_ARRAY(page, sizeof(page));
345         DECL_STATE_ENTRY_UINT8(dic_bank);
346         DECL_STATE_ENTRY_UINT8(kanji_bank);
347         DECL_STATE_ENTRY_BOOL(blank);
348         DECL_STATE_ENTRY_BOOL(hblank);
349         DECL_STATE_ENTRY_BOOL(vblank);
350         DECL_STATE_ENTRY_BOOL(busreq);
351         
352         leave_decl_state();
353 }
354
355 void MEMORY::save_state(FILEIO* state_fio)
356 {
357         if(state_entry != NULL) {
358                 state_entry->save_state(state_fio);
359         }
360 //      state_fio->FputUint32(STATE_VERSION);
361 //      state_fio->FputInt32(this_device_id);
362         
363 //      state_fio->Fwrite(ram, sizeof(ram), 1);
364 //      state_fio->Fwrite(vram, sizeof(vram), 1);
365 //      state_fio->Fwrite(tvram, sizeof(tvram), 1);
366 //      state_fio->Fwrite(pcg, sizeof(pcg), 1);
367 //      state_fio->FputUint8(bank);
368 //      state_fio->Fwrite(page, sizeof(page), 1);
369 //      state_fio->FputUint8(dic_bank);
370 //      state_fio->FputUint8(kanji_bank);
371 //      state_fio->FputBool(blank);
372 //      state_fio->FputBool(hblank);
373 //      state_fio->FputBool(vblank);
374 //      state_fio->FputBool(busreq);
375 }
376
377 bool MEMORY::load_state(FILEIO* state_fio)
378 {
379         bool mb = false;
380         if(state_entry != NULL) {
381                 mb = state_entry->load_state(state_fio);
382         }
383         if(!mb) {
384                 return false;
385         }
386 //      if(state_fio->FgetUint32() != STATE_VERSION) {
387 //              return false;
388 //      }
389 //      if(state_fio->FgetInt32() != this_device_id) {
390 //              return false;
391 //      }
392 //      state_fio->Fread(ram, sizeof(ram), 1);
393 //      state_fio->Fread(vram, sizeof(vram), 1);
394 //      state_fio->Fread(tvram, sizeof(tvram), 1);
395 //      state_fio->Fread(pcg, sizeof(pcg), 1);
396 //      bank = state_fio->FgetUint8();
397 //      state_fio->Fread(page, sizeof(page), 1);
398 //      dic_bank = state_fio->FgetUint8();
399 //      kanji_bank = state_fio->FgetUint8();
400 //      blank = state_fio->FgetBool();
401 //      hblank = state_fio->FgetBool();
402 //      vblank = state_fio->FgetBool();
403 //      busreq = state_fio->FgetBool();
404         
405         // post process
406         uint8_t bank_tmp = bank;
407         bank = 0;
408         for(int i = 0; i < 8; i++) {
409                 set_map(page[i]);
410         }
411         bank = bank_tmp;
412         return true;
413 }
414
415 bool MEMORY::process_state(FILEIO* state_fio, bool loading)
416 {
417         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
418                 return false;
419         }
420         if(!state_fio->StateCheckInt32(this_device_id)) {
421                 return false;
422         }
423         state_fio->StateBuffer(ram, sizeof(ram), 1);
424         state_fio->StateBuffer(vram, sizeof(vram), 1);
425         state_fio->StateBuffer(tvram, sizeof(tvram), 1);
426         state_fio->StateBuffer(pcg, sizeof(pcg), 1);
427         state_fio->StateUint8(bank);
428         state_fio->StateBuffer(page, sizeof(page), 1);
429         state_fio->StateUint8(dic_bank);
430         state_fio->StateUint8(kanji_bank);
431         state_fio->StateBool(blank);
432         state_fio->StateBool(hblank);
433         state_fio->StateBool(vblank);
434         state_fio->StateBool(busreq);
435         
436         // post process
437         if(loading) {
438                 uint8_t bank_tmp = bank;
439                 bank = 0;
440                 for(int i = 0; i < 8; i++) {
441                         set_map(page[i]);
442                 }
443                 bank = bank_tmp;
444         }
445         return true;
446 }