OSDN Git Service

[VM][General][WIP] Start to merge upstream 2018-10-14.Open branch upstream_20181014 .
[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 bool UPD71071::process_state(FILEIO* state_fio, bool loading)
296 {
297         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
298                 return false;
299         }
300         if(!state_fio->StateCheckInt32(this_device_id)) {
301                 return false;
302         }
303         for(int i = 0; i < 4; i++) {
304                 state_fio->StateValue(dma[i].areg);
305                 state_fio->StateValue(dma[i].bareg);
306                 state_fio->StateValue(dma[i].creg);
307                 state_fio->StateValue(dma[i].bcreg);
308                 state_fio->StateValue(dma[i].mode);
309         }
310         state_fio->StateValue(b16);
311         state_fio->StateValue(selch);
312         state_fio->StateValue(base);
313         state_fio->StateValue(cmd);
314         state_fio->StateValue(tmp);
315         state_fio->StateValue(req);
316         state_fio->StateValue(sreq);
317         state_fio->StateValue(mask);
318         state_fio->StateValue(tc);
319         return true;
320 }
321