Skip to content

Commit

Permalink
Support CRT v2.0 and WarpSpeed 128
Browse files Browse the repository at this point in the history
  • Loading branch information
KimJorgensen committed Feb 10, 2022
1 parent 1fde24c commit def71e3
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 76 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ The gerber files and BOM can be found [here](https://github.com/KimJorgensen/Kun
## Supported Cartridges
The following cartridge types are currently supported:

* Normal cartridge (8k, 16k, Ultimax)
* Generic cartridge (8k, 16k, Ultimax)
* Action Replay v4.x/v5/v6
* KCS Power Cartridge
* Final Cartridge III(+)
Expand All @@ -45,13 +45,15 @@ The following cartridge types are currently supported:
* Freeze Machine
* RGCD, Hucky
* Drean
* C128 Normal Cartridge (external function ROM)

* C128 Generic cartridge (external function ROM)
* WarpSpeed 128

## Supported File Types
The following file types are currently supported:

* Cartridge (CRT)
* C128 cartridge (ROM, BIN)
* C128 external function ROM (ROM, BIN)
* Disk image (D64, D71, D81)
* Tape image (T64)
* Program (PRG, P00)
Expand Down
8 changes: 5 additions & 3 deletions firmware/cartridges/cartridge.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 Kim Jørgensen
* Copyright (c) 2019-2022 Kim Jørgensen
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
Expand Down Expand Up @@ -84,7 +84,8 @@ static void (*crt_get_handler(u32 cartridge_type, bool vic_support)) (void)
return c64gs_handler;

case CRT_WARP_SPEED:
return warpspeed_handler;
case CRT_C128_WARP_SPEED:
return NTSC_OR_PAL_HANDLER(warpspeed);

case CRT_DINAMIC:
return dinamic_handler;
Expand Down Expand Up @@ -149,7 +150,8 @@ static void crt_init(DAT_CRT_HEADER *crt_header)
break;

case CRT_WARP_SPEED:
warpspeed_init();
case CRT_C128_WARP_SPEED:
warpspeed_init(crt_header);
break;

case CRT_ZAXXON_SUPER_ZAXXON:
Expand Down
37 changes: 20 additions & 17 deletions firmware/cartridges/warpspeed.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 Kim Jørgensen and Sven Oliver (SvOlli) Moll
* Copyright (c) 2019-2022 Kim Jørgensen and Sven Oliver (SvOlli) Moll
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
Expand All @@ -26,26 +26,19 @@
* - write $DF00-$DFFF turns ROM off
* still it's twice as fast as JiffyDOS and can load to RAM at $D000-$DFFF,
* and also packs a lot of features.
* the original hardware features also a C128 mode, which can't be recreated
* using a crt image.
*/

u32 warpspeed_on;

/*************************************************
* C64 bus read callback
*************************************************/
FORCE_INLINE bool warpspeed_read_handler(u32 control, u32 addr)
{
/* IO access */
if ((control & (C64_IO1|C64_IO2)) != (C64_IO1|C64_IO2))
/* IO and ROM access */
if ((control & (C64_IO1|C64_IO2|C64_ROML|C64_ROMH)) != (C64_IO1|C64_IO2|C64_ROML|C64_ROMH))
{
/* $DE00-$DFFF are a mirror of $9E00-$9FFF */
C64_DATA_WRITE(crt_ptr[addr & 0x1fff]);
return true;
}

/* ROM access */
if ((control & (C64_ROML|C64_ROMH)) != (C64_ROML|C64_ROMH))
{
C64_DATA_WRITE(crt_ptr[addr & 0x3fff]);
return true;
}
Expand All @@ -60,17 +53,27 @@ FORCE_INLINE void warpspeed_write_handler(u32 control, u32 addr, u32 data)
{
if (!(control & C64_IO1))
{
C64_CRT_CONTROL(STATUS_LED_ON|CRT_PORT_16K);
C64_CRT_CONTROL(warpspeed_on);
}
else if (!(control & C64_IO2))
{
C64_CRT_CONTROL(STATUS_LED_ON|CRT_PORT_NONE);
C64_CRT_CONTROL(STATUS_LED_OFF|CRT_PORT_NONE);
}
}

static void warpspeed_init(void)
static void warpspeed_init(DAT_CRT_HEADER *crt_header)
{
C64_CRT_CONTROL(STATUS_LED_ON|CRT_PORT_16K);
if (crt_header->type == CRT_WARP_SPEED)
{
warpspeed_on = STATUS_LED_ON|CRT_PORT_16K;
}
else // CRT_C128_WARP_SPEED
{
warpspeed_on = STATUS_LED_ON|CRT_PORT_NONE;
}

C64_CRT_CONTROL(warpspeed_on);
}

C64_BUS_HANDLER(warpspeed)
// Support C128 2MHz read access
C64_C128_BUS_HANDLER(warpspeed)
7 changes: 6 additions & 1 deletion firmware/file_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,14 @@ typedef enum {
CRT_LT_KERNAL_HOST_ADAPTOR,
CRT_RAMLINK,
CRT_DREAN,
CRT_IEEE_FLASH_64,
CRT_TURTLE_GRAPHICS_II,
CRT_FREEZE_FRAME_MK2,

// KFF specific extensions
CRT_C128_NORMAL_CARTRIDGE = 0xFF00
CRT_C128_CARTRIDGE = 0x8000,
CRT_C128_NORMAL_CARTRIDGE = CRT_C128_CARTRIDGE,
CRT_C128_WARP_SPEED
} CRT_TYPE;

typedef enum {
Expand Down
74 changes: 52 additions & 22 deletions firmware/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@
#define DAT_FILENAME "/KungFuFlash.dat"
#define UPD_FILENAME ("/KungFuFlash_v" VERSION ".upd")

#define CRT_SIGNATURE "C64 CARTRIDGE "
#define CRT_C64_SIGNATURE "C64 CARTRIDGE "
#define CRT_C128_SIGNATURE "C128 CARTRIDGE "
#define CRT_CHIP_SIGNATURE "CHIP"
#define CRT_VERSION_1_0 0x100
#define CRT_VERSION_1_1 0x101
#define CRT_VERSION_2_0 0x200

#define EAPI_OFFSET 0x3800
#define EAPI_SIZE 0x300
Expand Down Expand Up @@ -78,16 +79,28 @@ static bool crt_load_header(FIL *file, CRT_HEADER *header)
{
u32 len = file_read(file, header, sizeof(CRT_HEADER));

if (len != sizeof(CRT_HEADER) ||
memcmp(CRT_SIGNATURE, header->signature, sizeof(header->signature)) != 0)
if (len != sizeof(CRT_HEADER))
{
wrn("Unsupported CRT header\n");
return false;
}

u16 crt_type_flag = 0;
if (memcmp(CRT_C128_SIGNATURE, header->signature,
sizeof(header->signature)) == 0)
{
crt_type_flag = CRT_C128_CARTRIDGE;
}
else if (memcmp(CRT_C64_SIGNATURE, header->signature,
sizeof(header->signature)) != 0)
{
wrn("Unsupported CRT signature\n");
return false;
}

header->header_length = __REV(header->header_length);
header->version = __REV16(header->version);
header->cartridge_type = __REV16(header->cartridge_type);
header->cartridge_type = __REV16(header->cartridge_type) | crt_type_flag;

if (header->header_length != sizeof(CRT_HEADER))
{
Expand All @@ -103,7 +116,7 @@ static bool crt_load_header(FIL *file, CRT_HEADER *header)
}
}

if (header->version < CRT_VERSION_1_0 || header->version > CRT_VERSION_1_1)
if (header->version < CRT_VERSION_1_0 || header->version > CRT_VERSION_2_0)
{
wrn("Unsupported CRT version: %x\n", header->version);
return false;
Expand All @@ -115,7 +128,7 @@ static bool crt_load_header(FIL *file, CRT_HEADER *header)
static bool crt_write_header(FIL *file, u16 type, u8 exrom, u8 game, const char *name)
{
CRT_HEADER header;
memcpy(header.signature, CRT_SIGNATURE, sizeof(header.signature));
memcpy(header.signature, CRT_C64_SIGNATURE, sizeof(header.signature));
header.header_length = __REV(sizeof(CRT_HEADER));
header.version = __REV16(CRT_VERSION_1_0);
header.cartridge_type = __REV16(type);
Expand Down Expand Up @@ -186,9 +199,9 @@ static s32 crt_get_offset(CRT_CHIP_HEADER *header, u16 cartridge_type)
if (header->start_address == 0x8000 && header->image_size <= 16*1024)
{
// Suport ROML only cartridges with more than 64 banks
if(header->image_size <= 8*1024 &&
(cartridge_type == CRT_FUN_PLAY_POWER_PLAY ||
cartridge_type == CRT_MAGIC_DESK_DOMARK_HES_AUSTRALIA))
if (header->image_size <= 8*1024 &&
(cartridge_type == CRT_FUN_PLAY_POWER_PLAY ||
cartridge_type == CRT_MAGIC_DESK_DOMARK_HES_AUSTRALIA))
{
bool odd_bank = header->bank & 1;
header->bank >>= 1;
Expand All @@ -202,6 +215,10 @@ static s32 crt_get_offset(CRT_CHIP_HEADER *header, u16 cartridge_type)
}
else
{
if (cartridge_type & CRT_C128_CARTRIDGE)
{
header->bank *= 2;
}
offset = header->bank * 16*1024;
}
}
Expand All @@ -211,6 +228,12 @@ static s32 crt_get_offset(CRT_CHIP_HEADER *header, u16 cartridge_type)
{
offset = header->bank * 16*1024 + 8*1024;
}
// ROMH bank (C128)
else if (header->start_address == 0xc000 && header->image_size <= 16*1024)
{
header->bank = (header->bank * 2) + 1;
offset = header->bank * 16*1024;
}
// ROMH bank (4k Ultimax)
else if (header->start_address == 0xf000 && header->image_size == 4*1024)
{
Expand Down Expand Up @@ -701,22 +724,29 @@ static bool c64_set_mode(void)
}

u32 state = STATUS_LED_ON;
if (dat_file.crt.exrom)
{
state |= C64_EXROM_HIGH;
}
else
{
state |= C64_EXROM_LOW;
}

if (dat_file.crt.game)
if (!(dat_file.crt.type & CRT_C128_CARTRIDGE))
{
state |= C64_GAME_HIGH;
if (dat_file.crt.exrom)
{
state |= C64_EXROM_HIGH;
}
else
{
state |= C64_EXROM_LOW;
}

if (dat_file.crt.game)
{
state |= C64_GAME_HIGH;
}
else
{
state |= C64_GAME_LOW;
}
}
else
{
state |= C64_GAME_LOW;
state |= CRT_PORT_NONE;
}

C64_CRT_CONTROL(state);
Expand Down
68 changes: 38 additions & 30 deletions firmware/menu_sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,11 +505,26 @@ static bool handle_crt_supported(u32 cartridge_type)
return true;
}

sprint(scratch_buf, "Unsupported CRT type (%u)", cartridge_type);
sprint(scratch_buf, "Unsupported %s CRT type (%u)",
cartridge_type & CRT_C128_CARTRIDGE ? "C128" : "C64",
cartridge_type & (CRT_C128_CARTRIDGE-1));
handle_unsupported_ex("Unsupported", scratch_buf, dat_file.file);
return false;
}

static bool handle_c128_supported(const char *file_name, u8 flags, u8 element)
{
// Show warning on a C64
if (!(flags & SELECT_FLAG_C128) && !(flags & SELECT_FLAG_ACCEPT))
{
handle_unsupported_warning(
"Cartridge will only work on a C128", file_name, element);
return false;
}

return true;
}

static void handle_fw_not_in_root(const char *file_name)
{
handle_unsupported_ex("Unsupported",
Expand Down Expand Up @@ -559,45 +574,32 @@ static bool handle_load_file(SD_STATE *state, const char *file_name,

case FILE_ROM:
{
if (!(flags & SELECT_FLAG_ACCEPT))
{
FIL file;
handle_file_open(&file, file_name);
FIL file;
handle_file_open(&file, file_name);

if (rom_load_file(&file) &&
// Look for C128 CRT identifier
(memcmp("CBM", &dat_buffer[0x0007], 3) == 0 ||
memcmp("CBM", &dat_buffer[0x4007], 3) == 0))
if (rom_load_file(&file) &&
// Look for C128 CRT identifier
(memcmp("CBM", &dat_buffer[0x0007], 3) == 0 ||
memcmp("CBM", &dat_buffer[0x4007], 3) == 0))
{
if (!handle_crt_supported(CRT_C128_NORMAL_CARTRIDGE))
{
if (!handle_crt_supported(CRT_C128_NORMAL_CARTRIDGE))
{
break;
}

// Show warning on a C64
if (!(flags & SELECT_FLAG_C128))
{
handle_unsupported_warning(
"Cartridge will only run on a C128", file_name,
element);
}
else
{
exit_menu = true;
}
break;
}
else

if (!handle_c128_supported(file_name, flags, element))
{
handle_unsupported(file_name);
break;
}

file_close(&file);
exit_menu = true;
}
else
{
exit_menu = true;
handle_unsupported(file_name);
}

file_close(&file);

if (exit_menu)
{
c64_send_exit_menu();
Expand Down Expand Up @@ -633,6 +635,12 @@ static bool handle_load_file(SD_STATE *state, const char *file_name,
break;
}

if (header.cartridge_type & CRT_C128_CARTRIDGE &&
!handle_c128_supported(file_name, flags, element))
{
break;
}

c64_send_exit_menu();
c64_send_prg_message("Programming flash memory.");
c64_interface(false);
Expand Down

0 comments on commit def71e3

Please sign in to comment.