OSDN Git Service

[DOC] For release 2017-01-24.
[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         for(int i = 0; i < 4; i++) {
15                 dma[i].areg = dma[i].bareg = 0;
16                 dma[i].creg = dma[i].bcreg = 0;
17         }
18 }
19
20 void UPD71071::reset()
21 {
22         for(int i = 0; i < 4; i++) {
23                 dma[i].mode = 0x04;
24         }
25         b16 = selch = base = 0;
26         cmd = tmp = 0;
27         req = sreq = tc = 0;
28         mask = 0x0f;
29 }
30
31 void UPD71071::write_io8(uint32_t addr, uint32_t data)
32 {
33         switch(addr & 0x0f) {
34         case 0x00:
35                 if(data & 1) {
36                         // dma reset
37                         for(int i = 0; i < 4; i++) {
38                                 dma[i].mode = 0x04;
39                         }
40                         selch = base = 0;
41                         cmd = tmp = 0;
42                         sreq = tc = 0;
43                         mask = 0x0f;
44                 }
45                 b16 = data & 2;
46                 break;
47         case 0x01:
48                 selch = data & 3;
49                 base = data & 4;
50                 break;
51         case 0x02:
52                 dma[selch].bcreg = (dma[selch].bcreg & 0xff00) | data;
53 //              if(!base) {
54                         dma[selch].creg = (dma[selch].creg & 0xff00) | data;
55 //              }
56                 break;
57         case 0x03:
58                 dma[selch].bcreg = (dma[selch].bcreg & 0x00ff) | (data << 8);
59 //              if(!base) {
60                         dma[selch].creg = (dma[selch].creg & 0x00ff) | (data << 8);
61 //              }
62                 break;
63         case 0x04:
64                 dma[selch].bareg = (dma[selch].bareg & 0xffff00) | data;
65 //              if(!base) {
66                         dma[selch].areg = (dma[selch].areg & 0xffff00) | data;
67 //              }
68                 break;
69         case 0x05:
70                 dma[selch].bareg = (dma[selch].bareg & 0xff00ff) | (data << 8);
71 //              if(!base) {
72                         dma[selch].areg = (dma[selch].areg & 0xff00ff) | (data << 8);
73 //              }
74                 break;
75         case 0x06:
76                 dma[selch].bareg = (dma[selch].bareg & 0x00ffff) | (data << 16);
77 //              if(!base) {
78                         dma[selch].areg = (dma[selch].areg & 0x00ffff) | (data << 16);
79 //              }
80                 break;
81         case 0x08:
82                 cmd = (cmd & 0xff00) | data;
83                 break;
84         case 0x09:
85                 cmd = (cmd & 0xff) | (data << 8);
86                 break;
87         case 0x0a:
88                 dma[selch].mode = data;
89                 break;
90         case 0x0e:
91                 if((sreq = data) != 0) {
92 #ifndef SINGLE_MODE_DMA
93                         do_dma();
94 #endif
95                 }
96                 break;
97         case 0x0f:
98                 mask = data;
99                 break;
100         }
101 }
102
103 uint32_t UPD71071::read_io8(uint32_t addr)
104 {
105         uint32_t val;
106         
107         switch(addr & 0x0f) {
108         case 0x00:
109                 return b16;
110         case 0x01:
111                 return (base << 2) | (1 << selch);
112         case 0x02:
113                 if(base) {
114                         return dma[selch].bcreg & 0xff;
115                 } else {
116                         return dma[selch].creg & 0xff;
117                 }
118         case 0x03:
119                 if(base) {
120                         return (dma[selch].bcreg >> 8) & 0xff;
121                 } else {
122                         return (dma[selch].creg >> 8) & 0xff;
123                 }
124         case 0x04:
125                 if(base) {
126                         return dma[selch].bareg & 0xff;
127                 } else {
128                         return dma[selch].areg & 0xff;
129                 }
130         case 0x05:
131                 if(base) {
132                         return (dma[selch].bareg >> 8) & 0xff;
133                 } else {
134                         return (dma[selch].areg >> 8) & 0xff;
135                 }
136         case 0x06:
137                 if(base) {
138                         return (dma[selch].bareg >> 16) & 0xff;
139                 } else {
140                         return (dma[selch].areg >> 16) & 0xff;
141                 }
142         case 0x08:
143                 return cmd & 0xff;
144         case 0x09:
145                 return (cmd >> 8) & 0xff;
146         case 0x0a:
147                 return dma[selch].mode;
148         case 0x0b:
149                 val = (req << 4) | tc;
150                 tc = 0;
151                 return val;
152         case 0x0c:
153                 return tmp & 0xff;
154         case 0x0d:
155                 return (tmp >> 8) & 0xff;
156         case 0x0e:
157                 return sreq;
158         case 0x0f:
159                 return mask;
160         }
161         return 0xff;
162 }
163
164 void UPD71071::write_signal(int id, uint32_t data, uint32_t mask)
165 {
166         uint8_t bit = 1 << (id & 3);
167         
168         if(data & mask) {
169                 if(!(req & bit)) {
170                         req |= bit;
171 #ifndef SINGLE_MODE_DMA
172                         do_dma();
173 #endif
174                 }
175         } else {
176                 req &= ~bit;
177         }
178 }
179
180 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
181
182 void UPD71071::do_dma()
183 {
184         // check DDMA
185         if(cmd & 4) {
186                 return;
187         }
188         // ToDo: Will check WORD transfer mode for FM-Towns.(mode.bit0 = '1).
189         // run dma
190         for(int c = 0; c < 4; c++) {
191                 uint8_t bit = 1 << c;
192                 if(((req | sreq) & bit) && !(mask & bit)) {
193                         // execute dma
194                         while((req | sreq) & bit) {
195 #if 0
196                                 if((dma[c].mode & 0x01) == 1) { // 16bit transfer mode.
197                                         if((dma[c].mode & 0x0c) == 4) {
198                                                 // io -> memory
199                                                 uint32_t val = dma[c].dev->read_dma_io16(0);
200                                                 d_mem->write_dma_data16(dma[c].areg, val);
201                                                 // update temporary register
202                                                 tmp = val;
203                                         } else if((dma[c].mode & 0x0c) == 8) {
204                                                 // memory -> io
205                                                 uint32_t val = d_mem->read_dma_data16(dma[c].areg);
206                                                 dma[c].dev->write_dma_io16(0, val);
207                                                 // update temporary register
208                                                 tmp = val;
209                                         }
210                                         if(dma[c].mode & 0x20) {
211                                                 dma[c].areg = (dma[c].areg - 2) & 0xffffff;
212                                         } else {
213                                                 dma[c].areg = (dma[c].areg + 2) & 0xffffff;
214                                         }
215                                 } else { // 8bit mode
216 #endif
217                                 if((dma[c].mode & 0x0c) == 4) {
218                                         // io -> memory
219                                         uint32_t val = dma[c].dev->read_dma_io8(0);
220                                         d_mem->write_dma_data8(dma[c].areg, val);
221                                         // update temporary register
222                                         tmp = (tmp >> 8) | (val << 8);
223                                 } else if((dma[c].mode & 0x0c) == 8) {
224                                         // memory -> io
225                                         uint32_t val = d_mem->read_dma_data8(dma[c].areg);
226                                         dma[c].dev->write_dma_io8(0, val);
227                                         // update temporary register
228                                         tmp = (tmp >> 8) | (val << 8);
229                                 }
230                                 if(dma[c].mode & 0x20) {
231                                         dma[c].areg = (dma[c].areg - 1) & 0xffffff;
232                                 } else {
233                                         dma[c].areg = (dma[c].areg + 1) & 0xffffff;
234                                 }
235 #if 0 // 16bit mode
236                                 }
237 #endif
238                                 if(dma[c].creg-- == 0) {
239                                         // TC
240                                         if(dma[c].mode & 0x10) {
241                                                 // auto initialize
242                                                 dma[c].areg = dma[c].bareg;
243                                                 dma[c].creg = dma[c].bcreg;
244                                         } else {
245                                                 mask |= bit;
246                                         }
247                                         req &= ~bit;
248                                         sreq &= ~bit;
249                                         tc |= bit;
250                                         
251                                         write_signals(&outputs_tc, 0xffffffff);
252 #ifdef SINGLE_MODE_DMA
253                                 } else if((dma[c].mode & 0xc0) == 0x40) {
254                                         // single mode
255                                         break;
256 #endif
257                                 }
258                         }
259                 }
260         }
261 #ifdef SINGLE_MODE_DMA
262         if(d_dma) {
263                 d_dma->do_dma();
264         }
265 #endif
266 }
267
268 #define STATE_VERSION   1
269
270 void UPD71071::save_state(FILEIO* state_fio)
271 {
272         state_fio->FputUint32(STATE_VERSION);
273         state_fio->FputInt32(this_device_id);
274         
275         for(int i = 0; i < 4; i++) {
276                 state_fio->FputUint32(dma[i].areg);
277                 state_fio->FputUint32(dma[i].bareg);
278                 state_fio->FputUint16(dma[i].creg);
279                 state_fio->FputUint16(dma[i].bcreg);
280                 state_fio->FputUint8(dma[i].mode);
281         }
282         state_fio->FputUint8(b16);
283         state_fio->FputUint8(selch);
284         state_fio->FputUint8(base);
285         state_fio->FputUint16(cmd);
286         state_fio->FputUint16(tmp);
287         state_fio->FputUint8(req);
288         state_fio->FputUint8(sreq);
289         state_fio->FputUint8(mask);
290         state_fio->FputUint8(tc);
291 }
292
293 bool UPD71071::load_state(FILEIO* state_fio)
294 {
295         if(state_fio->FgetUint32() != STATE_VERSION) {
296                 return false;
297         }
298         if(state_fio->FgetInt32() != this_device_id) {
299                 return false;
300         }
301         for(int i = 0; i < 4; i++) {
302                 dma[i].areg = state_fio->FgetUint32();
303                 dma[i].bareg = state_fio->FgetUint32();
304                 dma[i].creg = state_fio->FgetUint16();
305                 dma[i].bcreg = state_fio->FgetUint16();
306                 dma[i].mode = state_fio->FgetUint8();
307         }
308         b16 = state_fio->FgetUint8();
309         selch = state_fio->FgetUint8();
310         base = state_fio->FgetUint8();
311         cmd = state_fio->FgetUint16();
312         tmp = state_fio->FgetUint16();
313         req = state_fio->FgetUint8();
314         sreq = state_fio->FgetUint8();
315         mask = state_fio->FgetUint8();
316         tc = state_fio->FgetUint8();
317         return true;
318 }
319