Skip to content

Commit

Permalink
v1.2.1, disk interface added
Browse files Browse the repository at this point in the history
Implemented interface for disk (and, actually, tape image) swapping.
Not really useful for Enterprise due to lack of multi-disk content,
but works for CPC disks, and ZX tapes.
  • Loading branch information
zoltanvb committed Oct 18, 2022
1 parent 8bde6e8 commit acf821e
Show file tree
Hide file tree
Showing 2 changed files with 194 additions and 41 deletions.
183 changes: 168 additions & 15 deletions core/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ virtual keyboard
core options v2 https://github.com/libretro/libretro-common/tree/master/samples/core_options
check and include libretro common
detailed type detection from content name
m3u (or, rather, name-based autodetect) multi-disk, multi-tape interface support (cpc 3 guerra)
locale support ep, cpc
rom config for clkoff+hfont
Expand All @@ -42,6 +41,7 @@ EP Mouse support
achievement support
test mp3 support with sndfile 1.1 - cmake won't find lame / mpeg123 when compiling libsndfile
led driver for tape / disk loading - see comments inside
name-based autodetect for multi-disk, multi-tape interface support (cpc 3 guerra)
*/

Expand Down Expand Up @@ -104,15 +104,25 @@ retro_usec_t prev_frame_time = 0;
float waitPeriod = 0.001;
bool useSwFb = false;
bool useHalfFrame = false;
bool enableDiskControl = false;
bool needsDiskControl = false;
int borderSize = 0;
bool soundHq = true;
unsigned maxUsers;
bool maxUsersSupported = true;
bool canSkipFrames = false;
bool enhancedRom = false;

unsigned maxUsers;
bool maxUsersSupported = true;

unsigned diskIndex = 0;
unsigned diskCount = 1;
#define MAX_DISK_COUNT 6
std::string diskPaths[MAX_DISK_COUNT];
std::string diskNames[MAX_DISK_COUNT];
bool diskEjected = false;

bool tapeContent = false;
bool diskContent = false;
bool fileContent = false;

Ep128Emu::VMThread *vmThread = (Ep128Emu::VMThread *) 0;
Ep128Emu::EmulatorConfiguration *config = (Ep128Emu::EmulatorConfiguration *) 0;
Ep128Emu::LibretroCore *core = (Ep128Emu::LibretroCore *) 0;
Expand Down Expand Up @@ -293,6 +303,117 @@ static void check_variables(void)
if(vmThread) vmThread->resetKeyboard();
}

/* If ejected is true, "ejects" the virtual disk tray.
*/
static bool set_eject_state_cb(bool ejected) {
log_cb(RETRO_LOG_DEBUG, "Disk control: eject (%d)\n",ejected?1:0);
diskEjected = ejected;
return true;
}

/* Gets current eject state. The initial state is 'not ejected'. */
static bool get_eject_state_cb(void) {
// log_cb(RETRO_LOG_DEBUG, "Disk control: get eject status (%d)\n",diskEjected?1:0);
return diskEjected;
}

/* Gets current disk index. First disk is index 0.
* If return value is >= get_num_images(), no disk is currently inserted.
*/
static unsigned get_image_index_cb(void) {
// log_cb(RETRO_LOG_DEBUG, "Disk control: get image index (%d)\n",diskIndex);
if (diskEjected) return diskCount + 1;
return diskIndex;
}

/* Sets image index. Can only be called when disk is ejected.
*/
static bool set_image_index_cb(unsigned index) {
log_cb(RETRO_LOG_DEBUG, "Disk control: change image to (%d)\n",index);
if (index>=diskCount) {
diskIndex = diskCount + 1;
} else {
diskIndex = index;
if (core) {
config = core->config;
if(diskContent) {
config->floppy.a.imageFile = diskPaths[index];
config->floppyAChanged = true;
log_cb(RETRO_LOG_DEBUG, "Disk control: new disk is %s\n",diskPaths[index].c_str());
} else if(tapeContent) {
config->tape.imageFile = diskPaths[index];
config->tapeFileChanged = true;
log_cb(RETRO_LOG_DEBUG, "Disk control: new tape is %s\n",diskPaths[index].c_str());
}
config->applySettings();
}
}
return true;
}

/* Gets total number of images which are available to use. */
static unsigned get_num_images_cb(void) {return diskCount;}

/* Replaces the disk image associated with index.
* Arguments to pass in info have same requirements as retro_load_game().
*/
static bool replace_image_index_cb(unsigned index,
const struct retro_game_info *info) {

log_cb(RETRO_LOG_DEBUG, "Disk control: replace image index (%d) to %s\n",index,info->path);
if (index >= diskCount) return false;
diskPaths[index] = info->path;
std::string contentPath;
Ep128Emu::splitPath(diskPaths[index],contentPath,diskNames[index]);
return true;
}

/* Adds a new valid index (get_num_images()) to the internal disk list.
* This will increment subsequent return values from get_num_images() by 1.
* This image index cannot be used until a disk image has been set
* with replace_image_index. */
static bool add_image_index_cb(void) {
log_cb(RETRO_LOG_DEBUG, "Disk control: add image index (current %d)\n",diskCount);
if (diskCount >= MAX_DISK_COUNT) return false;
diskCount++;
return true;
}

/* Sets initial image to insert in drive when calling
* core_load_game().
* Returns 'false' if index or 'path' are invalid, or core
* does not support this functionality
*/
static bool set_initial_image_cb(unsigned index, const char *path) {return false;}

/* Fetches the path of the specified disk image file.
* Returns 'false' if index is invalid (index >= get_num_images())
* or path is otherwise unavailable.
*/
static bool get_image_path_cb(unsigned index, char *path, size_t len) {
if (index >= diskCount) return false;
if(diskPaths[index].length() > 0)
path=(char*)diskPaths[index].c_str();
len=diskPaths[index].length();
log_cb(RETRO_LOG_DEBUG, "Disk control: get image path (%d) %s\n",index,path);
return true;
}

/* Fetches a core-provided 'label' for the specified disk
* image file. In the simplest case this may be a file name
* Returns 'false' if index is invalid (index >= get_num_images())
* or label is otherwise unavailable.
*/
static bool get_image_label_cb(unsigned index, char *label, size_t len) {
if(index >= diskCount) return false;
if(diskNames[index].length() > 0)
label=(char*)diskNames[index].c_str();
len=diskNames[index].length();
//log_cb(RETRO_LOG_DEBUG, "Disk control: get image label (%d) %s\n",index,label);
return true;
}


void retro_init(void)
{
struct retro_log_callback log;
Expand All @@ -303,12 +424,42 @@ void retro_init(void)
else
log_cb = fallback_log;

// actually it is the advanced disk control...
struct retro_disk_control_callback dccb =
{
set_eject_state_cb,
get_eject_state_cb,

get_image_index_cb,
set_image_index_cb,
get_num_images_cb,

replace_image_index_cb,
add_image_index_cb
};

struct retro_disk_control_ext_callback dccb_ext =
{
set_eject_state_cb,
get_eject_state_cb,

get_image_index_cb,
set_image_index_cb,
get_num_images_cb,

replace_image_index_cb,
add_image_index_cb,
set_initial_image_cb,

get_image_path_cb,
get_image_label_cb
};

unsigned dci;
if (environ_cb(RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION, &dci))
enableDiskControl = true;
else
enableDiskControl = false;
if (environ_cb(RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION, &dci)) {
environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE, &dccb_ext);
} else {
environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &dccb);
}

/* struct retro_led_interface led_interface;
if(environ_cb(RETRO_ENVIRONMENT_GET_LED_INTERFACE, &led_interface)) {
Expand Down Expand Up @@ -366,7 +517,7 @@ void retro_init(void)
sizeof(retro_system_save_directory) - 1
);

log_cb(RETRO_LOG_INFO, "Retro ROM DIRECTORY %s\n", retro_system_bios_directory);
log_cb(RETRO_LOG_DEBUG, "Retro ROM DIRECTORY %s\n", retro_system_bios_directory);
log_cb(RETRO_LOG_DEBUG, "Retro SAVE_DIRECTORY %s\n", retro_system_save_directory);
log_cb(RETRO_LOG_DEBUG, "Retro CONTENT_DIRECTORY %s\n", retro_content_directory);

Expand Down Expand Up @@ -421,7 +572,7 @@ void retro_get_system_info(struct retro_system_info *info)
{
memset(info, 0, sizeof(*info));
info->library_name = "ep128emu";
info->library_version = "v1.2.0";
info->library_version = "v1.2.1";
info->need_fullpath = true;
info->valid_extensions = "img|dsk|tap|dtf|com|trn|128|bas|cas|cdt|tzx|wav|tvcwav|.";
}
Expand Down Expand Up @@ -642,6 +793,8 @@ bool retro_load_game(const struct retro_game_info *info)
log_cb(RETRO_LOG_DEBUG, "Content extension: %s \n",contentExt.c_str());
Ep128Emu::splitPath(filename,contentPath,contentFile);
contentBasename = contentFile;
diskPaths[0] = filename;
diskNames[0] = contentBasename;
Ep128Emu::stringToLowerCase(contentBasename);

int contentLocale = Ep128Emu::LOCALE_UK;
Expand Down Expand Up @@ -720,9 +873,9 @@ bool retro_load_game(const struct retro_game_info *info)
// - 0xfe as "
// - 0xfd as F1 (START)
const char* startupSequence = "";
bool tapeContent = false;
bool diskContent = false;
bool fileContent = false;
tapeContent = false;
diskContent = false;
fileContent = false;
int detectedMachineDetailedType = Ep128Emu::VM_config.at("VM_CONFIG_UNKNOWN");

// start with longer magic strings - less chance of mis-detection
Expand Down
52 changes: 26 additions & 26 deletions ep128emu_core_libretro.info
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ license = "GPLv2"
permissions = ""

# Version of the core:
display_version = "v1.2.0"
display_version = "v1.2.1"

# Hardware Information - Information about the hardware the core supports (when applicable)
# Name of the manufacturer who produced the emulated system:
Expand All @@ -48,91 +48,91 @@ firmware_count = 22
# firmware0_opt = "true/false"

firmware0_desc = "exos21.rom (Enterprise 128 Expandible OS 2.1)"
firmware0_path = "ep128emu/roms/exos21.rom";
firmware0_path = "ep128emu/roms/exos21.rom"
firmware0_opt = "true"

firmware1_desc = "basic21.rom (Enterprise 128 BASIC Interpreter v2.1)"
firmware1_path = "ep128emu/roms/basic21.rom";
firmware1_path = "ep128emu/roms/basic21.rom"
firmware1_opt = "true"

firmware2_desc = "exdos13.rom (Enterprise 128 Disk Controller v1.3)"
firmware2_path = "ep128emu/roms/exdos13.rom";
firmware2_path = "ep128emu/roms/exdos13.rom"
firmware2_opt = "true"

firmware3_desc = "exos20.rom (Enterprise 64 Expandible OS 2.0)"
firmware3_path = "ep128emu/roms/exos20.rom";
firmware3_path = "ep128emu/roms/exos20.rom"
firmware3_opt = "true"

firmware4_desc = "basic20.rom (Enterprise 64 BASIC Interpreter v2.0)"
firmware4_path = "ep128emu/roms/basic20.rom";
firmware4_path = "ep128emu/roms/basic20.rom"
firmware4_opt = "true"

firmware5_desc = "epfileio.rom (Enterprise 128 Direct File I/O)"
firmware5_path = "ep128emu/roms/epfileio.rom";
firmware5_path = "ep128emu/roms/epfileio.rom"
firmware5_opt = "true"

firmware6_desc = "exos24uk.rom (Enterprise 128 Expandible OS 2.4)"
firmware6_path = "ep128emu/roms/exos24uk.rom";
firmware6_path = "ep128emu/roms/exos24uk.rom"
firmware6_opt = "true"

firmware7_desc = "hun.rom (Enterprise 128 Hungarian language extension)"
firmware7_path = "ep128emu/roms/hun.rom";
firmware7_path = "ep128emu/roms/hun.rom"
firmware7_opt = "true"

firmware8_desc = "epd19hft.rom (Enterprise 128 EP-DOS with Hungarian language extension)"
firmware8_path = "ep128emu/roms/epd19hft.rom";
firmware8_path = "ep128emu/roms/epd19hft.rom"
firmware8_opt = "true"

firmware9_desc = "zt19hfnt.rom (Enterprise 128 ZozoTools with Hungarian language extension 1.9)"
firmware9_path = "ep128emu/roms/zt19hfnt.rom";
firmware9_path = "ep128emu/roms/zt19hfnt.rom"
firmware9_opt = "true"

firmware10_desc = "brd.rom (Enterprise 128 German language extension)"
firmware10_path = "ep128emu/roms/brd.rom";
firmware10_path = "ep128emu/roms/brd.rom"
firmware10_opt = "true"

firmware11_desc = "zt19uk.rom (Enterprise 128 ZozoTools extension)"
firmware11_path = "ep128emu/roms/zt19uk.rom";
firmware11_path = "ep128emu/roms/zt19uk.rom"
firmware11_opt = "true"

firmware12_desc = "tvc22_sys.rom (Videoton TVC system BIOS)"
firmware12_path = "ep128emu/roms/tvc22_sys.rom";
firmware12_path = "ep128emu/roms/tvc22_sys.rom"
firmware12_opt = "true"

firmware13_desc = "tvc22_ext.rom (Videoton TVC extension BIOS)"
firmware13_path = "ep128emu/roms/tvc22_ext.rom";
firmware13_path = "ep128emu/roms/tvc22_ext.rom"
firmware13_opt = "true"

firmware14_desc = "tvcfileio.rom (Videoton TVC Direct File I/O)"
firmware14_path = "ep128emu/roms/tvcfileio.rom";
firmware14_path = "ep128emu/roms/tvcfileio.rom"
firmware14_opt = "true"

firmware15_desc = "tvc_dos12d.rom (Videoton TVC disk BIOS)"
firmware15_path = "ep128emu/roms/tvc_dos12d.rom";
firmware15_path = "ep128emu/roms/tvc_dos12d.rom"
firmware15_opt = "true"

firmware16_desc = "cpc464.rom (Amstrad CPC 464 BIOS)"
firmware16_path = "ep128emu/roms/cpc464.rom";
firmware16_path = "ep128emu/roms/cpc464.rom"
firmware16_opt = "true"

firmware17_desc = "cpc664.rom (Amstrad CPC 664 BIOS)"
firmware17_path = "ep128emu/roms/cpc664.rom";
firmware17_path = "ep128emu/roms/cpc664.rom"
firmware17_opt = "true"

firmware18_desc = "cpc6128.rom (Amstrad CPC 6128 BIOS)"
firmware18_path = "ep128emu/roms/cpc6128.rom";
firmware18_path = "ep128emu/roms/cpc6128.rom"
firmware18_opt = "true"

firmware19_desc = "cpc_amsdos.rom (Amstrad CPC AMSDOS BIOS)"
firmware19_path = "ep128emu/roms/cpc_amsdos.rom";
firmware19_path = "ep128emu/roms/cpc_amsdos.rom"
firmware19_opt = "true"

firmware20_desc = "zx128.rom (ZX Spectrum 128 BIOS)"
firmware20_path = "ep128emu/roms/zx128.rom";
firmware20_path = "ep128emu/roms/zx128.rom"
firmware20_opt = "true"

firmware21_desc = "zx48.rom (ZX Spectrum 48 BIOS)"
firmware21_path = "ep128emu/roms/zx48.rom";
firmware21_path = "ep128emu/roms/zx48.rom"
firmware21_opt = "true"

# Additional notes:
Expand All @@ -145,11 +145,11 @@ savestate = "true"
# If true, how complete is the savestate support? basic, serialized (rewind), deterministic (netplay/runahead)
savestate_features = "serialized"
# Does the core support the libretro cheat interface?
cheats = "false"
cheats = "true"
# Does the core support libretro input descriptors
input_descriptors = "true"
# Does the core support memory descriptors commonly used for achievements
memory_descriptors = "false"
memory_descriptors = "true"
# Does the core use the libretro save interface or does it do its own thing (like with shared memory cards)?
libretro_saves = "true"
# Does the core support the core options interface?
Expand All @@ -171,7 +171,7 @@ hw_render = "false"
# Does the core require ongoing access to the file after loading? Mostly used for softpatching and streaming of data
needs_fullpath = "true"
# Does the core support the libretro disk control interface for swapping disks on the fly?
disk_control = "false"
disk_control = "true"
# Is the core currently suitable for general use? That is, will regular users find it useful or is it for development/testing only (subject to change over time)?
is_experimental = "false"

Expand Down

0 comments on commit acf821e

Please sign in to comment.