OSDN Git Service

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