mirror of
https://github.com/libretro/hatari.git
synced 2026-11-07 10:36:00 -10:00
Add disk control to retro core / insert disk b
This commit is contained in:
1 parent
eed8c201dd
commit
15f1fa925a
4 files changed
+291
-1
No files matched your search
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user