// license:BSD-3-Clause // copyright-holders:Nathan Woods /**************************************************************************** rsdos.cpp CoCo RS-DOS disk images ****************************************************************************/ #include "imgtool.h" #include "filter.h" #include "iflopimg.h" #include "formats/coco_dsk.h" #include "corestr.h" #include "opresolv.h" #include #include #include /* this structure mirrors the structure of an RS-DOS directory entry on disk */ struct rsdos_dirent { char filename[11]; char ftype; char asciiflag; unsigned char first_granule; unsigned char lastsectorbytes_msb; unsigned char lastsectorbytes_lsb; unsigned char unused[16]; }; struct rsdos_direnum { int index; bool eof; }; #define RSDOS_OPTIONS_FTYPE 'T' #define RSDOS_OPTIONS_ASCII 'M' /********************************************************************* Imgtool module code *********************************************************************/ #define MAX_DIRENTS ((18-2)*(256/32)) #define MAX_GRANULEMAP_SIZE 256 //------------------------------------------------- // get_rsdos_dirent //------------------------------------------------- static floperr_t get_rsdos_dirent(imgtool::image &f, int index_loc, rsdos_dirent &ent) { return floppy_read_sector(imgtool_floppy(f), 0, 17, 3, index_loc * 32, (void *) &ent, sizeof(ent)); } //------------------------------------------------- // put_rsdos_dirent //------------------------------------------------- static floperr_t put_rsdos_dirent(imgtool::image &f, int index_loc, const rsdos_dirent &ent) { if (index_loc >= MAX_DIRENTS) return (floperr_t)IMGTOOLERR_FILENOTFOUND; return floppy_write_sector(imgtool_floppy(f), 0, 17, 3, index_loc * 32, (void *) &ent, sizeof(ent), 0); /* TODO: pass ddam argument from imgtool */ } //------------------------------------------------- // get_dirent_fname //------------------------------------------------- static std::string get_dirent_fname(const rsdos_dirent &ent) { return extract_padded_filename(ent.filename, 8, 3); } //------------------------------------------------- // lookup_rsdos_file //------------------------------------------------- static imgtoolerr_t lookup_rsdos_file(imgtool::image &f, const char *fname, rsdos_dirent &ent, int *position = nullptr) { int i; floperr_t ferr; std::string fnamebuf; i = 0; do { do { ferr = get_rsdos_dirent(f, i++, ent); if (ferr) return imgtool_floppy_error(ferr); } while(ent.filename[0] == '\0'); if (ent.filename[0] != -1) fnamebuf = get_dirent_fname(ent); } while((ent.filename[0] != -1) && core_stricmp(fnamebuf, fname)); if (ent.filename[0] == -1) return IMGTOOLERR_FILENOTFOUND; if (position) *position = i - 1; return (imgtoolerr_t)0; } //------------------------------------------------- // get_granule_count //------------------------------------------------- static uint8_t get_granule_count(imgtool::image &img) { uint16_t tracks; uint16_t granules; tracks = floppy_get_tracks_per_disk(imgtool_floppy(img)); granules = (tracks - 1) * 2; return (granules > 255) ? 255 : (uint8_t) granules; } //------------------------------------------------- // get_granule_map //------------------------------------------------- static floperr_t get_granule_map(imgtool::image &img, uint8_t *granule_map, uint8_t granule_count[MAX_GRANULEMAP_SIZE]) { uint8_t count; count = get_granule_count(img); if (granule_count) *granule_count = count; return floppy_read_sector(imgtool_floppy(img), 0, 17, 2, 0, granule_map, count); } //------------------------------------------------- // put_granule_map //------------------------------------------------- static floperr_t put_granule_map(imgtool::image &img, const uint8_t *granule_map, uint8_t granule_count) { return floppy_write_sector(imgtool_floppy(img), 0, 17, 2, 0, granule_map, granule_count, 0); /* TODO: pass ddam argument from imgtool */ } //------------------------------------------------- // transfer_granule //------------------------------------------------- static imgtoolerr_t transfer_granule(imgtool::image &img, uint8_t granule, int length, imgtool::stream &f, imgtoolerr_t (*proc)(imgtool::image &, int, int, int, int, size_t, imgtool::stream &)) { imgtoolerr_t err = IMGTOOLERR_SUCCESS; uint8_t track, sector; track = granule / 2; if (track >= 17) track++; sector = (granule % 2) ? 10 : 1; if (length > 0) err = proc(img, 0, track, sector, 0, length, f); return err; } //------------------------------------------------- // transfer_from_granule //------------------------------------------------- static imgtoolerr_t transfer_from_granule(imgtool::image &img, uint8_t granule, int length, imgtool::stream &destf) { return transfer_granule(img, granule, length, destf, imgtool_floppy_read_sector_to_stream); } //------------------------------------------------- // transfer_to_granule //------------------------------------------------- static imgtoolerr_t transfer_to_granule(imgtool::image &img, uint8_t granule, int length, imgtool::stream &sourcef) { return transfer_granule(img, granule, length, sourcef, imgtool_floppy_write_sector_from_stream); } //------------------------------------------------- // process_rsdos_file //------------------------------------------------- static imgtoolerr_t process_rsdos_file(struct rsdos_dirent *ent, imgtool::image &img, imgtool::stream *destf, size_t &size) { f
.. _frontends:

Frontends
=========

There are a number of third party tools for MAME to make system and software selection simpler. These tools are called "Frontends", and there are far too many to list conclusively here. Some are free, some are commercial-- caveat emptor. Some older frontends predate the merging of MAME and MESS and do not support the additional console, handheld, etc functionality that MAME inherited from MESS.

This following list is not an endorsement of any of these frontends by the MAME team, but simply showing a number of commonly used free frontends as a good starting point to begin from.

| QMC2 (multiple platforms)
| Download: http://qmc2.batcom-it.net/
|
| IV/Play (Microsoft Windows)
| Download: http://www.mameui.info/
|
| EmuLoader (Microsoft Windows)
| Download: http://emuloader.mameworld.info/
|

The MAME team will not provide support for issues with frontends. For support, we suggest contacting the frontend author or trying any of the popular MAME-friendly forums on the internet.
oppy_error(ferr); g = 0x00; do { while (granule_map[g] != 0xff) { g++; if ((g >= granule_count) || (g == 0)) return IMGTOOLERR_UNEXPECTED; // we should have already verified that there is enough space } *gptr = g; gptr = &granule_map[g]; i = std::min(sz, uint64_t(9*256)); err = transfer_to_granule(img, g, i, sourcef); if (err) return err; sz -= i; // go to next granule g++; } while(sz > 0); // now that we are done with the file, we need to specify the final entry // in the file allocation table *gptr = 0xc0 + ((i + 255) / 256); // now we need to find an empty directory entry i = -1; do { ferr = get_rsdos_dirent(img, ++i, ent2); if (ferr) return imgtool_floppy_error(ferr); } while((ent2.filename[0] != '\0') && strcmp(ent.filename, ent2.filename) && (ent2.filename[0] != -1)); // delete file if it already exists if (ent2.filename[0] && (ent2.filename[0] != -1)) { err = delete_entry(img, ent2, i); if (err) return err; } ferr = put_rsdos_dirent(img, i, ent); if (ferr) return imgtool_floppy_error(ferr); // write the granule map back out ferr = put_granule_map(img, granule_map, granule_count); if (ferr) return imgtool_floppy_error(ferr); return IMGTOOLERR_SUCCESS; } //------------------------------------------------- // rsdos_diskimage_deletefile //------------------------------------------------- static imgtoolerr_t rsdos_diskimage_deletefile(imgtool::partition &partition, const char *fname) { imgtoolerr_t err; imgtool::image &image(partition.image()); int pos; struct rsdos_dirent ent; err = lookup_rsdos_file(image, fname, ent, &pos); if (err) return err; return delete_entry(image, ent, pos); } //------------------------------------------------- // rsdos_diskimage_suggesttransfer //------------------------------------------------- static imgtoolerr_t rsdos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool::transfer_suggestion *suggestions, size_t suggestions_length) { imgtoolerr_t err; imgtool::image &image(partition.image()); struct rsdos_dirent ent; int pos; if (fname) { err = lookup_rsdos_file(image, fname, ent, &pos); if (err) return err; if (ent.asciiflag == (char) 0xFF) { /* ASCII file */ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED; suggestions[0].filter = filter_eoln_getinfo; suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE; suggestions[1].filter = nullptr; } else if (ent.ftype == 0) { /* tokenized BASIC file */ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED; suggestions[0].filter = nullptr; suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE; suggestions[1].filter = filter_cocobas_getinfo; } } else { suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED; suggestions[0].filter = nullptr; suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE; suggestions[1].filter = filter_eoln_getinfo; suggestions[2].viability = imgtool::SUGGESTION_POSSIBLE; suggestions[2].filter = filter_cocobas_getinfo; } return IMGTOOLERR_SUCCESS; } /********************************************************************* Imgtool module declaration *********************************************************************/ OPTION_GUIDE_START( coco_rsdos_writefile_optionguide ) OPTION_ENUM_START( RSDOS_OPTIONS_FTYPE, "ftype", "File type" ) OPTION_ENUM( 0, "basic", "Basic" ) OPTION_ENUM( 1, "data", "Data" ) OPTION_ENUM( 2, "binary", "Binary" ) OPTION_ENUM( 3, "assembler", "Assembler Source" ) OPTION_ENUM_END OPTION_ENUM_START( RSDOS_OPTIONS_ASCII, "ascii", "Ascii flag" ) OPTION_ENUM( 0, "ascii", "Ascii" ) OPTION_ENUM( 1, "binary", "Binary" ) OPTION_ENUM_END OPTION_GUIDE_END void rsdos_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoolinfo *info) { switch(state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case IMGTOOLINFO_INT_PREFER_UCASE: info->i = 1; break; case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct rsdos_direnum); break; /* --- the following bits of info are returned as NUL-terminated strings --- */ case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "rsdos"); break; case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "RS-DOS format"); break; case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break; case IMGTOOLINFO_STR_EOLN: strcpy(info->s = imgtool_temp_str(), "\r"); break; case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), "T0-[2]-3;M0-[1]"); break; /* --- the following bits of info are returned as pointers to data or functions --- */ case IMGTOOLINFO_PTR_MAKE_CLASS: info->make_class = imgtool_floppy_make_class; break; case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = rsdos_diskimage_nextenum; break; case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = rsdos_diskimage_freespace; break; case IMGTOOLINFO_PTR_READ_FILE: info->read_file = rsdos_diskimage_readfile; break; case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = rsdos_diskimage_writefile; break; case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = rsdos_diskimage_deletefile; break; case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = rsdos_diskimage_suggesttransfer; break; case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: info->writefile_optguide = &coco_rsdos_writefile_optionguide; break; case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_coco; break; } }