summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nubus/nubus_image.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/nubus/nubus_image.c')
-rw-r--r--src/devices/bus/nubus/nubus_image.c388
1 files changed, 388 insertions, 0 deletions
diff --git a/src/devices/bus/nubus/nubus_image.c b/src/devices/bus/nubus/nubus_image.c
new file mode 100644
index 00000000000..6b929c98270
--- /dev/null
+++ b/src/devices/bus/nubus/nubus_image.c
@@ -0,0 +1,388 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ nubus_image.c - synthetic NuBus card to allow reading/writing "raw"
+ HFS images, including floppy images (DD and HD) and vMac/Basilisk HDD
+ volumes up to 256 MB in size.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "nubus_image.h"
+#include "osdcore.h"
+
+#define IMAGE_ROM_REGION "image_rom"
+#define IMAGE_DISK0_TAG "nb_disk"
+
+#define MESSIMG_DISK_SECTOR_SIZE (512)
+
+// on big-endian, these are NOPs. (TODO: hey, where did WORDS_BIGENDIAN go since the GENie transition?!)
+#if defined(__ppc__) || defined (__PPC__) || defined(__ppc64__) || defined(__PPC64__)
+static UINT32 ni_htonl(UINT32 x) { return x; }
+static UINT32 ni_ntohl(UINT32 x) { return x; }
+#else
+static UINT32 ni_htonl(UINT32 x) { return FLIPENDIAN_INT32(x); }
+static UINT32 ni_ntohl(UINT32 x) { return FLIPENDIAN_INT32(x); }
+#endif
+
+
+// messimg_disk_image_device
+
+class messimg_disk_image_device : public device_t,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ messimg_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // image-level overrides
+ virtual iodevice_t image_type() const { return IO_QUICKLOAD; }
+
+ virtual bool is_readable() const { return 1; }
+ virtual bool is_writeable() const { return 1; }
+ virtual bool is_creatable() const { return 0; }
+ virtual bool must_be_loaded() const { return 0; }
+ virtual bool is_reset_on_load() const { return 0; }
+ virtual const char *image_interface() const { return NULL; }
+ virtual const char *file_extensions() const { return "img"; }
+ virtual const option_guide *create_option_guide() const { return NULL; }
+
+ virtual bool call_load();
+ virtual void call_unload();
+
+ protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+public:
+ UINT32 m_size;
+ UINT8 *m_data;
+ bool m_ejected;
+};
+
+
+// device type definition
+extern const device_type MESSIMG_DISK;
+
+const device_type MESSIMG_DISK = &device_creator<messimg_disk_image_device>;
+
+messimg_disk_image_device::messimg_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MESSIMG_DISK, "Mac image", tag, owner, clock, "messimg_disk_image", __FILE__),
+ device_image_interface(mconfig, *this)
+{
+}
+
+void messimg_disk_image_device::device_config_complete()
+{
+ update_names(MESSIMG_DISK, "disk", "disk");
+}
+
+
+/*-------------------------------------------------
+ device start callback
+-------------------------------------------------*/
+
+void messimg_disk_image_device::device_start()
+{
+ m_data = (UINT8 *)NULL;
+
+ if (exists() && fseek(0, SEEK_END) == 0)
+ {
+ m_size = (UINT32)ftell();
+ }
+}
+
+bool messimg_disk_image_device::call_load()
+{
+ fseek(0, SEEK_END);
+ m_size = (UINT32)ftell();
+ if (m_size > (256*1024*1024))
+ {
+ printf("Mac image too large: must be 256MB or less!\n");
+ m_size = 0;
+ return IMAGE_INIT_FAIL;
+ }
+
+ m_data = (UINT8 *)auto_alloc_array_clear(machine(), UINT32, m_size/sizeof(UINT32));
+ fseek(0, SEEK_SET);
+ fread(m_data, m_size);
+ m_ejected = false;
+
+ return IMAGE_INIT_PASS;
+}
+
+void messimg_disk_image_device::call_unload()
+{
+ // TODO: track dirty sectors and only write those
+ fseek(0, SEEK_SET);
+ fwrite(m_data, m_size);
+ m_size = 0;
+ //free(m_data);
+}
+
+/*-------------------------------------------------
+ device reset callback
+-------------------------------------------------*/
+
+void messimg_disk_image_device::device_reset()
+{
+}
+
+MACHINE_CONFIG_FRAGMENT( image )
+ MCFG_DEVICE_ADD(IMAGE_DISK0_TAG, MESSIMG_DISK, 0)
+MACHINE_CONFIG_END
+
+ROM_START( image )
+ ROM_REGION(0x2000, IMAGE_ROM_REGION, 0)
+ ROM_LOAD( "nb_fake.bin", 0x000000, 0x002000, CRC(9264bac5) SHA1(540c2ce3c90382b2da6e1e21182cdf8fc3f0c930) )
+ROM_END
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type NUBUS_IMAGE = &device_creator<nubus_image_device>;
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor nubus_image_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( image );
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *nubus_image_device::device_rom_region() const
+{
+ return ROM_NAME( image );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nubus_image_device - constructor
+//-------------------------------------------------
+
+nubus_image_device::nubus_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NUBUS_IMAGE, "Disk Image Pseudo-Card", tag, owner, clock, "nb_image", __FILE__),
+ device_nubus_card_interface(mconfig, *this)
+{
+}
+
+nubus_image_device::nubus_image_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
+ device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_nubus_card_interface(mconfig, *this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void nubus_image_device::device_start()
+{
+ UINT32 slotspace;
+ UINT32 superslotspace;
+
+ // set_nubus_device makes m_slot valid
+ set_nubus_device();
+ install_declaration_rom(this, IMAGE_ROM_REGION);
+
+ slotspace = get_slotspace();
+ superslotspace = get_super_slotspace();
+
+// printf("[image %p] slotspace = %x, super = %x\n", this, slotspace, superslotspace);
+
+ m_nubus->install_device(slotspace, slotspace+3, read32_delegate(FUNC(nubus_image_device::image_r), this), write32_delegate(FUNC(nubus_image_device::image_w), this));
+ m_nubus->install_device(slotspace+4, slotspace+7, read32_delegate(FUNC(nubus_image_device::image_status_r), this), write32_delegate(FUNC(nubus_image_device::image_status_w), this));
+ m_nubus->install_device(slotspace+8, slotspace+11, read32_delegate(FUNC(nubus_image_device::file_cmd_r), this), write32_delegate(FUNC(nubus_image_device::file_cmd_w), this));
+ m_nubus->install_device(slotspace+12, slotspace+15, read32_delegate(FUNC(nubus_image_device::file_data_r), this), write32_delegate(FUNC(nubus_image_device::file_data_w), this));
+ m_nubus->install_device(slotspace+16, slotspace+19, read32_delegate(FUNC(nubus_image_device::file_len_r), this), write32_delegate(FUNC(nubus_image_device::file_len_w), this));
+ m_nubus->install_device(slotspace+20, slotspace+147, read32_delegate(FUNC(nubus_image_device::file_name_r), this), write32_delegate(FUNC(nubus_image_device::file_name_w), this));
+ m_nubus->install_device(superslotspace, superslotspace+((256*1024*1024)-1), read32_delegate(FUNC(nubus_image_device::image_super_r), this), write32_delegate(FUNC(nubus_image_device::image_super_w), this));
+
+ m_image = subdevice<messimg_disk_image_device>(IMAGE_DISK0_TAG);
+
+ filectx.curdir[0] = '.';
+ filectx.curdir[1] = '\0';
+ filectx.dirp = NULL;
+ filectx.fd = NULL;
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void nubus_image_device::device_reset()
+{
+}
+
+WRITE32_MEMBER( nubus_image_device::image_status_w )
+{
+ m_image->m_ejected = true;
+}
+
+READ32_MEMBER( nubus_image_device::image_status_r )
+{
+ if(m_image->m_ejected) {
+ return 0;
+ }
+
+ if(m_image->m_size) {
+ return 1;
+ }
+ return 0;
+}
+
+WRITE32_MEMBER( nubus_image_device::image_w )
+{
+}
+
+READ32_MEMBER( nubus_image_device::image_r )
+{
+ return m_image->m_size;
+}
+
+WRITE32_MEMBER( nubus_image_device::image_super_w )
+{
+ UINT32 *image = (UINT32*)m_image->m_data;
+ data = ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
+ mem_mask = ((mem_mask & 0xff) << 24) | ((mem_mask & 0xff00) << 8) | ((mem_mask & 0xff0000) >> 8) | ((mem_mask & 0xff000000) >> 24);
+
+ COMBINE_DATA(&image[offset]);
+}
+
+READ32_MEMBER( nubus_image_device::image_super_r )
+{
+ UINT32 *image = (UINT32*)m_image->m_data;
+ UINT32 data = image[offset];
+ return ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
+}
+
+WRITE32_MEMBER( nubus_image_device::file_cmd_w )
+{
+ const osd_directory_entry *dp = NULL;
+ char fullpath[1024];
+ UINT64 filesize;
+
+// data = ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
+ filectx.curcmd = data;
+ switch(data) {
+ case kFileCmdGetDir:
+ strcpy((char*)filectx.filename, (char*)filectx.curdir);
+ break;
+ case kFileCmdSetDir:
+ if ((filectx.filename[0] == '/') || (filectx.filename[0] == '$')) {
+ strcpy((char*)filectx.curdir, (char*)filectx.filename);
+ } else {
+ strcat((char*)filectx.curdir, "/");
+ strcat((char*)filectx.curdir, (char*)filectx.filename);
+ }
+ break;
+ case kFileCmdGetFirstListing:
+ if(filectx.dirp) osd_closedir(filectx.dirp);
+ filectx.dirp = osd_opendir((const char *)filectx.curdir);
+ case kFileCmdGetNextListing:
+ if (filectx.dirp) {
+ dp = osd_readdir(filectx.dirp);
+ if(dp) {
+ strncpy((char*)filectx.filename, dp->name, sizeof(filectx.filename));
+ } else {
+ memset(filectx.filename, 0, sizeof(filectx.filename));
+ }
+ }
+ else {
+ memset(filectx.filename, 0, sizeof(filectx.filename));
+ }
+ break;
+ case kFileCmdGetFile:
+ memset(fullpath, 0, sizeof(fullpath));
+ strcpy(fullpath, (const char *)filectx.curdir);
+ strcat(fullpath, "/");
+ strcat(fullpath, (const char*)filectx.filename);
+ if(osd_open((const char*)fullpath, OPEN_FLAG_READ, &filectx.fd, &filectx.filelen) != FILERR_NONE) printf("Error opening %s\n", fullpath);
+ filectx.bytecount = 0;
+ break;
+ case kFileCmdPutFile:
+ memset(fullpath, 0, sizeof(fullpath));
+ strcpy(fullpath, (const char *)filectx.curdir);
+ strcat(fullpath, "/");
+ strcat(fullpath, (const char*)filectx.filename);
+ if(osd_open((const char*)fullpath, OPEN_FLAG_WRITE|OPEN_FLAG_CREATE, &filectx.fd, &filesize) != FILERR_NONE) printf("Error opening %s\n", fullpath);
+ filectx.bytecount = 0;
+ break;
+ }
+}
+
+READ32_MEMBER( nubus_image_device::file_cmd_r )
+{
+ return 0;
+}
+
+WRITE32_MEMBER( nubus_image_device::file_data_w )
+{
+ UINT32 count = 4;
+ UINT32 actualcount = 0;
+
+ data = ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
+ if(filectx.fd != NULL) {
+ //data = ni_ntohl(data);
+ if((filectx.bytecount + count) > filectx.filelen) count = filectx.filelen - filectx.bytecount;
+ osd_write(filectx.fd, &data, filectx.bytecount, count, &actualcount);
+ filectx.bytecount += actualcount;
+
+ if(filectx.bytecount >= filectx.filelen) {
+ osd_close(filectx.fd);
+ filectx.fd = NULL;
+ }
+ }
+}
+
+READ32_MEMBER( nubus_image_device::file_data_r )
+{
+ if(filectx.fd != NULL) {
+ UINT32 ret;
+ UINT32 actual = 0;
+ osd_read(filectx.fd, &ret, filectx.bytecount, sizeof(ret), &actual);
+ filectx.bytecount += actual;
+ if(actual < sizeof(ret)) {
+ osd_close(filectx.fd);
+ filectx.fd = NULL;
+ }
+ return ni_htonl(ret);
+ }
+ return 0;
+}
+
+WRITE32_MEMBER( nubus_image_device::file_len_w )
+{
+ data = ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
+ filectx.filelen = ni_ntohl(data);
+}
+
+READ32_MEMBER( nubus_image_device::file_len_r )
+{
+ return filectx.filelen;
+}
+
+WRITE32_MEMBER( nubus_image_device::file_name_w )
+{
+ ((UINT32*)(filectx.filename))[offset] = ni_ntohl(data);
+}
+
+READ32_MEMBER( nubus_image_device::file_name_r )
+{
+ UINT32 ret;
+ ret = ni_htonl(((UINT32*)(filectx.filename))[offset]);
+ return ret;
+}