OSDN Git Service

[VM] Add some devices to libCSPcommon_vm .
[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) == 4) {
203                                                 // io -> memory
204                                                 uint32_t val;
205                                                 if(dma[c].dev != NULL) {
206                                                         val = dma[c].dev->read_dma_io16(0);
207                                                 } else {
208                                                         val = 0xffff;
209                                                 }
210                                                 d_mem->write_dma_data16(dma[c].areg, val);
211                                                 // update temporary register
212                                                 tmp = val;
213                                         } else if((dma[c].mode & 0x0c) == 8) {
214                                                 // memory -> io
215                                                 uint32_t val = d_mem->read_dma_data16(dma[c].areg);
216                                                 if(dma[c].dev != NULL) dma[c].dev->write_dma_io16(0, val);
217                                                 // update temporary register
218                                                 tmp = val;
219                                         }
220                                         if(dma[c].mode & 0x20) {
221                                                 dma[c].areg = (dma[c].areg - 2) & 0xffffff;
222                                         } else {
223                                                 dma[c].areg = (dma[c].areg + 2) & 0xffffff;
224                                         }
225                                 } else
226 */
227                                 {
228                                         // 8bit transfer mode
229                                         if((dma[c].mode & 0x0c) == 4) {
230                                                 // io -> memory
231                                                 uint32_t val;
232                                                 if(dma[c].dev != NULL) {
233                                                         val = dma[c].dev->read_dma_io8(0);
234                                                 } else {
235                                                         val = 0xff;
236                                                 }
237                                                 d_mem->write_dma_data8(dma[c].areg, val);
238                                                 // update temporary register
239                                                 tmp = (tmp >> 8) | (val << 8);
240                                         } else if((dma[c].mode & 0x0c) == 8) {
241                                                 // memory -> io
242                                                 uint32_t val = d_mem->read_dma_data8(dma[c].areg);
243                                                 if(dma[c].dev != NULL) {
244                                                         dma[c].dev->write_dma_io8(0, val);
245                                                 }
246                                                 // update temporary register
247                                                 tmp = (tmp >> 8) | (val << 8);
248                                         }
249                                         if(dma[c].mode & 0x20) {
250                                                 dma[c].areg = (dma[c].areg - 1) & 0xffffff;
251                                         } else {
252                                                 dma[c].areg = (dma[c].areg + 1) & 0xffffff;
253                                         }
254                                 }
255                                 if(dma[c].creg-- == 0) {
256                                         // TC
257                                         if(dma[c].mode & 0x10) {
258                                                 // auto initialize
259                                                 dma[c].areg = dma[c].bareg;
260                                                 dma[c].creg = dma[c].bcreg;
261                                         } else {
262                                                 mask |= bit;
263                                         }
264                                         req &= ~bit;
265                                         sreq &= ~bit;
266                                         tc |= bit;
267                                         
268                                         write_signals(&outputs_tc, 0xffffffff);
269 //#ifdef SINGLE_MODE_DMA
270                                 } else if(_SINGLE_MODE_DMA) {
271                                         if((dma[c].mode & 0xc0) == 0x40) {
272                                                 // single mode
273                                                 break;
274                                         }
275 //#endif
276                                 }
277                         }
278                 }
279         }
280 //#ifdef SINGLE_MODE_DMA
281         if(_SINGLE_MODE_DMA) {
282                 if(d_dma) {
283                         d_dma->do_dma();
284                 }
285         }
286 //#endif
287 }
288
289 #define STATE_VERSION   1
290
291 void UPD71071::save_state(FILEIO* state_fio)
292 {
293         state_fio->FputUint32(STATE_VERSION);
294         state_fio->FputInt32(this_device_id);
295         
296         for(int i = 0; i < 4; i++) {
297                 state_fio->FputUint32(dma[i].areg);
298                 state_fio->FputUint32(dma[i].bareg);
299                 state_fio->FputUint16(dma[i].creg);
300                 state_fio->FputUint16(dma[i].bcreg);
301                 state_fio->FputUint8(dma[i].mode);
302         }
303         state_fio->FputUint8(b16);
304         state_fio->FputUint8(selch);
305         state_fio->FputUint8(base);
306         state_fio->FputUint16(cmd);
307         state_fio->FputUint16(tmp);
308         state_fio->FputUint8(req);
309         state_fio->FputUint8(sreq);
310         state_fio->FputUint8(mask);
311         state_fio->FputUint8(tc);
312 }
313
314 bool UPD71071::load_state(FILEIO* state_fio)
315 {
316         if(state_fio->FgetUint32() != STATE_VERSION) {
317                 return false;
318         }
319         if(state_fio->FgetInt32() != this_device_id) {
320                 return false;
321         }
322         for(int i = 0; i < 4; i++) {
323                 dma[i].areg = state_fio->FgetUint32();
324                 dma[i].bareg = state_fio->FgetUint32();
325                 dma[i].creg = state_fio->FgetUint16();
326                 dma[i].bcreg = state_fio->FgetUint16();
327                 dma[i].mode = state_fio->FgetUint8();
328         }
329         b16 = state_fio->FgetUint8();
330         selch = state_fio->FgetUint8();
331         base = state_fio->FgetUint8();
332         cmd = state_fio->FgetUint16();
333         tmp = state_fio->FgetUint16();
334         req = state_fio->FgetUint8();
335         sreq = state_fio->FgetUint8();
336         mask = state_fio->FgetUint8();
337         tc = state_fio->FgetUint8();
338         return true;
339 }
340