Compare commits

..

5 commits

Author SHA1 Message Date
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 203 additions and 105 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

@ -48,5 +48,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);
@ -162,15 +168,16 @@ static sony_drinfo_t *get_drive_info(int num)
void SonyInit(disc_descr_t discs[DISC_NUM_DRIVES])
{
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
for(int i = 0; i < DISC_NUM_DRIVES; i++) {
drives[i].num = 0; // set in SonyOpen
drives[i].to_be_mounted = 1;
drives[i].read_only = discs[i].read_only;
drives[i].data = discs[i].base;
drives[i].size = discs[i].size;
drives[i].op_ctx = discs[i].op_ctx;
drives[i].op_read = discs[i].op_read;
drives[i].op_write = discs[i].op_write;
}
}
/*
@ -227,38 +234,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 +382,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 +418,8 @@ 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();
}
break;
@ -534,3 +542,47 @@ 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;
accrun_flag = 0;
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

@ -49,7 +49,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 +78,44 @@ static void copy_fb(uint32_t *fb_out, uint8_t *fb_in)
}
}
static int open_disc(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);
// 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, slot %d, size %ld\n", (void *)disc_base, slot, disc_size);
desc->base = disc_base;
desc->read_only = 0; /* See above */
desc->size = disc_size;
return 0;
}
/**********************************************************************/
/* The emulator core expects to be given ROM and RAM pointers,
@ -91,11 +129,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 +140,9 @@ int main(int argc, char *argv[])
////////////////////////////////////////////////////////////////////////
// Args
disc_descr_t discs[DISC_NUM_DRIVES] = {0};
size_t disc_num = 0;
while ((ch = getopt(argc, argv, "r:d:W:ihw")) != -1) {
switch (ch) {
case 'r':
@ -115,7 +154,19 @@ int main(int argc, char *argv[])
break;
case 'd':
disc_filename = strdup(optarg);
if (disc_num < DISC_NUM_DRIVES) {
if (open_disc(&discs[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 +243,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