OSDN Git Service

[VM][General] Merge Upstream 20180530.
[csp-qt/common_source_project-fm7.git] / source / src / vm / upd71071.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2007.08.14 -
6
7         [ uPD71071 ]
8 */
9
10 #include "upd71071.h"
11
12 void UPD71071::initialize()
13 {
14         DEVICE::initialize();
15         _SINGLE_MODE_DMA = osd->check_feature(_T("SINGLE_MODE_DMA"));
16         
17         for(int i = 0; i < 4; i++) {
18                 dma[i].areg = dma[i].bareg = 0;
19                 dma[i].creg = dma[i].bcreg = 0;
20         }
21 }
22
23 void UPD71071::reset()
24 {
25         for(int i = 0; i < 4; i++) {
26                 dma[i].mode = 0x04;
27         }
28         b16 = selch = base = 0;
29         cmd = tmp = 0;
30         req = sreq = tc = 0;
31         mask = 0x0f;
32 }
33
34 void UPD71071::write_io8(uint32_t addr, uint32_t data)
35 {
36         switch(addr & 0x0f) {
37         case 0x00:
38                 if(data & 1) {
39                         // dma reset
40                         for(int i = 0; i < 4; i++) {
41                                 dma[i].mode = 0x04;
42                         }
43                         selch = base = 0;
44                         cmd = tmp = 0;
45                         sreq = tc = 0;
46                         mask = 0x0f;
47                 }
48                 b16 = data & 2;
49                 break;
50         case 0x01:
51                 selch = data & 3;
52                 base = data & 4;
53                 break;
54         case 0x02:
55                 dma[selch].bcreg = (dma[selch].bcreg & 0xff00) | data;
56 //              if(!base) {
57                         dma[selch].creg = (dma[selch].creg & 0xff00) | data;
58 //              }
59                 break;
60         case 0x03:
61                 dma[selch].bcreg = (dma[selch].bcreg & 0x00ff) | (data << 8);
62 //              if(!base) {
63                         dma[selch].creg = (dma[selch].creg & 0x00ff) | (data << 8);
64 //              }
65                 break;
66         case 0x04:
67                 dma[selch].bareg = (dma[selch].bareg & 0xffff00) | data;
68 //              if(!base) {
69                         dma[selch].areg = (dma[selch].areg & 0xffff00) | data;
70 //              }
71                 break;
72         case 0x05:
73                 dma[selch].bareg = (dma[selch].bareg & 0xff00ff) | (data << 8);
74 //              if(!base) {
75                         dma[selch].areg = (dma[selch].areg & 0xff00ff) | (data << 8);
76 //              }
77                 break;
78         case 0x06:
79                 dma[selch].bareg = (dma[selch].bareg & 0x00ffff) | (data << 16);
80 //              if(!base) {
81                         dma[selch].areg = (dma[selch].areg & 0x00ffff) | (data << 16);
82 //              }
83                 break;
84         case 0x08:
85                 cmd = (cmd & 0xff00) | data;
86                 break;
87         case 0x09:
88                 cmd = (cmd & 0xff) | (data << 8);
89                 break;
90         case 0x0a:
91                 dma[selch].mode = data;
92                 break;
93         case 0x0e:
94                 if(((sreq = data) != 0) && !(_SINGLE_MODE_DMA)) {
95 //#ifndef SINGLE_MODE_DMA
96                         do_dma();
97 //#endif
98                 }
99                 break;
100         case 0x0f:
101                 mask = data;
102                 break;
103         }
104 }
105
106 uint32_t UPD71071::read_io8(uint32_t addr)
107 {
108         uint32_t val;
109         
110         switch(addr & 0x0f) {
111         case 0x00:
112                 return b16;
113         case 0x01:
114                 return (base << 2) | (1 << selch);
115         case 0x02:
116                 if(base) {
117                         return dma[selch].bcreg & 0xff;
118                 } else {
119                         return dma[selch].creg & 0xff;
120                 }
121         case 0x03:
122                 if(base) {
123                         return (dma[selch].bcreg >> 8) & 0xff;
124                 } else {
125                         return (dma[selch].creg >> 8) & 0xff;
126                 }
127         case 0x04:
128                 if(base) {
129                         return dma[selch].bareg & 0xff;
130                 } else {
131                         return dma[selch].areg & 0xff;
132                 }
133         case 0x05:
134                 if(base) {
135                         return (dma[selch].bareg >> 8) & 0xff;
136                 } else {
137                         return (dma[selch].areg >> 8) & 0xff;
138                 }
139         case 0x06:
140                 if(base) {
141                         return (dma[selch].bareg >> 16) & 0xff;
142                 } else {
143                         return (dma[selch].areg >> 16) & 0xff;
144                 }
145         case 0x08:
146                 return cmd & 0xff;
147         case 0x09:
148                 return (cmd >> 8) & 0xff;
149         case 0x0a:
150                 return dma[selch].mode;
151         case 0x0b:
152                 val = (req << 4) | tc;
153                 tc = 0;
154                 return val;
155         case 0x0c:
156                 return tmp & 0xff;
157         case 0x0d:
158                 return (tmp >> 8) & 0xff;
159         case 0x0e:
160                 return sreq;
161         case 0x0f:
162                 return mask;
163         }
164         return 0xff;
165 }
166
167 void UPD71071::write_signal(int id, uint32_t data, uint32_t mask)
168 {
169         uint8_t bit = 1 << (id & 3);
170         
171         if(data & mask) {
172                 if(!(req & bit)) {
173                         req |= bit;
174 //#ifndef SINGLE_MODE_DMA
175                         if(!_SINGLE_MODE_DMA) do_dma();
176 //#endif
177                 }
178         } else {
179                 req &= ~bit;
180         }
181 }
182
183 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
184
185 void UPD71071::do_dma()
186 {
187         // check DDMA
188         if(cmd & 4) {
189                 return;
190         }
191         
192         // run dma
193         for(int c = 0; c < 4; c++) {
194                 uint8_t bit = 1 << c;
195                 if(((req | sreq) & bit) && !(mask & bit)) {
196                         // execute dma
197                         while((req | sreq) & bit) {
198                                 // ToDo: Will check WORD transfer mode for FM-Towns.(mode.bit0 = '1).
199 /*
200                                 if((dma[c].mode & 0x01) == 1) {
201                                         // 16bit transfer mode
202                                         if((dma[c].mode & 0x0c) == 0x00) {
203                                                 // verify
204                                                 uint32_t val = dma[c].dev->read_dma_io16(0);
205                                                 // update temporary register
206                                                 tmp = val;
207                                         } else if((dma[c].mode & 0x0c) == 0x04) {
208                                                 // io -> memory
209                                                 uint32_t val;
210                                                 if(dma[c].dev != NULL) {
211                                                         val = dma[c].dev->read_dma_io16(0);
212                                                 } else {
213                                                         val = 0xffff;
214                                                 }
215                                                 d_mem->write_dma_data16(dma[c].areg, val);
216                                                 // update temporary register
217                                                 tmp = val;
218                                         } else if((dma[c].mode & 0x0c) == 0x08) {
219                                                 // memory -> io
220                                                 uint32_t val = d_mem->read_dma_data16(dma[c].areg);
221                                                 if(dma[c].dev != NULL) dma[c].dev->write_dma_io16(0, val);
222                                                 // update temporary register
223                                                 tmp = val;
224                                         }
225                                         if(dma[c].mode & 0x20) {
226                                                 dma[c].areg = (dma[c].areg - 2) & 0xffffff;
227                                         } else {
228                                                 dma[c].areg = (dma[c].areg + 2) & 0xffffff;
229                                         }
230                                 } else
231 */
232                                 {
233                                         // 8bit transfer mode
234                                         if((dma[c].mode & 0x0c) == 0x00) {
235                                                 // verify
236                                                 uint32_t val = dma[c].dev->read_dma_io8(0);
237                                                 // update temporary register
238                                                 tmp = (tmp >> 8) | (val << 8);
239                                         } else if((dma[c].mode & 0x0c) == 0x04) {
240                                                 // io -> memory
241                                                 uint32_t val;
242                                                 val = dma[c].dev->read_dma_io8(0);
243                                                 d_mem->write_dma_data8(dma[c].areg, val);
244                                                 // update temporary register
245                                                 tmp = (tmp >> 8) | (val << 8);
246                                         } else if((dma[c].mode & 0x0c) == 0x08) {
247                                                 // memory -> io
248                                                 uint32_t val = d_mem->read_dma_data8(dma[c].areg);
249                                                 dma[c].dev->write_dma_io8(0, val);
250                                                 // update temporary register
251                                                 tmp = (tmp >> 8) | (val << 8);
252                                         }
253                                         if(dma[c].mode & 0x20) {
254                                                 dma[c].areg = (dma[c].areg - 1) & 0xffffff;
255                                         } else {
256                                                 dma[c].areg = (dma[c].areg + 1) & 0xffffff;
257                                         }
258                                 }
259                                 if(dma[c].creg-- == 0) {
260                                         // TC
261                                         if(dma[c].mode & 0x10) {
262                                                 // auto initialize
263                                                 dma[c].areg = dma[c].bareg;
264                                                 dma[c].creg = dma[c].bcreg;
265                                         } else {
266                                                 mask |= bit;
267                                         }
268                                         req &= ~bit;
269                                         sreq &= ~bit;
270                                         tc |= bit;
271                                         
272                                         write_signals(&outputs_tc, 0xffffffff);
273 //#ifdef SINGLE_MODE_DMA
274                                 } else if(_SINGLE_MODE_DMA) {
275                                         if((dma[c].mode & 0xc0) == 0x40) {
276                                                 // single mode
277                                                 break;
278                                         }
279 //#endif
280                                 }
281                         }
282                 }
283         }
284 //#ifdef SINGLE_MODE_DMA
285         if(_SINGLE_MODE_DMA) {
286                 if(d_dma) {
287                         d_dma->do_dma();
288                 }
289         }
290 //#endif
291 }
292
293 #define STATE_VERSION   1
294
295 #include "../statesub.h"
296
297 void UPD71071::decl_state()
298 {
299         enter_decl_state(STATE_VERSION);
300
301         for(int i = 0; i < 4; i++) {
302                 DECL_STATE_ENTRY_UINT32_MEMBER((dma[i].areg), i);
303                 DECL_STATE_ENTRY_UINT32_MEMBER((dma[i].bareg), i);
304                 DECL_STATE_ENTRY_UINT16_MEMBER((dma[i].creg), i);
305                 DECL_STATE_ENTRY_UINT16_MEMBER((dma[i].bcreg), i);
306                 DECL_STATE_ENTRY_UINT8_MEMBER((dma[i].mode), i);
307         }
308         DECL_STATE_ENTRY_UINT8(b16);
309         DECL_STATE_ENTRY_UINT8(selch);
310         DECL_STATE_ENTRY_UINT8(base);
311         DECL_STATE_ENTRY_UINT16(cmd);
312         DECL_STATE_ENTRY_UINT16(tmp);
313         DECL_STATE_ENTRY_UINT8(req);
314         DECL_STATE_ENTRY_UINT8(sreq);
315         DECL_STATE_ENTRY_UINT8(mask);
316         DECL_STATE_ENTRY_UINT8(tc);
317
318         leave_decl_state();
319 }       
320
321 void UPD71071::save_state(FILEIO* state_fio)
322 {
323         if(state_entry != NULL) {
324                 state_entry->save_state(state_fio);
325         }
326         
327 //      state_fio->FputUint32(STATE_VERSION);
328 //      state_fio->FputInt32(this_device_id);
329         
330 //      for(int i = 0; i < 4; i++) {
331 //              state_fio->FputUint32(dma[i].areg);
332 //              state_fio->FputUint32(dma[i].bareg);
333 //              state_fio->FputUint16(dma[i].creg);
334 //              state_fio->FputUint16(dma[i].bcreg);
335 //              state_fio->FputUint8(dma[i].mode);
336 //      }
337 //      state_fio->FputUint8(b16);
338 //      state_fio->FputUint8(selch);
339 //      state_fio->FputUint8(base);
340 //      state_fio->FputUint16(cmd);
341 //      state_fio->FputUint16(tmp);
342 //      state_fio->FputUint8(req);
343 //      state_fio->FputUint8(sreq);
344 //      state_fio->FputUint8(mask);
345 //      state_fio->FputUint8(tc);
346 }
347
348 bool UPD71071::load_state(FILEIO* state_fio)
349 {
350         bool mb = false;
351         if(state_entry != NULL) {
352                 mb = state_entry->load_state(state_fio);
353         }
354         if(!mb) return false;
355
356 //      if(state_fio->FgetUint32() != STATE_VERSION) {
357 //              return false;
358 //      }
359 //      if(state_fio->FgetInt32() != this_device_id) {
360 //              return false;
361 //      }
362 //      for(int i = 0; i < 4; i++) {
363 //              dma[i].areg = state_fio->FgetUint32();
364 //              dma[i].bareg = state_fio->FgetUint32();
365 //              dma[i].creg = state_fio->FgetUint16();
366 //              dma[i].bcreg = state_fio->FgetUint16();
367 //              dma[i].mode = state_fio->FgetUint8();
368 //      }
369 //      b16 = state_fio->FgetUint8();
370 //      selch = state_fio->FgetUint8();
371 //      base = state_fio->FgetUint8();
372 //      cmd = state_fio->FgetUint16();
373 //      tmp = state_fio->FgetUint16();
374 //      req = state_fio->FgetUint8();
375 //      sreq = state_fio->FgetUint8();
376 //      mask = state_fio->FgetUint8();
377 //      tc = state_fio->FgetUint8();
378         return true;
379 }
380