platforms/amiga/Gayle.c \
platforms/amiga/gayle-ide/ide.c \
platforms/amiga/rtg/rtg.c \
+ platforms/amiga/rtg/rtg-output.c \
platforms/shared/rtc.c
MUSASHIFILES = m68kcpu.c softfloat/softfloat.c
CC = gcc
WARNINGS = -Wall -Wextra -pedantic
CFLAGS = $(WARNINGS) -march=armv7 -O3
-LFLAGS = $(WARNINGS)
+LFLAGS = $(WARNINGS) -lSDL2
TARGET = $(EXENAME)$(EXE)
#include <sys/types.h>
#include <unistd.h>
#include <sys/ioctl.h>
+#include <SDL2/SDL.h>
#include "m68k.h"
#include "main.h"
#include "platforms/platforms.h"
}
}
+ // Initialize SDL.
+ printf("Initializing SDL2...\n");
+ if (SDL_Init(0) < 0) {
+ printf("Failed to initialize SDL2.\n");
+ }
+ else {
+ printf("Initializing SDL2 Video...\n");
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ printf("Failed to initialize SDL2 Video. Trying again.\n");
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ printf("Failed to initialize SDL2 Video again. Dying.\n");
+ }
+ }
+ printf("Initialized SDL2 Video.\n");
+ }
+
keyboard_fd = open(keyboard_file, O_RDONLY | O_NONBLOCK);
if (keyboard_fd == -1) {
printf("Failed to open keyboard event source.\n");
//#define GCLOW 0xda2010
//#define GDH 0xda2018
-// Gayle Addresses
-
-// Gayle IDE Reads
-#define GERROR 0xda2004 // Error
-#define GSTATUS 0xda201c // Status
-// Gayle IDE Writes
-#define GFEAT 0xda2004 // Write : Feature
-#define GCMD 0xda201c // Write : Command
-// Gayle IDE RW
-#define GDATA 0xda2000 // Data
-#define GSECTCNT 0xda2008 // SectorCount
-#define GSECTNUM 0xda200c // SectorNumber
-#define GCYLLOW 0xda2010 // CylinderLow
-#define GCYLHIGH 0xda2014 // CylinderHigh
-#define GDEVHEAD 0xda2018 // Device/Head
-#define GCTRL 0xda3018 // Control
-// Gayle Ident
-#define GIDENT 0xDE1000
-
-// Gayle IRQ/CC
-#define GCS 0xDA8000 // Card Control
-#define GIRQ 0xDA9000 // IRQ
-#define GINT 0xDAA000 // Int enable
-#define GCONF 0xDAB000 // Gayle Config
-
-/* DA8000 */
-#define GAYLE_CS_IDE 0x80 /* IDE int status */
-#define GAYLE_CS_CCDET 0x40 /* credit card detect */
-#define GAYLE_CS_BVD1 0x20 /* battery voltage detect 1 */
-#define GAYLE_CS_SC 0x20 /* credit card status change */
-#define GAYLE_CS_BVD2 0x10 /* battery voltage detect 2 */
-#define GAYLE_CS_DA 0x10 /* digital audio */
-#define GAYLE_CS_WR 0x08 /* write enable (1 == enabled) */
-#define GAYLE_CS_BSY 0x04 /* credit card busy */
-#define GAYLE_CS_IRQ 0x04 /* interrupt request */
-#define GAYLE_CS_DAEN 0x02 /* enable digital audio */
-#define GAYLE_CS_DIS 0x01 /* disable PCMCIA slot */
-
-/* DA9000 */
-#define GAYLE_IRQ_IDE 0x80
-#define GAYLE_IRQ_CCDET 0x40 /* credit card detect */
-#define GAYLE_IRQ_BVD1 0x20 /* battery voltage detect 1 */
-#define GAYLE_IRQ_SC 0x20 /* credit card status change */
-#define GAYLE_IRQ_BVD2 0x10 /* battery voltage detect 2 */
-#define GAYLE_IRQ_DA 0x10 /* digital audio */
-#define GAYLE_IRQ_WR 0x08 /* write enable (1 == enabled) */
-#define GAYLE_IRQ_BSY 0x04 /* credit card busy */
-#define GAYLE_IRQ_IRQ 0x04 /* interrupt request */
-#define GAYLE_IRQ_RESET 0x02 /* reset machine after CCDET change */
-#define GAYLE_IRQ_BERR 0x01 /* generate bus error after CCDET change */
-
-/* DAA000 */
-#define GAYLE_INT_IDE 0x80 /* IDE interrupt enable */
-#define GAYLE_INT_CCDET 0x40 /* credit card detect change enable */
-#define GAYLE_INT_BVD1 0x20 /* battery voltage detect 1 change enable */
-#define GAYLE_INT_SC 0x20 /* credit card status change enable */
-#define GAYLE_INT_BVD2 0x10 /* battery voltage detect 2 change enable */
-#define GAYLE_INT_DA 0x10 /* digital audio change enable */
-#define GAYLE_INT_WR 0x08 /* write enable change enabled */
-#define GAYLE_INT_BSY 0x04 /* credit card busy */
-#define GAYLE_INT_IRQ 0x04 /* credit card interrupt request */
-#define GAYLE_INT_BVD_LEV 0x02 /* BVD int level, 0=lev2,1=lev6 */
-#define GAYLE_INT_BSY_LEV 0x01 /* BSY int level, 0=lev2,1=lev6 */
+uint8_t gary_cfg[8];
+
+uint8_t gayle_a4k = 0xA0;
+uint16_t gayle_a4k_irq;
+uint8_t ramsey_cfg = 0x08;
+static uint8_t ramsey_id = RAMSEY_REV7;
int counter;
static uint8_t gayle_irq, gayle_cs, gayle_cs_mask, gayle_cfg;
uint8_t gayle_int;
+uint32_t gayle_ide_mask = ~GDATA;
+uint32_t gayle_ide_base = GDATA;
+uint8_t gayle_ide_adj = 0;
+
struct ide_controller *get_ide(int index) {
//if (index) {}
return ide0;
}
+void adjust_gayle_4000() {
+ gayle_ide_base = GDATA_A4000;
+ gayle_ide_adj = 2;
+}
+
+void adjust_gayle_1200() {
+
+}
+
void set_hard_drive_image_file_amiga(uint8_t index, char *filename) {
if (hdd_image_file[index] != NULL)
free(hdd_image_file[index]);
return 0;
}
-void writeGayleB(unsigned int address, unsigned int value) {
- if (address == GFEAT) {
- ide_write8(ide0, ide_feature_w, value);
- return;
- }
- if (address == GCMD) {
- ide_write8(ide0, ide_command_w, value);
- return;
- }
- if (address == GSECTCNT) {
- ide_write8(ide0, ide_sec_count, value);
- return;
- }
- if (address == GSECTNUM) {
- ide_write8(ide0, ide_sec_num, value);
- return;
- }
- if (address == GCYLLOW) {
- ide_write8(ide0, ide_cyl_low, value);
- return;
- }
- if (address == GCYLHIGH) {
- ide_write8(ide0, ide_cyl_hi, value);
- return;
- }
- if (address == GDEVHEAD) {
- ide_write8(ide0, ide_dev_head, value);
- return;
- }
- if (address == GCTRL) {
- ide_write8(ide0, ide_devctrl_w, value);
- return;
- }
-
- if (address == GIDENT) {
- counter = 0;
- // printf("Write Byte to Gayle Ident 0x%06x (0x%06x)\n",address,value);
- return;
- }
-
- if (address == GIRQ) {
- // printf("Write Byte to Gayle GIRQ 0x%06x (0x%06x)\n",address,value);
- gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
-
- return;
- }
+static uint8_t ide_action = 0;
- if (address == GCS) {
- printf("Write Byte to Gayle GCS 0x%06x (0x%06x)\n", address, value);
- gayle_cs_mask = value & ~3;
- gayle_cs &= ~3;
- gayle_cs |= value & 3;
- return;
- }
-
- if (address == GINT) {
- printf("Write Byte to Gayle GINT 0x%06x (0x%06x)\n", address, value);
- gayle_int = value;
+void writeGayleB(unsigned int address, unsigned int value) {
+ if (address >= gayle_ide_base) {
+ switch (address - gayle_ide_base + gayle_ide_adj) {
+ case GFEAT_OFFSET:
+ ide_action = ide_feature_w;
+ goto idewrite8;
+ case GCMD_OFFSET:
+ ide_action = ide_command_w;
+ goto idewrite8;
+ case GSECTCOUNT_OFFSET:
+ ide_action = ide_sec_count;
+ goto idewrite8;
+ case GSECTNUM_OFFSET:
+ ide_action = ide_sec_num;
+ goto idewrite8;
+ case GCYLLOW_OFFSET:
+ ide_action = ide_cyl_low;
+ goto idewrite8;
+ case GCYLHIGH_OFFSET:
+ ide_action = ide_cyl_hi;
+ goto idewrite8;
+ case GDEVHEAD_OFFSET:
+ ide_action = ide_dev_head;
+ goto idewrite8;
+ case GCTRL_OFFSET:
+ ide_action = ide_devctrl_w;
+ goto idewrite8;
+ case GIRQ_4000_OFFSET:
+ gayle_a4k_irq = value;
+ case GIRQ_OFFSET:
+ gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
+ return;
+ }
+ goto skip_idewrite8;
+idewrite8:;
+ ide_write8(ide0, ide_action, value);
return;
+skip_idewrite8:;
}
- if (address == GCONF) {
- printf("Write Byte to Gayle GCONF 0x%06x (0x%06x)\n", address, value);
- gayle_cfg = value;
- return;
+ switch (address) {
+ case 0xDD203A:
+ gayle_a4k = value;
+ return;
+ case GIDENT:
+ counter = 0;
+ return;
+ case GCONF:
+ gayle_cfg = value;
+ return;
+ case RAMSEY_REG:
+ ramsey_cfg = value & 0x0F;
+ return;
+ case GINT:
+ gayle_int = value;
+ return;
+ case GCS:
+ gayle_cs_mask = value & ~3;
+ gayle_cs &= ~3;
+ gayle_cs |= value & 3;
+ return;
}
if ((address & GAYLEMASK) == CLOCKBASE) {
}
void writeGayle(unsigned int address, unsigned int value) {
- if (address == GDATA) {
+ if (address - gayle_ide_base == GDATA_OFFSET) {
ide_write16(ide0, ide_data, value);
return;
}
+ if (address == GIRQ_A4000) {
+ gayle_a4k_irq = value;
+ return;
+ }
+
if ((address & GAYLEMASK) == CLOCKBASE) {
if ((address & CLOCKMASK) >= 0x8000) {
if (cdtv_mode) {
}
uint8_t readGayleB(unsigned int address) {
- if (address == GERROR) {
- return ide_read8(ide0, ide_error_r);
- }
- if (address == GSTATUS) {
- return ide_read8(ide0, ide_status_r);
- }
-
- if (address == GSECTCNT) {
- return ide_read8(ide0, ide_sec_count);
- }
-
- if (address == GSECTNUM) {
- return ide_read8(ide0, ide_sec_num);
- }
-
- if (address == GCYLLOW) {
- return ide_read8(ide0, ide_cyl_low);
- }
-
- if (address == GCYLHIGH) {
- return ide_read8(ide0, ide_cyl_hi);
- }
-
- if (address == GDEVHEAD) {
- return ide_read8(ide0, ide_dev_head);
- }
-
- if (address == GCTRL) {
- return ide_read8(ide0, ide_altst_r);
+ uint8_t ide_action = 0;
+
+ if (address >= gayle_ide_base + gayle_ide_adj) {
+ switch (address - gayle_ide_base) {
+ case GERROR_OFFSET:
+ ide_action = ide_error_r;
+ goto ideread8;
+ case GSTATUS_OFFSET:
+ ide_action = ide_status_r;
+ goto ideread8;
+ case GSECTCOUNT_OFFSET:
+ ide_action = ide_sec_count;
+ goto ideread8;
+ case GSECTNUM_OFFSET:
+ ide_action = ide_sec_num;
+ goto ideread8;
+ case GCYLLOW_OFFSET:
+ ide_action = ide_cyl_low;
+ goto ideread8;
+ case GCYLHIGH_OFFSET:
+ ide_action = ide_cyl_hi;
+ goto ideread8;
+ case GDEVHEAD_OFFSET:
+ ide_action = ide_dev_head;
+ goto ideread8;
+ case GCTRL_OFFSET:
+ ide_action = ide_altst_r;
+ goto ideread8;
+ case GIRQ_4000_OFFSET:
+ case GIRQ_OFFSET:
+ return 0x80;
+ //gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR));
+ }
+ goto skip_ideread8;
+ideread8:;
+ return ide_read8(ide0, ide_action);
+skip_ideread8:;
+ }
+
+ switch (address) {
+ case GIDENT: {
+ uint8_t val;
+ // printf("Read Byte from Gayle Ident 0x%06x (0x%06x)\n",address,counter);
+ if (counter == 0 || counter == 1 || counter == 3) {
+ val = 0x80; // 80; to enable gayle
+ } else {
+ val = 0x00;
+ }
+ counter++;
+ return val;
+ }
+ case GINT:
+ return gayle_int;
+ case GCONF:
+ return gayle_cfg & 0x0f;
+ case GCS: {
+ uint8_t v;
+ v = gayle_cs_mask | gayle_cs;
+ return v;
+ }
+ // This seems incorrect, GARY_REG3 is the same as GIDENT, and the A4000
+ // service manual says that Gary is accessible in the address range $DFC000 to $DFFFFF.
+ case GARY_REG0:
+ case GARY_REG1:
+ case GARY_REG2:
+ return gary_cfg[address - GARY_REG0];
+ break;
+ //case GARY_REG3:
+ case GARY_REG4:
+ //case GARY_REG5:
+ return gary_cfg[address - GARY_REG3];
+ case RAMSEY_ID:
+ return ramsey_id;
+ case RAMSEY_REG:
+ return ramsey_cfg;
+ case GARY_REG5: { // This makes no sense.
+ uint8_t val;
+ printf("Read Byte from GARY Ident 0x%06x (0x%06x)\n",address,counter);
+ if (counter == 0 || counter == 1 || counter == 3) {
+ val = 0x80; // 80; to enable GARY
+ } else {
+ val = 0x00;
+ }
+ counter++;
+ return val;
+ }
+ case 0xDD203A:
+ return gayle_a4k;
}
if ((address & GAYLEMASK) == CLOCKBASE) {
return get_rtc_byte(address, rtc_type);
}
- if (address == GIDENT) {
- uint8_t val;
- // printf("Read Byte from Gayle Ident 0x%06x (0x%06x)\n",address,counter);
- if (counter == 0 || counter == 1 || counter == 3) {
- val = 0x80; // 80; to enable gayle
- } else {
- val = 0x00;
- }
- counter++;
- return val;
- }
-
- if (address == GIRQ) {
- // printf("Read Byte From GIRQ Space 0x%06x\n",gayle_irq);
-
- return 0x80;//gayle_irq;
-/*
- uint8_t irq;
- irq = ide0->drive->intrq;
-
- if (irq == 1) {
- // printf("IDE IRQ: %x\n",irq);
- return 0x80; // gayle_irq;
- }
-
- return 0;
-*/
- }
-
- if (address == GCS) {
- printf("Read Byte From GCS Space 0x%06x\n", 0x1234);
- uint8_t v;
- v = gayle_cs_mask | gayle_cs;
- return v;
- }
-
- if (address == GINT) {
- // printf("Read Byte From GINT Space 0x%06x\n",gayle_int);
- return gayle_int;
- }
-
- if (address == GCONF) {
- printf("Read Byte From GCONF Space 0x%06x\n", gayle_cfg & 0x0f);
- return gayle_cfg & 0x0f;
- }
-
printf("Read Byte From Gayle Space 0x%06x\n", address);
return 0xFF;
}
uint16_t readGayle(unsigned int address) {
- if (address == GDATA) {
+ if (address - gayle_ide_base == GDATA_OFFSET) {
uint16_t value;
value = ide_read16(ide0, ide_data);
// value = (value << 8) | (value >> 8);
return value;
}
+ if (address == GIRQ_A4000) {
+ gayle_a4k_irq = 0x8000;
+ return 0x80FF;
+ }
+
if ((address & GAYLEMASK) == CLOCKBASE) {
if ((address & CLOCKMASK) >= 0x8000) {
if (cdtv_mode) {
uint32_t readGayleL(unsigned int address);
struct ide_controller *get_ide(int index);
+
+// Gayle Addresses
+#define GAYLE_IDE_BASE_A1200 0xDA2000 //16bit base
+#define GAYLE_IDE_BASE_A4000 0xDD2020
+
+// Gayle IDE Reads
+#define GERROR 0xda2004 // Error
+#define GSTATUS 0xda201C // Status
+#define GERROR_A4000 GAYLE_IDE_BASE_A4000 + 0x06 // Error
+#define GSTATUS_A4000 GAYLE_IDE_BASE_A4000 + 0x1E // Status
+
+// Gayle IDE read offsets
+#define GERROR_OFFSET 0x04
+#define GSTATUS_OFFSET 0x1C
+// Gayle IDE write offsets
+#define GFEAT_OFFSET 0x04
+#define GCMD_OFFSET 0x1C
+// Gayle IDE RW offsets
+#define GDATA_OFFSET 0x00
+#define GSECTCOUNT_OFFSET 0x08
+#define GSECTNUM_OFFSET 0x0C
+#define GCYLLOW_OFFSET 0x10
+#define GCYLHIGH_OFFSET 0x14
+#define GDEVHEAD_OFFSET 0x18
+#define GCTRL_OFFSET 0x1018
+#define GIRQ_OFFSET 0x7000
+#define GIRQ_4000_OFFSET 0x0FFE
+
+// Gayle IDE Writes
+#define GFEAT 0xda2004 // Write : Feature
+#define GCMD 0xda201c // Write : Command
+#define GFEAT_A4000 GAYLE_IDE_BASE_A4000 + 0x06 // Write : Feature
+#define GCMD_A4000 GAYLE_IDE_BASE_A4000 + 0x1E // Write : Command
+#define GMODEREG0_A4000 0x0DD1020 // D31, PIO modes (00,01,10)
+#define GMODEREG1_A4000 0x0DD1022 // D31, (MSB)
+
+// Gayle IDE RW
+#define GDATA 0xda2000 // Data - 16 bit
+#define GSECTCNT 0xda2008 // SectorCount
+#define GSECTNUM 0xda200c // SectorNumber
+#define GCYLLOW 0xda2010 // CylinderLow
+#define GCYLHIGH 0xda2014 // CylinderHigh
+#define GDEVHEAD 0xda2018 // Device/Head
+#define GCTRL 0xda3018 // Control
+
+#define GDATA_A4000 GAYLE_IDE_BASE_A4000 // Data
+#define GSECTCNT_A4000 GAYLE_IDE_BASE_A4000 + 0x0a // SectorCount
+#define GSECTNUM_A4000 GAYLE_IDE_BASE_A4000 + 0x0e // SectorNumber
+#define GCYLLOW_A4000 GAYLE_IDE_BASE_A4000 + 0x12 // CylinderLow
+#define GCYLHIGH_A4000 GAYLE_IDE_BASE_A4000 + 0x16 // CylinderHigh
+#define GDEVHEAD_A4000 GAYLE_IDE_BASE_A4000 + 0x1a // Device/Head
+#define GCTRL_A4000 GAYLE_IDE_BASE_A4000 + 0x101a // Control
+
+// For A4000 there's no need to populate other areas, just GIRQ
+#define GIRQ_A4000 GAYLE_IDE_BASE_A4000 + 0x1000 // IRQ 0xDD3020
+
+// Gayle Ident
+#define GIDENT 0xDE1000
+
+// Gayle IRQ/CC
+#define GCS 0xDA8000 // Card Control
+#define GIRQ 0xDA9000 // IRQ
+#define GINT 0xDAA000 // Int enable
+#define GCONF 0xDAB000 // Gayle Config
+
+/* DA8000 */
+#define GAYLE_CS_IDE 0x80 /* IDE int status */
+#define GAYLE_CS_CCDET 0x40 /* credit card detect */
+#define GAYLE_CS_BVD1 0x20 /* battery voltage detect 1 */
+#define GAYLE_CS_SC 0x20 /* credit card status change */
+#define GAYLE_CS_BVD2 0x10 /* battery voltage detect 2 */
+#define GAYLE_CS_DA 0x10 /* digital audio */
+#define GAYLE_CS_WR 0x08 /* write enable (1 == enabled) */
+#define GAYLE_CS_BSY 0x04 /* credit card busy */
+#define GAYLE_CS_IRQ 0x04 /* interrupt request */
+#define GAYLE_CS_DAEN 0x02 /* enable digital audio */
+#define GAYLE_CS_DIS 0x01 /* disable PCMCIA slot */
+
+/* DA9000 */
+#define GAYLE_IRQ_IDE 0x80
+#define GAYLE_IRQ_CCDET 0x40 /* credit card detect */
+#define GAYLE_IRQ_BVD1 0x20 /* battery voltage detect 1 */
+#define GAYLE_IRQ_SC 0x20 /* credit card status change */
+#define GAYLE_IRQ_BVD2 0x10 /* battery voltage detect 2 */
+#define GAYLE_IRQ_DA 0x10 /* digital audio */
+#define GAYLE_IRQ_WR 0x08 /* write enable (1 == enabled) */
+#define GAYLE_IRQ_BSY 0x04 /* credit card busy */
+#define GAYLE_IRQ_IRQ 0x04 /* interrupt request */
+#define GAYLE_IRQ_RESET 0x02 /* reset machine after CCDET change */
+#define GAYLE_IRQ_BERR 0x01 /* generate bus error after CCDET change */
+
+/* DAA000 */
+#define GAYLE_INT_IDE 0x80 /* IDE interrupt enable */
+#define GAYLE_INT_CCDET 0x40 /* credit card detect change enable */
+#define GAYLE_INT_BVD1 0x20 /* battery voltage detect 1 change enable */
+#define GAYLE_INT_SC 0x20 /* credit card status change enable */
+#define GAYLE_INT_BVD2 0x10 /* battery voltage detect 2 change enable */
+#define GAYLE_INT_DA 0x10 /* digital audio change enable */
+#define GAYLE_INT_WR 0x08 /* write enable change enabled */
+#define GAYLE_INT_BSY 0x04 /* credit card busy */
+#define GAYLE_INT_IRQ 0x04 /* credit card interrupt request */
+#define GAYLE_INT_BVD_LEV 0x02 /* BVD int level, 0=lev2,1=lev6 */
+#define GAYLE_INT_BSY_LEV 0x01 /* BSY int level, 0=lev2,1=lev6 */
+
#endif /* Gayle_h */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include "../platforms.h"
#include "amiga-autoconf.h"
#include "amiga-registers.h"
int handle_register_read_amiga(unsigned int addr, unsigned char type, unsigned int *val);
int handle_register_write_amiga(unsigned int addr, unsigned int value, unsigned char type);
+int init_rtg_data();
extern int ac_z2_done;
extern int ac_z2_pic_count;
int setup_platform_amiga(struct emulator_config *cfg) {
printf("Performing setup for Amiga platform.\n");
+
+ if (strlen(cfg->platform->subsys)) {
+ printf("Subsystem is [%s]\n", cfg->platform->subsys);
+ if (strcmp(cfg->platform->subsys, "4000") == 0 || strcmp(cfg->platform->subsys, "3000") == 0) {
+ printf("Adjusting Gayle accesses for A3000/4000 Kickstart.\n");
+ adjust_gayle_4000();
+ }
+ else if (strcmp(cfg->platform->subsys, "1200") == 0 || strcmp(cfg->platform->subsys, "cd32") == 0) {
+ printf("Adjusting Gayle accesses for A1200/CD32 Kickstart.\n");
+ adjust_gayle_1200();
+ }
+ else if (strcmp(cfg->platform->subsys, "cdtv") == 0) {
+ printf("Configuring platform for CDTV emulation.\n");
+ cdtv_mode = 1;
+ rtc_type = RTC_TYPE_MSM;
+ }
+ }
+ else
+ printf("No sub system specified.\n");
+
// Look for Z2 autoconf Fast RAM by id
int index = get_named_mapped_item(cfg, z2_autoconf_id);
more_z2_fast:;
cdtv_mode = 1;
}
if (strcmp(var, "rtg") == 0) {
- printf("[AMIGA] RTG Enabled.\n");
- rtg_enabled = 1;
- adjust_ranges_amiga(cfg);
+ if (init_rtg_data()) {
+ printf("[AMIGA] RTG Enabled.\n");
+ rtg_enabled = 1;
+ adjust_ranges_amiga(cfg);
+ }
+ else
+ printf("[AMIGA} Failed to enable RTG.\n");
}
if (strcmp(var, "rtc_type") == 0) {
if (val && strlen(val) != 0) {
if (subsys) {
cfg->subsys = malloc(strlen(subsys) + 1);
strcpy(cfg->subsys, subsys);
+ for (int i = 0; i < strlen(cfg->subsys); i++) {
+ cfg->subsys[i] = tolower(cfg->subsys[i]);
+ }
}
}
int custom_read_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int *val, unsigned char type);
int custom_write_amiga(struct emulator_config *cfg, unsigned int addr, unsigned int val, unsigned char type);
+void adjust_gayle_4000();
+void adjust_gayle_1200();
+
#define GAYLEBASE 0xD80000
#define GAYLESIZE 0x070000
#define GAYLEMASK 0xDF0000
#define CLOCKBASE 0xDC0000
#define CLOCKSIZE 0x010000
#define CLOCKMASK 0x00FFFF
+
+/* GARY ADDRESSES */
+#define GARY_REG0 0xDE0000
+#define GARY_REG1 0xDE0001
+#define GARY_REG2 0xDE0002
+#define GARY_REG3 0xDE1000
+#define GARY_REG4 0xDE1001
+#define GARY_REG5 0xDE1002
+
+/* RAMSEY ADDRESSES */
+#define RAMSEY_REG 0xDE0003 /* just a nibble, it should return 0x08 for defaults with 16MB */
+#define RAMSEY_ID 0xDE0043 /* Either 0x0D or 0x0F (most recent version) */
+/* RAMSEY TYPES */
+#define RAMSEY_REV4 0x0D
+#define RAMSEY_REV7 0x0F
\ No newline at end of file
--- /dev/null
+#include <SDL2/SDL.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#define RTG_INIT_ERR(a) { printf(a); *data->running = 0; }
+
+uint8_t busy = 0, rtg_on = 0;
+extern uint8_t *rtg_mem;
+extern uint32_t framebuffer_addr;
+
+extern uint16_t rtg_display_width, rtg_display_height;
+extern uint16_t rtg_display_format;
+extern uint16_t rtg_pitch, rtg_total_rows;
+extern uint16_t rtg_offset_x, rtg_offset_y;
+
+static pthread_t thread_id;
+
+struct rtg_shared_data {
+ uint16_t *width, *height;
+ uint16_t *format, *pitch;
+ uint16_t *offset_x, *offset_y;
+ uint8_t *memory;
+ uint32_t *addr;
+ uint8_t *running;
+};
+
+SDL_Window *win = NULL;
+SDL_Renderer *renderer = NULL;
+SDL_Texture *img = NULL;
+
+struct rtg_shared_data rtg_share_data;
+
+void rtg_update_screen() {
+ struct rtg_shared_data *data = &rtg_share_data;
+
+ //printf("RTG thread running\n");
+ //fflush(stdout);
+
+ //while (*data->running) {
+ //printf("We in da loop?\n");
+ //busy = 1;
+ SDL_UpdateTexture(img, NULL, &data->memory[*data->addr + (*data->offset_x << *data->format) + (*data->offset_y * *data->pitch)], *data->pitch);
+ //busy = 0;
+ SDL_RenderClear(renderer);
+ SDL_RenderCopy(renderer, img, NULL, NULL);
+ SDL_RenderPresent(renderer);
+ //sleep(0);
+ //}
+
+ //SDL_Quit();
+ //printf("RTG thread exited somewhat peacefully.\n");
+
+ //return args;
+}
+
+void rtg_set_clut_entry(uint8_t index, uint8_t r, uint8_t g, uint8_t b) {
+
+}
+
+void rtg_init_display() {
+ int err;
+ rtg_on = 1;
+
+ rtg_share_data.format = &rtg_display_format;
+ rtg_share_data.width = &rtg_display_width;
+ rtg_share_data.height = &rtg_display_height;
+ rtg_share_data.pitch = &rtg_pitch;
+ rtg_share_data.offset_x = &rtg_offset_x;
+ rtg_share_data.offset_y = &rtg_offset_y;
+ rtg_share_data.memory = rtg_mem;
+ rtg_share_data.running = &rtg_on;
+ rtg_share_data.addr = &framebuffer_addr;
+ struct rtg_shared_data *data = &rtg_share_data;
+
+ printf("Creating %dx%d SDL2 window...\n", *data->width, *data->height);
+ fflush(stdout);
+ win = SDL_CreateWindow("Pistorm RTG", 0, 0, *data->width, *data->height, 0);
+ if (!win) {
+ RTG_INIT_ERR("Failed create SDL2 window.\n");
+ fflush(stdout);
+ goto death;
+ }
+ else {
+ printf("Created %dx%d window.\n", *data->width, *data->height);
+ fflush(stdout);
+ }
+
+ printf("Creating SDL2 renderer...\n");
+ fflush(stdout);
+ renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
+ if (!renderer) {
+ RTG_INIT_ERR("Failed create SDL2 renderer.\n");
+ fflush(stdout);
+ goto death;
+ }
+ else {
+ printf("Created SDL2 renderer.\n");
+ fflush(stdout);
+ }
+
+ printf("Creating SDL2 texture...\n");
+ fflush(stdout);
+ img = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_TARGET, *data->width, *data->height);
+ if (!img) {
+ RTG_INIT_ERR("Failed create SDL2 texture.\n");
+ fflush(stdout);
+ goto death;
+ }
+ else {
+ printf("Created %dx%d texture.\n", *data->width, *data->height);
+ fflush(stdout);
+ }
+
+ /*err = pthread_create(&thread_id, NULL, &rtgThread, (void *)&rtg_share_data);
+ if (err != 0) {
+ rtg_on = 0;
+ printf("can't create RTG thread :[%s]", strerror(err));
+ }
+ else {
+ printf("RTG Thread created successfully\n");*/
+ printf("RTG display enabled.\n");
+ //}
+ death:;
+}
+
+void rtg_shutdown_display() {
+ //void *balf;
+ printf("RTG display disabled.\n");
+ //while(rtg_on) {
+ rtg_on = 0;
+ //sleep(0);
+ //}
+
+ if (img) SDL_DestroyTexture(img);
+ if (renderer) SDL_DestroyRenderer(renderer);
+ if (win) SDL_DestroyWindow(win);
+}
#include <stdint.h>
#include <endian.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
#include "rtg.h"
#include "../../../config_file/config_file.h"
static uint16_t palette[256];
-static uint8_t rtg_mem[64 * SIZE_MEGA]; // FIXME
static uint8_t rtg_u8[4];
static uint16_t rtg_x[3], rtg_y[3];
static uint32_t rtg_address[2];
static uint32_t rtg_rgb[2];
-static uint8_t rtg_enabled;
+static uint8_t display_enabled;
uint16_t rtg_display_width, rtg_display_height;
uint16_t rtg_display_format;
uint16_t rtg_pitch, rtg_total_rows;
uint16_t rtg_offset_x, rtg_offset_y;
+uint8_t *rtg_mem; // FIXME
+
uint32_t framebuffer_addr;
static void handle_rtg_command(uint32_t cmd);
+static struct timespec f1, f2;
static const char *op_type_names[OP_TYPE_NUM] = {
"BYTE",
"15BPP RGB (555)",
};
+int init_rtg_data() {
+ rtg_mem = calloc(1, 32 * SIZE_MEGA);
+ if (!rtg_mem) {
+ printf("Failed to allocate RTG video memory.\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+extern uint8_t busy, rtg_on;
+void rtg_update_screen();
+
unsigned int rtg_read(uint32_t address, uint8_t mode) {
//printf("%s read from RTG: %.8X\n", op_type_names[mode], address);
if (address >= PIGFX_REG_SIZE) {
return 0;
}
+struct timespec diff(struct timespec start, struct timespec end)
+{
+ struct timespec temp;
+ if ((end.tv_nsec-start.tv_nsec)<0) {
+ temp.tv_sec = end.tv_sec-start.tv_sec-1;
+ temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
+ } else {
+ temp.tv_sec = end.tv_sec-start.tv_sec;
+ temp.tv_nsec = end.tv_nsec-start.tv_nsec;
+ }
+ return temp;
+}
+
void rtg_write(uint32_t address, uint32_t value, uint8_t mode) {
//printf("%s write to RTG: %.8X (%.8X)\n", op_type_names[mode], address, value);
if (address >= PIGFX_REG_SIZE) {
}
}
+ if (rtg_on) {
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &f2);
+ if (diff(f1,f2).tv_nsec / 1000000.0 > 100.00) {
+ rtg_update_screen();
+ f1 = f2;
+ }
+ }
+
return;
}
break;
case RTGCMD_SETPAN:
//printf("Command: SetPan.\n");
- framebuffer_addr = rtg_address[0];
+ framebuffer_addr = rtg_address[0] - (PIGFX_RTG_BASE + PIGFX_REG_SIZE);
rtg_offset_x = rtg_x[1];
rtg_offset_y = rtg_y[1];
rtg_pitch = (rtg_x[0] << rtg_display_format);
case RTGCMD_SETCLUT: {
//printf("Command: SetCLUT.\n");
//printf("Set palette entry %d to %d, %d, %d\n", rtg_u8[0], rtg_u8[1], rtg_u8[2], rtg_u8[3]);
- int r = (int)((float)rtg_u8[1] / 255.0f * 31.0f);
+ /*int r = (int)((float)rtg_u8[1] / 255.0f * 31.0f);
int g = (int)((float)rtg_u8[2] / 255.0f * 63.0f);
int b = (int)((float)rtg_u8[3] / 255.0f * 31.0f);
- palette[rtg_u8[0]] = ((r & 0x1F) << 11) | ((g & 0x3F) << 6) | ((b & 0x1F) << 6);
+ palette[rtg_u8[0]] = ((r & 0x1F) << 11) | ((g & 0x3F) << 6) | (b & 0x1F);*/
+ rtg_set_clut_entry(rtg_u8[0], rtg_u8[1], rtg_u8[2], rtg_u8[3]);
break;
}
case RTGCMD_SETDISPLAY:
+ // I remeber wrongs.
//printf("Command: SetDisplay.\n");
- if (rtg_enabled != rtg_u8[1]) {
- //printf("RTG Display %s\n", (rtg_u8[1]) ? "enabled" : "disabled");
- rtg_enabled = rtg_u8[1];
- //if (rtg_enabled)
- //printf("%dx%d pixels\n", rtg_display_width, rtg_display_height);
- }
break;
case RTGCMD_ENABLE:
case RTGCMD_SETSWITCH:
- // Implementing this command only matters if the Pi is to pass through the analog (or digital)
- // native video, otherwise this does nothing.
+ if (display_enabled != rtg_u8[1]) {
+ //printf("RTG Display %s\n", (rtg_u8[1]) ? "enabled" : "disabled");
+ display_enabled = rtg_u8[1];
+ if (display_enabled) {
+ rtg_init_display();
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &f1);
+ }
+ else
+ rtg_shutdown_display();
+ }
+ break;
+ case RTGCMD_FILLRECT:
+ rtg_fillrect(rtg_x[0], rtg_y[0], rtg_x[1], rtg_y[1], rtg_rgb[0], rtg_x[2], rtg_format, 0xFF);
+ break;
+ }
+}
+
+void rtg_fillrect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color, uint16_t pitch, uint16_t format, uint8_t mask) {
+ if (mask) {}
+ switch(format) {
+ case RTGFMT_8BIT:
+ break;
+ case RTGFMT_RBG565: {
+ uint16_t *ptr = (uint16_t *)&rtg_mem[framebuffer_addr + (x << format) + (y * pitch)];
+ for (int xs = 0; xs < w; xs++) {
+ ptr[xs] = (color >> 16);
+ }
+ for (int ys = 1; ys < h; ys++) {
+ ptr += (rtg_pitch >> format);
+ memcpy(ptr, (void *)(size_t)(ptr - (rtg_pitch >> format)), rtg_pitch);
+ }
+ break;
+ }
+ case RTGFMT_RGB32:
break;
}
}
RTGCMD_ENABLE,
RTGCMD_SETDISPLAY,
RTGCMD_SETSWITCH,
+ RTGCMD_FILLRECT,
};
enum rtg_formats {
void rtg_write(uint32_t address, uint32_t value, uint8_t mode);
unsigned int rtg_read(uint32_t address, uint8_t mode);
+void rtg_set_clut_entry(uint8_t index, uint8_t r, uint8_t g, uint8_t b);
+void rtg_init_display();
+void rtg_shutdown_display();
+
+void rtg_fillrect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color, uint16_t pitch, uint16_t format, uint8_t mask);
\ No newline at end of file
--- /dev/null
+vc +aos68k -nostdlib -I$VBCC/targets/m68k-amigaos/include2 -c99 -O2 -o pigfx020.card pigfx.c -ldebug -lamiga -cpu=68020
+vc +aos68k -nostdlib -I$VBCC/targets/m68k-amigaos/include2 -c99 -O2 -o pigfx030.card pigfx.c -ldebug -lamiga -cpu=68030
RTGCMD_ENABLE,
RTGCMD_SETDISPLAY,
RTGCMD_SETSWITCH,
+ RTGCMD_FILLRECT,
};
enum rtg_formats {
void WaitVerticalSync (__REGA0(struct BoardInfo *b), __REGD0(BOOL toggle));
+void FillRect (__REGA0(struct BoardInfo *b), __REGA1(struct RenderInfo *r), __REGD0(WORD x), __REGD1(WORD y), __REGD2(WORD w), __REGD3(WORD h), __REGD4(ULONG color), __REGD5(UBYTE mask), __REGD7(RGBFTYPE format));
+
static ULONG LibStart(void) {
return(-1);
}
//b->BlitPlanar2Chunky = (void *)NULL;
//b->BlitPlanar2Direct = (void *)NULL;
- //b->FillRect = (void *)NULL;
+ b->FillRect = (void *)FillRect;
//b->InvertRect = (void *)NULL;
//b->BlitRect = (void *)NULL;
//b->BlitTemplate = (void *)NULL;
setswitch = enabled;
if (old_setswitch != enabled) {
- //WRITEBYTE(RTG_U81, (unsigned char)enabled);
- //WRITESHORT(RTG_COMMAND, RTGCMD_SETSWITCH);
+ WRITEBYTE(RTG_U81, (unsigned char)enabled);
+ WRITESHORT(RTG_COMMAND, RTGCMD_SETSWITCH);
}
return old_setswitch;
void WaitVerticalSync (__REGA0(struct BoardInfo *b), __REGD0(BOOL toggle)) {
// I don't know why this one has a bool in D0, but it isn't used for anything.
}
+
+void FillRect (__REGA0(struct BoardInfo *b), __REGA1(struct RenderInfo *r), __REGD0(WORD x), __REGD1(WORD y), __REGD2(WORD w), __REGD3(WORD h), __REGD4(ULONG color), __REGD5(UBYTE mask), __REGD7(RGBFTYPE format)) {
+ if (!r)
+ return;
+ if (mask != 0xFF)
+ b->FillRectDefault(b, r, x, y, w, h, color, mask, format);
+
+ WRITESHORT(RTG_FORMAT, rgbf_to_rtg[format]);
+ WRITESHORT(RTG_X1, x);
+ WRITESHORT(RTG_X2, w);
+ WRITESHORT(RTG_Y1, y);
+ WRITESHORT(RTG_Y2, h);
+ WRITELONG(RTG_RGB1, color);
+ WRITESHORT(RTG_X3, r->BytesPerRow);
+ WRITESHORT(RTG_COMMAND, RTGCMD_FILLRECT);
+}
\ No newline at end of file