Merge pull request #6801 from jriwanek-forks/ls120

Bring jriwanek LS-120 work
This commit is contained in:
Miran Grča
2026-02-11 10:59:36 +01:00
committed by GitHub
51 changed files with 3352 additions and 28 deletions

View File

@@ -91,6 +91,7 @@
#include <86box/cdrom.h>
#include <86box/cdrom_interface.h>
#include <86box/rdisk.h>
#include <86box/superdisk.h>
#include <86box/mo.h>
#include <86box/scsi_disk.h>
#include <86box/cdrom_image.h>
@@ -1292,6 +1293,7 @@ usage:
mouse_init();
cdrom_global_init();
rdisk_global_init();
superdisk_global_init();
mo_global_init();
/* Initialize the keyboard accelerator list with default values */
@@ -1651,6 +1653,8 @@ pc_reset_hard_close(void)
rdisk_close();
superdisk_close();
mo_close();
scsi_disk_close();
@@ -1767,7 +1771,7 @@ pc_reset_hard_init(void)
mo_hard_reset();
rdisk_hard_reset();
superdisk_hard_reset();
/* Reset any ISA ROM cards. */
isarom_reset();
@@ -1937,6 +1941,8 @@ pc_close(UNUSED(thread_t *ptr))
rdisk_close();
superdisk_close();
mo_close();
scsi_disk_close();

View File

@@ -127,6 +127,7 @@ target_link_libraries(86Box
game
cdrom
rdisk
superdisk
mo
hdd
net

View File

@@ -74,6 +74,7 @@
#include <86box/cdrom.h>
#include <86box/cdrom_interface.h>
#include <86box/rdisk.h>
#include <86box/superdisk.h>
#include <86box/mo.h>
#include <86box/sound.h>
#include <86box/midi.h>
@@ -1956,6 +1957,118 @@ load_other_removable_devices(void)
}
go_to_mo:
memset(temp, 0x00, sizeof(temp));
for (c = 0; c < SUPERDISK_NUM; c++) {
sprintf(temp, "superdisk_%02i_parameters", c + 1);
p = ini_section_get_string(cat, temp, NULL);
if (p != NULL)
sscanf(p, "%01u, %s", &superdisk_drives[c].is_240, s);
else
sscanf("0, none", "%01u, %s", &superdisk_drives[c].is_240, s);
superdisk_drives[c].bus_type = hdd_string_to_bus(s, 1);
/* Default values, needed for proper operation of the Settings dialog. */
superdisk_drives[c].ide_channel = superdisk_drives[c].scsi_device_id = c + 2;
if (superdisk_drives[c].bus_type == SUPERDISK_BUS_ATAPI) {
sprintf(temp, "superdisk_%02i_ide_channel", c + 1);
sprintf(tmp2, "%01u:%01u", (c + 2) >> 1, (c + 2) & 1);
p = ini_section_get_string(cat, temp, tmp2);
sscanf(p, "%01u:%01u", &board, &dev);
board &= 3;
dev &= 1;
superdisk_drives[c].ide_channel = (board << 1) + dev;
if (superdisk_drives[c].ide_channel > 7)
superdisk_drives[c].ide_channel = 7;
} else if (superdisk_drives[c].bus_type == SUPERDISK_BUS_SCSI) {
sprintf(temp, "superdisk_%02i_scsi_location", c + 1);
sprintf(tmp2, "%01u:%02u", SCSI_BUS_MAX, c + 2);
p = ini_section_get_string(cat, temp, tmp2);
sscanf(p, "%01u:%02u", &board, &dev);
if (board >= SCSI_BUS_MAX) {
/* Invalid bus - check legacy ID */
sprintf(temp, "superdisk_%02i_scsi_id", c + 1);
superdisk_drives[c].scsi_device_id = ini_section_get_int(cat, temp, c + 2);
if (superdisk_drives[c].scsi_device_id > 15)
superdisk_drives[c].scsi_device_id = 15;
} else {
board %= SCSI_BUS_MAX;
dev &= 15;
superdisk_drives[c].scsi_device_id = (board << 4) + dev;
}
}
if (superdisk_drives[c].bus_type != SUPERDISK_BUS_ATAPI) {
sprintf(temp, "superdisk_%02i_ide_channel", c + 1);
ini_section_delete_var(cat, temp);
}
if (superdisk_drives[c].bus_type != SUPERDISK_BUS_SCSI) {
sprintf(temp, "superdisk_%02i_scsi_location", c + 1);
ini_section_delete_var(cat, temp);
}
sprintf(temp, "superdisk_%02i_scsi_id", c + 1);
ini_section_delete_var(cat, temp);
sprintf(temp, "superdisk_%02i_image_path", c + 1);
p = ini_section_get_string(cat, temp, "");
if (!strcmp(p, usr_path))
p[0] = 0x00;
if (p[0] != 0x00) {
if (path_abs(p)) {
if (strlen(p) > 511)
fatal("Configuration: Length of superdisk_%02i_image_path is more than 511\n", c + 1);
else
strncpy(superdisk_drives[c].image_path, p, 511);
} else
path_append_filename(superdisk_drives[c].image_path, usr_path, p);
path_normalize(superdisk_drives[c].image_path);
}
for (int i = 0; i < MAX_PREV_IMAGES; i++) {
superdisk_drives[c].image_history[i] = (char *) calloc((MAX_IMAGE_PATH_LEN + 1) << 1, sizeof(char));
sprintf(temp, "superdisk_%02i_image_history_%02i", c + 1, i + 1);
p = ini_section_get_string(cat, temp, NULL);
if (p) {
if (path_abs(p)) {
if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1))
fatal("Configuration: Length of superdisk_%02i_image_history_%02i is more than %i\n",
c + 1, i + 1, MAX_IMAGE_PATH_LEN - 1);
else
snprintf(superdisk_drives[c].image_history[i], MAX_IMAGE_PATH_LEN, "%s", p);
} else
snprintf(superdisk_drives[c].image_history[i], MAX_IMAGE_PATH_LEN, "%s%s%s", usr_path,
path_get_slash(usr_path), p);
path_normalize(superdisk_drives[c].image_history[i]);
}
}
/* If the SuperDisk drive is disabled, delete all its variables. */
if (superdisk_drives[c].bus_type == SUPERDISK_BUS_DISABLED) {
sprintf(temp, "superdisk_%02i_parameters", c + 1);
ini_section_delete_var(cat, temp);
sprintf(temp, "superdisk_%02i_ide_channel", c + 1);
ini_section_delete_var(cat, temp);
sprintf(temp, "superdisk_%02i_scsi_location", c + 1);
ini_section_delete_var(cat, temp);
sprintf(temp, "superdisk_%02i_image_path", c + 1);
ini_section_delete_var(cat, temp);
for (int i = 0; i < MAX_PREV_IMAGES; i++) {
sprintf(temp, "superdisk_%02i_image_history_%02i", c + 1, i + 1);
ini_section_delete_var(cat, temp);
}
}
}
memset(temp, 0x00, sizeof(temp));
for (c = 0; c < MO_NUM; c++) {
sprintf(temp, "mo_%02i_parameters", c + 1);
@@ -2231,6 +2344,7 @@ config_load(void)
memset(cdrom_ioctl, 0, sizeof(cdrom_ioctl_t) * CDROM_NUM);
#endif
memset(rdisk_drives, 0, sizeof(rdisk_drive_t));
memset(superdisk_drives, 0, sizeof(superdisk_drive_t));
for (int i = 0; i < 768; i++)
scancode_config_map[i] = i;
@@ -3720,6 +3834,49 @@ save_other_removable_devices(void)
}
}
for (c = 0; c < SUPERDISK_NUM; c++) {
sprintf(temp, "superdisk_%02i_parameters", c + 1);
if (superdisk_drives[c].bus_type == 0) {
ini_section_delete_var(cat, temp);
} else {
sprintf(tmp2, "%u, %s", superdisk_drives[c].is_240,
hdd_bus_to_string(superdisk_drives[c].bus_type, 1));
ini_section_set_string(cat, temp, tmp2);
}
sprintf(temp, "superdisk_%02i_ide_channel", c + 1);
if (superdisk_drives[c].bus_type != SUPERDISK_BUS_ATAPI)
ini_section_delete_var(cat, temp);
else {
sprintf(tmp2, "%01u:%01u", superdisk_drives[c].ide_channel >> 1,
superdisk_drives[c].ide_channel & 1);
ini_section_set_string(cat, temp, tmp2);
}
sprintf(temp, "superdisk_%02i_scsi_id", c + 1);
ini_section_delete_var(cat, temp);
sprintf(temp, "superdisk_%02i_scsi_location", c + 1);
if (superdisk_drives[c].bus_type != SUPERDISK_BUS_SCSI)
ini_section_delete_var(cat, temp);
else {
sprintf(tmp2, "%01u:%02u", superdisk_drives[c].scsi_device_id >> 4,
superdisk_drives[c].scsi_device_id & 15);
ini_section_set_string(cat, temp, tmp2);
}
sprintf(temp, "superdisk_%02i_image_path", c + 1);
if ((superdisk_drives[c].bus_type == 0) || (strlen(superdisk_drives[c].image_path) == 0))
ini_section_delete_var(cat, temp);
else {
path_normalize(superdisk_drives[c].image_path);
if (!strnicmp(superdisk_drives[c].image_path, usr_path, strlen(usr_path)))
ini_section_set_string(cat, temp, &superdisk_drives[c].image_path[strlen(usr_path)]);
else
ini_section_set_string(cat, temp, superdisk_drives[c].image_path);
}
}
for (c = 0; c < MO_NUM; c++) {
sprintf(temp, "mo_%02i_parameters", c + 1);
if (mo_drives[c].bus_type == 0) {

View File

@@ -43,5 +43,7 @@ add_library(rdisk OBJECT rdisk.c)
add_library(mo OBJECT mo.c)
add_library(superdisk OBJECT superdisk.c)
add_subdirectory(minivhd)
target_link_libraries(86Box minivhd)

View File

@@ -36,6 +36,7 @@
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/rdisk.h>
#include <86box/superdisk.h>
#include <86box/mo.h>
typedef struct cmd640_t {
@@ -418,11 +419,19 @@ cmd640_reset(void *priv)
(cdrom[i].ide_channel <= max_channel) && cdrom[i].priv)
scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv);
}
for (i = 0; i < RDISK_NUM; i++) {
if ((rdisk_drives[i].bus_type == RDISK_BUS_ATAPI) && (rdisk_drives[i].ide_channel >= min_channel) &&
(rdisk_drives[i].ide_channel <= max_channel) && rdisk_drives[i].priv)
rdisk_reset((scsi_common_t *) rdisk_drives[i].priv);
}
for (i = 0; i < SUPERDISK_NUM; i++) {
if ((superdisk_drives[i].bus_type == SUPERDISK_BUS_ATAPI) && (superdisk_drives[i].ide_channel >= min_channel) &&
(superdisk_drives[i].ide_channel <= max_channel) && superdisk_drives[i].priv)
superdisk_reset((scsi_common_t *) superdisk_drives[i].priv);
}
for (i = 0; i < MO_NUM; i++) {
if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel >= min_channel) &&
(mo_drives[i].ide_channel <= max_channel) && mo_drives[i].priv)

View File

@@ -36,6 +36,7 @@
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/rdisk.h>
#include <86box/superdisk.h>
#include <86box/rom.h>
#include <86box/hdd.h>
#include <86box/scsi_disk.h>
@@ -542,10 +543,17 @@ cmd646_reset(void *priv)
if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && check_ch(dev, cdrom[i].ide_channel) && cdrom[i].priv)
scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv);
}
for (i = 0; i < RDISK_NUM; i++) {
if ((rdisk_drives[i].bus_type == RDISK_BUS_ATAPI) && check_ch(dev, rdisk_drives[i].ide_channel) && rdisk_drives[i].priv)
rdisk_reset((scsi_common_t *) rdisk_drives[i].priv);
}
for (i = 0; i < SUPERDISK_NUM; i++) {
if ((superdisk_drives[i].bus_type == SUPERDISK_BUS_ATAPI) && (superdisk_drives[i].ide_channel < 4) && superdisk_drives[i].priv)
superdisk_reset((scsi_common_t *) superdisk_drives[i].priv);
}
for (i = 0; i < MO_NUM; i++) {
if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && check_ch(dev, mo_drives[i].ide_channel) && mo_drives[i].priv)
mo_reset((scsi_common_t *) mo_drives[i].priv);

View File

@@ -41,6 +41,7 @@
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/rdisk.h>
#include <86box/superdisk.h>
#include <86box/mo.h>
#include <86box/plat_unused.h>
@@ -488,6 +489,7 @@ sff_reset(void *priv)
if ((hdd[i].bus_type == HDD_BUS_ATAPI) && (hdd[i].ide_channel < 4) && hdd[i].priv)
scsi_disk_reset((scsi_common_t *) hdd[i].priv);
}
for (uint8_t i = 0; i < CDROM_NUM; i++) {
if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel < 4) &&
cdrom[i].priv)
@@ -498,6 +500,12 @@ sff_reset(void *priv)
rdisk_drives[i].priv)
rdisk_reset((scsi_common_t *) rdisk_drives[i].priv);
}
for (uint8_t i = 0; i < SUPERDISK_NUM; i++) {
if ((superdisk_drives[i].bus_type == SUPERDISK_BUS_ATAPI) && (superdisk_drives[i].ide_channel < 4) && superdisk_drives[i].priv)
superdisk_reset((scsi_common_t *) superdisk_drives[i].priv);
}
for (uint8_t i = 0; i < MO_NUM; i++) {
if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel < 4) &&
mo_drives[i].priv)

View File

@@ -172,7 +172,7 @@ rdisk_load_abort(const rdisk_t *dev)
return 0;
}
int
static int
image_is_zdi(const char *s)
{
return !strcasecmp(path_get_extension((char *) s), "ZDI");

2334
src/disk/superdisk.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -35,7 +35,7 @@ typedef struct disk_size_t {
int root_dir_entries;
} disk_size_t;
static const disk_size_t disk_sizes[14] = {
static const disk_size_t disk_sizes[16] = {
// clang-format off
#if 0
{ 1, 1, 2, 1, 1, 77, 26, 0, 0, 4, 2, 6, 68 }, /* 250k 8" */
@@ -57,10 +57,8 @@ static const disk_size_t disk_sizes[14] = {
{ 2, 2, 3, 1, 0, 80, 36, 2, 0xf0, 2, 2, 9, 240 }, /* 2.88M */
{ 0, 64, 0, 0, 0, 96, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 100 */
{ 0, 64, 0, 0, 0, 239, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 250 */
#if 0
{ 0, 8, 0, 0, 0, 963, 32, 2, 0, 0, 0, 0, 0 }, /* LS-120 */
{ 0, 32, 0, 0, 0, 262, 56, 2, 0, 0, 0, 0, 0 } /* LS-240 */
#endif
// clang-format on
};

View File

@@ -21,6 +21,7 @@ typedef struct machine_status_t {
dev_status_empty_active_t fdd[FDD_NUM];
dev_status_empty_active_t cdrom[CDROM_NUM];
dev_status_empty_active_t rdisk[RDISK_NUM];
dev_status_empty_active_t superdisk[SUPERDISK_NUM];
dev_status_empty_active_t mo[MO_NUM];
dev_status_empty_active_t cassette;
dev_status_active_t hdd[HDD_BUS_USB];

View File

@@ -183,6 +183,9 @@ extern void rdisk_reload(uint8_t id);
extern void mo_eject(uint8_t id);
extern void mo_mount(uint8_t id, char *fn, uint8_t wp);
extern void mo_reload(uint8_t id);
extern void superdisk_eject(uint8_t id);
extern void superdisk_mount(uint8_t id, char *fn, uint8_t wp);
extern void superdisk_reload(uint8_t id);
/* Other stuff. */
extern void startblit(void);

View File

@@ -46,11 +46,14 @@
#define GPCMD_REQUEST_SENSE 0x03
#define GPCMD_FORMAT_UNIT 0x04
#define GPCMD_IOMEGA_SENSE 0x06
#define GPCMD_IMATION_SENSE 0x06
#define GPCMD_READ_6 0x08
#define GPCMD_WRITE_6 0x0a
#define GPCMD_SEEK_6 0x0b
#define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c
#define GPCMD_IMATION_SET_PROTECTION_MODE 0x0c
#define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */
#define GPCMD_IMATION_EJECT 0x0d /* ATAPI only? */
#define GPCMD_NO_OPERATION_TOSHIBA 0x0d /* Toshiba Vendor Unique command. */
#define GPCMD_NO_OPERATION_NEC 0x0d /* NEC Vendor Unique command. */
#define GPCMD_INQUIRY 0x12
@@ -160,21 +163,23 @@
#define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12_MATSUSHITA 0xe9 /* Matsushita Vendor Unique command */
/* Mode page codes for mode sense/set */
#define GPMODE_UNIT_ATN_PAGE 0x00
#define GPMODE_R_W_ERROR_PAGE 0x01
#define GPMODE_UNIT_ATN_PAGE 0x00 /* Unit Attention page */
#define GPMODE_R_W_ERROR_PAGE 0x01 /* Read-Write Error Recovery page */
#define GPMODE_DISCONNECT_PAGE 0x02 /* Disconnect/reconnect page */
#define GPMODE_FORMAT_DEVICE_PAGE 0x03
#define GPMODE_FORMAT_DEVICE_PAGE 0x03 /* Format device page */
#define GPMODE_RIGID_DISK_PAGE 0x04 /* Rigid disk geometry page */
#define GPMODE_FLEXIBLE_DISK_PAGE 0x05
#define GPMODE_CACHING_PAGE 0x08
#define GPMODE_CDROM_PAGE_SONY 0x08
#define GPMODE_CDROM_AUDIO_PAGE_SONY 0x09
#define GPMODE_CDROM_PAGE 0x0d
#define GPMODE_CDROM_AUDIO_PAGE 0x0e
#define GPMODE_CAPABILITIES_PAGE 0x2a
#define GPMODE_IOMEGA_PAGE 0x2f
#define GPMODE_UNK_VENDOR_PAGE 0x30
#define GPMODE_ALL_PAGES 0x3f
#define GPMODE_FLEXIBLE_DISK_PAGE 0x05 /* Flexible disk page */
#define GPMODE_CACHING_PAGE 0x08 /* Caching page */
#define GPMODE_CDROM_PAGE_SONY 0x08 /* Sony-specific CD-ROM page */
#define GPMODE_CDROM_AUDIO_PAGE_SONY 0x09 /* Sony-specific CD-ROM audio page */
#define GPMODE_MEDIUM_TYPES_PAGE 0x0b /* Medium types supported page */
#define GPMODE_CDROM_PAGE 0x0d /* General CD-ROM page */
#define GPMODE_CDROM_AUDIO_PAGE 0x0e /* General CD-ROM audio page */
#define GPMODE_REMOVABLE_BLOCK_ACCESS_PAGE 0x1b /* Removable block access capabilities page */
#define GPMODE_CAPABILITIES_PAGE 0x2a /* Capabilities page */
#define GPMODE_IOMEGA_PAGE 0x2f /* Iomega-specific page */
#define GPMODE_UNK_VENDOR_PAGE 0x30 /* Unknown vendor-specific page */
#define GPMODE_ALL_PAGES 0x3f /* All pages supported */
/* Mode page codes for presence */
#define GPMODEP_UNIT_ATN_PAGE 0x0000000000000001LL

View File

@@ -0,0 +1,148 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the Imation SuperDisk drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2018-2025 Miran Grca.
* Copyright 2022-2025 Jasmine Iwanek.
*/
#ifndef EMU_SUPERDISK_H
#define EMU_SUPERDISK_H
#define SUPERDISK_NUM 4
#define BUF_SIZE 32768
#define SUPERDISK_TIME 10.0
#define SUPERDISK_SECTORS (963 * 256)
#define SUPERDISK_240_SECTORS (469504)
#define SUPERDISK_IMAGE_HISTORY 10
enum {
SUPERDISK_BUS_DISABLED = 0,
SUPERDISK_BUS_ATAPI = 5,
SUPERDISK_BUS_SCSI = 6,
SUPERDISK_BUS_USB = 7
};
typedef struct superdisk_drive_t {
uint8_t id;
union {
uint8_t res;
/* Reserved for other ID's. */
uint8_t res0;
uint8_t res1;
uint8_t ide_channel;
uint8_t scsi_device_id;
};
uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */
uint8_t bus_mode; /* Bit 0 = PIO suported;
Bit 1 = DMA supportd. */
uint8_t read_only; /* Struct variable reserved for
media status. */
uint8_t pad;
uint8_t pad0;
FILE *fp;
void *priv;
char image_path[1024];
char prev_image_path[1024];
char *image_history[SUPERDISK_IMAGE_HISTORY];
uint32_t is_240;
uint32_t medium_size;
uint32_t base;
} superdisk_drive_t;
typedef struct superdisk_t {
mode_sense_pages_t ms_pages_saved;
superdisk_drive_t *drv;
#ifdef EMU_IDE_H
ide_tf_t *tf;
#else
void *tf;
#endif
uint8_t *buffer;
uint8_t atapi_cdb[16];
uint8_t current_cdb[16];
uint8_t sense[256];
uint8_t id;
uint8_t cur_lun;
uint8_t pad0;
uint8_t pad1;
uint16_t max_transfer_len;
uint16_t pad2;
int requested_blocks;
int packet_status;
int total_length;
int do_page_save;
int unit_attention;
int request_pos;
int old_len;
int transition;
uint32_t sector_pos;
uint32_t sector_len;
uint32_t packet_len;
double callback;
uint8_t (*ven_cmd)(void *sc, uint8_t *cdb, int32_t *BufLen);
} superdisk_t;
extern superdisk_t *superdisk[SUPERDISK_NUM];
extern superdisk_drive_t superdisk_drives[SUPERDISK_NUM];
extern uint8_t atapi_superdisk_drives[8];
extern uint8_t scsi_superdisk_drives[16];
#define superdisk_sense_error dev->sense[0]
#define superdisk_sense_key dev->sense[2]
#define superdisk_info *(uint32_t *) &(dev->sense[3])
#define superdisk_asc dev->sense[12]
#define superdisk_ascq dev->sense[13]
#ifdef __cplusplus
extern "C" {
#endif
extern void superdisk_disk_close(const superdisk_t *dev);
extern void superdisk_disk_reload(const superdisk_t *dev);
extern void superdisk_insert(superdisk_t *dev);
extern void superdisk_global_init(void);
extern void superdisk_hard_reset(void);
extern void superdisk_reset(scsi_common_t *sc);
extern int superdisk_is_empty(const uint8_t id);
extern void superdisk_load(const superdisk_t *dev, const char *fn, const int skip_insert);
extern void superdisk_close(void);
#ifdef __cplusplus
}
#endif
#endif /*EMU_SUPERDISK_H*/

View File

@@ -49,10 +49,11 @@ extern int ui_msgbox_header(int flags, void *header, void *message);
#define SB_CDROM 0x30
#define SB_RDISK 0x40
#define SB_MO 0x50
#define SB_HDD 0x60
#define SB_NETWORK 0x70
#define SB_SOUND 0x80
#define SB_TEXT 0x90
#define SB_SUPERDISK 0x60
#define SB_HDD 0x70
#define SB_NETWORK 0x80
#define SB_SOUND 0x90
#define SB_TEXT 0x100
extern wchar_t *ui_window_title(wchar_t *s);
extern void ui_hard_reset_completed(void);

View File

@@ -17,6 +17,7 @@
#include <86box/cassette.h>
#include <86box/cdrom.h>
#include <86box/rdisk.h>
#include <86box/superdisk.h>
#include <86box/mo.h>
#include <86box/hdd.h>
#include <86box/thread.h>
@@ -32,14 +33,22 @@ machine_status_init(void)
machine_status.fdd[i].empty = (strlen(floppyfns[i]) == 0);
machine_status.fdd[i].active = false;
}
for (size_t i = 0; i < CDROM_NUM; ++i) {
machine_status.cdrom[i].empty = (strlen(cdrom[i].image_path) == 0);
machine_status.cdrom[i].active = false;
}
for (size_t i = 0; i < RDISK_NUM; i++) {
machine_status.rdisk[i].empty = (strlen(rdisk_drives[i].image_path) == 0);
machine_status.rdisk[i].active = false;
}
for (size_t i = 0; i < SUPERDISK_NUM; i++) {
machine_status.superdisk[i].empty = (strlen(superdisk_drives[i].image_path) == 0);
machine_status.superdisk[i].active = false;
}
for (size_t i = 0; i < MO_NUM; i++) {
machine_status.mo[i].empty = (strlen(mo_drives[i].image_path) == 0);
machine_status.mo[i].active = false;

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -648,6 +648,12 @@ msgstr "Unitats de disc extraïble:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA RTC:"

View File

@@ -648,6 +648,12 @@ msgstr "Mechaniky vyměnitelných disků:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA hodiny:"

View File

@@ -648,6 +648,12 @@ msgstr "Wechseldatenträger:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA-Echtzeituhr:"

View File

@@ -648,6 +648,12 @@ msgstr "Unidades de disco removible:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA RTC:"

View File

@@ -648,6 +648,12 @@ msgstr "Irrotettavat levyasemat:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA-RTC (kello):"

View File

@@ -648,6 +648,12 @@ msgstr "Lecteurs de disques amovibles :"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "Horloge temps réel ISA :"

View File

@@ -650,6 +650,12 @@ msgstr "Pogoni izmjenjivih diskova:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "Sat stvarnog vremena (RTC):"

View File

@@ -648,6 +648,12 @@ msgstr "Unità disco rimovibili:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "RTC ISA:"

View File

@@ -649,6 +649,12 @@ msgstr "取り外し可能なディスクドライブ:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA RTCカード:"

View File

@@ -648,6 +648,12 @@ msgstr "제거 가능한 디스크 드라이브:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA RTC 카드:"

View File

@@ -649,6 +649,12 @@ msgstr "Stacje dysków wymiennych:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA RTC:"

View File

@@ -642,6 +642,12 @@ msgstr "Unidades de disco removível:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "RTC ISA:"

View File

@@ -649,6 +649,12 @@ msgstr "Unidades de disco amovível:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA RTC:"

View File

@@ -649,6 +649,12 @@ msgstr "Дисководы съёмных дисков:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA RTC:"

View File

@@ -648,6 +648,12 @@ msgstr "Mechaniky vymeniteľných diskov:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA hodiny:"

View File

@@ -650,6 +650,12 @@ msgstr "Odstranljivi diskovni pogoni:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "Ura realnega časa ISA:"

View File

@@ -648,6 +648,12 @@ msgstr "Çıkarılabilir disk sürücüleri:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA RTC:"

View File

@@ -650,6 +650,12 @@ msgstr "Дисководи знімних дисків:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA RTC:"

View File

@@ -649,6 +649,12 @@ msgstr "可移动磁盘 (ZIP) 驱动器:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA 实时时钟:"

View File

@@ -649,6 +649,12 @@ msgstr "抽取式磁碟機:"
msgid "ZIP 250"
msgstr "ZIP 250"
msgid "Superdrives:"
msgstr "Superdrives:"
msgid "LS-240"
msgstr "LS-240"
msgid "ISA RTC:"
msgstr "ISA 實時時鐘:"

View File

@@ -30,6 +30,7 @@ extern "C" {
#include <86box/scsi.h>
#include <86box/scsi_device.h>
#include <86box/rdisk.h>
#include <86box/superdisk.h>
#include <86box/mo.h>
#include <86box/plat.h>
#include <86box/machine.h>
@@ -107,6 +108,7 @@ struct Pixmaps {
PixmapSetEmptyActive floppy_35;
PixmapSetEmptyActive cdrom;
PixmapSetEmptyActive rdisk;
PixmapSetEmptyActive superdisk;
PixmapSetEmptyActive mo;
PixmapSetActive hd;
PixmapSetEmptyActive net;
@@ -328,6 +330,7 @@ struct MachineStatus::States {
pixmaps.floppy_35.load(QIcon(":/settings/qt/icons/floppy_35.ico"));
pixmaps.cdrom.load(QIcon(":/settings/qt/icons/cdrom.ico"));
pixmaps.rdisk.load(QIcon(":/settings/qt/icons/rdisk.ico"));
pixmaps.superdisk.load(QIcon(":/settings/qt/icons/superdisk.ico"));
pixmaps.mo.load(QIcon(":/settings/qt/icons/mo.ico"));
pixmaps.hd.load(QIcon(":/settings/qt/icons/hard_disk.ico"));
pixmaps.net.load(QIcon(":/settings/qt/icons/network.ico"));
@@ -345,6 +348,9 @@ struct MachineStatus::States {
for (auto &z : rdisk) {
z.pixmaps = &pixmaps.rdisk;
}
for (auto &z : superdisk) {
z.pixmaps = &pixmaps.superdisk;
}
for (auto &m : mo) {
m.pixmaps = &pixmaps.mo;
}
@@ -361,6 +367,7 @@ struct MachineStatus::States {
std::array<StateEmptyActive, FDD_NUM> fdd;
std::array<StateEmptyActive, CDROM_NUM> cdrom;
std::array<StateEmptyActive, RDISK_NUM> rdisk;
std::array<StateEmptyActive, SUPERDISK_NUM> superdisk;
std::array<StateEmptyActive, MO_NUM> mo;
std::array<StateActive, HDD_BUS_USB> hdds;
std::array<StateEmptyActive, NET_CARD_MAX> net;
@@ -461,6 +468,27 @@ MachineStatus::iterateRDisk(const std::function<void(int)> &cb)
}
}
void
MachineStatus::iterateSuperdisk(const std::function<void(int)> &cb)
{
auto hdc_name = QString(hdc_get_internal_name(hdc_current[0]));
for (size_t i = 0; i < SUPERDISK_NUM; i++) {
/* Could be Internal or External IDE.. */
if ((superdisk_drives[i].bus_type == SUPERDISK_BUS_ATAPI) && !hasIDE() &&
(hdc_name.left(3) != QStringLiteral("ide")) &&
(hdc_name.left(5) != QStringLiteral("xtide")) &&
(hdc_name.left(5) != QStringLiteral("mcide")))
continue;
if ((superdisk_drives[i].bus_type == SUPERDISK_BUS_SCSI) && !hasSCSI() &&
(scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) &&
(scsi_card_current[2] == 0) && (scsi_card_current[3] == 0))
continue;
if (superdisk_drives[i].bus_type != 0) {
cb(i);
}
}
}
void
MachineStatus::iterateMO(const std::function<void(int)> &cb)
{
@@ -580,6 +608,10 @@ MachineStatus::refreshIcons()
if (machine_status.rdisk[i].write_active)
ui_sb_update_icon_write(SB_RDISK | i, 0);
}
for (size_t i = 0; i < SUPERDISK_NUM; i++) {
d->superdisk[i].setActive(machine_status.superdisk[i].active);
d->superdisk[i].setEmpty(machine_status.superdisk[i].empty);
}
for (size_t i = 0; i < MO_NUM; i++) {
d->mo[i].setActive(machine_status.mo[i].active);
d->mo[i].setWriteActive(machine_status.mo[i].write_active);
@@ -619,6 +651,10 @@ MachineStatus::clearActivity()
rdisk.setActive(false);
rdisk.setWriteActive(false);
}
for (auto &superdisk : d->superdisk) {
superdisk.setActive(false);
superdisk.setWriteActive(false);
}
for (auto &mo : d->mo) {
mo.setActive(false);
mo.setWriteActive(false);
@@ -660,6 +696,9 @@ MachineStatus::refresh(QStatusBar *sbar)
for (size_t i = 0; i < RDISK_NUM; i++) {
sbar->removeWidget(d->rdisk[i].label.get());
}
for (size_t i = 0; i < SUPERDISK_NUM; i++) {
sbar->removeWidget(d->superdisk[i].label.get());
}
for (size_t i = 0; i < MO_NUM; i++) {
sbar->removeWidget(d->mo[i].label.get());
}
@@ -780,6 +819,22 @@ MachineStatus::refresh(QStatusBar *sbar)
sbar->addWidget(d->rdisk[i].label.get());
});
iterateSuperdisk([this, sbar](int i) {
d->superdisk[i].label = std::make_unique<ClickableLabel>();
d->superdisk[i].setEmpty(QString(superdisk_drives[i].image_path).isEmpty());
d->superdisk[i].setActive(false);
d->superdisk[i].refresh();
connect((ClickableLabel *) d->superdisk[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
MediaMenu::ptr->superdiskMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->superdiskMenus[i]->sizeHint().height()));
});
connect((ClickableLabel *) d->superdisk[i].label.get(), &ClickableLabel::dropped, [i](QString str) {
MediaMenu::ptr->superdiskMount(i, str, false);
});
d->superdisk[i].label->setToolTip(MediaMenu::ptr->superdiskMenus[i]->title());
d->superdisk[i].label->setAcceptDrops(true);
sbar->addWidget(d->superdisk[i].label.get());
});
iterateMO([this, sbar](int i) {
d->mo[i].label = std::make_unique<ClickableLabel>();
d->mo[i].setEmpty(QString(mo_drives[i].image_path).isEmpty());
@@ -985,6 +1040,10 @@ MachineStatus::updateTip(int tag)
if (d->rdisk[item].label && MediaMenu::ptr->rdiskMenus[item])
d->rdisk[item].label->setToolTip(MediaMenu::ptr->rdiskMenus[item]->toolTip());
break;
case SB_SUPERDISK:
if (d->superdisk[item].label && MediaMenu::ptr->superdiskMenus[item])
d->superdisk[item].label->setToolTip(MediaMenu::ptr->superdiskMenus[item]->title());
break;
case SB_MO:
if (d->mo[item].label && MediaMenu::ptr->moMenus[item])
d->mo[item].label->setToolTip(MediaMenu::ptr->moMenus[item]->toolTip());

View File

@@ -73,6 +73,7 @@ public:
static void iterateFDD(const std::function<void(int i)> &cb);
static void iterateCDROM(const std::function<void(int i)> &cb);
static void iterateRDisk(const std::function<void(int i)> &cb);
static void iterateSuperdisk(const std::function<void(int i)> &cb);
static void iterateMO(const std::function<void(int i)> &cb);
static void iterateNIC(const std::function<void(int i)> &cb);

View File

@@ -44,6 +44,7 @@ enum class MediaType {
Optical,
RDisk,
Mo,
SuperDisk,
Cassette,
Cartridge
};
@@ -57,10 +58,10 @@ typedef QHash<ui::MediaType, device_media_history_t> master_list_t;
// Used to iterate over all supported types when preparing data structures
// Also useful to indicate which types support history
static const MediaType AllSupportedMediaHistoryTypes[] = {
MediaType::Optical,
MediaType::Floppy,
MediaType::RDisk,
MediaType::Mo,
MediaType::SuperDisk,
MediaType::Cassette,
MediaType::Cartridge
};

View File

@@ -54,6 +54,7 @@ extern "C" {
#include <86box/cdrom.h>
#include <86box/scsi_device.h>
#include <86box/rdisk.h>
#include <86box/superdisk.h>
#include <86box/mo.h>
#include <86box/sound.h>
#include <86box/ui.h>
@@ -1136,6 +1137,141 @@ MediaMenu::moReload(int index, int slot)
ui_sb_update_tip(SB_MO | index);
}
void
MediaMenu::superdiskNewImage(int i)
{
NewFloppyDialog dialog(NewFloppyDialog::MediaType::SuperDisk, parentWidget);
switch (dialog.exec()) {
default:
break;
case QDialog::Accepted:
QByteArray filename = dialog.fileName().toUtf8();
superdiskMount(i, filename, false);
break;
}
}
void
MediaMenu::superdiskSelectImage(int i, bool wp)
{
const auto filename = QFileDialog::getOpenFileName(
parentWidget,
QString(),
QString(),
tr("SuperDisk images") % util::DlgFilter({ "im?", "sdi" }) % tr("All files") % util::DlgFilter({ "*" }, true));
if (!filename.isEmpty())
superdiskMount(i, filename, wp);
}
void
MediaMenu::superdiskMount(int i, const QString &filename, bool wp)
{
const auto dev = static_cast<superdisk_t *>(superdisk_drives[i].priv);
int was_empty = superdisk_is_empty(i);
superdisk_disk_close(dev);
superdisk_drives[i].read_only = wp;
if (!filename.isEmpty()) {
QByteArray filenameBytes = filename.toUtf8();
superdisk_load(dev, filenameBytes.data(), 1);
/* Signal media change to the emulated machine. */
superdisk_insert(dev);
/* The drive was previously empty, transition directly to UNIT ATTENTION. */
if (was_empty)
superdisk_insert(dev);
}
mhm.addImageToHistory(i, ui::MediaType::SuperDisk, superdisk_drives[i].prev_image_path, superdisk_drives[i].image_path);
ui_sb_update_icon_state(SB_SUPERDISK | i, filename.isEmpty() ? 1 : 0);
superdiskUpdateMenu(i);
ui_sb_update_tip(SB_SUPERDISK | i);
config_save();
}
void
MediaMenu::superdiskEject(int i)
{
const auto dev = static_cast<superdisk_t *>(superdisk_drives[i].priv);
mhm.addImageToHistory(i, ui::MediaType::SuperDisk, superdisk_drives[i].image_path, QString());
superdisk_disk_close(dev);
superdisk_drives[i].image_path[0] = 0;
if (superdisk_drives[i].bus_type) {
/* Signal disk change to the emulated machine. */
superdisk_insert(dev);
}
ui_sb_update_icon_state(SB_SUPERDISK | i, 1);
superdiskUpdateMenu(i);
ui_sb_update_tip(SB_SUPERDISK | i);
config_save();
}
void
MediaMenu::superdiskReloadPrev(int i)
{
const auto dev = static_cast<superdisk_t *>(superdisk_drives[i].priv);
superdisk_disk_reload(dev);
if (strlen(superdisk_drives[i].image_path) == 0) {
ui_sb_update_icon_state(SB_SUPERDISK | i, 1);
} else {
ui_sb_update_icon_state(SB_SUPERDISK | i, 0);
}
superdiskUpdateMenu(i);
ui_sb_update_tip(SB_SUPERDISK | i);
config_save();
}
void
MediaMenu::superdiskReload(int index, int slot)
{
const QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::SuperDisk);
superdiskMount(index, filename, false);
superdiskUpdateMenu(index);
ui_sb_update_tip(SB_SUPERDISK | index);
}
void
MediaMenu::superdiskUpdateMenu(int i)
{
const QString name = superdisk_drives[i].image_path;
const QString prev_name = superdisk_drives[i].prev_image_path;
if (!superdiskMenus.contains(i))
return;
auto *menu = superdiskMenus[i];
auto childs = menu->children();
auto *ejectMenu = dynamic_cast<QAction *>(childs[superdiskEjectPos]);
ejectMenu->setEnabled(!name.isEmpty());
QString busName = tr("Unknown Bus");
switch (superdisk_drives[i].bus_type) {
default:
break;
case SUPERDISK_BUS_ATAPI:
busName = "ATAPI";
break;
case SUPERDISK_BUS_SCSI:
busName = "SCSI";
break;
}
#if 0
menu->setTitle(tr("SuperDisk %1 %2 (%3): %4").arg((superdisk_drives[i].is_240 > 0) ? "240" : "120", QString::number(i+1), busName, name.isEmpty() ? tr("(empty)") : name));
#endif
menu->setTitle(QString::asprintf(tr("SuperDisk %03i %i (%s): %ls").toUtf8().constData(), (superdisk_drives[i].is_240 > 0) ? 240 : 120, i + 1, busName.toUtf8().data(), name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data()));
for (int slot = 0; slot < MAX_PREV_IMAGES; slot++)
updateImageHistory(i, slot, ui::MediaType::SuperDisk);
}
void
MediaMenu::nicConnect(int i)
{
@@ -1295,4 +1431,23 @@ mo_reload(uint8_t id)
{
MediaMenu::ptr->moReloadPrev(id);
}
void
superdisk_eject(uint8_t id)
{
MediaMenu::ptr->superdiskEject(id);
}
void
superdisk_mount(uint8_t id, char *fn, uint8_t wp)
{
MediaMenu::ptr->superdiskMount(id, QString(fn), wp);
}
void
superdisk_reload(uint8_t id)
{
MediaMenu::ptr->superdiskReloadPrev(id);
}
}

View File

@@ -67,6 +67,14 @@ public:
void moReload(int index, int slot);
void moUpdateMenu(int i);
void superdiskNewImage(int i);
void superdiskSelectImage(int i, bool wp);
void superdiskMount(int i, const QString &filename, bool wp);
void superdiskEject(int i);
void superdiskReloadPrev(int i);
void superdiskReload(int index, int slot);
void superdiskUpdateMenu(int i);
void nicConnect(int i);
void nicDisconnect(int i);
void nicUpdateMenu(int i);
@@ -86,6 +94,7 @@ private:
QMap<int, QMenu *> cdromMenus;
QMap<int, QMenu *> rdiskMenus;
QMap<int, QMenu *> moMenus;
QMap<int, QMenu *> superdiskMenus;
QMap<int, QMenu *> netMenus;
QString getMediaOpenDirectory();
@@ -117,6 +126,9 @@ private:
int moEjectPos;
int moImageHistoryPos[MAX_PREV_IMAGES];
int superdiskEjectPos;
int superdiskReloadPos;
int netDisconnPos;
friend class MachineStatus;

View File

@@ -28,6 +28,7 @@ extern "C" {
#include <86box/random.h>
#include <86box/scsi_device.h>
#include <86box/rdisk.h>
#include <86box/superdisk.h>
#include <86box/mo.h>
}
@@ -57,7 +58,7 @@ struct disk_size_t {
int root_dir_entries;
};
static const disk_size_t disk_sizes[14] = {
static const disk_size_t disk_sizes[16] = {
// clang-format off
#if 0
{ 1, 1, 2, 1, 1, 77, 26, 0, 0, 4, 2, 6, 68 }, /* 250k 8" */
@@ -79,11 +80,9 @@ static const disk_size_t disk_sizes[14] = {
{ 2, 2, 3, 1, 0, 80, 36, 2, 0xf0, 2, 2, 9, 240 }, /* 2.88M */
{ 0, 64, 0, 0, 0, 96, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 100 */
{ 0, 64, 0, 0, 0, 239, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 250 */
#if 0
{ 0, 8, 0, 0, 0, 963, 32, 2, 0, 0, 0, 0, 0 }, /* LS-120 */
{ 0, 32, 0, 0, 0, 262, 56, 2, 0, 0, 0, 0, 0 } /* LS-240 */
#endif
// clang-format on
// clang-format on
};
static const QStringList rpmModes = {
@@ -126,6 +125,11 @@ static const QStringList moTypes = {
"5.25\" 1.3 GB",
};
static const QStringList superDiskTypes = {
"LS-120",
"LS-240",
};
NewFloppyDialog::NewFloppyDialog(MediaType type, QWidget *parent)
: QDialog(parent)
, ui(new Ui::NewFloppyDialog)
@@ -150,6 +154,12 @@ NewFloppyDialog::NewFloppyDialog(MediaType type, QWidget *parent)
}
ui->fileField->setFilter(tr("Removable disk images") % util::DlgFilter({ "im?", "img", "rdi", "zdi" }, true));
break;
case MediaType::SuperDisk:
for (int i = 0; i < superDiskTypes.size(); ++i) {
Models::AddEntry(model, tr(superDiskTypes[i].toUtf8().data()), i);
}
ui->fileField->setFilter(tr("SuperDisk images") % util::DlgFilter({ "im?", "img", "sdi" }, true));
break;
case MediaType::Mo:
for (int i = 0; i < moTypes.size(); ++i) {
Models::AddEntry(model, tr(moTypes[i].toUtf8().data()), i);
@@ -232,6 +242,22 @@ NewFloppyDialog::onCreate()
}
}
break;
case MediaType::SuperDisk:
{
fileType = fi.suffix().toLower() == QStringLiteral("sdi") ? FileType::Sdi: FileType::Img;
std::atomic_bool res;
std::thread t([this, &res, filename, fileType, &progress] {
res = createSuperDiskSectorImage(filename, disk_sizes[ui->comboBoxSize->currentIndex() + 12], fileType, progress);
});
progress.exec();
t.join();
if (res) {
return;
}
}
break;
case MediaType::Mo:
{
fileType = fi.suffix().toLower() == QStringLiteral("mdi") ? FileType::Mdi : FileType::Img;
@@ -708,3 +734,186 @@ NewFloppyDialog::createMoSectorImage(const QString &filename, int8_t disk_size,
return true;
}
bool
NewFloppyDialog::createSuperDiskSectorImage(const QString &filename, const disk_size_t& disk_size, FileType type, QProgressDialog& pbar)
{
uint32_t total_size = 0;
uint32_t total_sectors = 0;
uint32_t sector_bytes = 0;
uint16_t base = 0x1000;
uint32_t pbar_max = 0;
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
return false;
}
QDataStream stream(&file);
stream.setByteOrder(QDataStream::LittleEndian);
sector_bytes = (128 << disk_size.sector_len);
total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors;
if (total_sectors > SUPERDISK_SECTORS)
total_sectors = SUPERDISK_240_SECTORS;
total_size = total_sectors * sector_bytes;
pbar_max = total_size;
if (type == FileType::Zdi) {
pbar_max += base;
}
pbar_max >>= 11;
if (type == FileType::Zdi) {
QByteArray data(base, 0);
auto empty = data.data();
*(uint32_t *) &(empty[0x08]) = (uint32_t) base;
*(uint32_t *) &(empty[0x0C]) = total_size;
*(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes;
*(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors;
*(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides;
*(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks;
stream.writeRawData(empty, base);
pbar_max -= 2;
}
QByteArray bytes(total_size, 0);
auto empty = bytes.data();
if (total_sectors == SUPERDISK_SECTORS) {
/* LS-120 */
/* MBR */
*(uint64_t *) &(empty[0x0000]) = 0x2054524150492EEBLL;
*(uint64_t *) &(empty[0x0008]) = 0x3930302065646F63LL;
*(uint64_t *) &(empty[0x0010]) = 0x67656D6F49202D20LL;
*(uint64_t *) &(empty[0x0018]) = 0x726F70726F432061LL;
*(uint64_t *) &(empty[0x0020]) = 0x202D206E6F697461LL;
*(uint64_t *) &(empty[0x0028]) = 0x30392F33322F3131LL;
*(uint64_t *) &(empty[0x01AE]) = 0x0116010100E90644LL;
*(uint64_t *) &(empty[0x01B6]) = 0xED08BBE5014E0135LL;
*(uint64_t *) &(empty[0x01BE]) = 0xFFFFFE06FFFFFE80LL;
*(uint64_t *) &(empty[0x01C6]) = 0x0002FFE000000020LL;
*(uint16_t *) &(empty[0x01FE]) = 0xAA55;
/* 31 sectors filled with 0x48 */
memset(&(empty[0x0200]), 0x48, 0x3E00);
/* Boot sector */
*(uint64_t *) &(empty[0x4000]) = 0x584F4236389058EBLL;
*(uint64_t *) &(empty[0x4008]) = 0x0008040200302E35LL;
*(uint64_t *) &(empty[0x4010]) = 0x00C0F80000020002LL;
*(uint64_t *) &(empty[0x4018]) = 0x0000002000FF003FLL;
*(uint32_t *) &(empty[0x4020]) = 0x0002FFE0;
*(uint16_t *) &(empty[0x4024]) = 0x0080;
empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */
empty[0x4027] = random_generate();
empty[0x4028] = random_generate();
empty[0x4029] = random_generate();
empty[0x402A] = random_generate();
memset(&(empty[0x402B]), 0x00, 0x000B);
memset(&(empty[0x4036]), 0x20, 0x0008);
empty[0x4036] = 'F';
empty[0x4037] = 'A';
empty[0x4038] = 'T';
empty[0x4039] = '1';
empty[0x403A] = '6';
memset(&(empty[0x403B]), 0x20, 0x0003);
empty[0x41FE] = 0x55;
empty[0x41FF] = 0xAA;
empty[0x5000] = empty[0x1D000] = empty[0x4015];
empty[0x5001] = empty[0x1D001] = 0xFF;
empty[0x5002] = empty[0x1D002] = 0xFF;
empty[0x5003] = empty[0x1D003] = 0xFF;
/* Root directory = 0x35000
Data = 0x39000 */
} else {
/* LS-240 */
/* MBR */
*(uint64_t *) &(empty[0x0000]) = 0x2054524150492EEBLL;
*(uint64_t *) &(empty[0x0008]) = 0x3930302065646F63LL;
*(uint64_t *) &(empty[0x0010]) = 0x67656D6F49202D20LL;
*(uint64_t *) &(empty[0x0018]) = 0x726F70726F432061LL;
*(uint64_t *) &(empty[0x0020]) = 0x202D206E6F697461LL;
*(uint64_t *) &(empty[0x0028]) = 0x30392F33322F3131LL;
*(uint64_t *) &(empty[0x01AE]) = 0x0116010100E900E9LL;
*(uint64_t *) &(empty[0x01B6]) = 0x2E32A7AC014E0135LL;
*(uint64_t *) &(empty[0x01EE]) = 0xEE203F0600010180LL;
*(uint64_t *) &(empty[0x01F6]) = 0x000777E000000020LL;
*(uint16_t *) &(empty[0x01FE]) = 0xAA55;
/* 31 sectors filled with 0x48 */
memset(&(empty[0x0200]), 0x48, 0x3E00);
/* The second sector begins with some strange data
in my reference image. */
*(uint64_t *) &(empty[0x0200]) = 0x3831393230334409LL;
*(uint64_t *) &(empty[0x0208]) = 0x6A57766964483130LL;
*(uint64_t *) &(empty[0x0210]) = 0x3C3A34676063653FLL;
*(uint64_t *) &(empty[0x0218]) = 0x586A56A8502C4161LL;
*(uint64_t *) &(empty[0x0220]) = 0x6F2D702535673D6CLL;
*(uint64_t *) &(empty[0x0228]) = 0x255421B8602D3456LL;
*(uint64_t *) &(empty[0x0230]) = 0x577B22447B52603ELL;
*(uint64_t *) &(empty[0x0238]) = 0x46412CC871396170LL;
*(uint64_t *) &(empty[0x0240]) = 0x704F55237C5E2626LL;
*(uint64_t *) &(empty[0x0248]) = 0x6C7932C87D5C3C20LL;
*(uint64_t *) &(empty[0x0250]) = 0x2C50503E47543D6ELL;
*(uint64_t *) &(empty[0x0258]) = 0x46394E807721536ALL;
*(uint64_t *) &(empty[0x0260]) = 0x505823223F245325LL;
*(uint64_t *) &(empty[0x0268]) = 0x365C79B0393B5B6ELL;
/* Boot sector */
*(uint64_t *) &(empty[0x4000]) = 0x584F4236389058EBLL;
*(uint64_t *) &(empty[0x4008]) = 0x0001080200302E35LL;
*(uint64_t *) &(empty[0x4010]) = 0x00EFF80000020002LL;
*(uint64_t *) &(empty[0x4018]) = 0x0000002000400020LL;
*(uint32_t *) &(empty[0x4020]) = 0x000777E0;
*(uint16_t *) &(empty[0x4024]) = 0x0080;
empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */
empty[0x4027] = random_generate();
empty[0x4028] = random_generate();
empty[0x4029] = random_generate();
empty[0x402A] = random_generate();
memset(&(empty[0x402B]), 0x00, 0x000B);
memset(&(empty[0x4036]), 0x20, 0x0008);
empty[0x4036] = 'F';
empty[0x4037] = 'A';
empty[0x4038] = 'T';
empty[0x4039] = '1';
empty[0x403A] = '6';
memset(&(empty[0x403B]), 0x20, 0x0003);
empty[0x41FE] = 0x55;
empty[0x41FF] = 0xAA;
empty[0x4200] = empty[0x22000] = empty[0x4015];
empty[0x4201] = empty[0x22001] = 0xFF;
empty[0x4202] = empty[0x22002] = 0xFF;
empty[0x4203] = empty[0x22003] = 0xFF;
/* Root directory = 0x3FE00
Data = 0x38200 */
}
pbar.setMaximum(pbar_max);
for (uint32_t i = 0; i < pbar_max; i++) {
stream.writeRawData(&empty[i << 11], 2048);
fileProgress(i);
}
fileProgress(pbar_max);
return true;
}

View File

@@ -18,11 +18,13 @@ public:
Floppy,
RDisk,
Mo,
SuperDisk,
};
enum class FileType {
Img,
Fdi,
Zdi,
Sdi,
Mdi,
};
explicit NewFloppyDialog(MediaType type, QWidget *parent = nullptr);
@@ -44,6 +46,7 @@ private:
bool createSectorImage(const QString &filename, const disk_size_t &disk_size, FileType type);
bool createRDiskSectorImage(const QString &filename, const disk_size_t &disk_size, FileType type, QProgressDialog &pbar);
bool createMoSectorImage(const QString &filename, int8_t disk_size, FileType type, QProgressDialog &pbar);
bool createSuperDiskSectorImage(const QString &filename, const disk_size_t &disk_size, FileType type, QProgressDialog &pbar);
};
#endif // QT_NEWFLOPPYDIALOG_HPP

View File

@@ -23,6 +23,7 @@ extern "C" {
#include <86box/scsi_device.h>
#include <86box/mo.h>
#include <86box/rdisk.h>
#include <86box/superdisk.h>
}
#include "qt_models_common.hpp"

View File

@@ -35,6 +35,9 @@ private slots:
void on_comboBoxRDiskBus_activated(int index);
void on_comboBoxRDiskChannel_activated(int index);
void on_comboBoxRDiskType_activated(int index);
#if 0
void onSuperDiskRowChanged(const QModelIndex &current);
#endif
private:
Ui::SettingsOtherRemovable *ui;

View File

@@ -49,6 +49,7 @@ extern "C" {
#include <86box/cassette.h>
#include <86box/cdrom.h>
#include <86box/rdisk.h>
#include <86box/superdisk.h>
#include <86box/mo.h>
#include <86box/hdd.h>
#include <86box/thread.h>
@@ -307,6 +308,9 @@ ui_sb_update_icon_state(int tag, int state)
case SB_RDISK:
machine_status.rdisk[item].empty = state > 0 ? true : false;
break;
case SB_SUPERDISK:
machine_status.superdisk[item].empty = state > 0 ? true : false;
break;
case SB_MO:
machine_status.mo[item].empty = state > 0 ? true : false;
break;
@@ -345,6 +349,9 @@ ui_sb_update_icon(int tag, int active)
case SB_RDISK:
machine_status.rdisk[item].active = active > 0 ? true : false;
break;
case SB_SUPERDISK:
machine_status.superdisk[item].active = active > 0 ? true : false;
break;
case SB_MO:
machine_status.mo[item].active = active > 0 ? true : false;
break;

View File

@@ -35,6 +35,11 @@
<file>qt/icons/record.ico</file>
<file>qt/icons/rewind.ico</file>
<file>qt/icons/sound.ico</file>
<file>qt/icons/superdisk.ico</file>
<file>qt/icons/superdisk_active.ico</file>
<file>qt/icons/superdisk_disabled.ico</file>
<file>qt/icons/superdisk_empty.ico</file>
<file>qt/icons/superdisk_empty_active.ico</file>
<file>qt/icons/storage_controllers.ico</file>
<file>qt/icons/superdisk.ico</file>
<file>qt/icons/superdisk_image.ico</file>

View File

@@ -6,7 +6,7 @@
*
* This file is part of the 86Box distribution.
*
* Handle the platform-side of CDROM/RDisk/MO drives.
* Handle the platform-side of CDROM/RDisk/MO/SuperDisk drives.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -30,6 +30,7 @@
#include <86box/scsi_device.h>
#include <86box/cdrom.h>
#include <86box/cdrom_image.h>
#include <86box/superdisk.h>
#include <86box/mo.h>
#include <86box/rdisk.h>
#include <86box/scsi_disk.h>
@@ -142,6 +143,63 @@ cdrom_mount(uint8_t id, char *fn)
config_save();
}
void
superdisk_eject(uint8_t id)
{
superdisk_t *dev = (superdisk_t *) superdisk_drives[id].priv;
superdisk_disk_close(dev);
if (superdisk_drives[id].bus_type) {
/* Signal disk change to the emulated machine. */
superdisk_insert(dev);
}
ui_sb_update_icon_state(SB_SUPERDISK | id, 1);
#if 0
media_menu_update_superdisk(id);
#endif
ui_sb_update_tip(SB_SUPERDISK | id);
config_save();
}
void
superdisk_mount(uint8_t id, char *fn, uint8_t wp)
{
superdisk_t *dev = (superdisk_t *) superdisk_drives[id].priv;
superdisk_disk_close(dev);
superdisk_drives[id].read_only = wp;
superdisk_load(dev, fn, 0);
ui_sb_update_icon_state(SB_SUPERDISK | id, strlen(superdisk_drives[id].image_path) ? 0 : 1);
#if 0
media_menu_update_superdisk(id);
#endif
ui_sb_update_tip(SB_SUPERDISK | id);
config_save();
}
void
superdisk_reload(uint8_t id)
{
superdisk_t *dev = (superdisk_t *) superdisk_drives[id].priv;
superdisk_disk_reload(dev);
if (strlen(superdisk_drives[id].image_path) == 0) {
ui_sb_update_icon_state(SB_SUPERDISK | id, 1);
} else {
ui_sb_update_icon_state(SB_SUPERDISK | id, 0);
}
#if 0
media_menu_update_superdisk(id);
#endif
ui_sb_update_tip(SB_SUPERDISK | id);
config_save();
}
void
mo_eject(uint8_t id)
{