1 //////////////////////////////////////////////////
2 // //
3 // Emu64 //
4 // von Thorsten Kattanek //
5 // //
6 // #file: reu_class.cpp //
7 // //
8 // Dieser Sourcecode ist Copyright geschützt! //
9 // Geistiges Eigentum von Th.Kattanek //
10 // //
11 // Letzte Änderung am 13.09.2019 //
12 // www.emu64.de //
13 // //
14 //////////////////////////////////////////////////
15
16 #include "reu_class.h"
17
REUClass()18 REUClass::REUClass()
19 {
20 REUInsert = false;
21
22 ClearRAM();
23
24 DMAStatus = 0;
25
26 Reset();
27 }
28
~REUClass()29 REUClass::~REUClass()
30 {
31 }
32
Insert(void)33 void REUClass::Insert(void)
34 {
35 REUInsert = true;
36 REUWait_FF00 = false;
37 }
38
Remove(void)39 void REUClass::Remove(void)
40 {
41 REUInsert = false;
42 }
43
LoadRAM(const char * filename)44 int REUClass::LoadRAM(const char *filename)
45 {
46 /// REU Inhalt laden ...
47 FILE* file;
48 file = fopen (filename,"rb");
49 if (file == NULL)
50 {
51 return 1;
52 }
53
54 size_t reading_bytes;
55
56 for(int i=0;i<256;i++)
57 {
58 reading_bytes = fread(RamBaenke[i],1,0x10000,file);
59 if(reading_bytes < 0x10000)
60 {
61 printf("Fehler beim laden der %d. REU RamBank\n",i);
62 return 1;
63 }
64 }
65
66 fclose(file);
67 return 0;
68 }
69
SaveRAM(const char * filename)70 int REUClass::SaveRAM(const char *filename)
71 {
72 /// REU Inhalt speichern ...
73 FILE* file;
74 file = fopen (filename,"wb");
75 if (file == NULL)
76 {
77 return 1;
78 }
79 for(int i=0;i<256;i++) fwrite(RamBaenke[i],1,0x10000,file);
80 fclose(file);
81 return 0;
82 }
83
ClearRAM(void)84 void REUClass::ClearRAM(void)
85 {
86 for(int i=0;i<256;i++)
87 for(int j=0;j<0x10000;j++)
88 RamBaenke[i][j] = 0;
89 }
90
OneZyklus(void)91 void REUClass::OneZyklus(void)
92 {
93 static unsigned char tmp1;
94
95 if(!REUInsert) return;
96 if(!*RESET) Reset();
97 if(!BA_STATUS) *BA = false;
98
99 if(*WRITE_FF00)
100 {
101 *WRITE_FF00 = false;
102
103 if(REUWait_FF00)
104 {
105 BA_STATUS = false; // CPU anhalten
106 CPUWaitCounter = 3; // 3 Zyklen Warten bis CPU anhält
107 TransferStart = true;
108 switch(TransferTyp)
109 {
110 case 0:
111 DMAStatus = 2;
112 break;
113 case 1:
114 DMAStatus = 1;
115 break;
116 case 2:
117 DMAStatus = 3;
118 break;
119 case 3:
120 DMAStatus = 4;
121 break;
122 }
123 }
124 }
125
126 if(TransferStart)
127 {
128 if(CPUWaitCounter > 0)
129 {
130 CPUWaitCounter--;
131 }
132 else
133 {
134 switch(TransferTyp)
135 {
136 case 0: // STASH C64 ---> REU
137 RamBaenke[Bank][AdresseREU] = Read(AdresseC64);
138 if((IO[10] & 128) != 128) AdresseC64++;
139 if((IO[10] & 64) != 64)
140 {
141 AdresseREU++;
142 if(AdresseREU == 0) Bank++;
143 }
144 Counter--;
145 if(Counter == 0)
146 {
147 TransferStart = false;
148 IO[0] |= 64;
149 BA_STATUS = true;
150 if((IO[1] & 32) != 32)
151 {
152 IO[2] = (unsigned char) AdresseC64;
153 IO[3] = (unsigned char) (AdresseC64>>8);
154 IO[4] = (unsigned char) AdresseREU;
155 IO[5] = (unsigned char) (AdresseREU>>8);
156 IO[6] = Bank;
157 IO[7] = (unsigned char) Counter;
158 IO[8] = (unsigned char) (Counter>>8);
159 }
160 if((IO[9] & 128) == 128) // Interrup ist zugelasssen ?
161 {
162 // Ja
163 if((IO[9] & 64) == 64) IO[0] |= 128;
164 }
165 }
166 break;
167 case 1: // FETCH REU ---> C64
168 Write(AdresseC64,RamBaenke[Bank][AdresseREU]);
169 if((IO[10] & 128) != 128) AdresseC64++;
170 if((IO[10] & 64) != 64)
171 {
172 AdresseREU++;
173 if(AdresseREU == 0) Bank++;
174 }
175 Counter--;
176 if(Counter == 0)
177 {
178 TransferStart = false;
179 IO[0] |= 64;
180 BA_STATUS = true;
181 if((IO[1] & 32) != 32)
182 {
183 IO[2] = (unsigned char) AdresseC64;
184 IO[3] = (unsigned char) (AdresseC64>>8);
185 IO[4] = (unsigned char) AdresseREU;
186 IO[5] = (unsigned char) (AdresseREU>>8);
187 IO[6] = Bank;
188 IO[7] = (unsigned char) Counter;
189 IO[8] = (unsigned char) (Counter>>8);
190 }
191 if((IO[9] & 128) == 128) // Interrup ist zugelasssen ?
192 {
193 // Ja
194 if((IO[9] & 64) == 64) IO[0] |= 128;
195 }
196 }
197 break;
198 case 2: // SWAP C64 <--> REU
199 tmp1 = Read(AdresseC64);
200 Write(AdresseC64,RamBaenke[Bank][AdresseREU]);
201 RamBaenke[Bank][AdresseREU] = tmp1;
202 if((IO[10] & 128) != 128) AdresseC64++;
203 if((IO[10] & 64) != 64)
204 {
205 AdresseREU++;
206 if(AdresseREU == 0) Bank++;
207 }
208 Counter--;
209 if(Counter == 0)
210 {
211 TransferStart = false;
212 IO[0] |= 64;
213 BA_STATUS = true;
214 if((IO[1] & 32) != 32)
215 {
216 IO[2] = (unsigned char) AdresseC64;
217 IO[3] = (unsigned char) (AdresseC64>>8);
218 IO[4] = (unsigned char) AdresseREU;
219 IO[5] = (unsigned char) (AdresseREU>>8);
220 IO[6] = Bank;
221 IO[7] = (unsigned char) Counter;
222 IO[8] = (unsigned char) (Counter>>8);
223 }
224 if((IO[9] & 128) == 128) // Interrup ist zugelasssen ?
225 {
226 // Ja
227 if((IO[9] & 64) == 64) IO[0] |= 128;
228 }
229 }
230 break;
231 case 3: // VERIFY C64 ---- REU
232 if(RamBaenke[Bank][AdresseREU] != Read(AdresseC64))
233 {
234 TransferStart = false;
235 IO[0] |= 32;
236 IO[0] |= 64;
237 BA_STATUS = true;
238 if((IO[9] & 128) == 128) // Interrup ist zugelasssen ?
239 {
240 // Ja
241 if((IO[9] & 32) == 32) IO[0] |= 128;
242 }
243 }
244 if((IO[10] & 128) != 128) AdresseC64++;
245 if((IO[10] & 64) != 64)
246 {
247 AdresseREU++;
248 if(AdresseREU == 0) Bank++;
249 }
250 Counter--;
251 if(Counter == 0)
252 {
253 TransferStart = false;
254 IO[0] |= 64;
255 BA_STATUS = true;
256 if((IO[1] & 32) != 32)
257 {
258 IO[2] = (unsigned char) AdresseC64;
259 IO[3] = (unsigned char) (AdresseC64>>8);
260 IO[4] = (unsigned char) AdresseREU;
261 IO[5] = (unsigned char) (AdresseREU>>8);
262 IO[6] = Bank;
263 IO[7] = (unsigned char) Counter;
264 IO[8] = (unsigned char) (Counter>>8);
265 }
266 if((IO[9] & 128) == 128) // Interrup ist zugelasssen ?
267 {
268 // Ja
269 if((IO[9] & 64) == 64) IO[0] |= 128;
270 }
271 }
272 break;
273 }
274 }
275 }
276 if((IO[0] & 128) == 128) CpuTriggerInterrupt(REU_IRQ);
277 else CpuClearInterrupt(REU_IRQ);
278 }
279
Read(unsigned short adresse)280 inline unsigned char REUClass::Read(unsigned short adresse)
281 {
282 unsigned char wert = ReadProcTbl[(adresse)>>8](adresse);
283 return wert;
284 }
285
Write(unsigned short adresse,unsigned char wert)286 inline void REUClass::Write(unsigned short adresse, unsigned char wert)
287 {
288 WriteProcTbl[(adresse)>>8](adresse,wert);
289 }
290
WriteIO1(unsigned short,unsigned char)291 void REUClass::WriteIO1(unsigned short /*adresse*/,unsigned char /*wert*/)
292 {
293 }
294
WriteIO2(unsigned short adresse,unsigned char wert)295 void REUClass::WriteIO2(unsigned short adresse,unsigned char wert)
296 {
297 if(!REUInsert) return;
298 switch(adresse)
299 {
300 case 0xdf00: // READ ONLY
301 break;
302 case 0xdf01:
303 IO[1] = wert;
304 Bank = IO[6];
305 AdresseC64 = IO[2] | (IO[3]<<8);
306 AdresseREU = IO[4] | (IO[5]<<8);
307 Counter = IO[7] | (IO[8]<<8);
308 TransferTyp = wert & 3;
309 if((wert & 128) == 128) // Befehl ausführen
310 {
311 if((IO[1] & 0x10) == 0x10)
312 {
313 BA_STATUS = false; // CPU anhalten
314 CPUWaitCounter = 3; // 3 Zyklen Warten bis CPU anhält
315 TransferStart = true;
316 switch(TransferTyp)
317 {
318 case 0:
319 DMAStatus = 2;
320 break;
321 case 1:
322 DMAStatus = 1;
323 break;
324 case 2:
325 DMAStatus = 3;
326 break;
327 case 3:
328 DMAStatus = 4;
329 break;
330 }
331 }
332 else
333 {
334 REUWait_FF00 = true;
335 }
336 }
337 break;
338 case 0xdf02:
339 IO[2] = wert;
340 break;
341 case 0xdf03:
342 IO[3] = wert;
343 break;
344 case 0xdf04:
345 IO[4] = wert;
346 break;
347 case 0xdf05:
348 IO[5] = wert;
349 break;
350 case 0xdf06:
351 IO[6] = wert;
352 break;
353 case 0xdf07:
354 IO[7] = wert;
355 break;
356 case 0xdf08:
357 IO[8] = wert;
358 break;
359 case 0xdf09:
360 IO[9] = wert;
361 break;
362 case 0xdf0a:
363 IO[10] = wert;
364 break;
365 default:
366 break;
367 }
368 }
369
ReadIO1(unsigned short)370 unsigned char REUClass::ReadIO1(unsigned short /*adresse*/)
371 {
372 return 0;
373 }
374
ReadIO2(unsigned short adresse)375 unsigned char REUClass::ReadIO2(unsigned short adresse)
376 {
377 static unsigned char ret;
378
379 if(!REUInsert) return 0x00; // Eigl. Zufallszahlen
380 switch(adresse)
381 {
382 case 0xdf00:
383 ret = IO[0];
384 IO[0] &= 31; // BIT 5/6/7 löschen
385 return ret;
386 break;
387 case 0xdf01:
388 return IO[1];
389 break;
390 case 0xdf02:
391 return IO[2];
392 break;
393 case 0xdf03:
394 return IO[3];
395 break;
396 case 0xdf04:
397 return IO[4];
398 break;
399 case 0xdf05:
400 return IO[5];
401 break;
402 case 0xdf06:
403 return IO[6];
404 break;
405 case 0xdf07:
406 return IO[7];
407 break;
408 case 0xdf08:
409 return IO[8];
410 break;
411 case 0xdf09:
412 return IO[9];
413 break;
414 case 0xdf0a:
415 return IO[10];
416 break;
417 default:
418 return 0; // Eigtl. Zufallszahlen
419 break;
420 }
421 }
422
Reset(void)423 inline void REUClass::Reset(void)
424 {
425 BA_STATUS = true;
426 TransferStart = false;
427 IO[0] = 16;
428 IO[1] = 16;
429 IO[2] = 0;
430 IO[3] = 0;
431 IO[4] = 0;
432 IO[5] = 0;
433 IO[6] = 0;
434 IO[7] = 255;
435 IO[8] = 255;
436 IO[9] = 31;
437 IO[10] = 63;
438 }
439
SaveFreez(FILE * File)440 bool REUClass::SaveFreez(FILE *File)
441 {
442 /// REU Inhalt speichern ...
443 for(int i=0;i<32;i++) fwrite(RamBaenke[i],1,0x10000,File);
444 return true;
445 }
446
LoadFreez(FILE * File,unsigned short Version)447 bool REUClass::LoadFreez(FILE *File,unsigned short Version)
448 {
449 size_t reading_bytes;
450
451 switch(Version)
452 {
453 case 0x0101:
454 /// REU Inhalt laden ...
455 for(int i=0;i<32;i++)
456 {
457 reading_bytes = fread(RamBaenke[i],1,0x10000,File);
458 if(reading_bytes < 0x10000){}
459 }
460 break;
461 }
462 return true;
463 }
464