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; }
static const char *default_device_name(const struct IODevice *dev, int id, char *buf, size_t bufsize) { const char *name; /* use the cool new device string technique */ name = device_get_info_string(&dev->devclass, DEVINFO_STR_DESCRIPTION+id); if (name) { snprintf(buf, bufsize, "%s", name); return buf; } name = ui_getstring((UI_cartridge - IO_CARTSLOT) + dev->type); if (dev->count > 1) { /* for the average user counting starts at #1 ;-) */ snprintf(buf, bufsize, "%s #%d", name, id + 1); name = buf; } return name; }
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; }