Add disk control to retro core / insert disk b

This commit is contained in:
Craig Carnell authored and Thomas Huth committed 2026-10-18 18:17:57 +02:00
1 parent eed8c201dd
commit 15f1fa925a
4 files changed
+291 -1

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
include_directories(. ../.. ../includes ../debug ../falcon)
add_library(UiRetro OBJECT audio.c joy_ui.c gui_event.c keymap.c main_retro.c
add_library(UiRetro OBJECT audio.c disk_control.c joy_ui.c gui_event.c keymap.c main_retro.c
microphone.c options.c screen.c statusbar.c timing.c)
target_include_directories(UiRetro PRIVATE ${LIBRETRO_INCLUDE_DIR})
set_target_properties(UiRetro PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
+264
View File
@@ -0,0 +1,264 @@
/*
Hatari - disk_control.c
This file is distributed under the GNU General Public License, version 2
or at your option any later version. Read the file gpl.txt for details.
*/
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <libretro.h>
#include "main.h"
#include "main_retro.h"
#include "disk_control.h"
#include "file.h"
#include "floppy.h"
#include "log.h"
typedef struct
{
char path[FILENAME_MAX];
char label[FILENAME_MAX];
} DISKCONTROL_IMAGE;
static DISKCONTROL_IMAGE *DiskImages;
static unsigned int DiskImagesCount;
static unsigned int DiskImagesAllocated;
static unsigned int CurrentImageIndex;
static bool bTrayEjected;
/**
* Make sure there is room
*/
static bool DiskControl_EnsureCapacity(unsigned int count)
{
unsigned int newcap;
DISKCONTROL_IMAGE *newarr;
if (count <= DiskImagesAllocated)
return true;
newcap = DiskImagesAllocated ? DiskImagesAllocated * 2 : 4;
if (newcap < count)
newcap = count;
newarr = realloc(DiskImages, newcap * sizeof(DISKCONTROL_IMAGE));
if (!newarr)
{
Log_Printf(LOG_ERROR, "DiskControl: out of memory growing image list\n");
return false;
}
DiskImages = newarr;
DiskImagesAllocated = newcap;
return true;
}
/**
* Derive a display label
*/
static void DiskControl_UpdateLabel(unsigned int idx)
{
const char *base;
if (!DiskImages[idx].path[0])
{
DiskImages[idx].label[0] = '\0';
return;
}
base = File_Basename(DiskImages[idx].path);
strncpy(DiskImages[idx].label, base, sizeof(DiskImages[idx].label) - 1);
DiskImages[idx].label[sizeof(DiskImages[idx].label) - 1] = '\0';
}
/**
* (Re-)insert the image at CurrentImageIndex into floppy drive A
*/
static void DiskControl_ApplyCurrentImage(void)
{
/* clear drive B first if using manual disk control */
Floppy_SetDiskFileNameNone(1);
Floppy_EjectDiskFromDrive(1);
if (CurrentImageIndex < DiskImagesCount && DiskImages[CurrentImageIndex].path[0])
{
if (Floppy_SetDiskFileName(0, DiskImages[CurrentImageIndex].path, NULL))
Floppy_InsertDiskIntoDrive(0);
else
Log_Printf(LOG_ERROR, "DiskControl: failed to set/insert '%s' "
"into drive A\n", DiskImages[CurrentImageIndex].path);
}
else
{
Floppy_SetDiskFileNameNone(0);
Floppy_EjectDiskFromDrive(0);
}
}
/*----------------------------------------------------------------------*/
/* libretro callbacks */
/*----------------------------------------------------------------------*/
static bool RETRO_CALLCONV DiskControl_SetEjectState(bool ejected)
{
if (ejected == bTrayEjected)
return true;
if (ejected)
Floppy_EjectDiskFromDrive(0);
else
DiskControl_ApplyCurrentImage();
bTrayEjected = ejected;
return true;
}
static bool RETRO_CALLCONV DiskControl_GetEjectState(void)
{
return bTrayEjected;
}
static unsigned RETRO_CALLCONV DiskControl_GetImageIndex(void)
{
return CurrentImageIndex;
}
static bool RETRO_CALLCONV DiskControl_SetImageIndex(unsigned int index)
{
/* Only allow swapping while the tray is open */
if (!bTrayEjected)
return false;
if (DiskImagesCount == 0 || index >= DiskImagesCount)
return false;
CurrentImageIndex = index;
return true;
}
static unsigned RETRO_CALLCONV DiskControl_GetNumImages(void)
{
return DiskImagesCount;
}
static bool RETRO_CALLCONV DiskControl_ReplaceImageIndex(unsigned int index,
const struct retro_game_info *info)
{
unsigned int i;
if (index >= DiskImagesCount || !bTrayEjected)
return false;
if (!info)
{
/* NULL means: remove this image from the list */
for (i = index; i + 1 < DiskImagesCount; i++)
DiskImages[i] = DiskImages[i + 1];
DiskImagesCount--;
if (CurrentImageIndex >= DiskImagesCount && DiskImagesCount > 0)
CurrentImageIndex = DiskImagesCount - 1;
return true;
}
if (!info->path)
return false;
strncpy(DiskImages[index].path, info->path, sizeof(DiskImages[index].path) - 1);
DiskImages[index].path[sizeof(DiskImages[index].path) - 1] = '\0';
DiskControl_UpdateLabel(index);
return true;
}
static bool RETRO_CALLCONV DiskControl_AddImageIndex(void)
{
if (!DiskControl_EnsureCapacity(DiskImagesCount + 1))
return false;
DiskImages[DiskImagesCount].path[0] = '\0';
DiskImages[DiskImagesCount].label[0] = '\0';
DiskImagesCount++;
return true;
}
static bool RETRO_CALLCONV DiskControl_CB_SetInitialImage(unsigned int index, const char *path)
{
(void)path;
if (DiskImagesCount && index < DiskImagesCount)
CurrentImageIndex = index;
return true;
}
static bool RETRO_CALLCONV DiskControl_GetImagePath(unsigned int index, char *path, size_t len)
{
if (index >= DiskImagesCount || !DiskImages[index].path[0] || len == 0)
return false;
strncpy(path, DiskImages[index].path, len - 1);
path[len - 1] = '\0';
return true;
}
static bool RETRO_CALLCONV DiskControl_GetImageLabel(unsigned int index, char *label, size_t len)
{
if (index >= DiskImagesCount || !DiskImages[index].label[0] || len == 0)
return false;
strncpy(label, DiskImages[index].label, len - 1);
label[len - 1] = '\0';
return true;
}
static struct retro_disk_control_ext_callback DiskControlCallbacks =
{
DiskControl_SetEjectState,
DiskControl_GetEjectState,
DiskControl_GetImageIndex,
DiskControl_SetImageIndex,
DiskControl_GetNumImages,
DiskControl_ReplaceImageIndex,
DiskControl_AddImageIndex,
DiskControl_CB_SetInitialImage,
DiskControl_GetImagePath,
DiskControl_GetImageLabel
};
/*----------------------------------------------------------------------*/
/* API */
/*----------------------------------------------------------------------*/
void DiskControl_Init(void)
{
if (!environment_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE,
&DiskControlCallbacks))
{
Log_Printf(LOG_WARN, "DiskControl: frontend does not support the "
"extended disk control interface, disk swapping via "
"the frontend won't be available.\n");
}
}
void DiskControl_NewGame(const char *path)
{
DiskImagesCount = 0;
CurrentImageIndex = 0;
bTrayEjected = false;
if (path && path[0] && DiskControl_EnsureCapacity(1))
{
strncpy(DiskImages[0].path, path, sizeof(DiskImages[0].path) - 1);
DiskImages[0].path[sizeof(DiskImages[0].path) - 1] = '\0';
DiskControl_UpdateLabel(0);
DiskImagesCount = 1;
}
}
void DiskControl_UnInit(void)
{
free(DiskImages);
DiskImages = NULL;
DiskImagesCount = 0;
DiskImagesAllocated = 0;
CurrentImageIndex = 0;
bTrayEjected = false;
}
+14
View File
@@ -0,0 +1,14 @@
/*
Hatari - disk_control.h
This file is distributed under the GNU General Public License, version 2
or at your option any later version. Read the file gpl.txt for details.
*/
#ifndef HATARI_RETRO_DISK_CONTROL_H
#define HATARI_RETRO_DISK_CONTROL_H
void DiskControl_Init(void);
void DiskControl_NewGame(const char *path);
void DiskControl_UnInit(void);
#endif /* HATARI_RETRO_DISK_CONTROL_H */
+12
View File
@@ -9,6 +9,7 @@
#include "main_retro.h"
#include "hatari-glue.h"
#include "dialog.h"
#include "disk_control.h"
#include "floppy.h"
#include "m68000.h"
#include "options.h"
@@ -74,6 +75,9 @@ RETRO_API void retro_init(void)
char *argv[4];
const char *system_dir = NULL;
/* Register disk control */
DiskControl_Init();
argv[0] = name;
if (environment_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &system_dir) && system_dir)
@@ -205,6 +209,12 @@ RETRO_API bool retro_load_game(const struct retro_game_info *game)
Floppy_InsertDiskIntoDrive(0);
// insert disk B also
if (ConfigureParams.DiskImage.szDiskFileName[1][0])
Floppy_InsertDiskIntoDrive(1);
DiskControl_NewGame(game ? game->path : NULL);
return true;
}
@@ -216,6 +226,8 @@ RETRO_API bool retro_load_game_special(unsigned game_type, const struct retro_ga
RETRO_API void retro_unload_game(void)
{
Floppy_EjectDiskFromDrive(0);
DiskControl_UnInit();
}
RETRO_API unsigned retro_get_region(void)