imgtool: WIP on hp9845 tape: read done, write & del to be done

This commit is contained in:
fulivi 2016-09-10 15:49:49 +02:00
parent 0474948833
commit e39c05c165

View File

@ -25,6 +25,8 @@
#define SECTORS_PER_DIR 2 // Sectors per copy of directory #define SECTORS_PER_DIR 2 // Sectors per copy of directory
#define MAX_DIR_ENTRIES 42 // And the answer is.... the maximum number of entries in the directory! #define MAX_DIR_ENTRIES 42 // And the answer is.... the maximum number of entries in the directory!
#define DIR_COPIES 2 // Count of directory copies #define DIR_COPIES 2 // Count of directory copies
#define CHARS_PER_FNAME 6 // Maximum characters in a filename
#define CHARS_PER_FNAME_EXT (CHARS_PER_FNAME + 1 + 4) // Characters in filename + extension
#define PAD_WORD 0xffff // Word value for padding #define PAD_WORD 0xffff // Word value for padding
#define FIRST_FILE_SECTOR (FIRST_DIR_SECTOR + SECTORS_PER_DIR * DIR_COPIES) // First file sector #define FIRST_FILE_SECTOR (FIRST_DIR_SECTOR + SECTORS_PER_DIR * DIR_COPIES) // First file sector
#define MAGIC 0x5441434f // Magic value at start of image file: "TACO" #define MAGIC 0x5441434f // Magic value at start of image file: "TACO"
@ -81,7 +83,7 @@ typedef INT32 tape_pos_t;
* Directory entries * Directory entries
********************************************************************************/ ********************************************************************************/
typedef struct { typedef struct {
UINT8 filename[ 6 ];// Filename (left justified, 0 padded on the right) UINT8 filename[ CHARS_PER_FNAME ]; // Filename (left justified, 0 padded on the right)
bool protection; // File protection bool protection; // File protection
UINT8 filetype; // File type (00-1f) UINT8 filetype; // File type (00-1f)
UINT16 filepos; // File position (# of 1st sector) UINT16 filepos; // File position (# of 1st sector)
@ -108,8 +110,15 @@ public:
void set_sector(unsigned s_no , const tape_word_t *s_data); void set_sector(unsigned s_no , const tape_word_t *s_data);
void unset_sector(unsigned s_no); void unset_sector(unsigned s_no);
bool get_sector(unsigned s_no , tape_word_t *s_data);
bool get_dir_entry(unsigned idx , dir_entry_t& entry); bool get_dir_entry(unsigned idx , dir_entry_t& entry);
bool get_dir_entry(const char* filename , dir_entry_t& entry);
static void tape_word_to_bytes(tape_word_t w , UINT8& bh , UINT8& bl);
static void bytes_to_tape_word(UINT8 bh , UINT8 bl , tape_word_t& w);
static void get_filename_and_ext(const dir_entry_t& ent , char *out , bool& qmark);
private: private:
bool dirty; bool dirty;
@ -121,8 +130,6 @@ private:
std::vector<dir_entry_t> dir; std::vector<dir_entry_t> dir;
static void wipe_sector(tape_word_t *s); static void wipe_sector(tape_word_t *s);
static void tape_word_to_bytes(tape_word_t w , UINT8& bh , UINT8& bl);
static void bytes_to_tape_word(UINT8 bh , UINT8 bl , tape_word_t& w);
void dump_dir_sect(const tape_word_t *dir_sect , unsigned dir_sect_idx); void dump_dir_sect(const tape_word_t *dir_sect , unsigned dir_sect_idx);
void fill_and_dump_dir_sect(tape_word_t *dir_sect , unsigned& idx , unsigned& dir_sect_idx , tape_word_t w) ; void fill_and_dump_dir_sect(tape_word_t *dir_sect , unsigned& idx , unsigned& dir_sect_idx , tape_word_t w) ;
void encode_dir(void); void encode_dir(void);
@ -476,6 +483,16 @@ void tape_image_t::unset_sector(unsigned s_no)
} }
} }
bool tape_image_t::get_sector(unsigned s_no , tape_word_t *s_data)
{
if (s_no < TOT_SECTORS && alloc_map[ s_no ]) {
memcpy(s_data , &img[ s_no ][ 0 ] , SECTOR_LEN);
return true;
} else {
return false;
}
}
bool tape_image_t::get_dir_entry(unsigned idx , dir_entry_t& entry) bool tape_image_t::get_dir_entry(unsigned idx , dir_entry_t& entry)
{ {
if (idx >= dir.size()) { if (idx >= dir.size()) {
@ -486,6 +503,22 @@ bool tape_image_t::get_dir_entry(unsigned idx , dir_entry_t& entry)
} }
} }
bool tape_image_t::get_dir_entry(const char* filename , dir_entry_t& entry)
{
for (const dir_entry_t& ent : dir) {
char full_fname[ CHARS_PER_FNAME_EXT + 1 ];
bool qmark;
get_filename_and_ext(ent, full_fname, qmark);
if (strcmp(filename , full_fname) == 0) {
entry = ent;
return true;
}
}
return false;
}
void tape_image_t::wipe_sector(tape_word_t *s) void tape_image_t::wipe_sector(tape_word_t *s)
{ {
for (unsigned i = 0; i < WORDS_PER_SECTOR; i++) { for (unsigned i = 0; i < WORDS_PER_SECTOR; i++) {
@ -616,6 +649,36 @@ bool tape_image_t::filename_check(const UINT8 *filename)
return true; return true;
} }
static const char *const filetype_attrs[] = {
BKUP_ATTR_STR, // 0
DATA_ATTR_STR, // 1
PROG_ATTR_STR, // 2
KEYS_ATTR_STR, // 3
BDAT_ATTR_STR, // 4
ALL_ATTR_STR, // 5
BPRG_ATTR_STR, // 6
OPRM_ATTR_STR // 7
};
void tape_image_t::get_filename_and_ext(const dir_entry_t& ent , char *out , bool& qmark)
{
strncpy(&out[ 0 ] , (const char*)&ent.filename[ 0 ] , CHARS_PER_FNAME);
out[ CHARS_PER_FNAME ] = '\0';
// Decode filetype
UINT8 type_low = ent.filetype & 7;
UINT8 type_hi = (ent.filetype >> 3) & 3;
const char *filetype_str = filetype_attrs[ type_low ];
// Same logic used by hp9845b to add a question mark next to filetype
qmark = (type_low == DATA_FILETYPE && type_hi == 3) ||
(type_low != DATA_FILETYPE && type_hi != 2);
strcat(out , ".");
strcat(out , filetype_str);
}
bool tape_image_t::decode_dir(void) bool tape_image_t::decode_dir(void)
{ {
unsigned sect_no = FIRST_DIR_SECTOR - 1; unsigned sect_no = FIRST_DIR_SECTOR - 1;
@ -795,17 +858,6 @@ static imgtoolerr_t hp9845_tape_begin_enum (imgtool_directory *enumeration, cons
return IMGTOOLERR_SUCCESS; return IMGTOOLERR_SUCCESS;
} }
static const char *const filetype_attrs[] = {
BKUP_ATTR_STR, // 0
DATA_ATTR_STR, // 1
PROG_ATTR_STR, // 2
KEYS_ATTR_STR, // 3
BDAT_ATTR_STR, // 4
ALL_ATTR_STR, // 5
BPRG_ATTR_STR, // 6
OPRM_ATTR_STR // 7
};
static imgtoolerr_t hp9845_tape_next_enum (imgtool_directory *enumeration, imgtool_dirent *ent) static imgtoolerr_t hp9845_tape_next_enum (imgtool_directory *enumeration, imgtool_dirent *ent)
{ {
tape_state_t& state = get_tape_state(imgtool_directory_image(enumeration)); tape_state_t& state = get_tape_state(imgtool_directory_image(enumeration));
@ -819,25 +871,12 @@ static imgtoolerr_t hp9845_tape_next_enum (imgtool_directory *enumeration, imgto
} else { } else {
ds->dir_idx++; ds->dir_idx++;
UINT8 tmp_fn[ 7 ]; bool qmark;
memcpy(&tmp_fn[ 0 ] , &entry.filename[ 0 ] , 6); tape_image_t::get_filename_and_ext(entry, ent->filename, qmark);
tmp_fn[ 6 ] = '\0';
// Decode filetype
UINT8 type_low = entry.filetype & 7;
UINT8 type_hi = (entry.filetype >> 3) & 3;
const char *filetype_str = filetype_attrs[ type_low ];
// Same logic used by hp9845b to add a question mark next to filetype
bool qmark = (type_low == DATA_FILETYPE && type_hi == 3) ||
(type_low != DATA_FILETYPE && type_hi != 2);
// "filename" and "attr" fields try to look like the output of the "CAT" command // "filename" and "attr" fields try to look like the output of the "CAT" command
snprintf(ent->filename , sizeof(ent->filename) , "%-6s %c %s%c" , tmp_fn , entry.protection ? '*' : ' ' , filetype_str , qmark ? '?' : ' '); snprintf(ent->attr , sizeof(ent->attr) , "%c %02x%c %4u %4u %3u" , entry.protection ? '*' : ' ' , entry.filetype , qmark ? '?' : ' ' , entry.n_recs , entry.wpr * 2 , entry.filepos);
snprintf(ent->attr , sizeof(ent->attr) , "%4u %4u %3u" , entry.n_recs , entry.wpr * 2 , entry.filepos);
ent->filesize = entry.n_sects * SECTOR_LEN; ent->filesize = entry.n_sects * SECTOR_LEN;
} }
@ -859,8 +898,28 @@ static imgtoolerr_t hp9845_tape_read_file(imgtool_partition *partition, const ch
tape_state_t& state = get_tape_state(imgtool_partition_image(partition)); tape_state_t& state = get_tape_state(imgtool_partition_image(partition));
tape_image_t& tape_image = get_tape_image(state); tape_image_t& tape_image = get_tape_image(state);
// TODO: dir_entry_t ent;
return IMGTOOLERR_UNIMPLEMENTED;
if (!tape_image.get_dir_entry(filename, ent)) {
return IMGTOOLERR_FILENOTFOUND;
}
unsigned sect_no = ent.filepos;
tape_word_t buff_w[ WORDS_PER_SECTOR ];
UINT8 buff_b[ SECTOR_LEN ];
while (ent.n_sects--) {
if (!tape_image.get_sector(sect_no++, &buff_w[ 0 ])) {
return IMGTOOLERR_READERROR;
}
for (unsigned i = 0; i < WORDS_PER_SECTOR; i++) {
tape_image_t::tape_word_to_bytes(buff_w[ i ], buff_b[ i * 2 ], buff_b[ i * 2 + 1 ]);
}
stream_write(destf , buff_b , SECTOR_LEN);
}
return IMGTOOLERR_SUCCESS;
} }
void hp9845_tape_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info) void hp9845_tape_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
@ -919,4 +978,3 @@ void hp9845_tape_get_info(const imgtool_class *imgclass, UINT32 state, union img
break; break;
} }
} }