Compare commits

..

11 commits

Author SHA1 Message Date
ac0ccec3f9 Try to mount a new disc always
.. even if the eject action didn't appear to eject anything
2025-04-16 19:39:08 +02:00
f34ec2a1b9 Initialize local variable 2025-04-16 19:37:58 +02:00
15d0a7b623 ensure to close disc after it's mmap'd 2025-04-04 21:27:52 +02:00
19f975ac6c fix mounting discs when called for
by not clearing the accrun flag, the dialog to insert a previously
ejected disc successfully causes the emulated mac to cycle to the
correct disc.

This worked in several cases I tested, though in the specific case
of an older OS (About Finder says 5.3) with a newer floppy
(HyperCardBootSystem7.img) the hypercard floppy keeps adding a new
desktop icon everytime it's ejected then re-loaded, and the request
to load it can never be satisfied.
2025-04-04 18:47:23 +02:00
b4e41a6739 multi discs
you can specify a directory as the second -d argument and then cycle
among them by dragging to trash. Using eject doesn't work very well,
because it leaves a ghost on the desktop and accessing it has no way
of completing.
2025-04-04 16:17:19 +02:00
46c886d9e5 WIP disc collections 2025-04-04 08:16:41 +02:00
cd98358391 Use emul_ret when calling a trap 2025-04-03 20:12:20 +02:00
a59b9fbeb3 manipulate the DiskInPlace flag better 2025-03-29 21:45:02 -05:00
24c8b1ebe6 It successfully mounted a 2nd disc!
with caveats
2025-03-29 21:22:53 -05:00
b12811d05b Add basic dependency analysis 2025-03-29 10:17:46 -05:00
a16d721ce8 unix_main: Support specification of multiple disc images.
This doesn't do anything yet, only the first disc image is
actually mounted.
2025-03-29 10:04:12 -05:00
9 changed files with 310 additions and 108 deletions

View file

@ -66,7 +66,7 @@ $(MUSASHI)/m68kops.c $(MUSASHI)/m68kops.h:
prepare: $(MUSASHI)/m68kops.c $(MUSASHI)/m68kops.h
%.o: %.c
$(CC) $(CFLAGS) $(CFLAGS_CFG) -c $< -o $@
$(CC) $(CFLAGS) $(CFLAGS_CFG) -c $< -o $@ -MMD -MF $*.d
main: $(OBJS)
@echo Linking $(OBJS)
@ -74,7 +74,7 @@ main: $(OBJS)
clean:
make -C $(MUSASHI) clean
rm -f $(MY_OBJS) main
rm -f $(MY_OBJS) $(OBJS:%.o=%.d) main
################################################################################
# Mac driver sources (no need to generally rebuild
@ -94,3 +94,5 @@ sonydrv.bin: macsrc/sonydrv.S
cpp $< | $(M68K_AS) -o sonydrv.o
$(M68K_LD) sonydrv.o -o sonydrv.elf -Ttext=0
$(M68K_OBJCOPY) sonydrv.elf -O binary --keep-section=.text $@
-include $(OBJS:%.o=%.d)

2
external/Musashi vendored

@ -1 +1 @@
Subproject commit b3144f12c1296d8fbb600eea13f5db71ffb1b8d8
Subproject commit 8dcac80091b745e9181281fbf63cdd04a95b963a

View file

@ -27,16 +27,21 @@
#include <inttypes.h>
typedef struct disc_desc disc_descr_t;
typedef int (*disc_op_read)(void *ctx, uint8_t *data, unsigned int offset, unsigned int len);
typedef int (*disc_op_write)(void *ctx, uint8_t *data, unsigned int offset, unsigned int len);
typedef struct {
typedef disc_descr_t *(*disc_op_next)(void *ctx);
struct disc_desc {
uint8_t *base;
unsigned int size;
int read_only;
void *op_ctx;
disc_op_read op_read;
disc_op_write op_write;
} disc_descr_t;
disc_op_next op_next;
};
#define DISC_NUM_DRIVES 2
@ -48,5 +53,5 @@ typedef struct {
*/
void disc_init(disc_descr_t discs[DISC_NUM_DRIVES]);
int disc_pv_hook(uint8_t opcode);
void disc_tick();
#endif

View file

@ -243,6 +243,13 @@
#define M68K_FAST_FUNC(x) __not_in_flash_func(x)
#endif
/* If ON, CPU will support "emul_op" instructions from 0x7100..0x713f by
* calling m68k_end_timeslice when they are encountered. The caller can (must)
* check the IR register and implement the operation.
* If off, these remain illegal instructions.
*/
#define M68K_EMUL_OP OPT_ON
#endif /* M68K_COMPILE_FOR_MAME */
/* ======================================================================== */

View file

@ -1,13 +1,16 @@
0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4c,
0x00, 0x56, 0x00, 0x68, 0x00, 0x94, 0x05, 0x2e, 0x53, 0x6f, 0x6e, 0x79,
0x48, 0xe7, 0x00, 0xc0, 0x10, 0x3c, 0x00, 0x1e, 0xa7, 0x1e, 0x24, 0x48,
0x4c, 0xdf, 0x03, 0x00, 0xb5, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x67, 0x00,
0x00, 0x18, 0x26, 0x7a, 0x00, 0x64, 0x16, 0xbc, 0x00, 0x00, 0x20, 0x3c,
0x00, 0x01, 0xff, 0xfb, 0x20, 0x4a, 0x5c, 0x88, 0xa0, 0x4e, 0x4e, 0x75,
0x70, 0xe9, 0x4e, 0x75, 0x24, 0x7a, 0x00, 0x4a, 0x14, 0xbc, 0x00, 0x01,
0x60, 0x1a, 0x24, 0x7a, 0x00, 0x40, 0x14, 0xbc, 0x00, 0x02, 0x0c, 0x68,
0x00, 0x01, 0x00, 0x1a, 0x66, 0x0a, 0x4e, 0x75, 0x24, 0x7a, 0x00, 0x2e,
0x14, 0xbc, 0x00, 0x03, 0x32, 0x28, 0x00, 0x06, 0x08, 0x01, 0x00, 0x09,
0x67, 0x0c, 0x4a, 0x40, 0x6f, 0x02, 0x42, 0x40, 0x31, 0x40, 0x00, 0x10,
0x4e, 0x75, 0x4a, 0x40, 0x6f, 0x04, 0x42, 0x40, 0x4e, 0x75, 0x2f, 0x38,
0x08, 0xfc, 0x4e, 0x75, 0x70, 0xe8, 0x4e, 0x75, 0x00, 0x00, 0x00, 0x00
0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x6a,
0x00, 0x74, 0x00, 0x86, 0x00, 0xb2, 0x05, 0x2e, 0x53, 0x6f, 0x6e, 0x79,
0xa0, 0x2f, 0x26, 0x7a, 0x00, 0x9c, 0x16, 0xbc, 0x00, 0x04, 0x48, 0xe7,
0x00, 0xc0, 0x10, 0x3c, 0x00, 0x3c, 0xa7, 0x1e, 0x24, 0x48, 0x4c, 0xdf,
0x03, 0x00, 0xb5, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x2c,
0x26, 0x7a, 0x00, 0x7a, 0x16, 0xbc, 0x00, 0x00, 0x76, 0x02, 0xd5, 0xfc,
0x00, 0x00, 0x00, 0x24, 0x20, 0x03, 0x48, 0x40, 0x00, 0x40, 0xff, 0xfb,
0x20, 0x4a, 0xa0, 0x4e, 0x95, 0xfc, 0x00, 0x00, 0x00, 0x1e, 0x53, 0x43,
0x66, 0x00, 0xff, 0xea, 0x4e, 0x75, 0x70, 0xe9, 0x4e, 0x75, 0x24, 0x7a,
0x00, 0x4c, 0x14, 0xbc, 0x00, 0x01, 0x60, 0x1a, 0x24, 0x7a, 0x00, 0x42,
0x14, 0xbc, 0x00, 0x02, 0x0c, 0x68, 0x00, 0x01, 0x00, 0x1a, 0x66, 0x0a,
0x4e, 0x75, 0x24, 0x7a, 0x00, 0x30, 0x14, 0xbc, 0x00, 0x03, 0x32, 0x28,
0x00, 0x06, 0x08, 0x01, 0x00, 0x09, 0x67, 0x0c, 0x4a, 0x40, 0x6f, 0x02,
0x42, 0x40, 0x31, 0x40, 0x00, 0x10, 0x4e, 0x75, 0x4a, 0x40, 0x6f, 0x04,
0x42, 0x40, 0x4e, 0x75, 0x2f, 0x38, 0x08, 0xfc, 0x4e, 0x75, 0x70, 0xe8,
0x4e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

View file

@ -12,6 +12,7 @@
#define SONY_REF_NUM -5
#define SONY_STATUS_SIZE 30
#define SONY_DRIVE_COUNT 2
.org 0
.globl _start
@ -31,26 +32,41 @@ name:
.byte 5
.ascii ".Sony"
accrun:
.word 0xA02F // PostEvent
move.l (faulting_address), %a3
move.b #4, (%a3) // Fault! end timeslice
open:
// Open()
// Allocate drive status block and pass to Open routine:
movem.l %a0-%a1, -(%sp)
move.b #SONY_STATUS_SIZE, %d0
move.b #SONY_STATUS_SIZE*SONY_DRIVE_COUNT, %d0
.word 0xa71e // NewPtrSysClear
move.l %a0, %a2
movem.l (%sp)+, %a0-%a1
cmp.l #0, %a2
beq 2f // lolfail
move.l (faulting_address), %a3
move.b #0, (%a3) // Fault! Open: op 0
// FIXME: Support variable number of drives
// Now add the drive:
move.l #(0x00010000 + (0xffff & SONY_REF_NUM)), %d0
// Now add the drives:
mov.l #SONY_DRIVE_COUNT, %d3
add.l #6+SONY_STATUS_SIZE*(SONY_DRIVE_COUNT-1), %a2
3:
move.l %d3, %d0
swap %d0 // refnum in top half of d0, lower is 0000
ori.w #(0xffff & SONY_REF_NUM), %d0 // index & refnum in d0
move.l %a2, %a0
add.l #6, %a0
.word 0xa04e // AddDrive
sub.l #SONY_STATUS_SIZE, %a2 // next drive on next iteration
subq #1, %d3
bne 3b // more drives to add?
1: rts
2: moveq #-23, %d0
rts

View file

@ -26,6 +26,8 @@
extern void umac_disc_ejected(void);
static uint8_t accrun_flag;
// B2 decls:
static int16_t SonyOpen(uint32_t pb, uint32_t dce, uint32_t status);
static int16_t SonyPrime(uint32_t pb, uint32_t dce);
@ -66,6 +68,10 @@ int disc_pv_hook(uint8_t opcode)
DDBG("[Disc: STATUS]\n");
d0 = SonyStatus(ADR24(a0), ADR24(a1));
break;
case 4: // upcall helper
DDBG("[Disc: end timeslice]\n");
m68k_end_timeslice();
break;
default:
DERR("[Disc PV op %02x unhandled!]\n", opcode);
@ -138,6 +144,7 @@ typedef struct sony_drive_info {
void *op_ctx;
disc_op_read op_read; // Callback for read (when data == 0)
disc_op_write op_write; // '' '' write ''
disc_op_next op_next; // Callback for mount next disc
} sony_drinfo_t;
// List of drives handled by this driver
@ -160,17 +167,24 @@ static sony_drinfo_t *get_drive_info(int num)
* Initialization
*/
void SonyInit(disc_descr_t discs[DISC_NUM_DRIVES])
static void SonyInit1(sony_drinfo_t *drive, disc_descr_t *disc)
{
drives[0].num = 0;
drives[0].to_be_mounted = 1;
drives[0].read_only = discs[0].read_only;
drives[0].data = discs[0].base;
drives[0].size = discs[0].size;
drives[0].op_ctx = discs[0].op_ctx;
drives[0].op_read = discs[0].op_read;
drives[0].op_write = discs[0].op_write;
// FIXME: Disc 2
drive->to_be_mounted = 1;
drive->read_only = disc->read_only;
drive->data = disc->base;
drive->size = disc->size;
drive->op_ctx = disc->op_ctx;
drive->op_read = disc->op_read;
drive->op_write = disc->op_write;
drive->op_next = disc->op_next;
}
static void SonyInit(disc_descr_t discs[DISC_NUM_DRIVES])
{
for(int i = 0; i < DISC_NUM_DRIVES; i++) {
drives[i].num = 0; // set in SonyOpen
SonyInit1(&drives[i], &discs[i]);
}
}
/*
@ -227,38 +241,44 @@ int16_t SonyOpen(uint32_t pb, uint32_t dce, uint32_t status)
set_dsk_err(0);
// Install drives
//for (int drnum = 0; drnum < NUM_DRIVES; drnum++) {
const int drnum = 0;
sony_drinfo_t *info = &drives[drnum];
int free_drive_number = 1;
for (int drnum = 0; drnum < DISC_NUM_DRIVES; drnum++) {
sony_drinfo_t *info = &drives[drnum];
info->num = FindFreeDriveNumber(1); // ? 1 for internal, 2 for external
info->to_be_mounted = 0;
info->num = FindFreeDriveNumber(free_drive_number); // ? 1 for internal, 2 for external
free_drive_number = info->num + 1;
info->to_be_mounted = 0;
// Original code allocated drive status record here (invoked
// trap to NewPtrSysClear), but our driver does this instead
// (it's passed in via status parameter), to avoid having to
// implement invocation of 68K traps/upcalls from sim env.
info->status = status;
DDBG(" DrvSts at %08x\n", info->status);
// Original code allocated drive status record here (invoked
// trap to NewPtrSysClear), but our driver does this instead
// (it's passed in via status parameter), to avoid having to
// implement invocation of 68K traps/upcalls from sim env.
info->status = status + 30 * drnum;
DDBG(" DrvSts at %08x gets drnum %d num %d\n", info->status, drnum, info->num);
// Set up drive status
// ME: do 800K, double sided (see IM)
WriteMacInt16(info->status + dsQType, sony);
WriteMacInt8(info->status + dsInstalled, 1);
WriteMacInt8(info->status + dsSides, 0xff); // 2 sides
WriteMacInt8(info->status + dsTwoSideFmt, 0xff); //
//WriteMacInt8(info->status + dsNewIntf, 0xff);
WriteMacInt8(info->status + dsMFMDrive, 0); // 0 = 400/800K GCR drive)
WriteMacInt8(info->status + dsMFMDisk, 0);
//WriteMacInt8(info->status + dsTwoMegFmt, 0xff); // 1.44MB (0 = 720K)
// Set up drive status
// ME: do 800K, double sided (see IM)
WriteMacInt16(info->status + dsQType, sony);
WriteMacInt8(info->status + dsInstalled, 1);
WriteMacInt8(info->status + dsSides, 0xff); // 2 sides
WriteMacInt8(info->status + dsTwoSideFmt, 0xff); //
//WriteMacInt8(info->status + dsNewIntf, 0xff);
WriteMacInt8(info->status + dsMFMDrive, 0); // 0 = 400/800K GCR drive)
WriteMacInt8(info->status + dsMFMDisk, 0);
//WriteMacInt8(info->status + dsTwoMegFmt, 0xff); // 1.44MB (0 = 720K)
// If disk in drive...
WriteMacInt8(info->status + dsDiskInPlace, 1); // Inserted removable disk
WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
DDBG(" disk inserted, flagging for mount\n");
info->to_be_mounted = 1;
// If disk in drive...
if (info->size) {
if (drnum == 0)
WriteMacInt8(info->status + dsDiskInPlace, 1); // Inserted removable disk
else
info->to_be_mounted = 1;
WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
DDBG(" disk inserted, flagging for mount\n");
}
}
// Original code ddded drive to drive queue here (invoked trap
// Original code added drive to drive queue here (invoked trap
// to AddDrive), but our driver does this after this PV call returns.
// FIXME: In future return a bitmap of drives to add.
(void)pb;
@ -369,14 +389,8 @@ int16_t SonyControl(uint32_t pb, uint32_t dce)
return set_dsk_err(noErr);
case 65: { // Periodic action (accRun, "insert" disks on startup)
static int complained_yet = 0;
if (!complained_yet) {
DERR("SonyControl:accRun: Not supported!\n");
complained_yet = 1;
}
// The original emulation code hooked this to mount_mountable_volumes,
// which called back to PostEvent(diskEvent).
return set_dsk_err(-1);
accrun_flag = 1;
return set_dsk_err(noErr);
}
}
@ -411,7 +425,15 @@ int16_t SonyControl(uint32_t pb, uint32_t dce)
// SysEject(info->fh);
WriteMacInt8(info->status + dsDiskInPlace, 0);
umac_disc_ejected();
if(info->num == 1)
umac_disc_ejected();
}
if(info->op_next) {
DERR("DISC: mount new\n");
disc_descr_t *new_disc = info->op_next(info->op_ctx);
if (new_disc) {
SonyInit1(info, new_disc);
}
}
break;
@ -534,3 +556,46 @@ int16_t SonyStatus(uint32_t pb, uint32_t dce)
return set_dsk_err(err);
}
#define M68K_REG_LAST (M68K_REG_CPU_TYPE)
static int PostEvent(int type, int num) {
DDBG("PostEvent EventCode=%d EventMsg=%d\n", type, num);
uint32_t regs[M68K_REG_LAST];
for(int i=0; i<M68K_REG_LAST; i++)
regs[i] = m68k_get_reg(NULL, i);
m68k_set_reg(M68K_REG_D0, num);
m68k_set_reg(M68K_REG_A0, type);
uint32_t new_sp = regs[M68K_REG_SP] - 4;
cpu_write_word(new_sp, 0xA02F); // PostEvent
cpu_write_word(new_sp+2, 0x7180); // emul_ret
m68k_set_reg(M68K_REG_PC, new_sp); // PostEvent
m68k_set_reg(M68K_REG_SP, new_sp); // Emul_Ret
int used = m68k_execute(80000);
int result = m68k_get_reg(NULL, M68K_REG_D0);
if (used >= 20000 || m68k_get_reg(NULL, M68K_REG_PC) != new_sp + 4 ||
m68k_get_reg(NULL, M68K_REG_SP) != new_sp) {
DERR("trap call didn't seem to work. used=%d PC=%08x (expected %08x) SP=%08x (expected %08x)\n",
used,
m68k_get_reg(NULL, M68K_REG_PC), new_sp+4,
m68k_get_reg(NULL, M68K_REG_SP), new_sp);
result = 1; // some kind of failure (but you're probably doomed)
}
for(int i=0; i<M68K_REG_LAST; i++)
m68k_set_reg(i, regs[i]);
return result;
}
void disc_tick() {
if (!accrun_flag) return;
for (int i = 0; i < DISC_NUM_DRIVES; i++) {
sony_drinfo_t *info = &drives[i];
if (drives[i].to_be_mounted) {
int inPlace = ReadMacInt8(info->status + dsDiskInPlace); // Inserted removable disk
if (inPlace || PostEvent(7, drives[i].num) == 0) {
drives[i].to_be_mounted = 0;
WriteMacInt8(info->status + dsDiskInPlace, 1); // Inserted removable disk
}
}
}
}

View file

@ -712,6 +712,7 @@ int umac_loop(void)
// Device polling
via_tick(global_time_us);
mouse_tick();
disc_tick();
kbd_check_work();
return sim_done;

View file

@ -28,6 +28,8 @@
*/
#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/mman.h>
@ -49,7 +51,7 @@ static void print_help(char *n)
printf("Syntax: %s <options>\n"
"\t-r <rom path>\t\tDefault 'rom.bin'\n"
"\t-W <rom dump path>\tDump ROM after patching\n"
"\t-d <disc path>\n"
"\t-d <disc path> (may be repeated)\n"
"\t-w\t\t\tEnable persistent disc writes (default R/O)\n"
"\t-i\t\t\tDisassembled instruction trace\n", n);
}
@ -78,6 +80,122 @@ static void copy_fb(uint32_t *fb_out, uint8_t *fb_in)
}
}
typedef struct {
disc_descr_t *desc;
int opt_write;
int slot;
int idx, num_names;
char **names;
} unix_disc_descr_t;
static int open_disc_single(unix_disc_descr_t *desc, int slot, int opt_write, const char *disc_filename) {
int ofd;
void *disc_base;
struct stat sb;
printf("Opening disc '%s'\n", disc_filename);
ofd = open(disc_filename, opt_write ? O_RDWR : O_RDONLY);
if (ofd < 0) {
perror("Disc");
return 1;
}
fstat(ofd, &sb);
size_t disc_size = sb.st_size;
/* Discs are always _writable_ from the perspective of
* the Mac, but by default data is a MAP_PRIVATE copy
* and is not synchronised to the backing file. If
* opt_write, we use MAP_SHARED and open the file RW,
* so writes persist to the disc image.
*/
disc_base = mmap(0, disc_size, PROT_READ | PROT_WRITE,
opt_write ? MAP_SHARED : MAP_PRIVATE,
ofd, 0);
close(ofd);
if (disc_base == MAP_FAILED) {
printf("Can't mmap disc!\n");
return 1;
}
printf("Disc mapped at %p, slot %d, size %ld\n", (void *)disc_base, slot, disc_size);
desc->desc->base = disc_base;
desc->desc->read_only = 0; /* See above */
desc->desc->size = disc_size;
desc->slot = slot;
return 0;
}
extern int asprintf(char **restrict strp, const char *restrict fmt, ...);
static disc_descr_t *disc_open_next(void *desc_in) {
unix_disc_descr_t *desc = desc_in;
if (desc->num_names == 0) {
return 0;
}
munmap(desc->desc->base, desc->desc->size);
desc->desc->base = 0;
desc->idx = (desc->idx + 1) % desc->num_names;
int r = open_disc_single(desc, desc->slot, desc->opt_write, desc->names[desc->idx]);
if (r == 0) return desc->desc;
return 0;
}
static int open_disc_collection(unix_disc_descr_t *desc, int slot, int opt_write, const char *disc_filename) {
struct stat sb;
printf("Opening disc collection '%s'\n", disc_filename);
DIR *d = opendir(disc_filename);
char **names = malloc(0);
struct dirent *ent;
int cnt=0;
for(; errno=0, ent = readdir(d);) {
names = realloc(names, sizeof(const char *) * (cnt + 1));
asprintf(&names[cnt], "%s/%s", disc_filename, ent->d_name);
stat(names[cnt], &sb);
if((sb.st_mode & S_IFMT) == S_IFDIR) {
continue;
}
printf("Found disc %s\n", names[cnt]);
cnt++;
}
if (errno != 0) {
perror("readdir");
}
closedir(d);
if(cnt == 0) {
printf("Didn't find any discs\n");
return 1;
}
desc->names = names;
desc->num_names = cnt;
desc->desc->op_next = disc_open_next;
desc->desc->op_ctx = desc;
return open_disc_single(desc, slot, opt_write, names[0]);
}
static int open_disc(unix_disc_descr_t *desc, int slot, int opt_write, const char *disc_filename) {
struct stat sb;
int r = stat(disc_filename, &sb);
if (r < 0) {
perror("Disc");
return 1;
}
if((sb.st_mode & S_IFMT) == S_IFDIR) {
if(slot == 0) {
printf("Initial disc argument must be a file, not a directory\n");
return 1;
}
return open_disc_collection(desc, slot, opt_write, disc_filename);
} else {
desc->desc->op_next = 0;
return open_disc_single(desc, slot, opt_write, disc_filename);
}
}
/**********************************************************************/
/* The emulator core expects to be given ROM and RAM pointers,
@ -91,11 +209,9 @@ int main(int argc, char *argv[])
{
void *ram_base;
void *rom_base;
void *disc_base;
char *rom_filename = "rom.bin";
char *rom_dump_filename = NULL;
char *ram_filename = "ram.bin";
char *disc_filename = NULL;
int ofd;
int ch;
int opt_disassemble = 0;
@ -104,6 +220,15 @@ int main(int argc, char *argv[])
////////////////////////////////////////////////////////////////////////
// Args
disc_descr_t discs[DISC_NUM_DRIVES] = {0};
unix_disc_descr_t udiscs[DISC_NUM_DRIVES] = {0};
for(int i=0; i<DISC_NUM_DRIVES; i++) {
udiscs[i].desc = &discs[i];
}
size_t disc_num = 0;
while ((ch = getopt(argc, argv, "r:d:W:ihw")) != -1) {
switch (ch) {
case 'r':
@ -115,7 +240,19 @@ int main(int argc, char *argv[])
break;
case 'd':
disc_filename = strdup(optarg);
if (disc_num < DISC_NUM_DRIVES) {
if (open_disc(&udiscs[disc_num], disc_num, opt_write, optarg) != 0) {
return 1;
}
disc_num ++;
} else {
printf("Too many discs\n");
return 1;
}
break;
case 'R':
opt_write = 0;
break;
case 'w':
@ -192,40 +329,6 @@ int main(int argc, char *argv[])
}
printf("RAM mapped at %p\n", (void *)ram_base);
disc_descr_t discs[DISC_NUM_DRIVES] = {0};
if (disc_filename) {
printf("Opening disc '%s'\n", disc_filename);
// FIXME: >1 disc
ofd = open(disc_filename, opt_write ? O_RDWR : O_RDONLY);
if (ofd < 0) {
perror("Disc");
return 1;
}
fstat(ofd, &sb);
size_t disc_size = sb.st_size;
/* Discs are always _writable_ from the perspective of
* the Mac, but by default data is a MAP_PRIVATE copy
* and is not synchronised to the backing file. If
* opt_write, we use MAP_SHARED and open the file RW,
* so writes persist to the disc image.
*/
disc_base = mmap(0, disc_size, PROT_READ | PROT_WRITE,
opt_write ? MAP_SHARED : MAP_PRIVATE,
ofd, 0);
if (disc_base == MAP_FAILED) {
printf("Can't mmap disc!\n");
return 1;
}
printf("Disc mapped at %p, size %ld\n", (void *)disc_base, disc_size);
discs[0].base = disc_base;
discs[0].read_only = 0; /* See above */
discs[0].size = disc_size;
}
////////////////////////////////////////////////////////////////////////
// SDL/UI init