static const char *internal_device_instancename(const device_class *devclass, int id, UINT32 base, const char *(*get_dev_typename)(iodevice_t)) { iodevice_t type; int count; const char *result; char *s; /* retrieve info about the device instance */ result = device_get_info_string(devclass, base + id); if (!result) { /* not specified? default to device names based on the device type */ type = (iodevice_t) (int) device_get_info_int(devclass, DEVINFO_INT_TYPE); count = (int) device_get_info_int(devclass, DEVINFO_INT_COUNT); result = get_dev_typename(type); /* need to number if there is more than one device */ if (count > 1) { s = device_temp_str(); sprintf(s, "%s%d", result, id + 1); result = s; } } return result; }
/* reads/writes a byte; write_value is -1 for read only */ static UINT8 apple525_process_byte(mess_image *img, int write_value) { UINT8 read_value; struct apple525_disk *disk; int spinfract_divisor; int spinfract_dividend; const struct IODevice *dev; disk = (struct apple525_disk *) image_lookuptag(img, APPLE525TAG); dev = image_device(img); spinfract_dividend = (int) device_get_info_int(&dev->devclass, DEVINFO_INT_APPLE525_SPINFRACT_DIVIDEND); spinfract_divisor = (int) device_get_info_int(&dev->devclass, DEVINFO_INT_APPLE525_SPINFRACT_DIVISOR); /* no image initialized for that drive ? */ if (!image_exists(img)) return 0xFF; /* check the spin count if reading*/ if (write_value < 0) { disk->spin_count++; disk->spin_count %= spinfract_divisor; if (disk->spin_count >= spinfract_dividend) return 0x00; } /* load track if need be */ if (disk->track_loaded == 0) apple525_load_current_track(img); /* perform the read */ read_value = disk->track_data[disk->position]; /* perform the write, if applicable */ if (write_value >= 0) { disk->track_data[disk->position] = write_value; disk->track_dirty = 1; } disk->position++; disk->position %= (sizeof(disk->track_data) / sizeof(disk->track_data[0])); /* when writing; save the current track after every full sector write */ if ((write_value >= 0) && ((disk->position % APPLE2_NIBBLE_SIZE) == 0)) apple525_save_current_track(img, FALSE); return read_value; }
static cassette_state get_default_state(const struct IODevice *dev) { assert(dev->type == IO_CASSETTE); return (cassette_state) (int) device_get_info_int(&dev->devclass, DEVINFO_INT_CASSETTE_DEFAULT_STATE); }
struct IODevice *devices_allocate(const game_driver *gamedrv) { struct SystemConfigurationParamBlock params; device_getinfo_handler handlers[64]; int count_overrides[sizeof(handlers) / sizeof(handlers[0])]; int createimage_optcount, count, i, j, position; const char *file_extensions, *info_string; char *converted_file_extensions; struct IODevice *devices = NULL; memset(handlers, 0, sizeof(handlers)); memset(count_overrides, 0, sizeof(count_overrides)); if (gamedrv->sysconfig_ctor) { memset(¶ms, 0, sizeof(params)); params.device_slotcount = sizeof(handlers) / sizeof(handlers[0]); params.device_handlers = handlers; params.device_countoverrides = count_overrides; gamedrv->sysconfig_ctor(¶ms); } /* count the amount of handlers that we have available */ for (count = 0; handlers[count]; count++) ; count++; /* for our purposes, include the tailing empty device */ devices = (struct IODevice *) auto_malloc(count * sizeof(struct IODevice)); memset(devices, 0, count * sizeof(struct IODevice)); position = 0; for (i = 0; i < count; i++) { devices[i].type = IO_COUNT; if (handlers[i]) { devices[i].devclass.get_info = handlers[i]; devices[i].devclass.gamedrv = gamedrv; /* convert file extensions from comma delimited to null delimited */ converted_file_extensions = NULL; file_extensions = device_get_info_string(&devices[i].devclass, DEVINFO_STR_FILE_EXTENSIONS); if (file_extensions) { converted_file_extensions = auto_malloc(strlen(file_extensions) + 2); for (j = 0; file_extensions[j]; j++) converted_file_extensions[j] = (file_extensions[j] != ',') ? file_extensions[j] : '\0'; converted_file_extensions[j + 0] = '\0'; converted_file_extensions[j + 1] = '\0'; } info_string = device_get_info_string(&devices[i].devclass, DEVINFO_STR_DEV_TAG); devices[i].tag = info_string ? auto_strdup(info_string) : NULL; devices[i].type = device_get_info_int(&devices[i].devclass, DEVINFO_INT_TYPE); devices[i].count = device_get_info_int(&devices[i].devclass, DEVINFO_INT_COUNT); devices[i].position = position; devices[i].file_extensions = converted_file_extensions; devices[i].readable = device_get_info_int(&devices[i].devclass, DEVINFO_INT_READABLE) ? 1 : 0; devices[i].writeable = device_get_info_int(&devices[i].devclass, DEVINFO_INT_WRITEABLE) ? 1 : 0; devices[i].creatable = device_get_info_int(&devices[i].devclass, DEVINFO_INT_CREATABLE) ? 1 : 0; devices[i].reset_on_load = device_get_info_int(&devices[i].devclass, DEVINFO_INT_RESET_ON_LOAD) ? 1 : 0; devices[i].must_be_loaded = device_get_info_int(&devices[i].devclass, DEVINFO_INT_MUST_BE_LOADED) ? 1 : 0; devices[i].load_at_init = device_get_info_int(&devices[i].devclass, DEVINFO_INT_LOAD_AT_INIT) ? 1 : 0; devices[i].not_working = device_get_info_int(&devices[i].devclass, DEVINFO_INT_NOT_WORKING) ? 1 : 0; devices[i].init = (device_init_handler) device_get_info_fct(&devices[i].devclass, DEVINFO_PTR_INIT); devices[i].exit = (device_exit_handler) device_get_info_fct(&devices[i].devclass, DEVINFO_PTR_EXIT); devices[i].load = (device_load_handler) device_get_info_fct(&devices[i].devclass, DEVINFO_PTR_LOAD); devices[i].create = (device_create_handler) device_get_info_fct(&devices[i].devclass, DEVINFO_PTR_CREATE); devices[i].unload = (device_unload_handler) device_get_info_fct(&devices[i].devclass, DEVINFO_PTR_UNLOAD); devices[i].imgverify = (device_verify_handler) device_get_info_fct(&devices[i].devclass, DEVINFO_PTR_VERIFY); devices[i].partialhash = (device_partialhash_handler) device_get_info_fct(&devices[i].devclass, DEVINFO_PTR_PARTIAL_HASH); devices[i].getdispositions = (device_getdispositions_handler) device_get_info_fct(&devices[i].devclass, DEVINFO_PTR_GET_DISPOSITIONS); devices[i].display = (device_display_handler) device_get_info_fct(&devices[i].devclass, DEVINFO_PTR_DISPLAY); devices[i].name = default_device_name; devices[i].createimage_optguide = (const struct OptionGuide *) device_get_info_ptr(&devices[i].devclass, DEVINFO_PTR_CREATE_OPTGUIDE); createimage_optcount = (int) device_get_info_int(&devices[i].devclass, DEVINFO_INT_CREATE_OPTCOUNT); if (createimage_optcount > 0) { if (createimage_optcount > DEVINFO_CREATE_OPTMAX) fatalerror("DEVINFO_INT_CREATE_OPTCOUNT: Too many options"); devices[i].createimage_options = auto_malloc((createimage_optcount + 1) * sizeof(*devices[i].createimage_options)); for (j = 0; j < createimage_optcount; j++) { info_string = device_get_info_string(&devices[i].devclass, DEVINFO_STR_CREATE_OPTNAME + j); devices[i].createimage_options[j].name = info_string ? auto_strdup(info_string) : NULL; info_string = device_get_info_string(&devices[i].devclass, DEVINFO_STR_CREATE_OPTDESC + j); devices[i].createimage_options[j].description = info_string ? auto_strdup(info_string) : NULL; info_string = device_get_info_string(&devices[i].devclass, DEVINFO_STR_CREATE_OPTEXTS + j); devices[i].createimage_options[j].extensions = info_string ? auto_strdup(info_string) : NULL; devices[i].createimage_options[j].optspec = device_get_info_ptr(&devices[i].devclass, DEVINFO_PTR_CREATE_OPTSPEC + j); } /* terminate the list */ memset(&devices[i].createimage_options[createimage_optcount], 0, sizeof(devices[i].createimage_options[createimage_optcount])); } position += devices[i].count; /* overriding the count? */ if (count_overrides[i]) devices[i].count = count_overrides[i]; /* any problems? */ if ((devices[i].type < 0) || (devices[i].type >= IO_COUNT)) goto error; if ((devices[i].count < 0) || (devices[i].count > MAX_DEV_INSTANCES)) goto error; /* fill in defaults */ if (!devices[i].getdispositions) devices[i].getdispositions = default_device_getdispositions; } } return devices; error: return NULL; }
static int validate_device(const device_class *devclass) { int error = 0; int is_invalid, i; const char *s; INT64 devcount, optcount; char buf[256]; char *s1; char *s2; iodevice_t devtype; int (*validity_check)(const device_class *devclass); /* critical information */ devtype = (iodevice_t) (int) device_get_info_int(devclass, DEVINFO_INT_TYPE); devcount = device_get_info_int(devclass, DEVINFO_INT_COUNT); /* sanity check device type */ if (devtype >= IO_COUNT) { printf("%s: invalid device type %i\n", devclass->gamedrv->name, (int) devtype); error = 1; } /* sanity check device count */ if ((devcount <= 0) || (devcount > MAX_DEV_INSTANCES)) { printf("%s: device type '%s' has an invalid device count %i\n", devclass->gamedrv->name, device_typename(devtype), (int) devcount); error = 1; } /* File Extensions Checks * * Checks the following * * 1. Tests the integrity of the string list * 2. Checks for duplicate extensions * 3. Makes sure that all extensions are either lower case chars or numbers */ s = device_get_info_string(devclass, DEVINFO_STR_FILE_EXTENSIONS); if (!s) { printf("%s: device type '%s' has null file extensions\n", devclass->gamedrv->name, device_typename(devtype)); error = 1; } else { memset(buf, 0, sizeof(buf)); strcpy(buf, s); /* convert to be null delimited */ s1 = buf; while(*s1) { if (*s1 == ',') *s1 = '\0'; s1++; } s1 = buf; while(*s1) { /* check for invalid chars */ is_invalid = 0; for (s2 = s1; *s2; s2++) { if (!isdigit(*s2) && !islower(*s2)) is_invalid = 1; } if (is_invalid) { printf("%s: device type '%s' has an invalid extension '%s'\n", devclass->gamedrv->name, device_typename(devtype), s1); error = 1; } s2++; /* check for dupes */ is_invalid = 0; while(*s2) { if (!strcmp(s1, s2)) is_invalid = 1; s2 += strlen(s2) + 1; } if (is_invalid) { printf("%s: device type '%s' has duplicate extensions '%s'\n", devclass->gamedrv->name, device_typename(devtype), s1); error = 1; } s1 += strlen(s1) + 1; } } /* enforce certain rules for certain device types */ switch(devtype) { case IO_QUICKLOAD: case IO_SNAPSHOT: if (devcount != 1) { printf("%s: there can only be one instance of devices of type '%s'\n", devclass->gamedrv->name, device_typename(devtype)); error = 1; } /* fallthrough */ case IO_CARTSLOT: if (!device_get_info_int(devclass, DEVINFO_INT_READABLE) || device_get_info_int(devclass, DEVINFO_INT_WRITEABLE) || device_get_info_int(devclass, DEVINFO_INT_CREATABLE)) { printf("%s: devices of type '%s' has invalid open modes\n", devclass->gamedrv->name, device_typename(devtype)); error = 1; } break; default: break; } /* check creation options */ optcount = device_get_info_int(devclass, DEVINFO_INT_CREATE_OPTCOUNT); if ((optcount < 0) || (optcount >= DEVINFO_CREATE_OPTMAX)) { printf("%s: device type '%s' has an invalid creation optcount\n", devclass->gamedrv->name, device_typename(devtype)); error = 1; } else { for (i = 0; i < (int) optcount; i++) { if (!device_get_info_string(devclass, DEVINFO_STR_CREATE_OPTNAME + i)) { printf("%s: device type '%s' create option #%d: name not present\n", devclass->gamedrv->name, device_typename(devtype), i); error = 1; } if (!device_get_info_string(devclass, DEVINFO_STR_CREATE_OPTDESC + i)) { printf("%s: device type '%s' create option #%d: description not present\n", devclass->gamedrv->name, device_typename(devtype), i); error = 1; } if (!device_get_info_string(devclass, DEVINFO_STR_CREATE_OPTEXTS + i)) { printf("%s: device type '%s' create option #%d: extensions not present\n", devclass->gamedrv->name, device_typename(devtype), i); error = 1; } } } /* is there a custom validity check? */ validity_check = (int (*)(const device_class *)) device_get_info_fct(devclass, DEVINFO_PTR_VALIDITY_CHECK); if (validity_check) { if (validity_check(devclass)) error = 1; } return error; }