Skip to content

Commit

Permalink
libretro#91: Optionally create empty disk images. Also show a notific…
Browse files Browse the repository at this point in the history
…ation when DISK.ROM is required but not loaded
  • Loading branch information
cayce-msx committed Dec 27, 2021
1 parent 1b7f159 commit 3dbad7b
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 13 deletions.
2 changes: 2 additions & 0 deletions EMULib/FDIDisk.c
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,8 @@ int SaveFDI(FDIDisk *D,const char *FileName,int Format)
RFILE *F;
byte *P,*T;

if (!FileName) return(0);

/* Must have a disk to save */
if(!D->Data) return(0);

Expand Down
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ Source : http://fms.komkon.org/fMSX/
* .cas .CAS - for fMSX tape files
* .m3u .M3U - for multidisk software

The supplied location must exist and must be a readable file with one of the listed extensions. If, e.g., it points to a directory or non-existent file,
The supplied location must exist and must be a readable file with one of the listed extensions.
If, e.g., it points to a directory or non-existent file,
no image is loaded and this core will boot into MSX-BASIC. It is not possible to insert a disk into a running core.


Expand Down Expand Up @@ -45,6 +46,27 @@ Note:
* images can only be swapped in the 'eject' state


## Creating empty disk images
An MSX computer will boot into an MSX-BASIC prompt when no cartridge or executable disk is inserted.
By default, attempts to do disk I/O will then result in 'Disk offline' errors.

To create an empty disk image, which can be written to from MSX-BASIC, set both of these options:
* "Create empty disk image when none loaded": Yes (option `fmsx_phantom_disk`)
* "Save changes to .dsk": Immediate or On close (option `fmsx_flush_disk`)
Without the latter setting, changes to the created disk will be lost.

This option can also be used to create User Disks for multi-disk games.

The following situations can arise:
* _no content selected when starting core_: changes will be lost; no filename is known
* _non-existent .cas, .rom, .m3u or .fdi selected_: changes will be lost
* _non-existent .dsk image selected_: .dsk image created on host filesystem
* _non-existent file listed in .m3u_: .dsk image created on host filesystem
* _RGUI > Quick Menu > Disk Control > Disk Image Append_: RGUI enforces an _existing_ file to be chosen.
However, this can, e.g., be a zero-byte file.
As long as it has a .dsk file extension, a valid .dsk image file will be created & saved.


## Cheats
"To make cheat codes for `Game.rom`, create `Game.cht` containing codes in `00AAAAAA-DD` and `00AAAAAA-DDDD` formats, one per line.
Where `AAAAAA` is the ROM address and `DD` is the value to write there. For 16bit values, use `DDDD`.
Expand Down Expand Up @@ -77,6 +99,7 @@ A restart is required after changing most of these options.
|`fmsx_allsprites`|Show all sprites - do not emulate VDP hardware limitation|No*|Yes
|`fmsx_font`|load a fixed text font from RetroArch's `system_directory`|standard*|DEFAULT.FNT|ITALIC.FNT|INTERNAT.FNT|CYRILLIC.FNT|KOREAN.FNT|JAPANESE.FNT
|`fmsx_flush_disk`|Save changes to .dsk image|Never*|Immediate|On close
|`fmsx_phantom_disk`|Create empty disk image when none loaded|No*|Yes
|`fmsx_custom_keyboard_XXX`<br>where XXX is `up`,`down`,`left`,`right`,`a`,`b`,`y`,`x`,`start`,`select`,`l`,`r`,`l2`,`r2`,`l3`,`r3`|For User 1 Device Type 'Custom Keyboard', map RetroPad button to selected MSX keyboard key|left&vert;up&vert;right&vert;down&vert;<br>shift&vert;ctrl&vert;graph&vert;<br>backspace&vert;tab&vert;escape&vert;space&vert;capslock&vert;select&vert;home&vert;enter&vert;del&vert;insert&vert;country&vert;dead&vert;stop&vert;<br>f1&vert;f2&vert;f3&vert;f4&vert;f5&vert;<br>keypad0~9&vert;kp_multiply&vert;kp_plus&vert;kp_divide&vert;kp_minus&vert;kp_comma&vert;kp_period&vert;<br>backquote&vert;minus&vert;equals&vert;leftbracket&vert;rightbracket&vert;backslash&vert;semicolon&vert;quote&vert;comma&vert;period&vert;slash&vert;<br>0-9&vert;a-z&vert;<br>
|`fmsx_log_level`|Configure the amount of fMSX logging|Off*&vert;Info&vert;Debug&vert;Spam

Expand Down Expand Up @@ -107,12 +130,13 @@ These BIOS ROMs are required for execution:
* MSX2+: MSX2P.ROM, MSX2PEXT.ROM

Optional; loaded when found:
* DISK.ROM
* DISK.ROM - required to be able to run .dsk and .m3u images.
A notification will be shown for 10s when loading such an image without a proper DISK.ROM in place.
* FMPAC.ROM
* KANJI.ROM
* MSXDOS2.ROM (MSX2/2+)
* PAINTER.ROM (MSX2/2+) - press space during boot to start
* RS232.ROM
* RS232.ROM - although serial COM I/O is removed in this core
* CMOS.ROM
* GMASTER2.ROM, GMASTER.ROM

Expand Down
3 changes: 3 additions & 0 deletions fMSX/MSX.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ byte *SRAMData[MAXSLOTS]; /* SRAM (battery backed) */

/** Disk images used by fMSX *********************************/
const char *DSKName[MAXDRIVES] = { "DRIVEA.DSK","DRIVEB.DSK" };
byte DiskROMLoaded = 0; /* 1 when DISK.ROM loaded */

/** Fixed font used by fMSX **********************************/
const char *FNTName = "DEFAULT.FNT"; /* Font file for text */
Expand Down Expand Up @@ -439,6 +440,7 @@ int StartMSX(int NewMode,int NewRAMPages,int NewVRAMPages)
CheatsON = 0;
CheatCount = 0;
MCFCount = 0;
DiskROMLoaded = 0;

/* Zero cartridge related data */
for(J=0;J<MAXSLOTS;++J)
Expand Down Expand Up @@ -778,6 +780,7 @@ int ResetMSX(int NewMode,int NewRAMPages,int NewVRAMPages)
if(Verbose && log_cb) log_cb(RETRO_LOG_INFO," Opening DISK.ROM...");
P1=LoadROM("DISK.ROM",0x4000,0);
PRINTRESULT(P1);
DiskROMLoaded=!!P1;

/* Change to the working directory */
if(WorkDir && chdir(WorkDir))
Expand Down
53 changes: 43 additions & 10 deletions libretro.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ char *autotype=0;
#define FLUSH_NEVER 0
#define FLUSH_IMMEDIATE 1
#define FLUSH_ON_CLOSE 2
int disk_flush=FLUSH_NEVER;
static int disk_flush=FLUSH_NEVER;
static bool phantom_disk = false;

extern int MCFCount;
int current_cheat;
Expand All @@ -63,6 +64,9 @@ extern int RAMPages ;

extern int VPeriod;

extern byte DiskROMLoaded;
bool require_disk_rom = false;

#define SND_RATE 48000
#define AUDIO_BUFFER_SIZE 1024 // .78 frames at 60Hz, .94 frames at 50Hz

Expand Down Expand Up @@ -515,6 +519,7 @@ void retro_set_environment(retro_environment_t cb)
{ "fmsx_allsprites", "Show all sprites; No|Yes" },
{ "fmsx_font", "Text font; standard|DEFAULT.FNT|ITALIC.FNT|INTERNAT.FNT|CYRILLIC.FNT|KOREAN.FNT|JAPANESE.FNT" },
{ "fmsx_flush_disk", "Save changes to .dsk; Never|Immediate|On close" },
{ "fmsx_phantom_disk", "Create empty disk when none loaded; No|Yes" },
{ "fmsx_custom_keyboard_up", up_value},
{ "fmsx_custom_keyboard_down", down_value},
{ "fmsx_custom_keyboard_left", left_value},
Expand Down Expand Up @@ -577,7 +582,7 @@ void disk_flush_on_close(void)
{
if(disk_flush==FLUSH_ON_CLOSE && FDD[0].Dirty)
{
SaveFDI(&FDD[0],DSKName[0],FMT_MSXDSK);
SaveFDI(&FDD[0],DSKName_buffer,FMT_MSXDSK);
FDD[0].Dirty = 0;
}
}
Expand Down Expand Up @@ -617,17 +622,21 @@ bool set_image_index(unsigned index)
if(disk_index == disk_images)
{
//retroarch is trying to set "no disk in tray"
ChangeDisk(0, NULL);
ChangeDisk(0,NULL);
return true;
}

strncpy(DSKName_buffer, disk_paths[disk_index], PATH_MAX-1);
DSKName_buffer[PATH_MAX-1] = 0;
DSKName[0]=DSKName_buffer;
if(!ChangeDisk(0,DSKName[0]) && log_cb) {
log_cb(RETRO_LOG_ERROR, "%s %s\n", "could not load", disk_paths[disk_index]);
return false;
}
if(!ChangeDisk(0,DSKName[0]))
if (phantom_disk)
ChangeDisk(0,"");
else
{
if (log_cb) log_cb(RETRO_LOG_ERROR, "%s %s\n", "could not load", disk_paths[disk_index]);
return false;
}

return true;
}
Expand Down Expand Up @@ -923,6 +932,12 @@ static void check_variables(void)
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && strcmp(var.value, "Yes") == 0)
Mode |= MSX_PATCHBDOS;

var.key = "fmsx_phantom_disk";
var.value = NULL;

if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && strcmp(var.value, "Yes") == 0)
phantom_disk=true;

var.key = "fmsx_flush_disk";
var.value = NULL;

Expand Down Expand Up @@ -1196,6 +1211,8 @@ bool retro_load_game(const struct retro_game_info *info)
static char CasName_buffer[PATH_MAX];
struct retro_keyboard_callback keyboard_event_callback;
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
bool have_image = false;
char *dot;

if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
{
Expand Down Expand Up @@ -1243,21 +1260,25 @@ bool retro_load_game(const struct retro_game_info *info)

if (info && path_is_valid(info->path))
{
char *dot = strrchr(info->path, '.');
dot = strrchr(info->path, '.');
if (dot && ( !strcasecmp(dot, ".rom") || !strcasecmp(dot, ".mx1") || !strcasecmp(dot, ".mx2") ))
{
strcpy(ROMName_buffer, info->path);
ROMName[0]=ROMName_buffer;
have_image = true;
}
else if (dot && ( !strcasecmp(dot, ".dsk") || !strcasecmp(dot, ".fdi") ))
{
strcpy(DSKName_buffer, info->path);
DSKName[0]=DSKName_buffer;
have_image = true;
require_disk_rom = true;
}
else if (dot && !strcasecmp(dot, ".cas"))
{
strcpy(CasName_buffer, info->path);
CasName=CasName_buffer;
have_image = true;
}
else if (dot && !strcasecmp(dot, ".m3u"))
{
Expand All @@ -1269,6 +1290,8 @@ bool retro_load_game(const struct retro_game_info *info)
set_image_index(0);
disk_inserted = true;
attach_disk_swap_interface();
have_image = true;
require_disk_rom = true;
}

if (try_loading_palette(info->path, "pal") || try_loading_palette(info->path, "PAL")) {}
Expand All @@ -1277,6 +1300,7 @@ bool retro_load_game(const struct retro_game_info *info)
{
ROMName[0]=NULL;
DSKName[0]=NULL;
DSKName_buffer[0]=0;
CasName=NULL;
}

Expand All @@ -1289,14 +1313,23 @@ bool retro_load_game(const struct retro_game_info *info)
SetColor(i, 0, 0, 0);

for(i = 0; i < 256; i++)
BPal[i]=PIXEL(((i>>2)&0x07)*255/7,((i>>5)&0x07)*255/7,(i&0x03)*255/3);
BPal[i]=PIXEL(((i>>2)&0x07)*255/7,((i>>5)&0x07)*255/7,(i&0x03)*255/3);

InitSound(SND_RATE, 0);
SetChannels(255/MAXCHANNELS, (1<<MAXCHANNELS)-1);

StartMSX(Mode,RAMPages,VRAMPages);
if (!have_image && phantom_disk)
{
if (info && (dot = strrchr(info->path, '.')) && !strcasecmp(dot, ".dsk"))
strcpy(DSKName_buffer, info->path);
ChangeDisk(0,"");
require_disk_rom = true;
}
if (info) load_core_specific_cheats(info->path);
update_fps();
if (require_disk_rom && !DiskROMLoaded)
show_message("DISK.ROM not loaded; content will not start", 10 * fps);
setup_tape_autotype();
return true;
}
Expand Down Expand Up @@ -1483,7 +1516,7 @@ void retro_run(void)
// debounce 1s before flushing to .dsk
if(disk_flush==FLUSH_IMMEDIATE && FDD[0].Dirty && ++FDD[0].Dirty >= fps)
{
SaveFDI(&FDD[0],DSKName[0],FMT_MSXDSK);
SaveFDI(&FDD[0],DSKName_buffer,FMT_MSXDSK);
FDD[0].Dirty = 0;
}
}
Expand Down

0 comments on commit 3dbad7b

Please sign in to comment.