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