static void dump_result(nameinfo_t *result) { printf("CMD=%s\n", command_to_name(result->cmd)); printf("DRIVE=%c\n", result->drive == NAMEINFO_UNUSED_DRIVE ? '-' : (result->drive == NAMEINFO_UNDEF_DRIVE ? '*' : (result->drive == NAMEINFO_LAST_DRIVE ? 'L' : result->drive + 0x30))); printf("DRIVENAME='%s'\n", result->drivename ? (char*) result->drivename : nullstring); printf("NAME='%s' (%d)\n", result->name ? (char*)result->name : nullstring, result->namelen); printf("ACCESS=%c\n", result->access ? result->access : '-'); printf("TYPE=%c", result->type ? result->type : '-'); debug_putcrlf(); printf("DRIVE2=%c\n", result->file[0].drive == NAMEINFO_UNUSED_DRIVE ? '-' : (result->file[0].drive == NAMEINFO_UNDEF_DRIVE ? '*' : (result->file[0].drive == NAMEINFO_LAST_DRIVE ? 'L' : result->file[0].drive + 0x30))); printf("DRIVENAME2='%s'\n", result->file[0].drivename ? (char*) result->file[0].drivename : nullstring); printf("NAME2='%s' (%d)\n", result->file[0].name ? (char*)result->file[0].name : nullstring, result->file[0].namelen); printf("RECLEN=%d\n", result->recordlen); debug_flush(); }
// opens the file, registers an error code in command->error if necessary // If the open was successful, setup a channel for the given channel number // (note: explicitely not secondary device number, as IEEE and IEC in parallel // use overlapping numbers, so they may be shifted or similar to avoid clashes) // // The command buffer is used as transmit buffer, so it must not be overwritten // until the open has been sent. // // note that if it returns a value <0 on error, it has to have the error message // set appropriately. // int8_t file_open(uint8_t channel_no, bus_t *bus, errormsg_t *errormsg, void (*callback)(int8_t errnum, uint8_t *rxdata), uint8_t openflag) { assert_not_null(bus, "file_open: bus is null"); cmd_t *command = &(bus->command); rtconfig_t *rtconf = &(bus->rtconf); #ifdef DEBUG_FILE debug_printf("OPEN FILE: FOR CHAN: %d WITH NAME: '%s', OPENFLAG=%d\n", channel_no, (char*)&(command->command_buffer), openflag); #endif // note: in a preemtive env, the following would have to be protected // to be atomic as we modify static variables parse_filename(command, &nameinfo, (openflag & OPENFLAG_LOAD) ? PARSEHINT_LOAD : 0); #ifdef DEBUG_FILE debug_printf(" PARSE -> ACCESS=%c, TYPE=%c\n", nameinfo.access, nameinfo.type); #endif // drive handling needed for error message drive if (nameinfo.drive == NAMEINFO_LAST_DRIVE) { nameinfo.drive = rtconf->last_used_drive; } else if (nameinfo.drive == NAMEINFO_UNUSED_DRIVE) { // TODO: match CBM behavior nameinfo.drive = rtconf->last_used_drive; } int8_t errdrive = rtconf->errmsg_with_drive ? nameinfo.drive : -1; // post-parse if (nameinfo.cmd != CMD_NONE && nameinfo.cmd != CMD_DIR && nameinfo.cmd != CMD_OVERWRITE) { // command name during open // this is in fact ignored by CBM DOS as checked with VICE's true drive emulation debug_printf("NO CORRECT CMD: %s\n", command_to_name(nameinfo.cmd)); nameinfo.cmd = 0; } if (nameinfo.type != 0 && nameinfo.type != 'S' && nameinfo.type != 'P' && nameinfo.type != 'U' && nameinfo.type != 'L') { // not set, or set as not sequential and not program debug_puts("UNKOWN FILE TYPE: "); debug_putc(nameinfo.type); debug_putcrlf(); set_error_tsd(errormsg, CBM_ERROR_FILE_TYPE_MISMATCH, 0, 0, errdrive); return -1; } if (nameinfo.access != 0 && nameinfo.access != 'W' && nameinfo.access != 'R' && nameinfo.access != 'A' && nameinfo.access != 'X') { debug_puts("UNKNOWN FILE ACCESS TYPE "); debug_putc(nameinfo.access); debug_putcrlf(); // not set, or set as not read, write, or append, or r/w ('X') set_error_tsd(errormsg, CBM_ERROR_SYNTAX_UNKNOWN, 0, 0, errdrive); return -1; } if (nameinfo.cmd == CMD_DIR && (nameinfo.access != 0 && nameinfo.access != 'R')) { // trying to write to a directory debug_puts("WRITE TO DIRECTORY!"); debug_putcrlf(); set_error_tsd(errormsg, CBM_ERROR_FILE_EXISTS, 0, 0, errdrive); return -1; } uint8_t type = FS_OPEN_RD; // file access default if (nameinfo.access == 0) { if (openflag == OPENFLAG_LOAD) { nameinfo.access = 'R'; } else if (openflag == OPENFLAG_SAVE) { nameinfo.access = 'W'; } } // file type defaults if (nameinfo.type == 0) { // do we create a file (access=='W')? if (nameinfo.access == 'W') { // write (like save) if (openflag == OPENFLAG_SAVE) { nameinfo.type = 'P'; } else { nameinfo.type = 'S'; } } if (nameinfo.access == 'R') { if (openflag == OPENFLAG_LOAD) { // on load, 'P' is the default nameinfo.type = 'P'; } } } if (nameinfo.access == 'X') { // trying to open up a R/W channel debug_puts("OPENING UP A R/W CHANNEL!"); debug_putcrlf(); type = FS_OPEN_RW; } if (nameinfo.name[0] == '#') { // trying to open up a direct channel // Note: needs to be supported for D64 support with U1/U2/... // Note: '#' is still blocking on read! debug_puts("OPENING UP A DIRECT CHANNEL!"); debug_putcrlf(); type = FS_OPEN_DIRECT; } // if ",W" or secondary address is one, i.e. save if (nameinfo.access == 'W') { type = FS_OPEN_WR; } if (nameinfo.access == 'A') { type = FS_OPEN_AP; } if (nameinfo.cmd == CMD_DIR) { if (openflag & OPENFLAG_LOAD) { type = FS_OPEN_DR; } else { type = FS_OPEN_RD; } } else if (nameinfo.cmd == CMD_OVERWRITE) { type = FS_OPEN_OW; } #ifdef DEBUG_FILE debug_printf("NAME='%s' (%d)\n", nameinfo.name, nameinfo.namelen); debug_printf("ACCESS=%c\n", nameinfo.access); debug_printf("CMD=%d\n", nameinfo.cmd); debug_flush(); #endif return file_submit_call(channel_no, type, command->command_buffer, errormsg, rtconf, callback, 0); }