Add disc read/write callbacks
Instead of relying on the disc data being directly mapped, and accessing blocks by memcpy'ing from it, provide op_read/op_write callbacks so that the host can do disc ops itself (e.g. access SD). The disc_descr_t describes the callbacks (and an opaque pointer passed as an argument when they are invoked), per-disc.
This commit is contained in:
parent
f0ff05081c
commit
854e89e162
3 changed files with 45 additions and 6 deletions
|
|
@ -189,6 +189,10 @@ pitfalls/observations:
|
|||
routed to host-side C code in `disc.c`. The emulation code
|
||||
doesn't support any of the advanced things a driver can be asked
|
||||
to do, such as formatting – just read/write of a block.
|
||||
The read/write can be performed internally, by passing a pointer
|
||||
to an in-memory mapping of the disc data (e.g. `unix_main.c` just
|
||||
`mmap()`s the disc); or, `op_read`/`op_write` callbacks can be
|
||||
used for when a host disc op needs to be performed.
|
||||
When the disc is asked to be ejected, a `umac` callback is called;
|
||||
currently this just exits the emulator. The beginnings of
|
||||
multi-disc support are there, but not enabled – again, bare
|
||||
|
|
|
|||
|
|
@ -27,10 +27,15 @@
|
|||
|
||||
#include <inttypes.h>
|
||||
|
||||
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 {
|
||||
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;
|
||||
|
||||
#define DISC_NUM_DRIVES 2
|
||||
|
|
|
|||
32
src/disc.c
32
src/disc.c
|
|
@ -130,11 +130,14 @@ int disc_pv_hook(uint8_t opcode)
|
|||
// Struct for each drive
|
||||
typedef struct sony_drive_info {
|
||||
int num; // Drive number
|
||||
uint8_t *data;
|
||||
uint8_t *data; // If non-zero, direct mapping of block data
|
||||
unsigned int size;
|
||||
int to_be_mounted; // Flag: drive must be mounted in accRun
|
||||
int read_only; // Flag: force write protection
|
||||
uint32_t status; // Mac address of drive status record
|
||||
void *op_ctx;
|
||||
disc_op_read op_read; // Callback for read (when data == 0)
|
||||
disc_op_write op_write; // '' '' write ''
|
||||
} sony_drinfo_t;
|
||||
|
||||
// List of drives handled by this driver
|
||||
|
|
@ -164,6 +167,9 @@ void SonyInit(disc_descr_t discs[DISC_NUM_DRIVES])
|
|||
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
|
||||
}
|
||||
|
||||
|
|
@ -295,8 +301,20 @@ int16_t SonyPrime(uint32_t pb, uint32_t dce)
|
|||
size_t actual = 0;
|
||||
if ((ReadMacInt16(pb + ioTrap) & 0xff) == aRdCmd) {
|
||||
DDBG("DISC: READ %ld from +0x%x\n", length, position);
|
||||
if (info->data) {
|
||||
DDBG(" (Read buffer: %p)\n", (void *)&info->data[position]);
|
||||
memcpy(buffer, &info->data[position], length);
|
||||
} else {
|
||||
if (info->op_read) {
|
||||
DDBG(" (read op into buffer)\n");
|
||||
int r = info->op_read(info->op_ctx, buffer, position, length);
|
||||
if (r < 0)
|
||||
return set_dsk_err(paramErr);
|
||||
} else {
|
||||
DERR("No disc read strategy!\n");
|
||||
return set_dsk_err(offLinErr);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear TagBuf
|
||||
WriteMacInt32(0x2fc, 0);
|
||||
|
|
@ -310,8 +328,20 @@ int16_t SonyPrime(uint32_t pb, uint32_t dce)
|
|||
return set_dsk_err(wPrErr);
|
||||
|
||||
DDBG("DISC: WRITE %ld to +0x%x\n", length, position);
|
||||
if (info->data) {
|
||||
DDBG(" (Write buffer: %p)\n", (void *)&info->data[position]);
|
||||
memcpy(&info->data[position], buffer, length);
|
||||
} else {
|
||||
if (info->op_write) {
|
||||
DDBG(" (write op into buffer)\n");
|
||||
int r = info->op_write(info->op_ctx, buffer, position, length);
|
||||
if (r < 0)
|
||||
return set_dsk_err(paramErr);
|
||||
} else {
|
||||
DERR("No disc write strategy!\n");
|
||||
return set_dsk_err(offLinErr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update ParamBlock and DCE
|
||||
|
|
|
|||
Loading…
Reference in a new issue