Added the "New Floppy Image" functionality with its own dialog box, can create 86F, Japanese FDI, and IMG images;
The settings dialog now keeps track of MFM/XTIDE/ESDI/IDE channels and SCSI ID's and LUN's; The IBM PS/2 Model 50 now installs a Model 80-style memory expansion card (MCA ID FCFF) when more than 2 MB RAM is selected, and now supports a maximum of 10 MB RAM.
This commit is contained in:
413
src/win/win_new_floppy.c
Normal file
413
src/win/win_new_floppy.c
Normal file
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Handle the New Floppy Image dialog.
|
||||
*
|
||||
* Version: @(#)win_new_floppy.c 1.0.0 2018/01/18
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#define UNICODE
|
||||
#define BITMAP WINDOWS_BITMAP
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#undef BITMAP
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../plat.h"
|
||||
#include "../random.h"
|
||||
#include "../ui.h"
|
||||
#include "win.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
int hole;
|
||||
int sides;
|
||||
int data_rate;
|
||||
int encoding;
|
||||
int rpm;
|
||||
int tracks;
|
||||
int sectors; /* For IMG and Japanese FDI only. */
|
||||
int sector_len; /* For IMG and Japanese FDI only. */
|
||||
int media_desc;
|
||||
int spc;
|
||||
int num_fats;
|
||||
int spfat;
|
||||
int root_dir_entries;
|
||||
} disk_size_t;
|
||||
|
||||
|
||||
disk_size_t disk_sizes[12] = { { 0, 1, 2, 1, 0, 40, 8, 2, 0xFE, 2, 2, 1, 112 }, /* 160k */
|
||||
{ 0, 1, 2, 1, 0, 40, 9, 2, 0xFC, 2, 2, 1, 112 }, /* 180k */
|
||||
{ 0, 2, 2, 1, 0, 40, 8, 2, 0xFF, 2, 2, 1, 112 }, /* 320k */
|
||||
{ 0, 2, 2, 1, 0, 40, 9, 2, 0xFD, 2, 2, 2, 112 }, /* 360k */
|
||||
{ 0, 2, 2, 1, 0, 80, 8, 2, 0xFB, 2, 2, 2, 112 }, /* 640k */
|
||||
{ 0, 2, 2, 1, 0, 80, 9, 2, 0xF9, 2, 2, 3, 112 }, /* 720k */
|
||||
{ 1, 2, 0, 1, 1, 80, 15, 2, 0xF9, 1, 2, 7, 224 }, /* 1.2M */
|
||||
{ 1, 2, 0, 1, 1, 77, 8, 3, 0xFE, 1, 2, 2, 192 }, /* 1.25M */
|
||||
{ 1, 2, 0, 1, 0, 80, 18, 2, 0xF0, 1, 2, 9, 224 }, /* 1.44M */
|
||||
{ 1, 2, 0, 1, 0, 80, 21, 2, 0xF0, 2, 2, 5, 16 }, /* DMF cluster 1024 */
|
||||
{ 1, 2, 0, 1, 0, 80, 21, 2, 0xF0, 4, 2, 3, 16 }, /* DMF cluster 2048 */
|
||||
{ 2, 2, 3, 1, 0, 80, 36, 2, 0xF0, 2, 2, 9, 240 } }; /* 2.88M */
|
||||
|
||||
static char *empty;
|
||||
|
||||
|
||||
static int
|
||||
create_86f(WCHAR *file_name, disk_size_t disk_size, uint8_t rpm_mode)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
uint32_t magic = 0x46423638;
|
||||
uint16_t version = 0x020B;
|
||||
uint16_t dflags = 0;
|
||||
uint16_t tflags = 0;
|
||||
uint16_t index_hole_pos = 0;
|
||||
uint32_t tarray[512];
|
||||
uint32_t array_size, array_size2;
|
||||
uint32_t track_base, track_size;
|
||||
int i;
|
||||
|
||||
dflags = 0; /* Has surface data? - Assume no for now. */
|
||||
dflags |= (disk_size.hole << 1); /* Hole */
|
||||
dflags |= ((disk_size.sides - 1) << 3); /* Sides. */
|
||||
dflags |= (0 << 4); /* Write protect? - Assume no for now. */
|
||||
dflags |= (rpm_mode << 5); /* RPM mode. */
|
||||
dflags |= (0 << 7); /* Has extra bit cells? - Assume no for now. */
|
||||
|
||||
tflags = disk_size.data_rate; /* Data rate. */
|
||||
tflags |= (disk_size.encoding << 3); /* Encoding. */
|
||||
tflags |= (disk_size.rpm << 5); /* RPM. */
|
||||
|
||||
switch (disk_size.hole) {
|
||||
case 0:
|
||||
case 1:
|
||||
default:
|
||||
switch(rpm_mode) {
|
||||
case 1:
|
||||
array_size = 25250;
|
||||
break;
|
||||
case 2:
|
||||
array_size = 25374;
|
||||
break;
|
||||
case 3:
|
||||
array_size = 25750;
|
||||
break;
|
||||
default:
|
||||
array_size = 25000;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch(rpm_mode) {
|
||||
case 1:
|
||||
array_size = 50500;
|
||||
break;
|
||||
case 2:
|
||||
array_size = 50750;
|
||||
break;
|
||||
case 3:
|
||||
array_size = 51000;
|
||||
break;
|
||||
default:
|
||||
array_size = 50000;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
array_size2 = (array_size << 3);
|
||||
array_size = (array_size2 >> 4) << 1;
|
||||
if (array_size2 & 15)
|
||||
array_size += 2;
|
||||
|
||||
empty = (char *) malloc(array_size);
|
||||
|
||||
memset(tarray, 0, 2048);
|
||||
memset(empty, 0, array_size);
|
||||
|
||||
f = plat_fopen(file_name, L"wb");
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
fwrite(&magic, 4, 1, f);
|
||||
fwrite(&version, 2, 1, f);
|
||||
fwrite(&dflags, 2, 1, f);
|
||||
|
||||
track_size = array_size + 6;
|
||||
|
||||
track_base = 8 + ((disk_size.sides == 2) ? 2048 : 1024);
|
||||
|
||||
for (i = 0; i < disk_size.tracks * disk_size.sides; i++)
|
||||
tarray[i] = track_base + (i * track_size);
|
||||
|
||||
fwrite(tarray, 1, (disk_size.sides == 2) ? 2048 : 1024, f);
|
||||
|
||||
for (i = 0; i < disk_size.tracks * disk_size.sides; i++) {
|
||||
fwrite(&tflags, 2, 1, f);
|
||||
fwrite(&index_hole_pos, 4, 1, f);
|
||||
fwrite(empty, 1, array_size, f);
|
||||
}
|
||||
|
||||
free(empty);
|
||||
|
||||
fclose(f);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
create_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_fdi)
|
||||
{
|
||||
FILE *f;
|
||||
uint32_t total_size = 0;
|
||||
uint32_t total_sectors = 0;
|
||||
uint32_t sector_bytes = 0;
|
||||
uint32_t root_dir_bytes = 0;
|
||||
uint32_t fat_size = 0;
|
||||
uint32_t fat1_offs = 0;
|
||||
uint32_t fat2_offs = 0;
|
||||
uint32_t zero_bytes = 0;
|
||||
uint16_t base = 0x1000;
|
||||
|
||||
f = plat_fopen(file_name, L"wb");
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
sector_bytes = (128 << disk_size.sector_len);
|
||||
total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors;
|
||||
total_size = total_sectors * sector_bytes;
|
||||
root_dir_bytes = (disk_size.root_dir_entries << 5);
|
||||
fat_size = (disk_size.spfat * sector_bytes);
|
||||
fat1_offs = sector_bytes;
|
||||
fat2_offs = fat1_offs + fat_size;
|
||||
zero_bytes = fat2_offs + fat_size + root_dir_bytes;
|
||||
|
||||
if (is_fdi) {
|
||||
empty = (char *) malloc(base);
|
||||
memset(empty, 0, base);
|
||||
|
||||
*(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;
|
||||
|
||||
fwrite(empty, 1, base, f);
|
||||
free(empty);
|
||||
}
|
||||
|
||||
empty = (char *) malloc(total_size);
|
||||
memset(empty, 0x00, zero_bytes);
|
||||
memset(empty + zero_bytes, 0xF6, total_size - zero_bytes);
|
||||
|
||||
empty[0x00] = 0xEB; /* Jump to make MS-DOS happy. */
|
||||
empty[0x01] = 0x58;
|
||||
empty[0x02] = 0x90;
|
||||
|
||||
empty[0x03] = 0x38; /* '86BOX5.0' OEM ID. */
|
||||
empty[0x04] = 0x36;
|
||||
empty[0x05] = 0x42;
|
||||
empty[0x06] = 0x4F;
|
||||
empty[0x07] = 0x58;
|
||||
empty[0x08] = 0x35;
|
||||
empty[0x09] = 0x2E;
|
||||
empty[0x0A] = 0x30;
|
||||
|
||||
*(uint16_t *) &(empty[0x0B]) = (uint16_t) sector_bytes;
|
||||
*(uint8_t *) &(empty[0x0D]) = (uint8_t) disk_size.spc;
|
||||
*(uint16_t *) &(empty[0x0E]) = (uint16_t) 1;
|
||||
*(uint8_t *) &(empty[0x10]) = (uint8_t) disk_size.num_fats;
|
||||
*(uint16_t *) &(empty[0x11]) = (uint16_t) disk_size.root_dir_entries;
|
||||
*(uint16_t *) &(empty[0x13]) = (uint16_t) total_sectors;
|
||||
*(uint8_t *) &(empty[0x15]) = (uint8_t) disk_size.media_desc;
|
||||
*(uint16_t *) &(empty[0x16]) = (uint16_t) disk_size.spfat;
|
||||
*(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sectors;
|
||||
*(uint8_t *) &(empty[0x1A]) = (uint8_t) disk_size.sides;
|
||||
|
||||
empty[0x26] = 0x29; /* ')' followed by randomly-generated volume serial number. */
|
||||
empty[0x27] = random_generate();
|
||||
empty[0x28] = random_generate();
|
||||
empty[0x29] = random_generate();
|
||||
empty[0x2A] = random_generate();
|
||||
|
||||
memset(&(empty[0x2B]), 0x20, 11);
|
||||
|
||||
empty[0x36] = 'F';
|
||||
empty[0x37] = 'A';
|
||||
empty[0x38] = 'T';
|
||||
empty[0x39] = '1';
|
||||
empty[0x3A] = '2';
|
||||
|
||||
empty[0x1FE] = 0x55;
|
||||
empty[0x1FF] = 0xAA;
|
||||
|
||||
empty[fat1_offs + 0x00] = empty[fat2_offs + 0x00] = empty[0x15];
|
||||
empty[fat1_offs + 0x01] = empty[fat2_offs + 0x01] = empty[0xFF];
|
||||
empty[fat1_offs + 0x02] = empty[fat2_offs + 0x02] = empty[0xFF];
|
||||
|
||||
fwrite(empty, 1, total_size, f);
|
||||
free(empty);
|
||||
|
||||
fclose(f);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int fdd_id, sb_part;
|
||||
|
||||
static int file_type = 0; /* 0 = IMG, 1 = Japanese FDI, 2 = 86F */
|
||||
static wchar_t fd_file_name[512];
|
||||
|
||||
|
||||
/* Show a MessageBox dialog. This is nasty, I know. --FvK */
|
||||
static int
|
||||
new_floppy_msgbox(HWND hwnd, int type, void *arg)
|
||||
{
|
||||
HWND h;
|
||||
int i;
|
||||
|
||||
h = hwndMain;
|
||||
hwndMain = hwnd;
|
||||
|
||||
i = ui_msgbox(type, arg);
|
||||
|
||||
hwndMain = h;
|
||||
|
||||
return(i);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __amd64__
|
||||
static LRESULT CALLBACK
|
||||
#else
|
||||
static BOOL CALLBACK
|
||||
#endif
|
||||
NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
HWND h;
|
||||
int i = 0;
|
||||
int wcs_len, ext_offs;
|
||||
wchar_t *ext;
|
||||
uint8_t disk_size, rpm_mode;
|
||||
int ret;
|
||||
FILE *f;
|
||||
|
||||
switch (message) {
|
||||
case WM_INITDIALOG:
|
||||
plat_pause(1);
|
||||
memset(fd_file_name, 0, 512 * sizeof(wchar_t));
|
||||
h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE);
|
||||
for (i = 0; i < 12; i++)
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_5888 + i));
|
||||
EnableWindow(h, FALSE);
|
||||
h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE);
|
||||
for (i = 0; i < 4; i++)
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM) plat_get_string(IDS_6144 + i));
|
||||
EnableWindow(h, FALSE);
|
||||
ShowWindow(h, SW_HIDE);
|
||||
h = GetDlgItem(hdlg, IDT_1751);
|
||||
EnableWindow(h, FALSE);
|
||||
ShowWindow(h, SW_HIDE);
|
||||
h = GetDlgItem(hdlg, IDOK);
|
||||
EnableWindow(h, FALSE);
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDOK:
|
||||
h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE);
|
||||
disk_size = SendMessage(h, CB_GETCURSEL, 0, 0);
|
||||
if (file_type == 2) {
|
||||
h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE);
|
||||
rpm_mode = SendMessage(h, CB_GETCURSEL, 0, 0);
|
||||
ret = create_86f(fd_file_name, disk_sizes[disk_size], rpm_mode);
|
||||
} else
|
||||
ret = create_sector_image(fd_file_name, disk_sizes[disk_size], file_type);
|
||||
if (ret)
|
||||
ui_sb_mount_floppy_img(fdd_id, sb_part, 0, fd_file_name);
|
||||
else {
|
||||
new_floppy_msgbox(hdlg, MBX_ERROR, (wchar_t *)IDS_4108);
|
||||
return TRUE;
|
||||
}
|
||||
case IDCANCEL:
|
||||
EndDialog(hdlg, 0);
|
||||
plat_pause(0);
|
||||
return TRUE;
|
||||
|
||||
case IDC_CFILE:
|
||||
if (!file_dlg_w(hdlg, plat_get_string(IDS_2174), L"", 1)) {
|
||||
h = GetDlgItem(hdlg, IDC_EDIT_FILE_NAME);
|
||||
f = _wfopen(wopenfilestring, L"rb");
|
||||
if (f != NULL) {
|
||||
fclose(f);
|
||||
if (new_floppy_msgbox(hdlg, MBX_QUESTION, (wchar_t *)IDS_4111) != 0) /* yes */
|
||||
return FALSE;
|
||||
}
|
||||
SendMessage(h, WM_SETTEXT, 0, (LPARAM) wopenfilestring);
|
||||
memset(fd_file_name, 0, sizeof(fd_file_name));
|
||||
wcscpy(fd_file_name, wopenfilestring);
|
||||
h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE);
|
||||
EnableWindow(h, TRUE);
|
||||
wcs_len = wcslen(wopenfilestring);
|
||||
ext_offs = wcs_len - 4;
|
||||
ext = &(wopenfilestring[ext_offs]);
|
||||
if ((wcs_len >= 4) && !wcsicmp(ext, L".FDI"))
|
||||
file_type = 1;
|
||||
else if ((wcs_len >= 4) && !wcsicmp(ext, L".86F"))
|
||||
file_type = 2;
|
||||
else
|
||||
file_type = 0;
|
||||
h = GetDlgItem(hdlg, IDT_1751);
|
||||
if (file_type == 2) {
|
||||
EnableWindow(h, TRUE);
|
||||
ShowWindow(h, SW_SHOW);
|
||||
} else {
|
||||
EnableWindow(h, FALSE);
|
||||
ShowWindow(h, SW_HIDE);
|
||||
}
|
||||
h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE);
|
||||
if (file_type == 2) {
|
||||
EnableWindow(h, TRUE);
|
||||
ShowWindow(h, SW_SHOW);
|
||||
} else {
|
||||
EnableWindow(h, FALSE);
|
||||
ShowWindow(h, SW_HIDE);
|
||||
}
|
||||
h = GetDlgItem(hdlg, IDOK);
|
||||
EnableWindow(h, TRUE);
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NewFloppyDialogCreate(HWND hwnd, int id, int part)
|
||||
{
|
||||
fdd_id = id;
|
||||
sb_part = part;
|
||||
DialogBox(hinstance, (LPCTSTR)DLG_NEW_FLOPPY, hwnd, NewFloppyDialogProcedure);
|
||||
}
|
||||
Reference in New Issue
Block a user