OSDN Git Service

[VM][FMTOWNS][MEMORY] Revert to use primitive_[read|write]. Fix CDROM's some issues...
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / towns_memory.h
1 /*
2         FUJITSU FM Towns Emulator 'eFMTowns'
3
4         Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2017.01.07 -
6
7         [ memory ]
8 */
9
10 #ifndef _TOWNS_MEMORY_H_
11 #define _TOWNS_MEMORY_H_
12
13 #include "device.h"
14 #include "../../common.h"
15 #include "../memory.h"
16 #include "./towns_common.h"
17
18 #define SIG_FMTOWNS_MACHINE_ID  1
19 #define SIG_MEMORY_EXTNMI       2
20
21 // MAP:
22 // 00000000 - 000fffff : SYSTEM RAM PAGE 0 (Similar to FMR-50).
23 // 00100000 - 3fffffff : EXTRA RAM (for i386 native mode.Page size is 1MB.)
24 // 40000000 - 7fffffff : External I/O BOX.Not accessible.
25 // 80000000 - bfffffff : VRAM (Reserved 01020000H bytes with earlier Towns.)
26 // c0000000 - c21fffff : ROM card and dictionaly/font/DOS ROMs.
27 // c2200000 - c2200fff : PCM RAM (Banked).
28 // c2201000 - fffbffff : Reserved.
29 // FFFC0000 - FFFFFFFF : Towns System ROM.
30
31 namespace FMTOWNS {
32 enum {
33         TOWNS_MEMORY_NORMAL = 0,
34         TOWNS_MEMORY_FMR_VRAM,
35         TOWNS_MEMORY_FMR_TEXT,
36         TOWNS_MEMORY_FMR_VRAM_RESERVE,
37         TOWNS_MEMORY_SPRITE_ANKCG1,
38         TOWNS_MEMORY_ANKCG2,
39         
40         TOWNS_MEMORY_MMIO_0CC,
41         
42         TOWNS_MEMORY_TYPE_EXT_MMIO,
43         TOWNS_MEMORY_TYPE_LEARN_RAM,
44         TOWNS_MEMORY_TYPE_WAVERAM,
45 };
46 }
47 // Please set from config
48 #define TOWNS_EXTRAM_PAGES 6
49
50 class BEEP;
51 class I386;
52
53 namespace FMTOWNS {
54         class TOWNS_VRAM;
55         class TOWNS_SPRITE;
56         class TOWNS_ROM_CARD;
57 }
58         
59 namespace FMTOWNS {
60 class TOWNS_MEMORY : public MEMORY
61 {
62 protected:
63         DEVICE* d_vram;
64         DEVICE* d_sprite;       // 0x81000000 - 0x8101ffff ?
65         DEVICE* d_romcard[2]; // 0xc0000000 - 0xc0ffffff / 0xc1000000 - 0xc1ffffff
66         DEVICE* d_pcm;             // 0xc2200000 - 0xc2200fff 
67         DEVICE* d_timer;
68         DEVICE* d_dmac;
69         DEVICE* d_crtc;
70         DEVICE* d_planevram;
71         I386*   d_cpu;
72         
73         DEVICE* d_dictionary;
74         DEVICE* d_sysrom;
75         DEVICE* d_msdos;
76         DEVICE* d_serialrom;
77         DEVICE* d_font;
78         DEVICE* d_font_20pix;
79
80         DEVICE* d_iccard[2];
81
82         outputs_t outputs_ram_wait;
83         outputs_t outputs_rom_wait;
84         
85         bool bankc0_vram;
86         bool ankcg_enabled;
87         bool select_d0_rom;
88         bool select_d0_dict;
89         
90         uint16_t machine_id;
91         uint8_t cpu_id;
92         bool is_compatible;
93         bool dma_is_vram;
94
95         // RAM
96         uint8_t ram_page0[0xc0000];       // 0x00000000 - 0x000bffff : RAM
97         uint8_t ram_pagec[0x10000];       // 0x000c0000 - 0x000cffff : URA? RAM
98         uint8_t ram_paged[0x10000];       // 0x000d0000 - 0x000dffff : RAM
99         uint8_t ram_pagee[0x10000];       // 0x000e0000 - 0x000effff : RAM
100         uint8_t ram_pagef[0x10000];       // 0x000f0000 - 0x000f8fff : RAM
101
102         uint8_t *extra_ram;                  // 0x00100000 - (0x3fffffff) : Size is defined by extram_size;
103         uint32_t extram_size;
104         uint32_t cpu_clock_val;
105         uint32_t vram_wait_val;
106         uint32_t mem_wait_val;
107
108         uint8_t wait_register;
109         
110         bool extra_nmi_mask;
111         bool extra_nmi_val;
112         bool nmi_mask;
113         bool software_reset;
114         bool nmi_vector_protect;
115         bool poff_status;
116         bool reset_happened;
117         
118         // misc
119         uint32_t vram_size; // Normally 512KB.
120         bool initialized;
121
122         virtual void set_wait_values();
123         virtual void config_page00();
124
125         inline uint32_t __FASTCALL read_primitive_byte(uint32_t addr)
126         {
127                 int bank = (addr & addr_mask) >> addr_shift;
128                 if(rd_table[bank].device != NULL) {
129                         return rd_table[bank].device->read_memory_mapped_io8(addr);
130                 } else {
131                         return rd_table[bank].memory[addr & bank_mask];
132                 }
133         }
134         
135         inline uint32_t __FASTCALL read_primitive_word(uint32_t addr)
136         {
137                 int bank = (addr & addr_mask) >> addr_shift;
138                 pair32_t n;
139                 uint32_t naddr = addr & bank_mask;
140                 n.d = 0;
141
142                 if((addr & bank_mask) == bank_mask) {
143                         if(rd_table[bank].device != NULL) {
144                                 n.b.l = rd_table[bank].device->read_memory_mapped_io8(addr);
145                         } else {
146                                 n.b.l = rd_table[bank].memory[naddr + 0];
147                         }
148                         n.b.h = read_primitive_byte(addr + 1);
149                 } else {
150                         if(rd_table[bank].device != NULL) {
151                                 n.w.l = rd_table[bank].device->read_memory_mapped_io16(addr);
152                         } else {
153                                 n.b.l = rd_table[bank].memory[naddr + 0];
154                                 n.b.h = rd_table[bank].memory[naddr + 1];
155                         }
156                 }
157                 return n.d;
158         }
159         inline uint32_t __FASTCALL read_primitive_dword(uint32_t addr)
160         {
161                 int bank = (addr & addr_mask) >> addr_shift;
162                 pair32_t n;
163                 uint32_t naddr = addr & bank_mask;
164                 n.d = 0;
165                 if((addr & bank_mask) > (bank_mask - 3)) {
166                         switch(addr & 3) {
167                         case 0:
168                                 n.w.l = read_primitive_word(addr + 0);
169                                 n.w.h = read_primitive_word(addr + 2);
170                                 break;
171                         case 1:
172                                 n.b.l  = read_primitive_byte(addr + 0);
173                                 n.b.h  = read_primitive_byte(addr + 1);
174                                 n.b.h2 = read_primitive_byte(addr + 2);
175                                 n.b.h3 = read_primitive_byte(addr + 3);
176                                 break;
177                         case 2:
178                                 n.w.l = read_primitive_word(addr + 0);
179                                 n.w.h = read_primitive_word(addr + 2);
180                                 break;
181                         case 3:
182                                 n.b.l  = read_primitive_byte(addr + 0);
183                                 n.b.h  = read_primitive_byte(addr + 1);
184                                 n.b.h2 = read_primitive_byte(addr + 2);
185                                 n.b.h3 = read_primitive_byte(addr + 3);
186                                 break;
187                         }
188                         return n.d;
189                 } else { // Inside of boundary
190                         if(rd_table[bank].device != NULL) {
191                                 return rd_table[bank].device->read_memory_mapped_io32(addr);
192                         } else {
193                                 n.b.l  = rd_table[bank].memory[naddr + 0];
194                                 n.b.h  = rd_table[bank].memory[naddr + 1];
195                                 n.b.h2 = rd_table[bank].memory[naddr + 2];
196                                 n.b.h3 = rd_table[bank].memory[naddr + 3];
197                         }
198                         return n.d;
199                 }
200         }
201         inline void __FASTCALL write_primitive_byte(uint32_t addr, uint32_t data)
202         {
203                 int bank = (addr & addr_mask) >> addr_shift;
204 //              if(addr == 0xd000) {
205 //                      out_debug_log(_T("WRITE  %02X to D000 / DEV=%08X"), data, wr_table[bank].device);
206 //              }
207                 if(wr_table[bank].device != NULL) {
208                         wr_table[bank].device->write_memory_mapped_io8(addr, data);
209                 } else {
210                         wr_table[bank].memory[addr & bank_mask] = data;
211                 }
212         }
213         
214         inline void __FASTCALL write_primitive_word(uint32_t addr, uint32_t data)
215         {
216                 int bank = (addr & addr_mask) >> addr_shift;
217                 
218                 if(wr_table[bank].device != NULL) {
219                         if((addr & bank_mask) == bank_mask) {
220                                 pair32_t n;
221                                 n.d = data;
222                                 wr_table[bank].device->write_memory_mapped_io8(addr + 0, n.b.l);
223                                 write_primitive_byte(addr + 1, n.b.h);
224                         } else {
225                                 wr_table[bank].device->write_memory_mapped_io16(addr, data);
226                         }
227                 } else {
228                         pair32_t n;
229                         uint32_t naddr = addr & bank_mask;
230                         n.d = data;
231                         if((addr & bank_mask) == bank_mask) {
232                                 wr_table[bank].memory[naddr + 0] = n.b.l;
233                                 write_primitive_byte(addr + 1, n.b.h);
234                         } else {
235                                 wr_table[bank].memory[naddr + 0] = n.b.l;
236                                 wr_table[bank].memory[naddr + 1] = n.b.h;
237                         }
238                 }
239         }
240         inline void __FASTCALL write_primitive_dword(uint32_t addr, uint32_t data)
241         {
242                 int bank = (addr & addr_mask) >> addr_shift;
243                 uint32_t naddr = addr & bank_mask;
244                 pair32_t n;
245                 n.d = data;
246                 if((addr & bank_mask) <= (bank_mask - 3)) {
247                         if(wr_table[bank].device != NULL) {
248                                 wr_table[bank].device->write_memory_mapped_io32(addr, data);
249                         } else {
250                                 wr_table[bank].memory[naddr + 0] = n.b.l;
251                                 wr_table[bank].memory[naddr + 1] = n.b.h;
252                                 wr_table[bank].memory[naddr + 2] = n.b.h2;
253                                 wr_table[bank].memory[naddr + 3] = n.b.h3;
254                         }
255                 } else {
256                         // BEYOND BOUNDARY
257                         switch(addr & 3) {
258                         case 0:
259                                 write_primitive_word(addr + 0, n.w.l);
260                                 write_primitive_word(addr + 2, n.w.h);
261                                 break;
262                         case 1:
263                                 {
264                                         write_primitive_byte(addr + 0, n.b.l);
265                                         pair16_t nn;
266                                         nn.b.l = n.b.h;
267                                         nn.b.h = n.b.h2;
268                                         write_primitive_word(addr + 1, nn.w);
269                                         write_primitive_byte(addr + 3, n.b.h3);
270                                 }
271                                 break;
272                         case 2:
273                                 write_primitive_word(addr + 0, n.w.l);
274                                 write_primitive_word(addr + 2, n.w.h);
275                                 break;
276                         case 3:
277                                 {
278                                         write_primitive_byte(addr + 0, n.b.l);
279                                         pair16_t nn;
280                                         nn.b.l = n.b.h;
281                                         nn.b.h = n.b.h2;
282                                         write_primitive_word(addr + 1, nn.w);
283                                         write_primitive_word(addr + 3, n.b.h3);
284                                 }
285                                 break;
286                         }
287                 }
288         }
289 public:
290         TOWNS_MEMORY(VM_TEMPLATE* parent_vm, EMU_TEMPLATE* parent_emu) : MEMORY(parent_vm, parent_emu) {
291                 set_device_name(_T("FMTOWNS_MEMORY"));
292                 addr_max = 0x100000000; // 4GiB
293                 bank_size = 1024; // 1024
294                 addr_shift = 10;
295                 bank_size_was_set = false;
296                 addr_max_was_set = false;
297                 
298                 _MEMORY_DISABLE_DMA_MMIO = false;
299                 
300                 extram_size = 0x00200000; // Basically 2MB
301                 
302                 d_cpu = NULL;
303                 
304                 d_vram = NULL;
305                 d_sprite = NULL;
306                 d_romcard[0] = d_romcard[1] = NULL;
307                 d_pcm = NULL;
308                 d_timer = NULL;
309                 d_dmac = NULL;
310                 d_crtc = NULL;
311                 d_planevram = NULL;
312                 d_iccard[0] = NULL;
313                 d_iccard[1] = NULL;
314                 
315                 d_dictionary = NULL;
316                 d_sysrom = NULL;
317                 d_msdos = NULL;
318                 d_serialrom = NULL;
319                 d_font = NULL;
320                 d_font_20pix = NULL;
321                 initialized = false;
322
323                 initialize_output_signals(&outputs_ram_wait);
324                 initialize_output_signals(&outputs_rom_wait);
325                 // Note: machine id must set before initialize() from set_context_machine_id() by VM::VM().
326                 // machine_id = 0x0100;   // FM-Towns 1,2
327                 // machine_id = 0x0200 // FM-Towns  1F/2F/1H/2H
328                 // machine_id = 0x0300 // FM-Towns  UX10/UX20/UX40
329                 // machine_id = 0x0400 // FM-Towns  10F/20F/40H/80H
330                 // machine_id = 0x0500 // FM-Towns2 CX10/CX20/CX40/CX100
331                 // machine_id = 0x0600 // FM-Towns2 UG10/UG20/UG40/UG80
332                 // machine_id = 0x0700 // FM-Towns2 HR20/HR100/HR200
333                 // machine_id = 0x0800 // FM-Towns2 HG20/HG40/HG100
334                 // machine_id = 0x0900 // FM-Towns2 UR20/UR40/UR80
335                 // machine_id = 0x0b00 // FM-Towns2 MA20/MA170/MA340
336                 // machine_id = 0x0c00 // FM-Towns2 MX20/MX170/MX340
337                 // machine_id = 0x0d00 // FM-Towns2 ME20/ME170
338                 // machine_id = 0x0f00 // FM-Towns2 MF20/MF170/Fresh
339                 machine_id = 0x0100;   // FM-Towns 1,2
340                 
341                 // Note: cpu id must set before initialize() from set_context_cpu_id() by VM::VM().
342                 // cpu_id = 0x00; // 80286. 
343                 // cpu_id = 0x01; // 80386DX. 
344                 // cpu_id = 0x02; // 80486SX/DX. 
345                 // cpu_id = 0x03; // 80386SX. 
346                 cpu_id = 0x01; // 80386DX. 
347                 extra_ram = NULL;
348         }
349         ~TOWNS_MEMORY() {}
350         
351         // common functions
352         void initialize();
353         void release();
354         void reset();
355         virtual void     __FASTCALL write_io8(uint32_t addr, uint32_t data);
356         virtual uint32_t __FASTCALL read_io8(uint32_t addr);
357         virtual uint32_t __FASTCALL read_io16(uint32_t addr);
358
359         uint32_t __FASTCALL read_data8(uint32_t addr);
360         uint32_t __FASTCALL read_data16(uint32_t addr);
361         uint32_t __FASTCALL read_data32(uint32_t addr);
362         void __FASTCALL write_data8(uint32_t addr, uint32_t data);
363         void __FASTCALL write_data16(uint32_t addr, uint32_t data);
364         void __FASTCALL write_data32(uint32_t addr, uint32_t data);
365         
366         uint32_t __FASTCALL read_data8w(uint32_t addr, int* wait);
367         uint32_t __FASTCALL read_data16w(uint32_t addr, int* wait);
368         uint32_t __FASTCALL read_data32w(uint32_t addr, int* wait);
369         void __FASTCALL write_data8w(uint32_t addr, uint32_t data, int* wait);
370         void __FASTCALL write_data16w(uint32_t addr, uint32_t data, int* wait);
371         void __FASTCALL write_data32w(uint32_t addr, uint32_t data, int* wait);
372
373 //      uint32_t __FASTCALL read_dma_data8w(uint32_t addr, int* wait);
374 //      uint32_t __FASTCALL read_dma_data16w(uint32_t addr, int* wait);
375 //      uint32_t __FASTCALL read_dma_data32w(uint32_t addr, int* wait);
376 //      void __FASTCALL write_dma_data8w(uint32_t addr, uint32_t data, int* wait);
377 //      void __FASTCALL write_dma_data16w(uint32_t addr, uint32_t data, int* wait);
378 //      void __FASTCALL write_dma_data32w(uint32_t addr, uint32_t data, int* wait);
379         
380         uint32_t __FASTCALL read_dma_data8(uint32_t addr);
381         uint32_t __FASTCALL read_dma_data16(uint32_t addr);
382         uint32_t __FASTCALL read_dma_data32(uint32_t addr);
383         void __FASTCALL write_dma_data8(uint32_t addr, uint32_t data);
384         void __FASTCALL write_dma_data16(uint32_t addr, uint32_t data);
385         void __FASTCALL write_dma_data32(uint32_t addr, uint32_t data);
386         
387         virtual void __FASTCALL write_memory_mapped_io8(uint32_t addr, uint32_t data);
388 //      virtual void __FASTCALL write_memory_mapped_io16(uint32_t addr, uint32_t data);
389 //      virtual void __FASTCALL write_memory_mapped_io32(uint32_t addr, uint32_t data);
390         virtual uint32_t __FASTCALL read_memory_mapped_io8(uint32_t addr);
391 //      virtual uint32_t __FASTCALL read_memory_mapped_io16(uint32_t addr);
392 //      virtual uint32_t __FASTCALL read_memory_mapped_io32(uint32_t addr);
393
394
395         void __FASTCALL write_signal(int id, uint32_t data, uint32_t mask);
396         uint32_t __FASTCALL read_signal(int ch);
397         
398         //void event_frame();
399         virtual void __FASTCALL set_intr_line(bool line, bool pending, uint32_t bit);
400         
401         bool process_state(FILEIO* state_fio, bool loading);
402         
403         // unique functions
404         void set_extra_ram_size(uint32_t megabytes)
405         {
406                 uint32_t limit = 5;
407                 uint32_t minimum = 2;
408                 switch(machine_id & 0xff00) {
409                 case 0x0000: // ???
410                 case 0x0100: // Towns Model 1/2
411                         minimum = 1;
412                         break;
413                 case 0x0200: // TOWNS 2F/2H
414                 case 0x0400: // TOWNS 10F/10H/20F/20H
415                         limit = 8; // 2MB + 2MB x 3
416                         break;
417                 case 0x0300: // TOWNS2 UX
418                 case 0x0600: // TOWNS2 UG
419                         limit = 9; // 2MB + 4MB x 2? - 1MB
420                         break;
421                 case 0x0500: // TOWNS2 CX
422                 case 0x0800: // TOWNS2 HG
423                         limit = 15; // 8MB x 2 - 1MB?
424                         break;
425                 case 0x0700: // TOWNS2 HR
426                 case 0x0900: // TOWNS2 UR
427                 case 0x0B00: // TOWNS2 MA
428                 case 0x0C00: // TOWNS2 MX
429                 case 0x0D00: // TOWNS2 ME
430                 case 0x0F00: // TOWNS2 MF/Fresh
431                         limit = 31; // 16MB x 2 - 1MB? 
432                         break;
433                 }
434                 if(megabytes > limit) megabytes = limit;
435                 if(megabytes < minimum) megabytes = minimum;
436                 extram_size = megabytes << 20;
437         }
438         void set_context_cpu(I386* device)
439         {
440                 d_cpu = device;
441         }
442         void set_context_dmac(DEVICE* device)
443         {
444                 d_dmac = device;
445         }
446         void set_context_vram(DEVICE* device)
447         {
448                 d_vram = device;
449         }
450         void set_context_system_rom(DEVICE* device)
451         {
452                 d_sysrom = device;
453         }
454         void set_context_font_rom(DEVICE* device)
455         {
456                 d_font = device;
457         }
458         void set_context_font_20pix_rom(DEVICE* device)
459         {
460                 d_font_20pix = device;
461         }
462         void set_context_dictionary(DEVICE* device)
463         {
464                 d_dictionary = device;
465         }
466         void set_context_msdos(DEVICE* device)
467         {
468                 d_msdos = device;
469         }
470         void set_context_timer(DEVICE* device)
471         {
472                 d_timer = device;
473         }
474         void set_context_sprite(DEVICE* device)
475         {
476                 d_sprite = device;
477         }
478         void set_context_crtc(DEVICE* device)
479         {
480                 d_crtc = device;
481         }
482         void set_context_romcard(DEVICE* device, int num)
483         {
484                 d_romcard[num & 1] = device;
485         }
486         void set_context_pcm(DEVICE* device)
487         {
488                 d_pcm = device;
489         }
490         void set_context_serial_rom(DEVICE* device)
491         {
492                 d_serialrom = device;
493         }
494         void set_context_planevram(DEVICE *dev)
495         {
496                 d_planevram = dev;
497         }
498         void set_context_iccard(DEVICE* device, int num)
499         {
500                 if((num >= 0) && (num < 2)) {
501                         d_iccard[num] = device;
502                 }
503         }
504         void set_machine_id(uint16_t val)
505         {
506                 machine_id = val & 0xfff8;
507         }
508         void set_cpu_id(uint16_t val)
509         {
510                 cpu_id = val & 0x07;
511         }
512 };
513
514 }
515 #endif
516