OSDN Git Service

5adab54c6006927db7a553eb6674c8b8db23df17
[csp-qt/common_source_project-fm7.git] / source / src / vm / qc10 / memory.cpp
1 /*
2         EPSON QC-10 Emulator 'eQC-10'
3
4         Author : Takeda.Toshiya
5         Date   : 2008.02.15 -
6
7         [ memory ]
8 */
9
10 #include "memory.h"
11 #include "../i8253.h"
12 #include "../pcm1bit.h"
13 #include "../upd765a.h"
14
15 #define SET_BANK(s, e, w, r) { \
16         int sb = (s) >> 11, eb = (e) >> 11; \
17         for(int i = sb; i <= eb; i++) { \
18                 wbank[i] = (w) + 0x800 * (i - sb); \
19                 rbank[i] = (r) + 0x800 * (i - sb); \
20         } \
21 }
22
23 void MEMORY::initialize()
24 {
25         // init memory
26         memset(ram, 0, sizeof(ram));
27         memset(cmos, 0, sizeof(cmos));
28         memset(ipl, 0xff, sizeof(ipl));
29         memset(rdmy, 0xff, sizeof(rdmy));
30         
31         // load rom images
32         FILEIO* fio = new FILEIO();
33         if(fio->Fopen(create_local_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
34                 fio->Fread(ipl, sizeof(ipl), 1);
35                 fio->Fclose();
36         }
37         if(fio->Fopen(create_local_path(_T("CMOS.BIN")), FILEIO_READ_BINARY)) {
38                 fio->Fread(cmos, sizeof(cmos), 1);
39                 fio->Fclose();
40         }
41         delete fio;
42         
43         cmos_crc32 = get_crc32(cmos, sizeof(cmos));
44 }
45
46 void MEMORY::release()
47 {
48         if(cmos_crc32 != get_crc32(cmos, sizeof(cmos))) {
49                 FILEIO* fio = new FILEIO();
50                 if(fio->Fopen(create_local_path(_T("CMOS.BIN")), FILEIO_WRITE_BINARY)) {
51                         fio->Fwrite(cmos, sizeof(cmos), 1);
52                         fio->Fclose();
53                 }
54                 delete fio;
55         }
56 }
57
58 void MEMORY::reset()
59 {
60         // init memory map
61         bank = 0x10;
62         psel = csel = 0;
63         update_map();
64         
65         // init pcm
66         pcm_on = pcm_cont = pcm_pit = false;
67         
68         // init fdc/fdd status
69         fdc_irq = motor = false;
70 }
71
72 void MEMORY::write_data8(uint32_t addr, uint32_t data)
73 {
74         addr &= 0xffff;
75         wbank[addr >> 11][addr & 0x7ff] = data;
76 }
77
78 uint32_t MEMORY::read_data8(uint32_t addr)
79 {
80         addr &= 0xffff;
81         return rbank[addr >> 11][addr & 0x7ff];
82 }
83
84 void MEMORY::write_io8(uint32_t addr, uint32_t data)
85 {
86         switch(addr & 0xff) {
87         case 0x18: case 0x19: case 0x1a: case 0x1b:
88                 bank = data;
89                 // timer gate signal
90                 d_pit->write_signal(SIG_I8253_GATE_0, data, 1);
91                 d_pit->write_signal(SIG_I8253_GATE_2, data, 2);
92                 // pcm on
93                 pcm_cont = ((data & 4) != 0);
94                 update_pcm();
95                 break;
96         case 0x1c: case 0x1d: case 0x1e: case 0x1f:
97                 psel = data;
98                 break;
99         case 0x20: case 0x21: case 0x22: case 0x23:
100                 csel = data;
101                 break;
102         }
103         update_map();
104 }
105
106 uint32_t MEMORY::read_io8(uint32_t addr)
107 {
108         switch(addr & 0xff) {
109         case 0x18: case 0x19: case 0x1a: case 0x1b:
110                 return ~config.dipswitch & 0xff;
111         case 0x30: case 0x31: case 0x32: case 0x33:
112                 return (bank & 0xf0) | (d_fdc->is_disk_inserted() ? 8 : 0) | (motor ? 0 : 2) | (fdc_irq ? 1 : 0);
113         }
114         return 0xff;
115 }
116
117 /*
118         0000-DFFF       : RAM * 4banks
119         E000-FFFF       : RAM
120         ----
121         0000-1FFF       : IPL
122         8000-87FF       : CMOS
123 */
124
125 void MEMORY::write_signal(int id, uint32_t data, uint32_t mask)
126 {
127         if(id == SIG_MEMORY_PCM) {
128                 // pcm on from pit
129                 pcm_pit = ((data & mask) != 0);
130                 update_pcm();
131         } else if(id == SIG_MEMORY_FDC_IRQ) {
132                 fdc_irq = ((data & mask) != 0);
133         } else if(id == SIG_MEMORY_MOTOR) {
134                 motor = ((data & mask) != 0);
135         }
136 }
137
138 void MEMORY::update_map()
139 {
140         if(!(psel & 1)) {
141                 SET_BANK(0x0000, 0x1fff, wdmy, ipl);
142                 SET_BANK(0x2000, 0xdfff, wdmy, rdmy);
143         } else if(csel & 1) {
144                 if(bank & 0x10) {
145                         SET_BANK(0x0000, 0x7fff, ram + 0x00000, ram + 0x00000);
146                 } else if(bank & 0x20) {
147                         SET_BANK(0x0000, 0x7fff, ram + 0x10000, ram + 0x10000);
148                 } else if(bank & 0x40) {
149                         SET_BANK(0x0000, 0x7fff, ram + 0x20000, ram + 0x20000);
150                 } else if(bank & 0x80) {
151                         SET_BANK(0x0000, 0x7fff, ram + 0x30000, ram + 0x30000);
152                 } else {
153                         SET_BANK(0x0000, 0x7fff, wdmy, rdmy);
154                 }
155                 SET_BANK(0x8000, 0x87ff, cmos, cmos);
156         } else {
157                 if(bank & 0x10) {
158                         SET_BANK(0x0000, 0xdfff, ram + 0x00000, ram + 0x00000);
159                 } else if(bank & 0x20) {
160                         SET_BANK(0x0000, 0xdfff, ram + 0x10000, ram + 0x10000);
161                 } else if(bank & 0x40) {
162                         SET_BANK(0x0000, 0xdfff, ram + 0x20000, ram + 0x20000);
163                 } else if(bank & 0x80) {
164                         SET_BANK(0x0000, 0xdfff, ram + 0x30000, ram + 0x30000);
165                 } else {
166                         SET_BANK(0x0000, 0xdfff, wdmy, rdmy);
167                 }
168         }
169         SET_BANK(0xe000, 0xffff, ram + 0xe000, ram + 0xe000);
170 }
171
172 void MEMORY::update_pcm()
173 {
174         if(!pcm_on && (pcm_cont || pcm_pit)) {
175                 d_pcm->write_signal(SIG_PCM1BIT_ON, 1, 1);
176                 pcm_on = true;
177         } else if(pcm_on && !(pcm_cont || pcm_pit)) {
178                 d_pcm->write_signal(SIG_PCM1BIT_ON, 0, 1);
179                 pcm_on = false;
180         }
181 }
182
183 #define STATE_VERSION   1
184
185 #include "../../statesub.h"
186
187 void MEMORY::decl_state()
188 {
189         enter_decl_state(STATE_VERSION);
190
191         DECL_STATE_ENTRY_1D_ARRAY(ram, sizeof(ram));
192         DECL_STATE_ENTRY_1D_ARRAY(cmos, sizeof(cmos));
193         DECL_STATE_ENTRY_UINT32(cmos_crc32);
194         DECL_STATE_ENTRY_UINT8(bank);
195         DECL_STATE_ENTRY_UINT8(psel);
196         DECL_STATE_ENTRY_UINT8(csel);
197         DECL_STATE_ENTRY_BOOL(pcm_on);
198         DECL_STATE_ENTRY_BOOL(pcm_cont);
199         DECL_STATE_ENTRY_BOOL(pcm_pit);
200         DECL_STATE_ENTRY_BOOL(fdc_irq);
201         DECL_STATE_ENTRY_BOOL(motor);
202         
203         leave_decl_state();
204 }
205
206 void MEMORY::save_state(FILEIO* state_fio)
207 {
208         if(state_entry != NULL) {
209                 state_entry->save_state(state_fio);
210         }
211 //      state_fio->FputUint32(STATE_VERSION);
212 //      state_fio->FputInt32(this_device_id);
213         
214 //      state_fio->Fwrite(ram, sizeof(ram), 1);
215 //      state_fio->Fwrite(cmos, sizeof(cmos), 1);
216 //      state_fio->FputUint32(cmos_crc32);
217 //      state_fio->FputUint8(bank);
218 //      state_fio->FputUint8(psel);
219 //      state_fio->FputUint8(csel);
220 //      state_fio->FputBool(pcm_on);
221 //      state_fio->FputBool(pcm_cont);
222 //      state_fio->FputBool(pcm_pit);
223 //      state_fio->FputBool(fdc_irq);
224 //      state_fio->FputBool(motor);
225 }
226
227 bool MEMORY::load_state(FILEIO* state_fio)
228 {
229         bool mb = false;
230         if(state_entry != NULL) {
231                 mb = state_entry->load_state(state_fio);
232         }
233         if(!mb) {
234                 return false;
235         }
236 //      if(state_fio->FgetUint32() != STATE_VERSION) {
237 //              return false;
238 //      }
239 //      if(state_fio->FgetInt32() != this_device_id) {
240 //              return false;
241 //      }
242 //      state_fio->Fread(ram, sizeof(ram), 1);
243 //      state_fio->Fread(cmos, sizeof(cmos), 1);
244 //      cmos_crc32 = state_fio->FgetUint32();
245 //      bank = state_fio->FgetUint8();
246 //      psel = state_fio->FgetUint8();
247 //      csel = state_fio->FgetUint8();
248 //      pcm_on = state_fio->FgetBool();
249 //      pcm_cont = state_fio->FgetBool();
250 //      pcm_pit = state_fio->FgetBool();
251 //      fdc_irq = state_fio->FgetBool();
252 //      motor = state_fio->FgetBool();
253         
254         // post process
255         update_map();
256         return true;
257 }
258
259 bool MEMORY::process_state(FILEIO* state_fio, bool loading)
260 {
261         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
262                 return false;
263         }
264         if(!state_fio->StateCheckInt32(this_device_id)) {
265                 return false;
266         }
267         state_fio->StateBuffer(ram, sizeof(ram), 1);
268         state_fio->StateBuffer(cmos, sizeof(cmos), 1);
269         state_fio->StateUint32(cmos_crc32);
270         state_fio->StateUint8(bank);
271         state_fio->StateUint8(psel);
272         state_fio->StateUint8(csel);
273         state_fio->StateBool(pcm_on);
274         state_fio->StateBool(pcm_cont);
275         state_fio->StateBool(pcm_pit);
276         state_fio->StateBool(fdc_irq);
277         state_fio->StateBool(motor);
278         
279         // post process
280         if(loading) {
281                 update_map();
282         }
283         return true;
284 }