OSDN Git Service

[VM][DEVICE] Get OSD:: at constructor, not initialize().
[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                                                 val = dma[c].dev->read_dma_io8(0);
233                                                 d_mem->write_dma_data8(dma[c].areg, val);
234                                                 // update temporary register
235                                                 tmp = (tmp >> 8) | (val << 8);
236                                         } else if((dma[c].mode & 0x0c) == 8) {
237                                                 // memory -> io
238                                                 uint32_t val = d_mem->read_dma_data8(dma[c].areg);
239                                                 dma[c].dev->write_dma_io8(0, val);
240                                                 // update temporary register
241                                                 tmp = (tmp >> 8) | (val << 8);
242                                         }
243                                         if(dma[c].mode & 0x20) {
244                                                 dma[c].areg = (dma[c].areg - 1) & 0xffffff;
245                                         } else {
246                                                 dma[c].areg = (dma[c].areg + 1) & 0xffffff;
247                                         }
248                                 }
249                                 if(dma[c].creg-- == 0) {
250                                         // TC
251                                         if(dma[c].mode & 0x10) {
252                                                 // auto initialize
253                                                 dma[c].areg = dma[c].bareg;
254                                                 dma[c].creg = dma[c].bcreg;
255                                         } else {
256                                                 mask |= bit;
257                                         }
258                                         req &= ~bit;
259                                         sreq &= ~bit;
260                                         tc |= bit;
261                                         
262                                         write_signals(&outputs_tc, 0xffffffff);
263 //#ifdef SINGLE_MODE_DMA
264                                 } else if(_SINGLE_MODE_DMA) {
265                                         if((dma[c].mode & 0xc0) == 0x40) {
266                                                 // single mode
267                                                 break;
268                                         }
269 //#endif
270                                 }
271                         }
272                 }
273         }
274 //#ifdef SINGLE_MODE_DMA
275         if(_SINGLE_MODE_DMA) {
276                 if(d_dma) {
277                         d_dma->do_dma();
278                 }
279         }
280 //#endif
281 }
282
283 #define STATE_VERSION   1
284
285 void UPD71071::save_state(FILEIO* state_fio)
286 {
287         state_fio->FputUint32(STATE_VERSION);
288         state_fio->FputInt32(this_device_id);
289         
290         for(int i = 0; i < 4; i++) {
291                 state_fio->FputUint32(dma[i].areg);
292                 state_fio->FputUint32(dma[i].bareg);
293                 state_fio->FputUint16(dma[i].creg);
294                 state_fio->FputUint16(dma[i].bcreg);
295                 state_fio->FputUint8(dma[i].mode);
296         }
297         state_fio->FputUint8(b16);
298         state_fio->FputUint8(selch);
299         state_fio->FputUint8(base);
300         state_fio->FputUint16(cmd);
301         state_fio->FputUint16(tmp);
302         state_fio->FputUint8(req);
303         state_fio->FputUint8(sreq);
304         state_fio->FputUint8(mask);
305         state_fio->FputUint8(tc);
306 }
307
308 bool UPD71071::load_state(FILEIO* state_fio)
309 {
310         if(state_fio->FgetUint32() != STATE_VERSION) {
311                 return false;
312         }
313         if(state_fio->FgetInt32() != this_device_id) {
314                 return false;
315         }
316         for(int i = 0; i < 4; i++) {
317                 dma[i].areg = state_fio->FgetUint32();
318                 dma[i].bareg = state_fio->FgetUint32();
319                 dma[i].creg = state_fio->FgetUint16();
320                 dma[i].bcreg = state_fio->FgetUint16();
321                 dma[i].mode = state_fio->FgetUint8();
322         }
323         b16 = state_fio->FgetUint8();
324         selch = state_fio->FgetUint8();
325         base = state_fio->FgetUint8();
326         cmd = state_fio->FgetUint16();
327         tmp = state_fio->FgetUint16();
328         req = state_fio->FgetUint8();
329         sreq = state_fio->FgetUint8();
330         mask = state_fio->FgetUint8();
331         tc = state_fio->FgetUint8();
332         return true;
333 }
334