/** * open_buffer - function to open a direct-access buffer * @secondary: secondary address used * * This function is called when the computer wants to open a direct * access buffer (#). */ static void open_buffer(uint8_t secondary) { buffer_t *buf,*prev; uint8_t count; if (command_length == 3 && command_buffer[1] == '#') { /* Open a large buffer */ count = command_buffer[2] - '0'; if (count == 0) return; /* Allocate a chain of linked buffers */ buf = alloc_linked_buffers(count); if (buf == NULL) return; do { buf->secondary = BUFFER_SEC_CHAIN - secondary; buf->refill = directbuffer_refill; buf->cleanup = largebuffer_cleanup; buf->read = 1; buf->lastused = 255; stick_buffer(buf); mark_write_buffer(buf); prev = buf; buf = buf->pvt.buffer.next; } while (buf != NULL); prev->sendeoi = 1; buf = prev->pvt.buffer.first; /* Set the first buffer as active by using the real secondary */ buf->secondary = secondary; } else { /* Normal buffer request */ // FIXME: This command can specify a specific buffer number. buf = alloc_buffer(); if (!buf) return; buf->secondary = secondary; buf->read = 1; buf->position = 1; /* Sic! */ buf->lastused = 255; buf->sendeoi = 1; buf->pvt.buffer.size = 1; /* directbuffer_refill is used to check for # buffers in iec.c */ buf->refill = directbuffer_refill; buf->pvt.buffer.first = buf; mark_write_buffer(buf); stick_buffer(buf); } return; }
static void eefs_open_read(path_t *path, cbmdirent_t *dent, buffer_t *buf) { eefs_error_t res; repad_filename(dent->name); res = eepromfs_open(dent->name, &buf->pvt.eefh, EEFS_MODE_READ); translate_error(res); if (res != EEFS_ERROR_OK) return; /* set up the buffer */ buf->read = 1; buf->refill = eefs_refill_read; // no cleanup/close function needed for read-only files stick_buffer(buf); buf->refill(buf); }
/** * load_directory - Prepare directory generation and create header * @secondary: secondary address used for reading the directory * * This function prepeares directory reading and fills the buffer * with the header line of the directory listing. * BUG: There is a not-well-known feature in the 1541/1571 disk * drives (and possibly others) that returns unparsed directory * sectors if $ is opened with a secondary address != 0. This * is not emulated here. */ static void load_directory(uint8_t secondary) { buffer_t *buf; path_t path; uint8_t pos=1; buf = alloc_buffer(); if (!buf) return; uint8_t *name; buf->secondary = secondary; buf->read = 1; buf->lastused = 31; if (command_length > 2 && secondary == 0) { if(command_buffer[1]=='=') { if(command_buffer[2]=='P') { /* Parse Partition Directory */ /* copy static header to start of buffer */ memcpy_P(buf->data, dirheader, sizeof(dirheader)); memcpy_P(buf->data + 32, syspart_line, sizeof(syspart_line)); buf->lastused = 63; /* set partition number */ buf->data[HEADER_OFFSET_DRIVE] = max_part; /* Let the refill callback handle everything else */ buf->refill = pdir_refill; if(command_length>3) { /* Parse the name pattern */ if (parse_path(command_buffer+3, &path, &name, 0)) return; buf->pvt.pdir.matchstr = name; } stick_buffer(buf); return; } else if(command_buffer[2]=='T') { buf->pvt.dir.format = DIR_FMT_CMD_SHORT; pos=3; } } } if (command_buffer[pos]) { /* do we have a path to scan? */ if (command_length > 2) { /* Parse the name pattern */ if (parse_path(command_buffer+pos, &path, &name, 0)) return; if (opendir(&buf->pvt.dir.dh, &path)) return; buf->pvt.dir.matchstr = name; /* Check for a filetype match */ name = ustrchr(name, '='); if (name != NULL) { *name++ = 0; switch (*name) { case 'S': buf->pvt.dir.filetype = TYPE_SEQ; break; case 'P': buf->pvt.dir.filetype = TYPE_PRG; break; case 'U': buf->pvt.dir.filetype = TYPE_USR; break; case 'R': buf->pvt.dir.filetype = TYPE_REL; break; case 'C': /* This is guessed, not verified */ buf->pvt.dir.filetype = TYPE_CBM; break; case 'B': /* CMD compatibility */ case 'D': /* Specifying DEL matches everything anyway */ buf->pvt.dir.filetype = TYPE_DIR; break; case 'H': /* Extension: Also show hidden files */ buf->pvt.dir.filetype = FLAG_HIDDEN; break; } if(buf->pvt.dir.filetype) { name++; if(*name++ != ',') { goto scandone; } } while(*name) { switch(*name++) { case '>': if(parse_date(&date_match_start,&name)) goto scandone; if(date_match_start.month && date_match_start.day) // ignore 00/00/00 buf->pvt.dir.match_start = &date_match_start; break; case '<': if(parse_date(&date_match_end,&name)) goto scandone; if(date_match_end.month && date_match_end.day) // ignore 00/00/00 buf->pvt.dir.match_end = &date_match_end; break; case 'L': /* don't switch to long format if 'N' has already been sent */ if(buf->pvt.dir.format != DIR_FMT_CBM) buf->pvt.dir.format = DIR_FMT_CMD_LONG; break; case 'N': buf->pvt.dir.format=DIR_FMT_CBM; /* turn off extended listing */ break; default: goto scandone; } if(*name && *name++ != ',') { goto scandone; } } } } else { /* Command string is two characters long, parse the drive */ if (command_buffer[1] == '0') path.part = current_part; else path.part = command_buffer[1] - '0' - 1; if (path.part >= max_part) { set_error(ERROR_DRIVE_NOT_READY); return; } path.dir = partition[path.part].current_dir; if (opendir(&buf->pvt.dir.dh, &path)) return; } } else { path.part = current_part; path.dir = partition[path.part].current_dir; // if you do not do this, get_label will fail below. if (opendir(&buf->pvt.dir.dh, &path)) return; } scandone: if (secondary != 0) { /* Raw directory */ if (partition[path.part].fop == &d64ops) { /* No need to fake it for D64 files */ d64_raw_directory(&path, buf); return; } /* prepare a fake BAM sector */ memset(buf->data, 0, 256); memset(buf->data + BAM_OFFSET_NAME - 2, 0xa0, BAM_A0_AREA_SIZE); /* fill label and id */ if (dir_label(&path, buf->data + BAM_OFFSET_NAME - 2)) return; if (disk_id(&path, buf->data + BAM_OFFSET_ID - 2)) return; /* change padding of label and id to 0xa0 */ name = buf->data + BAM_OFFSET_NAME - 2 + CBM_NAME_LENGTH; while (*--name == ' ') *name = 0xa0; if (buf->data[BAM_OFFSET_ID+2-2] == 0x20) buf->data[BAM_OFFSET_ID+2-2] = 0xa0; /* DOS version marker */ buf->data[0] = 'A'; buf->refill = rawdir_refill; buf->lastused = 253; } else { /* copy static header to start of buffer */ memcpy_P(buf->data, dirheader, sizeof(dirheader)); /* set partition number */ buf->data[HEADER_OFFSET_DRIVE] = path.part+1; /* read directory name */ if (dir_label(&path, buf->data+HEADER_OFFSET_NAME)) return; /* read id */ if (disk_id(&path,buf->data+HEADER_OFFSET_ID)) return; /* Let the refill callback handle everything else */ buf->refill = dir_refill; } /* Keep the buffer around */ stick_buffer(buf); return; }