Dysfunctional SDL2 RTG output

This commit is contained in:
beeanyew
2021-01-05 03:01:12 +01:00
parent a0664148fd
commit fa52466319
13 changed files with 597 additions and 218 deletions

View File

@@ -14,6 +14,7 @@ MAINFILES = emulator.c \
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
@@ -32,7 +33,7 @@ EXEPATH = ./
CC = gcc
WARNINGS = -Wall -Wextra -pedantic
CFLAGS = $(WARNINGS) -march=armv7 -O3
LFLAGS = $(WARNINGS)
LFLAGS = $(WARNINGS) -lSDL2
TARGET = $(EXENAME)$(EXE)

View File

@@ -14,6 +14,7 @@
#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"
@@ -137,6 +138,22 @@ int main(int argc, char *argv[]) {
}
}
// 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");

View File

@@ -29,69 +29,12 @@
//#define GCLOW 0xda2010
//#define GDH 0xda2018
// Gayle Addresses
uint8_t gary_cfg[8];
// 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 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;
@@ -107,11 +50,24 @@ unsigned char cdtv_sram[32 * SIZE_KILO];
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]);
@@ -148,71 +104,69 @@ uint8_t CheckIrq(void) {
return 0;
}
static uint8_t ide_action = 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);
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 == 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;
}
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;
return;
}
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) {
@@ -232,11 +186,16 @@ void writeGayleB(unsigned int address, unsigned int value) {
}
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) {
@@ -275,35 +234,94 @@ void writeGayleL(unsigned int address, unsigned int value) {
}
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);
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:;
}
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);
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) {
@@ -318,64 +336,23 @@ uint8_t readGayleB(unsigned int address) {
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) {

View File

@@ -24,4 +24,108 @@ uint16_t readGayle(unsigned int address);
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 */

View File

@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "../platforms.h"
#include "amiga-autoconf.h"
#include "amiga-registers.h"
@@ -9,6 +10,7 @@
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;
@@ -153,6 +155,26 @@ void adjust_ranges_amiga(struct emulator_config *cfg) {
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:;
@@ -261,9 +283,13 @@ void setvar_amiga(struct emulator_config *cfg, char *var, char *val) {
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) {
@@ -316,5 +342,8 @@ void create_platform_amiga(struct platform_config *cfg, char *subsys) {
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]);
}
}
}

View File

@@ -3,6 +3,9 @@ void set_hard_drive_image_file_amiga(uint8_t index, char *filename);
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
@@ -10,3 +13,18 @@ int custom_write_amiga(struct emulator_config *cfg, unsigned int addr, unsigned
#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

View File

@@ -0,0 +1,139 @@
#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);
}

View File

@@ -1,11 +1,13 @@
#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];
@@ -13,16 +15,19 @@ static uint16_t rtg_format;
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",
@@ -38,6 +43,19 @@ static const char *rtg_format_names[RTGFMT_NUM] = {
"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) {
@@ -61,6 +79,19 @@ unsigned int rtg_read(uint32_t address, uint8_t mode) {
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) {
@@ -138,6 +169,14 @@ void rtg_write(uint32_t address, uint32_t value, uint8_t mode) {
}
}
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;
}
@@ -162,7 +201,7 @@ static void handle_rtg_command(uint32_t cmd) {
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);
@@ -173,25 +212,53 @@ static void handle_rtg_command(uint32_t cmd) {
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;
}
}

View File

@@ -31,6 +31,7 @@ enum rtg_cmds {
RTGCMD_ENABLE,
RTGCMD_SETDISPLAY,
RTGCMD_SETSWITCH,
RTGCMD_FILLRECT,
};
enum rtg_formats {
@@ -43,3 +44,8 @@ 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);

View File

@@ -0,0 +1,2 @@
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

View File

@@ -52,6 +52,7 @@ enum rtg_cmds {
RTGCMD_ENABLE,
RTGCMD_SETDISPLAY,
RTGCMD_SETSWITCH,
RTGCMD_FILLRECT,
};
enum rtg_formats {
@@ -112,6 +113,8 @@ void SetReadPlane (__REGA0(struct BoardInfo *b), __REGD0(UBYTE plane));
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);
}
@@ -333,7 +336,7 @@ int InitCard(__REGA0(struct BoardInfo* b)) {
//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;
@@ -396,8 +399,8 @@ BOOL SetSwitch (__REGA0(struct BoardInfo *b), __REGD0(BOOL enabled)) {
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;
@@ -516,3 +519,19 @@ void SetReadPlane (__REGA0(struct BoardInfo *b), __REGD0(UBYTE plane)) {
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);
}