5 // Created by Matt Parsons on 06/03/2019.
6 // Copyright © 2019 Matt Parsons. All rights reserved.
9 // Write Byte to Gayle Space 0xda9000 (0x0000c3)
10 // Read Byte From Gayle Space 0xda9000
11 // Read Byte From Gayle Space 0xdaa000
22 #include "config_file/config_file.h"
23 #include "platforms/amiga/amiga-registers.h"
25 //#define GSTATUS 0xda201c
26 //#define GCLOW 0xda2010
27 //#define GDH 0xda2018
32 #define GERROR 0xda2004 // Error
33 #define GSTATUS 0xda201c // Status
35 #define GFEAT 0xda2004 // Write : Feature
36 #define GCMD 0xda201c // Write : Command
38 #define GDATA 0xda2000 // Data
39 #define GSECTCNT 0xda2008 // SectorCount
40 #define GSECTNUM 0xda200c // SectorNumber
41 #define GCYLLOW 0xda2010 // CylinderLow
42 #define GCYLHIGH 0xda2014 // CylinderHigh
43 #define GDEVHEAD 0xda2018 // Device/Head
44 #define GCTRL 0xda3018 // Control
46 #define GIDENT 0xDE1000
49 #define GCS 0xDA8000 // Card Control
50 #define GIRQ 0xDA9000 // IRQ
51 #define GINT 0xDAA000 // Int enable
52 #define GCONF 0xDAB000 // Gayle Config
55 #define GAYLE_CS_IDE 0x80 /* IDE int status */
56 #define GAYLE_CS_CCDET 0x40 /* credit card detect */
57 #define GAYLE_CS_BVD1 0x20 /* battery voltage detect 1 */
58 #define GAYLE_CS_SC 0x20 /* credit card status change */
59 #define GAYLE_CS_BVD2 0x10 /* battery voltage detect 2 */
60 #define GAYLE_CS_DA 0x10 /* digital audio */
61 #define GAYLE_CS_WR 0x08 /* write enable (1 == enabled) */
62 #define GAYLE_CS_BSY 0x04 /* credit card busy */
63 #define GAYLE_CS_IRQ 0x04 /* interrupt request */
64 #define GAYLE_CS_DAEN 0x02 /* enable digital audio */
65 #define GAYLE_CS_DIS 0x01 /* disable PCMCIA slot */
68 #define GAYLE_IRQ_IDE 0x80
69 #define GAYLE_IRQ_CCDET 0x40 /* credit card detect */
70 #define GAYLE_IRQ_BVD1 0x20 /* battery voltage detect 1 */
71 #define GAYLE_IRQ_SC 0x20 /* credit card status change */
72 #define GAYLE_IRQ_BVD2 0x10 /* battery voltage detect 2 */
73 #define GAYLE_IRQ_DA 0x10 /* digital audio */
74 #define GAYLE_IRQ_WR 0x08 /* write enable (1 == enabled) */
75 #define GAYLE_IRQ_BSY 0x04 /* credit card busy */
76 #define GAYLE_IRQ_IRQ 0x04 /* interrupt request */
77 #define GAYLE_IRQ_RESET 0x02 /* reset machine after CCDET change */
78 #define GAYLE_IRQ_BERR 0x01 /* generate bus error after CCDET change */
81 #define GAYLE_INT_IDE 0x80 /* IDE interrupt enable */
82 #define GAYLE_INT_CCDET 0x40 /* credit card detect change enable */
83 #define GAYLE_INT_BVD1 0x20 /* battery voltage detect 1 change enable */
84 #define GAYLE_INT_SC 0x20 /* credit card status change enable */
85 #define GAYLE_INT_BVD2 0x10 /* battery voltage detect 2 change enable */
86 #define GAYLE_INT_DA 0x10 /* digital audio change enable */
87 #define GAYLE_INT_WR 0x08 /* write enable change enabled */
88 #define GAYLE_INT_BSY 0x04 /* credit card busy */
89 #define GAYLE_INT_IRQ 0x04 /* credit card interrupt request */
90 #define GAYLE_INT_BVD_LEV 0x02 /* BVD int level, 0=lev2,1=lev6 */
91 #define GAYLE_INT_BSY_LEV 0x01 /* BSY int level, 0=lev2,1=lev6 */
93 #define GAYLE_MAX_HARDFILES 8
96 static uint8_t gayle_irq, gayle_int, gayle_cs, gayle_cs_mask, gayle_cfg;
97 static struct ide_controller *ide0;
100 uint8_t rtc_type = RTC_TYPE_RICOH;
102 char *hdd_image_file[GAYLE_MAX_HARDFILES];
104 void set_hard_drive_image_file_amiga(uint8_t index, char *filename) {
105 if (hdd_image_file[index] != NULL)
106 free(hdd_image_file[index]);
107 hdd_image_file[index] = calloc(1, strlen(filename) + 1);
108 strcpy(hdd_image_file[index], filename);
111 void InitGayle(void) {
112 if (!hdd_image_file[0]) {
113 hdd_image_file[0] = calloc(1, 64);
114 sprintf(hdd_image_file[0], "hd0.img");
117 ide0 = ide_allocate("cf");
118 fd = open(hdd_image_file[0], O_RDWR);
120 printf("HDD Image %s failed open\n", hdd_image_file[0]);
122 ide_attach(ide0, 0, fd);
123 ide_reset_begin(ide0);
124 printf("HDD Image %s attached\n", hdd_image_file[0]);
128 uint8_t CheckIrq(void) {
131 if (gayle_int & (1 << 7)) {
132 irq = ide0->drive->intrq;
134 // printf("IDE IRQ: %x\n",irq);
140 void writeGayleB(unsigned int address, unsigned int value) {
141 if (address == GFEAT) {
142 ide_write8(ide0, ide_feature_w, value);
145 if (address == GCMD) {
146 ide_write8(ide0, ide_command_w, value);
149 if (address == GSECTCNT) {
150 ide_write8(ide0, ide_sec_count, value);
153 if (address == GSECTNUM) {
154 ide_write8(ide0, ide_sec_num, value);
157 if (address == GCYLLOW) {
158 ide_write8(ide0, ide_cyl_low, value);
161 if (address == GCYLHIGH) {
162 ide_write8(ide0, ide_cyl_hi, value);
165 if (address == GDEVHEAD) {
166 ide_write8(ide0, ide_dev_head, value);
169 if (address == GCTRL) {
170 ide_write8(ide0, ide_devctrl_w, value);
174 if (address == GIDENT) {
176 // printf("Write Byte to Gayle Ident 0x%06x (0x%06x)\n",address,value);
180 if (address == GIRQ) {
181 // printf("Write Byte to Gayle GIRQ 0x%06x (0x%06x)\n",address,value);
182 gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
187 if (address == GCS) {
188 printf("Write Byte to Gayle GCS 0x%06x (0x%06x)\n", address, value);
189 gayle_cs_mask = value & ~3;
191 gayle_cs |= value & 3;
195 if (address == GINT) {
196 printf("Write Byte to Gayle GINT 0x%06x (0x%06x)\n", address, value);
201 if (address == GCONF) {
202 printf("Write Byte to Gayle GCONF 0x%06x (0x%06x)\n", address, value);
207 if ((address & GAYLEMASK) == CLOCKBASE) {
208 if ((address & CLOCKMASK) >= 0x8000) {
209 printf("Byte write to CDTV SRAM?\n");
212 put_rtc_byte(address, value, rtc_type);
216 printf("Write Byte to Gayle Space 0x%06x (0x%06x)\n", address, value);
219 void writeGayle(unsigned int address, unsigned int value) {
220 if (address == GDATA) {
221 ide_write16(ide0, ide_data, value);
225 if ((address & GAYLEMASK) == CLOCKBASE) {
226 if ((address & CLOCKMASK) >= 0x8000) {
227 printf("Word write to CDTV SRAM?\n");
230 printf("Word write to RTC.\n");
231 put_rtc_byte(address, (value & 0xFF), rtc_type);
232 put_rtc_byte(address + 1, (value >> 8), rtc_type);
236 printf("Write Word to Gayle Space 0x%06x (0x%06x)\n", address, value);
239 void writeGayleL(unsigned int address, unsigned int value) {
240 if ((address & GAYLEMASK) == CLOCKBASE) {
241 if ((address & CLOCKMASK) >= 0x8000) {
242 printf("Longword write to CDTV SRAM?\n");
245 printf("Longword write to RTC.\n");
246 put_rtc_byte(address, (value & 0xFF), rtc_type);
247 put_rtc_byte(address + 1, ((value & 0x0000FF00) >> 8), rtc_type);
248 put_rtc_byte(address + 2, ((value & 0x00FF0000) >> 16), rtc_type);
249 put_rtc_byte(address + 3, (value >> 24), rtc_type);
253 printf("Write Long to Gayle Space 0x%06x (0x%06x)\n", address, value);
256 static unsigned char rtc_mystery_reg[3];
258 void put_rtc_byte(uint32_t address_, uint8_t value, uint8_t rtc_type) {
259 uint32_t address = address_ & 0x3F;
261 if (rtc_type == RTC_TYPE_MSM) {
264 rtc_mystery_reg[address - 0x0D] = value & (0x01 | 0x08);
268 rtc_mystery_reg[address - 0x0D] = value;
275 int rtc_bank = (rtc_mystery_reg[0] & 0x03);
276 if ((rtc_bank & 0x02) && address < 0x0D) {
277 // RTC memory access?
278 printf("Write to Ricoh RTC memory.\n");
281 else if ((rtc_bank & 0x01) && address < 0x0D) {
283 printf("Write to Ricoh RTC alarm.\n");
286 else if (address >= 0x0D) {
287 rtc_mystery_reg[address - 0x0D] = value;
293 uint8_t get_rtc_byte(uint32_t address_, uint8_t rtc_type) {
294 uint32_t address = address_;
298 struct tm *rtc_time = localtime(&t);
300 if (rtc_type == RTC_TYPE_RICOH) {
301 int rtc_bank = (rtc_mystery_reg[0] & 0x03);
302 if ((rtc_bank & 0x02) && address < 0x0D) {
303 // RTC memory access?
304 printf("Read from Ricoh RTC memory.\n");
307 else if ((rtc_bank & 0x01) && address < 0x0D) {
309 printf("Read from Ricoh RTC alarm.\n");
315 case 0x00: // Seconds low?
316 return rtc_time->tm_sec % 10;
317 case 0x01: // Seconds high?
318 return rtc_time->tm_sec / 10;
319 case 0x02: // Minutes low?
320 return rtc_time->tm_min % 10;
321 case 0x03: // Minutes high?
322 return rtc_time->tm_min / 10;
323 case 0x04: // Hours low?
324 return rtc_time->tm_hour % 10;
325 case 0x05: // Hours high?
326 if (rtc_type == RTC_TYPE_MSM) {
327 if (rtc_mystery_reg[2] & 4) {
328 return ((rtc_time->tm_hour / 10) | (rtc_time->tm_hour > 12) ? 0x04 : 0x00);
331 return rtc_time->tm_hour / 10;
336 case 0x06: // Day low?
337 if (rtc_type == RTC_TYPE_MSM)
338 return rtc_time->tm_mday % 10;
340 return rtc_time->tm_wday;
341 case 0x07: // Day high?
342 if (rtc_type == RTC_TYPE_MSM)
343 return rtc_time->tm_mday / 10;
345 return rtc_time->tm_mday % 10;
346 case 0x08: // Month low?
347 if (rtc_type == RTC_TYPE_MSM)
348 return (rtc_time->tm_mon + 1) % 10;
350 return rtc_time->tm_mday / 10;
351 case 0x09: // Month high?
352 if (rtc_type == RTC_TYPE_MSM)
353 return (rtc_time->tm_mon + 1) / 10;
355 return (rtc_time->tm_mon + 1) % 10;
356 case 0x0A: // Year low?
357 if (rtc_type == RTC_TYPE_MSM)
358 return rtc_time->tm_year % 10;
360 return (rtc_time->tm_mon + 1) / 10;
361 case 0x0B: // Year high?
362 if (rtc_type == RTC_TYPE_MSM)
363 return rtc_time->tm_year / 10;
365 return rtc_time->tm_year % 10;
366 case 0x0C: // Day of week?
367 if (rtc_type == RTC_TYPE_MSM)
368 return rtc_time->tm_wday;
370 return rtc_time->tm_year / 10;
371 case 0x0D: // Mystery register D-F?
372 return rtc_mystery_reg[address - 0x0D];
383 uint8_t readGayleB(unsigned int address) {
384 if (address == GERROR) {
385 return ide_read8(ide0, ide_error_r);
387 if (address == GSTATUS) {
388 return ide_read8(ide0, ide_status_r);
391 if (address == GSECTCNT) {
392 return ide_read8(ide0, ide_sec_count);
395 if (address == GSECTNUM) {
396 return ide_read8(ide0, ide_sec_num);
399 if (address == GCYLLOW) {
400 return ide_read8(ide0, ide_cyl_low);
403 if (address == GCYLHIGH) {
404 return ide_read8(ide0, ide_cyl_hi);
407 if (address == GDEVHEAD) {
408 return ide_read8(ide0, ide_dev_head);
411 if (address == GCTRL) {
412 return ide_read8(ide0, ide_altst_r);
415 if ((address & GAYLEMASK) == CLOCKBASE) {
416 if ((address & CLOCKMASK) >= 0x8000) {
417 printf("Byte read from CDTV SRAM?\n");
420 return get_rtc_byte((address & 0x3F), rtc_type);
423 if (address == GIDENT) {
425 // printf("Read Byte from Gayle Ident 0x%06x (0x%06x)\n",address,counter);
426 if (counter == 0 || counter == 1 || counter == 3) {
427 val = 0x80; // 80; to enable gayle
435 if (address == GIRQ) {
436 // printf("Read Byte From GIRQ Space 0x%06x\n",gayle_irq);
438 return 0x80;//gayle_irq;
441 irq = ide0->drive->intrq;
444 // printf("IDE IRQ: %x\n",irq);
445 return 0x80; // gayle_irq;
452 if (address == GCS) {
453 printf("Read Byte From GCS Space 0x%06x\n", 0x1234);
455 v = gayle_cs_mask | gayle_cs;
459 if (address == GINT) {
460 // printf("Read Byte From GINT Space 0x%06x\n",gayle_int);
464 if (address == GCONF) {
465 printf("Read Byte From GCONF Space 0x%06x\n", gayle_cfg & 0x0f);
466 return gayle_cfg & 0x0f;
469 printf("Read Byte From Gayle Space 0x%06x\n", address);
473 uint16_t readGayle(unsigned int address) {
474 if (address == GDATA) {
476 value = ide_read16(ide0, ide_data);
477 // value = (value << 8) | (value >> 8);
481 if ((address & GAYLEMASK) == CLOCKBASE) {
482 if ((address & CLOCKMASK) >= 0x8000) {
483 printf("Word read from CDTV SRAM?\n");
486 return ((get_rtc_byte((address & 0x3F), rtc_type) << 8) | (get_rtc_byte(((address + 1) & 0x3F), rtc_type)));
489 printf("Read Word From Gayle Space 0x%06x\n", address);
493 uint32_t readGayleL(unsigned int address) {
494 if ((address & GAYLEMASK) == CLOCKBASE) {
495 if ((address & CLOCKMASK) >= 0x8000) {
496 printf("Longword read from CDTV SRAM?\n");
499 return ((get_rtc_byte((address & 0x3F), rtc_type) << 24) | (get_rtc_byte(((address + 1) & 0x3F), rtc_type) << 16) | (get_rtc_byte(((address + 2) & 0x3F), rtc_type) << 8) | (get_rtc_byte(((address + 3) & 0x3F), rtc_type)));
502 printf("Read Long From Gayle Space 0x%06x\n", address);