Migrate Atari800/5200 FW to Main (#1101)

* WIP Adding Atari800 side of things

* WIP Migrated some functionality from .sv to here

* WIP XEX file loading works, clean-ups

* WIP UART/SIO interface beginning

* WIP Adding Atari800 drive emulator

* WIP First version of the drive emulator working with ATR and XEX files

* WIP ATX files are working

* WIP HDD is now mounted separately

* WIP PBI/HDD is working too

* Cleaning up and adding supporting Atari ASM files

* Updated versioning information in the Atari800 FW

* WIP Adding support for the Atari 5200 core

* Atari 5200 support complete

* Atari800: fixed SIO timing bugs

* Atari800: sorting out SIO timing issues still

* Atari800: eliminate OSD lock up possibilities

* Atari800: Improved XEX loader
This commit is contained in:
Wojciech Mostowski
2026-02-24 05:51:17 +01:00
committed by GitHub
parent a9eb1f5c11
commit deb43cd870
19 changed files with 2999 additions and 2 deletions

View File

@@ -88,6 +88,7 @@
<ClCompile Include="support\arcade\mra_loader.cpp" />
<ClCompile Include="support\archie\archie.cpp" />
<ClCompile Include="support\c64\c64.cpp" />
<ClCompile Include="support\atari800\atari800.cpp" />
<ClCompile Include="support\chd\mister_chd.cpp" />
<ClCompile Include="support\megacd\megacd.cpp" />
<ClCompile Include="support\megacd\megacdd.cpp" />
@@ -167,6 +168,8 @@
<ClInclude Include="support\arcade\mra_loader.h" />
<ClInclude Include="support\archie\archie.h" />
<ClInclude Include="support\c64\c64.h" />
<ClInclude Include="support\atari8bit\atari800.h" />
<ClInclude Include="support\atari8bit\atari5200.h" />
<ClInclude Include="support\chd\mister_chd.h" />
<ClInclude Include="support\megacd\megacd.h" />
<ClInclude Include="support\minimig\miminig_fs_messages.h" />

View File

@@ -172,6 +172,12 @@
<ClCompile Include="support\c64\c64.cpp">
<Filter>Source Files\support</Filter>
</ClCompile>
<ClCompile Include="support\atari8bit\atari800.cpp">
<Filter>Source Files\support</Filter>
</ClCompile>
<ClCompile Include="support\atari8bit\atari5200.cpp">
<Filter>Source Files\support</Filter>
</ClCompile>
<ClCompile Include="support\pcecd\pcecd.cpp">
<Filter>Source Files\support</Filter>
</ClCompile>

109
menu.cpp
View File

@@ -203,6 +203,10 @@ enum MENU
// MT32-pi
MENU_MT32PI_MAIN1,
MENU_MT32PI_MAIN2,
// Atari 8bit cartridge type selection
MENU_ATARI8BIT_CART1,
MENU_ATARI8BIT_CART2,
};
static uint32_t menustate = MENU_NONE1;
@@ -2177,7 +2181,7 @@ void HandleUI(void)
if (is_gba() && FileExists(user_io_make_filepath(HomeDir(), "goomba.rom"))) strcat(ext, "GB GBC");
while (strlen(ext) % 3) strcat(ext, " ");
fs_Options = SCANO_DIR | (is_neogeo() ? SCANO_NEOGEO | SCANO_NOENTER : 0) | (store_name ? SCANO_CLEAR : 0);
fs_Options = SCANO_DIR | (is_neogeo() ? SCANO_NEOGEO | SCANO_NOENTER : 0) | (store_name ? SCANO_CLEAR : 0) | (is_atari5200() || (is_atari800() && (ioctl_index == 8 || ioctl_index == 9)) ? SCANO_UMOUNT : 0);
fs_MenuSelect = MENU_GENERIC_FILE_SELECTED;
fs_MenuCancel = MENU_GENERIC_MAIN1;
strcpy(fs_pFileExt, ext);
@@ -2350,6 +2354,8 @@ void HandleUI(void)
if (is_saturn() && !bit) saturn_reset();
if (is_n64() && !bit) n64_reset();
if (is_psx() && !bit) psx_reset();
if (is_atari800() && !bit) atari800_reset();
if (is_atari5200() && !bit) atari5200_reset();
user_io_status_set(opt, 1, ex);
user_io_status_set(opt, 0, ex);
@@ -2404,7 +2410,7 @@ void HandleUI(void)
}
}
MenuHide();
if(!(selPath[0] && (is_atari5200() || (is_atari800() && (ioctl_index == 8 || ioctl_index == 9))))) MenuHide();
printf("File selected: %s\n", selPath);
memcpy(Selected_F[ioctl_index & 15], selPath, sizeof(Selected_F[ioctl_index & 15]));
@@ -2446,6 +2452,38 @@ void HandleUI(void)
{
c64_open_file(selPath, idx);
}
else if (is_atari800() || is_atari5200())
{
if(is_atari800() && ioctl_index != 8 && ioctl_index != 9)
{
atari800_open_bios_file(selPath, idx);
}
else
{
int a8bit_cart_matches = is_atari5200() ? atari5200_check_cartridge_file(selPath, idx): atari800_check_cartridge_file(selPath, idx);
if(a8bit_cart_matches <= 1) MenuHide();
if(a8bit_cart_matches == 1)
{
if(is_atari5200())
{
atari5200_open_cartridge_file(selPath, 0);
}
else
{
atari800_open_cartridge_file(selPath, 0);
}
}
else if(a8bit_cart_matches > 1 && mgl->done)
{
menustate = MENU_ATARI8BIT_CART1;
menusub = 0;
}
else if(mgl->done)
{
Info("Unsupported cartridge type!", 2000);
}
}
}
else
{
user_io_file_tx(selPath, idx, opensave, 0, 0, load_addr);
@@ -2455,6 +2493,14 @@ void HandleUI(void)
if (addon[0] == 'f' && addon[1] == '1') process_addon(addon, idx);
}
else if(is_atari800() && (ioctl_index == 8 || ioctl_index == 9))
{
atari800_umount_cartridge(ioctl_index == 9);
}
else if(is_atari5200())
{
atari5200_umount_cartridge();
}
mgl->state = 3;
}
@@ -2530,6 +2576,10 @@ void HandleUI(void)
neocd_set_en(1);
neocd_set_image(selPath);
}
else if (is_atari800())
{
atari800_set_image(user_io_ext_idx(selPath, fs_pFileExt), ioctl_index, selPath);
}
else
{
user_io_set_index(user_io_ext_idx(selPath, fs_pFileExt) << 6 | (menusub + 1));
@@ -6984,6 +7034,61 @@ void HandleUI(void)
SelectFile("", 0, SCANO_CORES, MENU_CORE_FILE_SELECTED1, cp_MenuCancel);
break;
case MENU_ATARI8BIT_CART1:
helptext_idx = 0;
menumask = 0;
OsdSetSize(16);
OsdSetTitle("Cartridge Type");
menustate = MENU_ATARI8BIT_CART2;
parentstate = MENU_ATARI8BIT_CART1;
{
int entry = 0;
uint32_t selentry = 0;
int a8bit_match_count = is_atari5200() ? atari5200_get_match_cart_count() : atari800_get_match_cart_count();
for (int i = 0; i < a8bit_match_count; i++)
{
s[0] = ' ';
strcpy(s + 1, is_atari5200() ? atari5200_get_cart_match_name(i) : atari800_get_cart_match_name(i));
OsdWrite(entry, s, menusub == selentry);
menumask = (menumask << 1) | 1;
entry++;
selentry++;
}
while (entry < OsdGetSize() - 1) OsdWrite(entry++);
OsdWrite(entry, " Cancel", menusub == selentry);
menusub_last = selentry;
menumask = (menumask << 1) | 1;
}
break;
case MENU_ATARI8BIT_CART2:
if (menu || left)
{
menustate = MENU_GENERIC_MAIN1;
menusub = ioctl_index - 2;
}
else if (select)
{
menustate = MENU_NONE1;
if (menusub != menusub_last)
{
int match_index = menusub;
HandleUI(); // What MenuHide() would do...
if(is_atari5200())
{
atari5200_open_cartridge_file(selPath, match_index);
}
else
{
atari800_open_cartridge_file(selPath, match_index);
}
}
}
break;
/******************************************************************/
/* we should never come here */
/******************************************************************/

View File

@@ -40,6 +40,10 @@
// C64 support
#include "support/c64/c64.h"
// Atari 8bit support
#include "support/atari8bit/atari800.h"
#include "support/atari8bit/atari5200.h"
// PCECD support
#include "support/pcecd/pcecd.h"

View File

@@ -0,0 +1,15 @@
# This produces the supporting binary data for the Atari800 core,
# the internal XEX loader and the PBI rom file boot3.rom. The
# latter should be placed in games/ATARI800 folder of your MiSTer
# SD card.
all: ../xex_loader.h boot3.rom
../xex_loader.h: xex_loader.asm
xa xex_loader.asm -o xex_loader.o65 -l xex_loader.lab
python3 process_xex_loader.py
rm xex_loader.o65 xex_loader.lab
mv xex_loader.h ..
boot3.rom: pbi_bios.asm
xa -M -o boot3.rom pbi_bios.asm

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,206 @@
; Links:
; http://atariki.krap.pl/index.php/ROM_PBI
#define VER_MAJOR 0
#define VER_MINOR 9
warmst = $008
pdvmsk = $247
pdvrs = $248
ddevic = $300
dunit = $301
dstats = $303
dtimlo = $306
cdtma1 = $226
setvbv = $e45c
; PBI BIOS RAM
pbi_magic = $d100 ; word
pbi_splash_flag = $d102
pbi_req_init_flag = $d103
pbi_req_proc_res = $d104
pbi_req_proc_flag = $d105
pbi_stack_save = $d106
pbi_drive_boot_act = $d10a
pbi_drive_boot = $d10b
pbi_drive_conf = $d10c
; HSIO RAM variables sit upwards of $d1f0 incl.
* = $D800
bios1_start
.byte 'M', 'S', 'T'
; Magic 1
.byte $80
.byte $31 ; ddevic we are servicing
pdior_vec
jmp pdior
pdint_vec
rts : nop : nop
; Magic 2
.byte $91
.byte $00 ; no CIO
.word pdint_vec
.word pdint_vec
.word pdint_vec
.word pdint_vec
.word pdint_vec
.word pdint_vec
pdinit
lda pdvmsk : ora pdvrs : sta pdvmsk
lda #0 : ldx #$fe : sta $d100-1,x : dex : bne *-4
; Marker for the core firmware
lda #$a5 : sta pbi_magic : sta pbi_magic+1
; ask for init
inc pbi_req_init_flag : lda pbi_req_init_flag : bne *-3
lda warmst : bmi pdinit_1
lda pbi_drive_boot_act : beq pdinit_1
sta dunit
pdinit_1
; Do we want the splash?
lda pbi_splash_flag : beq pdinit_ret
jsr boot_screen_init
lda #$0c : sta $2c5 ; color 1
lda #$e0 : sta $d409 ; chbase
lda #<display_list : sta $d402 : lda #>display_list : sta $d403 ; display list
lda $14 : cmp $14 : beq *-2 : ldy #$22 : sty $d400 ; dmactl
clc : adc #100 : cmp $14 : bne *-2
lda #0 : sta $d400
pdinit_ret
rts
display_list
.byte $70, $70, $70
.byte $42 : .word display_text1
.byte $10
.byte $42 : .word display_text2
.byte $70
.byte $42 : .word display_text3
.byte $30
.byte $02
.byte $41 : .word display_list
display_text1
.byte 0,0
.byte 'A'-$20,'tari','8'-$20,'0'-$20,'0'-$20,0,'M'-$20,'i','S'-$20,'T'-$20,'er',0,'core',0
.byte 'P'-$20,'B'-$20,'I'-$20,0,'B'-$20,'I'-$20,'O'-$20,'S'-$20,0
.byte 'v',VER_MAJOR+$10,'.'-$20,VER_MINOR+$10
display_text1_len = *-display_text1
.dsb 40-display_text1_len,0
display_text2
.byte 0,0
.byte '('-$20,'C'-$20,')'-$20,0,'2'-$20,'0'-$20,'2'-$20,'6'-$20,0,'woj','@'-$20,'A'-$20,'tari','A'-$20,'ge'
display_text2_len = *-display_text2
.dsb 40-display_text2_len,0
display_text3 = $d110
drive_labels_1 .byte 'O'-$20, 'P'-$20, 'H'-$20
drive_labels_2 .byte 'f', 'B'-$20, 'S'-$20
drive_labels_3 .byte 'f', 'I'-$20, 'I'-$20
drive_labels_4 .byte 0, 0, 'O'-$20
boot_label_1 .byte 'B'-$20,'o','o','t',0,'D'-$20,'r','i','v','e',':'-$20
boot_label_1_len = *-boot_label_1
boot_label_2 .byte 'D'-$20,'e','f','a','u','l','t'
boot_label_2_len = *-boot_label_2
boot_label_3 .byte 'A'-$20,'P'-$20,'T'-$20
boot_label_3_len = *-boot_label_3
boot_screen_init
ldy #1
boot_screen_init_loop
lda #'D'-$20 : sta display_text3+2,x : inx
tya : pha : ora #$10 : sta display_text3+2,x : inx
lda #':'-$20 : sta display_text3+2,x : inx : inx
lda pbi_drive_conf-1,y : tay
lda drive_labels_1,y : sta display_text3+2,x : inx
lda drive_labels_2,y : sta display_text3+2,x : inx
lda drive_labels_3,y : sta display_text3+2,x : inx
lda drive_labels_4,y : sta display_text3+2,x : inx : inx
pla : tay : iny : cpy #5 : bne boot_screen_init_loop
ldy #boot_label_1_len
boot_screen_init_loop_2
lda boot_label_1-1,y : sta display_text3+41,y
dey : bne boot_screen_init_loop_2
ldx pbi_drive_boot : dex
bmi boot_drv_def
beq boot_drv_apt
lda #'D'-$20 : sta display_text3+42+boot_label_1_len+1
txa : ora #$10 : sta display_text3+42+boot_label_1_len+2
lda #':'-$20 : sta display_text3+42+boot_label_1_len+3
bne boot_screen_init_ret
boot_drv_def
ldy #boot_label_2_len
boot_drv_def_loop
lda boot_label_2-1,y : sta display_text3+42+boot_label_1_len,y
dey : bne boot_drv_def_loop
beq boot_screen_init_ret
boot_drv_apt
ldy #boot_label_3_len
boot_drv_apt_loop
lda boot_label_3-1,y : sta display_text3+42+boot_label_1_len,y
dey : bne boot_drv_apt_loop
boot_screen_init_ret
rts
; The main block I/O routine
pdior
lda ddevic : and #$7F : cmp #$31 : beq pdior_2
cmp #$20 : bne pdior_bail
pdior_2
lda dunit : beq pdior_bail
cmp #$10 : bcs pdior_bail
tsx : stx pbi_stack_save
lda dtimlo : ror : ror : tay : and #$3f : tax : tya : ror : and #$c0 : tay : lda #1
jsr setvbv
lda #<pbi_time_out : sta cdtma1 : lda #>pbi_time_out : sta cdtma1+1
inc pbi_req_proc_flag : lda pbi_req_proc_flag : bne *-3
ldx #0 : ldy #0 : lda #1 : jsr setvbv
lda pbi_req_proc_res : bmi pdior_bail ; the FW says either no PBI service or ATX (plain SIO)
beq pdior_pbi_ok ; the drive was in PBI mode and got serviced
; otherwise call HSIO
jsr $dc00 : sec : rts
pdior_pbi_ok
ldy dstats : sec : rts
pdior_bail
; We are not servicing this block I/O request
clc : rts
pbi_time_out
lda #0 : sta pbi_req_proc_flag : ldx pbi_stack_save : txs
lda #$8a : sta dstats : bne pdior_pbi_ok
bios1_end
.dsb ($400-bios1_end+bios1_start),$ff
hsio_start ; This should be $dc00
.bin 6,0,"hsio_pbi.xex"
hsio_end
.dsb ($3AD-hsio_end+hsio_start),$ff
.byte VER_MAJOR*16+VER_MINOR ; Version byte
.byte (device_name_end-device_name-1)
device_name
.byte "SDHC MiSTer SDEMU v.",VER_MAJOR+$30,'.',VER_MINOR+$30,$9B
device_name_end
.dsb (40-device_name_end+device_name),$ff
; .dsb ($3D7-hsio_end+hsio_start),$ff
.byte (bios_name_end-bios_name-1)
bios_name
.byte "MiSTer core PBI BIOS v.",VER_MAJOR+$30,'.',VER_MINOR+$30,$9B
bios_name_end
.dsb (40-bios_name_end+bios_name),$ff
* = $D800
.dsb $800,$FF
* = $D800
.dsb $800,$FF
* = $D800
.dsb $800,$FF

View File

@@ -0,0 +1,40 @@
#!/usr/bin/python3
f = open("xex_loader.o65", "rb")
loader = f.read()
f.close()
s = "const static uint8_t xex_loader[] =\n{\n\t"
i = 0
for b in loader:
s += f"0x{b:02X},"
i += 1
if i == len(loader):
s = s[:-1]
if i % 16 == 0:
s += "\n\t"
if i % 16 != 0:
s += "\n"
else:
s = s[:-1]
s += "};\n\n"
f = open("xex_loader.lab", "rt")
l = f.read().split("\n")
f.close()
for ll in l:
if ll[:11] == "read_status":
read_status = ll[17:19]
elif ll[:5] == "init1":
init1 = ll[11:13]
s += f"#define XEX_READ_STATUS 0x{read_status}\n"
s += f"#define XEX_INIT1 0x{init1}\n\n"
f = open("xex_loader.h", "wt")
f.write(s)
f.close()

View File

@@ -0,0 +1,16 @@
* = $D100
magic
.byte $61
init1
ldx #0 : stx $09 : dex : txs
dec magic
load_next_block
dec read_status
lda #1 : read_status = *-1 : beq *-2
bmi init_go
lda #>(load_next_block-1) : pha
lda #<(load_next_block-1) : pha
jmp ($2e2)
init_go
dec magic
jmp ($2e0)

View File

@@ -0,0 +1,284 @@
#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()
{
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);
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();
}
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();
}
}
void atari5200_poll()
{
uint16_t atari_status1 = get_a8bit_reg(REG_ATARI_STATUS1);
set_a8bit_reg(REG_PAUSE, atari_status1 & STATUS1_MASK_HALT);
if (atari_status1 & STATUS1_MASK_COLDBOOT) reboot();
}
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();
}

View File

@@ -0,0 +1,14 @@
#ifndef __ATARI5200_H__
#define __ATARI5200_H__
int atari5200_get_match_cart_count();
const char *atari5200_get_cart_match_name(int match_index);
void atari5200_init();
void atari5200_reset();
void atari5200_poll();
void atari5200_umount_cartridge();
int atari5200_check_cartridge_file(const char* name, unsigned char index);
void atari5200_open_cartridge_file(const char* name, int match_index);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
#ifndef __ATARI800_H__
#define __ATARI800_H__
int atari800_get_match_cart_count();
const char *atari800_get_cart_match_name(int match_index);
void atari800_init();
void atari800_reset();
void atari800_poll();
void atari800_umount_cartridge(uint8_t stacked);
int atari800_check_cartridge_file(const char* name, unsigned char index);
void atari800_open_cartridge_file(const char* name, int match_index);
void atari800_open_bios_file(const char* name, unsigned char index);
void atari800_set_image(int ext_index, int file_index, const char *name);
#endif

View File

@@ -0,0 +1,43 @@
#define STATUS1_MASK_SOFTBOOT 0x0001
#define STATUS1_MASK_COLDBOOT 0x0002
#define STATUS1_MASK_HALT 0x0004
#define STATUS1_MASK_MODE800 0x0008
#define STATUS1_MASK_BOOTX 0x0010
#define STATUS1_MASK_RDONLY 0x0040
#define STATUS1_MASK_MODEPBI 0x0080
#define STATUS1_MASK_ATX1050 0x8000
#define STATUS2_MASK_SPLASH 0x0800
#define BUFFER_SIZE 8192
#if BUFFER_SIZE < 8192
#error BUFFER_SIZE is too small!
#endif
#define A800_SIO_TX_STAT 0x03
#define A800_SIO_RX 0x04
#define A800_SIO_RX_STAT 0x05
#define A800_SIO_GETDIV 0x06
#define A800_SIO_ERROR 0x07
#define A800_GET_REGISTER 0x08
#define A800_SET_REGISTER 0x09
#define REG_CART1_SELECT 0x01
#define REG_CART2_SELECT 0x02
#define REG_RESET 0x03
#define REG_PAUSE 0x04
#define REG_FREEZER 0x05
#define REG_RESET_RNMI 0x06
#define REG_OPTION_FORCE 0x07
#define REG_DRIVE_LED 0x08
#define REG_XEX_LOADER 0x09
#define REG_SIO_TX 0x0A
#define REG_SIO_SETDIV 0x0B
#define REG_ATARI_STATUS1 0x01
#define REG_ATARI_STATUS2 0x02
#define SDRAM_BASE 0x2000000
#define ATARI_BASE 0x0010000

View File

@@ -0,0 +1,18 @@
// This loader is most probably originally from SDrive(Max). Should probably be reviewed,
// but then the best way to load XEX files on MiSTer is using the DMA loader anyways...
const static uint8_t boot_xex_loader[384] =
{
0x72,0x02,0x5f,0x07,0xf8,0x07,0xa9,0x00,0x8d,0x04,0x03,0x8d,0x44,0x02,0xa9,0x07,
0x8d,0x05,0x03,0xa9,0x70,0x8d,0x0a,0x03,0xa9,0x01,0x8d,0x0b,0x03,0x85,0x09,0x60,
0x7d,0x8a,0x48,0x20,0x53,0xe4,0x88,0xd0,0xfa,0x68,0xaa,0x8c,0x8e,0x07,0xad,0x7d,
0x07,0xee,0x8e,0x07,0x60,0xa9,0x93,0x8d,0xe2,0x02,0xa9,0x07,0x8d,0xe3,0x02,0xa2,
0x02,0x20,0xda,0x07,0x95,0x43,0x20,0xda,0x07,0x95,0x44,0x35,0x43,0xc9,0xff,0xf0,
0xf0,0xca,0xca,0x10,0xec,0x30,0x06,0xe6,0x45,0xd0,0x02,0xe6,0x46,0x20,0xda,0x07,
0xa2,0x01,0x81,0x44,0xb5,0x45,0xd5,0x43,0xd0,0xed,0xca,0x10,0xf7,0x20,0xd2,0x07,
0x4c,0x94,0x07,0xa9,0x03,0x8d,0x0f,0xd2,0x6c,0xe2,0x02,0xad,0x8e,0x07,0xcd,0x7f,
0x07,0xd0,0xab,0xee,0x0a,0x03,0xd0,0x03,0xee,0x0b,0x03,0xad,0x7d,0x07,0x0d,0x7e,
0x07,0xd0,0x8e,0x20,0xd2,0x07,0x6c,0xe0,0x02,0x20,0xda,0x07,0x8d,0xe0,0x02,0x20,
0xda,0x07,0x8d,0xe1,0x02,0x2d,0xe0,0x02,0xc9,0xff,0xf0,0xed,0xa9,0x00,0x8d,0x8e,
0x07,0xf0,0x82
};

View File

@@ -0,0 +1,10 @@
const static uint8_t xex_loader[] =
{
0x61,0xA2,0x00,0x86,0x09,0xCA,0x9A,0xCE,0x00,0xD1,0xCE,0x0E,0xD1,0xA9,0x01,0xF0,
0xFC,0x30,0x09,0xA9,0xD1,0x48,0xA9,0x09,0x48,0x6C,0xE2,0x02,0xCE,0x00,0xD1,0x6C,
0xE0,0x02
};
#define XEX_READ_STATUS 0x0e
#define XEX_INIT1 0x01

View File

@@ -317,6 +317,20 @@ char is_c128()
return (is_c128_type == 1);
}
static int is_atari800_type = 0;
char is_atari800()
{
if (!is_atari800_type) is_atari800_type = strcasecmp(orig_name, "Atari800") ? 2 : 1;
return (is_atari800_type == 1);
}
static int is_atari5200_type = 0;
char is_atari5200()
{
if (!is_atari5200_type) is_atari5200_type = strcasecmp(orig_name, "Atari5200") ? 2 : 1;
return (is_atari5200_type == 1);
}
static int is_psx_type = 0;
char is_psx()
{
@@ -398,6 +412,8 @@ void user_io_read_core_name()
is_gba_type = 0;
is_c64_type = 0;
is_c128_type = 0;
is_atari800_type = 0;
is_atari5200_type = 0;
is_psx_type = 0;
is_cdi_type = 0;
is_st_type = 0;
@@ -1523,6 +1539,14 @@ void user_io_init(const char *path, const char *xml)
printf("Identified Archimedes core");
archie_init();
}
else if (is_atari800())
{
atari800_init();
}
else if (is_atari5200())
{
atari5200_init();
}
else
{
const char *home = HomeDir();
@@ -3667,6 +3691,8 @@ void user_io_poll()
uint16_t save_req = spi_uio_cmd(UIO_CHK_UPLOAD);
if (save_req) c64_save_cart(save_req >> 8);
}
if (is_atari800()) atari800_poll();
if (is_atari5200()) atari5200_poll();
process_ss(0);
}

View File

@@ -289,6 +289,8 @@ char is_saturn();
char is_pcxt();
char is_n64();
char is_uneon();
char is_atari800();
char is_atari5200();
#define HomeDir(x) user_io_get_core_path(x)
#define CoreName user_io_get_core_name()