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:
committed by
GitHub
parent
a9eb1f5c11
commit
deb43cd870
@@ -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" />
|
||||
|
||||
@@ -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
109
menu.cpp
@@ -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 */
|
||||
/******************************************************************/
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
15
support/atari8bit/asm/Makefile
Normal file
15
support/atari8bit/asm/Makefile
Normal 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
|
||||
BIN
support/atari8bit/asm/boot3.rom
Normal file
BIN
support/atari8bit/asm/boot3.rom
Normal file
Binary file not shown.
BIN
support/atari8bit/asm/hsio_pbi.xex
Normal file
BIN
support/atari8bit/asm/hsio_pbi.xex
Normal file
Binary file not shown.
206
support/atari8bit/asm/pbi_bios.asm
Normal file
206
support/atari8bit/asm/pbi_bios.asm
Normal 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
|
||||
40
support/atari8bit/asm/process_xex_loader.py
Normal file
40
support/atari8bit/asm/process_xex_loader.py
Normal 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()
|
||||
16
support/atari8bit/asm/xex_loader.asm
Normal file
16
support/atari8bit/asm/xex_loader.asm
Normal 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)
|
||||
284
support/atari8bit/atari5200.cpp
Normal file
284
support/atari8bit/atari5200.cpp
Normal 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();
|
||||
}
|
||||
14
support/atari8bit/atari5200.h
Normal file
14
support/atari8bit/atari5200.h
Normal 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
|
||||
2190
support/atari8bit/atari800.cpp
Normal file
2190
support/atari8bit/atari800.cpp
Normal file
File diff suppressed because it is too large
Load Diff
15
support/atari8bit/atari800.h
Normal file
15
support/atari8bit/atari800.h
Normal 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
|
||||
43
support/atari8bit/atari8bit_defs.h
Normal file
43
support/atari8bit/atari8bit_defs.h
Normal 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
|
||||
18
support/atari8bit/boot_xex_loader.h
Normal file
18
support/atari8bit/boot_xex_loader.h
Normal 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
|
||||
};
|
||||
10
support/atari8bit/xex_loader.h
Normal file
10
support/atari8bit/xex_loader.h
Normal 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
|
||||
|
||||
26
user_io.cpp
26
user_io.cpp
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user