Files
Main_MiSTer/support/atari8bit/atari5200.cpp
Wojciech Mostowski 41c93443a9 Atari800: reset fix for oscillating keyboard triggered reset (#1139)
* Atari800: reset fix for oscillating keyboard triggered reset

* Atari5200: same reset fix as for the 800

* Atari800/5200: removed function naming clash

* Atari5200: one more reset fix
2026-03-25 18:15:05 +08:00

300 lines
7.2 KiB
C++

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../../hardware.h"
#include "../../menu.h"
#include "../../file_io.h"
#include "../../debug.h"
#include "../../user_io.h"
#include "../../fpga_io.h"
#include "atari5200.h"
#include "atari8bit_defs.h"
extern uint8_t a8bit_buffer[];
void set_a8bit_reg(uint8_t reg, uint8_t val);
uint16_t get_a8bit_reg(uint8_t reg);
void atari8bit_dma_write(const uint8_t *buf, uint32_t addr, uint32_t len);
void atari8bit_dma_zero(uint32_t addr, uint32_t len);
static void reboot_5200(uint8_t phase = 3)
{
if(phase & 0x01)
{
set_a8bit_reg(REG_PAUSE, 1);
// Initialize the first 16K of Atari RAM with a pattern
for(int i = 0; i < BUFFER_SIZE; i += 2)
{
a8bit_buffer[i] = 0xFF;
a8bit_buffer[i+1] = 0x00;
}
user_io_set_index(99);
user_io_set_download(1, ATARI_BASE);
for(int i = 0; i < 0x4000 / BUFFER_SIZE; i++) user_io_file_tx_data(a8bit_buffer, BUFFER_SIZE);
user_io_set_upload(0);
set_a8bit_reg(REG_RESET, 1);
}
if(phase & 0x02)
{
set_a8bit_reg(REG_RESET, 0);
set_a8bit_reg(REG_PAUSE, 0);
}
}
static int cart_matches_total;
static uint8_t cart_matches_type[2];
static uint8_t cart_match_car;
static unsigned char cart_io_index;
int atari5200_get_match_cart_count()
{
return cart_matches_total;
}
static const char one_chip[16] = "One chip";
static const char two_chip[16] = "Two chip";
const char *atari5200_get_cart_match_name(int match_index)
{
return match_index == 1 ? two_chip : one_chip;
}
void atari5200_umount_cartridge()
{
set_a8bit_reg(REG_CART1_SELECT, 0);
reboot_5200();
}
int atari5200_check_cartridge_file(const char* name, unsigned char index)
{
fileTYPE f = {};
int file_size;
cart_match_car = 0;
cart_matches_total = 0;
cart_io_index = index;
int ext_index = index >> 6; // CAR is index 0
if (FileOpen(&f, name))
{
file_size = f.size;
if (!ext_index)
{
cart_match_car = 1;
FileReadAdv(&f, a8bit_buffer, 16);
}
FileClose(&f);
if(cart_match_car)
{
// CAR file, presumably, let's check further
if (a8bit_buffer[0] == 'C' && a8bit_buffer[1] == 'A' && a8bit_buffer[2] == 'R' && a8bit_buffer[3] == 'T')
{
switch(a8bit_buffer[7])
{
case 0x04:
case 0x06:
case 0x07:
case 0x10:
case 0x13:
case 0x14:
case 0x47:
case 0x48:
case 0x49:
case 0x4A:
cart_matches_type[0] = a8bit_buffer[7];
cart_matches_total = 1;
break;
default:
break;
}
}
}
else
{
uint8_t type = 0xFF;
if (file_size == 0x10000) type = 0x47;
else if (file_size == 0x20000) type = 0x48;
else if (file_size == 0x40000) type = 0x49;
else if (file_size == 0x80000) type = 0x4A;
else if (file_size == 40960) type = 0x07;
else if (file_size == 0x8000) type = 0x04;
else if (file_size == 0x2000) type = 0x13;
else if (file_size == 0x1000) type = 0x14;
else if (file_size == 0x4000)
{
cart_matches_type[0] = 0x10;
cart_matches_type[1] = 0x06;
cart_matches_total = 2;
}
if(cart_matches_total == 0 && type != 0xFF)
{
cart_matches_total = 1;
cart_matches_type[0] = type;
}
}
}
return cart_matches_total;
}
void atari5200_open_cartridge_file(const char* name, int match_index)
{
fileTYPE f = {};
int offset = cart_match_car ? 16 : 0;
uint8_t cart_type = cart_matches_type[match_index];
if (FileOpen(&f, name))
{
//set_a8bit_reg(REG_PAUSE, 1);
set_a8bit_reg(REG_CART1_SELECT, 0);
ProgressMessage(0, 0, 0, 0);
FileSeek(&f, offset, SEEK_SET);
user_io_set_index(cart_io_index);
user_io_set_download(1, SDRAM_BASE + 0x4000);
if(cart_type == 0x06)
{
for(int i = 0; i < 4; i++)
{
ProgressMessage("Loading", f.name, i * 0x2000, 0x8000);
if(i % 2 == 0) FileReadAdv(&f, a8bit_buffer, 0x2000);
user_io_file_tx_data(a8bit_buffer, 0x2000);
}
}
else if(cart_type == 0x10)
{
for(int i = 0; i < 4; i++)
{
ProgressMessage("Loading", f.name, i * 0x2000, 0x8000);
if(i % 2 == 0) FileSeek(&f, offset, SEEK_SET);
FileReadAdv(&f, a8bit_buffer, 0x2000);
user_io_file_tx_data(a8bit_buffer, 0x2000);
}
}
else if(cart_type == 0x13 || cart_type == 0x14)
{
int block_size = f.size - offset;
FileReadAdv(&f, a8bit_buffer, block_size);
for(int i = 0; i < 0x8000 / block_size; i++)
{
ProgressMessage("Loading", f.name, i * block_size, 0x8000);
user_io_file_tx_data(a8bit_buffer, block_size);
}
}
else if(cart_type >= 0x47 && cart_type <= 0x4A)
{
int block_size = f.size - offset;
for(int i = 0; i < 0x80000 / block_size; i++)
{
FileSeek(&f, offset, SEEK_SET);
for(int j = 0; j < block_size / 0x2000; j++)
{
ProgressMessage("Loading", f.name, i * block_size + j * 0x2000, 0x80000);
FileReadAdv(&f, a8bit_buffer, 0x2000);
user_io_file_tx_data(a8bit_buffer, 0x2000);
}
}
}
else if(cart_type == 0x07)
{
FileSeek(&f, 0, SEEK_SET);
FileReadAdv(&f, a8bit_buffer, 512);
uint8_t bb_type1 = (a8bit_buffer[offset] == 0x2F);
FileSeek(&f, offset + (bb_type1 ? 0 : 0x2000), SEEK_SET);
ProgressMessage("Loading", f.name, 0, 0xC000);
FileReadAdv(&f, a8bit_buffer, 0x2000);
user_io_file_tx_data(a8bit_buffer, 0x2000);
ProgressMessage("Loading", f.name, 0x2000, 0xC000);
FileReadAdv(&f, a8bit_buffer, 0x2000);
user_io_file_tx_data(a8bit_buffer, 0x2000);
FileSeek(&f, offset + (bb_type1 ? 0x8000 : 0), SEEK_SET);
ProgressMessage("Loading", f.name, 0x4000, 0xC000);
FileReadAdv(&f, a8bit_buffer, 0x2000);
user_io_file_tx_data(a8bit_buffer, 0x2000);
ProgressMessage("Loading", f.name, 0x6000, 0xC000);
user_io_file_tx_data(a8bit_buffer, 0x2000);
FileSeek(&f, offset + (bb_type1 ? 0x4000 : 0x6000), SEEK_SET);
ProgressMessage("Loading", f.name, 0x8000, 0xC000);
FileReadAdv(&f, a8bit_buffer, 0x2000);
user_io_file_tx_data(a8bit_buffer, 0x2000);
ProgressMessage("Loading", f.name, 0xA000, 0xC000);
FileReadAdv(&f, a8bit_buffer, 0x2000);
user_io_file_tx_data(a8bit_buffer, 0x2000);
}
else if(cart_type == 0x04)
{
while (offset < f.size)
{
int to_read = f.size - offset;
if (to_read > BUFFER_SIZE) to_read = BUFFER_SIZE;
ProgressMessage("Loading", f.name, offset, f.size);
FileReadAdv(&f, a8bit_buffer, to_read);
user_io_file_tx_data(a8bit_buffer, to_read);
offset += to_read;
}
}
FileClose(&f);
user_io_set_download(0);
ProgressMessage(0, 0, 0, 0);
set_a8bit_reg(REG_CART1_SELECT, cart_type);
reboot_5200();
}
}
void atari5200_poll()
{
static uint8_t cold_reboot = 0;
uint16_t atari_status1 = get_a8bit_reg(REG_ATARI_STATUS1);
if(!cold_reboot) set_a8bit_reg(REG_PAUSE, atari_status1 & STATUS1_MASK_HALT);
if ((atari_status1 & STATUS1_MASK_COLDBOOT) && !cold_reboot)
{
cold_reboot = 1;
reboot_5200(1);
}
else if (!(atari_status1 & STATUS1_MASK_COLDBOOT) && cold_reboot)
{
cold_reboot = 0;
reboot_5200(2);
}
}
void atari5200_init()
{
set_a8bit_reg(REG_PAUSE, 1);
cart_matches_total = 0;
cart_match_car = 0;
static char mainpath[512];
const char *home = HomeDir();
sprintf(mainpath, "%s/boot0.rom", home);
user_io_file_tx(mainpath, 0);
atari5200_reset();
}
void atari5200_reset()
{
set_a8bit_reg(REG_PAUSE, 1);
set_a8bit_reg(REG_CART1_SELECT, 0);
atari8bit_dma_zero(SDRAM_BASE + 0x4000, 0x80000);
reboot_5200();
}