Compare commits
4 commits
main
...
multidrive
| Author | SHA1 | Date | |
|---|---|---|---|
| a59b9fbeb3 | |||
| 24c8b1ebe6 | |||
| b12811d05b | |||
| a16d721ce8 |
7 changed files with 190 additions and 103 deletions
6
Makefile
6
Makefile
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
96
src/disc.c
96
src/disc.c
|
|
@ -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,19 +234,20 @@ 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;
|
||||
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->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);
|
||||
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)
|
||||
|
|
@ -253,12 +261,17 @@ int16_t SonyOpen(uint32_t pb, uint32_t dce, uint32_t status)
|
|||
//WriteMacInt8(info->status + dsTwoMegFmt, 0xff); // 1.44MB (0 = 720K)
|
||||
|
||||
// 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");
|
||||
info->to_be_mounted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -534,3 +541,44 @@ int16_t SonyStatus(uint32_t pb, uint32_t dce)
|
|||
|
||||
return set_dsk_err(err);
|
||||
}
|
||||
|
||||
#define M68K_REG_LAST (M68K_REG_CPU_TYPE)
|
||||
#define ROM_PLUSv3_SONYDRV 0x17d30
|
||||
#define offset_accrun 0x18
|
||||
#define ROM_BASE 0x400000
|
||||
#define accrun_address (ROM_BASE + ROM_PLUSv3_SONYDRV + offset_accrun)
|
||||
|
||||
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);
|
||||
m68k_set_reg(M68K_REG_PC, accrun_address);
|
||||
int used = m68k_execute(20000);
|
||||
int result = m68k_get_reg(NULL, M68K_REG_D0);
|
||||
if (used >= 20000 || m68k_get_reg(NULL, M68K_REG_PC) != accrun_address + 10) {
|
||||
DERR("trap call didn't seem to work. used=%d PC=%08x (expected %08x)\n",
|
||||
used, m68k_get_reg(NULL, M68K_REG_PC), accrun_address + 10);
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue