summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/tools
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-09-30 17:21:14 +0200
committer Miodrag Milanovic <mmicko@gmail.com>2015-09-30 17:21:14 +0200
commit1fc48ce120a376c288daeeed98daccecf1b60d7b (patch)
tree72cefcede17f3a27fa8256b43bfac9756db82312 /src/mess/tools
parent87a576c55501bd7125b51ca786a010229669df0e (diff)
move mess into mame (nw)
Diffstat (limited to 'src/mess/tools')
-rw-r--r--src/mess/tools/castool/main.c217
-rw-r--r--src/mess/tools/floptool/main.c275
-rw-r--r--src/mess/tools/imgtool/charconv.c162
-rw-r--r--src/mess/tools/imgtool/charconv.h31
-rw-r--r--src/mess/tools/imgtool/filtbas.c3115
-rw-r--r--src/mess/tools/imgtool/filteoln.c127
-rw-r--r--src/mess/tools/imgtool/filter.c82
-rw-r--r--src/mess/tools/imgtool/filter.h66
-rw-r--r--src/mess/tools/imgtool/formats/coco_dsk.c1194
-rw-r--r--src/mess/tools/imgtool/formats/coco_dsk.h24
-rw-r--r--src/mess/tools/imgtool/formats/vt_dsk.c57
-rw-r--r--src/mess/tools/imgtool/formats/vt_dsk.h18
-rw-r--r--src/mess/tools/imgtool/iflopimg.c363
-rw-r--r--src/mess/tools/imgtool/iflopimg.h41
-rw-r--r--src/mess/tools/imgtool/imghd.c273
-rw-r--r--src/mess/tools/imgtool/imghd.h42
-rw-r--r--src/mess/tools/imgtool/imgterrs.c55
-rw-r--r--src/mess/tools/imgtool/imgterrs.h70
-rw-r--r--src/mess/tools/imgtool/imgtool.c2814
-rw-r--r--src/mess/tools/imgtool/imgtool.h169
-rw-r--r--src/mess/tools/imgtool/library.c282
-rw-r--r--src/mess/tools/imgtool/library.h408
-rw-r--r--src/mess/tools/imgtool/main.c972
-rw-r--r--src/mess/tools/imgtool/main.h20
-rw-r--r--src/mess/tools/imgtool/modules.c119
-rw-r--r--src/mess/tools/imgtool/modules.h18
-rw-r--r--src/mess/tools/imgtool/modules/amiga.c2411
-rw-r--r--src/mess/tools/imgtool/modules/bml3.c928
-rw-r--r--src/mess/tools/imgtool/modules/concept.c492
-rw-r--r--src/mess/tools/imgtool/modules/cybiko.c578
-rw-r--r--src/mess/tools/imgtool/modules/cybikoxt.c539
-rw-r--r--src/mess/tools/imgtool/modules/fat.c2111
-rw-r--r--src/mess/tools/imgtool/modules/fat.h3
-rw-r--r--src/mess/tools/imgtool/modules/hp48.c739
-rw-r--r--src/mess/tools/imgtool/modules/mac.c6418
-rw-r--r--src/mess/tools/imgtool/modules/macbin.c377
-rw-r--r--src/mess/tools/imgtool/modules/macutil.c89
-rw-r--r--src/mess/tools/imgtool/modules/macutil.h42
-rw-r--r--src/mess/tools/imgtool/modules/os9.c1244
-rw-r--r--src/mess/tools/imgtool/modules/pc_flop.c173
-rw-r--r--src/mess/tools/imgtool/modules/pc_hard.c470
-rw-r--r--src/mess/tools/imgtool/modules/prodos.c2282
-rw-r--r--src/mess/tools/imgtool/modules/psion.c683
-rw-r--r--src/mess/tools/imgtool/modules/rsdos.c623
-rw-r--r--src/mess/tools/imgtool/modules/thomson.c1681
-rw-r--r--src/mess/tools/imgtool/modules/ti99.c5360
-rw-r--r--src/mess/tools/imgtool/modules/ti990hd.c1818
-rw-r--r--src/mess/tools/imgtool/modules/vzdos.c960
-rw-r--r--src/mess/tools/imgtool/stream.c536
-rw-r--r--src/mess/tools/imgtool/stream.h48
50 files changed, 0 insertions, 41619 deletions
diff --git a/src/mess/tools/castool/main.c b/src/mess/tools/castool/main.c
deleted file mode 100644
index 22564dcdf78..00000000000
--- a/src/mess/tools/castool/main.c
+++ /dev/null
@@ -1,217 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Miodrag Milanovic
-/***************************************************************************
-
- main.c
-
- Castool command line front end
-
- 27/03/2009 Initial version by Miodrag Milanovic
-
-***************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <time.h>
-#include <assert.h>
-
-#include "corestr.h"
-
-#include "formats/a26_cas.h"
-#include "formats/ace_tap.h"
-#include "formats/adam_cas.h"
-#include "formats/apf_apt.h"
-#include "formats/cbm_tap.h"
-#include "formats/cgen_cas.h"
-#include "formats/coco_cas.h"
-#include "formats/csw_cas.h"
-#include "formats/fm7_cas.h"
-#include "formats/fmsx_cas.h"
-#include "formats/gtp_cas.h"
-#include "formats/hect_tap.h"
-#include "formats/kc_cas.h"
-#include "formats/kim1_cas.h"
-#include "formats/lviv_lvt.h"
-#include "formats/mz_cas.h"
-#include "formats/orao_cas.h"
-#include "formats/oric_tap.h"
-#include "formats/p6001_cas.h"
-#include "formats/phc25_cas.h"
-#include "formats/pmd_cas.h"
-#include "formats/primoptp.h"
-#include "formats/rk_cas.h"
-#include "formats/sc3000_bit.h"
-#include "formats/sol_cas.h"
-#include "formats/sorc_cas.h"
-#include "formats/sord_cas.h"
-#include "formats/spc1000_cas.h"
-#include "formats/svi_cas.h"
-#include "formats/thom_cas.h"
-#include "formats/trs_cas.h"
-#include "formats/tvc_cas.h"
-#include "formats/tzx_cas.h"
-#include "formats/uef_cas.h"
-#include "formats/vg5k_cas.h"
-#include "formats/vt_cas.h"
-#include "formats/x07_cas.h"
-#include "formats/x1_tap.h"
-#include "formats/zx81_p.h"
-
-struct SupportedCassetteFormats
-{
- const char *name;
- const struct CassetteFormat * const *formats;
- const char *desc;
-};
-
-const struct SupportedCassetteFormats formats[] = {
- {"a26", a26_cassette_formats ,"Atari 2600 SuperCharger"},
- {"apf", apf_cassette_formats ,"APF Imagination Machine"},
- {"bbc", bbc_cassette_formats ,"Acorn BBC & Electron"},
- {"cbm", cbm_cassette_formats ,"Commodore 8-bit series"},
- {"cdt", cdt_cassette_formats ,"Amstrad CPC"},
- {"cgenie", cgenie_cassette_formats ,"EACA Colour Genie"},
- {"coco", coco_cassette_formats ,"Tandy Radio Shack Color Computer"},
- {"csw", csw_cassette_formats ,"Compressed Square Wave"},
- {"ddp", coleco_adam_cassette_formats ,"Coleco ADAM"},
- {"fm7", fm7_cassette_formats ,"Fujitsu FM-7"},
- {"fmsx", fmsx_cassette_formats ,"MSX"},
- {"gtp", gtp_cassette_formats ,"Elektronika inzenjering Galaksija"},
- {"hector", hector_cassette_formats ,"Micronique Hector & Interact Family Computer"},
- {"jupiter", ace_cassette_formats ,"Jupiter Cantab Jupiter Ace"},
- {"kc85", kc_cassette_formats ,"VEB Mikroelektronik KC 85"},
- {"kim1", kim1_cassette_formats ,"MOS KIM-1"},
- {"lviv", lviv_lvt_format ,"PK-01 Lviv"},
- {"mo5", mo5_cassette_formats ,"Thomson MO-series"},
- {"mz", mz700_cassette_formats ,"Sharp MZ-700"},
- {"orao", orao_cassette_formats ,"PEL Varazdin Orao"},
- {"oric", oric_cassette_formats ,"Tangerine Oric"},
- {"pc6001", pc6001_cassette_formats ,"NEC PC-6001"},
- {"phc25", phc25_cassette_formats ,"Sanyo PHC-25"},
- {"pmd85", pmd85_cassette_formats ,"Tesla PMD-85"},
- {"primo", primo_ptp_format ,"Microkey Primo"},
- {"rku", rku_cassette_formats ,"UT-88"},
- {"rk8", rk8_cassette_formats ,"Mikro-80"},
- {"rks", rks_cassette_formats ,"Specialist"},
- {"rko", rko_cassette_formats ,"Orion"},
- {"rkr", rkr_cassette_formats ,"Radio-86RK"},
- {"rka", rka_cassette_formats ,"Zavod BRA Apogee BK-01"},
- {"rkm", rkm_cassette_formats ,"Mikrosha"},
- {"rkp", rkp_cassette_formats ,"SAM SKB VM Partner-01.01"},
- {"sc3000", sc3000_cassette_formats ,"Sega SC-3000"},
- {"sol20", sol20_cassette_formats ,"PTC SOL-20"},
- {"sorcerer", sorcerer_cassette_formats ,"Exidy Sorcerer"},
- {"sordm5", sordm5_cassette_formats ,"Sord M5"},
- {"spc1000", spc1000_cassette_formats ,"Samsung SPC-1000"},
- {"svi", svi_cassette_formats ,"Spectravideo SVI-318 & SVI-328"},
- {"to7", to7_cassette_formats ,"Thomson TO-series"},
- {"trs80l2", trs80l2_cassette_formats ,"TRS-80 Level 2"},
- {"tvc64", tvc64_cassette_formats ,"Videoton TVC 64"},
- {"tzx", tzx_cassette_formats ,"Sinclair ZX Spectrum"},
- {"uef", uef_cassette_formats ,"Acorn Electron"},
- {"vg5k", vg5k_cassette_formats ,"Philips VG 5000"},
- {"vtech1", vtech1_cassette_formats ,"Video Technology Laser 110-310"},
- {"vtech2", vtech2_cassette_formats ,"Video Technology Laser 350-700"},
- {"x07", x07_cassette_formats ,"Canon X-07"},
- {"x1", x1_cassette_formats ,"Sharp X1"},
- {"zx80_o", zx80_o_format ,"Sinclair ZX80"},
- {"zx81_p", zx81_p_format ,"Sinclair ZX81"},
-
-
-
- {NULL,NULL,NULL}
-};
-
-
-static const char *get_extension(const char *name)
-{
- const char *s;
- s = name;
- if (s != NULL)
- s = strrchr(s, '.');
- return s ? s+1 : NULL;
-}
-
-static void display_usage(void)
-{
- fprintf(stderr, "Usage: \n");
- fprintf(stderr, " castool.exe convert <format> <inputfile> <outputfile.wav>\n");
-}
-
-static void display_formats(void)
-{
- int i,j;
- fprintf(stderr, "Supported formats:\n\n");
- for (i = 0; formats[i].name; i++) {
- fprintf(stderr, "%10s - %s\n",formats[i].name,formats[i].desc);
- for (j = 1; formats[i].formats[j]; j++) {
- fprintf(stderr, "%15s %s\n","",formats[i].formats[j]->extensions);
- }
- }
-}
-
-int CLIB_DECL main(int argc, char *argv[])
-{
- int i;
- int found =0;
- const struct CassetteFormat * const *selected_formats = NULL;
- cassette_image *cassette;
- FILE *f;
-
- if (argc > 1)
- {
- if (!core_stricmp("convert", argv[1]))
- {
- // convert command
- if (argc!=5) {
- fprintf(stderr, "Wrong parameter number.\n\n");
- display_usage();
- return -1;
- } else {
- for (i = 0; formats[i].name; i++) {
- if (core_stricmp(formats[i].name,argv[2])==0) {
- selected_formats = formats[i].formats;
- found = 1;
- }
- }
- if (found==0) {
- fprintf(stderr, "Wrong format name.\n\n");
- display_usage();
- fprintf(stderr, "\n");
- display_formats();
- return -1;
- }
-
- f = fopen(argv[3], "rb");
- if (!f) {
- fprintf(stderr, "File %s not found.\n",argv[3]);
- return -1;
- }
-
- if (cassette_open_choices(f, &stdio_ioprocs, get_extension(argv[3]), selected_formats, CASSETTE_FLAG_READONLY, &cassette)) {
- fprintf(stderr, "Invalid format of input file.\n");
- fclose(f);
- return -1;
- }
-
- cassette_dump(cassette,argv[4]);
- cassette_close(cassette);
- fclose(f);
- goto theend;
- }
- }
- }
-
- /* Usage */
- fprintf(stderr, "castool - Generic cassette manipulation tool for use with MESS\n\n");
- display_usage();
- fprintf(stderr, "\n");
- display_formats();
- fprintf(stderr, "\nExample usage:\n");
- fprintf(stderr, " castool.exe convert tzx game.tzx game.wav\n\n");
-
-theend :
- return 0;
-}
diff --git a/src/mess/tools/floptool/main.c b/src/mess/tools/floptool/main.c
deleted file mode 100644
index 2cb36f3a873..00000000000
--- a/src/mess/tools/floptool/main.c
+++ /dev/null
@@ -1,275 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Miodrag Milanovic
-/***************************************************************************
-
- main.c
-
- Floptool command line front end
-
- 20/07/2011 Initial version by Miodrag Milanovic
-
-***************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <time.h>
-#include <stdarg.h>
-#include <assert.h>
-
-#include "corestr.h"
-
-#include "formats/mfi_dsk.h"
-#include "formats/dfi_dsk.h"
-#include "formats/ipf_dsk.h"
-
-#include "formats/hxcmfm_dsk.h"
-#include "formats/ami_dsk.h"
-
-#include "formats/st_dsk.h"
-#include "formats/pasti_dsk.h"
-
-#include "formats/dsk_dsk.h"
-
-#include "formats/d88_dsk.h"
-#include "formats/imd_dsk.h"
-#include "formats/td0_dsk.h"
-#include "formats/cqm_dsk.h"
-#include "formats/pc_dsk.h"
-#include "formats/naslite_dsk.h"
-
-#include "formats/ap_dsk35.h"
-#include "formats/ap2_dsk.h"
-
-#include "formats/oric_dsk.h"
-
-#include "formats/applix_dsk.h"
-
-static floppy_format_type floppy_formats[] = {
- FLOPPY_MFI_FORMAT,
- FLOPPY_DFI_FORMAT,
- FLOPPY_IPF_FORMAT,
-
- FLOPPY_MFM_FORMAT,
- FLOPPY_ADF_FORMAT,
-
- FLOPPY_ST_FORMAT,
- FLOPPY_MSA_FORMAT,
- FLOPPY_PASTI_FORMAT,
-
- FLOPPY_DSK_FORMAT,
-
- FLOPPY_D88_FORMAT,
- FLOPPY_IMD_FORMAT,
- FLOPPY_TD0_FORMAT,
- FLOPPY_CQM_FORMAT,
- FLOPPY_PC_FORMAT,
- FLOPPY_NASLITE_FORMAT,
-
- FLOPPY_DC42_FORMAT,
- FLOPPY_A216S_FORMAT,
- FLOPPY_RWTS18_FORMAT,
- FLOPPY_EDD_FORMAT,
-
- FLOPPY_ORIC_DSK_FORMAT,
-
- FLOPPY_APPLIX_FORMAT,
-};
-
-void CLIB_DECL ATTR_PRINTF(1,2) logerror(const char *format, ...)
-{
- va_list arg;
- va_start(arg, format);
- vprintf(format, arg);
- va_end(arg);
-}
-
-enum { FORMAT_COUNT = ARRAY_LENGTH(floppy_formats) };
-
-static floppy_image_format_t *formats[FORMAT_COUNT];
-
-static void init_formats()
-{
- for(int i=0; i != FORMAT_COUNT; i++)
- formats[i] = floppy_formats[i]();
-}
-
-static floppy_image_format_t *find_format_by_name(const char *name)
-{
- for(int i=0; i != FORMAT_COUNT; i++)
- if(!core_stricmp(name, formats[i]->name()))
- return formats[i];
- return 0;
-}
-
-static floppy_image_format_t *find_format_by_identify(io_generic *image)
-{
- int best = 0;
- floppy_image_format_t *best_fif = 0;
-
- for(int i = 0; i != FORMAT_COUNT; i++) {
- floppy_image_format_t *fif = formats[i];
- int score = fif->identify(image, floppy_image::FF_UNKNOWN);
- if(score > best) {
- best = score;
- best_fif = fif;
- }
- }
- return best_fif;
-}
-
-static void display_usage()
-{
- fprintf(stderr, "Usage: \n");
- fprintf(stderr, " floptool.exe identify <inputfile> [<inputfile> ...]\n");
- fprintf(stderr, " floptool.exe convert [input_format|auto] output_format <inputfile> <outputfile>\n");
-}
-
-static void display_formats()
-{
- fprintf(stderr, "Supported formats:\n\n");
- for(int i = 0; i != FORMAT_COUNT; i++)
- {
- floppy_image_format_t *fif = formats[i];
- fprintf(stderr, "%15s - %s [%s]\n", fif->name(), fif->description(), fif->extensions());
- }
-}
-
-static void display_full_usage()
-{
- /* Usage */
- fprintf(stderr, "floptool - Generic floppy image manipulation tool for use with MESS\n\n");
- display_usage();
- fprintf(stderr, "\n");
- display_formats();
- fprintf(stderr, "\nExample usage:\n");
- fprintf(stderr, " floptool.exe identify image.dsk\n\n");
-
-}
-
-static int identify(int argc, char *argv[])
-{
- if (argc<3) {
- fprintf(stderr, "Missing name of file to identify.\n\n");
- display_usage();
- return 1;
- }
-
- for(int i=2; i<argc; i++) {
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[i]);
- FILE *f = fopen(argv[i], "rb");
- if (!f) {
- perror(msg);
- return 1;
- }
- io_generic io;
- io.file = f;
- io.procs = &stdio_ioprocs_noclose;
- io.filler = 0xff;
-
- floppy_image_format_t *best_fif = find_format_by_identify(&io);
- if (best_fif)
- printf("%s : %s\n", argv[i], best_fif->description());
- else
- printf("%s : Unknown format\n", argv[i]);
- fclose(f);
- }
- return 0;
-}
-
-static int convert(int argc, char *argv[])
-{
- if (argc!=6) {
- fprintf(stderr, "Incorrect number of arguments.\n\n");
- display_usage();
- return 1;
- }
-
- floppy_image_format_t *source_format, *dest_format;
-
- char msg[4096];
- sprintf(msg, "Error opening %s for reading", argv[4]);
- FILE *f = fopen(argv[4], "rb");
- if (!f) {
- perror(msg);
- return 1;
- }
- io_generic source_io;
- source_io.file = f;
- source_io.procs = &stdio_ioprocs_noclose;
- source_io.filler = 0xff;
-
- if(!core_stricmp(argv[2], "auto")) {
- source_format = find_format_by_identify(&source_io);
- if(!source_format) {
- fprintf(stderr, "Error: Could not identify the format of file %s\n", argv[4]);
- return 1;
- }
-
- } else {
- source_format = find_format_by_name(argv[2]);
- if(!source_format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[2]);
- return 1;
- }
- }
-
- dest_format = find_format_by_name(argv[3]);
- if(!dest_format) {
- fprintf(stderr, "Error: Format '%s' unknown\n", argv[3]);
- return 1;
- }
- if(!dest_format->supports_save()) {
- fprintf(stderr, "Error: saving to format '%s' unsupported\n", argv[3]);
- return 1;
- }
-
- sprintf(msg, "Error opening %s for writing", argv[5]);
- f = fopen(argv[5], "wb");
- if (!f) {
- perror(msg);
- return 1;
- }
- io_generic dest_io;
- dest_io.file = f;
- dest_io.procs = &stdio_ioprocs_noclose;
- dest_io.filler = 0xff;
-
- floppy_image image(84, 2, floppy_image::FF_UNKNOWN);
- if(!source_format->load(&source_io, floppy_image::FF_UNKNOWN, &image)) {
- fprintf(stderr, "Error: parsing input file as '%s' failed\n", source_format->name());
- return 1;
- }
-
- if(!dest_format->save(&dest_io, &image)) {
- fprintf(stderr, "Error: writing output file as '%s' failed\n", dest_format->name());
- return 1;
- }
-
- fclose((FILE *)source_io.file);
- fclose((FILE *)dest_io.file);
-
- return 0;
-}
-
-int CLIB_DECL main(int argc, char *argv[])
-{
- init_formats();
-
- if (argc == 1) {
- display_full_usage();
- return 0;
- }
-
- if (!core_stricmp("identify", argv[1]))
- return identify(argc, argv);
- else if (!core_stricmp("convert", argv[1]))
- return convert(argc, argv);
- else {
- fprintf(stderr, "Unknown command '%s'\n\n", argv[1]);
- display_usage();
- return 1;
- }
-}
diff --git a/src/mess/tools/imgtool/charconv.c b/src/mess/tools/imgtool/charconv.c
deleted file mode 100644
index 39b5953d799..00000000000
--- a/src/mess/tools/imgtool/charconv.c
+++ /dev/null
@@ -1,162 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- charconv.c
-
- Imgtool character set conversion routines.
-
-***************************************************************************/
-
-#include "corestr.h"
-#include "charconv.h"
-
-
-/*-------------------------------------------------
- utf8_from_latin1 - convert an ISO-8859-1
- character sequence to an UTF-8 string
--------------------------------------------------*/
-
-static char *utf8_from_latin1(const char *src)
-{
- char *buffer, *bufptr;
-
- /* validate input */
- if (!src)
- {
- return NULL;
- }
-
- /* allocate space for result, twice the source len to be safe */
- buffer = (char *) osd_malloc(strlen(src) * 2 + 1);
-
- /* point to the start */
- bufptr = buffer;
-
- do
- {
- unsigned char c = *src;
-
- if (c < 0x80)
- {
- *bufptr++ = c;
- }
- else if (c < 0xc0)
- {
- *bufptr++ = '\xc2';
- *bufptr++ = c;
- }
- else
- {
- *bufptr++ = '\xc3';
- *bufptr++ = c - 0x40;
- }
- } while (*src++);
-
- return buffer;
-}
-
-
-/*-------------------------------------------------
- latin1_from_utf8 - convert an UTF-8
- character sequence to an ISO-8859-1 string
--------------------------------------------------*/
-
-static char *latin1_from_utf8(const char *src)
-{
- char *buffer, *bufptr;
-
- /* validate input */
- if (!src)
- {
- return NULL;
- }
-
- /* allocate space for result */
- buffer = (char *) osd_malloc(strlen(src) + 1);
-
- /* point to the start */
- bufptr = buffer;
-
- do
- {
- unsigned char c = *src;
-
- if (c < 0x80)
- {
- *bufptr++ = c;
- }
- else if (c == 0xc2)
- {
- c = *++src;
- *bufptr++ = c;
- }
- else if (c == 0xc3)
- {
- c = *++src;
- *bufptr++ = c + 0x40;
- }
- else
- {
- /* conversion failed */
- *bufptr++ = '\0';
- break;
- }
- } while(*src++);
-
- return buffer;
-}
-
-
-/*-------------------------------------------------
- utf8_from_native - convert specified character
- sequence to an UTF-8 string
--------------------------------------------------*/
-
-char *utf8_from_native(imgtool_charset charset, const char *src)
-{
- char *result;
-
- switch (charset)
- {
- case IMGTOOL_CHARSET_UTF8:
- result = core_strdup(src);
- break;
-
- case IMGTOOL_CHARSET_ISO_8859_1:
- result = utf8_from_latin1(src);
- break;
-
- default:
- result = NULL;
- break;
- }
- return result;
-}
-
-
-/*-------------------------------------------------
- native_from_utf8 - convert an UTF-8 string
- to specified character set
--------------------------------------------------*/
-
-char *native_from_utf8(imgtool_charset charset, const char *src)
-{
- char *result;
-
- switch (charset)
- {
- case IMGTOOL_CHARSET_UTF8:
- result = core_strdup(src);
- break;
-
- case IMGTOOL_CHARSET_ISO_8859_1:
- result = latin1_from_utf8(src);
- break;
-
- default:
- result = NULL;
- break;
- }
- return result;
-}
diff --git a/src/mess/tools/imgtool/charconv.h b/src/mess/tools/imgtool/charconv.h
deleted file mode 100644
index 1544e9df402..00000000000
--- a/src/mess/tools/imgtool/charconv.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- charconv.h
-
- Imgtool character set conversion routines.
-
-***************************************************************************/
-
-
-#ifndef __CHARCONV_H__
-#define __CHARCONV_H__
-
-
-/* Supported character sets */
-enum imgtool_charset
-{
- IMGTOOL_CHARSET_UTF8,
- IMGTOOL_CHARSET_ISO_8859_1,
-};
-
-
-/* Convert specified charset to UTF-8 */
-char *utf8_from_native(imgtool_charset charset, const char *src);
-
-/* Convert UTF-8 string to specified charset */
-char *native_from_utf8(imgtool_charset charset, const char *src);
-
-
-#endif /* __CHARCONV_H__ */
diff --git a/src/mess/tools/imgtool/filtbas.c b/src/mess/tools/imgtool/filtbas.c
deleted file mode 100644
index bff1bda121e..00000000000
--- a/src/mess/tools/imgtool/filtbas.c
+++ /dev/null
@@ -1,3115 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/****************************************************************************
-
- filtbas.c
-
- Filter for Microsoft-style tokenized BASIC files
-
- BASIC files typically follow the following format:
-
- int8 $ff
- int16 <TOTAL LENGTH>
- ...
- int16 <PTR_NEXT_LINE>
- int16 <LINE_NUM>
- int8[] <TOKENISED_DATA>
- int8 $00 End of line delimiter
-
-*****************************************************************************/
-
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-
-#include "imgtool.h"
-#include "formats/imageutl.h"
-
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-#define EOLN (CRLF == 1 ? "\r" : (CRLF == 2 ? "\n" : (CRLF == 3 ? "\r\n" : NULL)))
-
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-struct basictoken_tableent
-{
- UINT8 shift;
- UINT8 base;
- const char *const *tokens;
- int num_tokens;
-};
-
-
-
-struct basictokens
-{
- UINT16 baseaddress;
- unsigned int skip_bytes : 15;
- unsigned int be : 1;
- const basictoken_tableent *entries;
- int num_entries;
-};
-
-
-
-/***************************************************************************
- IMPLEMENTATION
-***************************************************************************/
-
-/*-------------------------------------------------
- basic_readfile - reads a file and decodes
- BASIC tokens into ASCII text
--------------------------------------------------*/
-
-static imgtoolerr_t basic_readfile(const basictokens *tokens,
- imgtool_partition *partition, const char *filename,
- const char *fork, imgtool_stream *destf)
-{
- imgtoolerr_t err;
- imgtool_stream *mem_stream;
- UINT8 line_header[4];
- UINT16 line_number; //, address;
- UINT8 b, shift;
- int i;
- int in_string = FALSE;
- const basictoken_tableent *token_table;
- const char *token;
-
- /* open a memory stream */
- mem_stream = stream_open_mem(NULL, 0);
- if (mem_stream == NULL)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- /* read actual file */
- err = imgtool_partition_read_file(partition, filename, fork, mem_stream, NULL);
- if (err)
- goto done;
-
- /* skip first few bytes */
- stream_seek(mem_stream, tokens->skip_bytes, SEEK_SET);
-
- /* keep reading line headers */
- while(stream_read(mem_stream, line_header, sizeof(line_header)) == sizeof(line_header))
- {
- /* pluck the address and line number out */
- if (tokens->be)
- {
- //address = (UINT16)
- pick_integer_be(line_header, 0, 2);
- line_number = (UINT16) pick_integer_be(line_header, 2, 2);
- }
- else
- {
- //address = (UINT16)
- pick_integer_le(line_header, 0, 2);
- line_number = (UINT16) pick_integer_le(line_header, 2, 2);
- }
-
- /* write the line number */
- stream_printf(destf, "%u ", (unsigned) line_number);
- shift = 0x00;
-
- while((stream_read(mem_stream, &b, 1) > 0) && (b != 0x00))
- {
- if (b == 0x22)
- in_string = in_string ? FALSE : TRUE;
-
- if ((b & 0x80) && (!in_string))
- {
- token = NULL;
-
- for (i = 0; i < tokens->num_entries; i++)
- {
- token_table = &tokens->entries[i];
- if (token_table->shift == shift)
- {
- if ((b - 0x80) < token_table->num_tokens)
- {
- token = token_table->tokens[b - 0x80];
- if (token)
- shift = 0x00;
- }
- }
-
- if (token_table->shift == b)
- {
- shift = token_table->shift;
- break;
- }
- }
-
- if (shift == 0x00)
- stream_puts(destf, token ? token : "!");
- }
- else
- {
- stream_putc(destf, (char) b);
- }
- }
-
- stream_puts(destf, EOLN);
- }
-
-done:
- if (mem_stream != NULL)
- stream_close(mem_stream);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- basic_writefile - translates ASCII text to
- BASIC tokens and writes it to a file
--------------------------------------------------*/
-
-static imgtoolerr_t basic_writefile(const basictokens *tokens,
- imgtool_partition *partition, const char *filename,
- const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- imgtoolerr_t err;
- imgtool_stream *mem_stream;
- char buf[1024];
- int eof = FALSE;
- UINT32 len;
- char c;
- int i, j, pos, in_quotes;
- UINT16 line_number;
- UINT8 line_header[4];
- UINT8 file_header[3];
- const basictoken_tableent *token_table;
- const char *token;
- UINT8 token_shift, token_value;
- UINT16 address;
-
- /* open a memory stream */
- mem_stream = stream_open_mem(NULL, 0);
- if (mem_stream == NULL)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- /* skip first few bytes */
- stream_fill(mem_stream, 0x00, tokens->skip_bytes);
-
- /* loop until the file is complete */
- while(!eof)
- {
- /* read a line */
- pos = 0;
- while((len = stream_read(sourcef, &c, 1)) > 0)
- {
- /* break if at end of line */
- if ((c == '\r') || (c == '\n'))
- break;
-
- if (pos <= ARRAY_LENGTH(buf) - 1)
- {
- buf[pos++] = c;
- }
- }
- eof = (len == 0);
- buf[pos] = '\0';
-
- /* ignore lines that don't start with digits */
- if (isdigit(buf[0]))
- {
- /* start at beginning of line */
- pos = 0;
-
- /* read line number */
- line_number = 0;
- while(isdigit(buf[pos]))
- {
- line_number *= 10;
- line_number += (buf[pos++] - '0');
- }
-
- /* determine address */
- if (tokens->baseaddress != 0)
- {
- address = tokens->baseaddress + (UINT16)stream_size(mem_stream) + 4;
- }
- else
- {
- address = 0x0000;
- }
-
- /* set up line header */
- memset(&line_header, 0, sizeof(line_header));
- if (tokens->be)
- {
- place_integer_be(line_header, 0, 2, address);
- place_integer_be(line_header, 2, 2, line_number);
- }
- else
- {
- place_integer_be(line_header, 0, 2, address);
- place_integer_be(line_header, 2, 2, line_number);
- }
-
- /* emit line header */
- stream_write(mem_stream, line_header, sizeof(line_header));
-
- /* skip spaces */
- while(isspace(buf[pos]))
- pos++;
-
- /* when we start out, we are not within quotation marks */
- in_quotes = FALSE;
-
- /* read until end of line */
- while(buf[pos] != '\0')
- {
- token = NULL;
- token_shift = 0;
- token_value = 0;
-
- if (buf[pos] == '\"')
- {
- /* flip quotation status */
- in_quotes = !in_quotes;
- }
- else if (!in_quotes)
- {
- for (i = 0; (token == NULL) && (i < tokens->num_entries); i++)
- {
- token_table = &tokens->entries[i];
- for (j = 0; (token == NULL) && (j < token_table->num_tokens); j++)
- {
- if (!strncmp(&buf[pos], token_table->tokens[j], strlen(token_table->tokens[j])))
- {
- token = token_table->tokens[j];
- token_shift = token_table->shift;
- token_value = token_table->base + j;
- pos += strlen(token);
- }
- }
- }
- }
-
- /* did we find a token? */
- if (token != NULL)
- {
- /* emit the token */
- if (token_shift != 0)
- stream_write(mem_stream, &token_shift, 1);
- stream_write(mem_stream, &token_value, 1);
- }
- else
- {
- /* no token; emit the byte */
- stream_write(mem_stream, &buf[pos++], 1);
- }
- }
-
- /* emit line terminator */
- stream_fill(mem_stream, 0x00, 1);
- }
- }
-
- /* emit program terminator */
- stream_fill(mem_stream, 0x00, 2);
-
- /* reset stream */
- stream_seek(mem_stream, 0, SEEK_SET);
-
- /* this is somewhat gross */
- if (tokens->skip_bytes >= 3)
- {
- if (tokens->be)
- {
- place_integer_be(file_header, 0, 1, 0xFF);
- place_integer_be(file_header, 1, 2, stream_size(mem_stream));
- }
- else
- {
- place_integer_le(file_header, 0, 1, 0xFF);
- place_integer_le(file_header, 1, 2, stream_size(mem_stream));
- }
- stream_write(mem_stream, file_header, 3);
- stream_seek(mem_stream, 0, SEEK_SET);
- }
-
- /* write actual file */
- err = imgtool_partition_write_file(partition, filename, fork, mem_stream, opts, NULL);
- if (err)
- goto done;
-
-done:
- if (mem_stream != NULL)
- stream_close(mem_stream);
- return err;
-}
-
-
-
-/***************************************************************************
- TOKEN DEFINITIONS
-***************************************************************************/
-
-static const char *const cocobas_statements[] =
-{
- "FOR", /* 0x80 */
- "GO", /* 0x81 */
- "REM", /* 0x82 */
- "'", /* 0x83 */
- "ELSE", /* 0x84 */
- "IF", /* 0x85 */
- "DATA", /* 0x86 */
- "PRINT", /* 0x87 */
- "ON", /* 0x88 */
- "INPUT", /* 0x89 */
- "END", /* 0x8a */
- "NEXT", /* 0x8b */
- "DIM", /* 0x8c */
- "READ", /* 0x8d */
- "RUN", /* 0x8e */
- "RESTORE", /* 0x8f */
- "RETURN", /* 0x90 */
- "STOP", /* 0x91 */
- "POKE", /* 0x92 */
- "CONT", /* 0x93 */
- "LIST", /* 0x94 */
- "CLEAR", /* 0x95 */
- "NEW", /* 0x96 */
- "CLOAD", /* 0x97 */
- "CSAVE", /* 0x98 */
- "OPEN", /* 0x99 */
- "CLOSE", /* 0x9a */
- "LLIST", /* 0x9b */
- "SET", /* 0x9c */
- "RESET", /* 0x9d */
- "CLS", /* 0x9e */
- "MOTOR", /* 0x9f */
- "SOUND", /* 0xa0 */
- "AUDIO", /* 0xa1 */
- "EXEC", /* 0xa2 */
- "SKIPF", /* 0xa3 */
- "TAB(", /* 0xa4 */
- "TO", /* 0xa5 */
- "SUB", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "OFF", /* 0xaa */
- "+", /* 0xab */
- "-", /* 0xac */
- "*", /* 0xad */
- "/", /* 0xae */
- "^", /* 0xaf */
- "AND", /* 0xb0 */
- "OR", /* 0xb1 */
- ">", /* 0xb2 */
- "=", /* 0xb3 */
- "<", /* 0xb4 */
- "DEL", /* 0xb5 */
- "EDIT", /* 0xb6 */
- "TRON", /* 0xb7 */
- "TROFF", /* 0xb8 */
- "DEF", /* 0xb9 */
- "LET", /* 0xba */
- "LINE", /* 0xbb */
- "PCLS", /* 0xbc */
- "PSET", /* 0xbd */
- "PRESET", /* 0xbe */
- "SCREEN", /* 0xbf */
- "PCLEAR", /* 0xc0 */
- "COLOR", /* 0xc1 */
- "CIRCLE", /* 0xc2 */
- "PAINT", /* 0xc3 */
- "GET", /* 0xc4 */
- "PUT", /* 0xc5 */
- "DRAW", /* 0xc6 */
- "PCOPY", /* 0xc7 */
- "PMODE", /* 0xc8 */
- "PLAY", /* 0xc9 */
- "DLOAD", /* 0xca */
- "RENUM", /* 0xcb */
- "FN", /* 0xcc */
- "USING", /* 0xcd */
- "DIR", /* 0xce */
- "DRIVE", /* 0xcf */
- "FIELD", /* 0xd0 */
- "FILES", /* 0xd1 */
- "KILL", /* 0xd2 */
- "LOAD", /* 0xd3 */
- "LSET", /* 0xd4 */
- "MERGE", /* 0xd5 */
- "RENAME", /* 0xd6 */
- "RSET", /* 0xd7 */
- "SAVE", /* 0xd8 */
- "WRITE", /* 0xd9 */
- "VERIFY", /* 0xda */
- "UNLOAD", /* 0xdb */
- "DSKINI", /* 0xdc */
- "BACKUP", /* 0xdd */
- "COPY", /* 0xde */
- "DSKI$", /* 0xdf */
- "DSKO$", /* 0xe0 */
- "DOS", /* 0xe1 */
- "WIDTH", /* 0xe2 */
- "PALETTE", /* 0xe3 */
- "HSCREEN", /* 0xe4 */
- "LPOKE", /* 0xe5 */
- "HCLS", /* 0xe6 */
- "HCOLOR", /* 0xe7 */
- "HPAINT", /* 0xe8 */
- "HCIRCLE", /* 0xe9 */
- "HLINE", /* 0xea */
- "HGET", /* 0xeb */
- "HPUT", /* 0xec */
- "HBUFF", /* 0xed */
- "HPRINT", /* 0xee */
- "ERR", /* 0xef */
- "BRK", /* 0xf0 */
- "LOCATE", /* 0xf1 */
- "HSTAT", /* 0xf2 */
- "HSET", /* 0xf3 */
- "HRESET", /* 0xf4 */
- "HDRAW", /* 0xf5 */
- "CMP", /* 0xf6 */
- "RGB", /* 0xf7 */
- "ATTR" /* 0xf8 */
-};
-
-static const char *const cocobas_functions[] =
-{
- "SGN", /* 0xff80 */
- "INT", /* 0xff81 */
- "ABS", /* 0xff82 */
- "USR", /* 0xff83 */
- "RND", /* 0xff84 */
- "SIN", /* 0xff85 */
- "PEEK", /* 0xff86 */
- "LEN", /* 0xff87 */
- "STR$", /* 0xff88 */
- "VAL", /* 0xff89 */
- "ASC", /* 0xff8a */
- "CHR$", /* 0xff8b */
- "EOF", /* 0xff8c */
- "JOYSTK", /* 0xff8d */
- "LEFT$", /* 0xff8e */
- "RIGHT$", /* 0xff8f */
- "MID$", /* 0xff90 */
- "POINT", /* 0xff91 */
- "INKEY$", /* 0xff92 */
- "MEM", /* 0xff93 */
- "ATN", /* 0xff94 */
- "COS", /* 0xff95 */
- "TAN", /* 0xff96 */
- "EXP", /* 0xff97 */
- "FIX", /* 0xff98 */
- "LOG", /* 0xff99 */
- "POS", /* 0xff9a */
- "SQR", /* 0xff9b */
- "HEX$", /* 0xff9c */
- "VARPTR", /* 0xff9d */
- "INSTR", /* 0xff9e */
- "TIMER", /* 0xff9f */
- "PPOINT", /* 0xffa0 */
- "STRING$", /* 0xffa1 */
- "CVN", /* 0xffa2 */
- "FREE", /* 0xffa3 */
- "LOC", /* 0xffa4 */
- "LOF", /* 0xffa5 */
- "MKN$", /* 0xffa6 */
- "AS", /* 0xffa7 */
- "LPEEK", /* 0xffa8 */
- "BUTTON", /* 0xffa9 */
- "HPOINT", /* 0xffaa */
- "ERNO", /* 0xffab */
- "ERLIN" /* 0xffac */
-};
-
-static const char *const dragonbas_statements[] =
-{
- "FOR", /* 0x80 */
- "GO", /* 0x81 */
- "REM", /* 0x82 */
- "'", /* 0x83 */
- "ELSE", /* 0x84 */
- "IF", /* 0x85 */
- "DATA", /* 0x86 */
- "PRINT", /* 0x87 */
- "ON", /* 0x88 */
- "INPUT", /* 0x89 */
- "END", /* 0x8a */
- "NEXT", /* 0x8b */
- "DIM", /* 0x8c */
- "READ", /* 0x8d */
- "LET", /* 0x8e */
- "RUN", /* 0x8f */
- "RESTORE", /* 0x90 */
- "RETURN", /* 0x91 */
- "STOP", /* 0x92 */
- "POKE", /* 0x93 */
- "CONT", /* 0x94 */
- "LIST", /* 0x95 */
- "CLEAR", /* 0x96 */
- "NEW", /* 0x97 */
- "DEF", /* 0x98 */
- "CLOAD", /* 0x99 */
- "CSAVE", /* 0x9a */
- "OPEN", /* 0x9b */
- "CLOSE", /* 0x9c */
- "LLIST", /* 0x9d */
- "SET", /* 0x9e */
- "RESET", /* 0x9f */
- "CLS", /* 0xa0 */
- "MOTOR", /* 0xa1 */
- "SOUND", /* 0xa2 */
- "AUDIO", /* 0xa3 */
- "EXEC", /* 0xa4 */
- "SKIPF", /* 0xa5 */
- "DEL", /* 0xa6 */
- "EDIT", /* 0xa7 */
- "TRON", /* 0xa8 */
- "TROFF", /* 0xa9 */
- "LINE", /* 0xaa */
- "PCLS", /* 0xab */
- "PSET", /* 0xac */
- "PRESET", /* 0xad */
- "SCREEN", /* 0xae */
- "PCLEAR", /* 0xaf */
- "COLOR", /* 0xb0 */
- "CIRCLE", /* 0xb1 */
- "PAINT", /* 0xb2 */
- "GET", /* 0xb3 */
- "PUT", /* 0xb4 */
- "DRAW", /* 0xb5 */
- "PCOPY", /* 0xb6 */
- "PMODE", /* 0xb7 */
- "PLAY", /* 0xb8 */
- "DLOAD", /* 0xb9 */
- "RENUM", /* 0xba */
- "TAB(", /* 0xbb */
- "TO", /* 0xbc */
- "SUB", /* 0xbd */
- "FN", /* 0xbe */
- "THEN", /* 0xbf */
- "NOT", /* 0xc0 */
- "STEP", /* 0xc1 */
- "OFF", /* 0xc2 */
- "+", /* 0xc3 */
- "-", /* 0xc4 */
- "*", /* 0xc5 */
- "/", /* 0xc6 */
- "^", /* 0xc7 */
- "AND", /* 0xc8 */
- "OR", /* 0xc9 */
- ">", /* 0xca */
- "=", /* 0xcb */
- "<", /* 0xcc */
- "USING", /* 0xcd */
- "DIR", /* 0xce */
- "DRIVE", /* 0xcf */
- "FIELD", /* 0xd0 */
- "FILES", /* 0xd1 */
- "KILL", /* 0xd2 */
- "LOAD", /* 0xd3 */
- "LSET", /* 0xd4 */
- "MERGE", /* 0xd5 */
- "RENAME", /* 0xd6 */
- "RSET", /* 0xd7 */
- "SAVE", /* 0xd8 */
- "WRITE", /* 0xd9 */
- "VERIFY", /* 0xda */
- "UNLOAD", /* 0xdb */
- "DSKINI", /* 0xdc */
- "BACKUP", /* 0xdd */
- "COPY", /* 0xde */
- "DSKI$", /* 0xdf */
- "DSKO$" /* 0xe0 */
-};
-
-static const char *const dragonbas_functions[] =
-{
- "SGN", /* 0xff80 */
- "INT", /* 0xff81 */
- "ABS", /* 0xff82 */
- "POS", /* 0xff83 */
- "RND", /* 0xff84 */
- "SQR", /* 0xff85 */
- "LOG", /* 0xff86 */
- "EXP", /* 0xff87 */
- "SIN", /* 0xff88 */
- "COS", /* 0xff89 */
- "TAN", /* 0xff8a */
- "ATN", /* 0xff8b */
- "PEEK", /* 0xff8c */
- "LEN", /* 0xff8d */
- "STR$", /* 0xff8e */
- "VAL", /* 0xff8f */
- "ASC", /* 0xff90 */
- "CHR$", /* 0xff91 */
- "EOF", /* 0xff92 */
- "JOYSTK", /* 0xff93 */
- "FIX", /* 0xff94 */
- "HEX$", /* 0xff95 */
- "LEFT$", /* 0xff96 */
- "RIGHT$", /* 0xff97 */
- "MID$", /* 0xff98 */
- "POINT", /* 0xff99 */
- "INKEY$", /* 0xff9a */
- "MEM", /* 0xff9b */
- "VARPTR", /* 0xff9c */
- "INSTR", /* 0xff9d */
- "TIMER", /* 0xff9e */
- "PPOINT", /* 0xff9f */
- "STRING$", /* 0xffa0 */
- "USR" /* 0xffa1 */
- "CVN", /* 0xffa2 */
- "FREE", /* 0xffa3 */
- "LOC", /* 0xffa4 */
- "LOF", /* 0xffa5 */
- "MKN$" /* 0xffa6 */
-};
-
-static const char *const vzbas[] =
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "RESET", /* 0x82 */
- "SET", /* 0x83 */
- "CLS", /* 0x84 */
- NULL, /* 0x85 */
- "RANDOM", /* 0x86 */
- "NEXT", /* 0x87 */
- "DATA", /* 0x88 */
- "INPUT", /* 0x89 */
- "DIM", /* 0x8a */
- "READ", /* 0x8b */
- "LET", /* 0x8c */
- "GOTO", /* 0x8d */
- "RUN", /* 0x8e */
- "IF", /* 0x8f */
- "RESTORE", /* 0x90 */
- "GOSUB", /* 0x91 */
- "RETURN", /* 0x92 */
- "'", /* 0x93 */
- "STOP", /* 0x94 */
- "ELSE", /* 0x95 */
- "COPY", /* 0x96 */
- "COLOR", /* 0x97 */
- "VERIFY", /* 0x98 */
- "DEFINT", /* 0x99 */
- "DEFSNG", /* 0x9a */
- "DEFDBL", /* 0x9b */
- "CRUN", /* 0x9c */
- "MODE", /* 0x9d */
- "ERROR", /* 0x9e */
- "RESUME", /* 0x9f */
- "OUT", /* 0xa0 */
- "IN", /* 0xa1 */
- NULL, /* 0xa2 */
- NULL, /* 0xa3 */
- NULL, /* 0xa4 */
- NULL, /* 0xa5 */
- NULL, /* 0xa6 */
- NULL, /* 0xa7 */
- NULL, /* 0xa8 */
- NULL, /* 0xa9 */
- NULL, /* 0xaa */
- NULL, /* 0xab */
- NULL, /* 0xac */
- NULL, /* 0xad */
- "(RESET)", /* 0xae */
- "LPRINT", /* 0xaf */
- NULL, /* 0xb0 */
- "POKE", /* 0xb1 */
- "PRINT", /* 0xb2 */
- "CONT", /* 0xb3 */
- "LIST", /* 0xb4 */
- "LLIST", /* 0xb5 */
- "DELETE", /* 0xb6 */
- "AUTO", /* 0xb7 */
- "CLEAR", /* 0xb8 */
- "CLOAD", /* 0xb9 */
- "CSAVE", /* 0xba */
- "NEW", /* 0xbb */
- "TAB(", /* 0xbc */
- "TO", /* 0xbd */
- NULL, /* 0xbe */
- "USING", /* 0xbf */
- "VARPTR", /* 0xc0 */
- "USR", /* 0xc1 */
- "ERL", /* 0xc2 */
- "ERR", /* 0xc3 */
- "STRING$", /* 0xc4 */
- NULL, /* 0xc5 */
- "POINT", /* 0xc6 */
- NULL, /* 0xc7 */
- "MEM", /* 0xc8 */
- "INKEY$", /* 0xc9 */
- "THEN", /* 0xca */
- "NOT", /* 0xcb */
- "STEP", /* 0xcc */
- "+", /* 0xcd */
- "-", /* 0xce */
- "*", /* 0xcf */
- "/", /* 0xd0 */
- "^", /* 0xd1 */
- "AND", /* 0xd2 */
- "OR", /* 0xd3 */
- ">", /* 0xd4 */
- "=", /* 0xd5 */
- "<", /* 0xd6 */
- "SGN", /* 0xd7 */
- "INT", /* 0xd8 */
- "ABS", /* 0xd9 */
- "FRE", /* 0xda */
- "INP", /* 0xdb */
- "POS", /* 0xdc */
- "SQR", /* 0xdd */
- "AND", /* 0xde */
- "LOG", /* 0xdf */
- "EXP", /* 0xe0 */
- "COS", /* 0xe1 */
- "SIN", /* 0xe2 */
- "TAN", /* 0xe3 */
- "ATN", /* 0xe4 */
- "PEEK", /* 0xe5 */
- NULL, /* 0xe6 */
- NULL, /* 0xe7 */
- NULL, /* 0xe8 */
- NULL, /* 0xe9 */
- NULL, /* 0xea */
- NULL, /* 0xeb */
- NULL, /* 0xec */
- NULL, /* 0xed */
- NULL, /* 0xee */
- "CINT", /* 0xef */
- "CSNG", /* 0xf0 */
- "CDBL", /* 0xf1 */
- "FIX", /* 0xf2 */
- "LEN", /* 0xf3 */
- "STR$", /* 0xf4 */
- "VAL", /* 0xf5 */
- "ASC", /* 0xf6 */
- "CHR$", /* 0xf7 */
- "LEFT$", /* 0xf8 */
- "RIGHT$", /* 0xf9 */
- "MID$", /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
- NULL /* 0xff */
-};
-
-static const char *const bml3bas_statements[] =
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "DIM", /* 0x84 */
- "READ", /* 0x85 */
- "LET", /* 0x86 */
- "GO", /* 0x87 */
- "RUN", /* 0x88 */
- "IF", /* 0x89 */
- "RESTORE", /* 0x8a */
- "RETURN", /* 0x8b */
- "REM", /* 0x8c */
- "'", /* 0x8d */
- "STOP", /* 0x8e */
- "ELSE", /* 0x8f */
- "TRON", /* 0x90 */
- "TROFF", /* 0x91 */
- "SWAP", /* 0x92 */
- "DEFSTR", /* 0x93 */
- "DEFINT", /* 0x94 */
- "DEFSNG", /* 0x95 */
- "DEFDBL", /* 0x96 */
- "ON", /* 0x97 */
- "WAIT", /* 0x98 */
- "RENUM", /* 0x99 */
- "EDIT", /* 0x9a */
- "ERROR", /* 0x9b */
- "RESUME", /* 0x9c */
- "AUTO", /* 0x9d */
- "DELETE", /* 0x9e */
- "TERM", /* 0x9f */
- "WIDTH", /* 0xa0 */
- "UNLIST", /* 0xa1 */
- "MON", /* 0xa2 */
- "LOCATE", /* 0xa3 */
- "CLS", /* 0xa4 */
- "CONSOLE", /* 0xa5 */
- "PSET", /* 0xa6 */
- "PRESET", /* 0xa7 */
- "MOTOR", /* 0xa8 */
- "SKIPF", /* 0xa9 */
- "SAVE", /* 0xaa */
- "LOAD", /* 0xab */
- "MERGE", /* 0xac */
- "EXEC", /* 0xad */
- "OPEN", /* 0xae */
- "CLOSE", /* 0xaf */
- "FILES", /* 0xb0 */
- "COM", /* 0xb1 */
- "KEY", /* 0xb2 */
- "PAINT", /* 0xb3 */
- "BEEP", /* 0xb4 */
- "COLOR", /* 0xb5 */
- "LINE", /* 0xb6 */
- "DEF", /* 0xb7 */
- "POKE", /* 0xb8 */
- "PRINT", /* 0xb9 */
- "CONT", /* 0xba */
- "LIST", /* 0xbb */
- "CLEAR", /* 0xbc */
- "RANDOMIZE",/* 0xbd */
- "WHILE", /* 0xbe */
- "WEND", /* 0xbf */
- "NEW", /* 0xc0 */
- "TAB(", /* 0xc1 */
- "TO", /* 0xc2 */
- "SUB", /* 0xc3 */
- "FN", /* 0xc4 */
- "SPC(", /* 0xc5 */
- "USING", /* 0xc6 */
- "USR", /* 0xc7 */
- "ERL", /* 0xc8 */
- "ERR", /* 0xc9 */
- "OFF", /* 0xca */
- "THEN", /* 0xcb */
- "NOT", /* 0xcc */
- "STEP", /* 0xcd */
- "+", /* 0xce */
- "-", /* 0xcf */
- "*", /* 0xd0 */
- "/", /* 0xd1 */
- "^", /* 0xd2 */
- "AND", /* 0xd3 */
- "OR", /* 0xd4 */
- "XOR", /* 0xd5 */
- "EQV", /* 0xd6 */
- "IMP", /* 0xd7 */
- "MOD", /* 0xd8 */
- "\\", /* 0xd9 */
- ">", /* 0xda */
- "=", /* 0xdb */
- "<" /* 0xdc */
-};
-
-static const char *const bml3bas_functions[] =
-{
- "SGN", /* 0xff80 */
- "INT", /* 0xff81 */
- "ABS", /* 0xff82 */
- "FRE", /* 0xff83 */
- "POS", /* 0xff84 */
- "SQR", /* 0xff85 */
- "LOG", /* 0xff86 */
- "EXP", /* 0xff87 */
- "COS", /* 0xff88 */
- "SIN", /* 0xff89 */
- "TAN", /* 0xff8a */
- "ATN", /* 0xff8b */
- "PEEK", /* 0xff8c */
- "LEN", /* 0xff8d */
- "STR$", /* 0xff8e */
- "VAL", /* 0xff8f */
- "ASC", /* 0xff90 */
- "CHR$", /* 0xff91 */
- "CINT", /* 0xff92 */
- "CSNG", /* 0xff93 */
- "CDBL", /* 0xff94 */
- "FIX", /* 0xff95 */
- "SPACE$", /* 0xff96 */
- "HEX$", /* 0xff97 */
- "OCT$", /* 0xff98 */
- "LOF", /* 0xff99 */
- "EOF", /* 0xff9a */
- "PEN", /* 0xff9b */
- "LEFT$", /* 0xff9c */
- "RIGHT$", /* 0xff9d */
- "MID$", /* 0xff9e */
- "INSTR", /* 0xff9f */
- "SCREEN", /* 0xffa0 */
- "VARPTR", /* 0xffa1 */
- "STRING$", /* 0xffa2 */
- "RND", /* 0xffa3 */
- "INKEY$", /* 0xffa4 */
- "INPUT", /* 0xffa5 */
- "CSRLIN", /* 0xffa6 */
- "POINT", /* 0xffa7 */
- "TIME", /* 0xffa8 */
- "DATE" /* 0xffa9 */
-};
-
-
-#ifdef BASIC_
-/* ----------------------------------------------------------------------- *
- * CBM machines *
- * ----------------------------------------------------------------------- */
-static const char *const basic_10[] = /* "BASIC 1.0" - supported by pet */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- NULL, /* 0xcb */
- NULL, /* 0xcc */
- NULL, /* 0xcd */
- NULL, /* 0xce */
- NULL, /* 0xcf */
- NULL, /* 0xd0 */
- NULL, /* 0xd1 */
- NULL, /* 0xd2 */
- NULL, /* 0xd3 */
- NULL, /* 0xd4 */
- NULL, /* 0xd5 */
- NULL, /* 0xd6 */
- NULL, /* 0xd7 */
- NULL, /* 0xd8 */
- NULL, /* 0xd9 */
- NULL, /* 0xda */
- NULL, /* 0xdb */
- NULL, /* 0xdc */
- NULL, /* 0xdd */
- NULL, /* 0xde */
- NULL, /* 0xdf */
- NULL, /* 0xe0 */
- NULL, /* 0xe1 */
- NULL, /* 0xe2 */
- NULL, /* 0xe3 */
- NULL, /* 0xe4 */
- NULL, /* 0xe5 */
- NULL, /* 0xe6 */
- NULL, /* 0xe7 */
- NULL, /* 0xe8 */
- NULL, /* 0xe9 */
- NULL, /* 0xea */
- NULL, /* 0xeb */
- NULL, /* 0xec */
- NULL, /* 0xed */
- NULL, /* 0xee */
- NULL, /* 0xef */
- NULL, /* 0xf0 */
- NULL, /* 0xf1 */
- NULL, /* 0xf2 */
- NULL, /* 0xf3 */
- NULL, /* 0xf4 */
- NULL, /* 0xf5 */
- NULL, /* 0xf6 */
- NULL, /* 0xf7 */
- NULL, /* 0xf8 */
- NULL, /* 0xf9 */
- NULL, /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
- "{PI}" /* 0xff - A single character shaped as greek lowercase 'PI' */
-};
-
-static const char *const basic_20[] = /* "BASIC 2.0" - supported by vic20 & clones, c64 & clones, cbm30xx series */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- NULL, /* 0xcc */
- NULL, /* 0xcd */
- NULL, /* 0xce */
- NULL, /* 0xcf */
- NULL, /* 0xd0 */
- NULL, /* 0xd1 */
- NULL, /* 0xd2 */
- NULL, /* 0xd3 */
- NULL, /* 0xd4 */
- NULL, /* 0xd5 */
- NULL, /* 0xd6 */
- NULL, /* 0xd7 */
- NULL, /* 0xd8 */
- NULL, /* 0xd9 */
- NULL, /* 0xda */
- NULL, /* 0xdb */
- NULL, /* 0xdc */
- NULL, /* 0xdd */
- NULL, /* 0xde */
- NULL, /* 0xdf */
- NULL, /* 0xe0 */
- NULL, /* 0xe1 */
- NULL, /* 0xe2 */
- NULL, /* 0xe3 */
- NULL, /* 0xe4 */
- NULL, /* 0xe5 */
- NULL, /* 0xe6 */
- NULL, /* 0xe7 */
- NULL, /* 0xe8 */
- NULL, /* 0xe9 */
- NULL, /* 0xea */
- NULL, /* 0xeb */
- NULL, /* 0xec */
- NULL, /* 0xed */
- NULL, /* 0xee */
- NULL, /* 0xef */
- NULL, /* 0xf0 */
- NULL, /* 0xf1 */
- NULL, /* 0xf2 */
- NULL, /* 0xf3 */
- NULL, /* 0xf4 */
- NULL, /* 0xf5 */
- NULL, /* 0xf6 */
- NULL, /* 0xf7 */
- NULL, /* 0xf8 */
- NULL, /* 0xf9 */
- NULL, /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
- "{PI}" /* 0xff - A single character shaped as greek lowercase 'PI' */
-};
-
-static const char *const basic_20_super_expander_vic[] = /* "BASIC 2.0 with Super Expander" - supported by vic20 & clones */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- "KEY", /* 0xcc */
- "GRAPHIC", /* 0xcd */
- "SCNCLR", /* 0xce */
- "CIRCLE", /* 0xcf */
- "DRAW", /* 0xd0 */
- "REGION", /* 0xd1 */
- "COLOR", /* 0xd2 */
- "POINT", /* 0xd3 */
- "SOUND", /* 0xd4 */
- "CHAR", /* 0xd5 */
- "PAINT", /* 0xd6 */
- "RPOT", /* 0xd7 */
- "RPEN", /* 0xd8 */
- "RSND", /* 0xd9 */
- "RCOLR", /* 0xda */
- "RGR", /* 0xdb */
- "RJOY", /* 0xdc */
- "RDOT", /* 0xdd */
- NULL, /* 0xde */
- NULL, /* 0xdf */
- NULL, /* 0xe0 */
- NULL, /* 0xe1 */
- NULL, /* 0xe2 */
- NULL, /* 0xe3 */
- NULL, /* 0xe4 */
- NULL, /* 0xe5 */
- NULL, /* 0xe6 */
- NULL, /* 0xe7 */
- NULL, /* 0xe8 */
- NULL, /* 0xe9 */
- NULL, /* 0xea */
- NULL, /* 0xeb */
- NULL, /* 0xec */
- NULL, /* 0xed */
- NULL, /* 0xee */
- NULL, /* 0xef */
- NULL, /* 0xf0 */
- NULL, /* 0xf1 */
- NULL, /* 0xf2 */
- NULL, /* 0xf3 */
- NULL, /* 0xf4 */
- NULL, /* 0xf5 */
- NULL, /* 0xf6 */
- NULL, /* 0xf7 */
- NULL, /* 0xf8 */
- NULL, /* 0xf9 */
- NULL, /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
- "{PI}" /* 0xff - A single character shaped as greek lowercase 'PI' */
-};
-
-static const char *const basic_20_turtle_basic_10[] = /* "BASIC 2.0 with Turtle BASIC 1.0" - supported by vic20 & clones */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- "GRAPHIC", /* 0xcc */
- "OLD", /* 0xcd */
- "TURN", /* 0xce */
- "PEN", /* 0xcf */
- "DRAW", /* 0xd0 */
- "MOVE", /* 0xd1 */
- "POINT", /* 0xd2 */
- "KILL", /* 0xd3 */
- "WRITE", /* 0xd4 */
- "REPEAT", /* 0xd5 */
- "SCREEN", /* 0xd6 */
- "DOKE", /* 0xd7 */
- "RELOC", /* 0xd8 */
- "FILL", /* 0xd9 */
- "RTIME", /* 0xda */
- "BASE", /* 0xdb */
- "PAUSE", /* 0xdc */
- "POP", /* 0xdd */
- "COLOR", /* 0xde */
- "MERGE", /* 0xdf */
- "CHAR", /* 0xe0 */
- "TAKE", /* 0xe1 */
- "SOUND", /* 0xe2 */
- "VOL", /* 0xe3 */
- "PUT", /* 0xe4 */
- "PLACE", /* 0xe5 */
- "CLS", /* 0xe6 */
- "ACCEPT", /* 0xe7 */
- "RESET", /* 0xe8 */
- "GRAB", /* 0xe9 */
- "RDOT", /* 0xea */
- "PLR$", /* 0xeb */
- "DEEK", /* 0xec */
- "JOY", /* 0xed */
- NULL, /* 0xee */
- NULL, /* 0xef */
- NULL, /* 0xf0 */
- NULL, /* 0xf1 */
- NULL, /* 0xf2 */
- NULL, /* 0xf3 */
- NULL, /* 0xf4 */
- NULL, /* 0xf5 */
- NULL, /* 0xf6 */
- NULL, /* 0xf7 */
- NULL, /* 0xf8 */
- NULL, /* 0xf9 */
- NULL, /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
- "{PI}" /* 0xff - A single character shaped as greek lowercase 'PI' */
-};
-
-static const char *const basic_20_speech_basic_27[] = /* "BASIC 2.0 with Speech BASIC 2.7" - supported by c64 & clones */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- "RESET", /* 0xcc */
- "BASIC", /* 0xcd */
- "HELP", /* 0xce */
- "KEY", /* 0xcf */
- "HIMEM", /* 0xd0 */
- "DISK", /* 0xd1 */
- "DIR", /* 0xd2 */
- "BLOAD", /* 0xd3 */
- "BSAVE", /* 0xd4 */
- "MAP", /* 0xd5 */
- "MEM", /* 0xd6 */
- "PAUSE", /* 0xd7 */
- "BLOCK", /* 0xd8 */
- "HEAR", /* 0xd9 */
- "RECORD", /* 0xda */
- "PLAY", /* 0xdb */
- "VOLDEF", /* 0xdc */
- "COLDEF", /* 0xdd */
- "HEX", /* 0xde */
- "DEZ", /* 0xdf */
- "SCREEN", /* 0xe0 */
- "EXEC", /* 0xe1 */
- "MON", /* 0xe2 */
- "{LEFT ARROW}", /* 0xe3 - A single character shaped as a left pointing arrow */
- "FROM", /* 0xe4 */
- "SPEED", /* 0xe5 */
- "OFF", /* 0xe6 */
- NULL, /* 0xe7 */
- NULL, /* 0xe8 */
- NULL, /* 0xe9 */
- NULL, /* 0xea */
- NULL, /* 0xeb */
- NULL, /* 0xec */
- NULL, /* 0xed */
- NULL, /* 0xee */
- NULL, /* 0xef */
- NULL, /* 0xf0 */
- NULL, /* 0xf1 */
- NULL, /* 0xf2 */
- NULL, /* 0xf3 */
- NULL, /* 0xf4 */
- NULL, /* 0xf5 */
- NULL, /* 0xf6 */
- NULL, /* 0xf7 */
- NULL, /* 0xf8 */
- NULL, /* 0xf9 */
- NULL, /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
- "{PI}" /* 0xff - A single character shaped as greek lowercase 'PI' */
-};
-
-static const char *const basic_20_at_basic[] = /* "BASIC 2.0 with @BASIC" - supported by c64 & clones */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- "TRACE", /* 0xcc */
- "DELETE", /* 0xcd */
- "AUTO", /* 0xce */
- "OLD", /* 0xcf */
- "DUMP", /* 0xd0 */
- "FIND", /* 0xd1 */
- "RENUMBER", /* 0xd2 */
- "DLOAD", /* 0xd3 */
- "DSAVE", /* 0xd4 */
- "DVERIFY", /* 0xd5 */
- "DIRECTORY" /* 0xd6 */
- "CATALOG", /* 0xd7 */
- "SCRATCH", /* 0xd8 */
- "COLLECT", /* 0xd9 */
- "RENAME", /* 0xda */
- "COPY", /* 0xdb */
- "BACKUP", /* 0xdc */
- "DISK", /* 0xdd */
- "HEADER", /* 0xde */
- "APPEND", /* 0xdf */
- "MERGE", /* 0xe0 */
- "MLOAD", /* 0xe1 */
- "MVERIFY", /* 0xe2 */
- "MSAVE", /* 0xe3 */
- "KEY", /* 0xe4 */
- "BASIC", /* 0xe5 */
- "RESET", /* 0xe6 */
- "EXIT", /* 0xe7 */
- "ENTER", /* 0xe8 */
- "DOKE", /* 0xe9 */
- "SET", /* 0xea */
- "HELP", /* 0xeb */
- "SCREEN", /* 0xec */
- "LOMEM", /* 0xed */
- "HIMEM", /* 0xee */
- "COLOUR", /* 0xef */
- "TYPE", /* 0xf0 */
- "TIME", /* 0xf1 */
- "DEEK", /* 0xf2 */
- "HEX$", /* 0xf3 */
- "BIN$", /* 0xf4 */
- "OFF", /* 0xf5 */
- "ALARM", /* 0xf6 */
- NULL, /* 0xf7 */
- NULL, /* 0xf8 */
- NULL, /* 0xf9 */
- NULL, /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
- "{PI}" /* 0xff - A single character shaped as greek lowercase 'PI' */
-};
-
-static const char *const basic_20_simon_s_basic[] = /* "BASIC 2.0 with Simon's BASIC" - supported by c64 & clones */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- NULL, /* 0xcc */
- NULL, /* 0xcd */
- NULL, /* 0xce */
- NULL, /* 0xcf */
- NULL, /* 0xd0 */
- NULL, /* 0xd1 */
- NULL, /* 0xd2 */
- NULL, /* 0xd3 */
- NULL, /* 0xd4 */
- NULL, /* 0xd5 */
- NULL, /* 0xd6 */
- NULL, /* 0xd7 */
- NULL, /* 0xd8 */
- NULL, /* 0xd9 */
- NULL, /* 0xda */
- NULL, /* 0xdb */
- NULL, /* 0xdc */
- NULL, /* 0xdd */
- NULL, /* 0xde */
- NULL, /* 0xdf */
- NULL, /* 0xe0 */
- NULL, /* 0xe1 */
- NULL, /* 0xe2 */
- NULL, /* 0xe3 */
- NULL, /* 0xe4 */
- NULL, /* 0xe5 */
- NULL, /* 0xe6 */
- NULL, /* 0xe7 */
- NULL, /* 0xe8 */
- NULL, /* 0xe9 */
- NULL, /* 0xea */
- NULL, /* 0xeb */
- NULL, /* 0xec */
- NULL, /* 0xed */
- NULL, /* 0xee */
- NULL, /* 0xef */
- NULL, /* 0xf0 */
- NULL, /* 0xf1 */
- NULL, /* 0xf2 */
- NULL, /* 0xf3 */
- NULL, /* 0xf4 */
- NULL, /* 0xf5 */
- NULL, /* 0xf6 */
- NULL, /* 0xf7 */
- NULL, /* 0xf8 */
- NULL, /* 0xf9 */
- NULL, /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
- "{PI}", /* 0xff - A single character shaped as greek lowercase 'PI' */
- NULL, /* 0x6400 */
- "HIRES", /* 0x6401 */
- "PLOT", /* 0x6402 */
- "LINE", /* 0x6403 */
- "BLOCK", /* 0x6404 */
- "FCHR", /* 0x6405 */
- "FCOL", /* 0x6406 */
- "FILL", /* 0x6407 */
- "REC", /* 0x6408 */
- "ROT", /* 0x6409 */
- "DRAW", /* 0x640a */
- "CHAR", /* 0x640b */
- "HI COL", /* 0x640c */
- "INV", /* 0x640d */
- "FRAC", /* 0x640e */
- "MOVE", /* 0x640f */
- "PLACE", /* 0x6410 */
- "UPB", /* 0x6411 */
- "UPW", /* 0x6412 */
- "LEFTW", /* 0x6413 */
- "LEFTB", /* 0x6414 */
- "DOWNB", /* 0x6415 */
- "DOWNW", /* 0x6416 */
- "RIGHTB", /* 0x6417 */
- "RIGHTW", /* 0x6418 */
- "MULTI", /* 0x6419 */
- "COLOUR", /* 0x641a */
- "MMOB", /* 0x641b */
- "BFLASH", /* 0x641c */
- "MOB SET", /* 0x641d */
- "MUSIC", /* 0x641e */
- "FLASH", /* 0x641f */
- "REPEAT", /* 0x6420 */
- "PLAY", /* 0x6421 */
- ">>", /* 0x6422 */
- "CENTRE", /* 0x6423 */
- "ENVELOPE", /* 0x6424 */
- "CGOTO", /* 0x6425 */
- "WAVE", /* 0x6426 */
- "FETCH", /* 0x6427 */
- "AT(", /* 0x6428 */
- "UNTIL", /* 0x6429 */
- ">>", /* 0x642a */
- ">>", /* 0x642b */
- "USE", /* 0x642c */
- ">>", /* 0x642d */
- "GLOBAL", /* 0x642e */
- ">>", /* 0x642f */
- "RESET", /* 0x6430 */
- "PROC", /* 0x6431 */
- "CALL", /* 0x6432 */
- "EXEC", /* 0x6433 */
- "END PROC", /* 0x6434 */
- "EXIT", /* 0x6435 */
- "END LOOP", /* 0x6436 */
- "ON KEY", /* 0x6437 */
- "DISABLE", /* 0x6438 */
- "RESUME", /* 0x6439 */
- "LOOP", /* 0x643a */
- "DELAY", /* 0x643b */
- ">>", /* 0x643c */
- ">>", /* 0x643d */
- ">>", /* 0x643e */
- ">>", /* 0x643f */
- "SECURE", /* 0x6440 */
- "DISAPA", /* 0x6441 */
- "CIRCLE", /* 0x6442 */
- "ON ERROR", /* 0x6443 */
- "NO ERROR", /* 0x6444 */
- "LOCAL", /* 0x6445 */
- "RCOMP", /* 0x6446 */
- "ELSE", /* 0x6447 */
- "RETRACE", /* 0x6448 */
- "TRACE", /* 0x6449 */
- "DIR", /* 0x644a */
- "PAGE", /* 0x644b */
- "DUMP", /* 0x644c */
- "FIND", /* 0x644d */
- "OPTION", /* 0x644e */
- "AUTO", /* 0x644f */
- "OLD", /* 0x6450 */
- "JOY", /* 0x6451 */
- "MOD", /* 0x6452 */
- "DIV", /* 0x6453 */
- ">>", /* 0x6454 */
- "DUP", /* 0x6455 */
- "INKEY", /* 0x6456 */
- "INST", /* 0x6457 */
- "TEST", /* 0x6458 */
- "LIN", /* 0x6459 */
- "EXOR", /* 0x645a */
- "INSERT", /* 0x645b */
- "POT", /* 0x645c */
- "PENX", /* 0x645d */
- ">>", /* 0x645e */
- "PENY", /* 0x645f */
- "SOUND", /* 0x6460 */
- "GRAPHICS", /* 0x6461 */
- "DESIGN", /* 0x6462 */
- "RLOCMOB", /* 0x6463 */
- "CMOB", /* 0x6464 */
- "BCKGNDS", /* 0x6465 */
- "PAUSE", /* 0x6466 */
- "NRM", /* 0x6467 */
- "MOB OFF", /* 0x6468 */
- "OFF", /* 0x6469 */
- "ANGL", /* 0x646a */
- "ARC", /* 0x646b */
- "COLD", /* 0x646c */
- "SCRSV", /* 0x646d */
- "SCRLD", /* 0x646e */
- "TEXT", /* 0x646f */
- "CSET", /* 0x6470 */
- "VOL", /* 0x6471 */
- "DISK", /* 0x6472 */
- "HRDCPY", /* 0x6473 */
- "KEY", /* 0x6474 */
- "PAINT", /* 0x6475 */
- "LOW COL", /* 0x6476 */
- "COPY", /* 0x6477 */
- "MERGE", /* 0x6478 */
- "RENUMBER", /* 0x6479 */
- "MEM", /* 0x647a */
- "DETECT", /* 0x647b */
- "CHECK", /* 0x647c */
- "DISPLAY", /* 0x647d */
- "ERR", /* 0x647e */
- "OUT" /* 0x647f */
-};
-
-static const char *const basic_20_exp_40[] = /* "BASIC 2.0 with BASIC 4.0 Expansion" - supported by c64 & clones */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- "CONCAT", /* 0xcc */
- "DOPEN", /* 0xcd */
- "DCLOSE", /* 0xce */
- "RECORD", /* 0xcf */
- "HEADER", /* 0xd0 */
- "COLLECT", /* 0xd1 */
- "BACKUP", /* 0xd2 */
- "COPY", /* 0xd3 */
- "APPEND", /* 0xd4 */
- "DSAVE", /* 0xd5 */
- "DLOAD", /* 0xd6 */
- "CATALOG", /* 0xd7 */
- "RENAME", /* 0xd8 */
- "SCRATCH", /* 0xd9 */
- "DIRECTORY", /* 0xda */
- "COLOR", /* 0xdb */
- "COLD", /* 0xdc */
- "KEY", /* 0xdd */
- "DVERIFY", /* 0xde */
- "DELETE" /* 0xdf */
- "AUTO", /* 0xe0 */
- "MERGE", /* 0xe1 */
- "OLD", /* 0xe2 */
- "MONITOR", /* 0xe3 */
- NULL, /* 0xe4 */
- NULL, /* 0xe5 */
- NULL, /* 0xe6 */
- NULL, /* 0xe7 */
- NULL, /* 0xe8 */
- NULL, /* 0xe9 */
- NULL, /* 0xea */
- NULL, /* 0xeb */
- NULL, /* 0xec */
- NULL, /* 0xed */
- NULL, /* 0xee */
- NULL, /* 0xef */
- NULL, /* 0xf0 */
- NULL, /* 0xf1 */
- NULL, /* 0xf2 */
- NULL, /* 0xf3 */
- NULL, /* 0xf4 */
- NULL, /* 0xf5 */
- NULL, /* 0xf6 */
- NULL, /* 0xf7 */
- NULL, /* 0xf8 */
- NULL, /* 0xf9 */
- NULL, /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
- "{PI}" /* 0xff - A single character shaped as greek lowercase 'PI' */
-};
-
-static const char *const basic_35[] = /* "BASIC 3.5" - supported by c16 & clones, except c364 */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- "RGR", /* 0xcc */
- "RCLR" /* 0xcd */
- "RLUM" /* 0xce */
- "JOY", /* 0xcf */
- "RDOT" /* 0xd0 */
- "DEC", /* 0xd1 */
- "HEX$", /* 0xd2 */
- "ERR$", /* 0xd3 */
- "INSTR", /* 0xd4 */
- "ELSE", /* 0xd5 */
- "RESUME", /* 0xd6 */
- "TRAP", /* 0xd7 */
- "TRON", /* 0xd8 */
- "TROFF", /* 0xd9 */
- "SOUND", /* 0xda */
- "VOL", /* 0xdb */
- "AUTO", /* 0xdc */
- "PUDEF", /* 0xdd */
- "GRAPHIC", /* 0xde */
- "PAINT", /* 0xdf */
- "CHAR", /* 0xe0 */
- "BOX", /* 0xe1 */
- "CIRCLE", /* 0xe2 */
- "GSHAPE", /* 0xe3 */
- "SSHAPE", /* 0xe4 */
- "DRAW", /* 0xe5 */
- "LOCATE", /* 0xe6 */
- "COLOR", /* 0xe7 */
- "SCNCLR", /* 0xe8 */
- "SCALE", /* 0xe9 */
- "HELP", /* 0xea */
- "DO", /* 0xeb */
- "LOOP", /* 0xec */
- "EXIT", /* 0xed */
- "DIRECTORY", /* 0xee */
- "DSAVE", /* 0xef */
- "DLOAD", /* 0xf0 */
- "HEADER", /* 0xf1 */
- "SCRATCH", /* 0xf2 */
- "COLLECT", /* 0xf3 */
- "COPY", /* 0xf4 */
- "RENAME", /* 0xf5 */
- "BACKUP", /* 0xf6 */
- "DELETE", /* 0xf7 */
- "RENUMBER", /* 0xf8 */
- "KEY", /* 0xf9 */
- "MONITOR", /* 0xfa */
- "USING", /* 0xfb */
- "UNTIL", /* 0xfc */
- "WHILE", /* 0xfd */
- NULL, /* 0xfe */
- "{PI}" /* 0xff - A single character shaped as greek lowercase 'PI' */
-};
-
-static const char *const basic_35_magic_voice[] = /* "BASIC 3.5 with Magic Voice Speech Synthesizer" - supported by c364 */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- "RGR", /* 0xcc */
- "RCLR" /* 0xcd */
- "RLUM" /* 0xce */
- "JOY", /* 0xcf */
- "RDOT" /* 0xd0 */
- "DEC", /* 0xd1 */
- "HEX$", /* 0xd2 */
- "ERR$", /* 0xd3 */
- "INSTR", /* 0xd4 */
- "ELSE", /* 0xd5 */
- "RESUME", /* 0xd6 */
- "TRAP", /* 0xd7 */
- "TRON", /* 0xd8 */
- "TROFF", /* 0xd9 */
- "SOUND", /* 0xda */
- "VOL", /* 0xdb */
- "AUTO", /* 0xdc */
- "PUDEF", /* 0xdd */
- "GRAPHIC", /* 0xde */
- "PAINT", /* 0xdf */
- "CHAR", /* 0xe0 */
- "BOX", /* 0xe1 */
- "CIRCLE", /* 0xe2 */
- "GSHAPE", /* 0xe3 */
- "SSHAPE", /* 0xe4 */
- "DRAW", /* 0xe5 */
- "LOCATE", /* 0xe6 */
- "COLOR", /* 0xe7 */
- "SCNCLR", /* 0xe8 */
- "SCALE", /* 0xe9 */
- "HELP", /* 0xea */
- "DO", /* 0xeb */
- "LOOP", /* 0xec */
- "EXIT", /* 0xed */
- "DIRECTORY", /* 0xee */
- "DSAVE", /* 0xef */
- "DLOAD", /* 0xf0 */
- "HEADER", /* 0xf1 */
- "SCRATCH", /* 0xf2 */
- "COLLECT", /* 0xf3 */
- "COPY", /* 0xf4 */
- "RENAME", /* 0xf5 */
- "BACKUP", /* 0xf6 */
- "DELETE", /* 0xf7 */
- "RENUMBER", /* 0xf8 */
- "KEY", /* 0xf9 */
- "MONITOR", /* 0xfa */
- "USING", /* 0xfb */
- "UNTIL", /* 0xfc */
- "WHILE", /* 0xfd */
- NULL, /* 0xfe - Prefix for additional tokens */
- "{PI}", /* 0xff - A single character shaped as greek lowercase 'PI' */
- NULL, /* 0xfe00 */
- "RATE", /* 0xfe01 */
- "VOC", /* 0xfe02 */
- NULL, /* 0xfe03 */
- "RDY", /* 0xfe04 */
- NULL, /* 0xfe05 */
- NULL, /* 0xfe06 */
- NULL, /* 0xfe07 */
- NULL, /* 0xfe08 */
- NULL, /* 0xfe09 */
- "SAY" /* 0xfe0a */
-};
-
-static const char *const basic_40[] = /* "BASIC 4.0" - supported by cbm40xx & cbm80xx series, p500, cbm600 & clones */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- "CONCAT", /* 0xcc */
- "DOPEN", /* 0xcd */
- "DCLOSE", /* 0xce */
- "RECORD", /* 0xcf */
- "HEADER", /* 0xd0 */
- "COLLECT", /* 0xd1 */
- "BACKUP", /* 0xd2 */
- "COPY", /* 0xd3 */
- "APPEND", /* 0xd4 */
- "DSAVE", /* 0xd5 */
- "DLOAD", /* 0xd6 */
- "CATALOG", /* 0xd7 */
- "RENAME", /* 0xd8 */
- "SCRATCH", /* 0xd9 */
- "DIRECTORY", /* 0xda */
- NULL, /* 0xdb */
- NULL, /* 0xdc */
- NULL, /* 0xdd */
- NULL, /* 0xde */
- NULL, /* 0xdf */
- NULL, /* 0xe0 */
- NULL, /* 0xe1 */
- NULL, /* 0xe2 */
- NULL, /* 0xe3 */
- NULL, /* 0xe4 */
- NULL, /* 0xe5 */
- NULL, /* 0xe6 */
- NULL, /* 0xe7 */
- NULL, /* 0xe8 */
- NULL, /* 0xe9 */
- NULL, /* 0xea */
- NULL, /* 0xeb */
- NULL, /* 0xec */
- NULL, /* 0xed */
- NULL, /* 0xee */
- NULL, /* 0xef */
- NULL, /* 0xf0 */
- NULL, /* 0xf1 */
- NULL, /* 0xf2 */
- NULL, /* 0xf3 */
- NULL, /* 0xf4 */
- NULL, /* 0xf5 */
- NULL, /* 0xf6 */
- NULL, /* 0xf7 */
- NULL, /* 0xf8 */
- NULL, /* 0xf9 */
- NULL, /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
- "{PI}" /* 0xff - A single character shaped as greek lowercase 'PI' */
-};
-
-static const char *const basic_70[] = /* "BASIC 7.0" - supported by c128 & clones */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- "RGR", /* 0xcc */
- "RCLR", /* 0xcd */
- NULL, /* 0xce - Prefix for additional tokens */
- "JOY", /* 0xcf */
- "RDOT" /* 0xd0 */
- "DEC", /* 0xd1 */
- "HEX$", /* 0xd2 */
- "ERR$", /* 0xd3 */
- "INSTR", /* 0xd4 */
- "ELSE", /* 0xd5 */
- "RESUME", /* 0xd6 */
- "TRAP", /* 0xd7 */
- "TRON", /* 0xd8 */
- "TROFF", /* 0xd9 */
- "SOUND", /* 0xda */
- "VOL", /* 0xdb */
- "AUTO", /* 0xdc */
- "PUDEF", /* 0xdd */
- "GRAPHIC", /* 0xde */
- "PAINT", /* 0xdf */
- "CHAR", /* 0xe0 */
- "BOX", /* 0xe1 */
- "CIRCLE", /* 0xe2 */
- "GSHAPE", /* 0xe3 */
- "SSHAPE", /* 0xe4 */
- "DRAW", /* 0xe5 */
- "LOCATE", /* 0xe6 */
- "COLOR", /* 0xe7 */
- "SCNCLR", /* 0xe8 */
- "SCALE", /* 0xe9 */
- "HELP", /* 0xea */
- "DO", /* 0xeb */
- "LOOP", /* 0xec */
- "EXIT", /* 0xed */
- "DIRECTORY", /* 0xee */
- "DSAVE", /* 0xef */
- "DLOAD", /* 0xf0 */
- "HEADER", /* 0xf1 */
- "SCRATCH", /* 0xf2 */
- "COLLECT", /* 0xf3 */
- "COPY", /* 0xf4 */
- "RENAME", /* 0xf5 */
- "BACKUP", /* 0xf6 */
- "DELETE", /* 0xf7 */
- "RENUMBER", /* 0xf8 */
- "KEY", /* 0xf9 */
- "MONITOR", /* 0xfa */
- "USING", /* 0xfb */
- "UNTIL", /* 0xfc */
- "WHILE", /* 0xfd */
- NULL, /* 0xfe - Prefix for additional tokens */
- "{PI}", /* 0xff - A single character shaped as greek lowercase 'PI' */
- NULL, /* 0xce00 */
- NULL, /* 0xce01 */
- "POT", /* 0xce02 */
- "BUMP", /* 0xce03 */
- "PEN", /* 0xce04 */
- "RSPPOS", /* 0xce05 */
- "RSPRITE", /* 0xce06 */
- "RSPCOLOR", /* 0xce07 */
- "XOR", /* 0xce08 */
- "RWINDOW", /* 0xce09 */
- "POINTER", /* 0xce0a */
- NULL, /* 0xfe00 */
- NULL, /* 0xfe01 */
- "BANK", /* 0xfe02 */
- "FILTER", /* 0xfe03 */
- "PLAY", /* 0xfe04 */
- "TEMPO", /* 0xfe05 */
- "MOVSPR", /* 0xfe06 */
- "SPRITE", /* 0xfe07 */
- "SPRCOLOR", /* 0xfe08 */
- "RREG", /* 0xfe09 */
- "ENVELOPE", /* 0xfe0a */
- "SLEEP", /* 0xfe0b */
- "CATALOG", /* 0xfe0c */
- "DOPEN", /* 0xfe0d */
- "APPEND", /* 0xfe0e */
- "DCLOSE", /* 0xfe0f */
- "BSAVE", /* 0xfe10 */
- "BLOAD", /* 0xfe11 */
- "RECORD", /* 0xfe12 */
- "CONCAT", /* 0xfe13 */
- "DVERIFY", /* 0xfe14 */
- "DCLEAR", /* 0xfe15 */
- "SPRSAV", /* 0xfe16 */
- "COLLISION", /* 0xfe17 */
- "BEGIN", /* 0xfe18 */
- "BEND", /* 0xfe19 */
- "WINDOW", /* 0xfe1a */
- "BOOT", /* 0xfe1b */
- "WIDTH", /* 0xfe1c */
- "SPRDEF", /* 0xfe1d */
- "QUIT", /* 0xfe1e */
- "STASH", /* 0xfe1f */
- NULL, /* 0xfe20 */
- "FETCH", /* 0xfe21 */
- NULL, /* 0xfe22 */
- "SWAP", /* 0xfe23 */
- "OFF", /* 0xfe24 */
- "FAST", /* 0xfe25 */
- "SLOW" /* 0xfe26 */
-};
-
-static const char *const basic_100[] = /* "BASIC 10.0" - supported by c65 & clones */
-{
- "END", /* 0x80 */
- "FOR", /* 0x81 */
- "NEXT", /* 0x82 */
- "DATA", /* 0x83 */
- "INPUT#", /* 0x84 */
- "INPUT", /* 0x85 */
- "DIM", /* 0x86 */
- "READ", /* 0x87 */
- "LET", /* 0x88 */
- "GOTO", /* 0x89 */
- "RUN", /* 0x8a */
- "IF", /* 0x8b */
- "RESTORE", /* 0x8c */
- "GOSUB", /* 0x8d */
- "RETURN", /* 0x8e */
- "REM", /* 0x8f */
- "STOP", /* 0x90 */
- "ON", /* 0x91 */
- "WAIT", /* 0x92 */
- "LOAD", /* 0x93 */
- "SAVE", /* 0x94 */
- "VERIFY", /* 0x95 */
- "DEF", /* 0x96 */
- "POKE", /* 0x97 */
- "PRINT#", /* 0x98 */
- "PRINT", /* 0x99 */
- "CONT", /* 0x9a */
- "LIST", /* 0x9b */
- "CLR", /* 0x9c */
- "CMD", /* 0x9d */
- "SYS", /* 0x9e */
- "OPEN", /* 0x9f */
- "CLOSE", /* 0xa0 */
- "GET", /* 0xa1 */
- "NEW", /* 0xa2 */
- "TAB(", /* 0xa3 */
- "TO", /* 0xa4 */
- "FN", /* 0xa5 */
- "SPC(", /* 0xa6 */
- "THEN", /* 0xa7 */
- "NOT", /* 0xa8 */
- "STEP", /* 0xa9 */
- "+", /* 0xaa */
- "-", /* 0xab */
- "*", /* 0xac */
- "/", /* 0xad */
- "^", /* 0xae */
- "AND", /* 0xaf */
- "OR", /* 0xb0 */
- ">", /* 0xb1 */
- "=", /* 0xb2 */
- "<", /* 0xb3 */
- "SGN", /* 0xb4 */
- "INT", /* 0xb5 */
- "ABS", /* 0xb6 */
- "USR", /* 0xb7 */
- "FRE", /* 0xb8 */
- "POS", /* 0xb9 */
- "SQR", /* 0xba */
- "RND", /* 0xbb */
- "LOG", /* 0xbc */
- "EXP", /* 0xbd */
- "COS", /* 0xbe */
- "SIN", /* 0xbf */
- "TAN", /* 0xc0 */
- "ATN", /* 0xc1 */
- "PEEK", /* 0xc2 */
- "LEN", /* 0xc3 */
- "STR$", /* 0xc4 */
- "VAL", /* 0xc5 */
- "ASC", /* 0xc6 */
- "CHR$", /* 0xc7 */
- "LEFT$", /* 0xc8 */
- "RIGHT$", /* 0xc9 */
- "MID$", /* 0xca */
- "GO", /* 0xcb */
- "RGR", /* 0xcc */
- "RCLR", /* 0xcd */
- NULL, /* 0xce - Prefix for additional tokens */
- "JOY", /* 0xcf */
- "RDOT" /* 0xd0 */
- "DEC", /* 0xd1 */
- "HEX$", /* 0xd2 */
- "ERR$", /* 0xd3 */
- "INSTR", /* 0xd4 */
- "ELSE", /* 0xd5 */
- "RESUME", /* 0xd6 */
- "TRAP", /* 0xd7 */
- "TRON", /* 0xd8 */
- "TROFF", /* 0xd9 */
- "SOUND", /* 0xda */
- "VOL", /* 0xdb */
- "AUTO", /* 0xdc */
- "PUDEF", /* 0xdd */
- "GRAPHIC", /* 0xde */
- "PAINT", /* 0xdf */
- "CHAR", /* 0xe0 */
- "BOX", /* 0xe1 */
- "CIRCLE", /* 0xe2 */
- "PASTE", /* 0xe3 */
- "CUT", /* 0xe4 */
- "LINE", /* 0xe5 */
- "LOCATE", /* 0xe6 */
- "COLOR", /* 0xe7 */
- "SCNCLR", /* 0xe8 */
- "SCALE", /* 0xe9 */
- "HELP", /* 0xea */
- "DO", /* 0xeb */
- "LOOP", /* 0xec */
- "EXIT", /* 0xed */
- "DIR", /* 0xee */
- "DSAVE", /* 0xef */
- "DLOAD", /* 0xf0 */
- "HEADER", /* 0xf1 */
- "SCRATCH", /* 0xf2 */
- "COLLECT", /* 0xf3 */
- "COPY", /* 0xf4 */
- "RENAME", /* 0xf5 */
- "BACKUP", /* 0xf6 */
- "DELETE", /* 0xf7 */
- "RENUMBER", /* 0xf8 */
- "KEY", /* 0xf9 */
- "MONITOR", /* 0xfa */
- "USING", /* 0xfb */
- "UNTIL", /* 0xfc */
- "WHILE", /* 0xfd */
- NULL, /* 0xfe - Prefix for additional tokens */
- "{PI}", /* 0xff - A single character shaped as greek lowercase 'PI' */
- NULL, /* 0xce00 */
- NULL, /* 0xce01 */
- "POT", /* 0xce02 */
- "BUMP", /* 0xce03 */
- "PEN", /* 0xce04 */
- "RSPPOS", /* 0xce05 */
- "RSPRITE", /* 0xce06 */
- "RSPCOLOR", /* 0xce07 */
- "XOR", /* 0xce08 */
- "RWINDOW", /* 0xce09 */
- "POINTER", /* 0xce0a */
- NULL, /* 0xfe00 */
- NULL, /* 0xfe01 */
- "BANK", /* 0xfe02 */
- "FILTER", /* 0xfe03 */
- "PLAY", /* 0xfe04 */
- "TEMPO", /* 0xfe05 */
- "MOVSPR", /* 0xfe06 */
- "SPRITE", /* 0xfe07 */
- "SPRCOLOR", /* 0xfe08 */
- "RREG", /* 0xfe09 */
- "ENVELOPE", /* 0xfe0a */
- "SLEEP", /* 0xfe0b */
- "CATALOG", /* 0xfe0c */
- "DOPEN", /* 0xfe0d */
- "APPEND", /* 0xfe0e */
- "DCLOSE", /* 0xfe0f */
- "BSAVE", /* 0xfe10 */
- "BLOAD", /* 0xfe11 */
- "RECORD", /* 0xfe12 */
- "CONCAT", /* 0xfe13 */
- "DVERIFY", /* 0xfe14 */
- "DCLEAR", /* 0xfe15 */
- "SPRSAV", /* 0xfe16 */
- "COLLISION", /* 0xfe17 */
- "BEGIN", /* 0xfe18 */
- "BEND", /* 0xfe19 */
- "WINDOW", /* 0xfe1a */
- "BOOT", /* 0xfe1b */
- "WIDTH", /* 0xfe1c */
- "SPRDEF", /* 0xfe1d */
- "QUIT", /* 0xfe1e */
- "DMA", /* 0xfe1f */
- NULL, /* 0xfe20 */
- "DMA", /* 0xfe21 */
- NULL, /* 0xfe22 */
- "DMA", /* 0xfe23 */
- "OFF", /* 0xfe24 */
- "FAST", /* 0xfe25 */
- "SLOW", /* 0xfe26 */
- "TYPE", /* 0xfe27 */
- "BVERIFY", /* 0xfe28 */
- "ECTORY", /* 0xfe29 */
- "ERASE", /* 0xfe2a */
- "FIND", /* 0xfe2b */
- "CHANGE", /* 0xfe2c */
- "SET", /* 0xfe2d */
- "SCREEN", /* 0xfe2e */
- "POLYGON", /* 0xfe2f */
- "ELLIPSE", /* 0xfe30 */
- "VIEWPORT", /* 0xfe31 */
- "GCOPY", /* 0xfe32 */
- "PEN", /* 0xfe33 */
- "PALETTE", /* 0xfe34 */
- "DMODE", /* 0xfe35 */
- "DPAT", /* 0xfe36 */
- "PIC", /* 0xfe37 */
- "GENLOCK", /* 0xfe38 */
- "FOREGROUND", /* 0xfe39 */
- NULL, /* 0xfe3a */
- "BACKGROUND", /* 0xfe3b */
- "BORDER", /* 0xfe3c */
- "HIGHLIGHT" /* 0xfe3d */
-};
-
-#endif
-
-
-
-/***************************************************************************
- COCO BASIC
-***************************************************************************/
-
-static const basictoken_tableent cocobas_tokenents[] =
-{
- { 0x00, 0x80, cocobas_statements, ARRAY_LENGTH(cocobas_statements) },
- { 0xff, 0x80, cocobas_functions, ARRAY_LENGTH(cocobas_functions) }
-};
-
-static const basictokens cocobas_tokens =
-{
- 0x2600,
- 3,
- TRUE,
- cocobas_tokenents,
- ARRAY_LENGTH(cocobas_tokenents)
-};
-
-static imgtoolerr_t cocobas_readfile(imgtool_partition *partition, const char *filename,
- const char *fork, imgtool_stream *destf)
-{
- return basic_readfile(&cocobas_tokens, partition, filename, fork, destf);
-}
-
-static imgtoolerr_t cocobas_writefile(imgtool_partition *partition, const char *filename,
- const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- return basic_writefile(&cocobas_tokens, partition, filename, fork, sourcef, opts);
-}
-
-void filter_cocobas_getinfo(UINT32 state, union filterinfo *info)
-{
- switch(state)
- {
- case FILTINFO_STR_NAME: info->s = "cocobas"; break;
- case FILTINFO_STR_HUMANNAME: info->s = "CoCo Tokenized Basic Files"; break;
- case FILTINFO_PTR_READFILE: info->read_file = cocobas_readfile; break;
- case FILTINFO_PTR_WRITEFILE: info->write_file = cocobas_writefile; break;
- }
-}
-
-
-
-/***************************************************************************
- DRAGON BASIC
-***************************************************************************/
-
-static const basictoken_tableent dragonbas_tokenents[] =
-{
- { 0x00, 0x80, dragonbas_statements, ARRAY_LENGTH(dragonbas_statements) },
- { 0xff, 0x80, dragonbas_functions, ARRAY_LENGTH(dragonbas_functions) }
-};
-
-static const basictokens dragonbas_tokens =
-{
- 0x2600,
- 4,
- TRUE,
- dragonbas_tokenents,
- ARRAY_LENGTH(dragonbas_tokenents)
-};
-
-static imgtoolerr_t dragonbas_readfile(imgtool_partition *partition, const char *filename,
- const char *fork, imgtool_stream *destf)
-{
- return basic_readfile(&dragonbas_tokens, partition, filename, fork, destf);
-}
-
-static imgtoolerr_t dragonbas_writefile(imgtool_partition *partition, const char *filename,
- const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- return basic_writefile(&dragonbas_tokens, partition, filename, fork, sourcef, opts);
-}
-
-void filter_dragonbas_getinfo(UINT32 state, union filterinfo *info)
-{
- switch(state)
- {
- case FILTINFO_STR_NAME: info->s = "dragonbas"; break;
- case FILTINFO_STR_HUMANNAME: info->s = "Dragon Tokenized Basic Files"; break;
- case FILTINFO_PTR_READFILE: info->read_file = dragonbas_readfile; break;
- case FILTINFO_PTR_WRITEFILE: info->write_file = dragonbas_writefile; break;
- }
-}
-
-
-
-/***************************************************************************
- VZBASIC
-***************************************************************************/
-
-static const basictoken_tableent vzbas_tokenents[] =
-{
- { 0x00, 0x80, vzbas, ARRAY_LENGTH(vzbas) }
-};
-
-
-
-static const basictokens vzbas_tokens =
-{
- 0x7ae9,
- 0,
- FALSE,
- vzbas_tokenents,
- ARRAY_LENGTH(vzbas_tokenents)
-};
-
-static imgtoolerr_t vzbas_readfile(imgtool_partition *partition, const char *filename,
- const char *fork, imgtool_stream *destf)
-{
- return basic_readfile(&vzbas_tokens, partition, filename, fork, destf);
-}
-
-static imgtoolerr_t vzbas_writefile(imgtool_partition *partition, const char *filename,
- const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- return basic_writefile(&vzbas_tokens, partition, filename, fork, sourcef, opts);
-}
-
-void filter_vzbas_getinfo(UINT32 state, union filterinfo *info)
-{
- switch(state)
- {
- case FILTINFO_STR_NAME: info->s = "vzbas"; break;
- case FILTINFO_STR_HUMANNAME: info->s = "Laser/VZ Tokenized Basic Files"; break;
- case FILTINFO_PTR_READFILE: info->read_file = vzbas_readfile; break;
- case FILTINFO_PTR_WRITEFILE: info->write_file = vzbas_writefile; break;
- }
-}
-
-
-
-/***************************************************************************
- BML3 BASIC
-***************************************************************************/
-
-static const basictoken_tableent bml3bas_tokenents[] =
-{
- { 0x00, 0x80, bml3bas_statements, ARRAY_LENGTH(bml3bas_statements) },
- { 0xff, 0x80, bml3bas_functions, ARRAY_LENGTH(bml3bas_functions) }
-};
-
-static const basictokens bml3bas_tokens =
-{
- 0x2600,
- 3,
- TRUE,
- bml3bas_tokenents,
- ARRAY_LENGTH(bml3bas_tokenents)
-};
-
-static imgtoolerr_t bml3bas_readfile(imgtool_partition *partition, const char *filename,
- const char *fork, imgtool_stream *destf)
-{
- return basic_readfile(&bml3bas_tokens, partition, filename, fork, destf);
-}
-
-static imgtoolerr_t bml3bas_writefile(imgtool_partition *partition, const char *filename,
- const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- return basic_writefile(&bml3bas_tokens, partition, filename, fork, sourcef, opts);
-}
-
-void filter_bml3bas_getinfo(UINT32 state, union filterinfo *info)
-{
- switch(state)
- {
- case FILTINFO_STR_NAME: info->s = "bml3bas"; break;
- case FILTINFO_STR_HUMANNAME: info->s = "Basic Master Level 3 Tokenized Basic Files"; break;
- case FILTINFO_PTR_READFILE: info->read_file = bml3bas_readfile; break;
- case FILTINFO_PTR_WRITEFILE: info->write_file = bml3bas_writefile; break;
- }
-}
diff --git a/src/mess/tools/imgtool/filteoln.c b/src/mess/tools/imgtool/filteoln.c
deleted file mode 100644
index 30fb52ed429..00000000000
--- a/src/mess/tools/imgtool/filteoln.c
+++ /dev/null
@@ -1,127 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/****************************************************************************
-
- filteoln.c
-
- Native end-of-line filter
-
-*****************************************************************************/
-
-#include <string.h>
-
-#include "imgtool.h"
-
-#define EOLN (CRLF == 1 ? "\r" : (CRLF == 2 ? "\n" : (CRLF == 3 ? "\r\n" : NULL)))
-
-
-
-static imgtoolerr_t convert_stream_eolns(imgtool_stream *source, imgtool_stream *dest, const char *eoln)
-{
- size_t len, i, pos;
- char buffer[2000];
- int hit_cr = FALSE;
-
- while((len = stream_read(source, buffer, sizeof(buffer))) > 0)
- {
- pos = 0;
-
- for (i = 0; i < len; i++)
- {
- switch(buffer[i])
- {
- case '\r':
- case '\n':
- if (!hit_cr || (buffer[i] != '\n'))
- {
- if (i > pos)
- stream_write(dest, buffer + pos, i - pos);
- stream_write(dest, eoln, strlen(eoln));
- }
- pos = i + 1;
- break;
- }
- hit_cr = (buffer[i] == '\r');
- }
-
- if (i > pos)
- stream_write(dest, buffer + pos, i - pos);
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t ascii_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- imgtoolerr_t err;
- imgtool_stream *mem_stream;
-
- mem_stream = stream_open_mem(NULL, 0);
- if (!mem_stream)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- err = imgtool_partition_read_file(partition, filename, fork, mem_stream, NULL);
- if (err)
- goto done;
-
- stream_seek(mem_stream, SEEK_SET, 0);
- err = convert_stream_eolns(mem_stream, destf, EOLN);
- if (err)
- goto done;
-
-done:
- if (mem_stream)
- stream_close(mem_stream);
- return err;
-}
-
-
-
-static imgtoolerr_t ascii_writefile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- imgtoolerr_t err;
- imgtool_stream *mem_stream = NULL;
- const char *eoln;
-
- /* create a stream */
- mem_stream = stream_open_mem(NULL, 0);
- if (!mem_stream)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- eoln = imgtool_partition_get_info_string(partition, IMGTOOLINFO_STR_EOLN);
-
- err = convert_stream_eolns(sourcef, mem_stream, eoln);
- if (err)
- goto done;
- stream_seek(mem_stream, SEEK_SET, 0);
-
- err = imgtool_partition_write_file(partition, filename, fork, mem_stream, opts, NULL);
- if (err)
- goto done;
-
-done:
- if (mem_stream)
- stream_close(mem_stream);
- return err;
-}
-
-
-
-void filter_eoln_getinfo(UINT32 state, union filterinfo *info)
-{
- switch(state)
- {
- case FILTINFO_STR_NAME: info->s = "ascii"; break;
- case FILTINFO_STR_HUMANNAME: info->s = "Ascii"; break;
- case FILTINFO_PTR_READFILE: info->read_file = ascii_readfile; break;
- case FILTINFO_PTR_WRITEFILE: info->write_file = ascii_writefile; break;
- }
-}
diff --git a/src/mess/tools/imgtool/filter.c b/src/mess/tools/imgtool/filter.c
deleted file mode 100644
index 5887d6b501d..00000000000
--- a/src/mess/tools/imgtool/filter.c
+++ /dev/null
@@ -1,82 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- filter.c
-
- Imgtool filters
-
-***************************************************************************/
-
-#include <string.h>
-
-#include "imgtool.h"
-
-/* ----------------------------------------------------------------------- */
-
-INT64 filter_get_info_int(filter_getinfoproc get_info, UINT32 state)
-{
- union filterinfo info;
- info.i = 0;
- get_info(state, &info);
- return info.i;
-}
-
-void *filter_get_info_ptr(filter_getinfoproc get_info, UINT32 state)
-{
- union filterinfo info;
- info.p = NULL;
- get_info(state, &info);
- return info.p;
-}
-
-void *filter_get_info_fct(filter_getinfoproc get_info, UINT32 state)
-{
- union filterinfo info;
- info.f = NULL;
- get_info(state, &info);
- return info.f;
-}
-
-const char *filter_get_info_string(filter_getinfoproc get_info, UINT32 state)
-{
- union filterinfo info;
- info.s = NULL;
- get_info(state, &info);
- return info.s;
-}
-
-/* ----------------------------------------------------------------------- */
-
-const filter_getinfoproc filters[] =
-{
- filter_eoln_getinfo,
- filter_cocobas_getinfo,
- filter_dragonbas_getinfo,
- filter_macbinary_getinfo,
- filter_vzsnapshot_getinfo,
- filter_vzbas_getinfo,
- filter_thombas5_getinfo,
- filter_thombas7_getinfo,
- filter_thombas128_getinfo,
- filter_thomcrypt_getinfo,
- filter_bml3bas_getinfo,
- NULL
-};
-
-
-
-filter_getinfoproc filter_lookup(const char *name)
-{
- int i;
- const char *filter_name;
-
- for (i = 0; filters[i]; i++)
- {
- filter_name = filter_get_info_string(filters[i], FILTINFO_STR_NAME);
- if (!strcmp(name, filter_name))
- return filters[i];
- }
-
- return NULL;
-}
diff --git a/src/mess/tools/imgtool/filter.h b/src/mess/tools/imgtool/filter.h
deleted file mode 100644
index 814d813d598..00000000000
--- a/src/mess/tools/imgtool/filter.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- filter.h
-
- Imgtool filters
-
-***************************************************************************/
-
-#ifndef FILTER_H
-#define FILTER_H
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "library.h"
-
-struct imgtool_filter;
-
-enum
-{
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- FILTINFO_INT_FIRST = 0x00000,
- FILTINFO_INT_STATESIZE,
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- FILTINFO_PTR_FIRST = 0x10000,
- FILTINFO_PTR_READFILE,
- FILTINFO_PTR_WRITEFILE,
- FILTINFO_PTR_CHECKSTREAM,
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- FILTINFO_STR_FIRST = 0x20000,
- FILTINFO_STR_NAME,
- FILTINFO_STR_HUMANNAME,
- FILTINFO_STR_EXTENSION
-};
-
-extern const filter_getinfoproc filters[];
-
-filter_getinfoproc filter_lookup(const char *name);
-
-/* ----------------------------------------------------------------------- */
-
-INT64 filter_get_info_int(filter_getinfoproc get_info, UINT32 state);
-void *filter_get_info_ptr(filter_getinfoproc get_info, UINT32 state);
-void *filter_get_info_fct(filter_getinfoproc get_info, UINT32 state);
-const char *filter_get_info_string(filter_getinfoproc get_info, UINT32 state);
-
-/* ----------------------------------------------------------------------- */
-
-extern void filter_eoln_getinfo(UINT32 state, union filterinfo *info);
-extern void filter_cocobas_getinfo(UINT32 state, union filterinfo *info);
-extern void filter_dragonbas_getinfo(UINT32 state, union filterinfo *info);
-extern void filter_macbinary_getinfo(UINT32 state, union filterinfo *info);
-extern void filter_vzsnapshot_getinfo(UINT32 state, union filterinfo *info);
-extern void filter_vzbas_getinfo(UINT32 state, union filterinfo *info);
-extern void filter_thombas5_getinfo(UINT32 state, union filterinfo *info);
-extern void filter_thombas7_getinfo(UINT32 state, union filterinfo *info);
-extern void filter_thombas128_getinfo(UINT32 state, union filterinfo *info);
-extern void filter_thomcrypt_getinfo(UINT32 state, union filterinfo *info);
-extern void filter_bml3bas_getinfo(UINT32 state, union filterinfo *info);
-
-
-#endif /* FILTER_H */
diff --git a/src/mess/tools/imgtool/formats/coco_dsk.c b/src/mess/tools/imgtool/formats/coco_dsk.c
deleted file mode 100644
index 9674ed9de11..00000000000
--- a/src/mess/tools/imgtool/formats/coco_dsk.c
+++ /dev/null
@@ -1,1194 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/*********************************************************************
-
- formats/coco_dsk.c
-
- Tandy Color Computer / Dragon disk images
-
-*********************************************************************/
-
-#include <string.h>
-#include <time.h>
-#include <assert.h>
-
-#include "formats/coco_dsk.h"
-#include "formats/basicdsk.h"
-#include "formats/imageutl.h"
-#include "coretmpl.h"
-
-/* -----------------------------------------------------------------------
- * JVC (Jeff Vavasour CoCo) format
- *
- * Used by Jeff Vavasour's CoCo Emulators
- *
- * Documentation taken from Tim Linder's web site:
- * http://home.netcom.com/~tlindner/JVC.html
- *
- * A. Header length
- * The header length is determined by the file length modulo 256:
- * headerSize = fileLength % 256;
- * This means that the header is variable length and the minimum size
- * is zero bytes, and the maximum size of 255 bytes.
- *
- * B. Header
- * Here is a description of the header bytes:
- * Byte Offset Description Default
- * ----------- ----------------- -------
- * 0 Sectors per track 18
- * 1 Side count 1
- * 2 Sector size code 1
- * 3 First sector ID 1
- * 4 Sector attribute flag 0
- *
- * If the sector attribute flag is zero then the track count is determined
- * by the formula:
- *
- * (fileLength - headerSize) / (sectorsPerTrack * (128 <<
- * sectorSizeCode)) / sideCount
- *
- * If the sector attribute flag is non zero then the track count is
- * determined by the more complex formula:
- *
- * (fileLength - headerSize) / (sectorsPerTrack * ((128 <<
- * sectorSizeCode) + 1) ) / sideCount
- *
- * If the length of the header is to short to contain the geometry desired,
- * then the default values are assumed. If the header length is zero the all
- * of the geometry is assumed. When creating disk images it is desirable to
- * make the header length as short as possible. The header should only be
- * used to deviate from the default values.
- *
- * The sector data begins immediately after the header. If the header length
- * is zero then the sector data is at the beginning file.
- *
- * C. Sectors per track
- * This is the number of sectors per track (ones based). A value of 18
- * means there are 18 sectors per track
- *
- * D. Side Count
- * This is the number of sides in the disk image. Values of 1 or 2 are
- * acceptable. If there are two sides then the tracks are interleaved.
- * The first track in the image file is track zero side 1, the second
- * track in the image file is track zero side 2.
- *
- * E. Sector size
- * The is the same value that is stored in the wd179x ID field to
- * determine sector size:
- *
- * 0x00 128 bytes
- * 0x01 256 bytes
- * 0x02 512 bytes
- * 0x03 1024 bytes
- *
- * Other values are undefined. Every sector in the disk image must be the
- * same size.
- *
- * F. First sector ID
- * This determines the first sector ID for each track. Each successive
- * sector adds one to the previous ID. If the first sector ID is 1, then
- * the second sector has an ID of 2, and the third has an ID of 3.
- *
- * G. Sector Attribute Flag
- * If this byte is non zero, then each sector contains an additional
- * byte prepended to the sector data. If the attribute flag is zero then
- * there are no extra bytes in front of the sector data.
- *
- * H. Sector attribute byte
- * This byte is put at the beginning of every sector if the header flag
- * is turned on. The information this byte contains is the same as the
- * status register (of the wd179x) would contain when a 'Read Sector'
- * command was issued. The bit fields are defined as:
- *
- * Bit position:
- * ---------------
- * 7 6 5 4 3 2 1 0
- * | | | | | | | |
- * | | | | | | | +--- Not used. Set to zero.
- * | | | | | | +----- Not used. Set to zero.
- * | | | | | +------- Not used. Set to zero.
- * | | | | +--------- Set on CRC error.
- * | | | +----------- Set if sector not found.
- * | | +------------- Record type: 1 - Deleted Data Mark, 0 - Data Mark.
- * | +--------------- Not Used. Set to zero.
- * +----------------- Not Used. Set to zero.
- *
- * ----------------------------------------------------------------------- */
-
-static int coco_jvc_decode_header(floppy_image_legacy *floppy, UINT64 size,
- struct basicdsk_geometry *geometry)
-{
- UINT8 header[256];
- UINT8 sector_attribute_flag;
- UINT16 physical_bytes_per_sector;
- UINT32 header_size, file_size;
- struct basicdsk_geometry dummy_geometry;
-
- if (geometry)
- memset(geometry, 0, sizeof(*geometry));
- else
- geometry = &dummy_geometry;
-
- if (size > 0xFFFFFFFF)
- return -1;
- file_size = (UINT32) size;
-
- /* read the header */
- header_size = (UINT32) file_size % 0x100;
- floppy_image_read(floppy, header, 0, header_size);
- geometry->offset = header_size;
-
- /* byte offset 0 - sectors per track */
- geometry->sectors = (header_size > 0) ? header[0] : 18;
- if (geometry->sectors <= 0)
- return -1;
-
- /* byte offset 1 - side count */
- geometry->heads = (header_size > 1) ? header[1] : 1;
- if (geometry->heads <= 0)
- return -1;
-
- /* byte offset 2 - sector size code */
- geometry->sector_length = 128 << ((header_size > 2) ? header[2] : 1);
- if (geometry->sector_length <= 0)
- return -1;
-
- /* byte offset 3 - first sector ID */
- geometry->first_sector_id = (header_size > 3) ? header[3] : 1;
-
- /* byte offset 4 - sector attribute flag */
- sector_attribute_flag = (header_size > 4) ? header[4] : 0;
- if (sector_attribute_flag != 0)
- return -1; /* we do not support sector attribute flags */
-
- physical_bytes_per_sector = geometry->sector_length;
- if (sector_attribute_flag)
- physical_bytes_per_sector++;
-
- geometry->tracks = (file_size - header_size) / geometry->sectors / geometry->heads / physical_bytes_per_sector;
-
- /* do we have an oddball size? reject this file if not */
- if ((file_size - header_size) % physical_bytes_per_sector)
- return -1;
-
- /* minimum of 35 tracks; support degenerate JVC files */
- if (geometry->tracks < 35)
- geometry->tracks = 35;
-
- return 0;
-}
-
-
-
-static FLOPPY_IDENTIFY(coco_jvc_identify)
-{
- UINT64 size;
- size = floppy_image_size(floppy);
- *vote = coco_jvc_decode_header(floppy, size, NULL) ? 0 : 100;
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static FLOPPY_CONSTRUCT(coco_jvc_construct)
-{
- struct basicdsk_geometry geometry;
- UINT8 header[5];
- size_t header_size;
-
- if (params)
- {
- /* create */
- memset(&geometry, 0, sizeof(geometry));
- geometry.heads = option_resolution_lookup_int(params, PARAM_HEADS);
- geometry.tracks = option_resolution_lookup_int(params, PARAM_TRACKS);
- geometry.sectors = option_resolution_lookup_int(params, PARAM_SECTORS);
- geometry.first_sector_id = option_resolution_lookup_int(params, PARAM_FIRST_SECTOR_ID);
- geometry.sector_length = option_resolution_lookup_int(params, PARAM_SECTOR_LENGTH);
-
- header[0] = (UINT8) geometry.sectors;
- header[1] = (UINT8) geometry.heads;
- header[2] = (UINT8) compute_log2(geometry.sector_length) - 7;
- header[3] = (UINT8) geometry.first_sector_id;
- header[4] = 0;
-
- /* now that we have the header computed, figure out the header size */
- header_size = 0;
- if (header[0] != 18)
- header_size = 1;
- if (header[1] != 1)
- header_size = 2;
- if (header[2] != 1)
- header_size = 3;
- if (header[3] != 1)
- header_size = 4;
- if (header[4] != 0)
- header_size = 5;
-
- geometry.offset = header_size;
-
- floppy_image_write(floppy, header, 0, header_size);
- }
- else
- {
- /* load */
- if (coco_jvc_decode_header(floppy, floppy_image_size(floppy), &geometry))
- return FLOPPY_ERROR_INVALIDIMAGE;
- }
- return basicdsk_construct(floppy, &geometry);
-}
-
-
-/* -----------------------------------------------------------------------
- * OS-9 file format
- *
- * This file format is largely a hack because there are a large amount of
- * disk images that do not have geometry image separate from the disk image
- * itself. So we support OS-9 images with are simply basic disks whose
- * geometry is determined by the disk image.
- *
- * OS-9 images identified by an LSN; which are simply blocks of 256 bytes
- *
- * LSN0
- * Byte size use
- * $00 3 sectors on disk
- * $03 1 track size in sectors
- * $04 2 bytes in allocation bit map; typically 1bit/sector so for
- * 35 tracks of 18 sectors each that's $4E (single sided disk)
- * 40 tracks per side, 18 sectors each = $B4
- * $06 2 sectors per bit in allocation map; normally 1
- * $08 3 LSN of root directory; normally 2 but depends on size of
- * $04 value
- * $0B 2 owner's user number; normally 0
- * $0D 1 disk attributes; normally $FF
- * $0E 2 psuedo random number for identification
- * $10 1 disk format; typical is 3
- * %00000001 0=single side 1=double side
- * %00000010 0=single density (non Coco) 1=double density
- * %00000100 0=48tracks/inch 1=96tracks/inch
- * $11 2 sectors per track; normal is $12 skip several not needed
- * for Format
- * $1A 5 date of creation Y:M:D:H:M
- * $1F 32 ASCII name of disk, last letter has $80 added to it,
- * the full 32 bytes do not need to be used.
- *
- * Allocation bit map, fill with zeros and set bits from low to high as
- * sectors are used. So, for a fresh disk sectors LSN0,LSN1,LSN2, and LSN3
- * will be in use so the first byte will be $FF $C0 and all others
- * in the map are $00
- *
- * Root directory LSN2
- * Byte size use
- * $00 1 attributes will be $BF
- * $01 2 owners ID will be $0000
- * $03 5 date last modified will be creation date Y:M:D:H:M
- * $08 1 link count; set to $02
- * $09 4 file size in bytes, set to $40
- * $0D 3 date created Y:M:D
- * $10 3 block LSN set to current sector number+1 ie $03 in this case
- * $13 2 size in sectors of directory block, set to $07
- * All other bytes in sector set to $00
- * LSN3 first sector of directory with names
- * Fill sector with all $00 and then set listed bytes
- * $00 2 value $2EAE which is .. with last byte+$80
- * $1F 1 value $02 LSN for start of this directory as there is
- * none higher in tree
- * $20 1 value $AE which is . with $80 added
- * $3F 1 value $02 LSN for start of this directory
- * ----------------------------------------------------------------------- */
-
-static floperr_t coco_os9_readheader(floppy_image_legacy *floppy, struct basicdsk_geometry *geometry)
-{
- UINT8 header[0x20];
- int total_sectors;
-
- floppy_image_read(floppy, header, 0, sizeof(header));
-
- total_sectors = (header[0x00] << 16) | (header[0x01] << 8) | header[0x02];
-
- memset(geometry, 0, sizeof(*geometry));
- geometry->first_sector_id = 1;
- geometry->sector_length = 256;
- geometry->sectors = (header[0x11] << 8) + header[0x12];
- geometry->heads = (header[0x10] & 0x01) ? 2 : 1;
-
- if (!geometry->sectors)
- return FLOPPY_ERROR_INVALIDIMAGE;
-
- geometry->tracks = total_sectors / geometry->sectors / geometry->heads;
-
- if (total_sectors != geometry->tracks * geometry->sectors * geometry->heads)
- return FLOPPY_ERROR_INVALIDIMAGE;
-
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static floperr_t coco_os9_post_format(floppy_image_legacy *floppy, option_resolution *params)
-{
- UINT8 header[0x0400];
- floperr_t err;
- time_t t;
- struct tm *ltime;
- int heads, tracks, sectors, total_sectors;
-
- heads = option_resolution_lookup_int(params, PARAM_HEADS);
- tracks = option_resolution_lookup_int(params, PARAM_TRACKS);
- sectors = option_resolution_lookup_int(params, PARAM_SECTORS);
- total_sectors = heads * tracks * sectors;
-
- /* write the initial header */
- time(&t);
- ltime = localtime(&t);
-
- memset(&header, 0, sizeof(header));
- header[0x0000] = (UINT8) (total_sectors >> 16);
- header[0x0001] = (UINT8) (total_sectors >> 8);
- header[0x0002] = (UINT8) (total_sectors >> 0);
- header[0x0003] = (UINT8) sectors;
- header[0x0004] = (UINT8) (((total_sectors + 7) / 8) >> 8);
- header[0x0005] = (UINT8) (((total_sectors + 7) / 8) >> 0);
- header[0x0006] = 0x00;
- header[0x0007] = 0x01;
- header[0x0008] = 0x00;
- header[0x0009] = 0x00;
- header[0x000a] = 0x02;
- header[0x000b] = 0x00;
- header[0x000c] = 0x00;
- header[0x000d] = 0xff;
- header[0x000e] = floppy_random_byte(floppy);
- header[0x000f] = floppy_random_byte(floppy);
- header[0x0010] = (heads == 2) ? 3 : 2;
- header[0x0011] = (UINT8) (sectors >> 8);
- header[0x0012] = (UINT8) (sectors >> 0);
- header[0x001A] = (UINT8) ltime->tm_year;
- header[0x001B] = (UINT8) ltime->tm_mon + 1;
- header[0x001C] = (UINT8) ltime->tm_mday;
- header[0x001D] = (UINT8) ltime->tm_hour;
- header[0x001E] = (UINT8) ltime->tm_min;
- header[0x001F] = 0xA0;
- header[0x0100] = 0xFF;
- header[0x0101] = 0xC0;
- header[0x0200] = 0xBF;
- header[0x0201] = 0x00;
- header[0x0202] = 0x00;
- header[0x0203] = (UINT8) ltime->tm_year;
- header[0x0204] = (UINT8) ltime->tm_mon + 1;
- header[0x0205] = (UINT8) ltime->tm_mday;
- header[0x0206] = (UINT8) ltime->tm_hour;
- header[0x0207] = (UINT8) ltime->tm_min;
- header[0x0208] = 0x02;
- header[0x0209] = 0x00;
- header[0x020A] = 0x00;
- header[0x020B] = 0x00;
- header[0x020C] = 0x40;
- header[0x020D] = (UINT8) (ltime->tm_year % 100);
- header[0x020E] = (UINT8) ltime->tm_mon;
- header[0x020F] = (UINT8) ltime->tm_mday;
- header[0x0210] = 0x00;
- header[0x0211] = 0x00;
- header[0x0212] = 0x03;
- header[0x0213] = 0x00;
- header[0x0214] = 0x07;
- header[0x0300] = 0x2E;
- header[0x0301] = 0xAE;
- header[0x031F] = 0x02;
- header[0x0320] = 0xAE;
- header[0x033F] = 0x02;
-
- if (total_sectors % 8)
- header[0x0100 + (total_sectors / 8)] = 0xFF >> (total_sectors % 8);
-
- err = floppy_write_sector(floppy, 0, 0, 1, 0, &header[0x0000], 256, 0);
- if (err)
- return err;
-
- err = floppy_write_sector(floppy, 0, 0, 2, 0, &header[0x0100], 256, 0);
- if (err)
- return err;
-
- err = floppy_write_sector(floppy, 0, 0, 3, 0, &header[0x0200], 256, 0);
- if (err)
- return err;
-
- err = floppy_write_sector(floppy, 0, 0, 4, 0, &header[0x0300], 256, 0);
- if (err)
- return err;
-
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static FLOPPY_IDENTIFY(coco_os9_identify)
-{
- struct basicdsk_geometry geometry;
- *vote = coco_os9_readheader(floppy, &geometry) ? 0 : 100;
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static FLOPPY_CONSTRUCT(coco_os9_construct)
-{
- floperr_t err;
- struct basicdsk_geometry geometry;
-
- if (params)
- {
- /* create */
- memset(&geometry, 0, sizeof(geometry));
- geometry.heads = option_resolution_lookup_int(params, PARAM_HEADS);
- geometry.tracks = option_resolution_lookup_int(params, PARAM_TRACKS);
- geometry.sectors = option_resolution_lookup_int(params, PARAM_SECTORS);
- geometry.first_sector_id = option_resolution_lookup_int(params, PARAM_FIRST_SECTOR_ID);
- geometry.sector_length = option_resolution_lookup_int(params, PARAM_SECTOR_LENGTH);
- }
- else
- {
- /* open */
- err = coco_os9_readheader(floppy, &geometry);
- if (err)
- return err;
- }
-
- /* actually construct the image */
- err = basicdsk_construct(floppy, &geometry);
- floppy_callbacks(floppy)->post_format = coco_os9_post_format;
- return err;
-}
-
-
-
-/* -----------------------------------------------------------------------
- * VDK file format
- *
- * Used by Paul Burgin's PC-Dragon emulator
- *
- * Offset Bytes Field Description
- * ------ ----- ------------ -----------
- * 0 1 magic1 Signature byte 1 ('d')
- * 1 1 magic2 Signature byte 2 ('k')
- * 2 2 header_len Total header length (little endian)
- * 4 1 ver_actual Version of the VDK format (0x10)
- * 5 1 ver_compat Backwards compatibility version (0x10)
- * 6 1 source_id Identify of the file source
- * 7 1 source_ver Version of the file source
- * 8 1 tracks Number of tracks
- * 9 1 sides Number of sides (1-2)
- * 10 1 flags Various flags
- * bit 0: Write protect
- * bit 1: A Lock
- * bit 2: F Lock
- * bit 3: Disk set
- * 11 1 compression Compression flags (bits 0-2) and name length
- * ----------------------------------------------------------------------- */
-
-
-
-static int coco_vdk_decode_header(floppy_image_legacy *floppy, struct basicdsk_geometry *geometry)
-{
- UINT8 header[12];
- UINT8 heads, tracks, sectors;
- UINT16 sector_length, offset;
- UINT64 size;
-
- size = floppy_image_size(floppy);
-
- floppy_image_read(floppy, header, 0, sizeof(header));
-
- if (header[0] != 'd')
- return -1;
- if (header[1] != 'k')
- return -1;
- if (header[5] != 0x10)
- return -1;
- if (header[11] & 0x07)
- return -1;
-
- heads = header[9];
- tracks = header[8];
- sectors = 18;
- sector_length = 0x100;
-
- offset = header[3] * 0x100 + header[2];
-
- if (size != ((UINT32) heads * tracks * sectors * sector_length + offset))
- return -1;
-
- if (geometry)
- {
- memset(geometry, 0, sizeof(*geometry));
- geometry->heads = heads;
- geometry->tracks = tracks;
- geometry->sectors = sectors;
- geometry->first_sector_id = 1;
- geometry->sector_length = sector_length;
- geometry->offset = offset;
- }
- return 0;
-}
-
-
-
-static FLOPPY_IDENTIFY(coco_vdk_identify)
-{
- *vote = coco_vdk_decode_header(floppy, NULL) ? 0 : 100;
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static FLOPPY_CONSTRUCT(coco_vdk_construct)
-{
- struct basicdsk_geometry geometry;
- UINT8 header[12];
-
- if (params)
- {
- /* create */
- memset(&geometry, 0, sizeof(geometry));
- geometry.heads = option_resolution_lookup_int(params, PARAM_HEADS);
- geometry.tracks = option_resolution_lookup_int(params, PARAM_TRACKS);
- geometry.sectors = 18;
- geometry.first_sector_id = 1;
- geometry.sector_length = 256;
- geometry.offset = sizeof(header);
-
- memset(&header, 0, sizeof(header));
- header[0] = 'd';
- header[1] = 'k';
- header[2] = (UINT8) (sizeof(header) >> 0);
- header[3] = (UINT8) (sizeof(header) >> 8);
- header[4] = 0x10;
- header[5] = 0x10;
- header[8] = (UINT8) geometry.tracks;
- header[9] = (UINT8) geometry.heads;
-
- floppy_image_write(floppy, header, 0, sizeof(header));
- }
- else
- {
- /* load */
- if (coco_vdk_decode_header(floppy, &geometry))
- return FLOPPY_ERROR_INVALIDIMAGE;
- }
- return basicdsk_construct(floppy, &geometry);
-}
-
-
-
-/* -----------------------------------------------------------------------
- * DMK file format
- *
- * David M. Keil's disk image format is aptly called an 'on disk' image
- * format. This means that whatever written to the disk is enocded into
- * the image file. IDAMS, sector headers, traling CRCs, and intra sector
- * spacing. *
- *
- * HEADER DESCRIPTION:
- *
- * Offset Bytes Field Description
- * ------ ----- ------------ -----------
- * 0 1 write_prot 0xff = Writed Protected, 0x00 = R/W
- * 1 1 tracks Number of tracks
- * 2 2 track_length Bytes per track (little endian)
- * 4 1 disk_options Miscellaneous flags
- * bit 0-3: Unused
- * bit 4: 1=single sided 0=dbl
- * bit 5: Unused
- * bit 6: Single density?
- * bit 6: Ignore density flags?
- * 5 7 reserved Reserved for future use
- * 12 4 real_disk_code If this is 0x12345678 (little endian)
- * then access a real disk drive
- * (unsupported)
- *
- * Each track begins with a track TOC, consisting of 64 little endian 16-bit
- * integers. Each integer has the following format:
- * bit 0-13: Offset from beginning of track to 'FE' byte of IDAM
- * Note these are always sorted from first to last. All empty
- * entries are 0x00
- * bit 14: Undefined (reserved)
- * bit 15: Sector double density (0=SD 1=DD)
- * ----------------------------------------------------------------------- */
-
-struct dmk_tag
-{
- int heads;
- int tracks;
- UINT32 track_size;
-};
-
-#define DMK_HEADER_LEN 16
-#define DMK_TOC_LEN 64
-#define DMK_IDAM_LENGTH 7
-#define DMK_DATA_GAP 80
-#define DMK_LEAD_IN 32
-#define DMK_EXTRA_TRACK_LENGTH 156
-
-#define dmk_idam_type(x) (x)[0]
-#define dmk_idam_track(x) (x)[1]
-#define dmk_idam_side(x) (x)[2]
-#define dmk_idam_sector(x) (x)[3]
-#define dmk_idam_sectorlength(x) (x)[4]
-#define dmk_idam_crc(x) (((x)[5] << 8) + (x)[6])
-#define dmk_idam_set_crc(x, crc) (x)[5] = ((crc) >> 8); (x)[6] = ((crc) >> 0);
-
-
-static struct dmk_tag *get_dmk_tag(floppy_image_legacy *floppy)
-{
- return (dmk_tag *)floppy_tag(floppy);
-}
-
-
-static floperr_t coco_dmk_get_offset(floppy_image_legacy *floppy, int head, int track, UINT64 *offset)
-{
- struct dmk_tag *tag = get_dmk_tag(floppy);
-
- if ((head < 0) || (head >= tag->heads) || (track < 0) || (track >= tag->tracks))
- return FLOPPY_ERROR_SEEKERROR;
-
- *offset = track;
- *offset *= tag->heads;
- *offset += head;
- *offset *= tag->track_size;
- *offset += DMK_HEADER_LEN;
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static UINT32 coco_dmk_min_track_size(int sectors, int sector_length)
-{
- int sector_physical_length;
- sector_physical_length = 8 + 3 + DMK_IDAM_LENGTH + 22 + 12 + 3 + 1 + sector_length + 2 + 24;
- return DMK_TOC_LEN * 2 + DMK_LEAD_IN + (sectors * sector_physical_length);
-}
-
-
-
-static floperr_t coco_dmk_read_track(floppy_image_legacy *floppy, int head, int track, UINT64 offset, void *buffer, size_t buflen)
-{
- floperr_t err;
- UINT64 track_offset;
-
- err = coco_dmk_get_offset(floppy, head, track, &track_offset);
- if (err)
- return err;
-
- floppy_image_read(floppy, buffer, offset + track_offset, buflen);
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static floperr_t coco_dmk_write_track(floppy_image_legacy *floppy, int head, int track, UINT64 offset, const void *buffer, size_t buflen)
-{
- floperr_t err;
- UINT64 track_offset;
-
- err = coco_dmk_get_offset(floppy, head, track, &track_offset);
- if (err)
- return err;
-
- floppy_image_write(floppy, buffer, offset + track_offset, buflen);
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static floperr_t coco_dmk_get_track_data_offset(floppy_image_legacy *floppy, int head, int track, UINT64 *offset)
-{
- *offset = DMK_TOC_LEN + 1;
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static floperr_t coco_dmk_format_track(floppy_image_legacy *floppy, int head, int track, option_resolution *params)
-{
- int sectors;
- int sector_length;
- int interleave;
- int first_sector_id;
- floperr_t err;
- int physical_sector;
- int logical_sector;
- int track_position;
- UINT16 idam_offset;
- UINT16 crc;
- UINT8 *track_data;
- void *track_data_v;
- UINT32 max_track_size;
- std::vector<int> sector_map;
-
- sectors = option_resolution_lookup_int(params, PARAM_SECTORS);
- sector_length = option_resolution_lookup_int(params, PARAM_SECTOR_LENGTH);
- interleave = option_resolution_lookup_int(params, PARAM_INTERLEAVE);
- first_sector_id = option_resolution_lookup_int(params, PARAM_FIRST_SECTOR_ID);
-
- max_track_size = get_dmk_tag(floppy)->track_size;
-
- if (sectors > DMK_TOC_LEN)
- {
- err = FLOPPY_ERROR_INTERNAL;
- goto done;
- }
-
- if (max_track_size < coco_dmk_min_track_size(sectors, sector_length))
- {
- err = FLOPPY_ERROR_NOSPACE;
- goto done;
- }
-
- err = floppy_load_track(floppy, head, track, TRUE, &track_data_v, NULL);
- if (err)
- goto done;
- track_data = (UINT8 *) track_data_v;
-
- /* set up sector map */
- memset(&sector_map[0], 0xff, sectors*sizeof(int));
-
- physical_sector = 0;
- for (logical_sector = 0; logical_sector < sectors; logical_sector++)
- {
- while(sector_map[physical_sector] >= 0)
- {
- physical_sector++;
- physical_sector %= sectors;
- }
-
- sector_map[physical_sector] = logical_sector + first_sector_id;
- physical_sector += interleave + 1;
- physical_sector %= sectors;
- }
-
- /* set up track table of contents */
- physical_sector = 0;
- track_position = DMK_TOC_LEN * 2 + DMK_LEAD_IN;
- while(physical_sector < DMK_TOC_LEN)
- {
- if (physical_sector >= sectors)
- {
- /* no more sectors */
- idam_offset = 0;
- }
- else
- {
- /* this is a sector */
- logical_sector = sector_map[physical_sector];
-
- /* write the sector */
- memset(&track_data[track_position], 0x00, 8);
- track_position += 8;
-
- memset(&track_data[track_position], 0xA1, 3);
- track_position += 3;
-
- idam_offset = track_position | 0x8000;
- dmk_idam_type( &track_data[track_position]) = 0xFE;
- dmk_idam_track( &track_data[track_position]) = track;
- dmk_idam_side( &track_data[track_position]) = head;
- dmk_idam_sector( &track_data[track_position]) = logical_sector;
- dmk_idam_sectorlength( &track_data[track_position]) = compute_log2(sector_length / 128);
- crc = ccitt_crc16(0xcdb4, &track_data[track_position], DMK_IDAM_LENGTH - 2);
- dmk_idam_set_crc( &track_data[track_position], crc);
- track_position += DMK_IDAM_LENGTH;
-
- memset(&track_data[track_position], 0x4E, 22);
- track_position += 22;
-
- memset(&track_data[track_position], 0x00, 12);
- track_position += 12;
-
- memset(&track_data[track_position], 0xA1, 3);
- track_position += 3;
-
- /* write sector body */
- track_data[track_position] = 0xFB;
- memset(&track_data[track_position + 1], floppy_get_filler(floppy), sector_length);
- crc = ccitt_crc16(0xcdb4, &track_data[track_position], sector_length + 1);
- track_data[track_position + sector_length + 1] = (UINT8) (crc >> 8);
- track_data[track_position + sector_length + 2] = (UINT8) (crc >> 0);
- track_position += sector_length + 3;
-
- /* write sector footer */
- memset(&track_data[track_position], 0x4E, 24);
- track_position += 24;
- }
-
- /* write the TOC entry */
- track_data[physical_sector * 2 + 0] = (UINT8) (idam_offset >> 0);
- track_data[physical_sector * 2 + 1] = (UINT8) (idam_offset >> 8);
-
- physical_sector++;
- }
-
- /* write track lead in */
- memset(&track_data[physical_sector * 2], 0x4e, DMK_LEAD_IN);
-
- /* write track footer */
- assert(max_track_size >= (UINT32)track_position);
- memset(&track_data[track_position], 0x4e, max_track_size - track_position);
-
-done:
- return err;
-}
-
-
-
-static int coco_dmk_get_heads_per_disk(floppy_image_legacy *floppy)
-{
- return get_dmk_tag(floppy)->heads;
-}
-
-
-
-static int coco_dmk_get_tracks_per_disk(floppy_image_legacy *floppy)
-{
- return get_dmk_tag(floppy)->tracks;
-}
-
-
-
-static UINT32 coco_dmk_get_track_size(floppy_image_legacy *floppy, int head, int track)
-{
- return get_dmk_tag(floppy)->track_size;
-}
-
-
-
-static floperr_t coco_dmk_seek_sector_in_track(floppy_image_legacy *floppy, int head, int track, int sector, int sector_is_index, int dirtify, UINT8 **sector_data, UINT32 *sector_length)
-{
- struct dmk_tag *tag = get_dmk_tag(floppy);
- floperr_t err;
- UINT32 idam_offset = 0;
- UINT16 calculated_crc;
- size_t i;
- size_t offs;
- int state;
- UINT8 *track_data;
- void *track_data_v;
- size_t track_length;
- size_t sec_len;
-
- err = floppy_load_track(floppy, head, track, dirtify, &track_data_v, &track_length);
- if (err)
- return err;
- track_data = (UINT8 *) track_data_v;
-
- /* search for matching IDAM */
- for (i = 0; i < DMK_TOC_LEN; i++)
- {
- idam_offset = track_data[i * 2 + 1];
- idam_offset <<= 8;
- idam_offset |= track_data[i * 2 + 0];
- idam_offset &= 0x3FFF;
-
- if (idam_offset == 0)
- {
- /* we've reached the end of the road */
- i = DMK_TOC_LEN;
- break;
- }
-
- if ((idam_offset + DMK_IDAM_LENGTH) >= tag->track_size)
- continue;
-
- calculated_crc = ccitt_crc16(0xCDB4, &track_data[idam_offset], DMK_IDAM_LENGTH - 2);
-
- if (calculated_crc == dmk_idam_crc(&track_data[idam_offset]))
- {
- if (sector_is_index)
- {
- /* the sector is indexed; decrement the index and go */
- if (sector-- == 0)
- break;
- }
- else
- {
- /* check IDAM integrity and check for matching sector */
- if (sector == dmk_idam_sector(&track_data[idam_offset])
-/* && (track == dmk_idam_track(&track_data[idam_offset])) */
-/* && (head == dmk_idam_side(&track_data[idam_offset])) */
- )
- break;
- }
- }
- }
-
- if (i >= DMK_TOC_LEN)
- return FLOPPY_ERROR_SEEKERROR;
-
- /* we found a matching sector ID */
- state = 0;
- offs = idam_offset + DMK_IDAM_LENGTH;
-
- /* find pattern 0xA1A1FB; this represents the start of a data sector */
- for (i = 0; i < DMK_DATA_GAP; i++)
- {
- /* overflowing the track? */
- if ((i + offs) >= tag->track_size)
- return FLOPPY_ERROR_SEEKERROR;
-
- if (track_data[offs + i] == 0xA1)
- state++;
- else if ((track_data[offs + i] == 0xFB) && state)
- break;
- else
- state = 0;
- }
- if (i >= DMK_DATA_GAP)
- return FLOPPY_ERROR_SEEKERROR;
-
- offs += i + 1;
- sec_len = 128 << dmk_idam_sectorlength(&track_data[idam_offset]);
-
- if ((offs + sec_len) > track_length)
- return FLOPPY_ERROR_INVALIDIMAGE;
-
- if (sector_data)
- *sector_data = track_data + offs;
- if (sector_length)
- *sector_length = sec_len;
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static floperr_t coco_dmk_get_sector_length(floppy_image_legacy *floppy, int head, int track, int sector, UINT32 *sector_length)
-{
- return coco_dmk_seek_sector_in_track(floppy, head, track, sector, FALSE, FALSE, NULL, sector_length);
-}
-
-
-
-static floperr_t coco_dmk_get_indexed_sector_info(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, UINT32 *sector_length, unsigned long *flags)
-{
- floperr_t err;
- UINT32 idam_offset;
- const UINT8 *track_data;
- void *track_data_v;
-
- if (sector_index*2 >= DMK_TOC_LEN)
- return FLOPPY_ERROR_SEEKERROR;
-
- err = floppy_load_track(floppy, head, track, FALSE, &track_data_v, NULL);
- if (err)
- return err;
- track_data = (UINT8 *) track_data_v;
-
- idam_offset = track_data[sector_index * 2 + 1];
- idam_offset <<= 8;
- idam_offset |= track_data[sector_index * 2 + 0];
- idam_offset &= 0x3FFF;
-
- if (idam_offset == 0)
- return FLOPPY_ERROR_SEEKERROR;
-
- if (cylinder)
- *cylinder = dmk_idam_track(&track_data[idam_offset]);
- if (side)
- *side = dmk_idam_side(&track_data[idam_offset]);
- if (sector)
- *sector = dmk_idam_sector(&track_data[idam_offset]);
- if (sector_length)
- *sector_length = 128 << dmk_idam_sectorlength(&track_data[idam_offset]);
- if (flags)
- /* TODO: read DAM or DDAM and determine flags */
- *flags = 0;
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static floperr_t internal_coco_dmk_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, int sector_is_index, void *buffer, size_t buflen)
-{
- floperr_t err;
- UINT32 sector_length;
- UINT16 crc_on_disk;
- UINT16 calculated_crc;
- UINT8 *sector_data;
-
- err = coco_dmk_seek_sector_in_track(floppy, head, track, sector, sector_is_index, FALSE, &sector_data, &sector_length);
- if (err)
- return err;
-
- crc_on_disk = sector_data[sector_length + 0];
- crc_on_disk <<= 8;
- crc_on_disk += sector_data[sector_length + 1];
-
- calculated_crc = ccitt_crc16(0xE295, sector_data, sector_length);
- if (calculated_crc != crc_on_disk)
- return FLOPPY_ERROR_INVALIDIMAGE;
-
- memcpy(buffer, sector_data, MIN(sector_length, buflen));
-
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static floperr_t internal_coco_dmk_write_sector(floppy_image_legacy *floppy, int head, int track, int sector, int sector_is_index, const void *buffer, size_t buflen, int ddam)
-{
- floperr_t err;
- UINT32 sector_length;
- UINT8 *sector_data;
- UINT16 crc;
-
- err = coco_dmk_seek_sector_in_track(floppy, head, track, sector, sector_is_index, TRUE, &sector_data, &sector_length);
- if (err)
- return err;
-
- if (buflen > sector_length)
- return FLOPPY_ERROR_INTERNAL;
-
- memcpy(sector_data, buffer, buflen);
-
- crc = ccitt_crc16(0xE295, sector_data, sector_length);
- sector_data[sector_length + 0] = crc >> 8;
- sector_data[sector_length + 1] = crc >> 0;
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static floperr_t coco_dmk_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen)
-{
- return internal_coco_dmk_read_sector(floppy, head, track, sector, FALSE, buffer, buflen);
-}
-
-static floperr_t coco_dmk_write_sector(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam)
-{
- return internal_coco_dmk_write_sector(floppy, head, track, sector, FALSE, buffer, buflen, ddam);
-}
-
-static floperr_t coco_dmk_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen)
-{
- return internal_coco_dmk_read_sector(floppy, head, track, sector, TRUE, buffer, buflen);
-}
-
-static floperr_t coco_dmk_write_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam)
-{
- return internal_coco_dmk_write_sector(floppy, head, track, sector, TRUE, buffer, buflen, ddam);
-}
-
-
-
-static void coco_dmk_interpret_header(floppy_image_legacy *floppy, int *heads, int *tracks, int *track_size)
-{
- UINT8 header[DMK_HEADER_LEN];
-
- floppy_image_read(floppy, header, 0, DMK_HEADER_LEN);
-
- if (tracks)
- *tracks = header[1];
- if (heads)
- *heads = (header[4] & 0x10) ? 1 : 2;
- if (track_size)
- *track_size = ((int) header[3]) * 0x100 + header[2];
-}
-
-
-
-FLOPPY_CONSTRUCT(coco_dmk_construct)
-{
- struct FloppyCallbacks *callbacks;
- struct dmk_tag *tag;
- UINT8 header[DMK_HEADER_LEN];
- int heads, tracks, track_size, sectors, sector_length;
-
- if (params)
- {
- heads = option_resolution_lookup_int(params, PARAM_HEADS);
- tracks = option_resolution_lookup_int(params, PARAM_TRACKS);
- sectors = option_resolution_lookup_int(params, PARAM_SECTORS);
- sector_length = option_resolution_lookup_int(params, PARAM_SECTOR_LENGTH);
-
- track_size = coco_dmk_min_track_size(sectors, sector_length) + DMK_EXTRA_TRACK_LENGTH;
-
- memset(header, 0, sizeof(header));
- header[1] = tracks;
- header[2] = track_size >> 0;
- header[3] = track_size >> 8;
- header[4] = (heads == 2) ? 0x00 : 0x10;
-
- floppy_image_write(floppy, header, 0, sizeof(header));
- }
- else
- {
- coco_dmk_interpret_header(floppy, &heads, &tracks, &track_size);
- }
-
- tag = (dmk_tag *)floppy_create_tag(floppy, sizeof(struct dmk_tag));
- if (!tag)
- return FLOPPY_ERROR_OUTOFMEMORY;
- tag->heads = heads;
- tag->track_size = track_size;
- tag->tracks = tracks;
-
- callbacks = floppy_callbacks(floppy);
- callbacks->read_track = coco_dmk_read_track;
- callbacks->write_track = coco_dmk_write_track;
- callbacks->get_track_data_offset = coco_dmk_get_track_data_offset;
- callbacks->format_track = coco_dmk_format_track;
- callbacks->get_heads_per_disk = coco_dmk_get_heads_per_disk;
- callbacks->get_tracks_per_disk = coco_dmk_get_tracks_per_disk;
- callbacks->get_track_size = coco_dmk_get_track_size;
- callbacks->get_sector_length = coco_dmk_get_sector_length;
- callbacks->get_indexed_sector_info = coco_dmk_get_indexed_sector_info;
- callbacks->read_sector = coco_dmk_read_sector;
- callbacks->write_sector = coco_dmk_write_sector;
- callbacks->read_indexed_sector = coco_dmk_read_indexed_sector;
- callbacks->write_indexed_sector = coco_dmk_write_indexed_sector;
-
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-FLOPPY_IDENTIFY(coco_dmk_identify)
-{
- int heads, tracks, track_size;
- UINT64 size, expected_size;
-
- size = floppy_image_size(floppy);
- coco_dmk_interpret_header(floppy, &heads, &tracks, &track_size);
- expected_size = DMK_HEADER_LEN + (heads * tracks * track_size);
- *vote = (size == expected_size) ? 100 : 0;
- return FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-LEGACY_FLOPPY_OPTIONS_START( coco )
- LEGACY_FLOPPY_OPTION( coco_jvc, "dsk", "CoCo JVC disk image", coco_jvc_identify, coco_jvc_construct, NULL,
- HEADS([1]-2)
- TRACKS([35]-255)
- SECTORS(1-[18]-255)
- SECTOR_LENGTH(128/[256]/512/1024)
- FIRST_SECTOR_ID(0-[1]))
- LEGACY_FLOPPY_OPTION( coco_os9, "os9", "CoCo OS-9 disk image", coco_os9_identify, coco_os9_construct, NULL,
- HEADS([1]-2)
- TRACKS([35]-255)
- SECTORS(1-[18]-255)
- SECTOR_LENGTH([256])
- FIRST_SECTOR_ID([1]))
- LEGACY_FLOPPY_OPTION( coco_vdk, "vdk", "CoCo VDK disk image", coco_vdk_identify, coco_vdk_construct, NULL,
- HEADS([1]-2)
- TRACKS([35]-255)
- SECTORS([18])
- SECTOR_LENGTH([256])
- FIRST_SECTOR_ID([1]))
- LEGACY_FLOPPY_OPTION( coco_dmk, "dsk,dmk", "CoCo DMK disk image", coco_dmk_identify, coco_dmk_construct, NULL,
- HEADS([1]-2)
- TRACKS([35]-255)
- SECTORS(1-[18])
- SECTOR_LENGTH(128/[256]/512/1024/2048/4096/8192)
- INTERLEAVE(0-[6]-17)
- FIRST_SECTOR_ID(0-[1]))
-LEGACY_FLOPPY_OPTIONS_END
diff --git a/src/mess/tools/imgtool/formats/coco_dsk.h b/src/mess/tools/imgtool/formats/coco_dsk.h
deleted file mode 100644
index 797911d40a1..00000000000
--- a/src/mess/tools/imgtool/formats/coco_dsk.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/*********************************************************************
-
- formats/coco_dsk.h
-
- Tandy Color Computer / Dragon disk images
-
-*********************************************************************/
-
-#ifndef COCO_DSK_H
-#define COCO_DSK_H
-
-#include "formats/flopimg.h"
-
-
-/**************************************************************************/
-
-LEGACY_FLOPPY_OPTIONS_EXTERN(coco);
-
-FLOPPY_IDENTIFY(coco_dmk_identify);
-FLOPPY_CONSTRUCT(coco_dmk_construct);
-
-#endif /* COCO_DSK_H */
diff --git a/src/mess/tools/imgtool/formats/vt_dsk.c b/src/mess/tools/imgtool/formats/vt_dsk.c
deleted file mode 100644
index 4e75e843d28..00000000000
--- a/src/mess/tools/imgtool/formats/vt_dsk.c
+++ /dev/null
@@ -1,57 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Juergen Buchmueller
-/*********************************************************************
-
- formats/vt_dsk.c
-
- VTech Laser/VZ disk images
-
-*********************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include "formats/vt_dsk.h"
-#include "formats/basicdsk.h"
-
-static FLOPPY_IDENTIFY(vz_identify)
-{
- UINT64 size = floppy_image_size(floppy);
- *vote = ((size == 98560) || (size == 99200) || (size == 99184)) ? 100 : 0;
- return FLOPPY_ERROR_SUCCESS;
-}
-
-static FLOPPY_CONSTRUCT(vz_construct)
-{
- struct basicdsk_geometry geometry;
- memset(&geometry, 0, sizeof(geometry));
-
- if (params)
- {
- geometry.heads = option_resolution_lookup_int(params, PARAM_HEADS);
- geometry.tracks = option_resolution_lookup_int(params, PARAM_TRACKS);
- geometry.sectors = option_resolution_lookup_int(params, PARAM_SECTORS);
- geometry.first_sector_id = option_resolution_lookup_int(params, PARAM_FIRST_SECTOR_ID);
- geometry.sector_length = option_resolution_lookup_int(params, PARAM_SECTOR_LENGTH);
- }
- else
- {
- geometry.heads = 1;
- geometry.tracks = 40;
- geometry.sectors = 16;
- geometry.first_sector_id = 0;
- geometry.sector_length = floppy_image_size(floppy)/geometry.tracks/geometry.sectors;
- }
-
- return basicdsk_construct(floppy, &geometry);
-}
-
-
-LEGACY_FLOPPY_OPTIONS_START(vz)
- LEGACY_FLOPPY_OPTION(vtech1, "dsk", "Laser/VZ disk image", vz_identify, vz_construct, NULL,
- HEADS([1])
- TRACKS([40])
- SECTORS([16])
- SECTOR_LENGTH([154])
- FIRST_SECTOR_ID([0]))
-LEGACY_FLOPPY_OPTIONS_END
diff --git a/src/mess/tools/imgtool/formats/vt_dsk.h b/src/mess/tools/imgtool/formats/vt_dsk.h
deleted file mode 100644
index a3f9a86b44e..00000000000
--- a/src/mess/tools/imgtool/formats/vt_dsk.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Juergen Buchmueller
-/*********************************************************************
-
- formats/vt_dsk.h
-
- Tandy Color Computer / Dragon disk images
-
-*********************************************************************/
-
-#ifndef VT_DSK_H
-#define VT_DSK_H
-
-#include "formats/flopimg.h"
-
-LEGACY_FLOPPY_OPTIONS_EXTERN(vz);
-
-#endif /* VT_DSK_H */
diff --git a/src/mess/tools/imgtool/iflopimg.c b/src/mess/tools/imgtool/iflopimg.c
deleted file mode 100644
index 9e8493f9477..00000000000
--- a/src/mess/tools/imgtool/iflopimg.c
+++ /dev/null
@@ -1,363 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/*********************************************************************
-
- iflopimg.c
-
- Bridge code for Imgtool into the standard floppy code
-
-*********************************************************************/
-
-#include "imgtool.h"
-#include "formats/flopimg.h"
-#include "library.h"
-#include "iflopimg.h"
-
-imgtoolerr_t imgtool_floppy_error(floperr_t err)
-{
- switch(err)
- {
- case FLOPPY_ERROR_SUCCESS:
- return IMGTOOLERR_SUCCESS;
-
- case FLOPPY_ERROR_OUTOFMEMORY:
- return IMGTOOLERR_OUTOFMEMORY;
-
- case FLOPPY_ERROR_INVALIDIMAGE:
- return IMGTOOLERR_CORRUPTIMAGE;
-
- case FLOPPY_ERROR_SEEKERROR:
- return IMGTOOLERR_SEEKERROR;
-
- case FLOPPY_ERROR_UNSUPPORTED:
- return IMGTOOLERR_UNIMPLEMENTED;
-
- default:
- return IMGTOOLERR_UNEXPECTED;
- }
-}
-
-
-
-/*********************************************************************
- Imgtool ioprocs
-*********************************************************************/
-
-static void imgtool_floppy_closeproc(void *file)
-{
- stream_close((imgtool_stream *) file);
-}
-
-static int imgtool_floppy_seekproc(void *file, INT64 offset, int whence)
-{
- stream_seek((imgtool_stream *) file, offset, whence);
- return 0;
-}
-
-static size_t imgtool_floppy_readproc(void *file, void *buffer, size_t length)
-{
- return stream_read((imgtool_stream *) file, buffer, length);
-}
-
-static size_t imgtool_floppy_writeproc(void *file, const void *buffer, size_t length)
-{
- stream_write((imgtool_stream *) file, buffer, length);
- return length;
-}
-
-static UINT64 imgtool_floppy_filesizeproc(void *file)
-{
- return stream_size((imgtool_stream *) file);
-}
-
-static const struct io_procs imgtool_ioprocs =
-{
- imgtool_floppy_closeproc,
- imgtool_floppy_seekproc,
- imgtool_floppy_readproc,
- imgtool_floppy_writeproc,
- imgtool_floppy_filesizeproc
-};
-
-static const struct io_procs imgtool_noclose_ioprocs =
-{
- NULL,
- imgtool_floppy_seekproc,
- imgtool_floppy_readproc,
- imgtool_floppy_writeproc,
- imgtool_floppy_filesizeproc
-};
-
-
-
-/*********************************************************************
- Imgtool handlers
-*********************************************************************/
-
-struct imgtool_floppy_image
-{
- floppy_image_legacy *floppy;
-};
-
-
-
-
-static imgtoolerr_t imgtool_floppy_open_internal(imgtool_image *image, imgtool_stream *f, int noclose)
-{
- floperr_t ferr;
- imgtoolerr_t err;
- struct imgtool_floppy_image *fimg;
- const imgtool_class *imgclass;
- const struct FloppyFormat *format;
- imgtoolerr_t (*open)(imgtool_image *image, imgtool_stream *f);
-
- fimg = (struct imgtool_floppy_image *) imgtool_image_extra_bytes(image);
- imgclass = &imgtool_image_module(image)->imgclass;
- format = (const struct FloppyFormat *) imgclass->derived_param;
- open = (imgtoolerr_t (*)(imgtool_image *, imgtool_stream *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_OPEN);
-
- /* open up the floppy */
- ferr = floppy_open(f, noclose ? &imgtool_noclose_ioprocs : &imgtool_ioprocs,
- NULL, format, FLOPPY_FLAGS_READWRITE, &fimg->floppy);
- if (ferr)
- {
- err = imgtool_floppy_error(ferr);
- return err;
- }
-
- if (open)
- {
- err = open(image, NULL);
- if (err)
- return err;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t imgtool_floppy_open(imgtool_image *image, imgtool_stream *f)
-{
- return imgtool_floppy_open_internal(image, f, FALSE);
-}
-
-
-
-static imgtoolerr_t imgtool_floppy_create(imgtool_image *image, imgtool_stream *f, option_resolution *opts)
-{
- floperr_t ferr;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- struct imgtool_floppy_image *fimg;
- const imgtool_class *imgclass;
- const struct FloppyFormat *format;
- imgtoolerr_t (*create)(imgtool_image *, imgtool_stream *, option_resolution *);
- imgtoolerr_t (*open)(imgtool_image *image, imgtool_stream *f);
-
- fimg = (struct imgtool_floppy_image *) imgtool_image_extra_bytes(image);
- imgclass = &imgtool_image_module(image)->imgclass;
- format = (const struct FloppyFormat *) imgclass->derived_param;
- create = (imgtoolerr_t (*)(imgtool_image *, imgtool_stream *, option_resolution *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_CREATE);
- open = (imgtoolerr_t (*)(imgtool_image *, imgtool_stream *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_OPEN);
-
- /* open up the floppy */
- ferr = floppy_create(f, &imgtool_ioprocs, format, opts, &fimg->floppy);
- if (ferr)
- {
- err = imgtool_floppy_error(ferr);
- goto done;
- }
-
- /* do we have to do extra stuff when creating the image? */
- if (create)
- {
- err = create(image, NULL, opts);
- if (err)
- goto done;
- }
-
- /* do we have to do extra stuff when opening the image? */
- if (open)
- {
- err = open(image, NULL);
- if (err)
- goto done;
- }
-
-done:
- return err;
-}
-
-
-
-static void imgtool_floppy_close(imgtool_image *img)
-{
- floppy_close(imgtool_floppy(img));
-}
-
-
-
-static imgtoolerr_t imgtool_floppy_get_sector_size(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, UINT32 *sector_size)
-{
- floperr_t ferr;
-
- ferr = floppy_get_sector_length(imgtool_floppy(image), head, track, sector, sector_size);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t imgtool_floppy_read_sector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, void *buffer, size_t len)
-{
- floperr_t ferr;
-
- ferr = floppy_read_sector(imgtool_floppy(image), head, track, sector, 0, buffer, len);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t imgtool_floppy_write_sector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, const void *buffer, size_t len, int ddam)
-{
- floperr_t ferr;
-
- ferr = floppy_write_sector(imgtool_floppy(image), head, track, sector, 0, buffer, len, ddam);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void imgtool_floppy_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- const struct FloppyFormat *format;
- imgtool_class derived_class;
-
- format = (const struct FloppyFormat *) imgclass->derived_param;
- memset(&derived_class, 0, sizeof(derived_class));
- derived_class.get_info = imgclass->derived_get_info;
-
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES:
- info->i = sizeof(struct imgtool_floppy_image) +
- imgtool_get_info_int(&derived_class, IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES);
- break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME:
- sprintf(info->s = imgtool_temp_str(), "%s_%s", format->name,
- imgtool_get_info_string(&derived_class, IMGTOOLINFO_STR_NAME));
- break;
- case IMGTOOLINFO_STR_DESCRIPTION:
- sprintf(info->s = imgtool_temp_str(), "%s (%s)", format->description,
- imgtool_get_info_string(&derived_class, IMGTOOLINFO_STR_DESCRIPTION));
- break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), format->extensions); break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: info->p = (void*)format->param_guidelines; break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_OPEN: info->open = imgtool_floppy_open; break;
- case IMGTOOLINFO_PTR_CREATE: info->create = imgtool_floppy_create; break;
- case IMGTOOLINFO_PTR_CLOSE: info->close = imgtool_floppy_close; break;
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = format->param_guidelines ? floppy_option_guide : NULL; break;
- case IMGTOOLINFO_PTR_GET_SECTOR_SIZE: info->get_sector_size = imgtool_floppy_get_sector_size; break;
- case IMGTOOLINFO_PTR_READ_SECTOR: info->read_sector = imgtool_floppy_read_sector; break;
- case IMGTOOLINFO_PTR_WRITE_SECTOR: info->write_sector = imgtool_floppy_write_sector; break;
-
- default: imgclass->derived_get_info(imgclass, state, info); break;
- }
-}
-
-
-
-int imgtool_floppy_make_class(int index, imgtool_class *imgclass)
-{
- const struct FloppyFormat *format;
-
- /* get the format */
- format = (const struct FloppyFormat *)
- imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_FORMAT);
- assert(format);
- if (!format[index].construct)
- return FALSE;
-
- imgclass->derived_get_info = imgclass->get_info;
- imgclass->get_info = imgtool_floppy_get_info;
- imgclass->derived_param = (void *) &format[index];
- return TRUE;
-}
-
-
-
-floppy_image_legacy *imgtool_floppy(imgtool_image *img)
-{
- struct imgtool_floppy_image *fimg;
- fimg = (struct imgtool_floppy_image *) imgtool_image_extra_bytes(img);
- return fimg->floppy;
-}
-
-
-
-static imgtoolerr_t imgtool_floppy_transfer_sector_tofrom_stream(imgtool_image *img, int head, int track, int sector, int offset, size_t length, imgtool_stream *f, int direction)
-{
- floperr_t err;
- floppy_image_legacy *floppy;
- dynamic_buffer buffer;
-
- floppy = imgtool_floppy(img);
-
- buffer.resize(length);
-
- if (direction)
- {
- err = floppy_read_sector(floppy, head, track, sector, offset, &buffer[0], length);
- if (err)
- goto done;
- stream_write(f, &buffer[0], length);
- }
- else
- {
- stream_read(f, &buffer[0], length);
- err = floppy_write_sector(floppy, head, track, sector, offset, &buffer[0], length, 0); /* TODO: pass ddam argument from imgtool */
- if (err)
- goto done;
- }
-
- err = FLOPPY_ERROR_SUCCESS;
-
-done:
- return imgtool_floppy_error(err);
-}
-
-
-
-imgtoolerr_t imgtool_floppy_read_sector_to_stream(imgtool_image *img, int head, int track, int sector, int offset, size_t length, imgtool_stream *f)
-{
- return imgtool_floppy_transfer_sector_tofrom_stream(img, head, track, sector, offset, length, f, 1);
-}
-
-
-
-imgtoolerr_t imgtool_floppy_write_sector_from_stream(imgtool_image *img, int head, int track, int sector, int offset, size_t length, imgtool_stream *f)
-{
- return imgtool_floppy_transfer_sector_tofrom_stream(img, head, track, sector, offset, length, f, 0);
-}
-
-
-
-void *imgtool_floppy_extrabytes(imgtool_image *img)
-{
- struct imgtool_floppy_image *fimg;
- fimg = (struct imgtool_floppy_image *) imgtool_image_extra_bytes(img);
- return fimg + 1;
-}
diff --git a/src/mess/tools/imgtool/iflopimg.h b/src/mess/tools/imgtool/iflopimg.h
deleted file mode 100644
index 8e298330845..00000000000
--- a/src/mess/tools/imgtool/iflopimg.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/*********************************************************************
-
- iflopimg.h
-
- Bridge code for Imgtool into the standard floppy code
-
-*********************************************************************/
-
-#ifndef IFLOPIMG_H
-#define IFLOPIMG_H
-
-#include "formats/flopimg.h"
-#include "library.h"
-
-/***************************************************************************
-
- Prototypes
-
-***************************************************************************/
-
-enum
-{
- IMGTOOLINFO_PTR_FLOPPY_FORMAT = IMGTOOLINFO_PTR_CLASS_SPECIFIC,
- IMGTOOLINFO_PTR_FLOPPY_OPEN,
- IMGTOOLINFO_PTR_FLOPPY_CREATE
-};
-
-int imgtool_floppy_make_class(int index, imgtool_class *imgclass);
-
-floppy_image_legacy *imgtool_floppy(imgtool_image *img);
-imgtoolerr_t imgtool_floppy_error(floperr_t err);
-
-imgtoolerr_t imgtool_floppy_read_sector_to_stream(imgtool_image *img, int head, int track, int sector, int offset, size_t length, imgtool_stream *f);
-imgtoolerr_t imgtool_floppy_write_sector_from_stream(imgtool_image *img, int head, int track, int sector, int offset, size_t length, imgtool_stream *f);
-
-
-void *imgtool_floppy_extrabytes(imgtool_image *img);
-
-#endif /* IFLOPIMG_H */
diff --git a/src/mess/tools/imgtool/imghd.c b/src/mess/tools/imgtool/imghd.c
deleted file mode 100644
index 8ac129751f9..00000000000
--- a/src/mess/tools/imgtool/imghd.c
+++ /dev/null
@@ -1,273 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods, Raphael Nabet
-/*
- Code to interface the MESS image code with MAME's harddisk core.
-
- We do not support diff files as it will involve some changes in the MESS
- image code.
-
- Raphael Nabet 2003
-*/
-
-#include "imgtool.h"
-#include "harddisk.h"
-#include "imghd.h"
-
-
-static imgtoolerr_t map_chd_error(chd_error chderr)
-{
- imgtoolerr_t err;
-
- switch(chderr)
- {
- case CHDERR_NONE:
- err = IMGTOOLERR_SUCCESS;
- break;
- case CHDERR_OUT_OF_MEMORY:
- err = IMGTOOLERR_OUTOFMEMORY;
- break;
- case CHDERR_FILE_NOT_WRITEABLE:
- err = IMGTOOLERR_READONLY;
- break;
- case CHDERR_NOT_SUPPORTED:
- err = IMGTOOLERR_UNIMPLEMENTED;
- break;
- default:
- err = IMGTOOLERR_UNEXPECTED;
- break;
- }
- return err;
-}
-
-
-
-/*
- imghd_create()
-
- Create a MAME HD image
-*/
-imgtoolerr_t imghd_create(imgtool_stream *stream, UINT32 hunksize, UINT32 cylinders, UINT32 heads, UINT32 sectors, UINT32 seclen)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- dynamic_buffer cache;
- chd_file chd;
- chd_error rc;
- UINT64 logicalbytes;
- int hunknum, totalhunks;
- std::string metadata;
- chd_codec_type compression[4] = { CHD_CODEC_NONE };
-
- /* sanity check args */
- if (hunksize >= 2048)
- {
- err = IMGTOOLERR_PARAMCORRUPT;
- goto done;
- }
- if (hunksize <= 0)
- hunksize = 1024; /* default value */
-
- /* bail if we are read only */
- if (stream_isreadonly(stream))
- {
- err = IMGTOOLERR_READONLY;
- goto done;
- }
-
- /* calculations */
- logicalbytes = (UINT64)cylinders * heads * sectors * seclen;
-
- /* create the new hard drive */
- rc = chd.create(*stream_core_file(stream), logicalbytes, hunksize, seclen, compression);
- if (rc != CHDERR_NONE)
- {
- err = map_chd_error(rc);
- goto done;
- }
-
- /* open the new hard drive */
- rc = chd.open(*stream_core_file(stream));
-
- if (rc != CHDERR_NONE)
- {
- err = map_chd_error(rc);
- goto done;
- }
-
- /* write the metadata */
- strprintf(metadata,HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, seclen);
- err = (imgtoolerr_t)chd.write_metadata(HARD_DISK_METADATA_TAG, 0, metadata);
- if (rc != CHDERR_NONE)
- {
- err = map_chd_error(rc);
- goto done;
- }
-
- /* alloc and zero buffer */
- cache.resize(hunksize);
- memset(&cache[0], 0, hunksize);
-
- /* zero out every hunk */
- totalhunks = (logicalbytes + hunksize - 1) / hunksize;
- for (hunknum = 0; hunknum < totalhunks; hunknum++)
- {
- rc = chd.write_units(hunknum, &cache[0]);
- if (rc)
- {
- err = IMGTOOLERR_WRITEERROR;
- goto done;
- }
- }
-
-done:
- return err;
-}
-
-
-
-/*
- imghd_open()
-
- Open stream as a MAME HD image
-*/
-imgtoolerr_t imghd_open(imgtool_stream *stream, struct mess_hard_disk_file *hard_disk)
-{
- chd_error chderr;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
- hard_disk->hard_disk = NULL;
- hard_disk->chd = NULL;
-
- chderr = hard_disk->chd->open(*stream_core_file(stream), stream_isreadonly(stream));
- if (chderr)
- {
- err = map_chd_error(chderr);
- goto done;
- }
-
- hard_disk->hard_disk = hard_disk_open(hard_disk->chd);
- if (!hard_disk->hard_disk)
- {
- err = IMGTOOLERR_UNEXPECTED;
- goto done;
- }
- hard_disk->stream = stream;
-
-done:
- if (err)
- imghd_close(hard_disk);
- return err;
-}
-
-
-
-/*
- imghd_close()
-
- Close MAME HD image
-*/
-void imghd_close(struct mess_hard_disk_file *disk)
-{
- if (disk->hard_disk)
- {
- hard_disk_close(disk->hard_disk);
- disk->hard_disk = NULL;
- }
- if (disk->stream)
- stream_close(disk->stream);
-}
-
-
-
-/*
- imghd_read()
-
- Read sector(s) from MAME HD image
-*/
-imgtoolerr_t imghd_read(struct mess_hard_disk_file *disk, UINT32 lbasector, void *buffer)
-{
- UINT32 reply;
- reply = hard_disk_read(disk->hard_disk, lbasector, buffer);
- return (imgtoolerr_t)(reply ? IMGTOOLERR_SUCCESS : map_chd_error((chd_error)reply));
-}
-
-
-
-/*
- imghd_write()
-
- Write sector(s) from MAME HD image
-*/
-imgtoolerr_t imghd_write(struct mess_hard_disk_file *disk, UINT32 lbasector, const void *buffer)
-{
- UINT32 reply;
- reply = hard_disk_write(disk->hard_disk, lbasector, buffer);
- return (imgtoolerr_t)(reply ? IMGTOOLERR_SUCCESS : map_chd_error((chd_error)reply));
-}
-
-
-
-/*
- imghd_get_header()
-
- Return pointer to the header of MAME HD image
-*/
-const hard_disk_info *imghd_get_header(struct mess_hard_disk_file *disk)
-{
- const hard_disk_info *reply;
- reply = hard_disk_get_info(disk->hard_disk);
- return reply;
-}
-
-
-static imgtoolerr_t mess_hd_image_create(imgtool_image *image, imgtool_stream *f, option_resolution *createoptions);
-
-enum
-{
- mess_hd_createopts_blocksize = 'B',
- mess_hd_createopts_cylinders = 'C',
- mess_hd_createopts_heads = 'D',
- mess_hd_createopts_sectors = 'E',
- mess_hd_createopts_seclen = 'F'
-};
-
-static OPTION_GUIDE_START( mess_hd_create_optionguide )
- OPTION_INT(mess_hd_createopts_blocksize, "blocksize", "Sectors Per Block" )
- OPTION_INT(mess_hd_createopts_cylinders, "cylinders", "Cylinders" )
- OPTION_INT(mess_hd_createopts_heads, "heads", "Heads" )
- OPTION_INT(mess_hd_createopts_sectors, "sectors", "Total Sectors" )
- OPTION_INT(mess_hd_createopts_seclen, "seclen", "Sector Bytes" )
-OPTION_GUIDE_END
-
-#define mess_hd_create_optionspecs "B[1]-2048;C1-[32]-65536;D1-[8]-64;E1-[128]-4096;F128/256/[512]/1024/2048/4096/8192/16384/32768/65536"
-
-
-void hd_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "mess_hd"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "MESS hard disk image"); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "hd"); break;
-
- case IMGTOOLINFO_PTR_CREATE: info->create = mess_hd_image_create; break;
-
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = mess_hd_create_optionguide; break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), mess_hd_create_optionspecs); break;
- }
-}
-
-
-
-static imgtoolerr_t mess_hd_image_create(imgtool_image *image, imgtool_stream *f, option_resolution *createoptions)
-{
- UINT32 blocksize, cylinders, heads, sectors, seclen;
-
- /* read options */
- blocksize = option_resolution_lookup_int(createoptions, mess_hd_createopts_blocksize);
- cylinders = option_resolution_lookup_int(createoptions, mess_hd_createopts_cylinders);
- heads = option_resolution_lookup_int(createoptions, mess_hd_createopts_heads);
- sectors = option_resolution_lookup_int(createoptions, mess_hd_createopts_sectors);
- seclen = option_resolution_lookup_int(createoptions, mess_hd_createopts_seclen);
-
- return imghd_create(f, blocksize, cylinders, heads, sectors, seclen);
-}
diff --git a/src/mess/tools/imgtool/imghd.h b/src/mess/tools/imgtool/imghd.h
deleted file mode 100644
index 3dba7d40d4f..00000000000
--- a/src/mess/tools/imgtool/imghd.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/****************************************************************************
-
- imghd.h
-
- Bridge between Imgtool and CHD hard disk images
-
-****************************************************************************/
-
-#ifndef IMGHD_H
-#define IMGHD_H
-
-#include "harddisk.h"
-
-struct mess_hard_disk_file
-{
- imgtool_stream *stream;
- hard_disk_file *hard_disk;
- chd_file *chd;
-};
-
-
-/* create a new hard disk */
-imgtoolerr_t imghd_create(imgtool_stream *stream, UINT32 blocksize, UINT32 cylinders, UINT32 heads, UINT32 sectors, UINT32 seclen);
-
-/* opens a hard disk given an Imgtool stream */
-imgtoolerr_t imghd_open(imgtool_stream *stream, struct mess_hard_disk_file *hard_disk);
-
-/* close a hard disk */
-void imghd_close(struct mess_hard_disk_file *disk);
-
-/* reads data from a hard disk */
-imgtoolerr_t imghd_read(struct mess_hard_disk_file *disk, UINT32 lbasector, void *buffer);
-
-/* writes data to a hard disk */
-imgtoolerr_t imghd_write(struct mess_hard_disk_file *disk, UINT32 lbasector, const void *buffer);
-
-/* gets the header from a hard disk */
-const hard_disk_info *imghd_get_header(struct mess_hard_disk_file *disk);
-
-#endif /* IMGHD_H */
diff --git a/src/mess/tools/imgtool/imgterrs.c b/src/mess/tools/imgtool/imgterrs.c
deleted file mode 100644
index bd679440309..00000000000
--- a/src/mess/tools/imgtool/imgterrs.c
+++ /dev/null
@@ -1,55 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- imgterrs.c
-
- Imgtool errors
-
-***************************************************************************/
-
-#include "imgtool.h"
-#include "imgterrs.h"
-#include "osdcomm.h"
-
-static const char *const msgs[] =
-{
- "Out of memory",
- "Unexpected error",
- "Argument too long",
- "Read error",
- "Write error",
- "Image is read only",
- "Corrupt image",
- "Corrupt file",
- "Corrupt directory",
- "File not found",
- "Unrecognized format",
- "Not implemented",
- "Parameter too small",
- "Parameter too large",
- "Missing parameter not found",
- "Inappropriate parameter",
- "Invalid parameter",
- "Bad file name",
- "Out of space on image",
- "Input past end of file",
- "Cannot specify path",
- "Invalid path",
- "Path not found",
- "Directory not empty",
- "Seek error",
- "File system does not support forks",
- "Fork not found",
- "Invalid partition"
-};
-
-
-
-const char *imgtool_error(imgtoolerr_t err)
-{
- err = (imgtoolerr_t)(ERRORCODE(err) - 1);
- assert(err >= 0);
- assert(err < ARRAY_LENGTH(msgs));
- return msgs[err];
-}
diff --git a/src/mess/tools/imgtool/imgterrs.h b/src/mess/tools/imgtool/imgterrs.h
deleted file mode 100644
index 1cdafb6cef2..00000000000
--- a/src/mess/tools/imgtool/imgterrs.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- imgterrs.h
-
- Imgtool errors
-
-***************************************************************************/
-
-#ifndef IMGTERRS_H
-#define IMGTERRS_H
-
-/* Error codes */
-enum imgtoolerr_t
-{
- IMGTOOLERR_SUCCESS,
- IMGTOOLERR_OUTOFMEMORY,
- IMGTOOLERR_UNEXPECTED,
- IMGTOOLERR_BUFFERTOOSMALL,
- IMGTOOLERR_READERROR,
- IMGTOOLERR_WRITEERROR,
- IMGTOOLERR_READONLY,
- IMGTOOLERR_CORRUPTIMAGE,
- IMGTOOLERR_CORRUPTFILE,
- IMGTOOLERR_CORRUPTDIR,
- IMGTOOLERR_FILENOTFOUND,
- IMGTOOLERR_MODULENOTFOUND,
- IMGTOOLERR_UNIMPLEMENTED,
- IMGTOOLERR_PARAMTOOSMALL,
- IMGTOOLERR_PARAMTOOLARGE,
- IMGTOOLERR_PARAMNEEDED,
- IMGTOOLERR_PARAMNOTNEEDED,
- IMGTOOLERR_PARAMCORRUPT,
- IMGTOOLERR_BADFILENAME,
- IMGTOOLERR_NOSPACE,
- IMGTOOLERR_INPUTPASTEND,
- IMGTOOLERR_CANNOTUSEPATH,
- IMGTOOLERR_INVALIDPATH,
- IMGTOOLERR_PATHNOTFOUND,
- IMGTOOLERR_DIRNOTEMPTY,
- IMGTOOLERR_SEEKERROR,
- IMGTOOLERR_NOFORKS,
- IMGTOOLERR_FORKNOTFOUND,
- IMGTOOLERR_INVALIDPARTITION
-};
-
-
-
-/* These error codes are actually modifiers that make it easier to distinguish
- * the cause of an error
- *
- * Note - drivers should not use these modifiers
- */
-#define IMGTOOLERR_SRC_MODULE 0x1000
-#define IMGTOOLERR_SRC_FUNCTIONALITY 0x2000
-#define IMGTOOLERR_SRC_IMAGEFILE 0x3000
-#define IMGTOOLERR_SRC_FILEONIMAGE 0x4000
-#define IMGTOOLERR_SRC_NATIVEFILE 0x5000
-
-#define ERRORCODE(err) ((err) & 0x0fff)
-#define ERRORSOURCE(err) ((err) & 0xf000)
-#define ERRORPARAM(err) (((err) & 0xf0000) / 0x10000)
-
-#define PARAM_TO_ERROR(errcode, param) ((errcode) | ((param) * 0x10000))
-
-
-const char *imgtool_error(imgtoolerr_t err);
-
-#endif /* IMGTERRS_H */
diff --git a/src/mess/tools/imgtool/imgtool.c b/src/mess/tools/imgtool/imgtool.c
deleted file mode 100644
index df44a9bbff2..00000000000
--- a/src/mess/tools/imgtool/imgtool.c
+++ /dev/null
@@ -1,2814 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- imgtool.c
-
- Core code for Imgtool
-
-***************************************************************************/
-
-#include <string.h>
-#include <ctype.h>
-
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "library.h"
-#include "modules.h"
-#include "pool.h"
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-struct imgtool_image
-{
- const imgtool_module *module;
- object_pool *pool;
-};
-
-struct imgtool_partition
-{
- imgtool_image *image;
- object_pool *pool;
- int partition_index;
- UINT64 base_block;
- UINT64 block_count;
-
- imgtool_class imgclass;
- size_t partition_extra_bytes;
- size_t directory_extra_bytes;
-
- char path_separator;
- char alternate_path_separator;
-
- unsigned int prefer_ucase : 1;
- unsigned int supports_creation_time : 1;
- unsigned int supports_lastmodified_time : 1;
- unsigned int supports_bootblock : 1; /* this module supports loading/storing the boot block */
-
- imgtoolerr_t (*begin_enum) (imgtool_directory *enumeration, const char *path);
- imgtoolerr_t (*next_enum) (imgtool_directory *enumeration, imgtool_dirent *ent);
- void (*close_enum) (imgtool_directory *enumeration);
- imgtoolerr_t (*free_space) (imgtool_partition *partition, UINT64 *size);
- imgtoolerr_t (*read_file) (imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf);
- imgtoolerr_t (*write_file) (imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts);
- imgtoolerr_t (*delete_file) (imgtool_partition *partition, const char *filename);
- imgtoolerr_t (*list_forks) (imgtool_partition *partition, const char *path, imgtool_forkent *ents, size_t len);
- imgtoolerr_t (*create_dir) (imgtool_partition *partition, const char *path);
- imgtoolerr_t (*delete_dir) (imgtool_partition *partition, const char *path);
- imgtoolerr_t (*list_attrs) (imgtool_partition *partition, const char *path, UINT32 *attrs, size_t len);
- imgtoolerr_t (*get_attrs) (imgtool_partition *partition, const char *path, const UINT32 *attrs, imgtool_attribute *values);
- imgtoolerr_t (*set_attrs) (imgtool_partition *partition, const char *path, const UINT32 *attrs, const imgtool_attribute *values);
- imgtoolerr_t (*attr_name) (UINT32 attribute, const imgtool_attribute *attr, char *buffer, size_t buffer_len);
- imgtoolerr_t (*get_iconinfo) (imgtool_partition *partition, const char *path, imgtool_iconinfo *iconinfo);
- imgtoolerr_t (*suggest_transfer)(imgtool_partition *partition, const char *path, imgtool_transfer_suggestion *suggestions, size_t suggestions_length);
- imgtoolerr_t (*get_chain) (imgtool_partition *partition, const char *path, imgtool_chainent *chain, size_t chain_size);
-
- const option_guide *writefile_optguide;
- const char *writefile_optspec;
-};
-
-struct imgtool_directory
-{
- imgtool_partition *partition;
-};
-
-
-
-/***************************************************************************
- GLOBALS
-***************************************************************************/
-
-static imgtool_library *global_imgtool_library;
-
-static int global_omit_untested;
-static void (*global_warn)(const char *message);
-
-
-void CLIB_DECL ATTR_PRINTF(1,2) logerror(const char *format, ...)
-{
- va_list arg;
- va_start(arg, format);
- vprintf(format, arg);
- va_end(arg);
-}
-
-/***************************************************************************
-
- Imgtool initialization and basics
-
-***************************************************************************/
-void rtrim(char *buf)
-{
- size_t buflen;
- char *s;
-
- buflen = strlen(buf);
- if (buflen)
- {
- for (s = &buf[buflen-1]; s >= buf && (*s >= '\0') && isspace(*s); s--)
- *s = '\0';
- }
-}
-
-char *strncpyz(char *dest, const char *source, size_t len)
-{
- char *s;
- if (len) {
- s = strncpy(dest, source, len - 1);
- dest[len-1] = '\0';
- }
- else {
- s = dest;
- }
- return s;
-}
-
-char *strncatz(char *dest, const char *source, size_t len)
-{
- size_t l;
- l = strlen(dest);
- dest += l;
- if (len > l)
- len -= l;
- else
- len = 0;
- return strncpyz(dest, source, len);
-}
-
-/*-------------------------------------------------
- markerrorsource - marks where an error source
--------------------------------------------------*/
-
-static imgtoolerr_t markerrorsource(imgtoolerr_t err)
-{
- switch(err)
- {
- case IMGTOOLERR_OUTOFMEMORY:
- case IMGTOOLERR_UNEXPECTED:
- case IMGTOOLERR_BUFFERTOOSMALL:
- /* Do nothing */
- break;
-
- case IMGTOOLERR_FILENOTFOUND:
- case IMGTOOLERR_BADFILENAME:
- err = (imgtoolerr_t)(err | IMGTOOLERR_SRC_FILEONIMAGE);
- break;
-
- default:
- err = (imgtoolerr_t)(err | IMGTOOLERR_SRC_IMAGEFILE);
- break;
- }
- return err;
-}
-
-char *imgtool_basename(char *filename)
-{
- char *c;
-
- // NULL begets NULL
- if (!filename)
- return NULL;
-
- // start at the end and return when we hit a slash or colon
- for (c = filename + strlen(filename) - 1; c >= filename; c--)
- if (*c == '\\' || *c == '/' || *c == ':')
- return c + 1;
-
- // otherwise, return the whole thing
- return filename;
-}
-
-/*-------------------------------------------------
- internal_error - debug function for raising
- internal errors
--------------------------------------------------*/
-
-static void internal_error(const imgtool_module *module, const char *message)
-{
-#ifdef MAME_DEBUG
- printf("%s: %s\n", module->name, message);
-#endif
-}
-
-
-/*-------------------------------------------------
- normalize_filename - convert a filename to the
- native format used by the module
--------------------------------------------------*/
-
-static char *normalize_filename(imgtool_partition *partition, const char *src)
-{
- imgtool_charset charset;
-
- /* get charset from module */
- charset = (imgtool_charset) (int) imgtool_partition_get_info_int(partition, IMGTOOLINFO_INT_CHARSET);
-
- /* and dupe it */
- return native_from_utf8(charset, src);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_init - initializes the imgtool core
--------------------------------------------------*/
-
-void imgtool_init(int omit_untested, void (*warn)(const char *message))
-{
- imgtoolerr_t err;
- err = imgtool_create_cannonical_library(omit_untested, &global_imgtool_library);
- assert(err == IMGTOOLERR_SUCCESS);
- if (err == IMGTOOLERR_SUCCESS)
- {
- imgtool_library_sort(global_imgtool_library, ITLS_DESCRIPTION);
- }
- global_omit_untested = omit_untested;
- global_warn = warn;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_exit - closes out the imgtool core
--------------------------------------------------*/
-
-void imgtool_exit(void)
-{
- if (global_imgtool_library)
- {
- imgtool_library_close(global_imgtool_library);
- global_imgtool_library = NULL;
- }
- global_warn = NULL;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_find_module - looks up a module
--------------------------------------------------*/
-
-const imgtool_module *imgtool_find_module(const char *modulename)
-{
- return imgtool_library_findmodule(global_imgtool_library, modulename);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_get_module_features - retrieves a
- structure identifying this module's features
- associated with an image
--------------------------------------------------*/
-
-imgtool_module_features imgtool_get_module_features(const imgtool_module *module)
-{
- imgtool_module_features features;
- memset(&features, 0, sizeof(features));
-
- if (module->create)
- features.supports_create = 1;
- if (module->open)
- features.supports_open = 1;
- if (module->read_sector)
- features.supports_readsector = 1;
- if (module->write_sector)
- features.supports_writesector = 1;
- return features;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_warn - issues a warning
--------------------------------------------------*/
-
-void imgtool_warn(const char *format, ...)
-{
- va_list va;
- char buffer[2000];
-
- if (global_warn)
- {
- va_start(va, format);
- vsprintf(buffer, format, va);
- va_end(va);
- global_warn(buffer);
- }
-}
-
-
-
-/*-------------------------------------------------
- evaluate_module - evaluates a single file to
- determine what module can best handle a file
--------------------------------------------------*/
-
-static imgtoolerr_t evaluate_module(const char *fname,
- const imgtool_module *module, float *result)
-{
- imgtoolerr_t err;
- imgtool_image *image = NULL;
- imgtool_partition *partition = NULL;
- imgtool_directory *imageenum = NULL;
- imgtool_dirent ent;
- float current_result;
-
- *result = 0.0;
-
- err = imgtool_image_open(module, fname, OSD_FOPEN_READ, &image);
- if (err)
- goto done;
-
- if (image)
- {
- current_result = module->open_is_strict ? 0.9 : 0.5;
-
- err = imgtool_partition_open(image, 0, &partition);
- if (err)
- goto done;
-
- err = imgtool_directory_open(partition, NULL, &imageenum);
- if (err)
- goto done;
-
- memset(&ent, 0, sizeof(ent));
- do
- {
- err = imgtool_directory_get_next(imageenum, &ent);
- if (err)
- goto done;
-
- if (ent.corrupt)
- current_result = (current_result * 99 + 1.00f) / 100;
- else
- current_result = (current_result + 1.00f) / 2;
- }
- while(!ent.eof);
-
- *result = current_result;
- }
-
-done:
- if (ERRORCODE(err) == IMGTOOLERR_CORRUPTIMAGE)
- err = IMGTOOLERR_SUCCESS;
- if (imageenum)
- imgtool_directory_close(imageenum);
- if (partition)
- imgtool_partition_close(partition);
- if (image)
- imgtool_image_close(image);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_image - retrieves the image
- associated with this partition
--------------------------------------------------*/
-
-imgtool_image *imgtool_partition_image(imgtool_partition *partition)
-{
- return partition->image;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_identify_file - attempts to determine the module
- for any given image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_identify_file(const char *fname, imgtool_module **modules, size_t count)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- imgtool_library *library = global_imgtool_library;
- imgtool_module *module = NULL;
- imgtool_module *insert_module;
- imgtool_module *temp_module;
- size_t i = 0;
- const char *extension;
- float val, temp_val, *values = NULL;
-
- if (count <= 0)
- {
- err = IMGTOOLERR_UNEXPECTED;
- goto done;
- }
-
- for (i = 0; i < count; i++)
- modules[i] = NULL;
- if (count > 1)
- count--; /* null terminate */
-
- values = (float *) malloc(count * sizeof(*values));
- if (!values)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
- for (i = 0; i < count; i++)
- values[i] = 0.0;
-
- /* figure out the file extension, if any */
- extension = strrchr(fname, '.');
- if (extension)
- extension++;
-
- /* iterate through all modules */
- while((module = imgtool_library_iterate(library, module)) != NULL)
- {
- if (!extension || image_find_extension(module->extensions, extension))
- {
- err = evaluate_module(fname, module, &val);
- if (err)
- goto done;
-
- insert_module = module;
- for (i = 0; (val > 0.0f) && (i < count); i++)
- {
- if (val > values[i])
- {
- temp_val = values[i];
- temp_module = modules[i];
- values[i] = val;
- modules[i] = insert_module;
- val = temp_val;
- insert_module = temp_module;
- }
- }
- }
- }
-
- if (!modules[0])
- err = (imgtoolerr_t)(IMGTOOLERR_MODULENOTFOUND | IMGTOOLERR_SRC_IMAGEFILE);
-
-done:
- if (values)
- free(values);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_get_sector_size - gets the size
- of a particular sector on an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_get_sector_size(imgtool_image *image, UINT32 track, UINT32 head,
- UINT32 sector, UINT32 *length)
-{
- /* implemented? */
- if (!image->module->get_sector_size)
- return (imgtoolerr_t )(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
-
- return image->module->get_sector_size(image, track, head, sector, length);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_get_geometry - gets the geometry
- of an image; note that this may disagree with
- particular sectors; this is a common copy
- protection scheme
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_get_geometry(imgtool_image *image, UINT32 *tracks, UINT32 *heads, UINT32 *sectors)
-{
- UINT32 dummy;
-
- /* some sanitization, to make the callbacks easier to implement */
- if (!tracks)
- tracks = &dummy;
- if (!heads)
- heads = &dummy;
- if (!sectors)
- sectors = &dummy;
- *tracks = 0;
- *heads = 0;
- *sectors = 0;
-
- /* implemented? */
- if (!image->module->get_geometry)
- return (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
-
- return image->module->get_geometry(image, tracks, heads, sectors);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_read_sector - reads a sector on an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_read_sector(imgtool_image *image, UINT32 track, UINT32 head,
- UINT32 sector, void *buffer, size_t len)
-{
- /* implemented? */
- if (!image->module->read_sector)
- return (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
-
- return image->module->read_sector(image, track, head, sector, buffer, len);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_write_sector - writes a sector on an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_write_sector(imgtool_image *image, UINT32 track, UINT32 head,
- UINT32 sector, const void *buffer, size_t len)
-{
- /* implemented? */
- if (!image->module->write_sector)
- return (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
-
- return image->module->write_sector(image, track, head, sector, buffer, len);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_get_block_size - gets the size of
- a standard block on an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_get_block_size(imgtool_image *image, UINT32 *length)
-{
- /* implemented? */
- if (image->module->block_size == 0)
- return (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
-
- *length = image->module->block_size;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_read_block - reads a standard
- block on an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_read_block(imgtool_image *image, UINT64 block, void *buffer)
-{
- /* implemented? */
- if (!image->module->read_block)
- return (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
-
- return image->module->read_block(image, buffer, block);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_write_block - writes a standard
- block on an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_write_block(imgtool_image *image, UINT64 block, const void *buffer)
-{
- /* implemented? */
- if (!image->module->write_block)
- return (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
-
- return image->module->write_block(image, buffer, block);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_clear_block - clears a standard
- block on an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_clear_block(imgtool_image *image, UINT64 block, UINT8 data)
-{
- imgtoolerr_t err;
- UINT8 *block_data = NULL;
- UINT32 length;
-
- err = imgtool_image_get_block_size(image, &length);
- if (err)
- goto done;
-
- block_data = (UINT8*)malloc(length);
- if (!block_data)
- {
- err = (imgtoolerr_t)IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
- memset(block_data, data, length);
-
- err = imgtool_image_write_block(image, block, block_data);
- if (err)
- goto done;
-
-done:
- if (block_data)
- free(block_data);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_list_partitions - lists the
- partitions on an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_list_partitions(imgtool_image *image, imgtool_partition_info *partitions, size_t len)
-{
- /* implemented? */
- if (!image->module->list_partitions)
- return (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
-
- memset(partitions, '\0', sizeof(*partitions) * len);
- return image->module->list_partitions(image, partitions, len);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_malloc - allocates memory associated with an
- image
--------------------------------------------------*/
-
-void *imgtool_image_malloc(imgtool_image *image, size_t size)
-{
- return pool_malloc_lib(image->pool, size);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_module - returns the module associated with
- this image
--------------------------------------------------*/
-
-const imgtool_module *imgtool_image_module(imgtool_image *img)
-{
- return img->module;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_extra_bytes - returns extra bytes on an image
--------------------------------------------------*/
-
-void *imgtool_image_extra_bytes(imgtool_image *image)
-{
- void *ptr = NULL;
- if (image->module->image_extra_bytes > 0)
- ptr = ((UINT8 *) image) + sizeof(*image);
- assert(ptr);
- return ptr;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_rand - returns a random number
--------------------------------------------------*/
-
-UINT64 imgtool_image_rand(imgtool_image *image)
-{
- /* we can't use mame_rand() here */
-#ifdef rand
-#undef rand
-#endif
- return ((UINT64) rand()) << 32
- | ((UINT64) rand()) << 0;
-}
-
-
-
-/***************************************************************************
-
- Imgtool partition management
-
-***************************************************************************/
-
-static char *pool_strdup_allow_null(object_pool *pool, char *s)
-{
- return s ? pool_strdup_lib(pool, s) : NULL;
-}
-
-
-
-imgtoolerr_t imgtool_partition_open(imgtool_image *image, int partition_index, imgtool_partition **partition)
-{
- imgtoolerr_t err = (imgtoolerr_t)IMGTOOLERR_SUCCESS;
- imgtool_partition *p = NULL;
- imgtool_class imgclass;
- imgtool_partition_info partition_info[32];
- UINT64 base_block, block_count;
- size_t partition_extra_bytes;
- object_pool *pool;
- imgtoolerr_t (*open_partition)(imgtool_partition *partition, UINT64 first_block, UINT64 block_count);
-
- if (image->module->list_partitions)
- {
- /* this image supports partitions */
- if ((partition_index < 0) || (partition_index >= ARRAY_LENGTH(partition_info)))
- return IMGTOOLERR_INVALIDPARTITION;
-
- /* retrieve the info on the partitions */
- memset(partition_info, '\0', sizeof(partition_info));
- err = image->module->list_partitions(image, partition_info, ARRAY_LENGTH(partition_info));
- if (err)
- return err;
-
- /* is this a valid partition */
- if (!partition_info[partition_index].get_info)
- return IMGTOOLERR_INVALIDPARTITION;
-
- /* use this partition */
- memset(&imgclass, 0, sizeof(imgclass));
- imgclass.get_info = partition_info[partition_index].get_info;
- base_block = partition_info[partition_index].base_block;
- block_count = partition_info[partition_index].block_count;
- }
- else
- {
- /* this image does not support partitions */
- if (partition_index != 0)
- return IMGTOOLERR_INVALIDPARTITION;
-
- /* identify the image class */
- imgclass = imgtool_image_module(image)->imgclass;
- base_block = 0;
- block_count = ~0;
- }
-
- /* does this partition type have extra bytes? */
- partition_extra_bytes = imgtool_get_info_int(&imgclass, IMGTOOLINFO_INT_PARTITION_EXTRA_BYTES);
-
- /* allocate the new memory pool */
- pool = pool_alloc_lib(NULL);
- if (!pool)
- {
- err = (imgtoolerr_t)IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- /* allocate the new partition object */
- p = (imgtool_partition *) pool_malloc_lib(pool, sizeof(*p) + partition_extra_bytes);
- if (!p)
- {
- err = (imgtoolerr_t)IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
- memset(p, 0, sizeof(*p) + partition_extra_bytes);
- p->pool = pool;
-
- /* fill out the structure */
- p->image = image;
- p->partition_index = partition_index;
- p->base_block = base_block;
- p->block_count = block_count;
- p->imgclass = imgclass;
- p->partition_extra_bytes = partition_extra_bytes;
- p->directory_extra_bytes = imgtool_get_info_int(&imgclass, IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES);
- p->path_separator = (char) imgtool_get_info_int(&imgclass, IMGTOOLINFO_INT_PATH_SEPARATOR);
- p->alternate_path_separator = (char) imgtool_get_info_int(&imgclass, IMGTOOLINFO_INT_ALTERNATE_PATH_SEPARATOR);
- p->prefer_ucase = imgtool_get_info_int(&imgclass, IMGTOOLINFO_INT_PREFER_UCASE) ? 1 : 0;
- p->supports_creation_time = imgtool_get_info_int(&imgclass, IMGTOOLINFO_INT_SUPPORTS_CREATION_TIME) ? 1 : 0;
- p->supports_lastmodified_time = imgtool_get_info_int(&imgclass, IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME) ? 1 : 0;
- p->supports_bootblock = imgtool_get_info_int(&imgclass, IMGTOOLINFO_INT_SUPPORTS_BOOTBLOCK) ? 1 : 0;
- p->begin_enum = (imgtoolerr_t (*)(imgtool_directory *, const char *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_BEGIN_ENUM);
- p->next_enum = (imgtoolerr_t (*)(imgtool_directory *, imgtool_dirent *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_NEXT_ENUM);
- p->free_space = (imgtoolerr_t (*)(imgtool_partition *, UINT64 *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_FREE_SPACE);
- p->read_file = (imgtoolerr_t (*)(imgtool_partition *, const char *, const char *, imgtool_stream *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_READ_FILE);
- p->write_file = (imgtoolerr_t (*)(imgtool_partition *, const char *, const char *, imgtool_stream *, option_resolution *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_WRITE_FILE);
- p->delete_file = (imgtoolerr_t (*)(imgtool_partition *, const char *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_DELETE_FILE);
- p->list_forks = (imgtoolerr_t (*)(imgtool_partition *, const char *, imgtool_forkent *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_LIST_FORKS);
- p->create_dir = (imgtoolerr_t (*)(imgtool_partition *, const char *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_CREATE_DIR);
- p->delete_dir = (imgtoolerr_t (*)(imgtool_partition *, const char *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_DELETE_DIR);
- p->list_attrs = (imgtoolerr_t (*)(imgtool_partition *, const char *, UINT32 *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_LIST_ATTRS);
- p->get_attrs = (imgtoolerr_t (*)(imgtool_partition *, const char *, const UINT32 *, imgtool_attribute *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_GET_ATTRS);
- p->set_attrs = (imgtoolerr_t (*)(imgtool_partition *, const char *, const UINT32 *, const imgtool_attribute *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_SET_ATTRS);
- p->attr_name = (imgtoolerr_t (*)(UINT32, const imgtool_attribute *, char *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_ATTR_NAME);
- p->get_iconinfo = (imgtoolerr_t (*)(imgtool_partition *, const char *, imgtool_iconinfo *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_GET_ICON_INFO);
- p->suggest_transfer = (imgtoolerr_t (*)(imgtool_partition *, const char *, imgtool_transfer_suggestion *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_SUGGEST_TRANSFER);
- p->get_chain = (imgtoolerr_t (*)(imgtool_partition *, const char *, imgtool_chainent *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_GET_CHAIN);
- p->writefile_optguide = (const option_guide *) imgtool_get_info_ptr(&imgclass, IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE);
- p->writefile_optspec = pool_strdup_allow_null(p->pool, (char*)imgtool_get_info_ptr(&imgclass, IMGTOOLINFO_STR_WRITEFILE_OPTSPEC));
-
- /* mask out if writing is untested */
- if (global_omit_untested && imgtool_get_info_int(&imgclass, IMGTOOLINFO_INT_WRITING_UNTESTED))
- {
- p->write_file = NULL;
- p->delete_file = NULL;
- p->create_dir = NULL;
- p->delete_dir = NULL;
- p->writefile_optguide = NULL;
- p->writefile_optspec = NULL;
- }
-
- /* call the partition open function, if present */
- open_partition = (imgtoolerr_t (*)(imgtool_partition *, UINT64, UINT64)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_OPEN_PARTITION);
- if (open_partition)
- {
- /* we have an open partition function */
- err = (*open_partition)(p, base_block, block_count);
- if (err)
- goto done;
- }
-
-done:
- *partition = err ? NULL : p;
- return err;
-}
-
-
-
-void imgtool_partition_close(imgtool_partition *partition)
-{
- pool_free_lib(partition->pool);
-}
-
-
-
-/***************************************************************************
-
- Imgtool partition operations
-
-***************************************************************************/
-
-/*-------------------------------------------------
- imgtool_partition_get_attribute_name - retrieves the human readable
- name for an attribute
--------------------------------------------------*/
-
-void imgtool_partition_get_attribute_name(imgtool_partition *partition, UINT32 attribute, const imgtool_attribute *attr_value,
- char *buffer, size_t buffer_len)
-{
- imgtoolerr_t err = (imgtoolerr_t)IMGTOOLERR_UNIMPLEMENTED;
-
- buffer[0] = '\0';
-
- if (attr_value)
- {
- if (partition->attr_name)
- err = partition->attr_name(attribute, attr_value, buffer, buffer_len);
-
- if (err == (imgtoolerr_t)IMGTOOLERR_UNIMPLEMENTED)
- {
- switch(attribute & 0xF0000)
- {
- case IMGTOOLATTR_INT_FIRST:
- snprintf(buffer, buffer_len, "%d", (int) attr_value->i);
- break;
- }
- }
- }
- else
- {
- switch(attribute)
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- snprintf(buffer, buffer_len, "File type");
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- snprintf(buffer, buffer_len, "File creator");
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- snprintf(buffer, buffer_len, "Finder flags");
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- snprintf(buffer, buffer_len, "X coordinate");
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- snprintf(buffer, buffer_len, "Y coordinate");
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- snprintf(buffer, buffer_len, "Finder folder");
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- snprintf(buffer, buffer_len, "Icon ID");
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- snprintf(buffer, buffer_len, "Script code");
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- snprintf(buffer, buffer_len, "Extended flags");
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- snprintf(buffer, buffer_len, "Comment ID");
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- snprintf(buffer, buffer_len, "Putaway directory");
- break;
- case IMGTOOLATTR_TIME_CREATED:
- snprintf(buffer, buffer_len, "Creation time");
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- snprintf(buffer, buffer_len, "Last modified time");
- break;
- }
- }
-}
-
-
-
-/*-------------------------------------------------
- imgtool_validitychecks - checks the validity
- of the imgtool modules
--------------------------------------------------*/
-
-int imgtool_validitychecks(void)
-{
- int error = 0;
- int val;
- imgtoolerr_t err = (imgtoolerr_t)IMGTOOLERR_SUCCESS;
- const imgtool_module *module = NULL;
- const option_guide *guide_entry;
- imgtool_module_features features;
- int created_library = FALSE;
-
- if (!global_imgtool_library)
- {
- imgtool_init(FALSE, NULL);
- created_library = TRUE;
- }
-
- while((module = imgtool_library_iterate(global_imgtool_library, module)) != NULL)
- {
- features = imgtool_get_module_features(module);
-
- if (!module->name)
- {
- printf("imgtool module %s has null 'name'\n", module->name);
- error = 1;
- }
- if (!module->description)
- {
- printf("imgtool module %s has null 'description'\n", module->name);
- error = 1;
- }
- if (!module->extensions)
- {
- printf("imgtool module %s has null 'extensions'\n", module->extensions);
- error = 1;
- }
-
-#if 0
- /* sanity checks on modules that do not support directories */
- if (!module->path_separator)
- {
- if (module->alternate_path_separator)
- {
- printf("imgtool module %s specified alternate_path_separator but not path_separator\n", module->name);
- error = 1;
- }
- if (module->initial_path_separator)
- {
- printf("imgtool module %s specified initial_path_separator without directory support\n", module->name);
- error = 1;
- }
- if (module->create_dir)
- {
- printf("imgtool module %s implements create_dir without directory support\n", module->name);
- error = 1;
- }
- if (module->delete_dir)
- {
- printf("imgtool module %s implements delete_dir without directory support\n", module->name);
- error = 1;
- }
- }
-#endif
-
- /* sanity checks on sector operations */
- if (module->read_sector && !module->get_sector_size)
- {
- printf("imgtool module %s implements read_sector without supporting get_sector_size\n", module->name);
- error = 1;
- }
- if (module->write_sector && !module->get_sector_size)
- {
- printf("imgtool module %s implements write_sector without supporting get_sector_size\n", module->name);
- error = 1;
- }
-
- /* sanity checks on creation options */
- if (module->createimage_optguide || module->createimage_optspec)
- {
- if (!module->create)
- {
- printf("imgtool module %s has creation options without supporting create\n", module->name);
- error = 1;
- }
- if ((!module->createimage_optguide && module->createimage_optspec)
- || (module->createimage_optguide && !module->createimage_optspec))
- {
- printf("imgtool module %s does has partially incomplete creation options\n", module->name);
- error = 1;
- }
-
- if (module->createimage_optguide && module->createimage_optspec)
- {
- guide_entry = module->createimage_optguide;
- while(guide_entry->option_type != OPTIONTYPE_END)
- {
- if (option_resolution_contains(module->createimage_optspec, guide_entry->parameter))
- {
- switch(guide_entry->option_type)
- {
- case OPTIONTYPE_INT:
- case OPTIONTYPE_ENUM_BEGIN:
- err = (imgtoolerr_t)option_resolution_getdefault(module->createimage_optspec,
- guide_entry->parameter, &val);
- if (err)
- goto done;
- break;
-
- default:
- break;
- }
- if (!guide_entry->identifier)
- {
- printf("imgtool module %s creation option %d has null identifier\n",
- module->name, (int) (guide_entry - module->createimage_optguide));
- error = 1;
- }
- if (!guide_entry->display_name)
- {
- printf("imgtool module %s creation option %d has null display_name\n",
- module->name, (int) (guide_entry - module->createimage_optguide));
- error = 1;
- }
- }
- guide_entry++;
- }
- }
- }
- }
-
-done:
- if (created_library)
- imgtool_exit();
- if (err)
- {
- printf("imgtool: %s\n", imgtool_error(err));
- error = 1;
- }
- return error;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_temp_str - provides a temporary string
- buffer used for string passing
--------------------------------------------------*/
-
-char *imgtool_temp_str(void)
-{
- static int index;
- static char temp_string_pool[32][256];
- return temp_string_pool[index++ % ARRAY_LENGTH(temp_string_pool)];
-}
-
-
-
-/***************************************************************************
-
- Image handling functions
-
-***************************************************************************/
-
-static imgtoolerr_t internal_open(const imgtool_module *module, const char *fname,
- int read_or_write, option_resolution *createopts, imgtool_image **outimg)
-{
- imgtoolerr_t err;
- imgtool_stream *f = NULL;
- imgtool_image *image = NULL;
- object_pool *pool = NULL;
- size_t size;
-
- if (outimg)
- *outimg = NULL;
-
- /* is the requested functionality implemented? */
- if ((read_or_write == OSD_FOPEN_RW_CREATE) ? !module->create : !module->open)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- /* create a memory pool */
- pool = pool_alloc_lib(NULL);
- if (!pool)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_OUTOFMEMORY);
- goto done;
- }
-
- /* open the stream */
- f = stream_open(fname, read_or_write);
- if (!f)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_FILENOTFOUND | IMGTOOLERR_SRC_IMAGEFILE);
- goto done;
- }
-
- /* setup the image structure */
- size = sizeof(imgtool_image) + module->image_extra_bytes;
- image = (imgtool_image *) pool_malloc_lib(pool, size);
- if (!image)
- {
- err = (imgtoolerr_t)IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
- memset(image, '\0', size);
- image->pool = pool;
- image->module = module;
-
- /* actually call create or open */
- if (read_or_write == OSD_FOPEN_RW_CREATE)
- err = module->create(image, f, createopts);
- else
- err = module->open(image, f);
- if (err)
- {
- err = markerrorsource(err);
- goto done;
- }
-
-done:
- if (err)
- {
- if (f)
- stream_close(f);
- if (pool)
- pool_free_lib(pool);
- image = NULL;
- }
-
- if (outimg)
- *outimg = image;
- else if (image)
- imgtool_image_close(image);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_open - open an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_open(const imgtool_module *module, const char *fname, int read_or_write, imgtool_image **outimg)
-{
- read_or_write = read_or_write ? OSD_FOPEN_RW : OSD_FOPEN_READ;
- return internal_open(module, fname, read_or_write, NULL, outimg);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_open_byname - open an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_open_byname(const char *modulename, const char *fname, int read_or_write, imgtool_image **outimg)
-{
- const imgtool_module *module;
-
- module = imgtool_find_module(modulename);
- if (!module)
- return (imgtoolerr_t)(IMGTOOLERR_MODULENOTFOUND | IMGTOOLERR_SRC_MODULE);
-
- return imgtool_image_open(module, fname, read_or_write, outimg);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_close - close an image
--------------------------------------------------*/
-
-void imgtool_image_close(imgtool_image *image)
-{
- if (image->module->close)
- image->module->close(image);
- pool_free_lib(image->pool);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_create - creates an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_create(const imgtool_module *module, const char *fname,
- option_resolution *opts, imgtool_image **image)
-{
- imgtoolerr_t err;
- option_resolution *alloc_resolution = NULL;
-
- /* allocate dummy options if necessary */
- if (!opts && module->createimage_optguide)
- {
- alloc_resolution = option_resolution_create(module->createimage_optguide, module->createimage_optspec);
- if (!alloc_resolution)
- {
- err = (imgtoolerr_t)IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
- opts = alloc_resolution;
- }
- if (opts)
- option_resolution_finish(opts);
-
- err = internal_open(module, fname, OSD_FOPEN_RW_CREATE, opts, image);
- if (err)
- goto done;
-
-done:
- if (alloc_resolution)
- option_resolution_close(alloc_resolution);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_create_byname - creates an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_create_byname(const char *modulename, const char *fname,
- option_resolution *opts, imgtool_image **image)
-{
- const imgtool_module *module;
-
- module = imgtool_find_module(modulename);
- if (!module)
- return (imgtoolerr_t)(IMGTOOLERR_MODULENOTFOUND | IMGTOOLERR_SRC_MODULE);
-
- return imgtool_image_create(module, fname, opts, image);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_image_info - returns format specific information
- about an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_image_info(imgtool_image *image, char *string, size_t len)
-{
- if (len > 0)
- {
- string[0] = '\0';
- if (image->module->info)
- image->module->info(image, string, len);
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-#define PATH_MUSTBEDIR 0x00000001
-#define PATH_LEAVENULLALONE 0x00000002
-#define PATH_CANBEBOOTBLOCK 0x00000004
-
-/*-------------------------------------------------
- cannonicalize_path - normalizes a path string
- into a NUL delimited list
--------------------------------------------------*/
-
-static imgtoolerr_t cannonicalize_path(imgtool_partition *partition, UINT32 flags,
- const char **path, char **alloc_path)
-{
- imgtoolerr_t err = (imgtoolerr_t)IMGTOOLERR_SUCCESS;
- char *new_path = NULL;
- char path_separator, alt_path_separator;
- const char *s;
- int in_path_separator, i, j;
-
- path_separator = partition->path_separator;
- alt_path_separator = partition->alternate_path_separator;
-
- /* is this path NULL? if so, is that ignored? */
- if (!*path && (flags & PATH_LEAVENULLALONE))
- goto done;
-
- /* is this the special filename for bootblocks? */
- if (*path == FILENAME_BOOTBLOCK)
- {
- if (!(flags & PATH_CANBEBOOTBLOCK))
- err = (imgtoolerr_t)IMGTOOLERR_UNEXPECTED;
- else if (!partition->supports_bootblock)
- err = (imgtoolerr_t)IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
-
- if (path_separator == '\0')
- {
- if (flags & PATH_MUSTBEDIR)
- {
- /* do we specify a path when paths are not supported? */
- if (*path && **path)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_CANNOTUSEPATH | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
- *path = NULL; /* normalize empty path */
- }
- }
- else
- {
- s = *path ? *path : "";
-
- /* allocate space for a new cannonical path */
- new_path = (char*)malloc(strlen(s) + 4);
- if (!new_path)
- {
- err = (imgtoolerr_t)IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- /* copy the path */
- in_path_separator = TRUE;
- i = j = 0;
- do
- {
- if ((s[i] != '\0') && (s[i] != path_separator) && (s[i] != alt_path_separator))
- {
- new_path[j++] = s[i];
- in_path_separator = FALSE;
- }
- else if (!in_path_separator)
- {
- new_path[j++] = '\0';
- in_path_separator = TRUE;
- }
- }
- while(s[i++] != '\0');
- new_path[j++] = '\0';
- new_path[j++] = '\0';
- *path = new_path;
- }
-
-done:
- *alloc_path = new_path;
- return err;
-}
-
-
-
-static imgtoolerr_t cannonicalize_fork(imgtool_partition *partition, const char **fork)
-{
- /* does this module support forks? */
- if (partition->list_forks)
- {
- /* this module supports forks; make sure that fork is non-NULL */
- if (!*fork)
- *fork = "";
- }
- else
- {
- /* this module does not support forks; make sure that fork is NULL */
- if (*fork)
- return IMGTOOLERR_NOFORKS;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_directory_entry - retrieves
- the nth directory entry within a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_get_directory_entry(imgtool_partition *partition, const char *path, int index, imgtool_dirent *ent)
-{
- imgtoolerr_t err;
- imgtool_directory *imgenum = NULL;
-
- if (index < 0)
- {
- err = (imgtoolerr_t)IMGTOOLERR_PARAMTOOSMALL;
- goto done;
- }
-
- err = imgtool_directory_open(partition, path, &imgenum);
- if (err)
- goto done;
-
- do
- {
- err = imgtool_directory_get_next(imgenum, ent);
- if (err)
- goto done;
-
- if (ent->eof)
- {
- err = (imgtoolerr_t)IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
- }
- while(index--);
-
-done:
- if (err)
- memset(ent->filename, 0, sizeof(ent->filename));
- if (imgenum)
- imgtool_directory_close(imgenum);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_file_size - returns free
- space on a partition, in bytes
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_get_file_size(imgtool_partition *partition, const char *fname, UINT64 *filesize)
-{
- imgtoolerr_t err;
- imgtool_directory *imgenum;
- imgtool_dirent ent;
- const char *path;
-
- path = NULL; /* TODO: Need to parse off the path */
-
- *filesize = -1;
- memset(&ent, 0, sizeof(ent));
-
- err = imgtool_directory_open(partition, path, &imgenum);
- if (err)
- goto done;
-
- do
- {
- err = imgtool_directory_get_next(imgenum, &ent);
- if (err)
- goto done;
-
- if (!core_stricmp(fname, ent.filename))
- {
- *filesize = ent.filesize;
- goto done;
- }
- }
- while(ent.filename[0]);
-
- err = (imgtoolerr_t)IMGTOOLERR_FILENOTFOUND;
-
-done:
- if (imgenum)
- imgtool_directory_close(imgenum);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_list_file_attributes - identifies
- all attributes on a file
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_list_file_attributes(imgtool_partition *partition, const char *path, UINT32 *attrs, size_t len)
-{
- imgtoolerr_t err;
- char *alloc_path = NULL;
- char *new_fname = NULL;
-
- memset(attrs, 0, sizeof(*attrs) * len);
-
- if (!partition->list_attrs)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- new_fname = normalize_filename(partition, path);
- if (new_fname == NULL)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_BADFILENAME | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- path = new_fname;
-
- /* cannonicalize path */
- err = cannonicalize_path(partition, PATH_LEAVENULLALONE, &path, &alloc_path);
- if (err)
- goto done;
-
- err = partition->list_attrs(partition, path, attrs, len);
- if (err)
- goto done;
-
-done:
- if (alloc_path != NULL)
- free(alloc_path);
- if (new_fname != NULL)
- osd_free(new_fname);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_file_attributes - retrieves
- attributes on a file
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_get_file_attributes(imgtool_partition *partition, const char *path, const UINT32 *attrs, imgtool_attribute *values)
-{
- imgtoolerr_t err;
- char *alloc_path = NULL;
- char *new_fname = NULL;
-
- if (!partition->get_attrs)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- new_fname = normalize_filename(partition, path);
- if (new_fname == NULL)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_BADFILENAME | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- path = new_fname;
-
- /* cannonicalize path */
- err = cannonicalize_path(partition, PATH_LEAVENULLALONE, &path, &alloc_path);
- if (err)
- goto done;
-
- err = partition->get_attrs(partition, path, attrs, values);
- if (err)
- goto done;
-
-done:
- if (alloc_path != NULL)
- free(alloc_path);
- if (new_fname != NULL)
- osd_free(new_fname);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_put_file_attributes - sets
- attributes on a file
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_put_file_attributes(imgtool_partition *partition, const char *path, const UINT32 *attrs, const imgtool_attribute *values)
-{
- imgtoolerr_t err;
- char *alloc_path = NULL;
-
- if (!partition->set_attrs)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- /* cannonicalize path */
- err = cannonicalize_path(partition, PATH_LEAVENULLALONE, &path, &alloc_path);
- if (err)
- goto done;
-
- err = partition->set_attrs(partition, path, attrs, values);
- if (err)
- goto done;
-
-done:
- if (alloc_path)
- free(alloc_path);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_file_attributes - retrieves
- an attribute on a single file
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_get_file_attribute(imgtool_partition *partition, const char *path, UINT32 attr, imgtool_attribute *value)
-{
- UINT32 attrs[2];
- attrs[0] = attr;
- attrs[1] = 0;
- return imgtool_partition_get_file_attributes(partition, path, attrs, value);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_put_file_attribute - sets
- attributes on a single file
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_put_file_attribute(imgtool_partition *partition, const char *path, UINT32 attr, imgtool_attribute value)
-{
- UINT32 attrs[2];
- attrs[0] = attr;
- attrs[1] = 0;
- return imgtool_partition_put_file_attributes(partition, path, attrs, &value);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_icon_info - retrieves the
- icon for a file stored on a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_get_icon_info(imgtool_partition *partition, const char *path, imgtool_iconinfo *iconinfo)
-{
- imgtoolerr_t err;
- char *alloc_path = NULL;
- char *new_fname = NULL;
-
- if (!partition->get_iconinfo)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- new_fname = normalize_filename(partition, path);
- if (new_fname == NULL)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_BADFILENAME | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- path = new_fname;
-
- /* cannonicalize path */
- err = cannonicalize_path(partition, 0, &path, &alloc_path);
- if (err)
- goto done;
-
- memset(iconinfo, 0, sizeof(*iconinfo));
- err = partition->get_iconinfo(partition, path, iconinfo);
- if (err)
- goto done;
-
-done:
- if (alloc_path)
- free(alloc_path);
- if (new_fname)
- osd_free(new_fname);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_suggest_file_filters - suggests
- a list of filters appropriate for a file on a
- partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_suggest_file_filters(imgtool_partition *partition, const char *path,
- imgtool_stream *stream, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- imgtoolerr_t err;
- int i, j;
- char *alloc_path = NULL;
- imgtoolerr_t (*check_stream)(imgtool_stream *stream, imgtool_suggestion_viability_t *viability);
- size_t position;
-
- /* clear out buffer */
- memset(suggestions, 0, sizeof(*suggestions) * suggestions_length);
-
- if (!partition->suggest_transfer)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- /* cannonicalize path */
- err = cannonicalize_path(partition, PATH_LEAVENULLALONE, &path, &alloc_path);
- if (err)
- goto done;
-
- /* invoke the module's suggest call */
- err = partition->suggest_transfer(partition, path, suggestions, suggestions_length);
- if (err)
- goto done;
-
- /* Loop on resulting suggestions, and do the following:
- * 1. Call check_stream if present, and remove disqualified streams
- * 2. Fill in missing descriptions
- */
- i = j = 0;
- while(suggestions[i].viability)
- {
- if (stream && suggestions[i].filter)
- {
- check_stream = (imgtoolerr_t (*)(imgtool_stream *, imgtool_suggestion_viability_t *)) filter_get_info_fct(suggestions[i].filter, FILTINFO_PTR_CHECKSTREAM);
- if (check_stream)
- {
- position = stream_tell(stream);
- err = check_stream(stream, &suggestions[i].viability);
- stream_seek(stream, position, SEEK_SET);
- if (err)
- goto done;
- }
- }
-
- /* the check_stream proc can remove the option by clearing out the viability */
- if (suggestions[i].viability)
- {
- /* we may have to move this suggestion, if one was removed */
- if (i != j)
- memcpy(&suggestions[j], &suggestions[i], sizeof(*suggestions));
-
- /* if the description is missing, fill it in */
- if (!suggestions[j].description)
- {
- if (suggestions[j].filter)
- suggestions[j].description = filter_get_info_string(suggestions[i].filter, FILTINFO_STR_HUMANNAME);
- else
- suggestions[j].description = "Raw";
- }
-
- j++;
- }
- i++;
- }
- suggestions[j].viability = (imgtool_suggestion_viability_t)0;
-
-done:
- if (alloc_path)
- free(alloc_path);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_chain - retrieves the block
- chain for a file or directory on a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_get_chain(imgtool_partition *partition, const char *path, imgtool_chainent *chain, size_t chain_size)
-{
- size_t i;
-
- assert(chain_size > 0);
-
- if (!partition->get_chain)
- return (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
-
- /* initialize the chain array, so the module's get_chain function can be lazy */
- for (i = 0; i < chain_size; i++)
- {
- chain[i].level = 0;
- chain[i].block = ~0;
- }
-
- return partition->get_chain(partition, path, chain, chain_size - 1);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_chain_string - retrieves
- the block chain for a file or directory on a
- partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_get_chain_string(imgtool_partition *partition, const char *path, char *buffer, size_t buffer_len)
-{
- imgtoolerr_t err;
- imgtool_chainent chain[512];
- UINT64 last_block;
- UINT8 cur_level = 0;
- int len, i;
- int comma_needed = FALSE;
-
- /* determine the last block identifier */
- chain[0].block = ~0;
- last_block = chain[0].block;
-
- err = imgtool_partition_get_chain(partition, path, chain, ARRAY_LENGTH(chain));
- if (err)
- return err;
-
- len = snprintf(buffer, buffer_len, "[");
- buffer += len;
- buffer_len -= len;
-
- for (i = 0; chain[i].block != last_block; i++)
- {
- while(cur_level < chain[i].level)
- {
- len = snprintf(buffer, buffer_len, " [");
- buffer += len;
- buffer_len -= len;
- cur_level++;
- comma_needed = FALSE;
- }
- while(cur_level > chain[i].level)
- {
- len = snprintf(buffer, buffer_len, "]");
- buffer += len;
- buffer_len -= len;
- cur_level--;
- }
-
- if (comma_needed)
- {
- len = snprintf(buffer, buffer_len, ", ");
- buffer += len;
- buffer_len -= len;
- }
-
- len = snprintf(buffer, buffer_len, "%u", (unsigned) chain[i].block);
- buffer += len;
- buffer_len -= len;
- comma_needed = TRUE;
- }
-
- do
- {
- len = snprintf(buffer, buffer_len, "]");
- buffer += len;
- buffer_len -= len;
- }
- while(cur_level-- > 0);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_free_space - returns the
- amount of free space on a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_get_free_space(imgtool_partition *partition, UINT64 *sz)
-{
- imgtoolerr_t err;
- UINT64 size;
-
- if (!partition->free_space)
- return (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
-
- err = partition->free_space(partition, &size);
- if (err)
- return (imgtoolerr_t)(err | IMGTOOLERR_SRC_IMAGEFILE);
-
- if (sz)
- *sz = size;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_read_file - starts reading
- from a file on a partition with a stream
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_read_file(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf, filter_getinfoproc filter)
-{
- imgtoolerr_t err;
- char *alloc_path = NULL;
- union filterinfo u;
-
- if (!partition->read_file)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- if (filter)
- {
- /* use a filter */
- filter(FILTINFO_PTR_READFILE, &u);
- if (!u.read_file)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- err = u.read_file(partition, filename, fork, destf);
- if (err)
- {
- err = markerrorsource(err);
- goto done;
- }
- }
- else
- {
- /* cannonicalize path */
- err = cannonicalize_path(partition, PATH_CANBEBOOTBLOCK, &filename, &alloc_path);
- if (err)
- goto done;
-
- err = cannonicalize_fork(partition, &fork);
- if (err)
- goto done;
-
- /* invoke the actual module */
- err = partition->read_file(partition, filename, fork, destf);
- if (err)
- {
- err = markerrorsource(err);
- goto done;
- }
- }
-
-done:
- if (alloc_path)
- free(alloc_path);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_write_file - starts writing
- to a new file on an image with a stream
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_write_file(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts, filter_getinfoproc filter)
-{
- imgtoolerr_t err;
- char *buf = NULL;
- char *s;
- option_resolution *alloc_resolution = NULL;
- char *alloc_path = NULL;
- UINT64 free_space;
- UINT64 file_size;
- union filterinfo u;
-
- if (!partition->write_file)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- if (filter)
- {
- /* use a filter */
- filter(FILTINFO_PTR_WRITEFILE, &u);
- if (!u.write_file)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- err = u.write_file(partition, filename, fork, sourcef, opts);
- if (err)
- {
- err = markerrorsource(err);
- goto done;
- }
- }
- else
- {
- /* does this partition prefer upper case file names? */
- if (partition->prefer_ucase)
- {
- buf = (char*)malloc(strlen(filename) + 1);
- if (!buf)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_OUTOFMEMORY);
- goto done;
- }
- strcpy(buf, filename);
- for (s = buf; *s; s++)
- *s = toupper(*s);
- filename = buf;
- }
-
- /* cannonicalize path */
- err = cannonicalize_path(partition, PATH_CANBEBOOTBLOCK, &filename, &alloc_path);
- if (err)
- goto done;
-
- err = cannonicalize_fork(partition, &fork);
- if (err)
- goto done;
-
- /* allocate dummy options if necessary */
- if (!opts && partition->writefile_optguide)
- {
- alloc_resolution = option_resolution_create(partition->writefile_optguide, partition->writefile_optspec);
- if (!alloc_resolution)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
- opts = alloc_resolution;
- }
- if (opts)
- option_resolution_finish(opts);
-
- /* if free_space is implemented; do a quick check to see if space is available */
- if (partition->free_space)
- {
- err = partition->free_space(partition, &free_space);
- if (err)
- {
- err = markerrorsource(err);
- goto done;
- }
-
- file_size = stream_size(sourcef);
-
- if (file_size > free_space)
- {
- err = markerrorsource(IMGTOOLERR_NOSPACE);
- goto done;
- }
- }
-
- /* actually invoke the write file handler */
- err = partition->write_file(partition, filename, fork, sourcef, opts);
- if (err)
- {
- err = markerrorsource(err);
- goto done;
- }
- }
-
-done:
- if (buf)
- free(buf);
- if (alloc_path)
- free(alloc_path);
- if (alloc_resolution)
- option_resolution_close(alloc_resolution);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_file - read a file from
- an image, storing it into a native file
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_get_file(imgtool_partition *partition, const char *filename, const char *fork,
- const char *dest, filter_getinfoproc filter)
-{
- imgtoolerr_t err;
- imgtool_stream *f;
- char *new_fname = NULL;
- char *alloc_dest = NULL;
- const char *filter_extension = NULL;
-
- if (!dest)
- {
- /* determine the filter extension, if appropriate */
- if (filter != NULL)
- filter_extension = filter_get_info_string(filter, FILTINFO_STR_EXTENSION);
-
- if (filter_extension != NULL)
- {
- alloc_dest = (char*)malloc(strlen(filename) + 1 + strlen(filter_extension) + 1);
- if (!alloc_dest)
- return IMGTOOLERR_OUTOFMEMORY;
-
- sprintf(alloc_dest, "%s.%s", filename, filter_extension);
- dest = alloc_dest;
- }
- else
- {
- if (filename == FILENAME_BOOTBLOCK)
- dest = "boot.bin";
- else
- dest = filename;
- }
- }
-
- f = stream_open(dest, OSD_FOPEN_WRITE);
- if (!f)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_FILENOTFOUND | IMGTOOLERR_SRC_NATIVEFILE);
- goto done;
- }
-
- new_fname = normalize_filename(partition, filename);
- if (new_fname == NULL)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_BADFILENAME | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- err = imgtool_partition_read_file(partition, new_fname, fork, f, filter);
- if (err)
- goto done;
-
-done:
- if (f != NULL)
- stream_close(f);
- if (alloc_dest != NULL)
- free(alloc_dest);
- if (new_fname != NULL)
- osd_free(new_fname);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_put_file - read a native file
- and store it on a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_put_file(imgtool_partition *partition, const char *newfname, const char *fork,
- const char *source, option_resolution *opts, filter_getinfoproc filter)
-{
- imgtoolerr_t err;
- imgtool_stream *f = NULL;
- imgtool_charset charset;
- char *alloc_newfname = NULL;
-
- if (!newfname)
- newfname = (const char *) imgtool_basename((char *) source);
-
- charset = (imgtool_charset) (int) imgtool_partition_get_info_int(partition, IMGTOOLINFO_INT_CHARSET);
- if (charset != IMGTOOL_CHARSET_UTF8)
- {
- /* convert to native format */
- alloc_newfname = native_from_utf8(charset, newfname);
- if (alloc_newfname == NULL)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_BADFILENAME | IMGTOOLERR_SRC_NATIVEFILE);
- goto done;
- }
-
- newfname = alloc_newfname;
- }
-
- f = stream_open(source, OSD_FOPEN_READ);
- if (f)
- err = imgtool_partition_write_file(partition, newfname, fork, f, opts, filter);
- else
- err = (imgtoolerr_t)(IMGTOOLERR_FILENOTFOUND | IMGTOOLERR_SRC_NATIVEFILE);
-
-done:
- /* clean up */
- if (f != NULL)
- stream_close(f);
- if (alloc_newfname != NULL)
- osd_free(alloc_newfname);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_delete_file - delete a file
- on a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_delete_file(imgtool_partition *partition, const char *fname)
-{
- imgtoolerr_t err;
- char *alloc_path = NULL;
- char *new_fname = NULL;
-
- if (!partition->delete_file)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- new_fname = normalize_filename(partition, fname);
- if (new_fname == NULL)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_BADFILENAME | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- fname = new_fname;
-
- /* cannonicalize path */
- err = cannonicalize_path(partition, 0, &fname, &alloc_path);
- if (err)
- goto done;
-
- err = partition->delete_file(partition, fname);
- if (err)
- {
- err = markerrorsource(err);
- goto done;
- }
-
-done:
- if (alloc_path)
- free(alloc_path);
- if (new_fname)
- osd_free(new_fname);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_list_file_forks - lists all
- forks on an image
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_list_file_forks(imgtool_partition *partition, const char *path, imgtool_forkent *ents, size_t len)
-{
- imgtoolerr_t err;
- char *alloc_path = NULL;
- char *new_fname = NULL;
-
- if (!partition->list_forks)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- new_fname = normalize_filename(partition, path);
- if (new_fname == NULL)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_BADFILENAME | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- path = new_fname;
-
- /* cannonicalize path */
- err = cannonicalize_path(partition, 0, &path, &alloc_path);
- if (err)
- goto done;
-
- err = partition->list_forks(partition, path, ents, len);
- if (err)
- goto done;
-
-done:
- if (alloc_path)
- free(alloc_path);
- if (new_fname)
- osd_free(new_fname);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_create_directory - creates a
- directory on a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_create_directory(imgtool_partition *partition, const char *path)
-{
- imgtoolerr_t err;
- char *alloc_path = NULL;
- char *new_path = NULL;
-
- /* implemented? */
- if (!partition->create_dir)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- new_path = normalize_filename(partition, path);
- if (new_path == NULL)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_BADFILENAME | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- path = new_path;
-
- /* cannonicalize path */
- err = cannonicalize_path(partition, PATH_MUSTBEDIR, &path, &alloc_path);
- if (err)
- goto done;
-
- err = partition->create_dir(partition, path);
- if (err)
- goto done;
-
-done:
- if (alloc_path)
- free(alloc_path);
- if (new_path)
- osd_free(new_path);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_delete_directory - deletes a
- directory on a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_delete_directory(imgtool_partition *partition, const char *path)
-{
- imgtoolerr_t err;
- char *alloc_path = NULL;
- char *new_path = NULL;
-
- /* implemented? */
- if (!partition->delete_dir)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- new_path = normalize_filename(partition, path);
- if (new_path == NULL)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_BADFILENAME | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- path = new_path;
-
- /* cannonicalize path */
- err = cannonicalize_path(partition, PATH_MUSTBEDIR, &path, &alloc_path);
- if (err)
- goto done;
-
- err = partition->delete_dir(partition, path);
- if (err)
- goto done;
-
-done:
- if (alloc_path)
- free(alloc_path);
- if (new_path)
- osd_free(new_path);
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_block_size - gets the
- size of a standard block on a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_get_block_size(imgtool_partition *partition, UINT32 *length)
-{
- return imgtool_image_get_block_size(partition->image, length);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_read_block - reads a standard
- block on a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_read_block(imgtool_partition *partition, UINT64 block, void *buffer)
-{
- if (block >= partition->block_count)
- return IMGTOOLERR_SEEKERROR;
- return imgtool_image_read_block(partition->image, block + partition->base_block, buffer);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_write_block - writes a
- standard block on a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_partition_write_block(imgtool_partition *partition, UINT64 block, const void *buffer)
-{
- if (block >= partition->block_count)
- return IMGTOOLERR_SEEKERROR;
- return imgtool_image_write_block(partition->image, block + partition->base_block, buffer);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_features - retrieves a
- structure identifying this partition's features
- associated with an image
--------------------------------------------------*/
-
-imgtool_partition_features imgtool_partition_get_features(imgtool_partition *partition)
-{
- imgtool_partition_features features;
- memset(&features, 0, sizeof(features));
-
- if (partition->read_file)
- features.supports_reading = 1;
- if (partition->write_file)
- features.supports_writing = 1;
- if (partition->delete_file)
- features.supports_deletefile = 1;
- if (partition->path_separator)
- features.supports_directories = 1;
- if (partition->free_space)
- features.supports_freespace = 1;
- if (partition->create_dir)
- features.supports_createdir = 1;
- if (partition->delete_dir)
- features.supports_deletedir = 1;
- if (partition->supports_creation_time)
- features.supports_creation_time = 1;
- if (partition->supports_lastmodified_time)
- features.supports_lastmodified_time = 1;
- if (!features.supports_writing && !features.supports_createdir && !features.supports_deletefile && !features.supports_deletedir)
- features.is_read_only = 1;
- return features;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_info_ptr - retrieves a
- pointer associated with a partition's format
--------------------------------------------------*/
-
-void *imgtool_partition_get_info_ptr(imgtool_partition *partition, UINT32 state)
-{
- return imgtool_get_info_ptr(&partition->imgclass, state);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_info_string - retrieves a
- string associated with a partition's format
--------------------------------------------------*/
-
-const char *imgtool_partition_get_info_string(imgtool_partition *partition, UINT32 state)
-{
- return imgtool_get_info_string(&partition->imgclass, state);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_info_int - retrieves a
- pointer associated with a partition's format
--------------------------------------------------*/
-
-UINT64 imgtool_partition_get_info_int(imgtool_partition *partition, UINT32 state)
-{
- return imgtool_get_info_int(&partition->imgclass, state);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_extra_bytes - returns extra
- bytes on a partition
--------------------------------------------------*/
-
-void *imgtool_partition_extra_bytes(imgtool_partition *partition)
-{
- void *ptr = NULL;
- if (partition->partition_extra_bytes > 0)
- ptr = ((UINT8 *) partition) + sizeof(*partition);
- assert(ptr);
- return ptr;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_rand - returns random number
--------------------------------------------------*/
-
-UINT64 imgtool_partition_rand(imgtool_partition *partition)
-{
- return imgtool_image_rand(partition->image);
-}
-
-
-
-/***************************************************************************
-
- Path handling functions
-
-***************************************************************************/
-
-/*-------------------------------------------------
- imgtool_partition_get_root_path - retrieves
- the path root of this partition
--------------------------------------------------*/
-
-const char *imgtool_partition_get_root_path(imgtool_partition *partition)
-{
- int initial_path_separator;
- char path_separator;
- char *buf;
- int pos = 0;
-
- initial_path_separator = imgtool_partition_get_info_int(partition, IMGTOOLINFO_INT_INITIAL_PATH_SEPARATOR) ? 1 : 0;
- path_separator = (char) imgtool_partition_get_info_int(partition, IMGTOOLINFO_INT_PATH_SEPARATOR);
- buf = imgtool_temp_str();
-
- if (initial_path_separator)
- buf[pos++] = path_separator;
- buf[pos] = '\0';
- return buf;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_path_concatenate - retrieves
- a pointer associated with a partition's format
--------------------------------------------------*/
-
-const char *imgtool_partition_path_concatenate(imgtool_partition *partition, const char *path1, const char *path2)
-{
- char path_separator;
- size_t len;
- char *buffer;
- size_t buffer_len;
-
- path_separator = (char) imgtool_partition_get_info_int(partition, IMGTOOLINFO_INT_PATH_SEPARATOR);
- len = strlen(path1);
-
- /* prepare buffer */
- buffer = imgtool_temp_str();
- buffer_len = 256;
-
- if (!strcmp(path2, "."))
- {
- /* keep the same directory */
- snprintf(buffer, buffer_len, "%s", path1);
- }
- else if (!strcmp(path2, ".."))
- {
- /* up one directory */
- while((len > 0) && (path1[len - 1] == path_separator))
- len--;
- while((len > 0) && (path1[len - 1] != path_separator))
- len--;
- while((len > 1) && (path1[len - 1] == path_separator))
- len--;
- snprintf(buffer, buffer_len, "%s", path1);
- buffer[len] = '\0';
- }
- else
- {
- /* append a path */
- if ((*path1 != 0) && (path1[strlen(path1) - 1] != path_separator))
- snprintf(buffer, buffer_len, "%s%c%s", path1, path_separator, path2);
- else
- snprintf(buffer, buffer_len, "%s%s", path1, path2);
- }
- return buffer;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_partition_get_base_name - retrieves
- a base name for a partition specific path
--------------------------------------------------*/
-
-const char *imgtool_partition_get_base_name(imgtool_partition *partition, const char *path)
-{
- char path_separator;
- const char *new_path = path;
- int i;
-
- path_separator = (char) imgtool_partition_get_info_int(partition, IMGTOOLINFO_INT_PATH_SEPARATOR);
-
- for (i = 0; path[i]; i++)
- {
- if (path[i] == path_separator)
- new_path = &path[i + 1];
- }
- return new_path;
-}
-
-
-
-/***************************************************************************
-
- Directory handling functions
-
-***************************************************************************/
-
-/*-------------------------------------------------
- imgtool_directory_open - begins
- enumerating files on a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_directory_open(imgtool_partition *partition, const char *path, imgtool_directory **outenum)
-{
- imgtoolerr_t err = (imgtoolerr_t)IMGTOOLERR_SUCCESS;
- imgtool_directory *enumeration = NULL;
- char *alloc_path = NULL;
- char *new_path = NULL;
- size_t size;
-
- /* sanity checks */
- assert(partition);
- assert(outenum);
-
- *outenum = NULL;
-
- if (!partition->next_enum)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
- goto done;
- }
-
- new_path = normalize_filename(partition, path);
- path = new_path;
-
- err = cannonicalize_path(partition, PATH_MUSTBEDIR, &path, &alloc_path);
- if (err)
- goto done;
-
- size = sizeof(imgtool_directory) + partition->directory_extra_bytes;
- enumeration = (imgtool_directory *) malloc(size);
- if (!enumeration)
- {
- err = (imgtoolerr_t)IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
- memset(enumeration, '\0', size);
- enumeration->partition = partition;
-
- if (partition->begin_enum)
- {
- err = partition->begin_enum(enumeration, path);
- if (err)
- {
- err = markerrorsource(err);
- goto done;
- }
- }
-
-done:
- if (alloc_path != NULL)
- free(alloc_path);
- if (new_path != NULL)
- osd_free(new_path);
- if (err && (enumeration != NULL))
- {
- free(enumeration);
- enumeration = NULL;
- }
- *outenum = enumeration;
- return err;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_directory_close - closes a directory
--------------------------------------------------*/
-
-void imgtool_directory_close(imgtool_directory *directory)
-{
- imgtool_partition *partition;
- partition = imgtool_directory_partition(directory);
- if (partition->close_enum)
- partition->close_enum(directory);
- free(directory);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_directory_get_next - continues
- enumerating files within a partition
--------------------------------------------------*/
-
-imgtoolerr_t imgtool_directory_get_next(imgtool_directory *directory, imgtool_dirent *ent)
-{
- imgtoolerr_t err;
- imgtool_partition *partition;
- int charset;
-
- partition = imgtool_directory_partition(directory);
-
- /* This makes it so that drivers don't have to take care of clearing
- * the attributes if they don't apply
- */
- memset(ent, 0, sizeof(*ent));
-
- err = partition->next_enum(directory, ent);
- if (err)
- return markerrorsource(err);
-
- charset = imgtool_partition_get_info_int(partition, IMGTOOLINFO_INT_CHARSET);
-
- if (charset)
- {
- char *new_fname = utf8_from_native((imgtool_charset)charset, ent->filename);
-
- if (!new_fname)
- return IMGTOOLERR_BADFILENAME;
-
- strcpy(ent->filename, new_fname);
- osd_free(new_fname);
- }
-
- /* don't trust the module! */
- if (!partition->supports_creation_time && (ent->creation_time != 0))
- {
- internal_error(NULL, "next_enum() specified creation_time, which is marked as unsupported by this module");
- return IMGTOOLERR_UNEXPECTED;
- }
- if (!partition->supports_lastmodified_time && (ent->lastmodified_time != 0))
- {
- internal_error(NULL, "next_enum() specified lastmodified_time, which is marked as unsupported by this module");
- return IMGTOOLERR_UNEXPECTED;
- }
- if (!partition->path_separator && ent->directory)
- {
- internal_error(NULL, "next_enum() returned a directory, which is marked as unsupported by this module");
- return IMGTOOLERR_UNEXPECTED;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_directory_module - returns the module associated
- with this directory
--------------------------------------------------*/
-
-const imgtool_module *imgtool_directory_module(imgtool_directory *directory)
-{
- return directory->partition->image->module;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_directory_extrabytes - returns extra
- bytes on a directory
--------------------------------------------------*/
-
-void *imgtool_directory_extrabytes(imgtool_directory *directory)
-{
- assert(directory->partition->directory_extra_bytes > 0);
- return ((UINT8 *) directory) + sizeof(*directory);
-}
-
-
-
-/*-------------------------------------------------
- imgtool_directory_partition - returns the
- partition associated with this directory
--------------------------------------------------*/
-
-imgtool_partition *imgtool_directory_partition(imgtool_directory *directory)
-{
- return directory->partition;
-}
-
-
-
-/*-------------------------------------------------
- imgtool_directory_image - returns the image
- associated with this directory
--------------------------------------------------*/
-
-imgtool_image *imgtool_directory_image(imgtool_directory *directory)
-{
- return directory->partition->image;
-}
-
-
-
-/*-------------------------------------------------
- unknown_partition_get_info - represents an
- unknown partition
--------------------------------------------------*/
-
-void unknown_partition_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "unknown"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Unknown partition type"); break;
- }
-}
diff --git a/src/mess/tools/imgtool/imgtool.h b/src/mess/tools/imgtool/imgtool.h
deleted file mode 100644
index e688dfb60f1..00000000000
--- a/src/mess/tools/imgtool/imgtool.h
+++ /dev/null
@@ -1,169 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- imgtool.h
-
- Main headers for Imgtool core
-
-***************************************************************************/
-
-#ifndef IMGTOOL_H
-#define IMGTOOL_H
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "corestr.h"
-#include "formats/flopimg.h"
-#include "opresolv.h"
-#include "library.h"
-#include "filter.h"
-
-/* ----------------------------------------------------------------------- */
-
-#define EOLN_CR "\x0d"
-#define EOLN_LF "\x0a"
-#define EOLN_CRLF "\x0d\x0a"
-
-#define FILENAME_BOOTBLOCK ((const char *) 1)
-
-enum
-{
- OSD_FOPEN_READ,
- OSD_FOPEN_WRITE,
- OSD_FOPEN_RW,
- OSD_FOPEN_RW_CREATE
-};
-
-/* ---------------------------------------------------------------------------
- * Image calls
- *
- * These are the calls that front ends should use for manipulating images. You
- * should never call the module functions directly because they may not be
- * implemented (i.e. - the function pointers are NULL). The img_* functions are
- * aware of these issues and will make the appropriate checks as well as
- * marking up return codes with the source. In addition, some of the img_*
- * calls are high level calls that simply image manipulation
- *
- * Calls that return 'int' that are not explictly noted otherwise return
- * imgtool error codes
- * ---------------------------------------------------------------------------
- */
-
-struct imgtool_module_features
-{
- unsigned int supports_create : 1;
- unsigned int supports_open : 1;
- unsigned int supports_readsector : 1;
- unsigned int supports_writesector : 1;
- unsigned int is_read_only : 1;
-};
-
-struct imgtool_partition_features
-{
- unsigned int supports_reading : 1;
- unsigned int supports_writing : 1;
- unsigned int supports_deletefile : 1;
- unsigned int supports_directories : 1;
- unsigned int supports_freespace : 1;
- unsigned int supports_createdir : 1;
- unsigned int supports_deletedir : 1;
- unsigned int supports_creation_time : 1;
- unsigned int supports_lastmodified_time : 1;
- unsigned int supports_forks : 1;
- unsigned int supports_geticoninfo : 1;
- unsigned int is_read_only : 1;
-};
-
-/* ----- initialization and basics ----- */
-void imgtool_init(int omit_untested, void (*warning)(const char *message));
-void imgtool_exit(void);
-const imgtool_module *imgtool_find_module(const char *modulename);
-imgtool_module_features imgtool_get_module_features(const imgtool_module *module);
-void imgtool_warn(const char *format, ...) ATTR_PRINTF(1,2);
-char *imgtool_basename(char *filename);
-
-/* ----- image management ----- */
-imgtoolerr_t imgtool_identify_file(const char *filename, imgtool_module **modules, size_t count);
-imgtoolerr_t imgtool_image_open(const imgtool_module *module, const char *filename, int read_or_write, imgtool_image **outimg);
-imgtoolerr_t imgtool_image_open_byname(const char *modulename, const char *filename, int read_or_write, imgtool_image **outimg);
-imgtoolerr_t imgtool_image_create(const imgtool_module *module, const char *fname, option_resolution *opts, imgtool_image **image);
-imgtoolerr_t imgtool_image_create_byname(const char *modulename, const char *fname, option_resolution *opts, imgtool_image **image);
-void imgtool_image_close(imgtool_image *image);
-imgtoolerr_t imgtool_image_info(imgtool_image *image, char *string, size_t len);
-imgtoolerr_t imgtool_image_get_sector_size(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, UINT32 *length);
-imgtoolerr_t imgtool_image_get_geometry(imgtool_image *image, UINT32 *tracks, UINT32 *heads, UINT32 *sectors);
-imgtoolerr_t imgtool_image_read_sector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, void *buffer, size_t len);
-imgtoolerr_t imgtool_image_write_sector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, const void *buffer, size_t len);
-imgtoolerr_t imgtool_image_get_block_size(imgtool_image *image, UINT32 *length);
-imgtoolerr_t imgtool_image_read_block(imgtool_image *image, UINT64 block, void *buffer);
-imgtoolerr_t imgtool_image_write_block(imgtool_image *image, UINT64 block, const void *buffer);
-imgtoolerr_t imgtool_image_clear_block(imgtool_image *image, UINT64 block, UINT8 data);
-imgtoolerr_t imgtool_image_list_partitions(imgtool_image *image, imgtool_partition_info *partitions, size_t len);
-void *imgtool_image_malloc(imgtool_image *image, size_t size);
-const imgtool_module *imgtool_image_module(imgtool_image *image);
-void *imgtool_image_extra_bytes(imgtool_image *image);
-UINT64 imgtool_image_rand(imgtool_image *image);
-
-/* ----- partition management ----- */
-imgtoolerr_t imgtool_partition_open(imgtool_image *image, int partition_index, imgtool_partition **partition);
-void imgtool_partition_close(imgtool_partition *partition);
-imgtool_image *imgtool_partition_image(imgtool_partition *partition);
-
-/* ----- partition operations ----- */
-imgtoolerr_t imgtool_partition_get_directory_entry(imgtool_partition *partition, const char *path, int index, imgtool_dirent *ent);
-imgtoolerr_t imgtool_partition_get_file_size(imgtool_partition *partition, const char *filename, UINT64 *filesize);
-imgtoolerr_t imgtool_partition_get_free_space(imgtool_partition *partition, UINT64 *sz);
-imgtoolerr_t imgtool_partition_read_file(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf, filter_getinfoproc filter);
-imgtoolerr_t imgtool_partition_write_file(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *resolution, filter_getinfoproc filter);
-imgtoolerr_t imgtool_partition_get_file(imgtool_partition *partition, const char *filename, const char *fork, const char *dest, filter_getinfoproc filter);
-imgtoolerr_t imgtool_partition_put_file(imgtool_partition *partition, const char *newfname, const char *fork, const char *source, option_resolution *opts, filter_getinfoproc filter);
-imgtoolerr_t imgtool_partition_delete_file(imgtool_partition *partition, const char *fname);
-imgtoolerr_t imgtool_partition_list_file_forks(imgtool_partition *partition, const char *path, imgtool_forkent *ents, size_t len);
-imgtoolerr_t imgtool_partition_create_directory(imgtool_partition *partition, const char *path);
-imgtoolerr_t imgtool_partition_delete_directory(imgtool_partition *partition, const char *path);
-imgtoolerr_t imgtool_partition_list_file_attributes(imgtool_partition *partition, const char *path, UINT32 *attrs, size_t len);
-imgtoolerr_t imgtool_partition_get_file_attributes(imgtool_partition *partition, const char *path, const UINT32 *attrs, imgtool_attribute *values);
-imgtoolerr_t imgtool_partition_put_file_attributes(imgtool_partition *partition, const char *path, const UINT32 *attrs, const imgtool_attribute *values);
-imgtoolerr_t imgtool_partition_get_file_attribute(imgtool_partition *partition, const char *path, UINT32 attr, imgtool_attribute *value);
-imgtoolerr_t imgtool_partition_put_file_attribute(imgtool_partition *partition, const char *path, UINT32 attr, imgtool_attribute value);
-void imgtool_partition_get_attribute_name(imgtool_partition *partition, UINT32 attribute, const imgtool_attribute *attr_value, char *buffer, size_t buffer_len);
-imgtoolerr_t imgtool_partition_get_icon_info(imgtool_partition *partition, const char *path, imgtool_iconinfo *iconinfo);
-imgtoolerr_t imgtool_partition_suggest_file_filters(imgtool_partition *partition, const char *path, imgtool_stream *stream, imgtool_transfer_suggestion *suggestions, size_t suggestions_length);
-imgtoolerr_t imgtool_partition_get_block_size(imgtool_partition *partition, UINT32 *length);
-imgtoolerr_t imgtool_partition_read_block(imgtool_partition *partition, UINT64 block, void *buffer);
-imgtoolerr_t imgtool_partition_write_block(imgtool_partition *partition, UINT64 block, const void *buffer);
-imgtoolerr_t imgtool_partition_get_chain(imgtool_partition *partition, const char *path, imgtool_chainent *chain, size_t chain_size);
-imgtoolerr_t imgtool_partition_get_chain_string(imgtool_partition *partition, const char *path, char *buffer, size_t buffer_len);
-imgtool_partition_features imgtool_partition_get_features(imgtool_partition *partition);
-void * imgtool_partition_get_info_ptr(imgtool_partition *partition, UINT32 state);
-const char * imgtool_partition_get_info_string(imgtool_partition *partition, UINT32 state);
-UINT64 imgtool_partition_get_info_int(imgtool_partition *partition, UINT32 state);
-void * imgtool_partition_extra_bytes(imgtool_partition *partition);
-UINT64 imgtool_partition_rand(imgtool_partition *partition);
-
-/* ----- path management ----- */
-const char * imgtool_partition_get_root_path(imgtool_partition *partition);
-const char * imgtool_partition_path_concatenate(imgtool_partition *partition, const char *path1, const char *path2);
-const char * imgtool_partition_get_base_name(imgtool_partition *partition, const char *path);
-
-/* ----- directory management ----- */
-imgtoolerr_t imgtool_directory_open(imgtool_partition *partition, const char *path, imgtool_directory **outenum);
-void imgtool_directory_close(imgtool_directory *enumeration);
-imgtoolerr_t imgtool_directory_get_next(imgtool_directory *enumeration, imgtool_dirent *ent);
-const imgtool_module *imgtool_directory_module(imgtool_directory *enumeration);
-void *imgtool_directory_extrabytes(imgtool_directory *enumeration);
-imgtool_partition *imgtool_directory_partition(imgtool_directory *directory);
-imgtool_image *imgtool_directory_image(imgtool_directory *enumeration);
-
-/* ----- special ----- */
-int imgtool_validitychecks(void);
-void unknown_partition_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info);
-
-char *strncpyz(char *dest, const char *source, size_t len);
-char *strncatz(char *dest, const char *source, size_t len);
-void rtrim(char *buf);
-
-#endif /* IMGTOOL_H */
diff --git a/src/mess/tools/imgtool/library.c b/src/mess/tools/imgtool/library.c
deleted file mode 100644
index e2ce14d4461..00000000000
--- a/src/mess/tools/imgtool/library.c
+++ /dev/null
@@ -1,282 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/****************************************************************************
-
- library.c
-
- Code relevant to the Imgtool library; analgous to the MESS/MAME driver
- list.
-
-****************************************************************************/
-
-#include <string.h>
-
-#include "imgtool.h"
-#include "library.h"
-#include "pool.h"
-
-struct imgtool_library
-{
- object_pool *pool;
- imgtool_module *first;
- imgtool_module *last;
-};
-
-
-
-imgtool_library *imgtool_library_create(void)
-{
- imgtool_library *library;
- object_pool *pool;
-
- /* create a memory pool */
- pool = pool_alloc_lib(NULL);
- if (!pool)
- goto error;
-
- /* allocate the main structure */
- library = (imgtool_library *)pool_malloc_lib(pool, sizeof(imgtool_library));
- if (!library)
- goto error;
-
- /* initialize the structure */
- memset(library, 0, sizeof(*library));
- library->pool = pool;
-
- return library;
-
-error:
- if (pool)
- pool_free_lib(pool);
- return NULL;
-}
-
-
-
-void imgtool_library_close(imgtool_library *library)
-{
- pool_free_lib(library->pool);
-}
-
-
-
-static void imgtool_library_add_class(imgtool_library *library, const imgtool_class *imgclass)
-{
- imgtool_module *module;
- char *s1, *s2;
-
- /* allocate the module and place it in the chain */
- module = (imgtool_module *)imgtool_library_malloc(library, sizeof(*module));
- memset(module, 0, sizeof(*module));
- module->previous = library->last;
- if (library->last)
- library->last->next = module;
- else
- library->first = module;
- library->last = module;
-
- /* extensions have a weird format */
- s1 = imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_FILE_EXTENSIONS);
- s2 = (char*)imgtool_library_malloc(library, strlen(s1) + 1);
- strcpy(s2, s1);
- module->extensions = s2;
-
- module->imgclass = *imgclass;
- module->name = imgtool_library_strdup(library, imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_NAME));
- module->description = imgtool_library_strdup(library, imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_DESCRIPTION));
- module->eoln = imgtool_library_strdup_allow_null(library, imgtool_get_info_string(imgclass, IMGTOOLINFO_STR_EOLN));
- module->initial_path_separator = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_INITIAL_PATH_SEPARATOR) ? 1 : 0;
- module->open_is_strict = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_OPEN_IS_STRICT) ? 1 : 0;
- module->tracks_are_called_cylinders = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_TRACKS_ARE_CALLED_CYLINDERS) ? 1 : 0;
- module->writing_untested = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_WRITING_UNTESTED) ? 1 : 0;
- module->creation_untested = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_CREATION_UNTESTED) ? 1 : 0;
- module->open = (imgtoolerr_t (*)(imgtool_image *, imgtool_stream *)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_OPEN);
- module->create = (imgtoolerr_t (*)(imgtool_image *, imgtool_stream *, option_resolution *)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_CREATE);
- module->close = (void (*)(imgtool_image *)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_CLOSE);
- module->info = (void (*)(imgtool_image *, char *, size_t)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_INFO);
- module->read_sector = (imgtoolerr_t (*)(imgtool_image *, UINT32, UINT32, UINT32, void *, size_t)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_READ_SECTOR);
- module->write_sector = (imgtoolerr_t (*)(imgtool_image *, UINT32, UINT32, UINT32, const void *, size_t)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_WRITE_SECTOR);
- module->get_geometry = (imgtoolerr_t (*)(imgtool_image *, UINT32 *, UINT32 *, UINT32 *))imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_GET_GEOMETRY);
- module->get_sector_size = (imgtoolerr_t (*)(imgtool_image *, UINT32, UINT32, UINT32, UINT32 *))imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_GET_SECTOR_SIZE);
- module->read_block = (imgtoolerr_t (*)(imgtool_image *, void *, UINT64)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_READ_BLOCK);
- module->write_block = (imgtoolerr_t (*)(imgtool_image *, const void *, UINT64)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_WRITE_BLOCK);
- module->list_partitions = (imgtoolerr_t (*)(imgtool_image *, imgtool_partition_info *, size_t)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_LIST_PARTITIONS);
- module->block_size = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_BLOCK_SIZE);
- module->createimage_optguide = (const option_guide *) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE);
- module->createimage_optspec = imgtool_library_strdup_allow_null(library, (const char*)imgtool_get_info_ptr(imgclass, IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC));
- module->image_extra_bytes += imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES);
-}
-
-
-
-void imgtool_library_add(imgtool_library *library, imgtool_get_info get_info)
-{
- int (*make_class)(int index, imgtool_class *imgclass);
- imgtool_class imgclass;
- int i, result;
-
- /* try this class */
- memset(&imgclass, 0, sizeof(imgclass));
- imgclass.get_info = get_info;
-
- /* do we have derived getinfo functions? */
- make_class = (int (*)(int index, imgtool_class *imgclass))
- imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_MAKE_CLASS);
-
- if (make_class)
- {
- i = 0;
- do
- {
- /* clear out the class */
- memset(&imgclass, 0, sizeof(imgclass));
- imgclass.get_info = get_info;
-
- /* make the class */
- result = make_class(i++, &imgclass);
- if (result)
- imgtool_library_add_class(library, &imgclass);
- }
- while(result);
- }
- else
- {
- imgtool_library_add_class(library, &imgclass);
- }
-}
-
-
-
-const imgtool_module *imgtool_library_unlink(imgtool_library *library,
- const char *module)
-{
- imgtool_module *m;
- imgtool_module **previous;
- imgtool_module **next;
-
- for (m = library->first; m; m = m->next)
- {
- if (!core_stricmp(m->name, module))
- {
- previous = m->previous ? &m->previous->next : &library->first;
- next = m->next ? &m->next->previous : &library->last;
- *previous = m->next;
- *next = m->previous;
- m->previous = NULL;
- m->next = NULL;
- return m;
- }
- }
- return NULL;
-}
-
-
-
-static int module_compare(const imgtool_module *m1,
- const imgtool_module *m2, imgtool_libsort_t sort)
-{
- int rc = 0;
- switch(sort)
- {
- case ITLS_NAME:
- rc = strcmp(m1->name, m2->name);
- break;
- case ITLS_DESCRIPTION:
- rc = core_stricmp(m1->name, m2->name);
- break;
- }
- return rc;
-}
-
-
-
-void imgtool_library_sort(imgtool_library *library, imgtool_libsort_t sort)
-{
- imgtool_module *m1;
- imgtool_module *m2;
- imgtool_module *target;
- imgtool_module **before;
- imgtool_module **after;
-
- for (m1 = library->first; m1; m1 = m1->next)
- {
- target = m1;
- for (m2 = m1->next; m2; m2 = m2->next)
- {
- while(module_compare(target, m2, sort) > 0)
- target = m2;
- }
-
- if (target != m1)
- {
- /* unlink the target */
- before = target->previous ? &target->previous->next : &library->first;
- after = target->next ? &target->next->previous : &library->last;
- *before = target->next;
- *after = target->previous;
-
- /* now place the target before m1 */
- target->previous = m1->previous;
- target->next = m1;
- before = m1->previous ? &m1->previous->next : &library->first;
- *before = target;
- m1->previous = target;
-
- /* since we changed the order, we have to replace ourselves */
- m1 = target;
- }
- }
-}
-
-
-
-const imgtool_module *imgtool_library_findmodule(
- imgtool_library *library, const char *module_name)
-{
- const imgtool_module *module;
-
- assert(library);
- module = library->first;
- while(module && module_name && strcmp(module->name, module_name))
- module = module->next;
- return module;
-}
-
-
-
-imgtool_module *imgtool_library_iterate(imgtool_library *library, const imgtool_module *module)
-{
- return module ? module->next : library->first;
-}
-
-
-
-imgtool_module *imgtool_library_index(imgtool_library *library, int i)
-{
- imgtool_module *module;
- module = library->first;
- while(module && i--)
- module = module->next;
- return module;
-}
-
-
-
-void *imgtool_library_malloc(imgtool_library *library, size_t mem)
-{
- return pool_malloc_lib(library->pool, mem);
-}
-
-
-
-char *imgtool_library_strdup(imgtool_library *library, const char *s)
-{
- return pool_strdup_lib(library->pool, s);
-}
-
-
-
-char *imgtool_library_strdup_allow_null(imgtool_library *library, const char *s)
-{
- return s ? imgtool_library_strdup(library, s) : NULL;
-}
diff --git a/src/mess/tools/imgtool/library.h b/src/mess/tools/imgtool/library.h
deleted file mode 100644
index 25c923c1f4d..00000000000
--- a/src/mess/tools/imgtool/library.h
+++ /dev/null
@@ -1,408 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/****************************************************************************
-
- library.h
-
- Code relevant to the Imgtool library; analgous to the MESS/MAME driver
- list.
-
- Unlike MESS and MAME which have static driver lists, Imgtool has a
- concept of a library and this library is built at startup time.
- dynamic for which modules are added to. This makes "dynamic" modules
- much easier
-
-****************************************************************************/
-
-#ifndef LIBRARY_H
-#define LIBRARY_H
-
-#include <time.h>
-
-#include "corestr.h"
-#include "opresolv.h"
-#include "stream.h"
-#include "unicode.h"
-#include "charconv.h"
-
-
-struct imgtool_image;
-struct imgtool_partition;
-struct imgtool_directory;
-struct imgtool_library;
-
-enum imgtool_suggestion_viability_t
-{
- SUGGESTION_END,
- SUGGESTION_POSSIBLE,
- SUGGESTION_RECOMMENDED
-};
-
-union filterinfo
-{
- INT64 i; /* generic integers */
- void * p; /* generic pointers */
- void * f; /* generic function pointers */
- const char *s; /* generic strings */
-
- imgtoolerr_t (*read_file)(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf);
- imgtoolerr_t (*write_file)(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts);
- imgtoolerr_t (*check_stream)(imgtool_stream *stream, imgtool_suggestion_viability_t *viability);
-};
-
-typedef void (*filter_getinfoproc)(UINT32 state, union filterinfo *info);
-
-enum imgtool_libsort_t
-{
- ITLS_NAME,
- ITLS_DESCRIPTION
-};
-
-struct imgtool_dirent
-{
- char filename[1024];
- char attr[64];
- UINT64 filesize;
-
- time_t creation_time;
- time_t lastmodified_time;
- time_t lastaccess_time;
-
- char softlink[1024];
- char comment[256];
-
- /* flags */
- unsigned int eof : 1;
- unsigned int corrupt : 1;
- unsigned int directory : 1;
- unsigned int hardlink : 1;
-};
-
-struct imgtool_chainent
-{
- UINT8 level;
- UINT64 block;
-};
-
-enum imgtool_forktype_t
-{
- FORK_END,
- FORK_DATA,
- FORK_RESOURCE,
- FORK_ALTERNATE
-};
-
-struct imgtool_forkent
-{
- imgtool_forktype_t type;
- UINT64 size;
- char forkname[64];
-};
-
-struct imgtool_transfer_suggestion
-{
- imgtool_suggestion_viability_t viability;
- filter_getinfoproc filter;
- const char *fork;
- const char *description;
-};
-
-enum
-{
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- IMGTOOLATTR_INT_FIRST = 0x00000,
- IMGTOOLATTR_INT_MAC_TYPE,
- IMGTOOLATTR_INT_MAC_CREATOR,
- IMGTOOLATTR_INT_MAC_FINDERFLAGS,
- IMGTOOLATTR_INT_MAC_COORDX,
- IMGTOOLATTR_INT_MAC_COORDY,
- IMGTOOLATTR_INT_MAC_FINDERFOLDER,
- IMGTOOLATTR_INT_MAC_ICONID,
- IMGTOOLATTR_INT_MAC_SCRIPTCODE,
- IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS,
- IMGTOOLATTR_INT_MAC_COMMENTID,
- IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY,
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- IMGTOOLATTR_PTR_FIRST = 0x10000,
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- IMGTOOLATTR_STR_FIRST = 0x20000,
-
- /* --- the following bits of info are returned as time_t values --- */
- IMGTOOLATTR_TIME_FIRST = 0x30000,
- IMGTOOLATTR_TIME_CREATED,
- IMGTOOLATTR_TIME_LASTMODIFIED
-};
-
-union imgtool_attribute
-{
- INT64 i;
- time_t t;
-};
-
-struct imgtool_iconinfo
-{
- unsigned icon16x16_specified : 1;
- unsigned icon32x32_specified : 1;
- UINT32 icon16x16[16][16];
- UINT32 icon32x32[32][32];
-};
-
-enum
-{
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- IMGTOOLINFO_INT_FIRST = 0x00000,
- IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES,
- IMGTOOLINFO_INT_PARTITION_EXTRA_BYTES,
- IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES,
- IMGTOOLINFO_INT_PATH_SEPARATOR,
- IMGTOOLINFO_INT_ALTERNATE_PATH_SEPARATOR,
- IMGTOOLINFO_INT_PREFER_UCASE,
- IMGTOOLINFO_INT_INITIAL_PATH_SEPARATOR,
- IMGTOOLINFO_INT_OPEN_IS_STRICT,
- IMGTOOLINFO_INT_SUPPORTS_CREATION_TIME,
- IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME,
- IMGTOOLINFO_INT_TRACKS_ARE_CALLED_CYLINDERS,
- IMGTOOLINFO_INT_WRITING_UNTESTED,
- IMGTOOLINFO_INT_CREATION_UNTESTED,
- IMGTOOLINFO_INT_SUPPORTS_BOOTBLOCK,
- IMGTOOLINFO_INT_BLOCK_SIZE,
- IMGTOOLINFO_INT_CHARSET,
-
- IMGTOOLINFO_INT_CLASS_SPECIFIC = 0x08000,
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- IMGTOOLINFO_PTR_FIRST = 0x10000,
-
- IMGTOOLINFO_PTR_OPEN,
- IMGTOOLINFO_PTR_CREATE,
- IMGTOOLINFO_PTR_CLOSE,
- IMGTOOLINFO_PTR_OPEN_PARTITION,
- IMGTOOLINFO_PTR_CREATE_PARTITION,
- IMGTOOLINFO_PTR_INFO,
- IMGTOOLINFO_PTR_BEGIN_ENUM,
- IMGTOOLINFO_PTR_NEXT_ENUM,
- IMGTOOLINFO_PTR_CLOSE_ENUM,
- IMGTOOLINFO_PTR_FREE_SPACE,
- IMGTOOLINFO_PTR_READ_FILE,
- IMGTOOLINFO_PTR_WRITE_FILE,
- IMGTOOLINFO_PTR_DELETE_FILE,
- IMGTOOLINFO_PTR_LIST_FORKS,
- IMGTOOLINFO_PTR_CREATE_DIR,
- IMGTOOLINFO_PTR_DELETE_DIR,
- IMGTOOLINFO_PTR_LIST_ATTRS,
- IMGTOOLINFO_PTR_GET_ATTRS,
- IMGTOOLINFO_PTR_SET_ATTRS,
- IMGTOOLINFO_PTR_ATTR_NAME,
- IMGTOOLINFO_PTR_GET_ICON_INFO,
- IMGTOOLINFO_PTR_SUGGEST_TRANSFER,
- IMGTOOLINFO_PTR_GET_CHAIN,
- IMGTOOLINFO_PTR_GET_SECTOR_SIZE,
- IMGTOOLINFO_PTR_GET_GEOMETRY,
- IMGTOOLINFO_PTR_READ_SECTOR,
- IMGTOOLINFO_PTR_WRITE_SECTOR,
- IMGTOOLINFO_PTR_READ_BLOCK,
- IMGTOOLINFO_PTR_WRITE_BLOCK,
- IMGTOOLINFO_PTR_APPROVE_FILENAME_CHAR,
- IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE,
- IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE,
- IMGTOOLINFO_PTR_MAKE_CLASS,
- IMGTOOLINFO_PTR_LIST_PARTITIONS,
-
- IMGTOOLINFO_PTR_CLASS_SPECIFIC = 0x18000,
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- IMGTOOLINFO_STR_FIRST = 0x20000,
-
- IMGTOOLINFO_STR_NAME,
- IMGTOOLINFO_STR_DESCRIPTION,
- IMGTOOLINFO_STR_FILE,
- IMGTOOLINFO_STR_FILE_EXTENSIONS,
- IMGTOOLINFO_STR_EOLN,
- IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC,
- IMGTOOLINFO_STR_WRITEFILE_OPTSPEC,
-
- IMGTOOLINFO_STR_CLASS_SPECIFIC = 0x28000
-};
-
-
-
-union imgtoolinfo;
-
-struct imgtool_class;
-typedef void (*imgtool_get_info)(const imgtool_class *, UINT32, union imgtoolinfo *);
-
-struct imgtool_class
-{
- imgtool_get_info get_info;
- imgtool_get_info derived_get_info;
- void *derived_param;
-};
-
-
-
-struct imgtool_partition_info
-{
- imgtool_get_info get_info;
- UINT64 base_block;
- UINT64 block_count;
-};
-
-
-
-union imgtoolinfo
-{
- INT64 i; /* generic integers */
- void * p; /* generic pointers */
- void * f; /* generic function pointers */
- char * s; /* generic strings */
-
- imgtoolerr_t (*open) (imgtool_image *image, imgtool_stream *stream);
- void (*close) (imgtool_image *image);
- imgtoolerr_t (*create) (imgtool_image *image, imgtool_stream *stream, option_resolution *opts);
- imgtoolerr_t (*create_partition) (imgtool_image *image, UINT64 first_block, UINT64 block_count);
- void (*info) (imgtool_image *image, char *string, size_t len);
- imgtoolerr_t (*begin_enum) (imgtool_directory *enumeration, const char *path);
- imgtoolerr_t (*next_enum) (imgtool_directory *enumeration, imgtool_dirent *ent);
- void (*close_enum) (imgtool_directory *enumeration);
- imgtoolerr_t (*open_partition) (imgtool_partition *partition, UINT64 first_block, UINT64 block_count);
- imgtoolerr_t (*free_space) (imgtool_partition *partition, UINT64 *size);
- imgtoolerr_t (*read_file) (imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf);
- imgtoolerr_t (*write_file) (imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts);
- imgtoolerr_t (*delete_file) (imgtool_partition *partition, const char *filename);
- imgtoolerr_t (*list_forks) (imgtool_partition *partition, const char *path, imgtool_forkent *ents, size_t len);
- imgtoolerr_t (*create_dir) (imgtool_partition *partition, const char *path);
- imgtoolerr_t (*delete_dir) (imgtool_partition *partition, const char *path);
- imgtoolerr_t (*list_attrs) (imgtool_partition *partition, const char *path, UINT32 *attrs, size_t len);
- imgtoolerr_t (*get_attrs) (imgtool_partition *partition, const char *path, const UINT32 *attrs, imgtool_attribute *values);
- imgtoolerr_t (*set_attrs) (imgtool_partition *partition, const char *path, const UINT32 *attrs, const imgtool_attribute *values);
- imgtoolerr_t (*attr_name) (UINT32 attribute, const imgtool_attribute *attr, char *buffer, size_t buffer_len);
- imgtoolerr_t (*get_iconinfo) (imgtool_partition *partition, const char *path, imgtool_iconinfo *iconinfo);
- imgtoolerr_t (*suggest_transfer) (imgtool_partition *partition, const char *path, imgtool_transfer_suggestion *suggestions, size_t suggestions_length);
- imgtoolerr_t (*get_chain) (imgtool_partition *partition, const char *path, imgtool_chainent *chain, size_t chain_size);
- imgtoolerr_t (*get_sector_size) (imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, UINT32 *sector_size);
- imgtoolerr_t (*get_geometry) (imgtool_image *image, UINT32 *tracks, UINT32 *heads, UINT32 *sectors);
- imgtoolerr_t (*read_sector) (imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, void *buffer, size_t len);
- imgtoolerr_t (*write_sector) (imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, const void *buffer, size_t len, int ddam);
- imgtoolerr_t (*read_block) (imgtool_image *image, void *buffer, UINT64 block);
- imgtoolerr_t (*write_block) (imgtool_image *image, const void *buffer, UINT64 block);
- imgtoolerr_t (*list_partitions) (imgtool_image *image, imgtool_partition_info *partitions, size_t len);
- int (*approve_filename_char)(unicode_char ch);
- int (*make_class)(int index, imgtool_class *imgclass);
-
- const option_guide *createimage_optguide;
- const option_guide *writefile_optguide;
-};
-
-
-
-INLINE INT64 imgtool_get_info_int(const imgtool_class *imgclass, UINT32 state)
-{
- union imgtoolinfo info;
- info.i = 0;
- imgclass->get_info(imgclass, state, &info);
- return info.i;
-}
-
-INLINE void *imgtool_get_info_ptr(const imgtool_class *imgclass, UINT32 state)
-{
- union imgtoolinfo info;
- info.p = NULL;
- imgclass->get_info(imgclass, state, &info);
- return info.p;
-}
-
-INLINE void *imgtool_get_info_fct(const imgtool_class *imgclass, UINT32 state)
-{
- union imgtoolinfo info;
- info.f = NULL;
- imgclass->get_info(imgclass, state, &info);
- return info.f;
-}
-
-INLINE char *imgtool_get_info_string(const imgtool_class *imgclass, UINT32 state)
-{
- union imgtoolinfo info;
- info.s = NULL;
- imgclass->get_info(imgclass, state, &info);
- return info.s;
-}
-
-/* circular string buffer */
-char *imgtool_temp_str(void);
-
-
-
-struct imgtool_module
-{
- imgtool_module *previous;
- imgtool_module *next;
-
- imgtool_class imgclass;
-
- const char *name;
- const char *description;
- const char *extensions;
- const char *eoln;
-
- size_t image_extra_bytes;
-
- /* flags */
- unsigned int initial_path_separator : 1;
- unsigned int open_is_strict : 1;
- unsigned int tracks_are_called_cylinders : 1; /* used for hard drivers */
- unsigned int writing_untested : 1; /* used when we support writing, but not in main build */
- unsigned int creation_untested : 1; /* used when we support creation, but not in main build */
-
- imgtoolerr_t (*open) (imgtool_image *image, imgtool_stream *f);
- void (*close) (imgtool_image *image);
- void (*info) (imgtool_image *image, char *string, size_t len);
- imgtoolerr_t (*create) (imgtool_image *image, imgtool_stream *f, option_resolution *opts);
- imgtoolerr_t (*get_sector_size)(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, UINT32 *sector_size);
- imgtoolerr_t (*get_geometry) (imgtool_image *image, UINT32 *track, UINT32 *heads, UINT32 *sectors);
- imgtoolerr_t (*read_sector) (imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, void *buffer, size_t len);
- imgtoolerr_t (*write_sector) (imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, const void *buffer, size_t len);
- imgtoolerr_t (*read_block) (imgtool_image *image, void *buffer, UINT64 block);
- imgtoolerr_t (*write_block) (imgtool_image *image, const void *buffer, UINT64 block);
- imgtoolerr_t (*list_partitions)(imgtool_image *image, imgtool_partition_info *partitions, size_t len);
-
- UINT32 block_size;
-
- const option_guide *createimage_optguide;
- const char *createimage_optspec;
-
- const void *extra;
-};
-
-/* creates an imgtool library */
-imgtool_library *imgtool_library_create(void);
-
-/* closes an imgtool library */
-void imgtool_library_close(imgtool_library *library);
-
-/* adds a module to an imgtool library */
-void imgtool_library_add(imgtool_library *library, imgtool_get_info get_info);
-
-/* seeks out and removes a module from an imgtool library */
-const imgtool_module *imgtool_library_unlink(imgtool_library *library,
- const char *module);
-
-/* sorts an imgtool library */
-void imgtool_library_sort(imgtool_library *library, imgtool_libsort_t sort);
-
-/* finds a module */
-const imgtool_module *imgtool_library_findmodule(
- imgtool_library *library, const char *module_name);
-
-/* memory allocators for pooled library memory */
-void *imgtool_library_malloc(imgtool_library *library, size_t mem);
-char *imgtool_library_strdup(imgtool_library *library, const char *s);
-char *imgtool_library_strdup_allow_null(imgtool_library *library, const char *s);
-
-imgtool_module *imgtool_library_iterate(
- imgtool_library *library, const imgtool_module *module);
-imgtool_module *imgtool_library_index(
- imgtool_library *library, int i);
-
-#endif /* LIBRARY_H */
diff --git a/src/mess/tools/imgtool/main.c b/src/mess/tools/imgtool/main.c
deleted file mode 100644
index 6825b71fa81..00000000000
--- a/src/mess/tools/imgtool/main.c
+++ /dev/null
@@ -1,972 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- main.c
-
- Imgtool command line front end
-
-***************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include "imgtool.h"
-#include "main.h"
-#include "modules.h"
-/* ---------------------------------------------------------------------- */
-
-static void writeusage(FILE *f, int write_word_usage, const struct command *c, char *argv[])
-{
- fprintf(f, "%s %s %s %s\n",
- (write_word_usage ? "Usage:" : " "),
- imgtool_basename(argv[0]),
- c->name,
- c->usage ? c->usage : "");
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static int parse_options(int argc, char *argv[], int minunnamed, int maxunnamed,
- option_resolution *resolution, filter_getinfoproc *filter, const char **fork)
-{
- int i;
- int lastunnamed = 0;
- char *s;
- char *name = NULL;
- char *value = NULL;
- optreserr_t oerr;
- static char buf[256];
-
- if (filter)
- *filter = NULL;
- if (fork)
- *fork = NULL;
-
- for (i = 0; i < argc; i++)
- {
- /* Named or unamed arg */
- if ((argv[i][0] != '-') || (argv[i][1] != '-'))
- {
- /* Unnamed */
- if (i >= maxunnamed)
- goto error; /* Too many unnamed */
- lastunnamed = i + 1;
- }
- else
- {
- /* Named */
- name = argv[i] + 2;
- s = strchr(name, '=');
- if (!s)
- goto error;
- *s = 0;
- value = s + 1;
-
- if (!strcmp(name, "filter"))
- {
- /* filter option */
- if (!filter)
- goto error; /* this command doesn't use filters */
- if (*filter)
- goto optionalreadyspecified;
- *filter = filter_lookup(value);
- if (!(*filter))
- goto filternotfound;
-
- }
- else if (!strcmp(name, "fork"))
- {
- /* fork option */
- if (!fork)
- goto error; /* this command doesn't use filters */
- if (*fork)
- goto optionalreadyspecified;
-
- snprintf(buf, ARRAY_LENGTH(buf), "%s", value);
- *fork = buf;
- }
- else
- {
- /* Other named option */
- if (i < minunnamed)
- goto error; /* Too few unnamed */
-
- oerr = option_resolution_add_param(resolution, name, value);
- if (oerr)
- goto opterror;
- }
- }
- }
- return lastunnamed;
-
-filternotfound:
- fprintf(stderr, "%s: Unknown filter type\n", value);
- return -1;
-
-optionalreadyspecified:
- fprintf(stderr, "Cannot specify multiple %ss\n", name);
- return -1;
-
-opterror:
- fprintf(stderr, "%s: %s\n", name, option_resolution_error_string(oerr));
- return -1;
-
-error:
- fprintf(stderr, "%s: Unrecognized option\n", argv[i]);
- return -1;
-}
-
-
-
-void reporterror(imgtoolerr_t err, const struct command *c, const char *format, const char *imagename,
- const char *filename, const char *newname, option_resolution *opts)
-{
- const char *src = "imgtool";
- const char *err_name;
-
- err_name = imgtool_error(err);
-
- switch(ERRORSOURCE(err)) {
- case IMGTOOLERR_SRC_MODULE:
- src = format;
- break;
- case IMGTOOLERR_SRC_FUNCTIONALITY:
- src = c->name;
- break;
- case IMGTOOLERR_SRC_IMAGEFILE:
- src = imagename;
- break;
- case IMGTOOLERR_SRC_FILEONIMAGE:
- src = filename;
- break;
- case IMGTOOLERR_SRC_NATIVEFILE:
- src = newname ? newname : filename;
- break;
- }
- fflush(stdout);
- fflush(stderr);
-
- if (!src)
- src = c->name;
- fprintf(stderr, "%s: %s\n", src, err_name);
-}
-
-
-
-static const char *interpret_filename(const char *filename)
-{
- if (!strcmp(filename, "??BOOT??")
- || !strcmp(filename, "\'??BOOT??\'")
- || !strcmp(filename, "\"??BOOT??\""))
- filename = FILENAME_BOOTBLOCK;
- return filename;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static int cmd_dir(const struct command *c, int argc, char *argv[])
-{
- imgtoolerr_t err;
- int total_count, total_size, freespace_err;
- UINT64 freespace;
- imgtool_image *image = NULL;
- imgtool_partition *partition = NULL;
- imgtool_directory *imgenum = NULL;
- imgtool_dirent ent;
- char buf[512];
- char last_modified[19];
- const char *path;
- int partition_index = 0;
-
- /* attempt to open image */
- err = imgtool_image_open_byname(argv[0], argv[1], OSD_FOPEN_READ, &image);
- if (err)
- goto done;
-
- /* attempt to open partition */
- err = imgtool_partition_open(image, partition_index, &partition);
- if (err)
- goto done;
-
- path = argc > 2 ? argv[2] : NULL;
-
- err = imgtool_directory_open(partition, path, &imgenum);
- if (err)
- goto done;
-
- memset(&ent, 0, sizeof(ent));
- last_modified[0] = '\0';
- total_count = 0;
- total_size = 0;
-
- fprintf(stdout, "Contents of %s:%s\n", argv[1], path ? path : "");
-
- imgtool_image_info(image, buf, sizeof(buf));
- if (buf[0])
- fprintf(stdout, "%s\n", buf);
- fprintf(stdout, "------------------------------ -------- --------------- ------------------\n");
-
- while (((err = imgtool_directory_get_next(imgenum, &ent)) == 0) && !ent.eof)
- {
- if (ent.directory)
- snprintf(buf, sizeof(buf), "<DIR>");
- else
- snprintf(buf, sizeof(buf), "%u", (unsigned int) ent.filesize);
-
- if (ent.lastmodified_time != 0)
- strftime(last_modified, sizeof(last_modified), "%d-%b-%y %H:%M:%S",
- localtime(&ent.lastmodified_time));
-
- if (ent.hardlink)
- strcat(ent.filename, " <hl>");
-
- fprintf(stdout, "%-30s %8s %15s %18s\n", ent.filename, buf, ent.attr, last_modified);
-
- if (ent.softlink && ent.softlink[0] != '\0')
- fprintf(stdout, "-> %s\n", ent.softlink);
-
- if (ent.comment && ent.comment[0] != '\0')
- fprintf(stdout, ": %s\n", ent.comment);
-
- total_count++;
- total_size += ent.filesize;
-
- memset(&ent, 0, sizeof(ent));
- }
-
- freespace_err = imgtool_partition_get_free_space(partition, &freespace);
-
- if (err)
- goto done;
-
- fprintf(stdout, "------------------------ ------ ---------------\n");
- fprintf(stdout, "%8i File(s) %8i bytes\n", total_count, total_size);
- if (!freespace_err)
- fprintf(stdout, " %8u bytes free\n", (unsigned int) freespace);
-
-done:
- if (imgenum)
- imgtool_directory_close(imgenum);
- if (partition)
- imgtool_partition_close(partition);
- if (image)
- imgtool_image_close(image);
- if (err)
- reporterror(err, c, argv[0], argv[1], NULL, NULL, NULL);
- return err ? -1 : 0;
-}
-
-
-
-static int cmd_get(const struct command *c, int argc, char *argv[])
-{
- imgtoolerr_t err;
- imgtool_image *image = NULL;
- imgtool_partition *partition = NULL;
- const char *filename;
- char *new_filename;
- int unnamedargs = 0;
- filter_getinfoproc filter;
- const char *fork;
- int partition_index = 0;
-
- err = imgtool_image_open_byname(argv[0], argv[1], OSD_FOPEN_READ, &image);
- if (err)
- goto done;
-
- err = imgtool_partition_open(image, partition_index, &partition);
- if (err)
- goto done;
-
- filename = interpret_filename(argv[2]);
-
- unnamedargs = parse_options(argc, argv, 3, 4, NULL, &filter, &fork);
- if (unnamedargs < 0)
- goto done;
-
- new_filename = (unnamedargs == 4) ? argv[3] : NULL;
-
- err = imgtool_partition_get_file(partition, filename, fork, new_filename, filter);
- if (err)
- goto done;
-
- err = IMGTOOLERR_SUCCESS;
-
-done:
- if (err)
- reporterror(err, c, argv[0], argv[1], argv[2], argv[3], NULL);
- if (partition)
- imgtool_partition_close(partition);
- if (image)
- imgtool_image_close(image);
- return (err || (unnamedargs < 0)) ? -1 : 0;
-}
-
-
-
-static int cmd_put(const struct command *c, int argc, char *argv[])
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- int i;
- imgtool_image *image = NULL;
- imgtool_partition *partition = NULL;
- const char *filename = NULL;
- int unnamedargs;
- filter_getinfoproc filter;
- const imgtool_module *module;
- option_resolution *resolution = NULL;
- const char *fork;
- const char *new_filename;
- char **filename_list;
- int filename_count;
- int partition_index = 0;
- const option_guide *writefile_optguide;
- const char *writefile_optspec;
-
- module = imgtool_find_module(argv[0]);
- if (!module)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_MODULENOTFOUND | IMGTOOLERR_SRC_MODULE);
- goto done;
- }
-
- /* ugh I hate the way this function is set up, this is because the
- * arguments depend on the partition; something that requires some
- * rudimentary parsing */
- if (argc >= 2)
- {
- /* open up the image */
- err = imgtool_image_open(module, argv[1], OSD_FOPEN_RW, &image);
- if (err)
- goto done;
-
- /* open up the partition */
- err = imgtool_partition_open(image, partition_index, &partition);
- if (err)
- goto done;
-
- writefile_optguide = (const option_guide *) imgtool_partition_get_info_ptr(partition, IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE);
- writefile_optspec = (const char *)imgtool_partition_get_info_ptr(partition, IMGTOOLINFO_STR_WRITEFILE_OPTSPEC);
-
- if (writefile_optguide && writefile_optspec)
- {
- resolution = option_resolution_create(writefile_optguide, writefile_optspec);
- if (!resolution)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
- }
- }
-
- unnamedargs = parse_options(argc, argv, 4, 0xffff, resolution, &filter, &fork);
- if (unnamedargs < 0)
- return -1;
-
- /* pick out which args are filenames, and which one is the destination */
- new_filename = interpret_filename(argv[unnamedargs - 1]);
- filename_list = &argv[2];
- filename_count = unnamedargs - 3;
-
- /* loop through the filenames, and put them */
- for (i = 0; i < filename_count; i++)
- {
- filename = filename_list[i];
- printf("Putting file '%s'...\n", filename);
- err = imgtool_partition_put_file(partition, new_filename, fork, filename, resolution, filter);
- if (err)
- goto done;
- }
-
-done:
- if (partition)
- imgtool_partition_close(partition);
- if (image)
- imgtool_image_close(image);
- if (resolution)
- option_resolution_close(resolution);
- if (err)
- reporterror(err, c, argv[0], argv[1], filename, NULL, resolution);
- return err ? -1 : 0;
-}
-
-
-
-static int cmd_getall(const struct command *c, int argc, char *argv[])
-{
- imgtoolerr_t err;
- imgtool_image *image = NULL;
- imgtool_partition *partition = NULL;
- imgtool_directory *imgenum = NULL;
- imgtool_dirent ent;
- filter_getinfoproc filter;
- int unnamedargs;
- const char *path = NULL;
- int arg;
- int partition_index = 0;
-
- err = imgtool_image_open_byname(argv[0], argv[1], OSD_FOPEN_READ, &image);
- if (err)
- goto done;
-
- err = imgtool_partition_open(image, partition_index, &partition);
- if (err)
- goto done;
-
- arg = 2;
- if ((argc > 2) && (argv[2][0] != '-'))
- {
- path = argv[arg++];
- }
-
- unnamedargs = parse_options(argc, argv, arg, arg, NULL, &filter, NULL);
- if (unnamedargs < 0)
- goto done;
-
- err = imgtool_directory_open(partition, path, &imgenum);
- if (err)
- goto done;
-
- memset(&ent, 0, sizeof(ent));
-
- while (((err = imgtool_directory_get_next(imgenum, &ent)) == 0) && !ent.eof)
- {
- fprintf(stdout, "Retrieving %s (%u bytes)\n", ent.filename, (unsigned int) ent.filesize);
-
- err = imgtool_partition_get_file(partition, ent.filename, NULL, NULL, filter);
- if (err)
- goto done;
- }
-
-done:
- if (imgenum)
- imgtool_directory_close(imgenum);
- if (partition)
- imgtool_partition_close(partition);
- if (image)
- imgtool_image_close(image);
- if (err)
- reporterror(err, c, argv[0], argv[1], NULL, NULL, NULL);
- return err ? -1 : 0;
-}
-
-
-
-static int cmd_del(const struct command *c, int argc, char *argv[])
-{
- imgtoolerr_t err;
- imgtool_image *image = NULL;
- imgtool_partition *partition = NULL;
- int partition_index = 0;
-
- err = imgtool_image_open_byname(argv[0], argv[1], OSD_FOPEN_RW, &image);
- if (err)
- goto done;
-
- err = imgtool_partition_open(image, partition_index, &partition);
- if (err)
- goto done;
-
- err = imgtool_partition_delete_file(partition, argv[2]);
- if (err)
- goto done;
-
-done:
- if (partition)
- imgtool_partition_close(partition);
- if (image)
- imgtool_image_close(image);
- if (err)
- reporterror(err, c, argv[0], argv[1], argv[2], NULL, NULL);
- return err ? -1 : 0;
-}
-
-
-
-static int cmd_mkdir(const struct command *c, int argc, char *argv[])
-{
- imgtoolerr_t err;
- imgtool_image *image = NULL;
- imgtool_partition *partition = NULL;
- int partition_index = 0;
-
- err = imgtool_image_open_byname(argv[0], argv[1], OSD_FOPEN_RW, &image);
- if (err)
- goto done;
-
- err = imgtool_partition_open(image, partition_index, &partition);
- if (err)
- goto done;
-
- err = imgtool_partition_create_directory(partition, argv[2]);
- if (err)
- goto done;
-
-done:
- if (partition)
- imgtool_partition_close(partition);
- if (image)
- imgtool_image_close(image);
- if (err)
- reporterror(err, c, argv[0], argv[1], argv[2], NULL, NULL);
- return err ? -1 : 0;
-}
-
-
-
-static int cmd_rmdir(const struct command *c, int argc, char *argv[])
-{
- imgtoolerr_t err;
- imgtool_image *image = NULL;
- imgtool_partition *partition = NULL;
- int partition_index = 0;
-
- err = imgtool_image_open_byname(argv[0], argv[1], OSD_FOPEN_RW, &image);
- if (err)
- goto done;
-
- err = imgtool_partition_open(image, partition_index, &partition);
- if (err)
- goto done;
-
- err = imgtool_partition_delete_directory(partition, argv[2]);
- if (err)
- goto done;
-
-done:
- if (partition)
- imgtool_partition_close(partition);
- if (image)
- imgtool_image_close(image);
- if (err)
- reporterror(err, c, argv[0], argv[1], argv[2], NULL, NULL);
- return err ? -1 : 0;
-}
-
-
-
-static int cmd_identify(const struct command *c, int argc, char *argv[])
-{
- imgtool_module *modules[128];
- imgtoolerr_t err;
- int i;
-
- err = imgtool_identify_file(argv[0], modules, ARRAY_LENGTH(modules));
- if (err)
- goto error;
-
- for (i = 0; modules[i]; i++)
- {
- printf("%.16s %s\n", modules[i]->name, modules[i]->description);
- }
-
- return 0;
-
-error:
- reporterror(err, c, NULL, argv[0], NULL, NULL, 0);
- return -1;
-}
-
-
-
-static int cmd_create(const struct command *c, int argc, char *argv[])
-{
- imgtoolerr_t err;
- int unnamedargs;
- const imgtool_module *module;
- option_resolution *resolution = NULL;
-
- module = imgtool_find_module(argv[0]);
- if (!module)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_MODULENOTFOUND | IMGTOOLERR_SRC_MODULE);
- goto error;
- }
-
- if (module->createimage_optguide && module->createimage_optspec)
- {
- resolution = option_resolution_create(module->createimage_optguide, module->createimage_optspec);
- if (!resolution)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto error;
- }
- }
-
- unnamedargs = parse_options(argc, argv, 2, 3, resolution, NULL, NULL);
- if (unnamedargs < 0)
- return -1;
-
- err = imgtool_image_create(module, argv[1], resolution, NULL);
- if (err)
- goto error;
-
- if (resolution)
- option_resolution_close(resolution);
- return 0;
-
-error:
- if (resolution)
- option_resolution_close(resolution);
- reporterror(err, c, argv[0], argv[1], NULL, NULL, 0);
- return -1;
-}
-
-
-
-static int cmd_readsector(const struct command *c, int argc, char *argv[])
-{
- imgtoolerr_t err;
- imgtool_image *img;
- imgtool_stream *stream = NULL;
- dynamic_buffer buffer;
- UINT32 size, track, head, sector;
-
- /* attempt to open image */
- err = imgtool_image_open_byname(argv[0], argv[1], OSD_FOPEN_READ, &img);
- if (err)
- goto done;
-
- track = atoi(argv[2]);
- head = atoi(argv[3]);
- sector = atoi(argv[4]);
-
- err = imgtool_image_get_sector_size(img, track, head, sector, &size);
- if (err)
- goto done;
-
- buffer.resize(size);
-
- err = imgtool_image_read_sector(img, track, head, sector, &buffer[0], size);
- if (err)
- goto done;
-
-
- stream = stream_open(argv[5], OSD_FOPEN_WRITE);
- if (!stream)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_FILENOTFOUND | IMGTOOLERR_SRC_NATIVEFILE);
- goto done;
- }
-
- stream_write(stream, &buffer[0], size);
-
-done:
- if (stream)
- stream_close(stream);
- if (err)
- reporterror(err, c, argv[0], argv[1], NULL, NULL, 0);
- return err ? -1 : 0;
-}
-
-
-
-static int cmd_writesector(const struct command *c, int argc, char *argv[])
-{
- imgtoolerr_t err;
- imgtool_image *img;
- imgtool_stream *stream = NULL;
- dynamic_buffer buffer;
- UINT32 size, track, head, sector;
-
- /* attempt to open image */
- err = imgtool_image_open_byname(argv[0], argv[1], OSD_FOPEN_RW, &img);
- if (err)
- goto done;
-
- track = atoi(argv[2]);
- head = atoi(argv[3]);
- sector = atoi(argv[4]);
-
- stream = stream_open(argv[5], OSD_FOPEN_READ);
- if (!stream)
- {
- err = (imgtoolerr_t)(IMGTOOLERR_FILENOTFOUND | IMGTOOLERR_SRC_NATIVEFILE);
- goto done;
- }
-
- size = (UINT32) stream_size(stream);
-
- buffer.resize(size);
-
- stream_read(stream, &buffer[0], size);
-
- err = imgtool_image_write_sector(img, track, head, sector, &buffer[0], size);
- if (err)
- goto done;
-
-done:
- if (stream)
- stream_close(stream);
- if (err)
- reporterror(err, c, argv[0], argv[1], NULL, NULL, 0);
- return err ? -1 : 0;
-}
-
-
-
-static int cmd_listformats(const struct command *c, int argc, char *argv[])
-{
- const imgtool_module *mod;
-
- fprintf(stdout, "Image formats supported by imgtool:\n\n");
-
- mod = imgtool_find_module(NULL);
- while(mod)
- {
- fprintf(stdout, " %-25s%s\n", mod->name, mod->description);
- mod = mod->next;
- }
-
- return 0;
-}
-
-
-
-static int cmd_listfilters(const struct command *c, int argc, char *argv[])
-{
- int i;
-
- fprintf(stdout, "Filters supported by imgtool:\n\n");
-
- for (i = 0; filters[i]; i++)
- {
- fprintf(stdout, " %-11s%s\n",
- filter_get_info_string(filters[i], FILTINFO_STR_NAME),
- filter_get_info_string(filters[i], FILTINFO_STR_HUMANNAME));
- }
-
- return 0;
-}
-
-static void listoptions(const option_guide *opt_guide, const char *opt_spec)
-{
- char opt_name[32];
- const char *opt_desc;
- struct OptionRange range[32];
- char range_buffer[512];
- char buf[32];
- int i;
-
- assert(opt_guide);
-
- fprintf(stdout, "Option Allowed values Description\n");
- fprintf(stdout, "---------------- ------------------------------ -----------\n");
-
- while(opt_guide->option_type != OPTIONTYPE_END)
- {
- range_buffer[0] = 0;
- snprintf(opt_name, ARRAY_LENGTH(opt_name), "--%s", opt_guide->identifier);
- opt_desc = opt_guide->display_name;
-
- /* is this option relevant? */
- if (!strchr(opt_spec, opt_guide->parameter))
- {
- opt_guide++;
- continue;
- }
-
- switch(opt_guide->option_type) {
- case OPTIONTYPE_INT:
- option_resolution_listranges(opt_spec, opt_guide->parameter,
- range, ARRAY_LENGTH(range));
-
- for (i = 0; range[i].max >= 0; i++)
- {
- if (range[i].min == range[i].max)
- snprintf(buf, ARRAY_LENGTH(buf), "%i", range[i].min);
- else
- snprintf(buf, ARRAY_LENGTH(buf), "%i-%i", range[i].min, range[i].max);
-
- if (i > 0)
- strncatz(range_buffer, "/", sizeof(range_buffer));
- strncatz(range_buffer, buf, sizeof(range_buffer));
- }
- break;
-
- case OPTIONTYPE_ENUM_BEGIN:
- i = 0;
- while(opt_guide[1].option_type == OPTIONTYPE_ENUM_VALUE)
- {
- if (i > 0)
- strncatz(range_buffer, "/", sizeof(range_buffer));
- strncatz(range_buffer, opt_guide[1].identifier, sizeof(range_buffer));
-
- opt_guide++;
- i++;
- }
- break;
-
- case OPTIONTYPE_STRING:
- snprintf(range_buffer, sizeof(range_buffer), "(string)");
- break;
- default:
- assert(0);
- break;
- }
-
- fprintf(stdout, "%16s %-30s %s\n",
- opt_name,
- range_buffer,
- opt_desc);
- opt_guide++;
- }
-}
-
-
-
-static int cmd_listdriveroptions(const struct command *c, int argc, char *argv[])
-{
- const imgtool_module *mod;
- const option_guide *opt_guide;
- const char *opt_spec;
-
- mod = imgtool_find_module(argv[0]);
- if (!mod)
- goto error;
-
- fprintf(stdout, "Driver specific options for module '%s':\n\n", argv[0]);
-
- /* list write options */
- opt_guide = (const option_guide *) imgtool_get_info_ptr(&mod->imgclass, IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE);
- opt_spec = imgtool_get_info_string(&mod->imgclass, IMGTOOLINFO_STR_WRITEFILE_OPTSPEC);
- if (opt_guide)
- {
- fprintf(stdout, "Image specific file options (usable on the 'put' command):\n\n");
- listoptions(opt_guide, opt_spec);
- puts("\n");
- }
- else
- {
- fprintf(stdout, "No image specific file options\n\n");
- }
-
- /* list create options */
- opt_guide = mod->createimage_optguide;
- if (opt_guide)
- {
- fprintf(stdout, "Image specific creation options (usable on the 'create' command):\n\n");
- listoptions(opt_guide, mod->createimage_optspec);
- puts("\n");
- }
- else
- {
- fprintf(stdout, "No image specific creation options\n\n");
- }
-
- return 0;
-
-error:
- reporterror((imgtoolerr_t)(IMGTOOLERR_MODULENOTFOUND|IMGTOOLERR_SRC_MODULE), c, argv[0], NULL, NULL, NULL, NULL);
- return -1;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static const struct command cmds[] =
-{
- { "create", cmd_create, "<format> <imagename> [--(createoption)=value]", 2, 8, 0},
- { "dir", cmd_dir, "<format> <imagename> [path]", 2, 3, 0 },
- { "get", cmd_get, "<format> <imagename> <filename> [newname] [--filter=filter] [--fork=fork]", 3, 4, 0 },
- { "put", cmd_put, "<format> <imagename> <filename>... <destname> [--(fileoption)==value] [--filter=filter] [--fork=fork]", 3, 0xffff, 0 },
- { "getall", cmd_getall, "<format> <imagename> [path] [--filter=filter]", 2, 3, 0 },
- { "del", cmd_del, "<format> <imagename> <filename>...", 3, 3, 1 },
- { "mkdir", cmd_mkdir, "<format> <imagename> <dirname>", 3, 3, 0 },
- { "rmdir", cmd_rmdir, "<format> <imagename> <dirname>...", 3, 3, 1 },
- { "readsector", cmd_readsector, "<format> <imagename> <track> <head> <sector> <filename>", 6, 6, 0 },
- { "writesector", cmd_writesector, "<format> <imagename> <track> <head> <sector> <filename>", 6, 6, 0 },
- { "identify", cmd_identify, "<imagename>", 1, 1 },
- { "listformats", cmd_listformats, NULL, 0, 0, 0 },
- { "listfilters", cmd_listfilters, NULL, 0, 0, 0 },
- { "listdriveroptions", cmd_listdriveroptions, "<format>", 1, 1, 0 }
-};
-
-int CLIB_DECL main(int argc, char *argv[])
-{
- int i;
- int result;
- const struct command *c;
- const char *sample_format = "coco_jvc_rsdos";
-
-#ifdef MAME_DEBUG
- if (imgtool_validitychecks())
- return -1;
-#endif /* MAME_DEBUG */
-
- putchar('\n');
-
- if (argc > 1)
- {
- /* figure out what command they are running, and run it */
- for (i = 0; i < ARRAY_LENGTH(cmds); i++)
- {
- c = &cmds[i];
- if (!core_stricmp(c->name, argv[1]))
- {
- /* check argument count */
- if (c->minargs > (argc - 2))
- goto cmderror;
-
- /* initialize the imgtool core */
- imgtool_init(TRUE, NULL);
-
- if (c->lastargrepeats && (argc > c->maxargs))
- {
- for (i = c->maxargs+1; i < argc; i++)
- {
- argv[c->maxargs+1] = argv[i];
-
- result = c->cmdproc(c, c->maxargs, argv + 2);
- if (result)
- goto done;
- }
- result = 0;
- goto done;
- }
- else
- {
- if ((c->maxargs > 0) && (c->maxargs < (argc - 2)))
- goto cmderror;
-
- result = c->cmdproc(c, argc - 2, argv + 2);
- goto done;
- }
- }
- }
- }
-
- /* Usage */
- fprintf(stderr, "imgtool - Generic image manipulation tool for use with MESS\n\n");
- for (i = 0; i < ARRAY_LENGTH(cmds); i++)
- {
- writeusage(stdout, (i == 0), &cmds[i], argv);
- }
-
- fprintf(stderr, "\n<format> is the image format, e.g. %s\n", sample_format);
- fprintf(stderr, "<imagename> is the image filename; can specify a ZIP file for image name\n");
-
- fprintf(stderr, "\nExample usage:\n");
- fprintf(stderr, "\t%s dir %s myimageinazip.zip\n", imgtool_basename(argv[0]), sample_format);
- fprintf(stderr, "\t%s get %s myimage.dsk myfile.bin mynewfile.txt\n", imgtool_basename(argv[0]), sample_format);
- fprintf(stderr, "\t%s getall %s myimage.dsk\n", imgtool_basename(argv[0]), sample_format);
- result = 0;
- goto done;
-
-cmderror:
- writeusage(stdout, 1, &cmds[i], argv);
- result = -1;
-
-done:
- imgtool_exit();
- return result;
-}
diff --git a/src/mess/tools/imgtool/main.h b/src/mess/tools/imgtool/main.h
deleted file mode 100644
index d4089686437..00000000000
--- a/src/mess/tools/imgtool/main.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-#include "imgtool.h"
-
-struct command
-{
- const char *name;
- int (*cmdproc)(const struct command *c, int argc, char *argv[]);
- const char *usage;
- int minargs;
- int maxargs;
- int lastargrepeats;
-};
-
-void reporterror(imgtoolerr_t err, const struct command *c, const char *format, const char *imagename,
- const char *filename, const char *newname, option_resolution *opts);
-
-#ifdef MAME_DEBUG
-int cmd_testsuite(struct command *c, int argc, char *argv[]);
-#endif
diff --git a/src/mess/tools/imgtool/modules.c b/src/mess/tools/imgtool/modules.c
deleted file mode 100644
index e5f0c43690c..00000000000
--- a/src/mess/tools/imgtool/modules.c
+++ /dev/null
@@ -1,119 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- modules.c
-
- List of Imgtool modules
-
-***************************************************************************/
-
-#include "imgtool.h"
-#include "modules.h"
-
-#ifndef MODULES_RECURSIVE
-#define MODULES_RECURSIVE
-
-/* step 1: declare all external references */
-#define MODULE(name) extern void name##_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info);
-#include "modules.c"
-#undef MODULE
-
-/* step 2: define the modules[] array */
-#define MODULE(name) name##_get_info,
-static void (*const modules[])(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info) =
-{
-#include "modules.c"
-};
-
-/* step 3: declare imgtool_create_cannonical_library() */
-imgtoolerr_t imgtool_create_cannonical_library(int omit_untested, imgtool_library **library)
-{
- imgtoolerr_t err;
- size_t i;
- imgtool_library *lib;
- imgtool_module *module;
-
- /* list of modules that we drop */
- static const char *const irrelevant_modules[] =
- {
- "coco_os9_rsdos"
- };
-
- lib = imgtool_library_create();
- if (!lib)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto error;
- }
-
- /* create all modules */
- for (i = 0; i < ARRAY_LENGTH(modules); i++)
- imgtool_library_add(lib, modules[i]);
-
- /* remove irrelevant modules */
- for (i = 0; i < ARRAY_LENGTH(irrelevant_modules); i++)
- {
- imgtool_library_unlink(lib, irrelevant_modules[i]);
- }
-
- /* if we are omitting untested, go through and block out the functionality in question */
- if (omit_untested)
- {
- module = NULL;
- while((module = imgtool_library_iterate(lib, module)) != NULL)
- {
- if (module->writing_untested)
- {
- module->write_sector = NULL;
- }
- if (module->creation_untested)
- {
- module->create = NULL;
- module->createimage_optguide = NULL;
- module->createimage_optspec = NULL;
- }
- }
- }
-
- *library = lib;
- return IMGTOOLERR_SUCCESS;
-
-error:
- if (lib)
- imgtool_library_close(lib);
- return err;
-
-}
-
-
-#else /* MODULES_RECURSIVE */
-
-MODULE(amiga_floppy)
-MODULE(concept)
-MODULE(mac_mfs)
-MODULE(mac_hfs)
-MODULE(hd)
-MODULE(rsdos)
-MODULE(vzdos)
-MODULE(os9)
-MODULE(ti99_old)
-MODULE(ti99_v9t9)
-MODULE(ti99_pc99fm)
-MODULE(ti99_pc99mfm)
-MODULE(ti99_ti99hd)
-MODULE(ti990)
-MODULE(pc_floppy)
-MODULE(pc_chd)
-MODULE(prodos_525)
-MODULE(prodos_35)
-MODULE(thom_fd_basic)
-MODULE(thom_qd_basic)
-MODULE(thom_sap_basic)
-MODULE(cybiko)
-MODULE(cybikoxt)
-MODULE(psion)
-MODULE(bml3)
-MODULE(hp48)
-
-#endif /* MODULES_RECURSIVE */
diff --git a/src/mess/tools/imgtool/modules.h b/src/mess/tools/imgtool/modules.h
deleted file mode 100644
index 6f5a3786c6b..00000000000
--- a/src/mess/tools/imgtool/modules.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/****************************************************************************
-
- modules.h
-
- Code that creates the "canonical" Imgtool library
-
-****************************************************************************/
-
-#ifndef MODULES_H
-#define MODULES_H
-
-#include "library.h"
-
-imgtoolerr_t imgtool_create_cannonical_library(int omit_untested, imgtool_library **library);
-
-#endif /* MODULES_H */
diff --git a/src/mess/tools/imgtool/modules/amiga.c b/src/mess/tools/imgtool/modules/amiga.c
deleted file mode 100644
index 7723748cbd2..00000000000
--- a/src/mess/tools/imgtool/modules/amiga.c
+++ /dev/null
@@ -1,2411 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
-/****************************************************************************
-
- amiga.c
-
- Amiga floppies
-
-****************************************************************************/
-
-
-/*****************************************************************************
- Includes
-*****************************************************************************/
-
-
-#include <time.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "imgtool.h"
-#include "iflopimg.h"
-#include "formats/imageutl.h"
-
-
-
-/*****************************************************************************
- Data structures
-*****************************************************************************/
-
-
-#define BSIZE (512) /* Block size is always 512 bytes for floppies */
-#define TSIZE ((BSIZE/4) - 56) /* Size of data tables */
-#define MSIZE ((BSIZE/4) - 1) /* Size of bitmaps */
-
-
-enum disk_type
-{
- DT_UNKNOWN = -1,
- DT_OFS = 0,
- DT_FFS = 1,
- DT_OFS_INTL = 2,
- DT_FFS_INTL = 3,
- DT_OFS_INTL_DIRC = 4,
- DT_FFS_INTL_DIRC = 5
-};
-
-
-enum
-{
- T_INVALID = 0,
- T_HEADER = 2,
- T_DATA = 8,
- T_LIST = 16,
- T_DIRCACHE = 33
-};
-
-
-enum sec_type
-{
- ST_INVALID = 0,
- ST_ROOT = 1,
- ST_USERDIR = 2,
- ST_FILE = -3,
- ST_LINKFILE = -4,
- ST_LINKDIR = 4,
- ST_SOFTLINK = 3
-};
-
-
-struct amiga_date
-{
- UINT32 days; /* days since 1 jan 78 */
- UINT32 mins; /* minutes past midnight */
- UINT32 ticks; /* ticks (1/50 sec) past last minute */
-};
-
-
-struct root_block
-{
- UINT32 ht_size; /* Hash table size in long */
- UINT32 chksum; /* Rootblock checksum */
- UINT32 ht[TSIZE]; /* Hash table (entry block number) */
- UINT32 bm_flag; /* bitmap flag, -1 means VALID */
- UINT32 bm_pages[25]; /* bitmap blocks pointers (first one at bm_pages[0]) */
- amiga_date r; /* last root alteration date */
- UINT8 name_len; /* volume name length */
- UINT8 diskname[30]; /* volume name */
- amiga_date v; /* last disk alteration date */
- amiga_date c; /* filesystem creation date */
- UINT32 extension; /* FFS: first directory cache block, 0 otherwise */
-};
-
-
-struct bitmap_block
-{
- UINT32 chksum; /* checksum, normal algorithm */
- UINT32 map[MSIZE]; /* bitmap */
-};
-
-
-struct bitmap_ext_block
-{
- UINT32 map[MSIZE]; /* bitmap */
- UINT32 next; /* next extension block */
-};
-
-
-struct file_block
-{
- UINT32 header_key; /* self pointer (to this block) */
- UINT32 high_seq; /* number of data block ptr stored here */
- UINT32 first_data; /* first data block ptr */
- UINT32 chksum; /* same algorithm as rootblock */
- UINT32 data_blocks[TSIZE]; /* data blk ptr */
- UINT16 uid; /* UserID */
- UINT16 gid; /* GroupID */
- UINT32 protect; /* protection flags (0 by default) */
- UINT32 byte_size; /* file size in bytes */
- UINT8 comm_len; /* file comment length */
- UINT8 comment[79]; /* comment (max. 79 chars permitted) */
- amiga_date date; /* last change date */
- UINT8 name_len; /* filename length */
- UINT8 filename[30]; /* filename (max. 30 chars permitted) */
- UINT32 real_entry; /* FFS: unused, set to 0 */
- UINT32 next_link; /* FFS: hardlinks chained list (first == newest */
- UINT32 hash_chain; /* next entry ptr with same hash */
- UINT32 parent; /* parent directory */
- UINT32 extension; /* pointer to 1st file extension block */
-};
-
-
-struct file_ext_block
-{
- UINT32 header_key; /* self pointer (to this block) */
- UINT32 high_seq; /* number of data block ptr stored here */
- UINT32 chksum; /* same algorithm as rootblock */
- UINT32 data_blocks[TSIZE]; /* data blk ptr */
- UINT32 parent; /* file header block */
- UINT32 extension; /* pointer to next file extension block */
-};
-
-
-struct data_block
-{
- UINT32 header_key; /* self pointer (to this block) */
- UINT32 seq_num; /* file data block number */
- UINT32 data_size; /* data size */
- UINT32 next_data; /* next data block ptr */
- UINT32 chksum; /* checksum, rootblock algorithm */
- UINT8 data[BSIZE-24]; /* file data */
-};
-
-
-struct dir_block
-{
- UINT32 header_key; /* self pointer (to this block) */
- UINT32 chksum; /* same algorithm as rootblock */
- UINT32 ht[TSIZE]; /* hash table (entry block number) */
- UINT8 uid; /* UserID */
- UINT8 gid; /* GroupID */
- UINT32 protect; /* protection flags (0 by default) */
- UINT8 comm_len; /* file comment length */
- UINT8 comment[79]; /* comment (max. 79 chars permitted) */
- amiga_date date; /* last access date */
- UINT8 name_len; /* directory name length */
- UINT8 dirname[30]; /* directory name (max. 30 chars permitted) */
- UINT32 next_link; /* FFS: hardlinks chained list (first == newest */
- UINT32 hash_chain; /* next entry ptr with same hash */
- UINT32 parent; /* parent directory */
- UINT32 extension; /* FFS: first directory cache block */
-};
-
-
-struct hardlink_block
-{
- UINT32 header_key; /* self pointer (to this block) */
- UINT32 chksum; /* same algorithm as rootblock */
- UINT32 protect; /* protection flags (0 by default) */
- UINT8 comm_len; /* file comment length */
- UINT8 comment[79]; /* comment (max. 79 chars permitted) */
- amiga_date date; /* last access date */
- UINT8 name_len; /* hard link name length */
- UINT8 hlname[30]; /* hard link name (max. 30 chars permitted) */
- UINT32 real_entry; /* FFS: pointer to "real" file or directory */
- UINT32 next_link; /* FFS: hardlinks chained list (first == newest */
- UINT32 hash_chain; /* next entry ptr with same hash */
- UINT32 parent; /* parent directory */
- UINT32 sec_type; /* secondary type, ST_LINKFILE/ST_LINKDIR */
-};
-
-
-struct softlink_block
-{
- UINT32 header_key; /* self pointer (to this block) */
- UINT32 chksum; /* same algorithm as rootblock */
- UINT8 symbolic_name[BSIZE-224]; /* path name to referenced object */
- UINT32 protect; /* protection flags (0 by default) */
- UINT8 comm_len; /* file comment length */
- UINT8 comment[79]; /* comment (max. 79 chars permitted) */
- amiga_date date; /* last access date */
- UINT8 name_len; /* soft link name length */
- UINT8 slname[30]; /* soft link name (max. 30 chars permitted) */
- UINT32 hash_chain; /* next entry ptr with same hash */
- UINT32 parent; /* parent directory */
-};
-
-
-/* Basic Amiga floppy disk image info */
-struct amiga_floppy
-{
- imgtool_stream *stream;
- UINT8 sectors;
-};
-
-
-/* iterator used to walk through directory entries */
-struct amiga_iterator
-{
- unsigned int index; /* current file index */
- int block; /* block number we are iterating */
- UINT32 next_block; /* next block in hash chain */
- int ht_index; /* current index in the hash table */
- unsigned int eof : 1; /* end of file listing reached? */
-};
-
-
-/*****************************************************************************
- Prototypes
-*****************************************************************************/
-
-
-static imgtoolerr_t amiga_image_read_sector(imgtool_image* img,
- UINT32 track, UINT32 head, UINT32 sector, void *buf, size_t len);
-static imgtoolerr_t amiga_image_write_sector(imgtool_image* img,
- UINT32 track, UINT32 head, UINT32 sector, const void *buf, size_t len, int ddam);
-
-
-
-/*****************************************************************************
- Utility functions
-*****************************************************************************/
-
-
-/* Amiga version of the toupper function */
-static int intl_toupper(int c)
-{
- return (c>='a' && c<='z') || (c>=224 && c<=254 && c!=247) ? c - ('a'-'A') : c ;
-}
-
-
-/* Amiga filename case insensitive string compare */
-static int intl_stricmp(const char *s1, const char *s2)
-{
- for (;;)
- {
- int c1 = intl_toupper(*s1++);
- int c2 = intl_toupper(*s2++);
-
- if (c1 == 0 || c1 != c2)
- return c1 - c2;
- }
-}
-
-
-/* Calculate the hash value for a filename */
-static int hash_name(const char *name, int intl)
-{
- int i, l = strlen(name);
- UINT32 hash = l;
-
- for(i = 0; i < l; i++)
- {
- hash *= 13;
- hash += (UINT8) (intl ? intl_toupper(name[i]) : toupper(name[i]));
- hash &= 0x7ff;
- }
-
- return hash % TSIZE; /* 0 < hash < 71 in case of BSIZE=512 */
-}
-
-
-/* Returns TRUE if year is a leap year */
-static int is_leap(int year)
-{
- return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
-}
-
-
-/* Convert amiga time to standard time */
-static time_t amiga_crack_time(amiga_date *date)
-{
- int month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
- int year = 1978, month = 1, year_days = 365; /* base date */
- int day = date->days;
- struct tm t;
-
- /* initialize struct */
- memset(&t, 0, sizeof(t));
-
- /* first calculate the year */
- while (day >= year_days)
- {
- day -= year_days;
- year_days = is_leap(++year) ? 366 : 365;
- }
-
- /* then the month */
- while(day >= month_days[month-1])
- {
- day -= month_days[month-1];
- if (month == 2 && is_leap(year))
- day -= 1;
- month++;
- }
-
- /* fill the struct with our calculated values */
- t.tm_year = year - 1900;
- t.tm_mon = month - 1;
- t.tm_mday = day + 1;
- t.tm_hour = date->mins / 60;
- t.tm_min = date->mins % 60;
- t.tm_sec = date->ticks / 50;
-
- return mktime(&t);
-}
-
-
-/* convert standard time to amiga time */
-static void amiga_setup_time(time_t time, amiga_date *dest)
-{
- struct tm t = *localtime(&time);
- int year;
-
- dest->days = 0;
-
- for (year = 1978; year < t.tm_year + 1900; year++)
- {
- dest->days += is_leap(year) ? 366 : 365;
- }
-
- dest->days += t.tm_yday;
- dest->mins = t.tm_hour * 60 + t.tm_min;
- dest->ticks = t.tm_sec * 50;
-}
-
-
-/* convert flags to human readable form */
-static void amiga_decode_flags(UINT32 flags, char *dest)
-{
- /* test for flags */
- dest[0] = (flags & 0x80) ? 'h' : '-';
- dest[1] = (flags & 0x40) ? 's' : '-';
- dest[2] = (flags & 0x20) ? 'p' : '-';
- dest[3] = (flags & 0x10) ? 'a' : '-';
- dest[4] = (flags & 0x08) ? '-' : 'r';
- dest[5] = (flags & 0x04) ? '-' : 'w';
- dest[6] = (flags & 0x02) ? '-' : 'e';
- dest[7] = (flags & 0x01) ? '-' : 'd';
- dest[8] = '\0';
-}
-
-
-static void copy_integer_array_be(UINT32 *dest, const UINT32 *source, int size)
-{
- int i;
-
- for (i = 0; i < size; i++)
- {
- dest[i] = BIG_ENDIANIZE_INT32(source[i]);
- }
-}
-
-
-/* This function converts an array of UINT32s to an amiga_date */
-static void copy_date_be(amiga_date *dest, const UINT32 *source)
-{
- dest->days = BIG_ENDIANIZE_INT32(source[0]);
- dest->mins = BIG_ENDIANIZE_INT32(source[1]);
- dest->ticks = BIG_ENDIANIZE_INT32(source[2]);
-}
-
-
-/* Calculate the block checksum of a byte array */
-static UINT32 block_checksum(UINT8 *buffer, int length)
-{
- UINT32 chksum = 0;
- int i;
-
- for (i = 0; i < length/4; i++)
- {
- chksum += pick_integer_be(buffer, i*4, 4);
- }
-
- return -chksum;
-}
-
-
-/* Returns the total number of blocks in the image */
-static int get_total_blocks(imgtool_image *img)
-{
- amiga_floppy *f = (amiga_floppy *)imgtool_image_extra_bytes(img);
-
- return 2 * 80 * f->sectors;
-}
-
-
-/* Returns track, head and sector for a block */
-static void find_block(amiga_floppy *f, int block, int *track,
- int *head, int *sector)
-{
- *track = block / f->sectors;
- *head = (block - *track * f->sectors) / f->sectors;
- *sector = (block - *track * f->sectors) % f->sectors;
-}
-
-
-/* Generic read block */
-static imgtoolerr_t read_block(imgtool_image *img, int block, UINT8 *buffer)
-{
- imgtoolerr_t ret;
- int track, head, sector;
-
- find_block((amiga_floppy *) imgtool_image_extra_bytes(img), block, &track, &head, &sector);
-
- /* get block from image */
- ret = amiga_image_read_sector(img, track, head, sector, buffer, BSIZE);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-/* Generic write block */
-static imgtoolerr_t write_block(imgtool_image *img, int block, const UINT8 *buffer)
-{
- imgtoolerr_t ret;
- int track, head, sector;
-
- find_block((amiga_floppy *) imgtool_image_extra_bytes(img), block, &track, &head, &sector);
-
- /* write block to image */
- ret = amiga_image_write_sector(img, track, head, sector, buffer, BSIZE, 0);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-/* Return the type a block */
-static sec_type get_block_type(imgtool_image *img, int block)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* get data */
- ret = read_block(img, block, buffer);
- if (ret) return ST_INVALID;
-
- /* return type */
- switch ((INT32) pick_integer_be(buffer, BSIZE-4, 4))
- {
- case 1: return ST_ROOT;
- case 2: return ST_USERDIR;
- case -3: return ST_FILE;
- case -4: return ST_LINKFILE;
- case 4: return ST_LINKDIR;
- case 3: return ST_SOFTLINK;
- default: return ST_INVALID;
- }
-}
-
-
-/* Read a bitmap block */
-static imgtoolerr_t read_bitmap_block(imgtool_image *img, int block, bitmap_block *bm)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* read block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* fill in data */
- bm->chksum = pick_integer_be(buffer, 0, 4);
- copy_integer_array_be(bm->map, (UINT32 *) &buffer[4], MSIZE);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-/* Write a bitmap block */
-static imgtoolerr_t write_bitmap_block(imgtool_image *img, int block, const bitmap_block *bm)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* Setup buffer */
- place_integer_be(buffer, 0, 4, bm->chksum);
- copy_integer_array_be((UINT32 *) &buffer[4], bm->map, MSIZE);
-
- /* write block */
- ret = write_block(img, block, buffer);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-#ifdef UNUSED_FUNCTION
-/* Read a bitmap extended block */
-static imgtoolerr_t read_bitmap_ext_block(imgtool_image *img, int block, bitmap_ext_block *bm)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* read block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* fill in data */
- copy_integer_array_be(bm->map, (UINT32 *) &buffer, MSIZE);
- bm->next = pick_integer_be(buffer, BSIZE-4, 4);
-
- return IMGTOOLERR_SUCCESS;
-}
-#endif
-
-
-/* Read the root block */
-static imgtoolerr_t read_root_block(imgtool_image *img, root_block *root)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* get raw root block from image */
- ret = read_block(img, get_total_blocks(img)/2, buffer);
- if (ret) return ret;
-
- /* copy data to root_block */
- memset(root, 0, sizeof(root_block));
-
- root->ht_size = pick_integer_be(buffer, 12, 4);
- root->chksum = pick_integer_be(buffer, 20, 4);
- copy_integer_array_be(root->ht, (UINT32 *) &buffer[24], TSIZE);
- root->bm_flag = pick_integer_be(buffer, BSIZE-200, 4);
- copy_integer_array_be(root->bm_pages, (UINT32 *) &buffer[BSIZE-196], 25);
- copy_date_be(&root->r, (UINT32 *) &buffer[BSIZE-92]);
- root->name_len = pick_integer_be(buffer, BSIZE-80, 1);
- memcpy(root->diskname, &buffer[BSIZE-79], 30);
- copy_date_be(&root->v, (UINT32 *) &buffer[BSIZE-40]);
- copy_date_be(&root->c, (UINT32 *) &buffer[BSIZE-28]);
- root->extension = pick_integer_be(buffer, BSIZE-8, 4);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t write_root_block(imgtool_image *img, const root_block *root)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* Setup buffer */
- memset(buffer, 0, BSIZE);
-
- place_integer_be(buffer, 0, 4, T_HEADER);
- place_integer_be(buffer, 12, 4, root->ht_size);
- place_integer_be(buffer, 20, 4, root->chksum);
- copy_integer_array_be((UINT32 *) &buffer[24], root->ht, TSIZE);
- place_integer_be(buffer, BSIZE-200, 4, root->bm_flag);
- copy_integer_array_be((UINT32 *) &buffer[BSIZE-196], root->bm_pages, 25);
- place_integer_be(buffer, BSIZE-92, 4, root->r.days);
- place_integer_be(buffer, BSIZE-88, 4, root->r.mins);
- place_integer_be(buffer, BSIZE-84, 4, root->r.ticks);
- place_integer_be(buffer, BSIZE-80, 1, root->name_len);
- memcpy(&buffer[BSIZE-79], root->diskname, root->name_len);
- place_integer_be(buffer, BSIZE-40, 4, root->v.days);
- place_integer_be(buffer, BSIZE-36, 4, root->v.mins);
- place_integer_be(buffer, BSIZE-32, 4, root->v.ticks);
- place_integer_be(buffer, BSIZE-28, 4, root->c.days);
- place_integer_be(buffer, BSIZE-24, 4, root->c.mins);
- place_integer_be(buffer, BSIZE-20, 4, root->c.ticks);
- place_integer_be(buffer, BSIZE-8, 4, root->extension);
- place_integer_be(buffer, BSIZE-4, 4, ST_ROOT);
-
- /* write root block to image */
- ret = write_block(img, get_total_blocks(img)/2, buffer);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-/* Read a file block */
-static imgtoolerr_t read_file_block(imgtool_image *img, int block, file_block *fb)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* read block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* fill in data */
- fb->header_key = pick_integer_be(buffer, 4, 4);
- fb->high_seq = pick_integer_be(buffer, 8, 4);
- fb->first_data = pick_integer_be(buffer, 16, 4);
- fb->chksum = pick_integer_be(buffer, 20, 4);
- copy_integer_array_be(fb->data_blocks, (UINT32 *) &buffer[24], TSIZE);
- fb->uid = pick_integer_be(buffer, BSIZE-196, 2);
- fb->gid = pick_integer_be(buffer, BSIZE-194, 2);
- fb->protect = pick_integer_be(buffer, BSIZE-192, 4);
- fb->byte_size = pick_integer_be(buffer, BSIZE-188, 4);
- fb->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
- memcpy(fb->comment, &buffer[BSIZE-183], 79);
- copy_date_be(&fb->date, (UINT32 *) &buffer[BSIZE-92]);
- fb->name_len = pick_integer_be(buffer, BSIZE-80, 1);
- memcpy(fb->filename, (UINT32 *) &buffer[BSIZE-79], 30);
- fb->real_entry = pick_integer_be(buffer, BSIZE-44, 4);
- fb->next_link = pick_integer_be(buffer, BSIZE-40, 4);
- fb->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- fb->parent = pick_integer_be(buffer, BSIZE-12, 4);
- fb->extension = pick_integer_be(buffer, BSIZE-8, 4);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t read_file_ext_block(imgtool_image *img, int block, file_ext_block *fe)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* read block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* fill in data */
- fe->header_key = pick_integer_be(buffer, 4, 4);
- fe->high_seq = pick_integer_be(buffer, 8, 4);
- fe->chksum = pick_integer_be(buffer, 20, 4);
- copy_integer_array_be(fe->data_blocks, (UINT32 *) &buffer[24], TSIZE);
- fe->parent = pick_integer_be(buffer, BSIZE-12, 4);
- fe->extension = pick_integer_be(buffer, BSIZE-8, 4);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t read_data_block(imgtool_image *img, int block, data_block *d)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* read block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* fill in data */
- d->header_key = pick_integer_be(buffer, 4, 4);
- d->seq_num = pick_integer_be(buffer, 8, 4);
- d->data_size = pick_integer_be(buffer, 12, 4);
- d->next_data = pick_integer_be(buffer, 16, 4);
- d->chksum = pick_integer_be(buffer, 20, 4);
- memcpy(d->data, &buffer[24], BSIZE-24);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-/* Read a directory block */
-static imgtoolerr_t read_dir_block(imgtool_image *img, int block, dir_block *db)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* read block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* fill in data */
- db->header_key = pick_integer_be(buffer, 4, 4);
- db->chksum = pick_integer_be(buffer, 20, 4);
- copy_integer_array_be(db->ht, (UINT32 *) &buffer[24], TSIZE);
- db->uid = pick_integer_be(buffer, BSIZE-196, 2);
- db->gid = pick_integer_be(buffer, BSIZE-194, 2);
- db->protect = pick_integer_be(buffer, BSIZE-192, 4);
- db->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
- memcpy(db->comment, &buffer[BSIZE-183], 79);
- copy_date_be(&db->date, (UINT32 *) &buffer[BSIZE-92]);
- db->name_len = pick_integer_be(buffer, BSIZE-80, 1);
- memcpy(db->dirname, (UINT32 *) &buffer[BSIZE-79], 30);
- db->next_link = pick_integer_be(buffer, BSIZE-40, 4);
- db->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- db->parent = pick_integer_be(buffer, BSIZE-12, 4);
- db->extension = pick_integer_be(buffer, BSIZE-8, 4);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t write_dir_block(imgtool_image *img, int block, const dir_block *db)
-{
- UINT8 buffer[BSIZE];
-
- /* Setup buffer */
- memset(buffer, 0, BSIZE);
-
- /* Copy data */
- place_integer_be(buffer, 0, 4, T_HEADER);
- place_integer_be(buffer, 4, 4, db->header_key);
- place_integer_be(buffer, 20, 4, db->chksum);
- copy_integer_array_be((UINT32 *) &buffer[24], db->ht, TSIZE);
- place_integer_be(buffer, BSIZE-196, 2, db->uid);
- place_integer_be(buffer, BSIZE-194, 2, db->gid);
- place_integer_be(buffer, BSIZE-192, 4, db->protect);
- place_integer_be(buffer, BSIZE-184, 1, db->comm_len);
- memcpy((UINT32 *) &buffer[BSIZE-183], db->comment, db->comm_len);
- place_integer_be(buffer, BSIZE-92, 4, db->date.days);
- place_integer_be(buffer, BSIZE-88, 4, db->date.mins);
- place_integer_be(buffer, BSIZE-84, 4, db->date.ticks);
- place_integer_be(buffer, BSIZE-80, 1, db->name_len);
- memcpy((UINT32 *) &buffer[BSIZE-79], db->dirname, db->name_len);
- place_integer_be(buffer, BSIZE-40, 4, db->next_link);
- place_integer_be(buffer, BSIZE-16, 4, db->hash_chain);
- place_integer_be(buffer, BSIZE-12, 4, db->parent);
- place_integer_be(buffer, BSIZE-8, 4, db->extension);
- place_integer_be(buffer, BSIZE-4, 4, ST_USERDIR);
-
- /* Write block to disk */
- return write_block(img, block, buffer);
-}
-
-
-static imgtoolerr_t read_hardlink_block(imgtool_image *img, int block, hardlink_block *hl)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* read block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* fill in data */
- hl->header_key = pick_integer_be(buffer, 4, 4);
- hl->chksum = pick_integer_be(buffer, 20, 4);
- hl->protect = pick_integer_be(buffer, BSIZE-192, 4);
- hl->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
- memcpy(hl->comment, &buffer[BSIZE-183], 79);
- copy_date_be(&hl->date, (UINT32 *) &buffer[BSIZE-92]);
- hl->name_len = pick_integer_be(buffer, BSIZE-80, 1);
- memcpy(hl->hlname, (UINT32 *) &buffer[BSIZE-79], 30);
- hl->real_entry = pick_integer_be(buffer, BSIZE-44, 4);
- hl->next_link = pick_integer_be(buffer, BSIZE-40, 4);
- hl->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- hl->parent = pick_integer_be(buffer, BSIZE-12, 4);
- hl->sec_type = pick_integer_be(buffer, BSIZE-4, 4);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t read_softlink_block(imgtool_image *img, int block, softlink_block *sl)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* read block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* fill in data */
- sl->header_key = pick_integer_be(buffer, 4, 4);
- sl->chksum = pick_integer_be(buffer, 20, 4);
- memcpy(sl->symbolic_name, &buffer[24], BSIZE-224);
- sl->protect = pick_integer_be(buffer, BSIZE-192, 4);
- sl->comm_len = pick_integer_be(buffer, BSIZE-184, 1);
- memcpy(sl->comment, &buffer[BSIZE-183], 79);
- copy_date_be(&sl->date, (UINT32 *) &buffer[BSIZE-92]);
- sl->name_len = pick_integer_be(buffer, BSIZE-80, 1);
- memcpy(sl->slname, (UINT32 *) &buffer[BSIZE-79], 30);
- sl->hash_chain = pick_integer_be(buffer, BSIZE-16, 4);
- sl->parent = pick_integer_be(buffer, BSIZE-12, 4);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-/* Returns the disk type */
-static disk_type get_disk_type(imgtool_image *img)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- ret = read_block(img, 0, buffer);
- if (ret) return DT_UNKNOWN;
-
- switch(buffer[3])
- {
- case 0: return DT_OFS;
- case 1: return DT_FFS;
- case 2: return DT_OFS_INTL;
- case 3: return DT_FFS_INTL;
- case 4: return DT_OFS_INTL_DIRC;
- case 5: return DT_FFS_INTL_DIRC;
- default: return DT_UNKNOWN;
- }
-}
-
-
-/* Returns TRUE if the disk is formatted with the FastFileSystem */
-static int is_ffs(imgtool_image *img)
-{
- disk_type t = get_disk_type(img);
-
- return ((t == DT_FFS ||
- t == DT_FFS_INTL ||
- t == DT_FFS_INTL_DIRC) ? TRUE : FALSE);
-}
-
-
-/* Returns TRUE if the disk uses the international mode */
-static int is_intl(imgtool_image *img)
-{
- disk_type t = get_disk_type(img);
-
- return ((t == DT_OFS_INTL ||
- t == DT_FFS_INTL ||
- t == DT_OFS_INTL_DIRC ||
- t == DT_FFS_INTL_DIRC) ? TRUE : FALSE);
-}
-
-#ifdef UNUSED_FUNCTION
-/* Returns TRUE if the disk uses the directory cache mode */
-static int is_dirc(imgtool_image *img)
-{
- disk_type t = get_disk_type(img);
-
- return ((t == DT_OFS_INTL_DIRC ||
- t == DT_FFS_INTL_DIRC) ? TRUE : FALSE);
-}
-#endif
-
-static imgtoolerr_t get_hash_table(imgtool_image *img, int block, UINT32 *ht)
-{
- imgtoolerr_t ret;
-
- switch (get_block_type(img, block))
- {
- case ST_USERDIR:
- {
- dir_block dir;
-
- /* get the directory block */
- ret = read_dir_block(img, block, &dir);
- if (ret) return ret;
-
- /* copy data */
- memcpy(ht, &dir.ht, TSIZE*4);
-
- return IMGTOOLERR_SUCCESS;
- }
-
- case ST_ROOT:
- {
- root_block root;
-
- /* get the root block */
- ret = read_root_block(img, &root);
- if (ret) return ret;
-
- /* copy data */
- memcpy(ht, &root.ht, TSIZE*4);
-
- return IMGTOOLERR_SUCCESS;
- }
-
- default:
- return IMGTOOLERR_UNEXPECTED;
- }
-}
-
-
-static imgtoolerr_t set_hash_table(imgtool_image *img, int block, const UINT32 *ht)
-{
- UINT8 buffer[BSIZE];
- imgtoolerr_t ret;
-
- /* Read block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* Copy new hash table into it */
- copy_integer_array_be((UINT32 *) &buffer[24], ht, TSIZE);
-
- /* Write it back again */
- ret = write_block(img, block, buffer);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t get_root_hash_table(imgtool_image *img, UINT32 *ht)
-{
- return get_hash_table(img, get_total_blocks(img)/2, ht);
-}
-#endif
-
-static imgtoolerr_t get_blockname(imgtool_image *img, int block, char *dest)
-{
- UINT8 buffer[BSIZE];
- imgtoolerr_t ret;
-
- /* Read the block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* Copy filename out of the buffer */
- memset(dest, 0, 31);
- memcpy(dest, &buffer[BSIZE-79], buffer[BSIZE-80]);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t get_hash_chain(imgtool_image *img, int block, UINT32 *chain)
-{
- UINT8 buffer[BSIZE];
- imgtoolerr_t ret;
-
- /* Read block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* Get chain value */
- *chain = pick_integer_be(buffer, BSIZE-16, 4);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t set_hash_chain(imgtool_image *img, int block, UINT32 chain)
-{
- UINT8 buffer[BSIZE];
- imgtoolerr_t ret;
-
- /* Read block */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* Copy new hash chain value into it */
- place_integer_be(buffer, BSIZE-16, 4, chain);
-
- /* Write it back again */
- ret = write_block(img, block, buffer);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t walk_hash_chain(imgtool_image *img, const char *path, int start_block, int *prev_block, int *block)
-{
- imgtoolerr_t err;
- UINT32 hash_chain;
- char name[31];
-
- /* choose compare function depending on intl mode */
- int (*cmp)(const char *, const char *) = is_intl(img) ? &intl_stricmp : &core_stricmp;
-
- /* initialize filenames */
- memset(name, 0, sizeof(name));
-
- switch (get_block_type(img, start_block))
- {
- case ST_USERDIR:
- {
- dir_block dir;
-
- /* read block */
- err = read_dir_block(img, start_block, &dir);
- if (err) return err;
-
- /* copy filename string and next hash */
- memcpy(name, dir.dirname, dir.name_len);
- hash_chain = dir.hash_chain;
-
- break;
- }
-
- case ST_FILE:
- {
- file_block file;
-
- /* read block */
- err = read_file_block(img, start_block, &file);
- if (err) return err;
-
- /* copy filename string and next hash */
- memcpy(name, file.filename, file.name_len);
- hash_chain = file.hash_chain;
-
- break;
- }
-
- case ST_SOFTLINK:
- {
- softlink_block sl;
-
- /* read block */
- err = read_softlink_block(img, start_block, &sl);
- if (err) return err;
-
- /* copy filename string and next hash */
- memcpy(name, sl.slname, sl.name_len);
- hash_chain = sl.hash_chain;
-
- break;
- }
-
- case ST_LINKDIR:
- case ST_LINKFILE:
- {
- hardlink_block hl;
-
- /* read block */
- err = read_hardlink_block(img, start_block, &hl);
- if (err) return err;
-
- /* copy filename string and next hash */
- memcpy(name, hl.hlname, hl.name_len);
- hash_chain = hl.hash_chain;
- break;
- }
-
- default:
- return IMGTOOLERR_UNEXPECTED;
-
- }
-
- /* if we haven't found the right filename but there are linked entries,
- * walk up the chain */
- if ((*cmp)(name, path) != 0 && hash_chain != 0)
- {
- *prev_block = start_block;
- return walk_hash_chain(img, path, hash_chain, prev_block, block);
- }
-
- /* found the correct block, return */
- if ((*cmp)(name, path) == 0)
- {
- *block = start_block;
- return IMGTOOLERR_SUCCESS;
- }
-
- /* we should never get here */
- return IMGTOOLERR_UNEXPECTED;
-}
-
-
-/* Returns the block number for a dir/file/link entry given as NUL delimited
- * list of path parts, for example "dir1\0dir2\0dir3" returns the block number
- * for directory "dir3" */
-static imgtoolerr_t find_entry(imgtool_image *img, const char *path, int start_block, int *block)
-{
- imgtoolerr_t ret;
- const char *next_path;
- int current_block, prev;
- UINT32 ht[TSIZE];
-
- /* get the hash table */
- ret = get_hash_table(img, start_block, ht);
- if (ret) return ret;
-
- /* calculate hash and get block for initial entry */
- current_block = ht[hash_name(path, is_intl(img))];
-
- /* check if there was a match in the hash table */
- if (current_block == 0)
- {
- return IMGTOOLERR_PATHNOTFOUND;
- }
-
- /* walk the linked hash list */
- ret = walk_hash_chain(img, path, current_block, &prev, block);
- if (ret) return ret;
-
- /* follow links */
- switch (get_block_type(img, *block))
- {
- case ST_SOFTLINK:
-
- /* TODO: Softlink support */
- return IMGTOOLERR_UNIMPLEMENTED;
-
- case ST_LINKDIR:
- case ST_LINKFILE:
- {
- hardlink_block hl;
-
- ret = read_hardlink_block(img, *block, &hl);
- if (ret) return ret;
-
- *block = hl.real_entry;
-
- break;
- }
-
- default:
- break;
- }
-
- /* get next path part */
- next_path = path + strlen(path) + 1;
-
- /* if there are more path parts, search the next block */
- if (next_path[0])
- {
- return find_entry(img, next_path, *block, block);
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t get_block_chksum(imgtool_image *img, int block, UINT32 *chksum, int bitmap)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* get block data */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* clear old checksum */
- if (bitmap)
- {
- memset(buffer, 0, 4);
- }
- else
- {
- memset(&buffer[20], 0, 4);
- }
-
- /* calulate checksum */
- *chksum = block_checksum(buffer, BSIZE);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t fix_chksum(imgtool_image *img, int block, int bitmap)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
- UINT32 chksum;
-
- /* calculate block checksum */
- ret = get_block_chksum(img, block, &chksum, bitmap);
- if (ret) return ret;
-
- /* read block data */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* update checksum */
- if (bitmap)
- {
- place_integer_be(buffer, 0, 4, chksum);
- }
- else
- {
- place_integer_be(buffer, 20, 4, chksum);
- }
-
- /* write back new block data */
- ret = write_block(img, block, buffer);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t fix_block_chksum(imgtool_image *img, int block)
-{
- return fix_chksum(img, block, FALSE);
-}
-
-
-static imgtoolerr_t fix_bitmap_chksum(imgtool_image *img, int block)
-{
- return fix_chksum(img, block, TRUE);
-}
-
-
-/* Set a block as used */
-static imgtoolerr_t bitmap_mark(imgtool_image *img, int block, int used)
-{
- imgtoolerr_t ret;
- bitmap_block bm;
- root_block root;
- int page;
-
- block -= 2; /* subtract boot block sectors, 2 only for floppies! */
-
- ret = read_root_block(img, &root);
- if (ret) return ret;
-
- /* figure out bitmap block location */
- page = root.bm_pages[block / (MSIZE * 32)];
-
- /* get bitmap */
- ret = read_bitmap_block(img, page, &bm);
- if (ret) return ret;
-
- /* subtract pages we skip */
- block -= MSIZE * 32 * (block / (MSIZE * 32));
-
- /* mark as used or free */
- if (used)
- {
- bm.map[block/32] &= ~(1 << block % 32);
- }
- else
- {
- bm.map[block/32] |= (1 << block % 32);
- }
-
- /* write changed bitmap block back to disk */
- ret = write_bitmap_block(img, page, &bm);
- if (ret) return ret;
-
- /* update checksum */
- ret = fix_bitmap_chksum(img, page);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t bitmap_mark_used(imgtool_image *img, int block)
-{
- return bitmap_mark(img, block, TRUE);
-}
-
-
-static imgtoolerr_t bitmap_mark_free(imgtool_image *img, int block)
-{
- return bitmap_mark(img, block, FALSE);
-}
-
-
-static imgtoolerr_t update_block_modified_date(imgtool_image *img, int block)
-{
- UINT8 buffer[BSIZE];
- imgtoolerr_t ret;
- amiga_date date;
- time_t now;
-
- ret = read_block(img, block, buffer);
- if (ret) return ret;
-
- /* Set new time */
- time(&now);
- amiga_setup_time(now, &date);
-
- /* Write new time into block */
- place_integer_be(buffer, BSIZE-92, 4, date.days);
- place_integer_be(buffer, BSIZE-88, 4, date.mins);
- place_integer_be(buffer, BSIZE-84, 4, date.ticks);
-
- /* Write block back to disk */
- ret = write_block(img, block, buffer);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t clear_hash_table_entry(imgtool_image *img, int parent, char *filename)
-{
- imgtoolerr_t ret;
- UINT32 ht[TSIZE], chain;
- int index, entry, prev, block;
-
- ret = get_hash_table(img, parent, ht);
- if (ret) return ret;
-
- /* Calculate hash and get block for initial entry */
- index = hash_name(filename, is_intl(img));
- entry = ht[index];
-
- /* Walk the hash chain to get the real entry */
- ret = walk_hash_chain(img, filename, entry, &prev, &block);
- if (ret) return ret;
-
- /* Get chained value from block */
- ret = get_hash_chain(img, block, &chain);
- if (ret) return ret;
-
- /* Check if we need to change the hash table */
- if (entry == block)
- {
- /* Set new value (might be 0 if there were no linked entries) */
- ht[index] = chain;
-
- /* Save changed hash table */
- ret = set_hash_table(img, parent, ht);
- if (ret) return ret;
-
- /* Update last modified date */
- ret = update_block_modified_date(img, parent);
- if (ret) return ret;
-
- /* Calculate new checksum */
- ret = fix_block_chksum(img, parent);
- if (ret) return ret;
- }
- else
- {
- /* Save chained value to previous chain element */
- ret = set_hash_chain(img, prev, chain);
- if (ret) return ret;
-
- /* Calculate new checksum */
- ret = fix_block_chksum(img, prev);
- if (ret) return ret;
- }
-
- /* Mark our block as free */
- ret = bitmap_mark_free(img, block);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-/* Returns the number of the first bit that is set in the array */
-static int get_first_bit(UINT32 *array, int size)
-{
- int i;
-
- for (i = 0; i < size; i++)
- {
- if (array[i] != 0)
- {
- UINT32 v = array[i];
- int c;
-
- /* get first bit that is set */
- for (c = 0; (v & 1) == 0; c++) v >>= 1;
-
- /* return bit number */
- return i * 32 + c;
- }
- }
-
- return -1;
-}
-
-
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t walk_bitmap_ext_blocks(imgtool_image *img, int start, int *block)
-{
- imgtoolerr_t ret;
- bitmap_ext_block bm_ext;
- int bit;
-
- /* if we don't have a valid block, bail out */
- if (start == 0)
- {
- return IMGTOOLERR_NOSPACE;
- }
-
- /* get the extended bitmap block */
- ret = read_bitmap_ext_block(img, start, &bm_ext);
- if (ret) return ret;
-
- /* get the first bit that is set in the map */
- bit = get_first_bit(bm_ext.map, MSIZE);
-
- /* if we found one, return */
- if (bit != -1)
- {
- *block += bit;
- return IMGTOOLERR_SUCCESS;
- }
-
- /* increase on each call */
- *block += MSIZE * 32;
-
- /* else continue walking the list */
- return walk_bitmap_ext_blocks(img, bm_ext.next, block);
-}
-#endif
-
-
-/* Searches for a block marked as free
- * TODO: bm_ext support for HDs */
-static imgtoolerr_t find_free_block(imgtool_image *img, int *block)
-{
- imgtoolerr_t ret;
- root_block root;
- int i;
-
- /* get root block */
- ret = read_root_block(img, &root);
- if (ret) return ret;
-
- /* iterate bitmap pointers */
- for (i = 0; i < 25; i++)
- {
- bitmap_block bm;
-
- /* get bitmap block pointed to */
- ret = read_bitmap_block(img, root.bm_pages[i], &bm);
- if (ret) return ret;
-
- *block = i * 32 * MSIZE + get_first_bit(bm.map, MSIZE);
-
- if (*block != -1)
- {
- *block += 2;
- return IMGTOOLERR_SUCCESS;
- }
- }
-
- /* if we get here we haven't found a free block */
- return IMGTOOLERR_NOSPACE;
-}
-
-
-static imgtoolerr_t add_entry(imgtool_image *img, int parent, int block)
-{
- imgtoolerr_t ret;
- UINT32 ht[TSIZE];
- char name[31];
- int hash;
-
- ret = get_blockname(img, block, name);
- if (ret) return ret;
-
- ret = get_hash_table(img, parent, ht);
- if (ret) return ret;
-
- hash = hash_name(name, is_intl(img));
-
- /* Check if there is already an entry with that name */
- if (ht[hash] != 0)
- {
- /* Save the old value to our hash chain */
- ret = set_hash_chain(img, block, ht[hash]);
- if (ret) return ret;
- }
-
- /* Write our block number into the table */
- ht[hash] = block;
-
- /* Write table back to disk */
- ret = set_hash_table(img, parent, ht);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-/* Recursively create new directory entries */
-static imgtoolerr_t makedir(imgtool_image *img, const char *path, int parent)
-{
- imgtoolerr_t ret;
- dir_block dir;
- time_t now;
- int block;
-
- if (!path)
- {
- return IMGTOOLERR_PARAMNEEDED;
- }
-
- if (!path[0])
- {
- return IMGTOOLERR_SUCCESS;
- }
-
- /* Get a free block */
- ret = find_free_block(img, &block);
- if (ret) return ret;
-
- /* Initialize entry */
- memset(&dir, 0, sizeof(dir_block));
-
- /* Copy data */
- time(&now);
- amiga_setup_time(now, &dir.date);
- dir.name_len = strlen(path);
- memcpy(dir.dirname, path, dir.name_len);
- dir.header_key = block;
- dir.parent = parent;
-
- /* Write block */
- ret = write_dir_block(img, block, &dir);
- if (ret) return ret;
-
- /* Fix checksum */
- ret = fix_block_chksum(img, block);
- if (ret) return ret;
-
- /* Link the new entry in the parent */
- ret = add_entry(img, parent, block);
- if (ret) return ret;
-
- /* Mark it as used */
- ret = bitmap_mark_used(img, block);
- if (ret) return ret;
-
- /* Create the next entry */
- return makedir(img, path + strlen(path) + 1, block);
-}
-
-
-/* Recursively checks the path parts and creates directories for them */
-static imgtoolerr_t checkdir(imgtool_image *img, const char *path, int parent)
-{
- imgtoolerr_t ret;
- int block;
- char first_part[31];
-
- memset(first_part, 0, sizeof(first_part));
- strcpy(first_part, path);
-
- /* Directories all the way down, bail out */
- if (!path[0])
- {
- return IMGTOOLERR_CANNOTUSEPATH;
- }
-
- /* Search for the entry */
- ret = find_entry(img, first_part, parent, &block);
-
- switch (ret)
- {
- case IMGTOOLERR_PATHNOTFOUND:
-
- /* There is no entry with this name yet, so we can just create them */
- return makedir(img, path, parent);
-
- case IMGTOOLERR_SUCCESS:
-
- if (get_block_type(img, block) == ST_USERDIR)
- {
- /* Go down one level */
- return checkdir(img, path + strlen(path) + 1, block);
- }
- else
- {
- /* There is an entry but it's not a directory, create it */
- return makedir(img, path, parent);
- }
-
- default: return ret;
- }
-}
-
-
-/* Writes the file data from the specified block into the stream */
-static imgtoolerr_t write_file_block_data(imgtool_image *img, int block, int size, imgtool_stream *destf)
-{
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
-
- /* Check if we even need to write something */
- if (size == 0)
- {
- return IMGTOOLERR_SUCCESS;
- }
-
- if (is_ffs(img))
- {
- /* Get block and read directly into buffer */
- ret = read_block(img, block, buffer);
- if (ret) return ret;
- }
- else
- {
- data_block db;
- UINT32 chksum;
-
- ret = read_data_block(img, block, &db);
- if (ret) return ret;
-
- /* Verify data checksum */
- ret = get_block_chksum(img, block, &chksum, FALSE);
- if (ret) return ret;
-
- if (db.chksum != chksum)
- {
- return IMGTOOLERR_CORRUPTFILE;
- }
-
- /* Copy data to buffer */
- memcpy(buffer, db.data, size);
- }
-
- /* Write data to stream */
- if (stream_write (destf, buffer, size) != size)
- {
- return IMGTOOLERR_WRITEERROR;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t walk_data_block_ptr(imgtool_image *img, UINT32 *ptr, int *filesize, imgtool_stream *destf, int write)
-{
- int i, blocksize = is_ffs(img) ? BSIZE : BSIZE-24;
- imgtoolerr_t ret;
-
- for (i = TSIZE-1; i >= 0; i--)
- {
- /* We write either blocksize bytes or whats remaining */
- int bytes_left = (*filesize >= blocksize) ? blocksize : *filesize;
-
- if (write)
- {
- ret = write_file_block_data(img, ptr[i], bytes_left, destf);
- if (ret) return ret;
- }
- else
- {
- ret = bitmap_mark_free(img, ptr[i]);
- if (ret) return ret;
- }
-
- *filesize -= bytes_left;
-
- /* Check if we are finished early */
- if (*filesize == 0) break;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t write_data_block_ptr(imgtool_image *img, UINT32 *ptr, int *filesize, imgtool_stream *destf)
-{
- return walk_data_block_ptr(img, ptr, filesize, destf, TRUE);
-}
-
-
-/* Marks all blocks pointed to by the data block pointers as free */
-static imgtoolerr_t clear_data_block_ptr(imgtool_image *img, UINT32 *ptr, int *filesize)
-{
- return walk_data_block_ptr(img, ptr, filesize, NULL, FALSE);
-}
-
-
-static imgtoolerr_t walk_file_ext_data(imgtool_image *img, int block, int *filesize, imgtool_stream *destf, int write)
-{
- file_ext_block file_ext;
- imgtoolerr_t ret;
-
- /* Get file extension block */
- ret = read_file_ext_block(img, block, &file_ext);
- if (ret) return ret;
-
- /* Write all data pointers in the table */
- ret = walk_data_block_ptr(img, file_ext.data_blocks, filesize, destf, write);
- if (ret) return ret;
-
- /* Check if we are finished */
- if (*filesize != 0)
- {
- if (file_ext.extension == 0)
- {
- /* We are not finished, but there are no more extension blocks */
- return IMGTOOLERR_CORRUPTFILE;
- }
- else
- {
- /* Write the next file extension block */
- return walk_file_ext_data(img, file_ext.extension, filesize, destf, write);
- }
- }
-
- /* Mark ourself as free if we not writing */
- if (!write)
- {
- ret = bitmap_mark_free(img, block);
- if (ret) return ret;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t write_file_ext_data(imgtool_image *img, int block, int *filesize, imgtool_stream *destf)
-{
- return walk_file_ext_data(img, block, filesize, destf, TRUE);
-}
-
-
-static imgtoolerr_t clear_file_ext_data(imgtool_image *img, int block, int *filesize)
-{
- return walk_file_ext_data(img, block, filesize, NULL, FALSE);
-}
-
-
-/* Updates the disk alteration date stored in the root block */
-static imgtoolerr_t update_disk_alteration_date(imgtool_image *img)
-{
- imgtoolerr_t ret;
- root_block root;
- time_t now;
-
- /* Get root block */
- ret = read_root_block(img, &root);
- if (ret) return ret;
-
- /* Get current time */
- time(&now);
- amiga_setup_time(now, &root.v);
-
- /* Write back new root block */
- ret = write_root_block(img, &root);
- if (ret) return ret;
-
- /* And update its checksum */
- ret = fix_block_chksum(img, get_total_blocks(img)/2);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-/*****************************************************************************
- Imgtool functions
-*****************************************************************************/
-
-
-static imgtoolerr_t amiga_image_open(imgtool_image *img, imgtool_stream *stream)
-{
- amiga_floppy *f = (amiga_floppy *) imgtool_image_extra_bytes(img);
- UINT64 size = stream_size(stream);
-
- f->stream = stream;
- f->sectors = size/BSIZE/80/2;
-
- if (f->sectors != 11 && f->sectors != 22)
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static void amiga_image_exit(imgtool_image *img)
-{
-}
-
-
-static void amiga_image_info(imgtool_image *img, char *string, size_t len)
-{
- imgtoolerr_t ret;
- root_block root;
- char info[255];
- time_t t_c, t_v, t_r;
- char c[19], v[19], r[19];
-
- ret = read_root_block(img, &root);
- if (ret) return;
-
- t_c = amiga_crack_time(&root.c);
- t_v = amiga_crack_time(&root.v);
- t_r = amiga_crack_time(&root.r);
-
- strftime(c, sizeof(c), "%d-%b-%y %H:%M:%S", localtime(&t_c));
- strftime(v, sizeof(v), "%d-%b-%y %H:%M:%S", localtime(&t_v));
- strftime(r, sizeof(r), "%d-%b-%y %H:%M:%S", localtime(&t_r));
-
- strcpy(info, "Volume name: ");
- strncat(info, (char *)root.diskname, root.name_len);
- strcat(info, "\nVolume created: ");
- strcat(info, c);
- strcat(info, "\nVolume modified: ");
- strcat(info, v);
- strcat(info, "\n Root modified: ");
- strcat(info, r);
-
- strncpy(string, info, len);
-}
-
-
-static imgtoolerr_t amiga_image_read_sector(imgtool_image* img, UINT32 track, UINT32 head, UINT32 sector, void *buf, size_t len)
-{
- amiga_floppy *f = (amiga_floppy *) imgtool_image_extra_bytes(img);
-
- /* skip ahead to the area we want to read */
- stream_seek(f->stream, track * (head+1) * f->sectors * BSIZE + sector * BSIZE, SEEK_CUR);
-
- if (stream_read(f->stream, buf, len) != len)
- {
- return IMGTOOLERR_READERROR;
- }
-
- /* reset stream */
- stream_seek(f->stream, 0, 0);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t amiga_image_write_sector(imgtool_image* img, UINT32 track, UINT32 head, UINT32 sector, const void *buf, size_t len, int ddam)
-{
- amiga_floppy *f = (amiga_floppy *) imgtool_image_extra_bytes(img);
-
- /* skip ahead to the area we want to write */
- stream_seek(f->stream, track * (head+1) * f->sectors * BSIZE + sector * BSIZE, SEEK_CUR);
-
- /* write data */
- if (stream_write(f->stream, buf, len) != len)
- {
- return IMGTOOLERR_WRITEERROR;
- }
-
- /* reset stream */
- stream_seek(f->stream, 0, 0);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t amiga_image_get_sector_size(imgtool_image* img, UINT32 track, UINT32 head, UINT32 sector, UINT32 *sector_size)
-{
- *sector_size = BSIZE;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t amiga_image_beginenum(imgtool_directory *enumeration, const char *path)
-{
- int blocks = get_total_blocks(imgtool_directory_image(enumeration));
- imgtoolerr_t ret;
- amiga_iterator *iter;
-
- iter = (amiga_iterator *) imgtool_directory_extrabytes(enumeration);
- if (!iter) return IMGTOOLERR_OUTOFMEMORY;
-
- iter->index = 1;
- iter->ht_index = 0;
- iter->eof = 0;
-
- if (path[0])
- {
- /* search for the directory block, start with the root block */
- ret = find_entry(imgtool_directory_image(enumeration), path, blocks/2, &iter->block);
- if (ret) return ret;
- }
- else
- {
- /* we didn't get a path, use the root directory */
- iter->block = blocks / 2;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t amiga_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- amiga_iterator *iter = (amiga_iterator *) imgtool_directory_extrabytes(enumeration);
- imgtoolerr_t ret;
- UINT32 ht[TSIZE];
- int block;
-
- /* finished listing all entries? */
- if (iter->eof == 1 || iter->ht_index == TSIZE)
- {
- ent->eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- /* get hash table */
- ret = get_hash_table(imgtool_directory_image(enumeration), iter->block, ht);
- if (ret) return ret;
-
- /* skip empty hash table entries */
- while (ht[iter->ht_index] == 0)
- {
- iter->ht_index++;
- /* check if we are already at the end */
- if (iter->ht_index == TSIZE)
- {
- ent->eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
- }
-
- /* get block number */
- block = (iter->next_block == 0) ? ht[iter->ht_index] : iter->next_block;
-
- switch (get_block_type(imgtool_directory_image(enumeration), block))
- {
- case ST_FILE:
- {
- file_block file;
-
- /* get block */
- ret = read_file_block(imgtool_directory_image(enumeration), block, &file);
- if (ret) return ret;
-
- /* fill directory entry */
- strncpyz(ent->filename, (char *)file.filename, file.name_len + 1);
- ent->filesize = file.byte_size;
- ent->lastmodified_time = amiga_crack_time(&file.date);
- amiga_decode_flags(file.protect, ent->attr);
- strncpyz(ent->comment, (char *)file.comment, file.comm_len + 1);
-
- iter->next_block = file.hash_chain;
-
- break;
- }
-
- case ST_USERDIR:
- {
- dir_block dir;
-
- /* get block */
- ret = read_dir_block(imgtool_directory_image(enumeration), block, &dir);
- if (ret) return ret;
-
- /* fill directory entry */
- strncpyz(ent->filename, (char *)dir.dirname, dir.name_len + 1);
- ent->lastmodified_time = amiga_crack_time(&dir.date);
- amiga_decode_flags(dir.protect, ent->attr);
- strncpyz(ent->comment, (char *)dir.comment, dir.comm_len + 1);
- ent->directory = 1;
-
- iter->next_block = dir.hash_chain;
-
- break;
- }
-
- case ST_SOFTLINK:
- {
- softlink_block sl;
-
- /* get block */
- ret = read_softlink_block(imgtool_directory_image(enumeration), block, &sl);
- if (ret) return ret;
-
- /* fill directory entry */
- strncpyz(ent->filename, (char *)sl.slname, sl.name_len + 1);
- ent->lastmodified_time = amiga_crack_time(&sl.date);
- amiga_decode_flags(sl.protect, ent->attr);
- strncpyz(ent->comment, (char *)sl.comment, sl.comm_len + 1);
- strcpy(ent->softlink, (char *)sl.symbolic_name);
-
- iter->next_block = sl.hash_chain;
-
- break;
- }
-
- case ST_LINKDIR:
-
- ent->directory = 1;
-
- case ST_LINKFILE:
- {
- hardlink_block hl;
-
- /* get block */
- ret = read_hardlink_block(imgtool_directory_image(enumeration), block, &hl);
- if (ret) return ret;
-
- /* get filesize from linked file */
- if (!ent->directory)
- {
- file_block file;
- ret = read_file_block(imgtool_directory_image(enumeration), hl.real_entry, &file);
- if (ret) return ret;
- ent->filesize = file.byte_size;
- }
-
- /* fill directory entry */
- strncpyz(ent->filename, (char *)hl.hlname, hl.name_len + 1);
- ent->lastmodified_time = amiga_crack_time(&hl.date);
- amiga_decode_flags(hl.protect, ent->attr);
- strncpyz(ent->comment, (char *)hl.comment, hl.comm_len + 1);
- ent->hardlink = 1;
-
- iter->next_block = hl.hash_chain;
-
- break;
- }
-
- default:
- return IMGTOOLERR_UNIMPLEMENTED;
- }
-
- /* if there are no linked entries, go to the next hash table entry */
- if (iter->next_block == 0)
- {
- iter->ht_index++;
- }
-
- /* jump to next index */
- iter->index++;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static void amiga_image_closeenum(imgtool_directory *enumeration)
-{
- free(enumeration);
-}
-
-
-static imgtoolerr_t amiga_image_freespace(imgtool_partition *partition, UINT64 *size)
-{
- imgtoolerr_t ret;
- imgtool_image *image = imgtool_partition_image(partition);
- const int data_size = is_ffs(image) ? BSIZE : BSIZE-24;
- root_block root;
- bitmap_block bm;
- int blocks, blocks_processed = 0, pages, i, c;
- UINT32 v;
-
- /* initialize size */
- *size = 0;
-
- /* get root block */
- ret = read_root_block(image, &root);
- if (ret) return ret;
-
- /* get total number of blocks in the image */
- blocks = get_total_blocks(image);
-
- /* subtract the two bootblock blocks (only for floppies!) */
- blocks -= 2;
-
- /* iterate all bitmap pages */
- for (pages = 0; pages < 25; pages++)
- {
- ret = read_bitmap_block(image, root.bm_pages[pages], &bm);
- if (ret) return ret;
-
- for (i = 0; i < MSIZE; i++)
- {
- v = bm.map[i];
-
- /* clear half used value */
- if ((blocks_processed + 32) > blocks)
- v &= ~(~0 << (blocks - blocks_processed));
-
- /* count bits */
- for (c = 0; v; c++)
- v &= v - 1;
-
- *size += c * data_size;
-
- blocks_processed += 32;
-
- if (blocks_processed >= blocks)
- return IMGTOOLERR_SUCCESS;
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t amiga_image_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- imgtoolerr_t ret;
- file_block file;
- int filesize, block;
-
- /* Search for the block number */
- ret = find_entry(img, filename, get_total_blocks(img)/2, &block);
- if (ret == IMGTOOLERR_PATHNOTFOUND) return IMGTOOLERR_FILENOTFOUND;
- if (ret) return ret; /* Other errors */
-
- /* Phase 1: Follow data pointers */
- ret = read_file_block(img, block, &file);
- if (ret) return ret;
-
- filesize = file.byte_size;
-
- /* Write out file data pointed to by data block pointers */
- ret = write_data_block_ptr(img, file.data_blocks, &filesize, destf);
- if (ret) return ret;
-
- /* Check if we are done already */
- if (filesize == 0) return IMGTOOLERR_SUCCESS;
-
- /* Phase 2: Follow file extension blocks */
- ret = write_file_ext_data(img, file.extension, &filesize, destf);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-/* When a file is deleted, only its File header block number is cleared from
- * the Directory block (or from the same-hash-value list) and the bitmap is
- * updated. File header block, Data blocks and File extension blocks are not
- * cleared, but the bitmap blocks are updated. */
-static imgtoolerr_t amiga_image_deletefile(imgtool_partition *partition, const char *fname)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- imgtoolerr_t ret;
- int parent, block;
- char filename[31];
-
- /* Initialize filename */
- memset(filename, 0, sizeof(filename));
-
- /* Search for the block number */
- ret = find_entry(img, fname, get_total_blocks(img)/2, &block);
- if (ret == IMGTOOLERR_PATHNOTFOUND) return IMGTOOLERR_FILENOTFOUND;
- if (ret) return ret;
-
- /* Get the parent block, where we need to clear the hash */
- switch (get_block_type(img, block))
- {
- case ST_FILE:
- {
- file_block file;
- int filesize;
-
- ret = read_file_block(img, block, &file);
- if (ret) return ret;
-
- filesize = file.byte_size;
- parent = file.parent;
- memcpy(filename, file.filename, file.name_len);
-
- /* Clear all linked data sectors */
- ret = clear_data_block_ptr(img, file.data_blocks, &filesize);
- if (ret) return ret;
-
- /* Clear extended file data sectors */
- if (filesize != 0)
- {
- ret = clear_file_ext_data(img, file.extension, &filesize);
- if (ret) return ret;
- }
-
- break;
- }
-
- case ST_LINKFILE:
- {
- softlink_block link;
-
- ret = read_softlink_block(img, block, &link);
- if (ret) return ret;
-
- parent = link.parent;
- memcpy(filename, link.slname, link.name_len);
-
- break;
- }
-
- default:
- return IMGTOOLERR_UNEXPECTED;
- }
-
- /* Clear hash table entry */
- ret = clear_hash_table_entry(img, parent, filename);
- if (ret) return ret;
-
- /* Update disk alteration date */
- ret = update_disk_alteration_date(img);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t amiga_image_writefile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- return IMGTOOLERR_UNIMPLEMENTED;
-}
-
-
-static imgtoolerr_t amiga_image_create(imgtool_image *img, imgtool_stream *stream, option_resolution *opts)
-{
- amiga_floppy *f = (amiga_floppy *) imgtool_image_extra_bytes(img);
- const char *dskname = option_resolution_lookup_string(opts, 'N');
- imgtoolerr_t ret;
- UINT8 buffer[BSIZE];
- root_block root;
- bitmap_block bm;
- time_t now;
- int blocks;
-
- f->stream = stream;
-
- switch (option_resolution_lookup_int(opts, 'S'))
- {
- case 0: f->sectors = 11; break;
- case 1: f->sectors = 22; break;
- default: return IMGTOOLERR_PARAMCORRUPT;
- }
-
- /* initialize with zeros */
- memset(buffer, 0, BSIZE);
-
- /* add DOS magic string and flags */
- buffer[0] = 'D';
- buffer[1] = 'O';
- buffer[2] = 'S';
- buffer[3] = 0;
-
- /* File system */
- buffer[3] += (option_resolution_lookup_int(opts, 'F'));
-
- /* File system mode */
- buffer[3] += (option_resolution_lookup_int(opts, 'M'));
-
- /* write first bootblock sector */
- ret = write_block(img, 0, buffer);
- if (ret) return ret;
-
- /* reset with zeros */
- memset(buffer, 0, BSIZE);
-
- /* write second bootblock sector */
- ret = write_block(img, 1, buffer);
- if (ret) return ret;
-
- /* rootblock */
- memset(&root, 0, sizeof(root_block));
-
- blocks = get_total_blocks(img);
-
- root.chksum = 0;
- root.ht_size = TSIZE;
- root.bm_flag = -1;
- root.bm_pages[0] = blocks/2 + 1; /* generally it's located here */
-
- time(&now);
- amiga_setup_time(now, &root.r);
- amiga_setup_time(now, &root.v);
- amiga_setup_time(now, &root.c);
-
- /* volume name */
- if (dskname)
- {
- root.name_len = strlen(dskname);
- memcpy(&root.diskname, dskname, root.name_len);
- }
- else
- {
- root.name_len = strlen("Empty");
- memcpy(&root.diskname, "Empty", root.name_len);
- }
-
- /* write root block to disk */
- ret = write_root_block(img, &root);
- if (ret) return ret;
-
- /* calculate block checksum */
- ret = fix_block_chksum(img, blocks/2);
- if (ret) return ret;
-
- /* bitmap block */
- memset(&bm, 0xff, sizeof(bitmap_block));
-
- /* write bitmap block to disk */
- ret = write_bitmap_block(img, root.bm_pages[0], &bm);
- if (ret) return ret;
-
- /* set root and bitmap block as used */
- ret = bitmap_mark_used(img, blocks/2);
- if (ret) return ret;
-
- ret = bitmap_mark_used(img, root.bm_pages[0]);
- if (ret) return ret;
-
- /* write empty last block so that we don't get a truncated image */
- memset(buffer, 0, BSIZE);
-
- ret = write_block(img, blocks - 1, buffer);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t amiga_image_createdir(imgtool_partition *partition, const char *path)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- imgtoolerr_t ret;
-
- /* Create directories */
- ret = checkdir(img, path, get_total_blocks(img)/2);
- if (ret) return ret;
-
- /* Update disk alteration date */
- ret = update_disk_alteration_date(img);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t amiga_image_getattrs(imgtool_partition *partition, const char *path, const UINT32 *attrs, imgtool_attribute *values)
-{
- return IMGTOOLERR_UNIMPLEMENTED;
-}
-
-
-static imgtoolerr_t amiga_image_setattrs(imgtool_partition *partition, const char *path, const UINT32 *attrs, const imgtool_attribute *values)
-{
- return IMGTOOLERR_UNIMPLEMENTED;
-}
-
-
-static imgtoolerr_t amiga_image_geticoninfo(imgtool_partition *partition, const char *path, imgtool_iconinfo *iconinfo)
-{
- return IMGTOOLERR_UNIMPLEMENTED;
-}
-
-
-static imgtoolerr_t amiga_image_suggesttransfer(imgtool_partition *partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- return IMGTOOLERR_UNIMPLEMENTED;
-}
-
-
-
-/*****************************************************************************
- Create image options
-*****************************************************************************/
-
-
-static OPTION_GUIDE_START(amiga_createimage_optionguide)
- OPTION_STRING( 'N', "name", "Volume name" )
- OPTION_ENUM_START( 'S', "density", "Density" )
- OPTION_ENUM( 0, "dd", "Double Density" )
- OPTION_ENUM( 1, "hd", "High Density" )
- OPTION_ENUM_END
- OPTION_ENUM_START( 'F', "filesystem", "File system" )
- OPTION_ENUM( 0, "ofs", "OldFileSystem" )
- OPTION_ENUM( 1, "ffs", "FastFileSystem" )
- OPTION_ENUM_END
- OPTION_ENUM_START( 'M', "mode", "File system options" )
- OPTION_ENUM( 0, "none", "None" )
- OPTION_ENUM( 2, "intl", "International Mode" )
- OPTION_ENUM( 4, "dirc", "International Mode with Directory Cache" )
- OPTION_ENUM_END
-OPTION_GUIDE_END
-
-
-
-/*****************************************************************************
- Imgtool module declaration
-*****************************************************************************/
-
-
-/* Amiga floppy disk attributes */
-void amiga_floppy_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(amiga_floppy); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(amiga_iterator); break;
- case IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME: info->i = 1; break;
- case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = '/'; break;
- case IMGTOOLINFO_INT_CHARSET: info->i = IMGTOOL_CHARSET_ISO_8859_1; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "amiga_floppy"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Amiga floppy disk image (OFS/FFS format)"); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "adf"); break;
- case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_EOLN: strcpy(info->s = imgtool_temp_str(), EOLN_LF); break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), "S[0]-1;F[0]-1;M[0]/2/4"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_OPEN: info->open = amiga_image_open; break;
- case IMGTOOLINFO_PTR_CLOSE: info->close = amiga_image_exit; break;
- case IMGTOOLINFO_PTR_READ_SECTOR: info->read_sector = amiga_image_read_sector; break;
- case IMGTOOLINFO_PTR_WRITE_SECTOR: info->write_sector = amiga_image_write_sector; break;
- case IMGTOOLINFO_PTR_GET_SECTOR_SIZE: info->get_sector_size = amiga_image_get_sector_size; break;
- case IMGTOOLINFO_PTR_CREATE: info->create = amiga_image_create; break;
- case IMGTOOLINFO_PTR_INFO: info->info = amiga_image_info; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = amiga_image_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = amiga_image_nextenum; break;
- case IMGTOOLINFO_PTR_CLOSE_ENUM: info->close_enum = amiga_image_closeenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = amiga_image_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = amiga_image_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = amiga_image_writefile; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = amiga_image_deletefile; break;
- case IMGTOOLINFO_PTR_CREATE_DIR: info->create_dir = amiga_image_createdir; break;
- case IMGTOOLINFO_PTR_GET_ATTRS: info->get_attrs = amiga_image_getattrs; break;
- case IMGTOOLINFO_PTR_SET_ATTRS: info->set_attrs = amiga_image_setattrs; break;
- case IMGTOOLINFO_PTR_GET_ICON_INFO: info->get_iconinfo = amiga_image_geticoninfo; break;
- case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = amiga_image_suggesttransfer; break;
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = amiga_createimage_optionguide; break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/bml3.c b/src/mess/tools/imgtool/modules/bml3.c
deleted file mode 100644
index 1ed1b645f69..00000000000
--- a/src/mess/tools/imgtool/modules/bml3.c
+++ /dev/null
@@ -1,928 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Jonathan Edwards
-/****************************************************************************
-
- bml3.c
-
- Hitachi bml3 disk images
-
- By Jonathan Edwards, based on rsdos.c (both use Microsoft BASIC)
-
-****************************************************************************/
-
-/* Supported Hitachi floppy formats are:
- - 3" or 5"1/4 single density, single-sided: 40 tracks, 16 sectors/track, 128 bytes/sector
- - (used with MP-1805 floppy disk controller card)
- - 5"1/4 double density, double-sided: 40 tracks, 16 sectors/track, 256 bytes/sector
- - (first track on first head may be single density)
- - (used with MP-1802 floppy disk controller card)
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include "imgtool.h"
-#include "iflopimg.h"
-
-#define MAX_SECTOR_SIZE 256
-
-struct bml3_diskinfo
-{
- UINT16 sector_size; /* 128 or 256 */
- UINT8 heads; /* 1 or 2 */
- UINT8 fat_start_sector; /* in cylinder 20, start sector of FAT */
- UINT8 fat_start_offset; /* start byte of FAT in sector */
- UINT8 fat_sectors; /* the number of sectors in the FAT */
- UINT8 dirent_start_sector; /* in cylinder 20, start sector of directory entries */
- UINT8 granule_sectors; /* how many sectors per granule */
- UINT8 first_granule_cylinder; /* the number of the first cylinder with granule numbers assigned */
- UINT8 variant; /* 0 - older version, uses EOF to terminate files, 1 - newer version, stores file length */
-};
-
-/* this structure mirrors the structure of a directory entry on disk */
-struct bml3_dirent
-{
- char fname[8];
- char fext[3];
- UINT8 ftype;
- UINT8 asciiflag;
- UINT8 first_granule;
- UINT16 lastsectorbytes;
- // TODO there are some 'unused' bytes here that are sometimes used to store a timestamp, maybe support this?
-};
-
-struct bml3_direnum
-{
- int index;
- int eof;
-};
-
-#define MAX_GRANULEMAP_SIZE 256
-
-struct granule_list_t {
- UINT8 granules[MAX_GRANULEMAP_SIZE];
- UINT8 granule_count;
- UINT8 last_granule_sectors;
-};
-
-#define BML3_OPTIONS_FTYPE 'T'
-#define BML3_OPTIONS_ASCII 'M'
-
-static imgtoolerr_t bml3_diskimage_deletefile(imgtool_partition *partition, const char *fname);
-
-
-
-/*********************************************************************
- Imgtool module code
-*********************************************************************/
-
-static bml3_diskinfo *bml3_get_diskinfo(imgtool_image *image)
-{
- return (bml3_diskinfo *) imgtool_floppy_extrabytes(image);
-}
-
-
-
-static int max_dirents(imgtool_image *image)
-{
- bml3_diskinfo *info = bml3_get_diskinfo(image);
- return (16 * info->heads + 1 - info->dirent_start_sector)*(info->sector_size/32);
-}
-
-
-
-static void dirent_location(imgtool_image *image, int index_loc, UINT8 *head, UINT8 *track, UINT8 *sector, UINT8 *offset)
-{
- bml3_diskinfo *info = bml3_get_diskinfo(image);
- *track = 20;
- *sector = info->dirent_start_sector + index_loc / (info->sector_size / 32);
- *head = 0;
- if (*sector > 16) {
- // wrap to second head
- *sector -= 16;
- (*head)++;
- }
- *offset = index_loc % (info->sector_size/32) * 32;
-}
-
-
-
-static floperr_t get_bml3_dirent(imgtool_image *f, int index_loc, struct bml3_dirent *ent)
-{
- floperr_t err;
- UINT8 head, track, sector, offset;
- UINT8 buf[32];
- bml3_diskinfo *info = bml3_get_diskinfo(f);
- dirent_location(f, index_loc, &head, &track, &sector, &offset);
- err = floppy_read_sector(imgtool_floppy(f), head, track, sector, offset, (void *) buf, sizeof(buf));
- memset(ent, 0, sizeof(*ent));
- switch (info->variant) {
- case 0:
- memcpy(&ent->fname, &buf[0], 8);
- ent->ftype = buf[11];
- ent->asciiflag = buf[12];
- ent->first_granule = buf[14];
- break;
- case 1:
- memcpy(&ent->fname, &buf[0], 8);
- memcpy(&ent->fext, &buf[8], 3);
- ent->ftype = buf[11];
- ent->asciiflag = buf[12];
- ent->first_granule = buf[13];
- ent->lastsectorbytes = (buf[14] << 8) | buf[15];
- break;
- default:
- return FLOPPY_ERROR_INVALIDIMAGE;
- }
- return err;
-}
-
-
-
-static floperr_t put_bml3_dirent(imgtool_image *f, int index_loc, const struct bml3_dirent *ent)
-{
- floperr_t err;
- UINT8 head, track, sector, offset;
- UINT8 buf[32];
- bml3_diskinfo *info = bml3_get_diskinfo(f);
- if (index_loc >= max_dirents(f))
- return (floperr_t)IMGTOOLERR_FILENOTFOUND;
- dirent_location(f, index_loc, &head, &track, &sector, &offset);
- memset(buf, 0, sizeof(buf));
- switch (info->variant) {
- case 0:
- memcpy(&buf[0], &ent->fname, 8);
- buf[11] = ent->ftype;
- buf[12] = ent->asciiflag;
- buf[14] = ent->first_granule;
- break;
- case 1:
- memcpy(&buf[0], &ent->fname, 8);
- memcpy(&buf[8], &ent->fext, 3);
- buf[11] = ent->ftype;
- buf[12] = ent->asciiflag;
- buf[13] = ent->first_granule;
- buf[14] = ent->lastsectorbytes >> 8;
- buf[15] = ent->lastsectorbytes & 0xff;
- break;
- default:
- return FLOPPY_ERROR_INVALIDIMAGE;
- }
- err = floppy_write_sector(imgtool_floppy(f), head, track, sector, offset, (void *) buf, sizeof(buf), 0); /* TODO: pass ddam argument from imgtool */
- return err;
-}
-
-
-
-/* fnamebuf must have at least 13 bytes */
-static void get_dirent_fname(char *fnamebuf, const struct bml3_dirent *ent)
-{
- char *s;
-
- memset(fnamebuf, 0, 13);
- memcpy(fnamebuf, ent->fname, sizeof(ent->fname));
- rtrim(fnamebuf);
- s = fnamebuf + strlen(fnamebuf);
- *(s++) = '.';
- memcpy(s, ent->fext, sizeof(ent->fext));
- rtrim(s);
-
- /* If no extension, remove period */
- if (*s == '\0')
- s[-1] = '\0';
-}
-
-
-
-static imgtoolerr_t lookup_bml3_file(imgtool_image *f, const char *fname, struct bml3_dirent *ent, int *position)
-{
- int i;
- floperr_t ferr;
- char fnamebuf[13];
-
- i = 0;
- fnamebuf[0] = '\0';
-
- do
- {
- do
- {
- ferr = get_bml3_dirent(f, i++, ent);
- if (ferr)
- return imgtool_floppy_error(ferr);
- }
- while(ent->fname[0] == '\0');
-
-
- if (ent->fname[0] != -1)
- get_dirent_fname(fnamebuf, ent);
- }
- while((ent->fname[0] != -1) && core_stricmp(fnamebuf, fname));
-
- if (ent->fname[0] == -1)
- return IMGTOOLERR_FILENOTFOUND;
-
- if (position)
- *position = i - 1;
- return (imgtoolerr_t)0;
-}
-
-
-
-static UINT8 get_granule_count(imgtool_image *img)
-{
- // UINT16 tracks;
- UINT16 disk_granules;
- bml3_diskinfo *info = bml3_get_diskinfo(img);
-
- // This always returns 82 for D88, so not quite right
- // tracks = floppy_get_tracks_per_disk(imgtool_floppy(img));
-
- // The number of granules is primarily constrained by the disk capacity.
- disk_granules = (40 - 1 - info->first_granule_cylinder) * info->heads * (16 / info->granule_sectors);
- // Also, granule numbers from 0xC0 upwards are reserved for terminating a granule chain
- return (UINT8)((disk_granules < 0xC0) ? disk_granules : 0xC0);
-}
-
-/* granule_map must be an array of MAX_GRANULEMAP_SIZE bytes */
-static floperr_t get_granule_map(imgtool_image *img, UINT8 *granule_map, UINT8 *granule_count)
-{
- bml3_diskinfo *info = bml3_get_diskinfo(img);
- UINT8 count;
-
- count = get_granule_count(img);
- if (granule_count)
- *granule_count = count;
-
- // The first byte of the granule map sector is ignored (and expected to be 0)
- return floppy_read_sector(imgtool_floppy(img), 0, 20, info->fat_start_sector, info->fat_start_offset, granule_map, count);
-}
-
-
-
-static floperr_t put_granule_map(imgtool_image *img, const UINT8 *granule_map, UINT8 granule_count)
-{
- bml3_diskinfo *info = bml3_get_diskinfo(img);
- return floppy_write_sector(imgtool_floppy(img), 0, 20, info->fat_start_sector, info->fat_start_offset, granule_map, granule_count, 0); /* TODO: pass ddam argument from imgtool */
-}
-
-
-
-
-static void granule_location(imgtool_image *image, UINT8 granule, UINT8 *head, UINT8 *track, UINT8 *sector)
-{
- bml3_diskinfo *info = bml3_get_diskinfo(image);
- UINT16 abs_track = granule * info->granule_sectors / 16;
- *head = abs_track % info->heads;
- *track = abs_track / info->heads + info->first_granule_cylinder;
- // skip filesystem cylinder
- if (*track >= 20)
- (*track)++;
- *sector = granule * info->granule_sectors % 16 + 1;
-}
-
-
-
-static imgtoolerr_t transfer_granule(imgtool_image *img, UINT8 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 head, track, sector;
- granule_location(img, granule, &head, &track, &sector);
- if (length > 0)
- err = proc(img, head, track, sector, 0, length, f);
- return err;
-}
-
-
-static imgtoolerr_t transfer_from_granule(imgtool_image *img, UINT8 granule, int length, imgtool_stream *destf)
-{
- return transfer_granule(img, granule, length, destf, imgtool_floppy_read_sector_to_stream);
-}
-
-
-
-static imgtoolerr_t transfer_to_granule(imgtool_image *img, UINT8 granule, int length, imgtool_stream *sourcef)
-{
- return transfer_granule(img, granule, length, sourcef, imgtool_floppy_write_sector_from_stream);
-}
-
-
-
-static floperr_t read_granule(imgtool_image *img, UINT8 granule, int offset, int length, UINT8 *buf)
-{
- UINT8 head, track, sector;
- granule_location(img, granule, &head, &track, &sector);
- return floppy_read_sector(imgtool_floppy(img), head, track, sector, offset, buf, length);
-}
-
-
-
-static floperr_t write_granule(imgtool_image *img, UINT8 granule, int offset, int length, const UINT8 *buf)
-{
- UINT8 head, track, sector;
- granule_location(img, granule, &head, &track, &sector);
- return floppy_write_sector(imgtool_floppy(img), head, track, sector, offset, buf, length, 0); /* TODO: pass ddam argument from imgtool */
-}
-
-
-
-static imgtoolerr_t list_granules(struct bml3_dirent *ent, imgtool_image *img, struct granule_list_t *granule_list)
-{
- floperr_t ferr;
- UINT8 max_granules;
- UINT8 granule;
- UINT8 usedmap[MAX_GRANULEMAP_SIZE]; /* Used to detect infinite loops */
- UINT8 granule_map[MAX_GRANULEMAP_SIZE];
- bml3_diskinfo *info = bml3_get_diskinfo(img);
-
- ferr = get_granule_map(img, granule_map, &max_granules);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- memset(usedmap, 0, max_granules);
-
- granule = ent->first_granule;
- granule_list->granule_count = 0;
-
- while(!usedmap[granule] && granule < max_granules)
- {
- usedmap[granule] = 1;
- granule_list->granules[granule_list->granule_count++] = granule;
- granule = granule_map[granule];
- }
-
- granule_list->last_granule_sectors = granule - 0xc0;
- if (info->variant == 0) {
- // add final incomplete sector
- granule_list->last_granule_sectors++;
- }
-
- // A value of zero (variant 1) and max (variant 0) seem to indicate a file open for writing.
- // Strictly speaking this means the image is corrupt, although a real system will happily read
- // garbage from the file.
- if (granule_list->last_granule_sectors > info->granule_sectors)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t get_file_size(struct bml3_dirent *ent, imgtool_image *img, const struct granule_list_t *granule_list, size_t *size)
-{
- floperr_t ferr;
- size_t last_sector_bytes = 0;
- bml3_diskinfo *info = bml3_get_diskinfo(img);
-
- // TODO are these special cases valid, or maybe indicate a corrupt image?
- if (granule_list->granule_count == 0) {
- *size = 0;
- return IMGTOOLERR_SUCCESS;
- }
- else if (granule_list->last_granule_sectors == 0) {
- *size = info->sector_size * ((granule_list->granule_count - 1) * info->granule_sectors);
- return IMGTOOLERR_SUCCESS;
- }
-
- // determine size excluding final sector
- *size = info->sector_size * ((granule_list->granule_count - 1) * info->granule_sectors + granule_list->last_granule_sectors - 1);
-
- // determine bytes used in final sector
- switch (info->variant) {
- case 0:
- // look for EOF (ASCII SUB) and trailing NULs in final sector
- {
- UINT8 buf[MAX_SECTOR_SIZE];
- ferr = read_granule(img, granule_list->granules[granule_list->granule_count-1], info->sector_size * (granule_list->last_granule_sectors - 1), info->sector_size, buf);
- if (ferr)
- return imgtool_floppy_error(ferr);
- for (last_sector_bytes = info->sector_size - 1; ; last_sector_bytes--) {
- if (buf[last_sector_bytes] != 0)
- break;
- if (last_sector_bytes == 0)
- break;
- }
- if (buf[last_sector_bytes] != 0x1a) {
- last_sector_bytes++;
- }
- }
- break;
- case 1:
- last_sector_bytes = ent->lastsectorbytes;
- break;
- }
-
- // TODO is it valid for last_sector_bytes == 0?
- if (last_sector_bytes > info->sector_size) {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- *size += last_sector_bytes;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t process_bml3_file(struct bml3_dirent *ent, imgtool_image *img, imgtool_stream *destf, size_t *size)
-{
- imgtoolerr_t err;
- size_t remaining_size, granule_size;
- bml3_diskinfo *info = bml3_get_diskinfo(img);
- struct granule_list_t granule_list;
- granule_list.granule_count = 0;
-
- err = list_granules(ent, img, &granule_list);
- if (err)
- return err;
- err = get_file_size(ent, img, &granule_list, size);
- if (err)
- return err;
-
- if (destf) {
- remaining_size = *size;
- granule_size = info->granule_sectors * info->sector_size;
-
- for (int c = 0; c < granule_list.granule_count; c++) {
- if (granule_size >= remaining_size)
- granule_size = remaining_size;
- transfer_from_granule(img, granule_list.granules[c], granule_size, destf);
- remaining_size -= granule_size;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/* create a new directory entry with a specified name */
-static imgtoolerr_t prepare_dirent(UINT8 variant, struct bml3_dirent *ent, const char *fname)
-{
- const char *fname_end;
- const char *fname_ext;
- int fname_ext_len;
-
- memset(ent, '\0', sizeof(*ent));
- memset(ent->fname, ' ', sizeof(ent->fname));
- memset(ent->fext, ' ', sizeof(ent->fext));
-
- fname_end = strchr(fname, '.');
- if (fname_end)
- fname_ext = fname_end + 1;
- else
- fname_end = fname_ext = fname + strlen(fname);
-
- fname_ext_len = strlen(fname_ext);
-
- switch (variant) {
- case 0:
- /* 8-character max filename */
- if (((fname_end - fname) > 8) || (fname_ext_len > 0))
- return IMGTOOLERR_BADFILENAME;
- break;
- case 1:
- /*8.3 filename */
- if (((fname_end - fname) > 8) || (fname_ext_len > 3))
- return IMGTOOLERR_BADFILENAME;
- break;
- default:
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- memcpy(ent->fname, fname, fname_end - fname);
- memcpy(ent->fext, fname_ext, fname_ext_len);
-
- /* By default, set as a type 2 binary file */
- ent->ftype = 2;
- ent->asciiflag = 0;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t bml3_diskimage_open(imgtool_image *image, imgtool_stream *stream)
-{
- // imgtoolerr_t err;
- floperr_t ferr;
- bml3_diskinfo *info = bml3_get_diskinfo(image);
- floppy_image_legacy *floppy = imgtool_floppy(image);
- const struct FloppyCallbacks *callbacks = floppy_callbacks(floppy);
-
- // probe disk geometry to guess format
- int heads_per_disk = callbacks->get_heads_per_disk(floppy);
- UINT32 sector_length;
- ferr = callbacks->get_sector_length(floppy, 0, 20, 1, &sector_length);
- if (ferr)
- return imgtool_floppy_error(ferr);
- int sectors_per_track = callbacks->get_sectors_per_track(floppy, 0, 20);
-
- if (heads_per_disk == 2 && sector_length == 128 && sectors_per_track == 16) {
- // single-sided, single-density
- info->sector_size = 128;
- info->heads = 1;
- info->fat_start_sector = 1;
- info->fat_start_offset = 5;
- info->fat_sectors = 2;
- info->dirent_start_sector = 7;
- info->granule_sectors = 4;
- info->first_granule_cylinder = 0;
- info->variant = 0;
- }
- else if (heads_per_disk == 2 && sector_length == 256 && sectors_per_track == 16) {
- // double-sided, double-density
- info->sector_size = 256;
- info->heads = 2;
- info->fat_start_sector = 2;
- info->fat_start_offset = 1;
- info->fat_sectors = 1;
- info->dirent_start_sector = 5;
- info->granule_sectors = 8;
- info->first_granule_cylinder = 1;
- info->variant = 1;
- }
- else {
- // invalid or unsupported format
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t bml3_diskimage_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- floperr_t ferr;
- imgtoolerr_t err;
- size_t filesize;
- struct bml3_direnum *rsenum;
- struct bml3_dirent rsent;
- char fname[13];
- imgtool_image *image;
-
- image = imgtool_directory_image(enumeration);
- rsenum = (struct bml3_direnum *) imgtool_directory_extrabytes(enumeration);
-
- /* Did we hit the end of file before? */
- if (rsenum->eof)
- goto eof;
-
- do
- {
- if (rsenum->index >= max_dirents(image))
- goto eof;
-
- ferr = get_bml3_dirent(image, rsenum->index++, &rsent);
- if (ferr)
- return imgtool_floppy_error(ferr);
- }
- while(rsent.fname[0] == '\0');
-
- /* Now are we at the eof point? */
- if (rsent.fname[0] == -1)
- {
- rsenum->eof = 1;
-eof:
- ent->eof = 1;
- }
- else
- {
- /* Not the end of file */
- err = process_bml3_file(&rsent, image, NULL, &filesize);
- if (err)
- return err;
-
- if (filesize == ((size_t) -1))
- {
- /* corrupt! */
- ent->filesize = 0;
- ent->corrupt = 1;
- }
- else
- {
- ent->filesize = filesize;
- ent->corrupt = 0;
- }
- ent->eof = 0;
-
- get_dirent_fname(fname, &rsent);
-
- snprintf(ent->filename, ARRAY_LENGTH(ent->filename), "%s", fname);
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "%d %c", (int) rsent.ftype, (char) (rsent.asciiflag + 'B'));
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t bml3_diskimage_freespace(imgtool_partition *partition, UINT64 *size)
-{
- floperr_t ferr;
- UINT8 i;
- size_t s = 0;
- UINT8 granule_count;
- UINT8 granule_map[MAX_GRANULEMAP_SIZE];
- imgtool_image *image = imgtool_partition_image(partition);
- bml3_diskinfo *info = bml3_get_diskinfo(image);
-
- ferr = get_granule_map(image, granule_map, &granule_count);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- for (i = 0; i < granule_count; i++)
- {
- if (granule_map[i] == 0xff)
- s += (info->granule_sectors * info->sector_size);
- }
- *size = s;
- return (imgtoolerr_t)FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t delete_entry(imgtool_image *img, struct bml3_dirent *ent, int pos)
-{
- floperr_t ferr;
- unsigned char g, i;
- UINT8 granule_count;
- UINT8 granule_map[MAX_GRANULEMAP_SIZE];
-
- /* Write a NUL in the filename, marking it deleted */
- ent->fname[0] = 0;
- ferr = put_bml3_dirent(img, pos, ent);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- ferr = get_granule_map(img, granule_map, &granule_count);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- /* Now free up the granules */
- g = ent->first_granule;
- while (g < granule_count)
- {
- i = granule_map[g];
- granule_map[g] = 0xff;
- g = i;
- }
-
- ferr = put_granule_map(img, granule_map, granule_count);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t bml3_diskimage_readfile(imgtool_partition *partition, const char *fname, const char *fork, imgtool_stream *destf)
-{
- imgtoolerr_t err;
- struct bml3_dirent ent;
- size_t size;
- imgtool_image *img = imgtool_partition_image(partition);
-
- err = lookup_bml3_file(img, fname, &ent, NULL);
- if (err)
- return err;
-
- err = process_bml3_file(&ent, img, destf, &size);
- if (err)
- return err;
-
- if (size == (size_t) -1)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- return (imgtoolerr_t)0;
-}
-
-
-
-static imgtoolerr_t bml3_diskimage_writefile(imgtool_partition *partition, const char *fname, const char *fork, imgtool_stream *sourcef, option_resolution *writeoptions)
-{
- floperr_t ferr;
- imgtoolerr_t err;
- imgtool_image *img = imgtool_partition_image(partition);
- bml3_diskinfo *info = bml3_get_diskinfo(img);
- struct bml3_dirent ent, ent2;
- size_t i;
- UINT64 sz, read_sz;
- UINT64 freespace = 0;
- unsigned char *gptr;
- UINT8 granule_count;
- UINT8 granule_map[MAX_GRANULEMAP_SIZE];
- UINT8 eof_buf[MAX_SECTOR_SIZE];
-
- // one-time setup of eof_buf
- memset(eof_buf, 0, sizeof(eof_buf));
- eof_buf[0] = 0x1A;
-
- /* can we write to this image? */
- if (floppy_is_read_only(imgtool_floppy(img)))
- return IMGTOOLERR_READONLY;
-
- err = bml3_diskimage_freespace(partition, &freespace);
- if (err)
- return err;
-
- /* is there enough space? */
- sz = read_sz = stream_size(sourcef);
- if (info->variant == 0) {
- // also need to write EOF
- sz++;
- }
- if (sz > freespace)
- return IMGTOOLERR_NOSPACE;
-
- /* setup our directory entry */
- err = prepare_dirent(info->variant, &ent, fname);
- if (err)
- return err;
-
- ent.ftype = option_resolution_lookup_int(writeoptions, BML3_OPTIONS_FTYPE);
- ent.asciiflag = ((UINT8) option_resolution_lookup_int(writeoptions, BML3_OPTIONS_ASCII)) - 1;
- gptr = &ent.first_granule;
-
- ferr = get_granule_map(img, granule_map, &granule_count);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- unsigned char g = 0x00;
- UINT32 granule_bytes = info->granule_sectors * info->sector_size;
-
- 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 = MIN(read_sz, granule_bytes);
- if (i > 0) {
- err = transfer_to_granule(img, g, i, sourcef);
- if (err)
- return err;
- read_sz -= i;
- sz -= i;
- }
- if (i < info->granule_sectors * info->sector_size && sz > 0) {
- // write EOF and trailing NULs in the final sector
- ferr = write_granule(img, g, i, (info->granule_sectors * info->sector_size - i - 1) % info->sector_size + 1, eof_buf);
- if (ferr)
- return imgtool_floppy_error(ferr);
- 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 + info->sector_size-1) / info->sector_size) - (info->variant == 0 ? 1 : 0);
- ent.lastsectorbytes = (i - 1) % info->sector_size + 1;
-
- /* delete file if it already exists */
- err = bml3_diskimage_deletefile(partition, fname);
- if (err && err != IMGTOOLERR_FILENOTFOUND)
- return err;
-
- /* Now we need to find an empty directory entry */
- i = -1;
- do
- {
- ferr = get_bml3_dirent(img, ++i, &ent2);
- if (ferr)
- return imgtool_floppy_error(ferr);
- }
- while(ent2.fname[0] != '\0' && ent2.fname[0] != -1);
-
- ferr = put_bml3_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;
-}
-
-
-
-static imgtoolerr_t bml3_diskimage_deletefile(imgtool_partition *partition, const char *fname)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- int pos = 0;
- struct bml3_dirent ent;
-
- err = lookup_bml3_file(image, fname, &ent, &pos);
- if (err)
- return err;
-
- return delete_entry(image, &ent, pos);
-}
-
-
-
-static imgtoolerr_t bml3_diskimage_suggesttransfer(imgtool_partition *partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- struct bml3_dirent ent;
- int pos;
-
- if (fname)
- {
- err = lookup_bml3_file(image, fname, &ent, &pos);
- if (err)
- return err;
-
- if (ent.asciiflag == 0xFF)
- {
- /* ASCII file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = filter_eoln_getinfo;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
- }
- else if (ent.ftype == 0)
- {
- /* tokenized BASIC file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = filter_bml3bas_getinfo;
- }
- }
- else
- {
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = filter_eoln_getinfo;
- suggestions[2].viability = SUGGESTION_POSSIBLE;
- suggestions[2].filter = filter_bml3bas_getinfo;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*********************************************************************
- Imgtool module declaration
-*********************************************************************/
-
-static OPTION_GUIDE_START( bml3_writefile_optionguide )
- OPTION_ENUM_START( BML3_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( BML3_OPTIONS_ASCII, "ascii", "Ascii flag" )
- OPTION_ENUM( 0, "ascii", "Ascii" )
- OPTION_ENUM( 1, "binary", "Binary" )
- OPTION_ENUM_END
-OPTION_GUIDE_END
-
-
-
-void bml3_get_info(const imgtool_class *imgclass, UINT32 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_IMAGE_EXTRA_BYTES: info->i = sizeof(bml3_diskinfo); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct bml3_direnum); break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "bml3"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Basic Master Level 3 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_FLOPPY_OPEN: info->open = bml3_diskimage_open; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = bml3_diskimage_nextenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = bml3_diskimage_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = bml3_diskimage_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = bml3_diskimage_writefile; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = bml3_diskimage_deletefile; break;
- case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = bml3_diskimage_suggesttransfer; break;
- case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: info->writefile_optguide = bml3_writefile_optionguide; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_default; break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/concept.c b/src/mess/tools/imgtool/modules/concept.c
deleted file mode 100644
index a5c5a37b1ad..00000000000
--- a/src/mess/tools/imgtool/modules/concept.c
+++ /dev/null
@@ -1,492 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/*
- Handlers for concept floppy images
-
- Disk images are in MESS format.
-
- Raphael Nabet, 2003
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include "imgtool.h"
-
-struct UINT16xE
-{
- UINT8 bytes[2];
-};
-
-/*
- get_UINT16xE
-
- Read a 16-bit word, whether it is little-endian or big-endian
-
- little_endian (I): non-zero if word is little-endian, zero if word is
- big-endian
- word (I): pointer to word to read
-
- Returns value of word in native format
-*/
-INLINE UINT16 get_UINT16xE(int little_endian, UINT16xE word)
-{
- return little_endian ? (word.bytes[0] | (word.bytes[1] << 8)) : ((word.bytes[0] << 8) | word.bytes[1]);
-}
-
-#if 0
-/*
- set_UINT16xE
-
- Write a 16-bit word, whether it is little-endian or big-endian
-
- little_endian (I): non-zero if word is little-endian, zero if word is
- big-endian
- word (O): pointer to word to write
- data (I): value to write in word, in native format
-*/
-INLINE void set_UINT16xE(int little_endian, UINT16xE *word, UINT16 data)
-{
- if (little_endian)
- {
- word->bytes[0] = data & 0xff;
- word->bytes[1] = (data >> 8) & 0xff;
- }
- else
- {
- word->bytes[0] = (data >> 8) & 0xff;
- word->bytes[1] = data & 0xff;
- }
-}
-#endif
-
-/*
- Disk structure:
-
- Track 0 Sector 0 & 1: bootstrap loader
- Track 0 Sector 2 through 5: disk directory
- Remaining sectors are used for data.
-*/
-
-/*
- device directory record (Disk sector 2-5)
-*/
-
-struct concept_vol_hdr_entry
-{
- UINT16xE first_block;
- UINT16xE next_block;
- UINT16xE ftype;
-
- unsigned char volname[8];
- UINT16xE last_block;
- UINT16xE num_files;
- UINT16xE last_boot;
- UINT16xE last_access;
- char mem_flipped;
- char disk_flipped;
- UINT16xE unused;
-};
-
-struct concept_file_dir_entry
-{
- UINT16xE first_block;
- UINT16xE next_block;
- UINT16xE ftype;
-
- unsigned char filename[16];
- UINT16xE last_byte;
- UINT16xE last_access;
-};
-
-struct concept_dev_dir
-{
- concept_vol_hdr_entry vol_hdr;
- concept_file_dir_entry file_dir[77];
- char unused[20];
-};
-
-/*
- concept disk image descriptor
-*/
-struct concept_image
-{
- imgtool_stream *file_handle; /* imgtool file handle */
- concept_dev_dir dev_dir; /* cached copy of device directory */
-};
-
-/*
- concept catalog iterator, used when imgtool reads the catalog
-*/
-struct concept_iterator
-{
- concept_image *image;
- int index; /* current index */
-};
-
-
-static imgtoolerr_t concept_image_init(imgtool_image *img, imgtool_stream *f);
-static void concept_image_exit(imgtool_image *img);
-static void concept_image_info(imgtool_image *img, char *string, size_t len);
-static imgtoolerr_t concept_image_beginenum(imgtool_directory *enumeration, const char *path);
-static imgtoolerr_t concept_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent);
-static void concept_image_closeenum(imgtool_directory *enumeration);
-static imgtoolerr_t concept_image_freespace(imgtool_partition *partition, UINT64 *size);
-static imgtoolerr_t concept_image_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf);
-#if 0
-static imgtoolerr_t concept_image_writefile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *writeoptions);
-static imgtoolerr_t concept_image_deletefile(imgtool_partition *partition, const char *filename);
-static imgtoolerr_t concept_image_create(const imgtool_module *mod, imgtool_stream *f, option_resolution *createoptions);
-#endif
-
-void concept_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(concept_image); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(concept_iterator); break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "concept"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Concept floppy disk image"); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "img"); break;
- case IMGTOOLINFO_STR_EOLN: strcpy(info->s = imgtool_temp_str(), "\r"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_OPEN: info->open = concept_image_init; break;
- case IMGTOOLINFO_PTR_CLOSE: info->close = concept_image_exit; break;
- case IMGTOOLINFO_PTR_INFO: info->info = concept_image_info; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = concept_image_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = concept_image_nextenum; break;
- case IMGTOOLINFO_PTR_CLOSE_ENUM: info->close_enum = concept_image_closeenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = concept_image_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = concept_image_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: /* info->write_file = concept_image_writefile */; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: /* info->delete_file = concept_image_deletefile */; break;
- case IMGTOOLINFO_PTR_CREATE: /* info->create = concept_image_create */; break;
- }
-}
-
-/*
- read_physical_record
-
- Read one 512-byte physical record from a disk image
-
- file_handle: imgtool file handle
- secnum: physical record address
- dest: pointer to destination buffer
-
- Return non-zero on error
-*/
-static int read_physical_record(imgtool_stream *file_handle, int secnum, void *dest)
-{
- int reply;
-
- /* seek to sector */
- reply = stream_seek(file_handle, secnum*512, SEEK_SET);
- if (reply)
- return 1;
- /* read it */
- reply = stream_read(file_handle, dest, 512);
- if (reply != 512)
- return 1;
-
- return 0;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- write_physical_record
-
- Write one 512-byte physical record to a disk image
-
- file_handle: imgtool file handle
- secnum: logical sector address
- src: pointer to source buffer
-
- Return non-zero on error
-*/
-static int write_physical_record(imgtool_stream *file_handle, int secnum, const void *src)
-{
- int reply;
-
- /* seek to sector */
- reply = stream_seek(file_handle, secnum*512, SEEK_SET);
- if (reply)
- return 1;
- /* read it */
- reply = stream_write(file_handle, src, 512);
- if (reply != 512)
- return 1;
-
- return 0;
-}
-#endif
-
-/*
- Search for a file name on a concept_image
-
- image (I): image reference
- filename (I): name of the file to search
- entry_index (O): index of file in disk catalog
-
- Return non-zero on error
-*/
-static int get_catalog_entry(concept_image *image, const unsigned char *filename, int *entry_index)
-{
- int filename_len = filename[0];
- int i;
-
- if (filename_len > 15)
- /* file name is bad */
- return 1;
-
- for (i = 0; i < 77; i++)
- {
- if (!memcmp(filename, image->dev_dir.file_dir[i].filename, filename_len+1))
- {
- /* file found */
- *entry_index = i;
- return 0;
- }
- }
-
- /* file not found */
- return 1;
-}
-
-/*
- Open a file as a concept_image.
-*/
-static imgtoolerr_t concept_image_init(imgtool_image *img, imgtool_stream *f)
-{
- concept_image *image = (concept_image *) imgtool_image_extra_bytes(img);
- int reply;
- int i;
- unsigned totphysrecs;
-
- image->file_handle = f;
-
- /* read device directory */
- for (i=0; i<4; i++)
- {
- reply = read_physical_record(f, i+2, ((char *) & image->dev_dir)+i*512);
- if (reply)
- return IMGTOOLERR_READERROR;
- }
-
- /* do primitive checks */
- totphysrecs = get_UINT16xE(image->dev_dir.vol_hdr.disk_flipped, image->dev_dir.vol_hdr.last_block)
- - get_UINT16xE(image->dev_dir.vol_hdr.disk_flipped, image->dev_dir.vol_hdr.first_block);
-
- if ((get_UINT16xE(image->dev_dir.vol_hdr.disk_flipped, image->dev_dir.vol_hdr.first_block) != 0)
- || (get_UINT16xE(image->dev_dir.vol_hdr.disk_flipped, image->dev_dir.vol_hdr.next_block) != 6)
- || (totphysrecs < 6) /*|| (stream_size(f) != totphysrecs*512)*/
- || (image->dev_dir.vol_hdr.volname[0] > 7))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- close a concept_image
-*/
-static void concept_image_exit(imgtool_image *img)
-{
- /*concept_image *image = (concept_image *) imgtool_image_extra_bytes(img);*/
-}
-
-/*
- get basic information on a concept_image
-
- Currently returns the volume name
-*/
-static void concept_image_info(imgtool_image *img, char *string, size_t len)
-{
- concept_image *image = (concept_image *) imgtool_image_extra_bytes(img);
- char vol_name[8];
-
- memcpy(vol_name, image->dev_dir.vol_hdr.volname + 1, image->dev_dir.vol_hdr.volname[0]);
- vol_name[image->dev_dir.vol_hdr.volname[0]] = 0;
-
- snprintf(string, len, "%s", vol_name);
-}
-
-/*
- Open the disk catalog for enumeration
-*/
-static imgtoolerr_t concept_image_beginenum(imgtool_directory *enumeration, const char *path)
-{
- concept_iterator *iter;
-
- iter = (concept_iterator *) imgtool_directory_extrabytes(enumeration);
- iter->image = (concept_image *) imgtool_image_extra_bytes(imgtool_directory_image(enumeration));
- iter->index = 0;
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Enumerate disk catalog next entry
-*/
-static imgtoolerr_t concept_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- concept_iterator *iter = (concept_iterator *) imgtool_directory_extrabytes(enumeration);
-
-
- ent->corrupt = 0;
- ent->eof = 0;
-
- if ((iter->image->dev_dir.file_dir[iter->index].filename[0] == 0) || (iter->index > 77))
- {
- ent->eof = 1;
- }
- else if (iter->image->dev_dir.file_dir[iter->index].filename[0] > 15)
- {
- ent->corrupt = 1;
- }
- else
- {
- int len = iter->image->dev_dir.file_dir[iter->index].filename[0];
- const char *type;
-
- if (len > ARRAY_LENGTH(ent->filename))
- len = ARRAY_LENGTH(ent->filename);
- memcpy(ent->filename, iter->image->dev_dir.file_dir[iter->index].filename + 1, len);
- ent->filename[len] = 0;
-
- /* parse flags */
- switch (get_UINT16xE(iter->image->dev_dir.vol_hdr.disk_flipped, iter->image->dev_dir.file_dir[iter->index].ftype) & 0xf)
- {
- case 0:
- case 8:
- type = "DIRHDR";
- break;
- case 2:
- type = "CODE";
- break;
- case 3:
- type = "TEXT";
- break;
- case 5:
- type = "DATA";
- break;
- default:
- type = "???";
- break;
- }
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "%s", type);
-
- /* len in physrecs */
- ent->filesize = get_UINT16xE(iter->image->dev_dir.vol_hdr.disk_flipped, iter->image->dev_dir.file_dir[iter->index].next_block)
- - get_UINT16xE(iter->image->dev_dir.vol_hdr.disk_flipped, iter->image->dev_dir.file_dir[iter->index].first_block);
-
- iter->index++;
- }
-
- return (imgtoolerr_t)0;
-}
-
-/*
- Free enumerator
-*/
-static void concept_image_closeenum(imgtool_directory *enumeration)
-{
-}
-
-/*
- Compute free space on disk image
-*/
-static imgtoolerr_t concept_image_freespace(imgtool_partition *partition, UINT64 *size)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- concept_image *image = (concept_image*) img;
- int free_blocks;
- int i;
-
- /* first get number of data blocks */
- free_blocks = get_UINT16xE(image->dev_dir.vol_hdr.disk_flipped, image->dev_dir.vol_hdr.last_block)
- - get_UINT16xE(image->dev_dir.vol_hdr.disk_flipped, image->dev_dir.vol_hdr.next_block);
-
- /* next substract length of each file */
- for (i=0; (image->dev_dir.file_dir[i].filename[0] != 0) && (i <= 77); i++)
- {
- free_blocks -= get_UINT16xE(image->dev_dir.vol_hdr.disk_flipped, image->dev_dir.file_dir[i].next_block)
- - get_UINT16xE(image->dev_dir.vol_hdr.disk_flipped, image->dev_dir.file_dir[i].first_block);
- }
-
- *size = free_blocks;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Extract a file from a concept_image.
-*/
-static imgtoolerr_t concept_image_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- concept_image *image = (concept_image *) imgtool_image_extra_bytes(img);
- size_t filename_len = strlen(filename);
- unsigned char concept_fname[16];
- int catalog_index;
- int i;
- UINT8 buf[512];
-
- if (filename_len > 15)
- return IMGTOOLERR_BADFILENAME;
-
- concept_fname[0] = filename_len;
- memcpy(concept_fname+1, filename, filename_len);
-
- if (get_catalog_entry(image, concept_fname, &catalog_index))
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i = get_UINT16xE(image->dev_dir.vol_hdr.disk_flipped, image->dev_dir.file_dir[catalog_index].first_block);
- i < get_UINT16xE(image->dev_dir.vol_hdr.disk_flipped, image->dev_dir.file_dir[catalog_index].next_block);
- i++)
- {
- if (read_physical_record(image->file_handle, i, buf))
- return IMGTOOLERR_READERROR;
-
- if (stream_write(destf, buf, 512) != 512)
- return IMGTOOLERR_WRITEERROR;
- }
-
- return (imgtoolerr_t)0;
-}
-
-#if 0
-/*
- Add a file to a concept_image.
-*/
-static imgtoolerr_t concept_image_writefile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *writeoptions)
-{
- /* ... */
-
- return 0;
-}
-
-/*
- Delete a file from a concept_image.
-*/
-static imgtoolerr_t concept_image_deletefile(imgtool_partition *partition, const char *filename)
-{
- /* ... */
-
- return 0;
-}
-
-/*
- Create a blank concept_image.
-*/
-static imgtoolerr_t concept_image_create(const imgtool_module *mod, imgtool_stream *f, option_resolution *createoptions)
-{
- /* ... */
-
- return 0;
-}
-#endif
diff --git a/src/mess/tools/imgtool/modules/cybiko.c b/src/mess/tools/imgtool/modules/cybiko.c
deleted file mode 100644
index 1fc2afd319b..00000000000
--- a/src/mess/tools/imgtool/modules/cybiko.c
+++ /dev/null
@@ -1,578 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tim Schuerewegen
-/*
-
- Cybiko Classic File System
-
- (c) 2007 Tim Schuerewegen
-
-*/
-
-#include "imgtool.h"
-
-#include <zlib.h>
-
-struct cybiko_file_system
-{
- imgtool_stream *stream;
- UINT32 page_count, page_size, block_count_boot, block_count_file;
- UINT16 write_count;
-};
-
-struct cybiko_iter
-{
- UINT16 block;
-};
-
-struct cfs_file
-{
- char name[64]; // name of the file
- UINT32 date; // date/time of the file (seconds since 1900/01/01)
- UINT32 size; // size of the file
- UINT32 blocks; // number of blocks occupied by the file
-};
-
-enum
-{
- BLOCK_TYPE_INVALID,
- BLOCK_TYPE_BOOT,
- BLOCK_TYPE_FILE
-};
-
-#define MAX_PAGE_SIZE (264 * 2)
-
-#define INVALID_FILE_ID 0xFFFF
-
-enum
-{
- FLASH_TYPE_INVALID,
- FLASH_TYPE_AT45DB041,
- FLASH_TYPE_AT45DB081,
- FLASH_TYPE_AT45DB161
-};
-
-#define BLOCK_USED(x) (x[0] & 0x80)
-#define BLOCK_FILE_ID(x) buffer_read_16_be( x + 2)
-#define BLOCK_PART_ID(x) buffer_read_16_be( x + 4)
-#define BLOCK_FILENAME(x) (char*)(x + 7)
-
-#define FILE_HEADER_SIZE 0x48
-
-// 2208988800 is the number of seconds between 1900/01/01 and 1970/01/01
-
-static time_t time_crack( UINT32 cfs_time)
-{
- return (time_t)(cfs_time - 2208988800UL);
-}
-
-static UINT32 time_setup( time_t ansi_time)
-{
- return (UINT32)(ansi_time + 2208988800UL);
-}
-
-static UINT32 buffer_read_32_be( UINT8 *buffer)
-{
- return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3] << 0);
-}
-
-static UINT16 buffer_read_16_be( UINT8 *buffer)
-{
- return (buffer[0] << 8) | (buffer[1] << 0);
-}
-
-static void buffer_write_32_be( UINT8 *buffer, UINT32 data)
-{
- buffer[0] = (data >> 24) & 0xFF;
- buffer[1] = (data >> 16) & 0xFF;
- buffer[2] = (data >> 8) & 0xFF;
- buffer[3] = (data >> 0) & 0xFF;
-}
-
-static void buffer_write_16_be( UINT8 *buffer, UINT16 data)
-{
- buffer[0] = (data >> 8) & 0xFF;
- buffer[1] = (data >> 0) & 0xFF;
-}
-
-// page = crc1 (4) + wcnt (2) + crc2 (2) + data (x) + unk (2)
-
-static UINT32 page_buffer_calc_checksum_1( UINT8 *buffer, UINT32 size, int block_type)
-{
- return crc32( 0, buffer + 8, (block_type == BLOCK_TYPE_BOOT) ? 250 : size - 10);
-}
-
-static UINT16 page_buffer_calc_checksum_2( UINT8 *buffer)
-{
- UINT16 val = 0xAF17;
- val ^= buffer_read_16_be( buffer + 0);
- val ^= buffer_read_16_be( buffer + 2);
- val ^= buffer_read_16_be( buffer + 4);
- return FLIPENDIAN_INT16(val);
-}
-
-static int page_buffer_verify( UINT8 *buffer, UINT32 size, int block_type)
-{
- UINT32 checksum_page, checksum_calc;
- // checksum 1
- checksum_calc = page_buffer_calc_checksum_1( buffer, size, block_type);
- checksum_page = buffer_read_32_be( buffer + 0);
- if (checksum_calc != checksum_page) return FALSE;
- // checksum 2
- checksum_calc = page_buffer_calc_checksum_2( buffer);
- checksum_page = buffer_read_16_be( buffer + 6);
- if (checksum_calc != checksum_page) return FALSE;
- // ok
- return TRUE;
-}
-
-static int cfs_block_to_page( cybiko_file_system *cfs, int block_type, UINT32 block, UINT32 *page)
-{
- switch (block_type)
- {
- case BLOCK_TYPE_BOOT : if (page) *page = block; return TRUE;
- case BLOCK_TYPE_FILE : if (page) *page = block + cfs->block_count_boot; return TRUE;
- default : return FALSE;
- }
-}
-
-static int cfs_page_to_block( cybiko_file_system *cfs, UINT32 page, int *block_type, UINT32 *block)
-{
- UINT32 tmp = page;
- // boot block
- if (tmp < cfs->block_count_boot)
- {
- if (block_type) *block_type = BLOCK_TYPE_BOOT;
- if (block) *block = tmp;
- return TRUE;
- }
- tmp -= cfs->block_count_boot;
- // file block
- if (tmp < cfs->block_count_file)
- {
- if (block_type) *block_type = BLOCK_TYPE_FILE;
- if (block) *block = tmp;
- return TRUE;
- }
- tmp -= cfs->block_count_file;
- // error
- return FALSE;
-}
-
-static int cfs_page_read( cybiko_file_system *cfs, UINT8 *buffer, UINT32 page)
-{
- if (page >= cfs->page_count) return FALSE;
- stream_seek( cfs->stream, page * cfs->page_size, SEEK_SET);
- stream_read( cfs->stream, buffer, cfs->page_size);
- return TRUE;
-}
-
-static int cfs_page_write( cybiko_file_system *cfs, UINT8 *buffer, UINT32 page)
-{
- if (page >= cfs->page_count) return FALSE;
- stream_seek( cfs->stream, page * cfs->page_size, SEEK_SET);
- stream_write( cfs->stream, buffer, cfs->page_size);
- return TRUE;
-}
-
-static int cfs_block_read( cybiko_file_system *cfs, UINT8 *buffer, int block_type, UINT32 block)
-{
- UINT8 buffer_page[MAX_PAGE_SIZE];
- UINT32 page;
- if (!cfs_block_to_page( cfs, block_type, block, &page)) return FALSE;
- if (!cfs_page_read( cfs, buffer_page, page)) return FALSE;
- memcpy( buffer, buffer_page + 8, cfs->page_size - 10);
- return TRUE;
-}
-
-static int cfs_block_write( cybiko_file_system *cfs, UINT8 *buffer, int block_type, UINT32 block)
-{
- UINT8 buffer_page[MAX_PAGE_SIZE];
- UINT32 page;
- memcpy( buffer_page + 8, buffer, cfs->page_size - 10);
- buffer_write_32_be( buffer_page + 0, page_buffer_calc_checksum_1( buffer_page, cfs->page_size, block_type));
- buffer_write_16_be( buffer_page + 4, cfs->write_count++);
- buffer_write_16_be( buffer_page + 6, page_buffer_calc_checksum_2( buffer_page));
- buffer_write_16_be( buffer_page + cfs->page_size - 2, 0xFFFF);
- if (!cfs_block_to_page( cfs, block_type, block, &page)) return FALSE;
- if (!cfs_page_write( cfs, buffer_page, page)) return FALSE;
- return TRUE;
-}
-
-static int cfs_file_delete( cybiko_file_system *cfs, UINT16 file_id)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return FALSE;
- if (BLOCK_USED(buffer) && (BLOCK_FILE_ID(buffer) == file_id))
- {
- buffer[0] &= ~0x80;
- if (!cfs_block_write( cfs, buffer, BLOCK_TYPE_FILE, i)) return FALSE;
- }
- }
- return TRUE;
-}
-
-static int cfs_file_info( cybiko_file_system *cfs, UINT16 file_id, cfs_file *file)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i;
- file->blocks = file->size = 0;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return FALSE;
- if (BLOCK_USED(buffer) && (BLOCK_FILE_ID(buffer) == file_id))
- {
- if (BLOCK_PART_ID(buffer) == 0)
- {
- strcpy( file->name, BLOCK_FILENAME(buffer));
- file->date = buffer_read_32_be( buffer + 6 + FILE_HEADER_SIZE - 4);
- }
- file->size += buffer[1];
- file->blocks++;
- }
- }
- return (file->blocks > 0) ? TRUE : FALSE;
-}
-
-static int cfs_file_find( cybiko_file_system *cfs, const char *filename, UINT16 *file_id)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return FALSE;
- if (BLOCK_USED(buffer) && (strncmp( filename, BLOCK_FILENAME(buffer), 40) == 0))
- {
- *file_id = i;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static int cfs_verify( cybiko_file_system *cfs)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i, block_type;
- for (i=0;i<cfs->page_count;i++)
- {
- if (!cfs_page_read( cfs, buffer, i)) return FALSE;
- if (!cfs_page_to_block( cfs, i, &block_type, NULL)) return FALSE;
- if (!page_buffer_verify( buffer, cfs->page_size, block_type)) return FALSE;
- }
- return TRUE;
-}
-
-static int cfs_init( cybiko_file_system *cfs, imgtool_stream *stream, int flash_type)
-{
- cfs->stream = stream;
- switch (flash_type)
- {
- case FLASH_TYPE_AT45DB041 : cfs->page_count = 2048; cfs->page_size = 264; break;
- case FLASH_TYPE_AT45DB081 : cfs->page_count = 4096; cfs->page_size = 264; break;
- case FLASH_TYPE_AT45DB161 : cfs->page_count = 4096; cfs->page_size = 528; break;
- default : return FALSE;
- }
- cfs->block_count_boot = 5;
- cfs->block_count_file = cfs->page_count - cfs->block_count_boot;
- cfs->write_count = 0;
- return TRUE;
-}
-
-static int cfs_format( cybiko_file_system *cfs)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i;
- // boot blocks
- memset( buffer, 0xFF, sizeof( buffer));
- for (i=0;i<cfs->block_count_boot;i++)
- {
- if (!cfs_block_write( cfs, buffer, BLOCK_TYPE_BOOT, i)) return FALSE;
- }
- // file blocks
- memset( buffer, 0xFF, sizeof( buffer));
- buffer[0] &= ~0x80;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_write( cfs, buffer, BLOCK_TYPE_FILE, i)) return FALSE;
- }
- // ok
- return TRUE;
-}
-
-static UINT16 cfs_calc_free_blocks( cybiko_file_system *cfs)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i;
- UINT16 blocks = 0;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return 0;
- if (!BLOCK_USED(buffer)) blocks++;
- }
- return blocks;
-}
-
-static UINT32 cfs_calc_free_space( cybiko_file_system *cfs, UINT16 blocks)
-{
- UINT32 free_space;
- free_space = blocks * (cfs->page_size - 0x10);
- if (free_space > 0) free_space -= FILE_HEADER_SIZE;
- return free_space;
-}
-
-static int flash_size_to_flash_type( size_t size)
-{
- switch (size)
- {
- case 0x084000 : return FLASH_TYPE_AT45DB041;
- case 0x108000 : return FLASH_TYPE_AT45DB081;
- case 0x210000 : return FLASH_TYPE_AT45DB161;
- default : return FLASH_TYPE_INVALID;
- }
-}
-
-static int flash_option_to_flash_type( int option)
-{
- switch (option)
- {
- case 0 : return FLASH_TYPE_AT45DB041;
- case 1 : return FLASH_TYPE_AT45DB081;
- case 2 : return FLASH_TYPE_AT45DB161;
- default : return FLASH_TYPE_INVALID;
- }
-}
-
-static imgtoolerr_t cybiko_image_open( imgtool_image *image, imgtool_stream *stream)
-{
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- int flash_type;
- // init
- flash_type = flash_size_to_flash_type( stream_size( stream));
- if (!cfs_init( cfs, stream, flash_type)) return IMGTOOLERR_CORRUPTIMAGE;
- // verify
- if (!cfs_verify( cfs)) return IMGTOOLERR_CORRUPTIMAGE;
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-static void cybiko_image_close( imgtool_image *image)
-{
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- stream_close( cfs->stream);
-}
-
-static imgtoolerr_t cybiko_image_create( imgtool_image *image, imgtool_stream *stream, option_resolution *opts)
-{
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- int flash_type;
- // init
- flash_type = flash_option_to_flash_type( option_resolution_lookup_int( opts, 'F'));
- if (!cfs_init( cfs, stream, flash_type)) return IMGTOOLERR_CORRUPTIMAGE;
- // format
- if (!cfs_format( cfs)) return IMGTOOLERR_CORRUPTIMAGE;
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t cybiko_image_begin_enum( imgtool_directory *enumeration, const char *path)
-{
- cybiko_iter *iter = (cybiko_iter*)imgtool_directory_extrabytes( enumeration);
- iter->block = 0;
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t cybiko_image_next_enum( imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- imgtool_image *image = imgtool_directory_image( enumeration);
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- cybiko_iter *iter = (cybiko_iter*)imgtool_directory_extrabytes( enumeration);
- UINT8 buffer[MAX_PAGE_SIZE];
- UINT16 file_id = INVALID_FILE_ID;
- cfs_file file;
- // find next file
- while (iter->block < cfs->block_count_file)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, iter->block++)) return IMGTOOLERR_READERROR;
- if (BLOCK_USED(buffer) && (BLOCK_PART_ID(buffer) == 0))
- {
- file_id = BLOCK_FILE_ID(buffer);
- break;
- }
- }
- // get file information
- if ((file_id != INVALID_FILE_ID) && cfs_file_info( cfs, file_id, &file))
- {
- strcpy( ent->filename, file.name);
- ent->filesize = file.size;
- ent->lastmodified_time = time_crack( file.date);
- ent->filesize = file.size;
- }
- else
- {
- ent->eof = 1;
- }
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-static void cybiko_image_close_enum( imgtool_directory *enumeration)
-{
- // nothing
-}
-
-static imgtoolerr_t cybiko_image_free_space( imgtool_partition *partition, UINT64 *size)
-{
- imgtool_image *image = imgtool_partition_image( partition);
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- if (size) *size = cfs_calc_free_space( cfs, cfs_calc_free_blocks( cfs));
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t cybiko_image_read_file( imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- imgtool_image *image = imgtool_partition_image( partition);
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- UINT8 buffer[MAX_PAGE_SIZE];
- UINT16 file_id, part_id = 0, old_part_id;
- int i;
- // find file
- if (!cfs_file_find( cfs, filename, &file_id)) return IMGTOOLERR_FILENOTFOUND;
- // read file
- do
- {
- old_part_id = part_id;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return IMGTOOLERR_READERROR;
- if (BLOCK_USED(buffer) && (BLOCK_FILE_ID(buffer) == file_id) && (BLOCK_PART_ID(buffer) == part_id))
- {
- stream_write( destf, buffer + 6 + ((part_id == 0) ? FILE_HEADER_SIZE : 0), buffer[1]);
- part_id++;
- }
- }
- } while (old_part_id != part_id);
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t cybiko_image_write_file( imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- imgtool_image *image = imgtool_partition_image( partition);
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- UINT8 buffer[MAX_PAGE_SIZE];
- UINT16 file_id, part_id = 0, free_blocks;
- UINT64 bytes_left;
- cfs_file file;
- int i;
- // find file
- if (!cfs_file_find( cfs, filename, &file_id)) file_id = INVALID_FILE_ID;
- // check free space
- free_blocks = cfs_calc_free_blocks( cfs);
- if (file_id != INVALID_FILE_ID)
- {
- if (!cfs_file_info( cfs, file_id, &file)) return IMGTOOLERR_UNEXPECTED;
- free_blocks += file.blocks;
- }
- if (cfs_calc_free_space( cfs, free_blocks) < stream_size( sourcef)) return IMGTOOLERR_NOSPACE;
- // delete file
- if (file_id != INVALID_FILE_ID)
- {
- if (!cfs_file_delete( cfs, file_id)) return IMGTOOLERR_UNEXPECTED;
- }
- // create/write destination file
- bytes_left = stream_size( sourcef);
- i = 0;
- while ((bytes_left > 0) && (i < cfs->block_count_file))
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return IMGTOOLERR_READERROR;
- if (!BLOCK_USED(buffer))
- {
- if (part_id == 0) file_id = i;
- memset( buffer, 0xFF, cfs->page_size - 0x10);
- buffer[0] = 0x80;
- buffer[1] = cfs->page_size - 0x10 - ((part_id == 0) ? FILE_HEADER_SIZE : 0);
- if (bytes_left < buffer[1]) buffer[1] = bytes_left;
- buffer_write_16_be( buffer + 2, file_id);
- buffer_write_16_be( buffer + 4, part_id);
- if (part_id == 0)
- {
- buffer[6] = 0;
- strcpy( BLOCK_FILENAME(buffer), filename);
- buffer_write_32_be( buffer + 6 + FILE_HEADER_SIZE - 4, time_setup( time( NULL)));
- stream_read( sourcef, buffer + 6 + FILE_HEADER_SIZE, buffer[1]);
- }
- else
- {
- stream_read( sourcef, buffer + 6, buffer[1]);
- }
- if (!cfs_block_write( cfs, buffer, BLOCK_TYPE_FILE, i)) return IMGTOOLERR_WRITEERROR;
- bytes_left -= buffer[1];
- part_id++;
- }
- i++;
- }
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t cybiko_image_delete_file( imgtool_partition *partition, const char *filename)
-{
- imgtool_image *image = imgtool_partition_image( partition);
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- UINT16 file_id;
- // find file
- if (!cfs_file_find( cfs, filename, &file_id)) return IMGTOOLERR_FILENOTFOUND;
- // delete file
- if (!cfs_file_delete( cfs, file_id)) return IMGTOOLERR_UNEXPECTED;
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-static OPTION_GUIDE_START( cybiko_image_createimage_optguide )
- OPTION_ENUM_START( 'F', "flash", "Flash Type" )
- OPTION_ENUM( 0, "AT45DB041", "AT45DB041 (528 KByte)" )
- OPTION_ENUM( 1, "AT45DB081", "AT45DB081 (1056 KByte)" )
- OPTION_ENUM( 2, "AT45DB161", "AT45DB161 (2112 KByte)" )
- OPTION_ENUM_END
-OPTION_GUIDE_END
-
-//OPTION_GUIDE_START( cybiko_image_writefile_optguide )
-// OPTION_INT( 'B', "boot", "Boot Flag" )
-//OPTION_GUIDE_END
-
-void cybiko_get_info( const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch (state)
- {
- // --- the following bits of info are returned as 64-bit signed integers ---
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES : info->i = sizeof( cybiko_file_system); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES : info->i = sizeof( cybiko_iter); break;
-// case IMGTOOLINFO_INT_SUPPORTS_CREATION_TIME : info->i = 1; break;
- case IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME : info->i = 1; break;
-// case IMGTOOLINFO_INT_BLOCK_SIZE : info->i = 264; break;
- // --- the following bits of info are returned as pointers to data or functions ---
- case IMGTOOLINFO_PTR_OPEN : info->open = cybiko_image_open; break;
- case IMGTOOLINFO_PTR_CREATE : info->create = cybiko_image_create; break;
- case IMGTOOLINFO_PTR_CLOSE : info->close = cybiko_image_close; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM : info->begin_enum = cybiko_image_begin_enum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM : info->next_enum = cybiko_image_next_enum; break;
- case IMGTOOLINFO_PTR_CLOSE_ENUM : info->close_enum = cybiko_image_close_enum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE : info->free_space = cybiko_image_free_space; break;
- case IMGTOOLINFO_PTR_READ_FILE : info->read_file = cybiko_image_read_file; break;
- case IMGTOOLINFO_PTR_WRITE_FILE : info->write_file = cybiko_image_write_file; break;
- case IMGTOOLINFO_PTR_DELETE_FILE : info->delete_file = cybiko_image_delete_file; break;
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE : info->createimage_optguide = cybiko_image_createimage_optguide; break;
-// case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE : info->writefile_optguide = cybiko_image_writefile_optguide; break;
- // --- the following bits of info are returned as NULL-terminated strings ---
- case IMGTOOLINFO_STR_NAME : strcpy( info->s = imgtool_temp_str(), "cybiko"); break;
- case IMGTOOLINFO_STR_DESCRIPTION : strcpy( info->s = imgtool_temp_str(), "Cybiko Classic File System"); break;
- case IMGTOOLINFO_STR_FILE : strcpy( info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS : strcpy( info->s = imgtool_temp_str(), "bin,nv"); break;
- case IMGTOOLINFO_STR_EOLN : strcpy( info->s = imgtool_temp_str(), "\r\n"); break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC : strcpy( info->s = imgtool_temp_str(), "F[0]-2"); break;
-// case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC : strcpy( info->s = imgtool_temp_str(), "B[0]-1"); break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/cybikoxt.c b/src/mess/tools/imgtool/modules/cybikoxt.c
deleted file mode 100644
index a1908dc9c76..00000000000
--- a/src/mess/tools/imgtool/modules/cybikoxt.c
+++ /dev/null
@@ -1,539 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tim Schuerewegen
-/*
-
- Cybiko Xtreme File System
-
- (c) 2010 Tim Schuerewegen
-
-*/
-
-#include "imgtool.h"
-
-#include <zlib.h>
-
-struct cybiko_file_system
-{
- imgtool_stream *stream;
- UINT32 page_count, page_size, block_count_boot, block_count_file;
- UINT16 write_count;
-};
-
-struct cybiko_iter
-{
- UINT16 block;
-};
-
-struct cfs_file
-{
- char name[64]; // name of the file
- UINT32 date; // date/time of the file (seconds since 1900/01/01)
- UINT32 size; // size of the file
- UINT32 blocks; // number of blocks occupied by the file
-};
-
-enum
-{
- BLOCK_TYPE_INVALID,
- BLOCK_TYPE_BOOT,
- BLOCK_TYPE_FILE
-};
-
-#define MAX_PAGE_SIZE (264 * 2)
-
-#define INVALID_FILE_ID 0xFFFF
-
-#define BLOCK_USED(x) (x[0] & 0x80)
-#define BLOCK_FILE_ID(x) buffer_read_16_be( x + 2)
-#define BLOCK_PART_ID(x) buffer_read_16_be( x + 4)
-#define BLOCK_FILENAME(x) (char*)(x + 7)
-
-#define FILE_HEADER_SIZE 0x48
-
-// 2208988800 is the number of seconds between 1900/01/01 and 1970/01/01
-
-static time_t time_crack( UINT32 cfs_time)
-{
- return (time_t)(cfs_time - 2208988800UL);
-}
-
-static UINT32 time_setup( time_t ansi_time)
-{
- return (UINT32)(ansi_time + 2208988800UL);
-}
-
-static UINT32 buffer_read_32_be( UINT8 *buffer)
-{
- return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3] << 0);
-}
-
-static UINT16 buffer_read_16_be( UINT8 *buffer)
-{
- return (buffer[0] << 8) | (buffer[1] << 0);
-}
-
-static void buffer_write_32_be( UINT8 *buffer, UINT32 data)
-{
- buffer[0] = (data >> 24) & 0xFF;
- buffer[1] = (data >> 16) & 0xFF;
- buffer[2] = (data >> 8) & 0xFF;
- buffer[3] = (data >> 0) & 0xFF;
-}
-
-static void buffer_write_16_be( UINT8 *buffer, UINT16 data)
-{
- buffer[0] = (data >> 8) & 0xFF;
- buffer[1] = (data >> 0) & 0xFF;
-}
-
-// page = crc (2) + data (x)
-
-static UINT16 page_buffer_calc_checksum( UINT8 *data, UINT32 size)
-{
- int i;
- UINT32 val = 0;
- for (i = 0; i < size; i++)
- {
- val = (val ^ data[i] ^ i) << 1;
- val = val | ((val >> 16) & 0x0001);
- }
- return val;
-}
-
-static int page_buffer_verify( UINT8 *buffer, UINT32 size, int block_type)
-{
- // checksum
- if (block_type == BLOCK_TYPE_FILE)
- {
- UINT32 checksum_page, checksum_calc;
- checksum_calc = page_buffer_calc_checksum( buffer + 2, size - 2);
- checksum_page = buffer_read_16_be( buffer + 0);
- if (checksum_calc != checksum_page) return FALSE;
- }
- // ok
- return TRUE;
-}
-
-static int cfs_block_to_page( cybiko_file_system *cfs, int block_type, UINT32 block, UINT32 *page)
-{
- switch (block_type)
- {
- case BLOCK_TYPE_BOOT : if (page) *page = block; return TRUE;
- case BLOCK_TYPE_FILE : if (page) *page = block + cfs->block_count_boot; return TRUE;
- default : return FALSE;
- }
-}
-
-static int cfs_page_to_block( cybiko_file_system *cfs, UINT32 page, int *block_type, UINT32 *block)
-{
- UINT32 tmp = page;
- // boot block
- if (tmp < cfs->block_count_boot)
- {
- if (block_type) *block_type = BLOCK_TYPE_BOOT;
- if (block) *block = tmp;
- return TRUE;
- }
- tmp -= cfs->block_count_boot;
- // file block
- if (tmp < cfs->block_count_file)
- {
- if (block_type) *block_type = BLOCK_TYPE_FILE;
- if (block) *block = tmp;
- return TRUE;
- }
- tmp -= cfs->block_count_file;
- // error
- return FALSE;
-}
-
-static int cfs_page_read( cybiko_file_system *cfs, UINT8 *buffer, UINT32 page)
-{
- if (page >= cfs->page_count) return FALSE;
- stream_seek( cfs->stream, page * cfs->page_size, SEEK_SET);
- stream_read( cfs->stream, buffer, cfs->page_size);
- return TRUE;
-}
-
-static int cfs_page_write( cybiko_file_system *cfs, UINT8 *buffer, UINT32 page)
-{
- if (page >= cfs->page_count) return FALSE;
- stream_seek( cfs->stream, page * cfs->page_size, SEEK_SET);
- stream_write( cfs->stream, buffer, cfs->page_size);
- return TRUE;
-}
-
-static int cfs_block_read( cybiko_file_system *cfs, UINT8 *buffer, int block_type, UINT32 block)
-{
- UINT8 buffer_page[MAX_PAGE_SIZE];
- UINT32 page;
- if (!cfs_block_to_page( cfs, block_type, block, &page)) return FALSE;
- if (!cfs_page_read( cfs, buffer_page, page)) return FALSE;
- memcpy( buffer, buffer_page + 2, cfs->page_size - 2);
- return TRUE;
-}
-
-static int cfs_block_write( cybiko_file_system *cfs, UINT8 *buffer, int block_type, UINT32 block)
-{
- UINT8 buffer_page[MAX_PAGE_SIZE];
- UINT32 page;
- UINT16 checksum;
- memcpy( buffer_page + 2, buffer, cfs->page_size - 2);
- if (block_type == BLOCK_TYPE_BOOT)
- {
- checksum = 0xFFFF;
- }
- else
- {
- checksum = page_buffer_calc_checksum( buffer_page + 2, cfs->page_size - 2);
- }
- buffer_write_16_be( buffer_page + 0, checksum);
- if (!cfs_block_to_page( cfs, block_type, block, &page)) return FALSE;
- if (!cfs_page_write( cfs, buffer_page, page)) return FALSE;
- return TRUE;
-}
-
-static int cfs_file_delete( cybiko_file_system *cfs, UINT16 file_id)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return FALSE;
- if (BLOCK_USED(buffer) && (BLOCK_FILE_ID(buffer) == file_id))
- {
- buffer[0] &= ~0x80;
- if (!cfs_block_write( cfs, buffer, BLOCK_TYPE_FILE, i)) return FALSE;
- }
- }
- return TRUE;
-}
-
-static int cfs_file_info( cybiko_file_system *cfs, UINT16 file_id, cfs_file *file)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i;
- file->blocks = file->size = 0;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return FALSE;
- if (BLOCK_USED(buffer) && (BLOCK_FILE_ID(buffer) == file_id))
- {
- if (BLOCK_PART_ID(buffer) == 0)
- {
- strcpy( file->name, BLOCK_FILENAME(buffer));
- file->date = buffer_read_32_be( buffer + 6 + FILE_HEADER_SIZE - 4);
- }
- file->size += buffer[1];
- file->blocks++;
- }
- }
- return (file->blocks > 0) ? TRUE : FALSE;
-}
-
-static int cfs_file_find( cybiko_file_system *cfs, const char *filename, UINT16 *file_id)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return FALSE;
- if (BLOCK_USED(buffer) && (BLOCK_PART_ID(buffer) == 0) && (strcmp( filename, BLOCK_FILENAME(buffer)) == 0))
- {
- *file_id = i;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static int cfs_verify( cybiko_file_system *cfs)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i, block_type;
- for (i=0;i<cfs->page_count;i++)
- {
- if (!cfs_page_read( cfs, buffer, i)) return FALSE;
- if (!cfs_page_to_block( cfs, i, &block_type, NULL)) return FALSE;
- if (!page_buffer_verify( buffer, cfs->page_size, block_type)) return FALSE;
- }
- return TRUE;
-}
-
-static int cfs_init( cybiko_file_system *cfs, imgtool_stream *stream)
-{
- cfs->stream = stream;
- cfs->page_count = 2005;
- cfs->page_size = 258;
- cfs->block_count_boot = 5;
- cfs->block_count_file = cfs->page_count - cfs->block_count_boot;
- cfs->write_count = 0;
- return TRUE;
-}
-
-static int cfs_format( cybiko_file_system *cfs)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i;
- // boot blocks
- memset( buffer, 0xFF, sizeof( buffer));
- for (i=0;i<cfs->block_count_boot;i++)
- {
- if (!cfs_block_write( cfs, buffer, BLOCK_TYPE_BOOT, i)) return FALSE;
- }
- // file blocks
- memset( buffer, 0xFF, sizeof( buffer));
- buffer[0] &= ~0x80;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_write( cfs, buffer, BLOCK_TYPE_FILE, i)) return FALSE;
- }
- // padding
- buffer[0] = 0xFF;
- for (i=0;i<0x1B56;i++)
- {
- stream_write( cfs->stream, buffer, 1);
- }
- // ok
- return TRUE;
-}
-
-static UINT16 cfs_calc_free_blocks( cybiko_file_system *cfs)
-{
- UINT8 buffer[MAX_PAGE_SIZE];
- int i;
- UINT16 blocks = 0;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return 0;
- if (!BLOCK_USED(buffer)) blocks++;
- }
- return blocks;
-}
-
-static UINT32 cfs_calc_free_space( cybiko_file_system *cfs, UINT16 blocks)
-{
- UINT32 free_space;
- free_space = blocks * ((cfs->page_size - 2) - 6);
- if (free_space > 0) free_space -= FILE_HEADER_SIZE;
- return free_space;
-}
-
-static imgtoolerr_t cybiko_image_open( imgtool_image *image, imgtool_stream *stream)
-{
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- // init
- if (!cfs_init( cfs, stream)) return IMGTOOLERR_CORRUPTIMAGE;
- // verify
- if (!cfs_verify( cfs)) return IMGTOOLERR_CORRUPTIMAGE;
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-static void cybiko_image_close( imgtool_image *image)
-{
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- stream_close( cfs->stream);
-}
-
-static imgtoolerr_t cybiko_image_create( imgtool_image *image, imgtool_stream *stream, option_resolution *opts)
-{
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- // init
- if (!cfs_init( cfs, stream)) return IMGTOOLERR_CORRUPTIMAGE;
- // format
- if (!cfs_format( cfs)) return IMGTOOLERR_CORRUPTIMAGE;
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t cybiko_image_begin_enum( imgtool_directory *enumeration, const char *path)
-{
- cybiko_iter *iter = (cybiko_iter*)imgtool_directory_extrabytes( enumeration);
- iter->block = 0;
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t cybiko_image_next_enum( imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- imgtool_image *image = imgtool_directory_image( enumeration);
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- cybiko_iter *iter = (cybiko_iter*)imgtool_directory_extrabytes( enumeration);
- UINT8 buffer[MAX_PAGE_SIZE];
- UINT16 file_id = INVALID_FILE_ID;
- cfs_file file;
- // find next file
- while (iter->block < cfs->block_count_file)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, iter->block++)) return IMGTOOLERR_READERROR;
- if (BLOCK_USED(buffer) && (BLOCK_PART_ID(buffer) == 0))
- {
- file_id = BLOCK_FILE_ID(buffer);
- break;
- }
- }
- // get file information
- if ((file_id != INVALID_FILE_ID) && cfs_file_info( cfs, file_id, &file))
- {
- strcpy( ent->filename, file.name);
- ent->filesize = file.size;
- ent->lastmodified_time = time_crack( file.date);
- ent->filesize = file.size;
- }
- else
- {
- ent->eof = 1;
- }
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-static void cybiko_image_close_enum( imgtool_directory *enumeration)
-{
- // nothing
-}
-
-static imgtoolerr_t cybiko_image_free_space( imgtool_partition *partition, UINT64 *size)
-{
- imgtool_image *image = imgtool_partition_image( partition);
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- if (size) *size = cfs_calc_free_space( cfs, cfs_calc_free_blocks( cfs));
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t cybiko_image_read_file( imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- imgtool_image *image = imgtool_partition_image( partition);
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- UINT8 buffer[MAX_PAGE_SIZE];
- UINT16 file_id, part_id = 0, old_part_id;
- int i;
- // check filename
- if (strlen( filename) > 58) return IMGTOOLERR_BADFILENAME;
- // find file
- if (!cfs_file_find( cfs, filename, &file_id)) return IMGTOOLERR_FILENOTFOUND;
- // read file
- do
- {
- old_part_id = part_id;
- for (i=0;i<cfs->block_count_file;i++)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return IMGTOOLERR_READERROR;
- if (BLOCK_USED(buffer) && (BLOCK_FILE_ID(buffer) == file_id) && (BLOCK_PART_ID(buffer) == part_id))
- {
- stream_write( destf, buffer + 6 + ((part_id == 0) ? FILE_HEADER_SIZE : 0), buffer[1]);
- part_id++;
- }
- }
- } while (old_part_id != part_id);
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t cybiko_image_write_file( imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- imgtool_image *image = imgtool_partition_image( partition);
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- UINT8 buffer[MAX_PAGE_SIZE];
- UINT16 file_id, part_id = 0, free_blocks;
- UINT64 bytes_left;
- cfs_file file;
- int i;
- // check filename
- if (strlen( filename) > 58) return IMGTOOLERR_BADFILENAME;
- // find file
- if (!cfs_file_find( cfs, filename, &file_id)) file_id = INVALID_FILE_ID;
- // check free space
- free_blocks = cfs_calc_free_blocks( cfs);
- if (file_id != INVALID_FILE_ID)
- {
- if (!cfs_file_info( cfs, file_id, &file)) return IMGTOOLERR_UNEXPECTED;
- free_blocks += file.blocks;
- }
- if (cfs_calc_free_space( cfs, free_blocks) < stream_size( sourcef)) return IMGTOOLERR_NOSPACE;
- // delete file
- if (file_id != INVALID_FILE_ID)
- {
- if (!cfs_file_delete( cfs, file_id)) return IMGTOOLERR_UNEXPECTED;
- }
- // create/write destination file
- bytes_left = stream_size( sourcef);
- i = 0;
- while (i < cfs->block_count_file)
- {
- if (!cfs_block_read( cfs, buffer, BLOCK_TYPE_FILE, i)) return IMGTOOLERR_READERROR;
- if (!BLOCK_USED(buffer))
- {
- if (part_id == 0) file_id = i;
- memset( buffer, 0xFF, cfs->page_size - 0x02);
- buffer[0] = 0x80;
- buffer[1] = (cfs->page_size - 2) - 6 - ((part_id == 0) ? FILE_HEADER_SIZE : 0);
- if (bytes_left < buffer[1]) buffer[1] = bytes_left;
- buffer_write_16_be( buffer + 2, file_id);
- buffer_write_16_be( buffer + 4, part_id);
- if (part_id == 0)
- {
- buffer[6] = 0x20;
- strcpy( BLOCK_FILENAME(buffer), filename);
- buffer_write_32_be( buffer + 6 + FILE_HEADER_SIZE - 4, time_setup( time( NULL)));
- stream_read( sourcef, buffer + 6 + FILE_HEADER_SIZE, buffer[1]);
- }
- else
- {
- stream_read( sourcef, buffer + 6, buffer[1]);
- }
- if (!cfs_block_write( cfs, buffer, BLOCK_TYPE_FILE, i)) return IMGTOOLERR_WRITEERROR;
- bytes_left -= buffer[1];
- if (bytes_left == 0) break;
- part_id++;
- }
- i++;
- }
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t cybiko_image_delete_file( imgtool_partition *partition, const char *filename)
-{
- imgtool_image *image = imgtool_partition_image( partition);
- cybiko_file_system *cfs = (cybiko_file_system*)imgtool_image_extra_bytes( image);
- UINT16 file_id;
- // check filename
- if (strlen( filename) > 58) return IMGTOOLERR_BADFILENAME;
- // find file
- if (!cfs_file_find( cfs, filename, &file_id)) return IMGTOOLERR_FILENOTFOUND;
- // delete file
- if (!cfs_file_delete( cfs, file_id)) return IMGTOOLERR_UNEXPECTED;
- // ok
- return IMGTOOLERR_SUCCESS;
-}
-
-void cybikoxt_get_info( const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch (state)
- {
- // --- the following bits of info are returned as 64-bit signed integers ---
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES : info->i = sizeof( cybiko_file_system); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES : info->i = sizeof( cybiko_iter); break;
-// case IMGTOOLINFO_INT_SUPPORTS_CREATION_TIME : info->i = 1; break;
- case IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME : info->i = 1; break;
-// case IMGTOOLINFO_INT_BLOCK_SIZE : info->i = 264; break;
- // --- the following bits of info are returned as pointers to data or functions ---
- case IMGTOOLINFO_PTR_OPEN : info->open = cybiko_image_open; break;
- case IMGTOOLINFO_PTR_CREATE : info->create = cybiko_image_create; break;
- case IMGTOOLINFO_PTR_CLOSE : info->close = cybiko_image_close; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM : info->begin_enum = cybiko_image_begin_enum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM : info->next_enum = cybiko_image_next_enum; break;
- case IMGTOOLINFO_PTR_CLOSE_ENUM : info->close_enum = cybiko_image_close_enum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE : info->free_space = cybiko_image_free_space; break;
- case IMGTOOLINFO_PTR_READ_FILE : info->read_file = cybiko_image_read_file; break;
- case IMGTOOLINFO_PTR_WRITE_FILE : info->write_file = cybiko_image_write_file; break;
- case IMGTOOLINFO_PTR_DELETE_FILE : info->delete_file = cybiko_image_delete_file; break;
- // --- the following bits of info are returned as NULL-terminated strings ---
- case IMGTOOLINFO_STR_NAME : strcpy( info->s = imgtool_temp_str(), "cybikoxt"); break;
- case IMGTOOLINFO_STR_DESCRIPTION : strcpy( info->s = imgtool_temp_str(), "Cybiko Xtreme File System"); break;
- case IMGTOOLINFO_STR_FILE : strcpy( info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS : strcpy( info->s = imgtool_temp_str(), "bin,nv"); break;
- case IMGTOOLINFO_STR_EOLN : strcpy( info->s = imgtool_temp_str(), "\r\n"); break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/fat.c b/src/mess/tools/imgtool/modules/fat.c
deleted file mode 100644
index 4f2fca17c25..00000000000
--- a/src/mess/tools/imgtool/modules/fat.c
+++ /dev/null
@@ -1,2111 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- fat.c
-
- PC FAT disk images
-
-*****************************************************************************
-
- Master boot record format:
-
- Offset Length Description
- ------ ------ -----------
- 0 446 Boot machine code
- 446 16 Partion #1 info
- 462 16 Partion #2 info
- 478 16 Partion #3 info
- 494 16 Partion #4 info
- 510 2 Magic bytes (0x55 0xAA)
-
-
- Partition info format:
-
- Offset Length Description
- ------ ------ -----------
- 0 1 Active byte (0x80=active 0x00=inactive)
- 1 1 Starting head
- 2 1 Starting sector (bits 5-0) and high bits of starting track (bits 6-5)
- 3 1 Low bits of starting track
- 4 1 Partition type:
- 0x00 Unused
- 0x?1 FAT12 (0-15 MB)
- 0x?2 XENIX
- 0x?4 FAT16 (16-32 MB)
- 0x?6 FAT16` (32 MB-2 GB)
- 0x?7 HPFS or NTFS
- 0x?A Boot Manager
- 0x?B FAT32 (512 MB-2 TB)
- 0x?C FAT32 (512 MB-2 TB LBA)
- 0x1? OS/2 Boot manager/Win95 hidden
- 0xC? DR-DOS secured partition
- 0xD? Multiuser DOS secured partition
- 0xE? SpeedStor extended partition
- 5 1 Ending head
- 6 1 Ending sector (bits 5-0) and high bits of ending track (bits 6-5)
- 7 1 Low bits of ending track
- 8 4 Sector index of beginning of partition
- 12 4 Total sectors in partition
-
-
- Boot sector format:
-
- Offset Length Description
- ------ ------ -----------
- 0 3 Jump instruction (to skip over header on boot)
- 3 8 OEM Name
- 11 2 Bytes per sector
- 13 1 Sectors per cluster
- 14 2 Reserved sector count (including boot sector)
- 16 1 Number of FATs (file allocation tables)
- 17 2 Number of root directory entries
- 19 2 Total sectors (bits 0-15)
- 21 1 Media descriptor
- 22 2 Sectors per FAT
- 24 2 Sectors per track
- 26 2 Number of heads
- 28 4 Hidden sectors
- 32 4 Total sectors (bits 16-47)
- 36 1 Physical drive number
- 37 1 Current head
- 38 1 Signature
- 39 4 ID
- 43 11 Volume Label
- 54 8 FAT file system type
- 62 448 Boot machine code
- 510 2 Magic bytes (0x55 0xAA)
-
- For more information:
- http://support.microsoft.com/kb/q140418/
-
-
- Directory Entry Format:
-
- Offset Length Description
- ------ ------ -----------
- 0 8 DOS File Name (padded with spaces)
- 8 3 DOS File Extension (padded with spaces)
- 11 1 File Attributes
- 12 2 Unknown
- 14 4 Time of Creation
- 18 2 Last Access Time
- 20 2 EA-Index (OS/2 stuff)
- 22 4 Last Modified Time
- 26 2 First Cluster
- 28 4 File Size
-
-
- Dates and times are stored in separate words; when together, the time is
- first and the date is second.
-
- Time:
- bits 15-11 Hour
- bits 10- 5 Minute
- bits 4- 0 Second / 2
-
- Date:
- bits 15- 9 Year - 1980
- bits 8- 5 Month
- bits 4- 0 Day
-
- LFN Entry Format:
-
- Offset Length Description
- ------ ------ -----------
- 0 1 Sequence Number (bit 6 is set on highest sequence)
- 1 10 Name characters (five UTF-16LE chars)
- 11 1 Attributes (always 0x0F)
- 12 1 Reserved (always 0x00)
- 13 1 Checksum of short filename entry
- 14 12 Name characters (six UTF-16LE chars)
- 26 2 Entry Cluster (always 0x00)
- 28 4 Name characters (two UTF-16LE chars)
-
- Valid characters in DOS file names:
- - Upper case letters A-Z
- - Numbers 0-9
- - Space (though there is no way to identify a trailing space)
- - ! # $ % & ( ) - @ ^ _ ` { } ~
- - Characters 128-255 (though the code page is indeterminate)
-
- For more information:
- http://en.wikipedia.org/wiki/File_Allocation_Table
-
-****************************************************************************/
-
-#include <time.h>
-#include <ctype.h>
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "unicode.h"
-#include "fat.h"
-
-#define FAT_DIRENT_SIZE 32
-#define FAT_SECLEN 512
-
-#define LOG(x)
-
-struct fat_partition_info
-{
- UINT32 fat_bits;
- UINT32 sectors_per_cluster;
- UINT32 cluster_size;
- UINT32 reserved_sectors;
- UINT32 fat_count;
- UINT32 root_entries;
- UINT32 sectors_per_fat;
- UINT64 total_sectors;
- UINT32 total_clusters;
-};
-
-struct fat_file
-{
- unsigned int root : 1;
- unsigned int directory : 1;
- unsigned int eof : 1;
- UINT32 index;
- UINT32 filesize;
- UINT32 first_cluster;
- UINT32 parent_first_cluster;
- UINT32 cluster;
- UINT32 cluster_index;
- UINT32 dirent_sector_index;
- UINT32 dirent_sector_offset;
-};
-
-struct fat_dirent
-{
- char long_filename[512];
- char short_filename[13];
- unsigned int directory : 1;
- unsigned int eof : 1;
- UINT32 filesize;
- UINT32 first_cluster;
- UINT32 dirent_sector_index;
- UINT32 dirent_sector_offset;
- time_t creation_time;
- time_t lastmodified_time;
-};
-
-struct fat_freeentry_info
-{
- UINT32 required_size;
- UINT32 candidate_position;
- UINT32 position;
-};
-
-struct fat_mediatype
-{
- UINT8 media_descriptor;
- UINT8 heads;
- UINT8 tracks;
- UINT8 sectors;
-};
-
-enum creation_policy_t
-{
- CREATE_NONE,
- CREATE_FILE,
- CREATE_DIR
-};
-
-
-
-static const fat_mediatype known_media[] =
-{
- { 0xF0, 2, 80, 36 },
- { 0xF0, 2, 80, 18 },
- { 0xF9, 2, 80, 9 },
- { 0xF9, 2, 80, 15 },
- { 0xFD, 2, 40, 9 },
- { 0xFF, 2, 40, 8 },
- { 0xFC, 1, 40, 9 },
- { 0xFE, 1, 40, 8 },
- { 0xF8, 0, 0, 0 }
-};
-
-/* boot sector code taken from FreeDOS */
-static const UINT8 boot_sector_code[] =
-{
- 0xfa, 0xfc, 0x31, 0xc0, 0x8e, 0xd8, 0xbd, 0x00, 0x7c, 0xb8, 0xe0, 0x1f,
- 0x8e, 0xc0, 0x89, 0xee, 0x89, 0xef, 0xb9, 0x00, 0x01, 0xf3, 0xa5, 0xea,
- 0x5e, 0x7c, 0xe0, 0x1f, 0x00, 0x00, 0x60, 0x00, 0x8e, 0xd8, 0x8e, 0xd0,
- 0x8d, 0x66, 0xa0, 0xfb, 0x80, 0x7e, 0x24, 0xff, 0x75, 0x03, 0x88, 0x56,
- 0x24, 0xc7, 0x46, 0xc0, 0x10, 0x00, 0xc7, 0x46, 0xc2, 0x01, 0x00, 0x8b,
- 0x76, 0x1c, 0x8b, 0x7e, 0x1e, 0x03, 0x76, 0x0e, 0x83, 0xd7, 0x00, 0x89,
- 0x76, 0xd2, 0x89, 0x7e, 0xd4, 0x8a, 0x46, 0x10, 0x98, 0xf7, 0x66, 0x16,
- 0x01, 0xc6, 0x11, 0xd7, 0x89, 0x76, 0xd6, 0x89, 0x7e, 0xd8, 0x8b, 0x5e,
- 0x0b, 0xb1, 0x05, 0xd3, 0xeb, 0x8b, 0x46, 0x11, 0x31, 0xd2, 0xf7, 0xf3,
- 0x89, 0x46, 0xd0, 0x01, 0xc6, 0x83, 0xd7, 0x00, 0x89, 0x76, 0xda, 0x89,
- 0x7e, 0xdc, 0x8b, 0x46, 0xd6, 0x8b, 0x56, 0xd8, 0x8b, 0x7e, 0xd0, 0xc4,
- 0x5e, 0x5a, 0xe8, 0xac, 0x00, 0xc4, 0x7e, 0x5a, 0xb9, 0x0b, 0x00, 0xbe,
- 0xf1, 0x7d, 0x57, 0xf3, 0xa6, 0x5f, 0x26, 0x8b, 0x45, 0x1a, 0x74, 0x0b,
- 0x83, 0xc7, 0x20, 0x26, 0x80, 0x3d, 0x00, 0x75, 0xe7, 0x72, 0x68, 0x50,
- 0xc4, 0x5e, 0x5a, 0x8b, 0x7e, 0x16, 0x8b, 0x46, 0xd2, 0x8b, 0x56, 0xd4,
- 0xe8, 0x7e, 0x00, 0x58, 0x1e, 0x07, 0x8e, 0x5e, 0x5c, 0xbf, 0x00, 0x20,
- 0xab, 0x89, 0xc6, 0x01, 0xf6, 0x01, 0xc6, 0xd1, 0xee, 0xad, 0x73, 0x04,
- 0xb1, 0x04, 0xd3, 0xe8, 0x80, 0xe4, 0x0f, 0x3d, 0xf8, 0x0f, 0x72, 0xe8,
- 0x31, 0xc0, 0xab, 0x0e, 0x1f, 0xc4, 0x5e, 0x5a, 0xbe, 0x00, 0x20, 0xad,
- 0x09, 0xc0, 0x75, 0x05, 0x88, 0xd3, 0xff, 0x6e, 0x5a, 0x48, 0x48, 0x8b,
- 0x7e, 0x0d, 0x81, 0xe7, 0xff, 0x00, 0xf7, 0xe7, 0x03, 0x46, 0xda, 0x13,
- 0x56, 0xdc, 0xe8, 0x34, 0x00, 0xeb, 0xe0, 0x5e, 0xac, 0x56, 0xb4, 0x0e,
- 0xcd, 0x10, 0x3c, 0x2e, 0x75, 0xf5, 0xc3, 0xe8, 0xf1, 0xff, 0x45, 0x72,
- 0x72, 0x6f, 0x72, 0x21, 0x20, 0x48, 0x69, 0x74, 0x20, 0x61, 0x20, 0x6b,
- 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74,
- 0x2e, 0x30, 0xe4, 0xcd, 0x13, 0xcd, 0x16, 0xcd, 0x19, 0x56, 0x89, 0x46,
- 0xc8, 0x89, 0x56, 0xca, 0x8c, 0x46, 0xc6, 0x89, 0x5e, 0xc4, 0xe8, 0xbe,
- 0xff, 0x2e, 0xb4, 0x41, 0xbb, 0xaa, 0x55, 0x8a, 0x56, 0x24, 0x84, 0xd2,
- 0x74, 0x19, 0xcd, 0x13, 0x72, 0x15, 0xd1, 0xe9, 0x81, 0xdb, 0x54, 0xaa,
- 0x75, 0x0d, 0x8d, 0x76, 0xc0, 0x89, 0x5e, 0xcc, 0x89, 0x5e, 0xce, 0xb4,
- 0x42, 0xeb, 0x26, 0x8b, 0x4e, 0xc8, 0x8b, 0x56, 0xca, 0x8a, 0x46, 0x18,
- 0xf6, 0x66, 0x1a, 0x91, 0xf7, 0xf1, 0x92, 0xf6, 0x76, 0x18, 0x89, 0xd1,
- 0x88, 0xc6, 0x86, 0xe9, 0xd0, 0xc9, 0xd0, 0xc9, 0x08, 0xe1, 0x41, 0xc4,
- 0x5e, 0xc4, 0xb8, 0x01, 0x02, 0x8a, 0x56, 0x24, 0xcd, 0x13, 0x0f, 0x82,
- 0x75, 0xff, 0x8b, 0x46, 0x0b, 0xf6, 0x76, 0xc0, 0x01, 0x46, 0xc6, 0x83,
- 0x46, 0xc8, 0x01, 0x83, 0x56, 0xca, 0x00, 0x4f, 0x75, 0x98, 0x8e, 0x46,
- 0xc6, 0x5e, 0xc3, 0x4d, 0x45, 0x54, 0x41, 0x4b, 0x45, 0x52, 0x4e, 0x53,
- 0x59, 0x53, 0x00, 0x00, 0x55, 0xaa
-};
-
-static const char fat8_string[8] = { 'F', 'A', 'T', ' ', ' ', ' ', ' ', ' ' };
-static const char fat12_string[8] = { 'F', 'A', 'T', '1', '2', ' ', ' ', ' ' };
-static const char fat16_string[8] = { 'F', 'A', 'T', '1', '6', ' ', ' ', ' ' };
-static const char fat32_string[8] = { 'F', 'A', 'T', '3', '2', ' ', ' ', ' ' };
-
-
-
-static fat_partition_info *fat_get_partition_info(imgtool_partition *partition)
-{
- return (fat_partition_info *) imgtool_partition_extra_bytes(partition);
-}
-
-
-
-static imgtoolerr_t fat_read_sector(imgtool_partition *partition, UINT32 sector_index,
- int offset, void *buffer, size_t buffer_len)
-{
- //const fat_partition_info *disk_info;
- imgtoolerr_t err;
- UINT8 data[FAT_SECLEN];
- UINT32 block_size;
- size_t len;
-
- //disk_info = fat_get_partition_info(partition);
-
- /* sanity check */
- err = imgtool_partition_get_block_size(partition, &block_size);
- if (err)
- return err;
- assert(block_size == sizeof(data));
-
- while(buffer_len > 0)
- {
- err = imgtool_partition_read_block(partition, sector_index++, data);
- if (err)
- return err;
-
- len = MIN(buffer_len, sizeof(data) - offset);
- memcpy(buffer, data + offset, len);
-
- buffer = ((UINT8 *) buffer) + len;
- buffer_len -= len;
- offset = 0;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_write_sector(imgtool_partition *partition, UINT32 sector_index,
- int offset, const void *buffer, size_t buffer_len)
-{
- //const fat_partition_info *disk_info;
- imgtoolerr_t err;
- UINT8 data[FAT_SECLEN];
- const void *write_data;
- UINT32 block_size;
- size_t len;
-
- //disk_info = fat_get_partition_info(partition);
-
- /* sanity check */
- err = imgtool_partition_get_block_size(partition, &block_size);
- if (err)
- return err;
- assert(block_size == sizeof(data));
-
- while(buffer_len > 0)
- {
- len = MIN(buffer_len, sizeof(data) - offset);
-
- if ((offset != 0) || (buffer_len < sizeof(data)))
- {
- err = imgtool_partition_read_block(partition, sector_index, data);
- if (err)
- return err;
- memcpy(data + offset, buffer, len);
- write_data = data;
- }
- else
- {
- write_data = buffer;
- }
-
- err = imgtool_partition_write_block(partition, sector_index++, write_data);
- if (err)
- return err;
-
- buffer = ((UINT8 *) buffer) + len;
- buffer_len -= len;
- offset = 0;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t fat_clear_sector(imgtool_partition *partition, UINT32 sector_index, UINT8 data)
-{
- char buf[FAT_SECLEN];
- memset(buf, data, sizeof(buf));
- return fat_write_sector(partition, sector_index, 0, buf, sizeof(buf));
-}
-#endif
-
-
-static imgtoolerr_t fat_partition_open(imgtool_partition *partition, UINT64 first_block, UINT64 block_count)
-{
- UINT8 header[FAT_SECLEN];
- imgtoolerr_t err;
- fat_partition_info *info;
- UINT32 fat_bits, total_sectors_l, total_sectors_h, sector_size;
- UINT64 available_sectors;
- //int has_extended_bios_param_block = TRUE;
-
- info = fat_get_partition_info(partition);
-
- /* read the boot/root sector */
- err = fat_read_sector(partition, 0, 0, header, sizeof(header));
- if (err)
- return err;
-
- /* magic bytes present? */
- if ((header[510] != 0x55) || (header[511] != 0xAA))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* determine which type of FAT is on this disk */
- if (!memcmp(&header[54], fat8_string, sizeof(fat8_string)))
- fat_bits = 8;
- else if (!memcmp(&header[54], fat12_string, sizeof(fat12_string)))
- fat_bits = 12;
- else if (!memcmp(&header[54], fat16_string, sizeof(fat16_string)))
- fat_bits = 16;
- else if (!memcmp(&header[54], fat32_string, sizeof(fat32_string)))
- fat_bits = 32;
- else
- {
- fat_bits = 8;
- //has_extended_bios_param_block = FALSE;
- }
-
- info->fat_bits = fat_bits;
- sector_size = pick_integer_le(header, 11, 2);
- info->sectors_per_cluster = pick_integer_le(header, 13, 1);
- info->reserved_sectors = pick_integer_le(header, 14, 2);
- info->fat_count = pick_integer_le(header, 16, 1);
- info->root_entries = pick_integer_le(header, 17, 2);
- total_sectors_l = pick_integer_le(header, 19, 2);
- info->sectors_per_fat = pick_integer_le(header, 22, 2);
- total_sectors_h = pick_integer_le(header, 32, 4);
-
- if (info->sectors_per_cluster == 0)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- info->total_sectors = total_sectors_l + (((UINT64) total_sectors_h) << 16);
- available_sectors = info->total_sectors - info->reserved_sectors
- - (info->sectors_per_fat * info->fat_count)
- - (info->root_entries * FAT_DIRENT_SIZE + FAT_SECLEN - 1) / FAT_SECLEN;
- info->total_clusters = (available_sectors + info->sectors_per_cluster - 1) / info->sectors_per_cluster;
- info->cluster_size = FAT_SECLEN * info->sectors_per_cluster;
-
- if (info->fat_count == 0)
- return IMGTOOLERR_CORRUPTIMAGE;
- if (sector_size != FAT_SECLEN)
- return IMGTOOLERR_CORRUPTIMAGE;
- if (info->sectors_per_fat == 0)
- return IMGTOOLERR_CORRUPTIMAGE;
- if (info->sectors_per_cluster == 0)
- return IMGTOOLERR_CORRUPTIMAGE;
- if (info->reserved_sectors == 0)
- return IMGTOOLERR_CORRUPTIMAGE;
- if (info->total_clusters * info->fat_bits > info->sectors_per_fat * FAT_SECLEN * 8)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_partition_create(imgtool_image *image, UINT64 first_block, UINT64 block_count)
-{
- imgtoolerr_t err;
- UINT32 heads, tracks, sectors_per_track;
- UINT32 fat_bits, sectors_per_cluster, reserved_sectors, hidden_sectors;
- UINT32 root_dir_count, root_dir_sectors;
- UINT32 sectors_per_fat, fat_count, i;
- UINT32 boot_sector_offset;
- UINT64 total_clusters;
- UINT8 media_descriptor;
- //const char *title;
- const char *fat_bits_string;
- UINT8 header[FAT_SECLEN];
-#if 0
- UINT64 first_fat_entries;
-#endif
-
- /* check for limits */
- if (block_count > U64(0xFFFFFFFFFFFF))
- return IMGTOOLERR_PARAMTOOLARGE;
-
- /* get the geometry */
- err = imgtool_image_get_geometry(image, &tracks, &heads, &sectors_per_track);
- if (err)
- return err;
-
- /* cap our sector count so that we only use FAT12/16 */
- sectors_per_cluster = (block_count + 65524 - 1) / 65524;
-
- /* compute the FAT file system type */
- if ((block_count / sectors_per_cluster) <= 4084)
- {
- fat_bits = 12;
- fat_bits_string = fat12_string;
- }
- else if ((block_count / sectors_per_cluster) <= 65524)
- {
- fat_bits = 16;
- fat_bits_string = fat16_string;
- }
- else
- {
- fat_bits = 32;
- fat_bits_string = fat32_string;
- }
-
- /* figure out media type */
- i = 0;
- while((known_media[i].heads > 0) && ((known_media[i].heads != heads)
- || (known_media[i].tracks != tracks)
- || (known_media[i].sectors != sectors_per_track)))
- {
- i++;
- }
- media_descriptor = known_media[i].media_descriptor;
-
- /* other miscellaneous settings */
- //title = "";
- fat_count = 2;
- root_dir_count = 512;
- hidden_sectors = 0;
- reserved_sectors = 1;
-
- /* calculated settings */
- root_dir_sectors = (root_dir_count * FAT_DIRENT_SIZE + FAT_SECLEN - 1) / FAT_SECLEN;
- total_clusters = (block_count - reserved_sectors - hidden_sectors - root_dir_sectors)
- / sectors_per_cluster;
- sectors_per_fat = (total_clusters * fat_bits + (FAT_SECLEN * 8) - 1)
- / (FAT_SECLEN * 8);
-
- /* prepare the header */
- memset(header, 0, sizeof(header));
- memcpy(&header[3], "IMGTOOL ", 8);
- place_integer_le(header, 11, 2, FAT_SECLEN);
- place_integer_le(header, 13, 1, sectors_per_cluster);
- place_integer_le(header, 14, 1, reserved_sectors);
- place_integer_le(header, 16, 1, fat_count);
- place_integer_le(header, 17, 2, root_dir_count);
- place_integer_le(header, 19, 2, (UINT16) (block_count >> 0));
- place_integer_le(header, 21, 1, media_descriptor);
- place_integer_le(header, 22, 2, sectors_per_fat);
- place_integer_le(header, 24, 2, sectors_per_track);
- place_integer_le(header, 26, 2, heads);
- place_integer_le(header, 28, 4, hidden_sectors);
- place_integer_le(header, 32, 4, (UINT32) (block_count >> 16));
- place_integer_le(header, 36, 1, 0xFF);
- place_integer_le(header, 38, 1, 0x28);
- place_integer_le(header, 39, 4, imgtool_image_rand(image));
- memcpy(&header[43], " ", 11);
- memcpy(&header[54], fat_bits_string, 8);
-
- /* store boot code */
- boot_sector_offset = sizeof(header) - sizeof(boot_sector_code);
- if (boot_sector_offset < 62)
- return IMGTOOLERR_UNEXPECTED; /* sanity check */
- if (boot_sector_offset > 510)
- return IMGTOOLERR_UNEXPECTED; /* sanity check */
- memcpy(&header[boot_sector_offset], boot_sector_code, sizeof(boot_sector_code));
-
- /* specify jump instruction */
- if (boot_sector_offset <= 129)
- {
- header[0] = 0xEB; /* JMP rel8 */
- header[1] = (UINT8) (boot_sector_offset - 2); /* (offset) */
- header[2] = 0x90; /* NOP */
- }
- else
- {
- header[0] = 0xE9; /* JMP rel16 */
- header[1] = (UINT8) ((boot_sector_offset - 2) >> 0); /* (offset) */
- header[2] = (UINT8) ((boot_sector_offset - 2) >> 8); /* (offset) */
- }
-
- err = imgtool_image_write_block(image, first_block, header);
- if (err)
- return err;
-
- /* clear out file allocation table */
- for (i = reserved_sectors; i < (reserved_sectors + sectors_per_fat * fat_count + root_dir_sectors); i++)
- {
- err = imgtool_image_clear_block(image, first_block + i, 0);
- if (err)
- return err;
- }
-
- // FIXME: this causes a corrupt PC floppy image since it doubles the FAT partition header - works without it though
-#if 0
- /* set first two FAT entries */
- first_fat_entries = ((UINT64) media_descriptor) | 0xFFFFFF00;
- first_fat_entries &= (((UINT64) 1) << fat_bits) - 1;
- first_fat_entries |= ((((UINT64) 1) << fat_bits) - 1) << fat_bits;
- first_fat_entries = LITTLE_ENDIANIZE_INT64(first_fat_entries);
-
- for (i = 0; i < fat_count; i++)
- {
- err = imgtool_image_write_block(image, first_block + 1 + (i * sectors_per_fat), &first_fat_entries);
- if (err)
- return err;
- }
-#endif
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_load_fat(imgtool_partition *partition, UINT8 **fat_table)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- const fat_partition_info *disk_info;
- UINT8 *table;
- UINT32 table_size;
- UINT32 pos, len;
- UINT32 sector_index;
-
- disk_info = fat_get_partition_info(partition);
-
- table_size = disk_info->sectors_per_fat * disk_info->fat_count * FAT_SECLEN;
-
- /* allocate the table with extra bytes, in case we "overextend" our reads */
- table = (UINT8*)malloc(table_size + sizeof(UINT64));
- if (!table)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
- memset(table, 0, table_size + sizeof(UINT64));
-
- pos = 0;
- sector_index = disk_info->reserved_sectors;
-
- while(pos < table_size)
- {
- len = MIN(table_size - pos, FAT_SECLEN);
-
- err = fat_read_sector(partition, sector_index++, 0, &table[pos], len);
- if (err)
- goto done;
-
- pos += FAT_SECLEN;
- }
-
-done:
- if (err && table)
- {
- free(table);
- table = NULL;
- }
- *fat_table = table;
- return err;
-}
-
-
-
-static imgtoolerr_t fat_save_fat(imgtool_partition *partition, const UINT8 *fat_table)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- const fat_partition_info *disk_info;
- UINT32 table_size;
- UINT32 pos, len;
- UINT32 sector_index;
-
- disk_info = fat_get_partition_info(partition);
-
- table_size = disk_info->sectors_per_fat * disk_info->fat_count * FAT_SECLEN;
-
- pos = 0;
- sector_index = disk_info->reserved_sectors;
-
- while(pos < table_size)
- {
- len = MIN(table_size - pos, FAT_SECLEN);
-
- err = fat_write_sector(partition, sector_index++, 0, &fat_table[pos], len);
- if (err)
- goto done;
-
- pos += FAT_SECLEN;
- }
-
-done:
- return err;
-}
-
-
-
-static UINT32 fat_get_fat_entry(imgtool_partition *partition, const UINT8 *fat_table, UINT32 fat_entry)
-{
- const fat_partition_info *disk_info;
- UINT64 entry;
- UINT32 bit_index, i;
- UINT32 last_entry = 0;
- UINT32 bit_mask;
-
- disk_info = fat_get_partition_info(partition);
- bit_index = fat_entry * disk_info->fat_bits;
- bit_mask = 0xFFFFFFFF >> (32 - disk_info->fat_bits);
-
- if (fat_entry >= disk_info->total_clusters)
- {
- assert(0);
- return 1;
- }
-
- /* make sure that the cluster is free in all fats */
- for (i = 0; i < disk_info->fat_count; i++)
- {
- memcpy(&entry, fat_table + (i * FAT_SECLEN
- * disk_info->sectors_per_fat) + (bit_index / 8), sizeof(entry));
-
- /* we've extracted the bytes; we now need to normalize it */
- entry = LITTLE_ENDIANIZE_INT64(entry);
- entry >>= bit_index % 8;
- entry &= bit_mask;
-
- if (i == 0)
- last_entry = (UINT32) entry;
- else if (last_entry != (UINT32) entry)
- return 1; /* if the FATs disagree; mark this as reserved */
- }
-
- /* normalize special clusters */
- if (last_entry >= (0xFFFFFFF0 & bit_mask))
- {
- last_entry |= 0xFFFFFFF0;
- if (last_entry >= 0xFFFFFFF8)
- last_entry = 0xFFFFFFFF;
- }
- return last_entry;
-}
-
-
-
-static void fat_set_fat_entry(imgtool_partition *partition, UINT8 *fat_table, UINT32 fat_entry, UINT32 value)
-{
- const fat_partition_info *disk_info;
- UINT64 entry;
- UINT32 bit_index, i;
-
- disk_info = fat_get_partition_info(partition);
- bit_index = fat_entry * disk_info->fat_bits;
- value &= 0xFFFFFFFF >> (32 - disk_info->fat_bits);
-
- for (i = 0; i < disk_info->fat_count; i++)
- {
- memcpy(&entry, fat_table + (i * FAT_SECLEN
- * disk_info->sectors_per_fat) + (bit_index / 8), sizeof(entry));
-
- entry = LITTLE_ENDIANIZE_INT64(entry);
- entry &= (~((UINT64) 0xFFFFFFFF >> (32 - disk_info->fat_bits)) << (bit_index % 8)) | ((1 << (bit_index % 8)) - 1);
- entry |= ((UINT64) value) << (bit_index % 8);
- entry = LITTLE_ENDIANIZE_INT64(entry);
-
- memcpy(fat_table + (i * FAT_SECLEN
- * disk_info->sectors_per_fat) + (bit_index / 8), &entry, sizeof(entry));
- }
-}
-
-
-
-static void fat_debug_integrity_check(imgtool_partition *partition, const UINT8 *fat_table, const fat_file *file)
-{
-#ifdef MAME_DEBUG
- /* debug function to test the integrity of a file */
- UINT32 cluster;
- const fat_partition_info *disk_info;
-
- disk_info = fat_get_partition_info(partition);
- cluster = file->first_cluster ? file->first_cluster : 0xFFFFFFFF;
-
- if (!file->root)
- {
- while(cluster != 0xFFFFFFFF)
- {
- assert((cluster >= 2) && (cluster < disk_info->total_clusters));
- cluster = fat_get_fat_entry(partition, fat_table, cluster);
- }
- }
-#endif
-}
-
-
-
-static imgtoolerr_t fat_seek_file(imgtool_partition *partition, fat_file *file, UINT32 pos)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- const fat_partition_info *disk_info;
- UINT32 new_cluster;
- UINT8 *fat_table = NULL;
-
- disk_info = fat_get_partition_info(partition);
-
- /* can't seek past end of file */
- if (!file->directory && (pos > file->filesize))
- pos = file->filesize;
-
- if (file->first_cluster == 0)
- {
- /* special case; the root directory */
- file->index = pos;
- }
- else
- {
- /* first, we need to check to see if we have to go back to the beginning */
- if (pos < file->index)
- {
- file->cluster = file->first_cluster;
- file->cluster_index = 0;
- file->eof = 0;
- }
-
- /* skip ahead clusters */
- while((file->cluster_index + disk_info->cluster_size) <= pos)
- {
- if (!fat_table)
- {
- err = fat_load_fat(partition, &fat_table);
- if (err)
- goto done;
- }
-
- new_cluster = fat_get_fat_entry(partition, fat_table, file->cluster);
-
- file->cluster = new_cluster;
- file->cluster_index += disk_info->cluster_size;
-
- /* are we at the end of the file? */
- if (new_cluster == 0xFFFFFFFF)
- {
- pos = file->cluster_index;
- file->eof = 1;
- }
- }
- file->index = pos;
- }
-
-done:
- if (fat_table)
- free(fat_table);
- return err;
-}
-
-
-
-static UINT32 fat_get_filepos_sector_index(imgtool_partition *partition, fat_file *file)
-{
- UINT32 sector_index;
- const fat_partition_info *disk_info;
-
- disk_info = fat_get_partition_info(partition);
-
- sector_index = disk_info->reserved_sectors + (disk_info->sectors_per_fat * disk_info->fat_count);
- if (file->root)
- {
- /* special case for the root file */
- sector_index += file->index / FAT_SECLEN;
- }
- else
- {
- /* cluster out of range? */
- if ((file->cluster < 2) || (file->cluster >= disk_info->total_clusters))
- return 0;
-
- sector_index += (disk_info->root_entries * FAT_DIRENT_SIZE + FAT_SECLEN - 1) / FAT_SECLEN;
- sector_index += (file->cluster - 2) * disk_info->sectors_per_cluster;
- sector_index += (file->index / FAT_SECLEN) % disk_info->sectors_per_cluster;
- }
- return sector_index;
-}
-
-
-
-static imgtoolerr_t fat_corrupt_file_error(const fat_file *file)
-{
- imgtoolerr_t err;
- if (file->root)
- err = IMGTOOLERR_CORRUPTIMAGE;
- else if (file->directory)
- err = IMGTOOLERR_CORRUPTDIR;
- else
- err = IMGTOOLERR_CORRUPTFILE;
- return err;
-}
-
-
-
-static imgtoolerr_t fat_readwrite_file(imgtool_partition *partition, fat_file *file,
- void *buffer, size_t buffer_len, size_t *bytes_read, int read_or_write)
-{
- imgtoolerr_t err;
-// const fat_partition_info *disk_info;
- UINT32 sector_index;
- int offset;
- size_t len;
-
-// disk_info =
- fat_get_partition_info(partition);
- if (bytes_read)
- *bytes_read = 0;
- if (!file->directory)
- buffer_len = MIN(buffer_len, file->filesize - file->index);
-
- while(!file->eof && (buffer_len > 0))
- {
- sector_index = fat_get_filepos_sector_index(partition, file);
- if (sector_index == 0)
- return fat_corrupt_file_error(file);
-
- offset = file->index % FAT_SECLEN;
- len = MIN(buffer_len, FAT_SECLEN - offset);
-
- /* read or write the data from the disk */
- if (read_or_write)
- err = fat_write_sector(partition, sector_index, offset, buffer, len);
- else
- err = fat_read_sector(partition, sector_index, offset, buffer, len);
- if (err)
- return err;
-
- /* and move the file pointer ahead */
- err = fat_seek_file(partition, file, file->index + len);
- if (err)
- return err;
-
- buffer = ((UINT8 *) buffer) + len;
- buffer_len -= len;
- if (bytes_read)
- *bytes_read += len;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_read_file(imgtool_partition *partition, fat_file *file,
- void *buffer, size_t buffer_len, size_t *bytes_read)
-{
- return fat_readwrite_file(partition, file, buffer, buffer_len, bytes_read, 0);
-}
-
-
-
-static imgtoolerr_t fat_write_file(imgtool_partition *partition, fat_file *file,
- const void *buffer, size_t buffer_len, size_t *bytes_read)
-{
- return fat_readwrite_file(partition, file, (void *) buffer, buffer_len, bytes_read, 1);
-}
-
-
-
-static UINT32 fat_allocate_cluster(imgtool_partition *partition, UINT8 *fat_table)
-{
- const fat_partition_info *disk_info;
- UINT32 i, val;
-
- disk_info = fat_get_partition_info(partition);
-
- for (i = 2; i < disk_info->total_clusters; i++)
- {
- val = fat_get_fat_entry(partition, fat_table, i);
- if (val == 0)
- {
- fat_set_fat_entry(partition, fat_table, i, 1);
- return i;
- }
- }
- return 0;
-}
-
-
-
-/* sets the size of a file; ~0 means 'delete' */
-static imgtoolerr_t fat_set_file_size(imgtool_partition *partition, fat_file *file,
- UINT32 new_size)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- const fat_partition_info *disk_info;
- UINT32 new_cluster_count;
- UINT32 old_cluster_count;
- UINT32 cluster, write_cluster, last_cluster, new_pos, i;
- UINT8 *fat_table = NULL;
- UINT8 dirent[32];
- size_t clear_size;
- void *clear_buffer = NULL;
- int delete_file = FALSE;
- int rest_free = FALSE;
-
- disk_info = fat_get_partition_info(partition);
-
- LOG(("fat_set_file_size(): file->first_cluster=%d new_size=0x%08x\n", file->first_cluster, new_size));
-
- /* special case */
- if (new_size == ~0)
- {
- delete_file = TRUE;
- new_size = 0;
- }
-
- /* if this is the trivial case (not changing the size), succeed */
- if (!delete_file && (file->filesize == new_size))
- {
- err = IMGTOOLERR_SUCCESS;
- goto done;
- }
-
- /* what is the new position? */
- new_pos = MIN(file->index, new_size);
-
- if (file->root)
- {
- /* this is the root directory; this is a special case */
- if (new_size > (disk_info->root_entries * FAT_DIRENT_SIZE))
- {
- err = IMGTOOLERR_NOSPACE;
- goto done;
- }
- }
- else
- {
- old_cluster_count = (file->filesize + disk_info->cluster_size - 1) / disk_info->cluster_size;
- new_cluster_count = (new_size + disk_info->cluster_size - 1) / disk_info->cluster_size;
- cluster = 0;
-
- /* load the dirent */
- err = fat_read_sector(partition, file->dirent_sector_index, file->dirent_sector_offset, dirent, sizeof(dirent));
- if (err)
- goto done;
-
- /* need to load the FAT whether we are growing or shrinking the file */
- if (old_cluster_count != new_cluster_count)
- {
- err = fat_load_fat(partition, &fat_table);
- if (err)
- goto done;
-
- cluster = 0;
- i = 0;
- do
- {
- last_cluster = cluster;
- write_cluster = 0;
-
- /* identify the next cluster */
- if (cluster != 0)
- cluster = fat_get_fat_entry(partition, fat_table, cluster);
- else
- cluster = file->first_cluster ? file->first_cluster : 0xFFFFFFFF;
-
- /* do we need to grow the file by a cluster? */
- if (i < new_cluster_count && ((cluster < 2) || (cluster >= disk_info->total_clusters)))
- {
- /* grow this file by a cluster */
- cluster = fat_allocate_cluster(partition, fat_table);
- if (cluster == 0)
- {
- err = IMGTOOLERR_NOSPACE;
- goto done;
- }
-
- write_cluster = cluster;
- }
- else if (i >= new_cluster_count)
- {
- /* we are shrinking the file; we need to unlink this node */
- if ((cluster < 2) || (cluster >= disk_info->total_clusters))
- cluster = 0xFFFFFFFF; /* ack file is corrupt! recover */
- write_cluster = 0xFFFFFFFF;
- }
-
- /* write out the entry, if appropriate */
- if (write_cluster != 0)
- {
- /* are we tieing up loose ends? */
- if (rest_free && (write_cluster == 0xFFFFFFFF))
- write_cluster = 0;
-
- if (last_cluster == 0)
- file->first_cluster = (write_cluster != 0xFFFFFFFF) ? write_cluster : 0;
- else
- fat_set_fat_entry(partition, fat_table, last_cluster, write_cluster);
-
- /* did we write the last cluster? if so, the rest (if any) are free */
- if (write_cluster == 0xFFFFFFFF)
- rest_free = TRUE;
- }
- }
- while((++i < new_cluster_count) || (cluster != 0xFFFFFFFF));
- }
-
- /* record the new file size */
- place_integer_le(dirent, 26, 2, file->first_cluster);
- place_integer_le(dirent, 28, 4, new_size);
-
- /* delete the file, if appropriate */
- if (delete_file)
- dirent[0] = 0xE5;
-
- /* save the dirent */
- err = fat_write_sector(partition, file->dirent_sector_index, file->dirent_sector_offset, dirent, sizeof(dirent));
- if (err)
- goto done;
-
- /* if we've modified the FAT, save it out */
- if (fat_table)
- {
- err = fat_save_fat(partition, fat_table);
- if (err)
- goto done;
- }
-
- /* update the file structure */
- if (!file->directory)
- file->filesize = new_size;
- file->cluster = file->first_cluster;
- file->index = 0;
- file->cluster_index = 0;
- file->eof = (new_cluster_count == 0);
- }
-
- /* special case; clear out stale bytes on non-root directories */
- if (file->directory && !delete_file)
- {
- if (file->root)
- clear_size = MIN(file->filesize - new_size, FAT_DIRENT_SIZE);
- else
- clear_size = (disk_info->cluster_size - (new_size % disk_info->cluster_size)) % disk_info->cluster_size;
-
- if (clear_size > 0)
- {
- err = fat_seek_file(partition, file, new_size);
- if (err)
- goto done;
-
- clear_buffer = malloc(clear_size);
- if (!clear_buffer)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
- memset(clear_buffer, '\0', clear_size);
-
- err = fat_write_file(partition, file, clear_buffer, clear_size, NULL);
- if (err)
- goto done;
- }
- }
-
- /* seek back to original pos */
- err = fat_seek_file(partition, file, new_pos);
- if (err)
- goto done;
-
- if (fat_table)
- fat_debug_integrity_check(partition, fat_table, file);
-
-done:
- if (fat_table)
- free(fat_table);
- if (clear_buffer)
- free(clear_buffer);
- return err;
-}
-
-
-
-static void prepend_lfn_bytes(utf16_char *lfn_buf, size_t lfn_buflen, size_t *lfn_len,
- const UINT8 *entry, int offset, int chars)
-{
- UINT16 w;
- int i;
- size_t move_len;
-
- move_len = MIN(*lfn_len + 1, lfn_buflen - chars - 1);
- memmove(&lfn_buf[chars], &lfn_buf[0], move_len * sizeof(*lfn_buf));
-
- for (i = 0; i < chars; i++)
- {
- /* read the character */
- memcpy(&w, &entry[offset + i * 2], 2);
- w = LITTLE_ENDIANIZE_INT16(w);
-
- /* append to buffer */
- lfn_buf[i] = (w != 0xFFFF) ? w : 0;
- }
- *lfn_len += chars;
-}
-
-
-
-static UINT8 fat_calc_filename_checksum(const UINT8 *short_filename)
-{
- UINT8 checksum;
- int i, j;
-
- checksum = 0;
- for (i = 0; i < 11; i++)
- {
- j = checksum & 1;
- checksum >>= 1;
- if (j)
- checksum |= 0x80;
- checksum += short_filename[i];
- }
- return checksum;
-}
-
-
-
-static void fat_calc_dirent_lfnchecksum(UINT8 *entry, size_t entry_len)
-{
- UINT8 checksum;
- int i;
-
- checksum = fat_calc_filename_checksum(entry + entry_len - FAT_DIRENT_SIZE);
-
- for (i = 0; i < (entry_len / FAT_DIRENT_SIZE - 1); i++)
- entry[i * FAT_DIRENT_SIZE + 13] = checksum;
-}
-
-
-
-static char fat_cannonicalize_sfn_char(char ch)
-{
- /* return the display version of this short file name character */
- return tolower(ch);
-}
-
-
-
-static void fat_cannonicalize_sfn(char *sfn, const UINT8 *sfn_bytes)
-{
- /* return the display version of this short file name */
- int i;
-
- memset(sfn, '\0', 13);
- memcpy(sfn, sfn_bytes, 8);
- rtrim(sfn);
- if (sfn[0] == 0x05)
- sfn[0] = (char) 0xE5;
- if ((sfn_bytes[8] != ' ') || (sfn_bytes[9] != ' ') || (sfn_bytes[10] != ' '))
- {
- strcat(sfn, ".");
- memcpy(sfn + strlen(sfn), &sfn_bytes[8], 3);
- rtrim(sfn);
- }
- for (i = 0; sfn[i]; i++)
- sfn[i] = fat_cannonicalize_sfn_char(sfn[i]);
-}
-
-
-
-static time_t fat_crack_time(UINT32 fat_time)
-{
- struct tm t;
- time_t now;
-
- time(&now);
- t = *localtime(&now);
-
- t.tm_sec = ((fat_time >> 0) & 0x001F) * 2;
- t.tm_min = ((fat_time >> 5) & 0x003F);
- t.tm_hour = ((fat_time >> 11) & 0x001F);
- t.tm_mday = ((fat_time >> 16) & 0x001F);
- t.tm_mon = ((fat_time >> 21) & 0x000F);
- t.tm_year = ((fat_time >> 25) & 0x007F) + 1980 - 1900;
-
- return mktime(&t);
-}
-
-
-
-static UINT32 fat_setup_time(time_t ansi_time)
-{
- struct tm t;
- UINT32 result = 0;
-
- t = *localtime(&ansi_time);
-
- result |= (((UINT32) (t.tm_sec / 2)) & 0x001F) << 0;
- result |= (((UINT32) t.tm_min) & 0x003F) << 5;
- result |= (((UINT32) t.tm_hour) & 0x001F) << 11;
- result |= (((UINT32) t.tm_mday) & 0x001F) << 16;
- result |= (((UINT32) t.tm_mon) & 0x000F) << 21;
- result |= (((UINT32) (t.tm_year + 1900 - 1980)) & 0x007F) << 25;
-
- return result;
-}
-
-
-
-static imgtoolerr_t fat_read_dirent(imgtool_partition *partition, fat_file *file,
- fat_dirent *ent, fat_freeentry_info *freeent)
-{
- imgtoolerr_t err;
- //const fat_partition_info *disk_info;
- UINT8 entry[FAT_DIRENT_SIZE];
- size_t bytes_read;
- int i, j;
- unicode_char ch;
- utf16_char lfn_buf[512];
- size_t lfn_len = 0;
- int lfn_lastentry = 0;
- UINT8 lfn_checksum = 0;
- UINT32 entry_index, entry_sector_index, entry_sector_offset;
-
- assert(file->directory);
- lfn_buf[0] = '\0';
- memset(ent, 0, sizeof(*ent));
- //disk_info = fat_get_partition_info(partition);
-
- /* The first eight bytes of a FAT directory entry is a blank padded name
- *
- * The first byte can be special:
- * 0x00 - entry is available and no further entry is used
- * 0x05 - first character is actually 0xe5
- * 0x2E - dot entry; either '.' or '..'
- * 0xE5 - entry has been erased and is available
- *
- * Byte 11 is the attributes; and 0x0F denotes a LFN entry
- */
- do
- {
- entry_index = file->index;
- entry_sector_index = fat_get_filepos_sector_index(partition, file);
- entry_sector_offset = file->index % FAT_SECLEN;
-
- err = fat_read_file(partition, file, entry, sizeof(entry), &bytes_read);
- if (err)
- return err;
- if (bytes_read < sizeof(entry))
- memset(entry, 0, sizeof(entry));
-
- if (entry[11] == 0x0F)
- {
- /* this is an LFN entry */
- if ((lfn_lastentry == 0)
- || ((entry[0] & 0x3F) != (lfn_lastentry - 1))
- || (lfn_checksum != entry[13]))
- {
- lfn_buf[0] = 0;
- lfn_len = 0;
- lfn_checksum = entry[13];
- }
- lfn_lastentry = entry[0] & 0x3F;
- prepend_lfn_bytes(lfn_buf, ARRAY_LENGTH(lfn_buf),
- &lfn_len, entry, 28, 2);
- prepend_lfn_bytes(lfn_buf, ARRAY_LENGTH(lfn_buf),
- &lfn_len, entry, 14, 6);
- prepend_lfn_bytes(lfn_buf, ARRAY_LENGTH(lfn_buf),
- &lfn_len, entry, 1, 5);
- }
- else if (freeent && (freeent->position == ~0))
- {
- /* do a quick check to find out if we found space */
- if ((entry[0] == '\0') || (entry[0] == 0xE5))
- {
- if (freeent->candidate_position > entry_index)
- freeent->candidate_position = entry_index;
-
- if ((entry[0] == '\0') || (freeent->candidate_position + freeent->required_size < file->index))
- freeent->position = freeent->candidate_position;
- }
- else
- {
- freeent->candidate_position = ~0;
- }
- }
- }
- while((entry[0] == 0x2E) || (entry[0] == 0xE5) || (entry[11] == 0x0F));
-
- /* no more directory entries? */
- if (entry[0] == '\0')
- {
- ent->eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- /* pick apart short filename */
- fat_cannonicalize_sfn(ent->short_filename, entry);
-
- /* and the long filename */
- if (lfn_lastentry == 1)
- {
- /* only use the LFN if the checksum passes */
- if (lfn_checksum == fat_calc_filename_checksum(entry))
- {
- i = 0;
- j = 0;
- do
- {
- i += uchar_from_utf16(&ch, &lfn_buf[i], ARRAY_LENGTH(lfn_buf) - i);
- j += utf8_from_uchar(&ent->long_filename[j], ARRAY_LENGTH(ent->long_filename) - j, ch);
- }
- while(ch != 0);
- }
- }
-
- /* other attributes */
- ent->filesize = pick_integer_le(entry, 28, 4);
- ent->directory = (entry[11] & 0x10) ? 1 : 0;
- ent->first_cluster = pick_integer_le(entry, 26, 2);
- ent->dirent_sector_index = entry_sector_index;
- ent->dirent_sector_offset = entry_sector_offset;
- ent->creation_time = fat_crack_time(pick_integer_le(entry, 14, 4));
- ent->lastmodified_time = fat_crack_time(pick_integer_le(entry, 22, 4));
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-enum sfn_disposition_t
-{
- SFN_SUFFICIENT, /* name fully representable in short file name */
- SFN_DERIVATIVE, /* name not fully representable in short file name, but no need to tildize */
- SFN_MANGLED /* name not representable in short file name; must tildize */
-};
-
-static imgtoolerr_t fat_construct_dirent(const char *filename, creation_policy_t create,
- UINT8 **entry, size_t *entry_len)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- UINT8 *created_entry = NULL;
- UINT8 *new_created_entry;
- UINT32 now;
- size_t created_entry_len = FAT_DIRENT_SIZE;
- size_t created_entry_pos = 0;
- unicode_char ch;
- char last_short_char = ' ';
- char short_char = '\0';
- char cannonical_short_char;
- utf16_char buf[UTF16_CHAR_MAX];
- int i, len;
- int sfn_pos = 0;
- sfn_disposition_t sfn_disposition = SFN_SUFFICIENT;
- int sfn_in_extension = 0;
-
- /* sanity check */
- if (*filename == '\0')
- {
- err = IMGTOOLERR_BADFILENAME;
- goto done;
- }
-
- /* construct intial entry */
- created_entry = (UINT8 *) malloc(FAT_DIRENT_SIZE);
- if (!created_entry)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- /* set up the basics for the new dirent */
- memset(created_entry + 0, ' ', 11);
- memset(created_entry + 12, '\0', FAT_DIRENT_SIZE - 12);
- created_entry[11] = (create == CREATE_DIR) ? 0x10 : 0x00;
-
- /* set up file dates in the new dirent */
- now = fat_setup_time(time(NULL));
- place_integer_le(created_entry, 14, 4, now);
- place_integer_le(created_entry, 18, 2, now);
- place_integer_le(created_entry, 22, 4, now);
-
- while(*filename)
- {
- filename += uchar_from_utf8(&ch, filename, UTF8_CHAR_MAX);
-
- /* append to short filename, if possible */
- if ((ch < 32) || (ch > 128))
- short_char = '\0';
- else if (isalnum((char) ch))
- short_char = toupper((char) ch);
- else if (strchr(".!#$%^()-@^_`{}~", (char) ch))
- short_char = (char) ch;
- else
- short_char = '\0'; /* illegal SFN char */
- cannonical_short_char = fat_cannonicalize_sfn_char((char) ch);
- if (!short_char || (short_char != cannonical_short_char))
- {
- if (toupper(short_char) == toupper(cannonical_short_char))
- sfn_disposition = MAX(sfn_disposition, SFN_DERIVATIVE);
- else
- sfn_disposition = SFN_MANGLED;
- }
-
- /* append the short filename char */
- if (short_char == '.')
- {
- /* multiple extensions or trailing spaces? */
- if (sfn_in_extension)
- sfn_disposition = SFN_MANGLED;
- else if (last_short_char == ' ')
- sfn_disposition = MAX(sfn_disposition, SFN_DERIVATIVE);
-
- sfn_in_extension = 1;
- sfn_pos = 8;
- created_entry[created_entry_len - FAT_DIRENT_SIZE + 8] = ' ';
- created_entry[created_entry_len - FAT_DIRENT_SIZE + 9] = ' ';
- created_entry[created_entry_len - FAT_DIRENT_SIZE + 10] = ' ';
- }
- else if (sfn_pos == (sfn_in_extension ? 11 : 8))
- {
- /* ran out of characters for short filename */
- sfn_disposition = SFN_MANGLED;
- }
- else if (short_char != '\0')
- {
- created_entry[created_entry_len - FAT_DIRENT_SIZE + sfn_pos++] = short_char;
- }
- last_short_char = short_char;
-
-
- /* convert to UTF-16 and add a long filename entry */
- len = utf16le_from_uchar(buf, UTF16_CHAR_MAX, ch);
- for (i = 0; i < len; i++)
- {
- switch(created_entry_pos)
- {
- case 0:
- case 32:
- /* need to grow */
- new_created_entry = (UINT8 *) malloc(created_entry_len + FAT_DIRENT_SIZE);
- if (!new_created_entry)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- /* move existing entries forward */
- memmove(new_created_entry + 32, created_entry, created_entry_len);
-
- if (created_entry) free(created_entry);
- created_entry = new_created_entry;
- created_entry_len += 32;
-
- /* set up this LFN */
- memset(created_entry, '\0', 32);
- memset(&created_entry[1], '\xFF', 10);
- memset(&created_entry[14], '\xFF', 12);
- memset(&created_entry[28], '\xFF', 4);
- created_entry[11] = 0x0F;
-
- /* specify entry index */
- created_entry[0] = (created_entry_len / 32) - 1;
- if (created_entry[0] >= 0x40)
- {
- err = IMGTOOLERR_BADFILENAME;
- goto done;
- }
- created_entry_pos = 1;
- break;
-
- case 11:
- created_entry_pos = 14;
- break;
-
- case 26:
- created_entry_pos = 28;
- break;
- }
-
- memcpy(&created_entry[created_entry_pos], &buf[i], 2);
- created_entry_pos += 2;
- }
- }
-
- /* trailing spaces? */
- if (short_char == ' ')
- sfn_disposition = MAX(sfn_disposition, SFN_DERIVATIVE);
-
- if (sfn_disposition == SFN_SUFFICIENT)
- {
- /* the short filename suffices; remove the LFN stuff */
- memcpy(created_entry, created_entry + created_entry_len - FAT_DIRENT_SIZE, FAT_DIRENT_SIZE);
- created_entry_len = FAT_DIRENT_SIZE;
- free(created_entry);
- new_created_entry = (UINT8 *) malloc(created_entry_len);
- if (!new_created_entry)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
- created_entry = new_created_entry;
- }
- else
- {
- /* need to do finishing touches on the LFN */
- created_entry[0] |= 0x40;
-
- /* if necessary, mangle the name */
- if (sfn_disposition == SFN_MANGLED)
- {
- i = 6;
- while((i > 0) && isspace(created_entry[created_entry_len - FAT_DIRENT_SIZE + i - 1]))
- i--;
- created_entry[created_entry_len - FAT_DIRENT_SIZE + i + 0] = '~';
- created_entry[created_entry_len - FAT_DIRENT_SIZE + i + 1] = '1';
- }
- fat_calc_dirent_lfnchecksum(created_entry, created_entry_len);
- }
-
-done:
- if (err && created_entry)
- {
- free(created_entry);
- created_entry = NULL;
- }
- *entry = created_entry;
- *entry_len = created_entry_len;
- return err;
-}
-
-
-
-static void fat_bump_dirent(imgtool_partition *partition, UINT8 *entry, size_t entry_len)
-{
- UINT8 *sfn_entry;
- int pos, digit_count, i;
- UINT32 digit_place, val = 0;
-
- sfn_entry = &entry[entry_len - FAT_DIRENT_SIZE];
-
- digit_place = 1;
- for (pos = 7; (pos >= 0) && isdigit((char) sfn_entry[pos]); pos--)
- {
- val += (sfn_entry[pos] - '0') * digit_place;
- digit_place *= 10;
- }
- val++;
- pos++;
-
- /* count the digits */
- digit_place = 1;
- digit_count = 1;
- while(val >= digit_place * 10)
- {
- digit_count++;
- digit_place *= 10;
- }
-
- /* give us some more space, if necessary */
- while ((pos > 0) && ((pos + digit_count) > 8))
- pos--;
-
- /* have we actually ran out of digits */
- if ((pos + digit_count) > 8)
- {
- /* extreme degenerate case; simply randomize the filename */
- for (i = 0; i < 6; i++)
- sfn_entry[i] = 'A' + (imgtool_partition_rand(partition) % 26);
- sfn_entry[6] = '~';
- sfn_entry[7] = '0';
- }
- else
- {
- /* write the tilde, if possible */
- if (pos > 0)
- sfn_entry[pos - 1] = '~';
-
- /* write out the number */
- while(digit_place > 0)
- {
- sfn_entry[pos++] = (val / digit_place) + '0';
- val %= digit_place;
- digit_place /= 10;
- }
- }
-
- /* since we changed the short file name, we need to recalc the checksums
- * in the LFN entries */
- fat_calc_dirent_lfnchecksum(entry, entry_len);
-}
-
-
-
-static imgtoolerr_t fat_lookup_path(imgtool_partition *partition, const char *path,
- creation_policy_t create, fat_file *file)
-{
- imgtoolerr_t err;
- const fat_partition_info *disk_info;
- fat_dirent ent;
- fat_freeentry_info freeent = { 0, };
- const char *next_path_part;
- UINT8 *created_entry = NULL;
- size_t created_entry_len = 0;
- UINT32 entry_sector_index, entry_sector_offset;
- UINT32 parent_first_cluster;
- int bumped_sfn;
- char sfn[13];
-
- disk_info = fat_get_partition_info(partition);
-
- memset(file, 0, sizeof(*file));
- file->root = 1;
- file->directory = 1;
- file->filesize = disk_info->root_entries * FAT_DIRENT_SIZE;
-
- while(*path)
- {
- if (!file->directory)
- {
- err = IMGTOOLERR_PATHNOTFOUND;
- goto done;
- }
-
- next_path_part = path + strlen(path) + 1;
- if (create && (*next_path_part == '\0'))
- {
- /* this is the last entry, and we are creating a file */
- err = fat_construct_dirent(path, create, &created_entry, &created_entry_len);
- if (err)
- goto done;
-
- freeent.required_size = created_entry_len;
- freeent.candidate_position = ~0;
- freeent.position = ~0;
- }
-
- do
- {
- err = fat_read_dirent(partition, file, &ent, created_entry ? &freeent : NULL);
- if (err)
- goto done;
-
- LOG(("fat_lookup_path(): %s/%s: %d\n", ent.short_filename, ent.long_filename, ent.dirent_sector_offset));
- }
- while(!ent.eof && core_stricmp(path, ent.short_filename) && core_stricmp(path, ent.long_filename));
-
- parent_first_cluster = file->first_cluster;
-
- if (ent.eof)
- {
- /* it seems that we have reached the end of this directory */
- if (!created_entry)
- {
- err = IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
-
- if (created_entry_len > FAT_DIRENT_SIZE)
- {
- /* must ensure uniqueness of the short filename */
- do
- {
- /* rewind to the beginning of the directory */
- err = fat_seek_file(partition, file, 0);
- if (err)
- goto done;
-
- bumped_sfn = FALSE;
- fat_cannonicalize_sfn(sfn, &created_entry[created_entry_len - FAT_DIRENT_SIZE]);
-
- do
- {
- err = fat_read_dirent(partition, file, &ent, NULL);
- if (err)
- goto done;
-
- if (!core_stricmp(sfn, ent.short_filename))
- {
- bumped_sfn = TRUE;
- fat_bump_dirent(partition, created_entry, created_entry_len);
- fat_cannonicalize_sfn(sfn, &created_entry[created_entry_len - FAT_DIRENT_SIZE]);
- }
- }
- while(!ent.eof);
- }
- while(bumped_sfn);
- }
-
- LOG(("fat_lookup_path(): creating entry; pos=%u length=%u\n", freeent.position, freeent.required_size));
-
- err = fat_set_file_size(partition, file, MAX(file->filesize, freeent.position + created_entry_len));
- if (err)
- goto done;
-
- err = fat_seek_file(partition, file, freeent.position);
- if (err)
- goto done;
-
- err = fat_write_file(partition, file, created_entry, created_entry_len, NULL);
- if (err)
- goto done;
-
- /* we have to do a special seek operation to get the main dirent */
- err = fat_seek_file(partition, file, freeent.position + created_entry_len - FAT_DIRENT_SIZE);
- if (err)
- goto done;
- entry_sector_index = fat_get_filepos_sector_index(partition, file);
- entry_sector_offset = file->index % FAT_SECLEN;
-
- /* build the file struct for the newly created file/directory */
- memset(file, 0, sizeof(*file));
- file->directory = (created_entry[created_entry_len - FAT_DIRENT_SIZE + 11] & 0x10) ? 1 : 0;
- file->dirent_sector_index = entry_sector_index;
- file->dirent_sector_offset = entry_sector_offset;
- }
- else
- {
- /* update the current file */
- memset(file, 0, sizeof(*file));
- file->directory = ent.directory;
- file->filesize = ent.filesize;
- file->cluster = ent.first_cluster;
- file->first_cluster = ent.first_cluster;
- file->dirent_sector_index = ent.dirent_sector_index;
- file->dirent_sector_offset = ent.dirent_sector_offset;
- }
-
- path = next_path_part;
- file->parent_first_cluster = parent_first_cluster;
- }
-
- err = IMGTOOLERR_SUCCESS;
-
-done:
- if (created_entry)
- free(created_entry);
- return err;
-}
-
-
-
-static imgtoolerr_t fat_partition_beginenum(imgtool_directory *enumeration, const char *path)
-{
- imgtoolerr_t err;
- fat_file *file;
-
- file = (fat_file *) imgtool_directory_extrabytes(enumeration);
-
- err = fat_lookup_path(imgtool_directory_partition(enumeration), path, CREATE_NONE, file);
- if (err)
- return err;
- if (!file->directory)
- return IMGTOOLERR_PATHNOTFOUND;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_partition_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- imgtoolerr_t err;
- fat_file *file;
- fat_dirent fatent;
-
- file = (fat_file *) imgtool_directory_extrabytes(enumeration);
- err = fat_read_dirent(imgtool_directory_partition(enumeration), file, &fatent, NULL);
- if (err)
- return err;
-
- /* copy stuff from the FAT dirent to the Imgtool dirent */
- snprintf(ent->filename, ARRAY_LENGTH(ent->filename), "%s", fatent.long_filename[0]
- ? fatent.long_filename : fatent.short_filename);
- ent->filesize = fatent.filesize;
- ent->directory = fatent.directory;
- ent->eof = fatent.eof;
- ent->creation_time = fatent.creation_time;
- ent->lastmodified_time = fatent.lastmodified_time;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_read_bootblock(imgtool_partition *partition, imgtool_stream *stream)
-{
- imgtoolerr_t err;
- UINT8 block[FAT_SECLEN];
-
- err = fat_read_sector(partition, 0, 0, block, sizeof(block));
- if (err)
- return err;
-
- stream_write(stream, block, sizeof(block));
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_write_bootblock(imgtool_partition *partition, imgtool_stream *stream)
-{
- imgtoolerr_t err;
- UINT8 block[FAT_SECLEN];
- UINT8 new_block[FAT_SECLEN];
-
- if (stream_size(stream) != sizeof(new_block))
- return IMGTOOLERR_UNEXPECTED;
- stream_read(stream, new_block, sizeof(new_block));
-
- if (new_block[510] != 0x55)
- return IMGTOOLERR_UNEXPECTED;
- if (new_block[511] != 0xAA)
- return IMGTOOLERR_UNEXPECTED;
-
- /* read current boot sector */
- err = fat_read_sector(partition, 0, 0, block, sizeof(block));
- if (err)
- return err;
-
- /* merge in the new stuff */
- memcpy(&block[ 0], &new_block[ 0], 3);
- memcpy(&block[62], &new_block[62], 448);
-
- /* and write it out */
- err = fat_write_sector(partition, 0, 0, block, sizeof(block));
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_partition_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- imgtoolerr_t err;
- fat_file file;
- size_t bytes_read;
- char buffer[1024];
-
- /* special case for bootblock */
- if (filename == FILENAME_BOOTBLOCK)
- return fat_read_bootblock(partition, destf);
-
- err = fat_lookup_path(partition, filename, CREATE_NONE, &file);
- if (err)
- return err;
-
- if (file.directory)
- return IMGTOOLERR_FILENOTFOUND;
-
- do
- {
- err = fat_read_file(partition, &file, buffer, sizeof(buffer), &bytes_read);
- if (err)
- return err;
-
- stream_write(destf, buffer, bytes_read);
- }
- while(bytes_read > 0);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_partition_writefile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- imgtoolerr_t err;
- fat_file file;
- UINT32 bytes_left, len;
- char buffer[1024];
-
- /* special case for bootblock */
- if (filename == FILENAME_BOOTBLOCK)
- return fat_write_bootblock(partition, sourcef);
-
- err = fat_lookup_path(partition, filename, CREATE_FILE, &file);
- if (err)
- return err;
-
- if (file.directory)
- return IMGTOOLERR_FILENOTFOUND;
-
- bytes_left = (UINT32) stream_size(sourcef);
-
- err = fat_set_file_size(partition, &file, bytes_left);
- if (err)
- return err;
-
- while(bytes_left > 0)
- {
- len = MIN(bytes_left, sizeof(buffer));
- stream_read(sourcef, buffer, len);
-
- err = fat_write_file(partition, &file, buffer, len, NULL);
- if (err)
- return err;
-
- bytes_left -= len;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_partition_delete(imgtool_partition *partition, const char *filename, unsigned int dir)
-{
- imgtoolerr_t err;
- fat_file file;
- fat_dirent ent;
-
- err = fat_lookup_path(partition, filename, CREATE_NONE, &file);
- if (err)
- return err;
- if (file.directory != dir)
- return IMGTOOLERR_FILENOTFOUND;
-
- if (dir)
- {
- err = fat_read_dirent(partition, &file, &ent, NULL);
- if (err)
- return err;
- if (!ent.eof)
- return IMGTOOLERR_DIRNOTEMPTY;
- }
-
- err = fat_set_file_size(partition, &file, ~0);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_partition_deletefile(imgtool_partition *partition, const char *filename)
-{
- return fat_partition_delete(partition, filename, 0);
-}
-
-
-
-static imgtoolerr_t fat_partition_freespace(imgtool_partition *partition, UINT64 *size)
-{
- imgtoolerr_t err;
- const fat_partition_info *disk_info;
- UINT8 *fat_table;
- UINT32 i;
-
- disk_info = fat_get_partition_info(partition);
-
- err = fat_load_fat(partition, &fat_table);
- if (err)
- goto done;
-
- *size = 0;
- for (i = 2; i < disk_info->total_clusters; i++)
- {
- if (fat_get_fat_entry(partition, fat_table, i) == 0)
- *size += disk_info->cluster_size;
- }
-
-done:
- if (fat_table)
- free(fat_table);
- return err;
-}
-
-
-
-static imgtoolerr_t fat_partition_createdir(imgtool_partition *partition, const char *path)
-{
- imgtoolerr_t err;
- fat_file file;
- UINT8 initial_data[64];
-
- err = fat_lookup_path(partition, path, CREATE_DIR, &file);
- if (err)
- return err;
- if (!file.directory)
- return IMGTOOLERR_FILENOTFOUND;
-
- err = fat_set_file_size(partition, &file, sizeof(initial_data));
- if (err)
- return err;
-
- /* set up the two directory entries in all directories */
- memset(initial_data, 0, sizeof(initial_data));
- memcpy(&initial_data[0], ". ", 11);
- place_integer_le(initial_data, 11, 1, 0x10);
- place_integer_le(initial_data, 26, 2, file.first_cluster);
- memcpy(&initial_data[32], ". ", 11);
- place_integer_le(initial_data, 43, 1, 0x10);
- place_integer_le(initial_data, 58, 2, file.parent_first_cluster);
-
- err = fat_write_file(partition, &file, initial_data, sizeof(initial_data), NULL);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_partition_deletedir(imgtool_partition *partition, const char *path)
-{
- return fat_partition_delete(partition, path, 1);
-}
-
-
-
-void fat_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_INITIAL_PATH_SEPARATOR: info->i = 1; break;
- case IMGTOOLINFO_INT_OPEN_IS_STRICT: info->i = 1; break;
- case IMGTOOLINFO_INT_SUPPORTS_CREATION_TIME: info->i = 1; break;
- case IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME: info->i = 1; break;
- case IMGTOOLINFO_INT_SUPPORTS_BOOTBLOCK: info->i = 1; break;
- case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = '\\'; break;
- case IMGTOOLINFO_INT_ALTERNATE_PATH_SEPARATOR: info->i = '/'; break;
- case IMGTOOLINFO_INT_PARTITION_EXTRA_BYTES: info->i = sizeof(fat_partition_info); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(fat_file); break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_EOLN: strcpy(info->s = imgtool_temp_str(), "\r\n"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_CREATE_PARTITION: info->create_partition = fat_partition_create; break;
- case IMGTOOLINFO_PTR_OPEN_PARTITION: info->open_partition = fat_partition_open; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = fat_partition_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = fat_partition_nextenum; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = fat_partition_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = fat_partition_writefile; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = fat_partition_deletefile; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = fat_partition_freespace; break;
- case IMGTOOLINFO_PTR_CREATE_DIR: info->create_dir = fat_partition_createdir; break;
- case IMGTOOLINFO_PTR_DELETE_DIR: info->delete_dir = fat_partition_deletedir; break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/fat.h b/src/mess/tools/imgtool/modules/fat.h
deleted file mode 100644
index 46f741999c3..00000000000
--- a/src/mess/tools/imgtool/modules/fat.h
+++ /dev/null
@@ -1,3 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-void fat_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info);
diff --git a/src/mess/tools/imgtool/modules/hp48.c b/src/mess/tools/imgtool/modules/hp48.c
deleted file mode 100644
index e54908c9c1e..00000000000
--- a/src/mess/tools/imgtool/modules/hp48.c
+++ /dev/null
@@ -1,739 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Antoine Mine
-/****************************************************************************
-
- hp48.c
-
- Memory cards for HP48 SX/GX
-
- Antoine Mine' 2014
-
-*****************************************************************************
-*/
-
-/*
- HP memory cards can contain two kinds of objects:
- - attached libraries
- - backup objects (encapsulating any kind of object)
-
- Attached libraries appear with a LIB attribute in imgtool's listing, and in
- the global "LIBRARY" menu on the HP48.
- Backup objects appear with a BAK attribute in imgtool's listing, and
- in the relevant "PORTS" menu on the HP48.
-
- Currently, we only support storing host files into backup objects and
- retreiving backup objects into files.
- For attached library objects in the memory card, we only show their name, but
- cannot retrieve their contents.
-
- To install a library contained in a host file, copy it with imgtool to
- the card; it creates a backup object visible in the "PORTS" menu;
- then evalue the object, store it into some port (e.g, 0 STO),
- turn off the HP48 and back on; the library should now be attached and
- visible in the "LIBRARY" menu.
- (The process is similar to installing a library from a file you get
- from the serial interface.)
-*/
-
-
-/*
- HP memory cards have size from 32 KB to 4096 KB.
- However, cards with size greater than 128 KB are seen as multiple ports of
- size 128 KB on the HP48 GX. In imgtool, we see them as distinct 128 KB
- partitions.
- Unfortunately, at the moment, partitions do not seem to be supported in the
- command-line tool...
- */
-
-
-/*
- Here is the format of backup objects (addresses are in 4-bit nibbles):
-
- offset field size value
- 0 prolog 5 02B62 prolog for overall backup object
- 5 size 5 len total size in nibble without prolog
- 10 name length 2 nbcar object name, in characters
- 12 name 2*nbcar -
- 12+2*nbcar name length 2 nbcar same value as name length at 10
- 14+2*nbcar object - -
- len-5 prolog 5 02911 prolog for inlined system integer
- len - 1 0
- len+1 CRC 4 - CRC from 5 to len
-
- total length: len+4
-
- i.e., the backup object is a container containing the object name
- and two objects: the backuped object itself and a system integer
- that contains the CRC.
-
- HP48 host files start with a "HPHP48-X" header (where X can be any
- single letter, which denotes a ROM revision and, implicitly, whether
- the program is for the S/SX or the G/GX family).
- When storing a file to the memory card, we strip the header and
- embed the object into a backup object with the correct CRC.
- When copying from the memory card to a host file, we extract the object
- from the backup container, stripping its CRC, and add the HPHP48-X header.
-
- */
-
-
-
-
-
-/*****************************************************************************
- Includes
-*****************************************************************************/
-
-#include "imgtool.h"
-
-
-
-/*****************************************************************************
- Data structures
-*****************************************************************************/
-
-
-struct hp48_card
-{
- imgtool_stream *stream;
- int modified;
-
- /* size, in bytes of card data: from 32 KB to 4 MB */
- int size;
-
- /* we store each nibble (4-bit) into its own byte, for simpler addressing;
- hence, data has 2*size
- */
- UINT8* data;
-
-};
-
-struct hp48_partition
-{
- /* pointer to the beginning of the partition inside the hp48_card */
- UINT8* data;
-
- /* size, in bytes (128 KB or less) */
- int size;
-
-};
-
-struct hp48_directory
-{
- int pos;
-};
-
-
-#define PROLOG_BACKUP 0x02B62
-#define PROLOG_LIBRARY 0x02B40
-#define PROLOG_SYSINT 0x02911
-
-/* memory cards are composed solely of libraries and backup objects */
-#define IS_OBJECT(prolog) ((prolog) == PROLOG_LIBRARY || (prolog) == PROLOG_BACKUP)
-
-/* host files begin with this prefix (up to the last letter) */
-static const char* hp48_prefix = "HPHP48-R";
-
-
-
-static OPTION_GUIDE_START( hp48_create_optionguide )
- OPTION_INT('S', "size", "Size in KB" )
-OPTION_GUIDE_END
-
-/* size in KB, 128 KB being the default */
-static const char hp48_create_optionspec[] = "S32/64/[128]/256/512/1024/2048/4096";
-
-
-
-/*****************************************************************************
- Utility functions
-*****************************************************************************/
-
-
-/* byes to nibbles */
-static void unpack(UINT8* dst, UINT8* src, int nsize)
-{
- int i;
-
- if ( nsize & 1 )
- {
- dst[nsize-1] = src[nsize/2] & 0xf;
- }
-
- for ( i = nsize/2-1; i >= 0; i-- )
- {
- dst[2*i+1] = src[i] >> 4;
- dst[2*i ] = src[i] & 0xf;
- }
-}
-
-/* nibbles to bytes */
-static void pack(UINT8* dst, UINT8* src, int nsize)
-{
- int i;
-
- for ( i = 0 ; i < nsize/2; i++ )
- {
- dst[i] = (src[2*i] & 0xf) | (src[2*i+1] << 4);
- }
-
- if ( nsize & 1 )
- {
- dst[nsize/2] = src[nsize-1] & 0xf;
- }
- }
-
-
-static int read20(UINT8* data)
-{
- return data[0] | (data[1] << 4) | (data[2] << 8) | (data[3] << 12) | (data[4] << 16);
-}
-
-static int read8(UINT8* data)
-{
- return data[0] | (data[1] << 4);
-}
-
-static void readstring(char* dst, UINT8* data, int nb)
-{
- int i;
- for ( i = 0; i < nb; i++ )
- {
- dst[i] = read8( data + 2*i );
- }
- dst[nb] = 0;
-}
-
-static void write20(UINT8* data, int v)
-{
- data[0] = v & 0xf;
- data[1] = (v >> 4) & 0xf;
- data[2] = (v >> 8) & 0xf;
- data[3] = (v >> 12) & 0xf;
- data[4] = (v >> 16) & 0xf;
-}
-
-static void write8(UINT8* data, int v)
-{
- data[0] = v & 0xf;
- data[1] = (v >> 4) & 0xf;
-}
-
-static void writestring(UINT8* data, const char* str, int nb)
-{
- int i;
- for ( i = 0; i < nb; i++ )
- {
- write8( data + 2*i, str[i] );
- }
-}
-
-
-/* go to the end, return its offset */
-static int find_end(hp48_partition* p)
-{
- int pos = 0;
- while (1)
- {
- if ( pos + 10 > 2*p->size) break;
-
- int prolog = read20( p->data + pos );
- if ( !IS_OBJECT( prolog )) break;
-
- pos += read20( p->data + pos + 5 ) + 5;
- }
-
- if ( pos > 2*p->size ) pos = 2*p->size;
- return pos;
-}
-
-
-/* find the backup object with the given name, returns its offset or -1 (not found) */
-static int find_file(hp48_partition* p, const char* filename, int *ptotalsize, int* pstart, int* pcontentsize)
-{
- UINT8* data = p->data;
- int pos = 0;
-
- /* find file */
- while (1)
- {
- if ( pos + 10 > 2*p->size) return -1;
-
- /* get prolog */
- int prolog = read20( data+pos );
- if ( !IS_OBJECT(prolog)) return -1;
-
- /* get size */
- int totalsize = read20( data+pos+5 );
- if ( totalsize < 14) return -1;
- if ( pos + 5 + totalsize > 2*p->size ) return -1;
-
- if ( prolog == PROLOG_BACKUP )
- {
- /* get name */
- int namelen = read8( data + pos + 10 );
- char name[257];
- if ( 9 + 2*namelen > totalsize ) return -1;
- readstring( name, data + pos + 12, namelen );
-
- /* check name */
- if ( !strcmp( name, filename ) )
- {
- /* found! */
- if ( ptotalsize ) *ptotalsize = totalsize;
- if ( pstart ) *pstart = pos + 14 + 2*namelen;
- if ( pcontentsize ) *pcontentsize = totalsize - (9 + 2*namelen);
- return pos;
- }
- else
- {
- /* skip */
- pos += totalsize + 5;
- }
- }
- else
- {
- /* skip */
- pos += totalsize + 5;
- }
-
- }
-
- // never executed
- //return -1;
-}
-
-
-/* CRC computing.
- This is the same CRC that is computed by the HP48 hardware.
- */
-static UINT16 crc(UINT8* data, int len)
-{
- UINT16 crc = 0;
- int i;
-
- for ( i = 0; i < len; i++ )
- {
- crc = (crc >> 4) ^ (((crc ^ data[i]) & 0xf) * 0x1081);
- }
-
- return crc;
-}
-
-
-
-/*****************************************************************************
- Imgtool functions
-*****************************************************************************/
-
-
-static imgtoolerr_t hp48_open(imgtool_image *img, imgtool_stream *stream)
-{
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- int size = stream_size( stream );
-
- /* check that size is a power of 2 between 32 KB and 4 MG */
- if ( (size < 32 * 1024) ||
- (size > 4 * 1024 * 1024) ||
- (size & (size-1)) )
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- /* store info */
- c->stream = stream;
- c->modified = 0;
- c->size = size;
- c->data = (UINT8*) malloc( 2 * size );
- if ( !c->data )
- {
- return IMGTOOLERR_READERROR;
- }
-
- /* fully load image */
- stream_seek( stream, 0, SEEK_SET );
- if ( stream_read( stream, c->data, size ) < size )
- {
- return IMGTOOLERR_READERROR;
- }
- unpack( c->data, c->data, 2 * size );
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_create(imgtool_image* img,
- imgtool_stream *stream,
- option_resolution *opts)
-{
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- int size;
-
- size = option_resolution_lookup_int(opts, 'S');
-
- c->stream = stream;
- c->modified = 1;
- c->size = size * 1024;
- c->data = (UINT8*) malloc( 2 * c->size );
- if ( !c->data )
- {
- return IMGTOOLERR_READERROR;
- }
-
- /* zeroing the image seems fine */
- memset( c->data, 0, 2 * c->size );
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void hp48_close(imgtool_image *img)
-{
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
-
- if ( c->modified )
- {
- /* save image */
- pack( c->data, c->data, 2 * c->size );
- stream_seek( c->stream, 0, SEEK_SET );
- stream_write( c->stream, c->data, c->size );
- }
-
- /* clean up */
- free( c->data );
- stream_close( c->stream );
-}
-
-
-
-/* each 128 KB chunk is a distinct partition */
-#define MAX_PORT_SIZE (128*1024)
-
-void hp48_partition_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info);
-
-static imgtoolerr_t hp48_list_partitions(imgtool_image *img,
- imgtool_partition_info *partitions,
- size_t len)
-{
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
-
- int i;
- for ( i = 0; i < len && i * MAX_PORT_SIZE < c->size ; i++ )
- {
- /* offset and size in bytes */
- partitions[i].base_block = i * MAX_PORT_SIZE;
- partitions[i].block_count = c->size - partitions[i].base_block;
- if ( partitions[i].block_count > MAX_PORT_SIZE )
- {
- partitions[i].block_count = MAX_PORT_SIZE;
- }
-
- partitions[i].get_info = hp48_partition_get_info;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t hp48_open_partition(imgtool_partition *part,
- UINT64 first_block, UINT64 block_count)
-{
- imgtool_image* img = imgtool_partition_image( part );
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
-
- if ( first_block + block_count > c->size )
- return IMGTOOLERR_INVALIDPARTITION;
-
- /* store partition position */
- p->data = c->data + first_block;
- p->size = block_count;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_beginenum(imgtool_directory *enumeration,
- const char *path)
-{
- hp48_directory* d = (hp48_directory*) imgtool_directory_extrabytes( enumeration );
-
- d->pos = 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_nextenum(imgtool_directory *enumeration,
- imgtool_dirent *ent)
-{
- imgtool_partition *part = imgtool_directory_partition( enumeration );
- //imgtool_image* img = imgtool_partition_image( part );
- //hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
- hp48_directory* d = (hp48_directory*) imgtool_directory_extrabytes( enumeration );
-
- UINT8* data = p->data;
- int pos = d->pos;
-
- if ( pos < 0 || pos+12 > 2*p->size )
- {
- ent->eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- int prolog = read20( data+pos );
-
- if ( IS_OBJECT(prolog) )
- {
- pos += 5;
- int totalsize = read20( data+pos );
- pos += 5;
-
- int namelen = read8( data+pos );
- pos += 2;
- if ( (pos + 2*namelen > 2*p->size) ||
- (namelen >= sizeof(ent->filename)) )
- {
- ent->eof = 1;
- return IMGTOOLERR_CORRUPTFILE;
- }
- readstring( ent->filename, data+pos, namelen );
-
- /* compute size in bytes, removing name, length & CRC fields */
- ent->filesize = ((totalsize - 19 - 2*namelen) + 1) / 2;
-
- switch (prolog)
- {
- case PROLOG_LIBRARY: strncpy( ent->attr, "LIB", sizeof(ent->attr) ); break;
- case PROLOG_BACKUP: strncpy( ent->attr, "BAK", sizeof(ent->attr) ); break;
- default: strncpy( ent->attr, "?", sizeof(ent->attr) );
- }
-
- d->pos = d->pos + totalsize + 5;
- }
- else
- {
- /* 0 or unknown object => end */
- ent->eof = 1;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_freespace(imgtool_partition *part, UINT64 *size)
-{
- //imgtool_image* img = imgtool_partition_image( part );
- //hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
-
- *size = p->size - (find_end(p)+1)/2;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_readfile(imgtool_partition *part,
- const char *filename,
- const char *fork,
- imgtool_stream *destf)
-{
- //imgtool_image* img = imgtool_partition_image( part );
- //hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
-
- /* find entry */
- int totalsize, start, size;
- int pos = find_file(p, filename, &totalsize, &start, &size);
- if ( pos == -1 )
- {
- return IMGTOOLERR_FILENOTFOUND;
- }
-
- /* CRC check */
- UINT16 objcrc = read20( p->data + pos + totalsize ) >> 4;
- UINT16 mycrc = crc( p->data + pos + 5, totalsize - 4);
- if ( objcrc != mycrc )
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- size -= 10;
-
- /* save header */
- stream_write( destf, hp48_prefix, 8);
-
- /* save contents to host file */
- int bytesize = (size + 1) / 2;
- UINT8* buf = (UINT8*) malloc( bytesize );
- if (!buf)
- {
- return IMGTOOLERR_FILENOTFOUND;
- }
- pack( buf, p->data + start, size );
- stream_write( destf, buf, bytesize );
- free( buf );
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_deletefile(imgtool_partition *part,
- const char *filename)
-{
- imgtool_image* img = imgtool_partition_image( part );
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
-
- /* find entry */
- int totalsize;
- int pos = find_file(p, filename, &totalsize, NULL, NULL );
- if ( pos == -1 )
- {
- return IMGTOOLERR_FILENOTFOUND;
- }
-
- /* move */
- totalsize += 5;
- memmove( p->data+pos, p->data+pos+totalsize, 2*p->size-(pos+totalsize) );
- memset( p->data + 2*p->size-totalsize, 0, totalsize);
- c->modified = 1;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t hp48_writefile(imgtool_partition *part,
- const char *filename,
- const char *fork,
- imgtool_stream *sourcef,
- option_resolution *opts)
-{
- imgtool_image* img = imgtool_partition_image( part );
- hp48_card* c = (hp48_card*) imgtool_image_extra_bytes( img );
- hp48_partition* p = (hp48_partition*) imgtool_partition_extra_bytes( part );
-
- /* check header */
- char head[8];
- stream_read( sourcef, head, 8 );
- if ( memcmp( head, hp48_prefix, 7) )
- {
- return IMGTOOLERR_READERROR;
- }
-
- /* ensure that the file does not exist */
- /* TODO: resize the existing file instead, to keep it in place? */
- hp48_deletefile( part, filename );
-
- /* goto end */
- //UINT8* data = p->data;
- int pos = find_end(p);
-
- int len = strlen( filename );
- if ( len > 255 ) len = 255;
-
- /* check size */
- int filesize = stream_size( sourcef ) - 8;
- if ( pos + 2*filesize + 24 + 2*len > 2 * p->size )
- {
- return IMGTOOLERR_NOSPACE;
- }
-
- /* load file */
- UINT8* buf = (UINT8*) malloc( filesize );
- if ( !buf ) return IMGTOOLERR_NOSPACE;
- stream_read( sourcef, buf, filesize );
-
- /* store backup object */
- int org = pos;
- int totalsize = 2*filesize + 19 + 2*len;
- write20( p->data+pos, PROLOG_BACKUP );
- pos +=5;
- write20( p->data+pos, totalsize );
- pos +=5;
- write8( p->data+pos, len );
- pos += 2;
- writestring( p->data+pos, filename, len );
- pos += 2*len;
- write8( p->data+pos, len );
- pos += 2;
- unpack( p->data+pos, buf, 2*filesize );
- pos += 2*filesize;
-
- /* store crc */
- write20( p->data+pos, PROLOG_SYSINT );
- pos += 5;
- p->data[pos] = 0;
- write20( p->data+pos, crc(p->data+org+5, totalsize-4) << 4 );
-
- free(buf);
-
- c->modified = 1;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-
-/*****************************************************************************
- Imgtool module declaration
-*****************************************************************************/
-
-
-
-void hp48_partition_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "hp48"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "HP48 SX/GX memory card"); break;
- case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "crd"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_OPEN_PARTITION: info->open_partition = hp48_open_partition; break;
- case IMGTOOLINFO_PTR_CLOSE: info->close = hp48_close; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = hp48_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = hp48_nextenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = hp48_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = hp48_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = hp48_writefile; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = hp48_deletefile; break;
-
- case IMGTOOLINFO_INT_PARTITION_EXTRA_BYTES: info->i = sizeof(hp48_partition); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(hp48_directory); break;
-
- }
-}
-
-void hp48_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "hp48"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "HP48 SX/GX memory card"); break;
- case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "crd"); break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), hp48_create_optionspec); break;
-
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = hp48_create_optionguide; break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_OPEN: info->open = hp48_open; break;
- case IMGTOOLINFO_PTR_CREATE: info->create = hp48_create; break;
- case IMGTOOLINFO_PTR_CLOSE: info->close = hp48_close; break;
- case IMGTOOLINFO_PTR_LIST_PARTITIONS: info->list_partitions = hp48_list_partitions; break;
-
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(hp48_card); break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/mac.c b/src/mess/tools/imgtool/modules/mac.c
deleted file mode 100644
index 53ae4be3ec0..00000000000
--- a/src/mess/tools/imgtool/modules/mac.c
+++ /dev/null
@@ -1,6418 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- mac.c
-
- Handlers for Classic MacOS images (MFS and HFS formats).
-
- Raphael Nabet, 2003
-
- TODO:
- * add support for HFS write
-
-*****************************************************************************
-
- terminology:
- disk block: 512-byte logical block. With sectors of 512 bytes, one logical
- block is equivalent to one sector; when the sector size is not 512
- bytes, sectors are split or grouped to make 512-byte disk blocks.
- allocation block: The File Manager always allocates logical disk blocks to
- a file in groups called allocation blocks; an allocation block is
- simply a group of consecutive logical blocks. The size of a volume's
- allocation blocks depends on the capacity of the volume; there can be
- at most 4094 (MFS) or 65535 (HFS) allocation blocks on a volume.
- MFS (Macintosh File System): File system used by the early Macintosh. This
- File system does not support folders (you may create folders on a MFS
- disk, but such folders are not implemented on File System level but in
- the Desktop file, and they are just a hint of how programs should list
- files, i.e. you can't have two files with the same name on a volume
- even if they are in two different folders), and it is not adequate for
- large volumes.
- HFS (Hierarchical File System): File system introduced with the HD20
- harddisk, the Macintosh Plus ROMs, and system 3.2 (IIRC). Contrary to
- MFS, it supports hierarchical folders. Also, it is suitable for larger
- volumes.
- HFS+ (HFS Plus): New file system introduced with MacOS 8.1. It has a lot
- in common with HFS, but it supports more allocation blocks (up to 4
- billions IIRC), and many extra features, including longer file names
- (up to 255 UTF-16 Unicode chars).
- tag data: with the GCR encoding, each disk block is associated with a 12
- (3.5" floppies) or 20 (HD20) byte tag record. This tag record contains
- information on the block allocation status (whether it is allocated
- in a file or free, which file is it belongs to, what offset the block
- has in the file). This enables to recover all files whose data blocks
- are still on the disk surface even if the disk catalog has been trashed
- completely (though most file properties, like the name, type and
- logical EOF, are not saved in the tag record and cannot be recovered).
-
- Organization of an MFS volume:
-
- Logical Contents Allocation block
- block
-
- 0 - 1: System startup information
- 2 - m: Master directory block (MDB)
- + allocation block link pointers
- m+1 - n: Directory file
- n+1 - p-2: Other files and free space 0 - ((p-2)-(n+1))/k
- p-1: Alternate MDB
- p: Not used
- usually, k = 2, m = 3, n = 16, p = 799 (SSDD 3.5" floppy)
- with DSDD 3.5" floppy, I assume that p = 1599, but I don't know the other
- values
-
-
- Master Directory Block:
-
- Offset Length Description
- ------ ------ -----------
- 0 2 Volume Signature
- 2 4 Creation Date
- 6 4 Last Modification Date
- 10 2 Volume Attributes
- 12 2 Number of Files In Root Directory
- 14 2 First Block of Volume Bitmap
- ...
-
- Links:
- http://developer.apple.com/documentation/mac/Files/Files-99.html
- http://developer.apple.com/documentation/mac/Files/Files-100.html
- http://developer.apple.com/documentation/mac/Files/Files-101.html
- http://developer.apple.com/documentation/mac/Files/Files-102.html
- http://developer.apple.com/documentation/mac/Files/Files-103.html
- http://developer.apple.com/documentation/mac/Files/Files-104.html
- http://developer.apple.com/documentation/mac/Files/Files-105.html
- http://developer.apple.com/documentation/mac/Files/Files-106.html
- http://developer.apple.com/documentation/mac/Devices/Devices-121.html#MARKER-2-169
- http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
-
-*****************************************************************************/
-
-#include <ctype.h>
-#include <string.h>
-#include <time.h>
-#include <limits.h>
-#include <stddef.h>
-
-#include "formats/imageutl.h"
-#include "imgtool.h"
-#include "macutil.h"
-#include "iflopimg.h"
-#include "formats/ap_dsk35.h"
-
-/* if 1, check consistency of B-Tree (most of the checks will eventually be
- suppressed when the image is opened as read-only and only enabled when
- the image is opened as read/write) */
-#define BTREE_CHECKS 1
-/* if 1, check consistency of tag data when we are at risk of corrupting the
- disk (file write and allocation) */
-#define TAG_CHECKS 1
-/* if 1, check consistency of tag data when reading files (not recommended
- IMHO) */
-#define TAG_EXTRA_CHECKS 0
-
-#if 0
-#pragma mark MISCELLANEOUS UTILITIES
-#endif
-
-struct UINT16BE
-{
- UINT8 bytes[2];
-};
-
-struct UINT24BE
-{
- UINT8 bytes[3];
-};
-
-struct UINT32BE
-{
- UINT8 bytes[4];
-};
-
-INLINE UINT16 get_UINT16BE(UINT16BE word)
-{
- return (word.bytes[0] << 8) | word.bytes[1];
-}
-
-INLINE void set_UINT16BE(UINT16BE *word, UINT16 data)
-{
- word->bytes[0] = (data >> 8) & 0xff;
- word->bytes[1] = data & 0xff;
-}
-
-#if 0
-INLINE UINT32 get_UINT24BE(UINT24BE word)
-{
- return (word.bytes[0] << 16) | (word.bytes[1] << 8) | word.bytes[2];
-}
-
-INLINE void set_UINT24BE(UINT24BE *word, UINT32 data)
-{
- word->bytes[0] = (data >> 16) & 0xff;
- word->bytes[1] = (data >> 8) & 0xff;
- word->bytes[2] = data & 0xff;
-}
-#endif
-
-INLINE UINT32 get_UINT32BE(UINT32BE word)
-{
- return (word.bytes[0] << 24) | (word.bytes[1] << 16) | (word.bytes[2] << 8) | word.bytes[3];
-}
-
-INLINE void set_UINT32BE(UINT32BE *word, UINT32 data)
-{
- word->bytes[0] = (data >> 24) & 0xff;
- word->bytes[1] = (data >> 16) & 0xff;
- word->bytes[2] = (data >> 8) & 0xff;
- word->bytes[3] = data & 0xff;
-}
-
-/*
- Macintosh string: first byte is length
-*/
-typedef UINT8 mac_str27[28];
-typedef UINT8 mac_str31[32];
-typedef UINT8 mac_str63[64];
-typedef UINT8 mac_str255[256];
-
-/*
- Macintosh type/creator code: 4 char value
-*/
-typedef UINT32BE mac_type;
-
-/*
- point record, with the y and x coordinates
-*/
-struct mac_point
-{
- UINT16BE v; /* actually signed */
- UINT16BE h; /* actually signed */
-};
-
-/*
- rect record, with the corner coordinates
-*/
-struct mac_rect
-{
- UINT16BE top; /* actually signed */
- UINT16BE left; /* actually signed */
- UINT16BE bottom;/* actually signed */
- UINT16BE right; /* actually signed */
-};
-
-/*
- FInfo (Finder file info) record
-*/
-struct mac_FInfo
-{
- mac_type type; /* file type */
- mac_type creator; /* file creator */
- UINT16BE flags; /* Finder flags */
- mac_point location; /* file's location in window */
- /* If set to {0, 0}, and the inited flag is
- clear, the Finder will place the item
- automatically */
- UINT16BE fldr; /* MFS: window that contains file */
- /* -3: trash */
- /* -2: desktop */
- /* -1: new folder template?????? */
- /* 0: disk window ("root") */
- /* > 0: specific folder, index of FOBJ resource??? */
- /* The FOBJ resource contains some folder info;
- the name of the resource is the folder name. */
- /* HFS & HFS+:
- System 7: The window in which the file???s icon appears
- System 8: reserved (set to 0) */
-};
-
-/*
- FXInfo (Finder extended file info) record -- not found in MFS
-*/
-struct mac_FXInfo
-{
- UINT16BE iconID; /* System 7: An ID number for the file???s icon; the
- numbers that identify icons are assigned by the
- Finder */
- /* System 8: Reserved (set to 0) */
- UINT16BE reserved[3]; /* Reserved (set to 0) */
- UINT8 script; /* System 7: if high-bit is set, the script code
- for displaying the file name; ignored otherwise */
- /* System 8: Extended flags MSB(?) */
- UINT8 XFlags; /* Extended flags */
- UINT16BE comment; /* System 7: Comment ID if high-bit is clear */
- /* System 8: Reserved (set to 0) */
- UINT32BE putAway; /* Put away folder ID (i.e. if the user moves the
- file onto the desktop, the directory ID of the
- folder from which the user moves the file is
- saved here) */
-};
-
-/*
- DInfo (Finder folder info) record -- not found in MFS
-*/
-struct mac_DInfo
-{
- mac_rect rect; /* Folder's window bounds */
- UINT16BE flags; /* Finder flags, e.g. kIsInvisible, kNameLocked, etc */
- mac_point location; /* Location of the folder in parent window */
- /* If set to {0, 0}, and the initied flag is
- clear, the Finder will place the item
- automatically */
- UINT16BE view; /* System 7: The manner in which folders are
- displayed */
- /* System 8: reserved (set to 0) */
-};
-
-/*
- DXInfo (Finder extended folder info) record -- not found in MFS
-*/
-struct mac_DXInfo
-{
- mac_point scroll; /* Scroll position */
- UINT32BE openChain; /* System 7: chain of directory IDs for open folders */
- /* System 8: reserved (set to 0) */
- UINT8 script; /* System 7: if high-bit is set, the script code
- for displaying the folder name; ignored otherwise */
- /* System 8: Extended flags MSB(?) */
- UINT8 XFlags; /* Extended flags */
- UINT16BE comment; /* System 7: Comment ID if high-bit is clear */
- /* System 8: Reserved (set to 0) */
- UINT32BE putAway; /* Put away folder ID (i.e. if the user moves the
- folder onto the desktop, the directory ID of
- the folder from which the user moves it is
- saved here) */
-};
-
-/*
- defines for FInfo & DInfo flags fields
-*/
-enum
-{
- fif_isOnDesk = 0x0001, /* System 6: set if item is located on desktop (files and folders) */
- /* System 7: Unused (set to 0) */
- fif_color = 0x000E, /* color coding (files and folders) */
- fif_colorReserved = 0x0010, /* System 6: reserved??? */
- /* System 7: Unused (set to 0) */
- fif_requiresSwitchLaunch= 0x0020, /* System 6: ??? */
- /* System 7: Unused (set to 0) */
- fif_isShared = 0x0040, /* Applications files: if set, the */
- /* application can be executed by */
- /* multiple users simultaneously. */
- /* Otherwise, set to 0. */
- fif_hasNoINITs = 0x0080, /* Extensions/Control Panels: if set(?), */
- /* this file contains no INIT */
- /* resource */
- /* Otherwise, set to 0. */
- fif_hasBeenInited = 0x0100, /* System 6: The Finder has recorded information from
- the file???s bundle resource into the desktop
- database and given the file or folder a
- position on the desktop. */
- /* System 7? 8?: Clear if the file contains desktop database */
- /* resources ('BNDL', 'FREF', 'open', 'kind'...) */
- /* that have not been added yet. Set only by the Finder */
- /* Reserved for folders - make sure this bit is cleared for folders */
-
- /* bit 0x0200 was at a point (AOCE for system 7.x?) the letter bit for
- AOCE, but was reserved before and it is reserved again in recent MacOS
- releases. */
-
- fif_hasCustomIcon = 0x0400, /* (files and folders) */
- fif_isStationery = 0x0800, /* System 7: (files only) */
- fif_nameLocked = 0x1000, /* (files and folders) */
- fif_hasBundle = 0x2000, /* Files only */
- fif_isInvisible = 0x4000, /* (files and folders) */
- fif_isAlias = 0x8000 /* System 7: (files only) */
-};
-
-/*
- mac_to_c_strncpy()
-
- Encode a macintosh string as a C string. The NUL character is escaped,
- using the "%00" sequence. To avoid any ambiguity, '%' is escaped with
- '%25'.
-
- dst (O): C string
- n (I): length of buffer pointed to by dst
- src (I): macintosh string (first byte is length)
-*/
-static void mac_to_c_strncpy(char *dst, int n, UINT8 *src)
-{
- size_t len = src[0];
- int i, j;
-
- i = j = 0;
- while ((i < len) && (j < n-1))
- {
- switch (src[i+1])
- {
- case '\0':
- if (j >= n-3)
- goto exit;
- dst[j] = '%';
- dst[j+1] = '0';
- dst[j+2] = '0';
- j += 3;
- break;
-
- case '%':
- if (j >= n-3)
- goto exit;
- dst[j] = '%';
- dst[j+1] = '2';
- dst[j+2] = '5';
- j += 3;
- break;
-
- default:
- dst[j] = src[i+1];
- j++;
- break;
- }
- i++;
- }
-
-exit:
- if (n > 0)
- dst[j] = '\0';
-}
-
-/*
- c_to_mac_strncpy()
-
- Decode a C string to a macintosh string. The NUL character is escaped,
- using the "%00" sequence. To avoid any ambiguity, '%' is escaped with
- '%25'.
-
- dst (O): macintosh string (first byte is length)
- src (I): C string
- n (I): length of string pointed to by src
-*/
-static void c_to_mac_strncpy(mac_str255 dst, const char *src, int n)
-{
- size_t len;
- int i;
- char buf[3];
-
-
- len = 0;
- i = 0;
- while ((i < n) && (len < 255))
- {
- switch (src[i])
- {
- case '%':
- if (i >= n-2)
- goto exit;
- buf[0] = src[i+1];
- buf[1] = src[i+2];
- buf[2] = '\0';
- dst[len+1] = strtoul(buf, NULL, 16);
- i += 3;
- break;
-
- default:
- dst[len+1] = src[i];
- i++;
- break;
- }
- len++;
- }
-
-exit:
- dst[0] = len;
-}
-
-/*
- mac_strcmp()
-
- Compare two macintosh strings
-
- s1 (I): the string to compare
- s2 (I): the comparison string
-
- Return a zero if s1 and s2 are equal, a negative value if s1 is less than
- s2, and a positive value if s1 is greater than s2.
-*/
-#ifdef UNUSED_FUNCTION
-static int mac_strcmp(const UINT8 *s1, const UINT8 *s2)
-{
- size_t common_len;
-
- common_len = (s1[0] <= s2[0]) ? s1[0] : s2[0];
-
- return memcmp(s1+1, s2+1, common_len) || ((int)s1[0] - s2[0]);
-}
-#endif
-
-/*
- mac_stricmp()
-
- Compare two macintosh strings in a manner compatible with the macintosh HFS
- file system.
-
- This functions emulates the way HFS (and MFS???) sorts string: this is
- equivalent to the RelString macintosh toolbox call with the caseSensitive
- parameter as false and the diacSensitive parameter as true.
-
- s1 (I): the string to compare
- s2 (I): the comparison string
-
- Return a zero if s1 and s2 are equal, a negative value if s1 is less than
- s2, and a positive value if s1 is greater than s2.
-
-Known issues:
- Using this function makes sense with the MacRoman encoding, as it means the
- computer will regard "DeskTop File", "Desktop File", "Desktop file", etc,
- as the same file. (UNIX users will probably regard this as an heresy, but
- you must consider that, unlike UNIX, the Macintosh was not designed for
- droids, but error-prone human beings that may forget about case.)
-
- (Also, letters with diatrical signs follow the corresponding letters
- without diacritical signs in the HFS catalog file. This does not matter,
- though, since the Finder will not display files in the HFS catalog order,
- but it will instead sort files according to whatever order is currently
- selected in the View menu.)
-
- However, with other text encodings, the behavior will be completely absurd.
- For instance, with the Greek encoding, it will think that the degree symbol
- is the same letter (with different case) as the upper-case Psi, so that if
- a program asks for a file called "90??" on a greek HFS volume, and there is
- a file called "90??" on this volume, file "90??" will be opened.
- Results will probably be even weirder with 2-byte scripts like Japanese or
- Chinese. Of course, we are not going to fix this issue, since doing so
- would break the compatibility with the original Macintosh OS.
-*/
-
-static int mac_stricmp(const UINT8 *s1, const UINT8 *s2)
-{
- static const unsigned char mac_char_sort_table[256] =
- {
- /* \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- /* \x08 \x09 \x0a \x0b \x0c \x0d \x0e \x0f */
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- /* \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 */
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- /* \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f */
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- /* \x20 \x21 \x22 \x23 \x24 \x25 \x26 \x27 */
- 0x20, 0x21, 0x22, 0x27, 0x28, 0x29, 0x2a, 0x2b,
- /* \x28 \x29 \x2a \x2b \x2c \x2d \x2e \x2f */
- 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
- /* \x30 \x31 \x32 \x33 \x34 \x35 \x36 \x37 */
- 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
- /* \x38 \x39 \x3a \x3b \x3c \x3d \x3e \x3f */
- 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
- /* \x40 \x41 \x42 \x43 \x44 \x45 \x46 \x47 */
- 0x46, 0x47, 0x51, 0x52, 0x54, 0x55, 0x5a, 0x5b,
- /* \x48 \x49 \x4a \x4b \x4c \x4d \x4e \x4f */
- 0x5c, 0x5d, 0x62, 0x63, 0x64, 0x65, 0x66, 0x68,
- /* \x50 \x51 \x52 \x53 \x54 \x55 \x56 \x57 */
- 0x71, 0x72, 0x73, 0x74, 0x76, 0x77, 0x7c, 0x7d,
- /* \x58 \x59 \x5a \x5b \x5c \x5d \x5e \x5f */
- 0x7e, 0x7f, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
- /* \x60 \x61 \x62 \x63 \x64 \x65 \x66 \x67 */
- 0x4d, 0x47, 0x51, 0x52, 0x54, 0x55, 0x5a, 0x5b,
- /* \x68 \x69 \x6a \x6b \x6c \x6d \x6e \x6f */
- 0x5c, 0x5d, 0x62, 0x63, 0x64, 0x65, 0x66, 0x68,
- /* \x70 \x71 \x72 \x73 \x74 \x75 \x76 \x77 */
- 0x71, 0x72, 0x73, 0x74, 0x76, 0x77, 0x7c, 0x7d,
- /* \x78 \x79 \x7a \x7b \x7c \x7d \x7e \x7f */
- 0x7e, 0x7f, 0x81, 0x87, 0x88, 0x89, 0x8a, 0x8b,
- /* \x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87 */
- 0x49, 0x4b, 0x53, 0x56, 0x67, 0x69, 0x78, 0x4e,
- /* \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f */
- 0x48, 0x4f, 0x49, 0x4a, 0x4b, 0x53, 0x56, 0x57,
- /* \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 */
- 0x58, 0x59, 0x5e, 0x5f, 0x60, 0x61, 0x67, 0x6d,
- /* \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f */
- 0x6e, 0x6f, 0x69, 0x6a, 0x79, 0x7a, 0x7b, 0x78,
- /* \xa0 \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 */
- 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x75,
- /* \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf */
- 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x4c, 0x6b,
- /* \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 */
- 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0,
- /* \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf */
- 0xa1, 0xa2, 0xa3, 0x50, 0x70, 0xa4, 0x4c, 0x6b,
- /* \xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 */
- 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0x25,
- /* \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf */
- 0x26, 0xac, 0x20, 0x48, 0x4a, 0x6a, 0x6c, 0x6c,
- /* \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 */
- 0xad, 0xae, 0x23, 0x24, 0x2c, 0x2d, 0xaf, 0xb0,
- /* \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf */
- 0x80, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
- /* \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 */
- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
- /* \xe8 \xe9 \xea \xeb \xec \xed \xee \xef */
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
- /* \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 */
- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
- /* \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff */
- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7
- };
-
- size_t common_len;
- int i;
- int c1, c2;
-
- common_len = (s1[0] <= s2[0]) ? s1[0] : s2[0];
-
- for (i=0; i<common_len; i++)
- {
- c1 = mac_char_sort_table[s1[i+1]];
- c2 = mac_char_sort_table[s2[i+1]];
- if (c1 != c2)
- return c1 - c2;
- }
-
- return ((int)s1[0] - s2[0]);
-}
-
-/*
- mac_strcpy()
-
- Copy a macintosh string
-
- dst (O): dest macintosh string
- src (I): source macintosh string (first byte is length)
-
- Return a zero if s1 and s2 are equal, a negative value if s1 is less than
- s2, and a positive value if s1 is greater than s2.
-*/
-INLINE void mac_strcpy(UINT8 *dest, const UINT8 *src)
-{
- memcpy(dest, src, src[0]+1);
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- mac_strncpy()
-
- Copy a macintosh string
-
- dst (O): dest macintosh string
- n (I): max string length for dest (range 0-255, buffer length + 1)
- src (I): source macintosh string (first byte is length)
-*/
-static void mac_strncpy(UINT8 *dest, int n, const UINT8 *src)
-{
- size_t len;
-
- len = src[0];
- if (len > n)
- len = n;
- dest[0] = len;
- memcpy(dest+1, src+1, len);
-}
-#endif
-
-/*
- disk image reference
-*/
-struct mac_l1_imgref
-{
- imgtool_image *image;
- UINT32 heads;
-};
-
-
-
-static imgtoolerr_t mac_find_block(mac_l1_imgref *image, int block,
- UINT32 *track, UINT32 *head, UINT32 *sector)
-{
- *track = 0;
- while(block >= (apple35_sectors_per_track(imgtool_floppy(image->image), *track) * image->heads))
- {
- block -= (apple35_sectors_per_track(imgtool_floppy(image->image), (*track)++) * image->heads);
- if (*track >= 80)
- return IMGTOOLERR_SEEKERROR;
- }
-
- *head = block / apple35_sectors_per_track(imgtool_floppy(image->image), *track);
- *sector = block % apple35_sectors_per_track(imgtool_floppy(image->image), *track);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*
- image_read_block()
-
- Read one 512-byte block of data from a macintosh disk image
-
- image (I/O): level-1 image reference
- block (I): address of block to read
- dest (O): buffer where block data should be stored
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_read_block(mac_l1_imgref *image, UINT32 block, void *dest)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- UINT32 track, head, sector;
-
- err = mac_find_block(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_read_sector(imgtool_floppy(image->image), head, track, sector, 0, dest, 512);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- image_write_block()
-
- Read one 512-byte block of data from a macintosh disk image
-
- image (I/O): level-1 image reference
- block (I): address of block to write
- src (I): buffer with the block data
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_write_block(mac_l1_imgref *image, UINT32 block, const void *src)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- UINT32 track, head, sector;
-
- err = mac_find_block(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_write_sector(imgtool_floppy(image->image), head, track, sector, 0, src, 512, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- image_get_tag_len()
-
- Get length of tag data (12 for GCR floppies, 20 for HD20, 0 otherwise)
-
- image (I/O): level-1 image reference
-
- Return tag length
-*/
-INLINE int image_get_tag_len(mac_l1_imgref *image)
-{
- return 0;
-}
-
-
-
-/*
- image_read_tag()
-
- Read a 12- or 20-byte tag record associated with a disk block
-
- image (I/O): level-1 image reference
- block (I): address of block to read
- dest (O): buffer where tag data should be stored
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_read_tag(mac_l1_imgref *image, UINT32 block, void *dest)
-{
- return IMGTOOLERR_UNEXPECTED;
-}
-
-/*
- image_write_tag()
-
- Write a 12- or 20-byte tag record associated with a disk block
-
- image (I/O): level-1 image reference
- block (I): address of block to write
- src (I): buffer with the tag data
-
- Return imgtool error code
-*/
-static imgtoolerr_t image_write_tag(mac_l1_imgref *image, UINT32 block, const void *src)
-{
- return IMGTOOLERR_UNEXPECTED;
-}
-
-#if 0
-#pragma mark -
-#pragma mark MFS/HFS WRAPPERS
-#endif
-
-enum mac_format
-{
- L2I_MFS,
- L2I_HFS
-};
-
-enum mac_forkID { data_fork = 0x00, rsrc_fork = 0xff };
-
-/*
- MFS image ref
-*/
-struct mfs_l2_imgref
-{
- UINT16 dir_num_files;
- UINT16 dir_start;
- UINT16 dir_blk_len;
-
- UINT16 ABStart;
-
- mac_str27 volname;
-
- unsigned char ABlink_dirty[13]; /* dirty flag for each disk block in the ABlink array */
- UINT8 ABlink[6141];
-};
-
-/*
- HFS extent descriptor
-*/
-struct hfs_extent
-{
- UINT16BE stABN; /* first allocation block */
- UINT16BE numABlks; /* number of allocation blocks */
-};
-
-/*
- HFS likes to group extents by 3 (it is 8 with HFS+), so we create a
- specific type.
-*/
-typedef hfs_extent hfs_extent_3[3];
-
-/*
- MFS open file ref
-*/
-struct mfs_fileref
-{
- UINT16 stBlk; /* first allocation block of file */
-};
-
-/*
- HFS open file ref
-*/
-struct hfs_fileref
-{
- hfs_extent_3 extents; /* first 3 file extents */
-
- UINT32 parID; /* CNID of parent directory (undefined for extent & catalog files) */
- mac_str31 filename; /* file name (undefined for extent & catalog files) */
-};
-
-struct mac_l2_imgref;
-
-/*
- MFS/HFS open file ref
-*/
-struct mac_fileref
-{
- struct mac_l2_imgref *l2_img; /* image pointer */
-
- UINT32 fileID; /* file ID (a.k.a. CNID in HFS/HFS+) */
-
- mac_forkID forkType; /* 0x00 for data, 0xff for resource */
-
- UINT32 eof; /* logical end-of-file */
- UINT32 pLen; /* physical end-of-file */
-
- UINT32 crPs; /* current position in file */
-
- UINT8 reload_buf;
- UINT8 block_buffer[512]; /* buffer with current file block */
-
- union
- {
- mfs_fileref mfs;
- hfs_fileref hfs;
- };
-};
-
-/*
- open BT ref
-*/
-struct mac_BTref
-{
- struct mac_fileref fileref; /* open B-tree file ref */
-
- UINT16 nodeSize; /* size of a node, in bytes */
- UINT32 rootNode; /* node number of root node */
- UINT32 firstLeafNode; /* node number of first leaf node */
- UINT32 attributes; /* persistent attributes about the tree */
- UINT16 treeDepth; /* maximum height (usually leaf nodes) */
- UINT16 maxKeyLength; /* maximum key length */
-
- /* function to compare keys during tree searches */
- int (*key_compare_func)(const void *key1, const void *key2);
-
- void *node_buf; /* current node buffer */
-};
-
-/*
- Constants for BTHeaderRec attributes field
-*/
-enum
-{
- btha_badCloseMask = 0x00000001, /* reserved */
- btha_bigKeysMask = 0x00000002, /* key length field is 16 bits */
- btha_variableIndexKeysMask = 0x00000004 /* keys in index nodes are variable length */
-};
-
-/*
- HFS image ref
-*/
-struct hfs_l2_imgref
-{
- UINT16 VBM_start;
-
- UINT16 ABStart;
-
- mac_str27 volname;
-
- mac_BTref extents_BT;
- mac_BTref cat_BT;
-
- UINT8 VBM[8192];
-};
-
-/*
- MFS/HFS image ref
-*/
-struct mac_l2_imgref
-{
- mac_l1_imgref l1_img;
-
- UINT16 numABs;
- UINT16 blocksperAB;
-
- UINT16 freeABs;
-
- UINT32 nxtCNID; /* nxtFNum in MFS, nxtCNID in HFS */
-
- mac_format format;
- union
- {
- mfs_l2_imgref mfs;
- hfs_l2_imgref hfs;
- } u;
-};
-
-/*
- MFS Master Directory Block
-*/
-struct mfs_mdb
-{
- UINT8 sigWord[2]; /* volume signature - always $D2D7 */
- UINT32BE crDate; /* date and time of volume creation */
- UINT32BE lsMod/*lsBkUp???*/;/* date and time of last modification (backup???) */
- UINT16BE atrb; /* volume attributes (0x0000) */
- /* bit 15 is set if volume is locked by software */
- UINT16BE nmFls; /* number of files in directory */
- UINT16BE dirSt; /* first block of directory */
-
- UINT16BE blLn; /* length of directory in blocks (0x000C) */
- UINT16BE nmAlBlks; /* number of allocation blocks in volume (0x0187) */
- UINT32BE alBlkSiz; /* size (in bytes) of allocation blocks (0x00000400) */
- UINT32BE clpSiz; /* default clump size - number of bytes to allocate
- when a file grows (0x00002000) */
- UINT16BE alBlSt; /* first allocation block in volume (0x0010) */
-
- UINT32BE nxtFNum; /* next unused file number */
- UINT16BE freeABs; /* number of unused allocation blocks */
-
- mac_str27 VN; /* volume name */
-
- UINT8 ABlink[512-64];/* Link array for file ABs. Array of nmAlBlks
- 12-bit-long entries, indexed by AB address. If an
- AB belongs to no file, the entry is 0; if an AB is
- the last in any file, the entry is 1; if an AB
- belongs to a file and is not the last one, the
- entry is the AB address of the next file AB plus 1.
- Note that the array extends on as many consecutive
- disk blocks as needed (usually the MDB block plus
- the next one). Incidentally, this array is not
- saved in the secondary MDB: presumably, the idea
- was that the disk utility could rely on the tag
- data to rebuild the link array if it should ever
- be corrupted. */
-};
-
-/*
- HFS Master Directory Block
-*/
-struct hfs_mdb
-{
-/* First fields are similar to MFS, though several fields have a different meaning */
- UINT8 sigWord[2]; /* volume signature - always $D2D7 */
- UINT32BE crDate; /* date and time of volume creation */
- UINT32BE lsMod; /* date and time of last modification */
- UINT16BE atrb; /* volume attributes (0x0000) */
- /* bit 15 is set if volume is locked by software */
- UINT16BE nmFls; /* number of files in root folder */
- UINT16BE VBMSt; /* first block of volume bitmap */
- UINT16BE allocPtr; /* start of next allocation search */
-
- UINT16BE nmAlBlks; /* number of allocation blocks in volume */
- UINT32BE alBlkSiz; /* size (in bytes) of allocation blocks */
- UINT32BE clpSiz; /* default clump size - number of bytes to allocate
- when a file grows */
- UINT16BE alBlSt; /* first allocation block in volume (0x0010) */
- UINT32BE nxtCNID; /* next unused catalog node ID */
- UINT16BE freeABs; /* number of unused allocation blocks */
- mac_str27 VN; /* volume name */
-
-/* next fields are HFS-specific */
-
- UINT32BE volBkUp; /* date and time of last backup */
- UINT16BE vSeqNum; /* volume backup sequence number */
- UINT32BE wrCnt; /* volume write count */
- UINT32BE xtClpSiz; /* clump size for extents overflow file */
- UINT32BE ctClpSiz; /* clump size for catalog file */
- UINT16BE nmRtDirs; /* number of directories in root folder */
- UINT32BE filCnt; /* number of files in volume */
- UINT32BE dirCnt; /* number of directories in volume */
- UINT8 fndrInfo[32]; /* information used by the Finder */
-
- union
- {
- struct
- {
- UINT16BE VCSize; /* size (in blocks) of volume cache */
- UINT16BE VBMCSize; /* size (in blocks) of volume bitmap cache */
- UINT16BE ctlCSize; /* size (in blocks) of common volume cache */
- };
- struct
- {
- UINT16BE embedSigWord; /* embedded volume signature */
- hfs_extent embedExtent; /* embedded volume location and size */
- } v2;
- } u;
-
- UINT32BE xtFlSize; /* size (in bytes) of extents overflow file */
- hfs_extent_3 xtExtRec; /* extent record for extents overflow file */
- UINT32BE ctFlSize; /* size (in bytes) of catalog file */
- hfs_extent_3 ctExtRec; /* extent record for catalog file */
-};
-
-/* to save a little stack space, we use the same buffer for MDB and next blocks */
-union img_open_buf
-{
- struct mfs_mdb mfs_mdb;
- struct hfs_mdb hfs_mdb;
- UINT8 raw[512];
-};
-
-/*
- Information extracted from catalog/directory
-*/
-struct mac_dirent
-{
- UINT16 dataRecType; /* type of data record */
-
- mac_FInfo flFinderInfo; /* information used by the Finder */
- mac_FXInfo flXFinderInfo; /* information used by the Finder */
-
- UINT8 flags; /* bit 0=1 if file locked */
-
- UINT32 fileID; /* file ID in directory/catalog */
-
- UINT32 dataLogicalSize; /* logical EOF of data fork */
- UINT32 dataPhysicalSize; /* physical EOF of data fork */
- UINT32 rsrcLogicalSize; /* logical EOF of resource fork */
- UINT32 rsrcPhysicalSize; /* physical EOF of resource fork */
-
- UINT32 createDate; /* date and time of creation */
- UINT32 modifyDate; /* date and time of last modification */
-};
-
-/*
- Tag record for GCR floppies (12 bytes)
-
- And, no, I don't know the format of the 20-byte tag record of the HD20
-*/
-struct floppy_tag_record
-{
- UINT32BE fileID; /* a.k.a. CNID */
- /* a value of 1 seems to be the default for non-AB blocks, but this is not consistent */
- UINT8 ftype; /* bit 1 = 1 if resource fork */
- /* bit 0 = 1 if block is allocated to user file (i.e. it is not
- in HFS extent & catalog, and not in non-AB blocks such
- as MDB and MFS directory)??? */
- /* bit 7 seems to be used, but I don't know what it means */
- /* a value of $FF seems to be the default for non-AB blocks, but this is not consistent */
- UINT8 fattr; /* bit 0 = 1 if locked(?) */
- /* a value of $FF seems to be the default for non-AB blocks, but this is not consistent */
- UINT16BE fblock; /* relative file block number (enough for any volume up to 32 MBytes in size) */
- UINT32BE wrCnt; /* MFS: date and time of last write */
- /* HFS: seems related to the wrCnt field in the mdb, i.e.
- each time a volume is written to, the current value of
- wrCnt is written in the tag field, then it is incremented */
- /* (DV17 says "disk block number", but it cannot be true) */
-};
-
-#ifdef UNUSED_FUNCTION
-static void hfs_image_close(struct mac_l2_imgref *l2_img);
-#endif
-static imgtoolerr_t mfs_file_get_nth_block_address(struct mac_fileref *fileref, UINT32 block_num, UINT32 *block_address);
-static imgtoolerr_t hfs_file_get_nth_block_address(struct mac_fileref *fileref, UINT32 block_num, UINT32 *block_address);
-static imgtoolerr_t mfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, mac_str255 filename, mac_dirent *cat_info, int create_it);
-static imgtoolerr_t hfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, UINT32 *parID, mac_str255 filename, mac_dirent *cat_info);
-static imgtoolerr_t mfs_file_open(struct mac_l2_imgref *l2_img, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref);
-static imgtoolerr_t hfs_file_open(struct mac_l2_imgref *l2_img, UINT32 parID, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref);
-static imgtoolerr_t mfs_file_setABeof(struct mac_fileref *fileref, UINT32 newABeof);
-static imgtoolerr_t mfs_dir_update(struct mac_fileref *fileref);
-
-static struct mac_l2_imgref *get_imgref(imgtool_image *img)
-{
- return (struct mac_l2_imgref *) imgtool_floppy_extrabytes(img);
-}
-
-
-#ifdef UNUSED_FUNCTION
-/*
- mac_image_close
-
- Close a macintosh image.
-
- l2_img (I/O): level-2 image reference
-*/
-static void mac_image_close(struct mac_l2_imgref *l2_img)
-{
- switch (l2_img->format)
- {
- case L2I_MFS:
- break;
-
- case L2I_HFS:
- hfs_image_close(l2_img);
- break;
- }
-}
-#endif
-
-/*
- mac_lookup_path
-
- Resolve a file path, and translate it to a parID + filename pair that enables
- to do an efficient file search on a HFS volume (and an inefficient one on
- MFS, but it is not an issue as MFS volumes typically have a few dozens
- files, vs. possibly thousands with HFS volumes).
-
- l2_img (I/O): level-2 image reference
- fpath (I): file path (C string)
- parID (O): set to the CNID of the parent directory if the volume is in HFS
- format (reserved for MFS volumes)
- filename (O): set to the actual name of the file, with capitalization matching
- the one on the volume rather than the one in the fpath parameter (Mac
- string)
- cat_info (O): catalog info for this file extracted from the catalog file
- (may be NULL)
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, UINT32 *parID, mac_str255 filename, mac_dirent *cat_info, int create_it)
-{
- imgtoolerr_t err = IMGTOOLERR_UNEXPECTED;
-
- switch (l2_img->format)
- {
- case L2I_MFS:
- *parID = 0;
- err = mfs_lookup_path(l2_img, fpath, filename, cat_info, create_it);
- break;
-
- case L2I_HFS:
- err = hfs_lookup_path(l2_img, fpath, parID, filename, cat_info);
- break;
- }
- return err;
-}
-
-/*
- mac_file_open
-
- Open a file located on a macintosh image
-
- l2_img (I/O): level-2 image reference
- parID (I): CNID of the parent directory if the volume is in HFS format
- (reserved for MFS volumes)
- filename (I): name of the file (Mac string)
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_open(struct mac_l2_imgref *l2_img, UINT32 parID, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref)
-{
- switch (l2_img->format)
- {
- case L2I_MFS:
- return mfs_file_open(l2_img, filename, fork, fileref);
-
- case L2I_HFS:
- return hfs_file_open(l2_img, parID, filename, fork, fileref);
- }
-
- return IMGTOOLERR_UNEXPECTED;
-}
-
-/*
- mac_file_read
-
- Read data from an open mac file, starting at current position in file
-
- fileref (I/O): mac file reference
- len (I): number of bytes to read
- dest (O): destination buffer
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_read(struct mac_fileref *fileref, UINT32 len, void *dest)
-{
- UINT32 block = 0;
- floppy_tag_record tag;
- int run_len;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
- if ((fileref->crPs + len) > fileref->eof)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
-
- while (len > 0)
- {
- if (fileref->reload_buf)
- {
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- err = mfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
-
- case L2I_HFS:
- err = hfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
- }
- if (err)
- return err;
- err = image_read_block(&fileref->l2_img->l1_img, block, fileref->block_buffer);
- if (err)
- return err;
- fileref->reload_buf = FALSE;
-
- if (TAG_EXTRA_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((fileref->crPs/512) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
- }
- run_len = 512 - (fileref->crPs % 512);
- if (run_len > len)
- run_len = len;
-
- memcpy(dest, fileref->block_buffer+(fileref->crPs % 512), run_len);
- len -= run_len;
- dest = (UINT8 *)dest + run_len;
- fileref->crPs += run_len;
- if ((fileref->crPs % 512) == 0)
- fileref->reload_buf = TRUE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mac_file_write
-
- Write data to an open mac file, starting at current position in file
-
- fileref (I/O): mac file reference
- len (I): number of bytes to read
- dest (O): destination buffer
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_write(struct mac_fileref *fileref, UINT32 len, const void *src)
-{
- UINT32 block = 0;
- floppy_tag_record tag;
- int run_len;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
- if ((fileref->crPs + len) > fileref->eof)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
-
- while (len > 0)
- {
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- err = mfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
-
- case L2I_HFS:
- err = hfs_file_get_nth_block_address(fileref, fileref->crPs/512, &block);
- break;
- }
- if (err)
- return err;
-
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((fileref->crPs/512) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
-
- if (fileref->reload_buf)
- {
- err = image_read_block(&fileref->l2_img->l1_img, block, fileref->block_buffer);
- if (err)
- return err;
- fileref->reload_buf = FALSE;
- }
- run_len = 512 - (fileref->crPs % 512);
- if (run_len > len)
- run_len = len;
-
- memcpy(fileref->block_buffer+(fileref->crPs % 512), src, run_len);
- err = image_write_block(&fileref->l2_img->l1_img, block, fileref->block_buffer);
- if (err)
- return err;
- /* update tag data */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- if (!TAG_CHECKS)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
- }
-
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- set_UINT32BE(&tag.wrCnt, mac_time_now());
- break;
-
- case L2I_HFS:
- /*set_UINT32BE(&tag.wrCnt, ++fileref->l2_img.u.hfs.wrCnt);*/ /* ***TODO*** */
- break;
- }
-
- err = image_write_tag(&fileref->l2_img->l1_img, block, &tag);
- if (err)
- return err;
- }
- len -= run_len;
- src = (const UINT8 *)src + run_len;
- fileref->crPs += run_len;
- if ((fileref->crPs % 512) == 0)
- fileref->reload_buf = TRUE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- mac_file_tell
-
- Get current position in an open mac file
-
- fileref (I/O): mac file reference
- filePos (O): current position in file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_tell(struct mac_fileref *fileref, UINT32 *filePos)
-{
- *filePos = fileref->crPs;
-
- return IMGTOOLERR_SUCCESS;
-}
-#endif
-
-/*
- mac_file_seek
-
- Set current position in an open mac file
-
- fileref (I/O): mac file reference
- filePos (I): new position in file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_seek(struct mac_fileref *fileref, UINT32 filePos)
-{
- if ((fileref->crPs / 512) != (filePos / 512))
- fileref->reload_buf = TRUE;
-
- fileref->crPs = filePos;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mac_file_seteof
-
- Set the position of the EOF in an open mac file
-
- fileref (I/O): mac file reference
- newEof (I): new position of EOF in file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mac_file_seteof(struct mac_fileref *fileref, UINT32 newEof)
-{
- UINT32 newABEof;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
- newABEof = (newEof + fileref->l2_img->blocksperAB * 512 - 1) / (fileref->l2_img->blocksperAB * 512);
-
-#if 0
- if (fileref->pLen % (fileref->l2_img->blocksperAB * 512))
- return IMGTOOLERR_CORRUPTIMAGE;
-#endif
-
- if (newEof < fileref->eof)
- fileref->eof = newEof;
-
- switch (fileref->l2_img->format)
- {
- case L2I_MFS:
- err = mfs_file_setABeof(fileref, newABEof);
- break;
-
- case L2I_HFS:
- err = IMGTOOLERR_UNIMPLEMENTED;
- break;
- }
- if (err)
- return err;
-
- fileref->eof = newEof;
-
- err = mfs_dir_update(fileref);
- if (err)
- return err;
-
- /* update current pos if beyond new EOF */
-#if 0
- if (fileref->crPs > newEof)
- {
- if ((fileref->crPs / 512) != (newEof / 512))
- fileref->reload_buf = TRUE;
-
- fileref->crPs = newEof;
- }
-#endif
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#if 0
-#pragma mark -
-#pragma mark MFS IMPLEMENTATION
-#endif
-
-/*
- directory entry for use in the directory file
-
- Note the structure is variable length. It is always word-aligned, and
- cannot cross block boundaries.
-
- Note that the directory does not seem to be sorted: the order in which
- files appear does not match file names, and it does not always match file
- IDs.
-*/
-struct mfs_dir_entry
-{
- UINT8 flags; /* bit 7=1 if entry used, bit 0=1 if file locked */
- /* 0x00 means end of block: if we are not done
- with reading the directory, the remnants will
- be read from next block */
- UINT8 flVersNum; /* version number (usually 0x00, but I don't
- have the IM volume that describes it) */
- mac_FInfo flFinderInfo; /* information used by the Finder */
-
- UINT32BE fileID; /* file ID */
-
- UINT16BE dataStartBlock; /* first allocation block of data fork */
- UINT32BE dataLogicalSize; /* logical EOF of data fork */
- UINT32BE dataPhysicalSize; /* physical EOF of data fork */
- UINT16BE rsrcStartBlock; /* first allocation block of resource fork */
- UINT32BE rsrcLogicalSize; /* logical EOF of resource fork */
- UINT32BE rsrcPhysicalSize; /* physical EOF of resource fork */
-
- UINT32BE createDate; /* date and time of creation */
- UINT32BE modifyDate; /* date and time of last modification */
-
- UINT8 name[1]; /* first char is length of file name */
- /* next chars are file name - 255 chars at most */
- /* IIRC, Finder 7 only supports 31 chars,
- wheareas earlier versions support 63 chars */
-};
-
-/*
- FOBJ desktop resource: describes a folder, or the location of the volume
- icon.
-
- In typical Apple manner, this resource is not documented. However, I have
- managed to reverse engineer some parts of it.
-*/
-struct mfs_FOBJ
-{
- UINT8 unknown0[2]; /* $00: $0004 for disk, $0008 for folder??? */
- mac_point location; /* $02: location in parent window */
- UINT8 unknown1[4]; /* $06: ??? */
- UINT8 view; /* $0A: manner in which folders are displayed??? */
- UINT8 unknown2; /* $0B: ??? */
- UINT16BE par_fldr; /* $0C: parent folder ID */
- UINT8 unknown3[10]; /* $0E: ??? */
- UINT16BE unknown4; /* $18: ??? */
- UINT32BE createDate; /* $1A: date and time of creation */
- UINT32BE modifyDate; /* $1E: date and time of last modification */
- UINT16BE unknown5; /* $22: put-away folder ID?????? */
- UINT8 unknown6[8]; /* $24: ??? */
- mac_rect bounds; /* $2C: window bounds */
- mac_point scroll; /* $34: current scroll offset??? */
- union
- { /* I think there are two versions of the structure */
- struct
- {
- UINT16BE item_count; /* number of items (folders and files) in
- this folder */
- UINT32BE item_descs[1]; /* this variable-length array has
- item_count entries - meaning of entry is unknown */
- } v1;
- struct
- {
- UINT16BE zerofill; /* always 0? */
- UINT16BE unknown0; /* always 0??? */
- UINT16BE item_count; /* number of items (folders and files) in
- this folder */
- UINT8 unknown1[20]; /* ??? */
- UINT8 name[1]; /* variable-length macintosh string */
- } v2;
- } u;
-};
-
-/*
- MFS open dir ref
-*/
-struct mfs_dirref
-{
- struct mac_l2_imgref *l2_img; /* image pointer */
- UINT16 index; /* current file index in the disk directory */
- UINT16 cur_block; /* current block offset in directory file */
- UINT16 cur_offset; /* current byte offset in current block of directory file */
- UINT8 block_buffer[512]; /* buffer with current directory block */
-};
-
-
-
-static imgtoolerr_t mfs_image_create(imgtool_image *image, imgtool_stream *stream, option_resolution *opts)
-{
- imgtoolerr_t err;
- UINT8 buffer[512];
- UINT32 heads, tracks, sector_bytes, i;
- UINT32 total_disk_blocks, total_allocation_blocks, allocation_block_size;
- UINT32 free_allocation_blocks;
-
- heads = option_resolution_lookup_int(opts, 'H');
- tracks = option_resolution_lookup_int(opts, 'T');
- sector_bytes = option_resolution_lookup_int(opts, 'L');
-
- get_imgref(image)->l1_img.image = image;
- get_imgref(image)->l1_img.heads = heads;
-
- if (sector_bytes != 512)
- return IMGTOOLERR_UNEXPECTED;
-
- /* computation */
- allocation_block_size = 1024;
- total_disk_blocks = 0;
- for (i = 0; i < tracks; i++)
- total_disk_blocks += heads * apple35_sectors_per_track(imgtool_floppy(image), i) * sector_bytes / 512;
- total_allocation_blocks = total_disk_blocks / (allocation_block_size / 512);
- free_allocation_blocks = total_allocation_blocks - 3;
-
- /* write master directory block */
- memset(buffer, 0, sizeof(buffer));
- place_integer_be(buffer, 0, 2, 0xd2d7); /* signature */
- place_integer_be(buffer, 2, 4, mac_time_now()); /* creation date */
- place_integer_be(buffer, 6, 4, mac_time_now()); /* last modified date */
- place_integer_be(buffer, 10, 2, 0); /* volume attributes */
- place_integer_be(buffer, 12, 2, 0); /* number of files in directory */
- place_integer_be(buffer, 14, 2, 4); /* first block of directory */
- place_integer_be(buffer, 16, 2, 12); /* length of directory in blocks */
- place_integer_be(buffer, 18, 2, total_allocation_blocks); /* allocation blocks on volume count */
- place_integer_be(buffer, 20, 4, allocation_block_size); /* allocation block size */
- place_integer_be(buffer, 24, 4, 8192); /* default clumping size */
- place_integer_be(buffer, 28, 2, 16); /* first allocation block on volume */
- place_integer_be(buffer, 30, 4, 2); /* next unused catalog node */
- place_integer_be(buffer, 34, 2, free_allocation_blocks); /* free allocation block count */
- pascal_from_c_string(&buffer[36], 28, "Untitled"); /* volume title */
-
- err = image_write_block(&get_imgref(image)->l1_img, 2, buffer);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*
- mfs_image_open
-
- Open a MFS image. Image must already be open on level 1. This function
- should not be called directly: call mac_image_open() instead.
-
- l2_img (I/O): level-2 image reference to open (l1_img and format fields
- must be initialized)
- img_open_buf (I): buffer with the MDB block
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_image_open(imgtool_image *image, imgtool_stream *stream)
-{
- imgtoolerr_t err;
- struct mac_l2_imgref *l2_img;
- img_open_buf buf_local;
- img_open_buf *buf;
-
- l2_img = get_imgref(image);
- l2_img->l1_img.image = image;
- l2_img->l1_img.heads = 1;
- l2_img->format = L2I_MFS;
-
- /* read MDB */
- err = image_read_block(&l2_img->l1_img, 2, &buf_local.raw);
- if (err)
- return err;
- buf = &buf_local;
-
- /* check signature word */
- if ((buf->mfs_mdb.sigWord[0] != 0xd2) || (buf->mfs_mdb.sigWord[1] != 0xd7)
- || (buf->mfs_mdb.VN[0] > 27))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- l2_img->u.mfs.dir_num_files = get_UINT16BE(buf->mfs_mdb.nmFls);
- l2_img->u.mfs.dir_start = get_UINT16BE(buf->mfs_mdb.dirSt);
- l2_img->u.mfs.dir_blk_len = get_UINT16BE(buf->mfs_mdb.blLn);
-
- l2_img->numABs = get_UINT16BE(buf->mfs_mdb.nmAlBlks);
- if ((get_UINT32BE(buf->mfs_mdb.alBlkSiz) % 512) || (get_UINT32BE(buf->mfs_mdb.alBlkSiz) == 0))
- return IMGTOOLERR_CORRUPTIMAGE;
- l2_img->blocksperAB = get_UINT32BE(buf->mfs_mdb.alBlkSiz) / 512;
- l2_img->u.mfs.ABStart = get_UINT16BE(buf->mfs_mdb.alBlSt);
-
- l2_img->nxtCNID = get_UINT32BE(buf->mfs_mdb.nxtFNum);
-
- l2_img->freeABs = get_UINT16BE(buf->mfs_mdb.freeABs);
-
- mac_strcpy(l2_img->u.mfs.volname, buf->mfs_mdb.VN);
-
- if (l2_img->numABs > 4094)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* extract link array */
- {
- int byte_len = l2_img->numABs + ((l2_img->numABs + 1) >> 1);
- int cur_byte;
- int cur_block;
- int block_len = sizeof(buf->mfs_mdb.ABlink);
-
- /* clear dirty flags */
- for (cur_block=0; cur_block<13; cur_block++)
- l2_img->u.mfs.ABlink_dirty[cur_block] = 0;
-
- /* append the chunk after MDB to link array */
- cur_byte = 0;
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
- memcpy(l2_img->u.mfs.ABlink+cur_byte, buf->mfs_mdb.ABlink, block_len);
- cur_byte += block_len;
- cur_block = 2;
- while (cur_byte < byte_len)
- {
- /* read next block */
- cur_block++;
- err = image_read_block(&l2_img->l1_img, cur_block, buf->raw);
- if (err)
- return err;
- block_len = 512;
-
- /* append this block to link array */
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
- memcpy(l2_img->u.mfs.ABlink+cur_byte, buf->raw, block_len);
- cur_byte += block_len;
- }
- /* check that link array and directory don't overlap */
- if (cur_block >= l2_img->u.mfs.dir_start)
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_update_mdb
-
- Update MDB on disk
-
- l2_img (I/O): level-2 image reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_update_mdb(struct mac_l2_imgref *l2_img)
-{
- imgtoolerr_t err;
- union
- {
- struct mfs_mdb mfs_mdb;
- UINT8 raw[512];
- } buf;
-
- assert(l2_img->format == L2I_MFS);
-
- /* read MDB */
- err = image_read_block(&l2_img->l1_img, 2, &buf.mfs_mdb);
- if (err)
- return err;
-
- set_UINT16BE(&buf.mfs_mdb.nmFls, l2_img->u.mfs.dir_num_files);
-#if 0 /* these fields are never changed */
- set_UINT16BE(&buf.mfs_mdb.dirSt, l2_img->u.mfs.dir_start);
- set_UINT16BE(&buf.mfs_mdb.blLn, l2_img->u.mfs.dir_blk_len);
-
- set_UINT16BE(&buf.mfs_mdb.nmAlBlks, l2_img->numABs);
- set_UINT32BE(&buf.mfs_mdb.alBlkSiz, l2_img->blocksperAB*512);
- set_UINT16BE(&buf.mfs_mdb.alBlSt, l2_img->u.mfs.ABStart);
-#endif
-
- set_UINT32BE(&buf.mfs_mdb.nxtFNum, l2_img->nxtCNID);
-
- set_UINT16BE(&buf.mfs_mdb.freeABs, l2_img->freeABs);
-
-#if 0 /* these fields are never changed */
- mac_strcpy(buf.mfs_mdb.VN, l2_img->u.mfs.volname);
-#endif
-
- /* save link array */
- {
- int byte_len = l2_img->numABs + ((l2_img->numABs + 1) >> 1);
- int cur_byte = 0;
- int cur_block = 2;
- int block_len = sizeof(buf.mfs_mdb.ABlink);
-
- /* update the chunk of link array after the MDB */
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
- memcpy(buf.mfs_mdb.ABlink, l2_img->u.mfs.ABlink+cur_byte, block_len);
- cur_byte += block_len;
-
- if (block_len < sizeof(buf.mfs_mdb.ABlink))
- memset(buf.mfs_mdb.ABlink+block_len, 0, sizeof(buf.mfs_mdb.ABlink)-block_len);
-
- l2_img->u.mfs.ABlink_dirty[0] = 0;
-
- /* write back modified MDB+link */
- err = image_write_block(&l2_img->l1_img, 2, &buf.mfs_mdb);
- if (err)
- return err;
-
- while (cur_byte < byte_len)
- {
- /* advance to next block */
- cur_block++;
- block_len = 512;
-
- /* extract the current chunk of link array */
- if (block_len > (byte_len - cur_byte))
- block_len = byte_len - cur_byte;
-
- if (l2_img->u.mfs.ABlink_dirty[cur_block-2])
- {
- memcpy(buf.raw, l2_img->u.mfs.ABlink+cur_byte, block_len);
- if (block_len < 512)
- memset(buf.raw+block_len, 0, 512-block_len);
- /* write back link array */
- err = image_write_block(&l2_img->l1_img, cur_block, buf.raw);
- if (err)
- return err;
- l2_img->u.mfs.ABlink_dirty[cur_block-2] = 0;
- }
-
- cur_byte += block_len;
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_dir_open
-
- Open the directory file
-
- l2_img (I/O): level-2 image reference
- dirref (O): open directory file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_open(struct mac_l2_imgref *l2_img, const char *path, mfs_dirref *dirref)
-{
- imgtoolerr_t err;
-
- assert(l2_img->format == L2I_MFS);
-
- if (path[0])
- return IMGTOOLERR_PATHNOTFOUND;
-
- dirref->l2_img = l2_img;
- dirref->index = 0;
-
- dirref->cur_block = 0;
- dirref->cur_offset = 0;
- err = image_read_block(&l2_img->l1_img, l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_dir_read
-
- Read one entry of directory file
-
- dirref (I/O): open directory file reference
- dir_entry (O): set to point to the entry read: set to NULL if EOF or error
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_read(mfs_dirref *dirref, mfs_dir_entry **dir_entry)
-{
- mfs_dir_entry *cur_dir_entry;
- size_t cur_dir_entry_len;
- imgtoolerr_t err;
-
-
- if (dir_entry)
- *dir_entry = NULL;
-
- if (dirref->index == dirref->l2_img->u.mfs.dir_num_files)
- /* EOF */
- return IMGTOOLERR_SUCCESS;
-
- /* get cat entry pointer */
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- while ((dirref->cur_offset == 512) || ! (cur_dir_entry->flags & 0x80))
- {
- dirref->cur_block++;
- dirref->cur_offset = 0;
- if (dirref->cur_block > dirref->l2_img->u.mfs.dir_blk_len)
- /* aargh! */
- return IMGTOOLERR_CORRUPTIMAGE;
- err = image_read_block(&dirref->l2_img->l1_img, dirref->l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- }
-
- cur_dir_entry_len = offsetof(mfs_dir_entry, name) + cur_dir_entry->name[0] + 1;
-
- if ((dirref->cur_offset + cur_dir_entry_len) > 512)
- /* aargh! */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* entry looks valid: set pointer to entry */
- if (dir_entry)
- *dir_entry = cur_dir_entry;
-
- /* update offset in block */
- dirref->cur_offset += cur_dir_entry_len;
- /* align to word boundary */
- dirref->cur_offset = (dirref->cur_offset + 1) & ~1;
-
- /* update file count */
- dirref->index++;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_dir_insert
-
- Add an entry in the directory file
-
- l2_img (I/O): level-2 image reference
- dirref (I/O): open directory file reference
- filename (I): name of the file for which an entry is created (Mac string)
- dir_entry (O): set to point to the created entry: set to NULL if EOF or
- error
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_insert(struct mac_l2_imgref *l2_img, mfs_dirref *dirref, const UINT8 *new_fname, mfs_dir_entry **dir_entry)
-{
- size_t new_dir_entry_len;
- mfs_dir_entry *cur_dir_entry;
- size_t cur_dir_entry_len;
- UINT32 cur_date;
- imgtoolerr_t err;
-
- dirref->l2_img = l2_img;
- dirref->index = 0;
-
- new_dir_entry_len = offsetof(mfs_dir_entry, name) + new_fname[0] + 1;
-
- for (dirref->cur_block = 0; dirref->cur_block < dirref->l2_img->u.mfs.dir_blk_len; dirref->cur_block++)
- {
- /* read current block */
- err = image_read_block(&dirref->l2_img->l1_img, dirref->l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
-
- /* get free chunk in this block */
- dirref->cur_offset = 0;
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- while ((dirref->cur_offset < 512) && (cur_dir_entry->flags & 0x80))
- { /* skip cur_dir_entry */
- cur_dir_entry_len = offsetof(mfs_dir_entry, name) + cur_dir_entry->name[0] + 1;
- /* update offset in block */
- dirref->cur_offset += cur_dir_entry_len;
- /* align to word boundary */
- dirref->cur_offset = (dirref->cur_offset + 1) & ~1;
- /* update entry pointer */
- cur_dir_entry = (mfs_dir_entry *) (dirref->block_buffer + dirref->cur_offset);
- /* update file index (useless, but can't harm) */
- dirref->index++;
- }
-
- if (new_dir_entry_len <= (/*512*/510 - dirref->cur_offset))
- {
- /*memcpy(cur_dir_entry, new_dir_entry, new_dir_entry_len);*/
- cur_dir_entry->flags = 0x80;
- cur_dir_entry->flVersNum = 0x00;
- memset(&cur_dir_entry->flFinderInfo, 0, sizeof(cur_dir_entry->flFinderInfo));
- set_UINT32BE(&cur_dir_entry->fileID, dirref->l2_img->nxtCNID++);
- set_UINT16BE(&cur_dir_entry->dataStartBlock, 1);
- set_UINT32BE(&cur_dir_entry->dataLogicalSize, 0);
- set_UINT32BE(&cur_dir_entry->dataPhysicalSize, 0);
- set_UINT16BE(&cur_dir_entry->rsrcStartBlock, 1);
- set_UINT32BE(&cur_dir_entry->rsrcLogicalSize, 0);
- set_UINT32BE(&cur_dir_entry->rsrcPhysicalSize, 0);
- cur_date = mac_time_now();
- set_UINT32BE(&cur_dir_entry->createDate, cur_date);
- set_UINT32BE(&cur_dir_entry->modifyDate, cur_date);
- mac_strcpy(cur_dir_entry->name, new_fname);
-
- /* update offset in block */
- dirref->cur_offset += new_dir_entry_len;
- /* align to word boundary */
- dirref->cur_offset = (dirref->cur_offset + 1) & ~1;
- if (dirref->cur_offset < 512)
- /* mark remaining space as free record */
- dirref->block_buffer[dirref->cur_offset] = 0;
- /* write back directory */
- err = image_write_block(&dirref->l2_img->l1_img, dirref->l2_img->u.mfs.dir_start + dirref->cur_block, dirref->block_buffer);
- if (err)
- return err;
- /* update file count */
- dirref->l2_img->u.mfs.dir_num_files++;
-
- /* update MDB (nxtCNID & dir_num_files fields) */
- err = mfs_update_mdb(dirref->l2_img);
- if (err)
- return err;
-
- if (dir_entry)
- *dir_entry = cur_dir_entry;
- return IMGTOOLERR_SUCCESS;
- }
- }
-
- return IMGTOOLERR_NOSPACE;
-}
-
-/*
- mfs_dir_update
-
- Update one entry of directory file
-
- fileref (I/O): open file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_dir_update(struct mac_fileref *fileref)
-{
- UINT16 cur_block;
- UINT16 cur_offset;
- UINT8 block_buffer[512];
- mfs_dir_entry *cur_dir_entry;
- size_t cur_dir_entry_len;
- imgtoolerr_t err;
-
- for (cur_block = 0; cur_block < fileref->l2_img->u.mfs.dir_blk_len; cur_block++)
- {
- /* read current block */
- err = image_read_block(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.dir_start + cur_block, block_buffer);
- if (err)
- return err;
-
- /* get free chunk in this block */
- cur_offset = 0;
- cur_dir_entry = (mfs_dir_entry *) (block_buffer + cur_offset);
- while ((cur_offset < 512) && (cur_dir_entry->flags & 0x80))
- {
- if (get_UINT32BE(cur_dir_entry->fileID) == fileref->fileID)
- { /* found it: update directory entry */
- switch (fileref->forkType)
- {
- case data_fork:
- set_UINT16BE(&cur_dir_entry->dataStartBlock, fileref->mfs.stBlk);
- set_UINT32BE(&cur_dir_entry->dataLogicalSize, fileref->eof);
- set_UINT32BE(&cur_dir_entry->dataPhysicalSize, fileref->pLen);
- break;
-
- case rsrc_fork:
- set_UINT16BE(&cur_dir_entry->rsrcStartBlock, fileref->mfs.stBlk);
- set_UINT32BE(&cur_dir_entry->rsrcLogicalSize, fileref->eof);
- set_UINT32BE(&cur_dir_entry->rsrcPhysicalSize, fileref->pLen);
- break;
- }
- /* write back directory */
- err = image_write_block(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.dir_start + cur_block, block_buffer);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
- }
- /* skip cur_dir_entry */
- cur_dir_entry_len = offsetof(mfs_dir_entry, name) + cur_dir_entry->name[0] + 1;
- /* update offset in block */
- cur_offset += cur_dir_entry_len;
- /* align to word boundary */
- cur_offset = (cur_offset + 1) & ~1;
- /* update entry pointer */
- cur_dir_entry = (mfs_dir_entry *) (block_buffer + cur_offset);
- }
- }
-
- return IMGTOOLERR_UNEXPECTED;
-}
-
-
-/*
- mfs_find_dir_entry
-
- Find a file in an MFS directory
-
- dirref (I/O): open directory file reference
- filename (I): file name (Mac string)
- dir_entry (O): set to point to the entry read: set to NULL if EOF or error
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_find_dir_entry(mfs_dirref *dirref, const mac_str255 filename, mfs_dir_entry **dir_entry)
-{
- mfs_dir_entry *cur_dir_entry;
- imgtoolerr_t err;
-
- if (dir_entry)
- *dir_entry = NULL;
-
- /* scan dir for file */
- while (1)
- {
- err = mfs_dir_read(dirref, &cur_dir_entry);
- if (err)
- return err;
- if (!cur_dir_entry)
- /* EOF */
- break;
- if ((! mac_stricmp(filename, cur_dir_entry->name)) && (cur_dir_entry->flVersNum == 0))
- { /* file found */
-
- if (dir_entry)
- *dir_entry = cur_dir_entry;
-
- return IMGTOOLERR_SUCCESS;
- }
- }
-
- return IMGTOOLERR_FILENOTFOUND;
-}
-
-/*
- mfs_lookup_path
-
- Resolve a file path for MFS volumes. This function should not be called
- directly: call mac_lookup_path instead.
-
- l2_img (I/O): level-2 image reference
- fpath (I): file path (C string)
- filename (O): set to the actual name of the file, with capitalization matching
- the one on the volume rather than the one in the fpath parameter (Mac
- string)
- cat_info (I/O): on output, catalog info for this file extracted from the
- catalog file (may be NULL)
- If create_it is TRUE, created info will first be set according to the
- data from cat_info
- create_it (I): TRUE if entry should be created if not found
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, mac_str255 filename, mac_dirent *cat_info, int create_it)
-{
- mfs_dirref dirref;
- mfs_dir_entry *dir_entry;
- imgtoolerr_t err;
-
- /* rapid check */
- if (strchr(fpath, ':'))
- return IMGTOOLERR_BADFILENAME;
-
- /* extract file name */
- c_to_mac_strncpy(filename, fpath, strlen(fpath));
-
- /* open dir */
- mfs_dir_open(l2_img, "", &dirref);
-
- /* find file */
- err = mfs_find_dir_entry(&dirref, filename, &dir_entry);
- if ((err == IMGTOOLERR_FILENOTFOUND) && create_it)
- err = mfs_dir_insert(l2_img, &dirref, filename, &dir_entry);
- if (err)
- return err;
-
- mac_strcpy(filename, dir_entry->name);
-
- if (create_it && cat_info)
- {
- dir_entry->flFinderInfo = cat_info->flFinderInfo;
- dir_entry->flags = (dir_entry->flags & 0x80) | (cat_info->flags & 0x7f);
- set_UINT32BE(&dir_entry->createDate, cat_info->createDate);
- set_UINT32BE(&dir_entry->modifyDate, cat_info->modifyDate);
-
- /* write current directory block */
- err = image_write_block(&l2_img->l1_img, l2_img->u.mfs.dir_start + dirref.cur_block, dirref.block_buffer);
- if (err)
- return err;
- }
-
- if (cat_info)
- {
- cat_info->flFinderInfo = dir_entry->flFinderInfo;
- memset(&cat_info->flXFinderInfo, 0, sizeof(cat_info->flXFinderInfo));
- cat_info->flags = dir_entry->flags;
- cat_info->fileID = get_UINT32BE(dir_entry->fileID);
- cat_info->dataLogicalSize = get_UINT32BE(dir_entry->dataLogicalSize);
- cat_info->dataPhysicalSize = get_UINT32BE(dir_entry->dataPhysicalSize);
- cat_info->rsrcLogicalSize = get_UINT32BE(dir_entry->rsrcLogicalSize);
- cat_info->rsrcPhysicalSize = get_UINT32BE(dir_entry->rsrcPhysicalSize);
- cat_info->createDate = get_UINT32BE(dir_entry->createDate);
- cat_info->modifyDate = get_UINT32BE(dir_entry->modifyDate);
- cat_info->dataRecType = 0x200; /* hcrt_File */
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_open_internal
-
- Open a file fork, given its directory entry. This function should not be
- called directly: call mfs_file_open instead.
-
- l2_img (I/O): level-2 image reference
- dir_entry (I): directory entry for the file to open
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_open_internal(struct mac_l2_imgref *l2_img, const mfs_dir_entry *dir_entry, mac_forkID fork, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_MFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = get_UINT32BE(dir_entry->fileID);
- fileref->forkType = fork;
-
- switch (fork)
- {
- case data_fork:
- fileref->mfs.stBlk = get_UINT16BE(dir_entry->dataStartBlock);
- fileref->eof = get_UINT32BE(dir_entry->dataLogicalSize);
- fileref->pLen = get_UINT32BE(dir_entry->dataPhysicalSize);
- break;
-
- case rsrc_fork:
- fileref->mfs.stBlk = get_UINT16BE(dir_entry->rsrcStartBlock);
- fileref->eof = get_UINT32BE(dir_entry->rsrcLogicalSize);
- fileref->pLen = get_UINT32BE(dir_entry->rsrcPhysicalSize);
- break;
- }
-
- fileref->crPs = 0;
-
- fileref->reload_buf = TRUE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_open
-
- Open a file located on a MFS volume. This function should not be called
- directly: call mac_file_open instead.
-
- l2_img (I/O): level-2 image reference
- filename (I): name of the file (Mac string)
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_open(struct mac_l2_imgref *l2_img, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref)
-{
- mfs_dirref dirref;
- mfs_dir_entry *dir_entry;
- imgtoolerr_t err;
-
- /* open dir */
- mfs_dir_open(l2_img, "", &dirref);
-
- /* find file */
- err = mfs_find_dir_entry(&dirref, filename, &dir_entry);
- if (err)
- return err;
-
- /* open it */
- return mfs_file_open_internal(l2_img, dir_entry, fork, fileref);
-}
-
-/*
- mfs_get_ABlink
-
- Read one entry of the Allocation Bitmap link array, on an MFS volume.
-
- l2_img (I/O): level-2 image reference
- AB_address (I): index in the array, which is an AB address
-
- Returns the 12-bit value read in array.
-*/
-static UINT16 mfs_get_ABlink(struct mac_l2_imgref *l2_img, UINT16 AB_address)
-{
- UINT16 reply;
- int base;
-
- assert(l2_img->format == L2I_MFS);
-
- base = (AB_address >> 1) * 3;
-
- if (! (AB_address & 1))
- reply = (l2_img->u.mfs.ABlink[base] << 4) | ((l2_img->u.mfs.ABlink[base+1] >> 4) & 0x0f);
- else
- reply = ((l2_img->u.mfs.ABlink[base+1] << 8) & 0xf00) | l2_img->u.mfs.ABlink[base+2];
-
- return reply;
-}
-
-/*
- mfs_set_ABlink
-
- Set one entry of the Allocation Bitmap link array, on an MFS volume.
-
- l2_img (I/O): level-2 image reference
- AB_address (I): index in the array, which is an AB address
- data (I): 12-bit value to write in array
-*/
-static void mfs_set_ABlink(struct mac_l2_imgref *l2_img, UINT16 AB_address, UINT16 data)
-{
- int base;
-
- assert(l2_img->format == L2I_MFS);
-
- base = (AB_address >> 1) * 3;
-
- if (! (AB_address & 1))
- {
- l2_img->u.mfs.ABlink[base] = (data >> 4) & 0xff;
- l2_img->u.mfs.ABlink[base+1] = (l2_img->u.mfs.ABlink[base+1] & 0x0f) | ((data << 4) & 0xf0);
-
- l2_img->u.mfs.ABlink_dirty[(base+64)/512] = 1;
- l2_img->u.mfs.ABlink_dirty[(base+1+64)/512] = 1;
- }
- else
- {
- l2_img->u.mfs.ABlink[base+1] = (l2_img->u.mfs.ABlink[base+1] & 0xf0) | ((data >> 8) & 0x0f);
- l2_img->u.mfs.ABlink[base+2] = data & 0xff;
-
- l2_img->u.mfs.ABlink_dirty[(base+1+64)/512] = 1;
- l2_img->u.mfs.ABlink_dirty[(base+2+64)/512] = 1;
- }
-}
-
-/*
- mfs_file_get_nth_block_address
-
- Get the disk block address of a given block in an open file on a MFS image.
- Called by macintosh file code.
-
- fileref (I/O): open mac file reference
- block_num (I): file block index
- block_address (O): disk block address for the file block
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_get_nth_block_address(struct mac_fileref *fileref, UINT32 block_num, UINT32 *block_address)
-{
- UINT32 AB_num;
- UINT32 i;
- UINT16 AB_address;
-
- assert(fileref->l2_img->format == L2I_MFS);
-
- AB_num = block_num / fileref->l2_img->blocksperAB;
-
- AB_address = fileref->mfs.stBlk;
- if ((AB_address == 0) || (AB_address >= fileref->l2_img->numABs+2))
- /* 0 -> ??? */
- return IMGTOOLERR_CORRUPTIMAGE;
- if (AB_address == 1)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
- AB_address -= 2;
- for (i=0; i<AB_num; i++)
- {
- AB_address = mfs_get_ABlink(fileref->l2_img, AB_address);
- if ((AB_address == 0) || (AB_address >= fileref->l2_img->numABs+2))
- /* 0 -> empty block: there is no way an empty block could make it
- into the link chain!!! */
- return IMGTOOLERR_CORRUPTIMAGE;
- if (AB_address == 1)
- /* EOF */
- return IMGTOOLERR_UNEXPECTED;
- AB_address -= 2;
- }
-
- *block_address = fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB
- + block_num % fileref->l2_img->blocksperAB;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_allocABs
-
- Allocate a chunk of ABs
-
- fileref (I/O): open mac file reference
- lastAB (I): AB address on disk of last file AB (only if
- fileref->mfs.stBlk != 1)
- allocABs (I): number of ABs to allocate in addition to the current file
- allocation
- fblock (I): first file block to allocate (used for tag data)
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_allocABs(struct mac_fileref *fileref, UINT16 lastAB, UINT32 allocABs, UINT32 fblock)
-{
- int numABs = fileref->l2_img->numABs;
- int free_ABs;
- int i, j;
- floppy_tag_record tag;
- int extentBaseAB, extentABlen;
- int firstBestExtentBaseAB = 0, firstBestExtentABlen;
- int secondBestExtentBaseAB = 0, secondBestExtentABlen;
- imgtoolerr_t err;
-
- /* return if done */
- if (! allocABs)
- return IMGTOOLERR_SUCCESS;
-
- /* compute free space */
- free_ABs = 0;
- for (i=0; i<numABs; i++)
- {
- if (mfs_get_ABlink(fileref->l2_img, i) == 0)
- {
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + i * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if (get_UINT32BE(tag.fileID) != 0)
- {
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- goto corrupt_free_block;
- }
- }
- }
- }
-
- free_ABs++;
- }
-corrupt_free_block:
- ;
- }
-
- /* check we have enough free space */
- if (free_ABs < allocABs)
- return IMGTOOLERR_NOSPACE;
-
- if (fileref->mfs.stBlk != 1)
- { /* try to extend last file extent */
- /* append free ABs after last AB */
- for (i=lastAB+1; (mfs_get_ABlink(fileref->l2_img, i) == 0) && (allocABs > 0) && (i < numABs); i++)
- {
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + i * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if (get_UINT32BE(tag.fileID) != 0)
- {
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- goto corrupt_free_block2;
- }
- }
- }
- }
-
- mfs_set_ABlink(fileref->l2_img, lastAB, i+2);
- lastAB = i;
- allocABs--;
- free_ABs--;
- }
-corrupt_free_block2:
- /* return if done */
- if (! allocABs)
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- return IMGTOOLERR_SUCCESS; /* done */
- }
- }
-
- while (allocABs)
- {
- /* find smallest data block at least nb_alloc_physrecs in length, and largest data block less than nb_alloc_physrecs in length */
- firstBestExtentABlen = INT_MAX;
- secondBestExtentABlen = 0;
- for (i=0; i<numABs; i++)
- {
- if (mfs_get_ABlink(fileref->l2_img, i) == 0)
- { /* found one free block */
- /* compute its length */
- extentBaseAB = i;
- extentABlen = 0;
- while ((i<numABs) && (mfs_get_ABlink(fileref->l2_img, i) == 0))
- {
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + i * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if (get_UINT32BE(tag.fileID) != 0)
- {
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- goto corrupt_free_block3;
- }
- }
- }
- }
-
- extentABlen++;
- i++;
- }
-corrupt_free_block3:
- /* compare to previous best and second-best blocks */
- if ((extentABlen < firstBestExtentABlen) && (extentABlen >= allocABs))
- {
- firstBestExtentBaseAB = extentBaseAB;
- firstBestExtentABlen = extentABlen;
- if (extentABlen == allocABs)
- /* no need to search further */
- break;
- }
- else if ((extentABlen > secondBestExtentABlen) && (extentABlen < allocABs))
- {
- secondBestExtentBaseAB = extentBaseAB;
- secondBestExtentABlen = extentABlen;
- }
- }
- }
-
- if (firstBestExtentABlen != INT_MAX)
- { /* found one contiguous block which can hold it all */
- extentABlen = allocABs;
- for (i=0; i<allocABs; i++)
- {
- if (fileref->mfs.stBlk != 1)
- mfs_set_ABlink(fileref->l2_img, lastAB, firstBestExtentBaseAB+i+2);
- else
- fileref->mfs.stBlk = firstBestExtentBaseAB+i+2;
- lastAB = firstBestExtentBaseAB+i;
- free_ABs--;
- /* set tag to allocated */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- set_UINT32BE(&tag.fileID, fileref->fileID);
- tag.ftype = 1;
- if ((fileref->forkType) == rsrc_fork)
- tag.ftype |= 2;
- tag.fattr = /*fattr*/ 0; /* ***TODO*** */
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- set_UINT16BE(&tag.fblock, fblock & 0xffff);
- set_UINT32BE(&tag.wrCnt, mac_time_now());
- err = image_write_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + lastAB * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- return err;
- }
- fblock++;
- }
- }
- }
- allocABs = 0;
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- /*return IMGTOOLERR_SUCCESS;*/ /* done */
- }
- else if (secondBestExtentABlen != 0)
- { /* jeez, we need to fragment it. We use the largest smaller block to limit fragmentation. */
- for (i=0; i<secondBestExtentABlen; i++)
- {
- if (fileref->mfs.stBlk != 1)
- mfs_set_ABlink(fileref->l2_img, lastAB, secondBestExtentBaseAB+i+2);
- else
- fileref->mfs.stBlk = secondBestExtentBaseAB+i+2;
- lastAB = secondBestExtentBaseAB+i;
- free_ABs--;
- /* set tag to allocated */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- set_UINT32BE(&tag.fileID, fileref->fileID);
- tag.ftype = 1;
- if ((fileref->forkType) == rsrc_fork)
- tag.ftype |= 2;
- tag.fattr = /*fattr*/ 0; /* ***TODO*** */
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- set_UINT16BE(&tag.fblock, fblock & 0xffff);
- set_UINT32BE(&tag.wrCnt, mac_time_now());
- err = image_write_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + lastAB * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- fileref->l2_img->freeABs = free_ABs;
- return err;
- }
- fblock++;
- }
- }
- }
- allocABs -= secondBestExtentABlen;
- }
- else
- {
- mfs_set_ABlink(fileref->l2_img, lastAB, 1);
- return IMGTOOLERR_NOSPACE; /* This should never happen, as we pre-check that there is enough free space */
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- mfs_file_setABeof
-
- Set physical file EOF in ABs
-
- fileref (I/O): open mac file reference
- newABeof (I): desired number of allocated ABs for this file
-
- Return imgtool error code
-*/
-static imgtoolerr_t mfs_file_setABeof(struct mac_fileref *fileref, UINT32 newABeof)
-{
- UINT16 AB_address = 0;
- UINT16 AB_link;
- int i, j;
- floppy_tag_record tag;
- int MDB_dirty = 0;
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
-
-
- assert(fileref->l2_img->format == L2I_MFS);
-
- /* run through link chain until we reach the old or the new EOF */
- AB_link = fileref->mfs.stBlk;
- if ((AB_link == 0) || (AB_link >= fileref->l2_img->numABs+2))
- /* 0 -> ??? */
- return IMGTOOLERR_CORRUPTIMAGE;
- for (i=0; (i<newABeof) && (AB_link!=1); i++)
- {
- AB_address = AB_link - 2;
- AB_link = mfs_get_ABlink(fileref->l2_img, AB_address);
- if ((AB_link == 0) || (AB_link >= fileref->l2_img->numABs+2))
- /* 0 -> empty block: there is no way an empty block could make it
- into the link chain!!! */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((i * fileref->l2_img->blocksperAB + j) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
- }
- }
-
- if (i == newABeof)
- { /* new EOF is shorter than old one */
- /* mark new eof */
- if (i==0)
- fileref->mfs.stBlk = 1;
- else
- {
- mfs_set_ABlink(fileref->l2_img, AB_address, 1);
- MDB_dirty = 1;
- }
-
- /* free all remaining blocks */
- while (AB_link != 1)
- {
- AB_address = AB_link - 2;
- AB_link = mfs_get_ABlink(fileref->l2_img, AB_address);
- if ((AB_link == 0) || (AB_link >= fileref->l2_img->numABs+2))
- { /* 0 -> empty block: there is no way an empty block could make
- it into the link chain!!! */
- if (MDB_dirty)
- { /* update MDB (freeABs field) and ABLink array */
- err = mfs_update_mdb(fileref->l2_img);
- if (err)
- return err;
- }
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- if (TAG_CHECKS)
- {
- /* optional check */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_read_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
-
- if ((get_UINT32BE(tag.fileID) != fileref->fileID)
- || (((tag.ftype & 2) != 0) != (fileref->forkType == rsrc_fork))
- || (get_UINT16BE(tag.fblock) != ((i * fileref->l2_img->blocksperAB + j) & 0xffff)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- }
- }
- }
-
- mfs_set_ABlink(fileref->l2_img, AB_address, 0);
- fileref->l2_img->freeABs++;
- MDB_dirty = 1;
- /* set tag to free */
- if (image_get_tag_len(&fileref->l2_img->l1_img) == 12)
- {
- memset(&tag, 0, sizeof(tag));
- for (j=0; j<fileref->l2_img->blocksperAB; j++)
- {
- err = image_write_tag(&fileref->l2_img->l1_img, fileref->l2_img->u.mfs.ABStart + AB_address * fileref->l2_img->blocksperAB + j, &tag);
- if (err)
- return err;
- }
- }
- i++;
- }
- }
- else
- { /* new EOF is larger than old one */
- err = mfs_file_allocABs(fileref, AB_address, newABeof - i, i * fileref->l2_img->blocksperAB);
- if (err)
- return err;
- MDB_dirty = 1;
- }
-
- if (MDB_dirty)
- { /* update MDB (freeABs field) and ABLink array */
- err = mfs_update_mdb(fileref->l2_img);
- if (err)
- return err;
- }
-
- fileref->pLen = newABeof * (fileref->l2_img->blocksperAB * 512);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- mfs_hashString
-
- Hash a string: under MFS, this provides the resource ID of the comment
- resource associated with the file whose name is provided (FCMT resource
- type).
-
- Ripped from Apple technote TB06 (converted from 68k ASM to C)
-
- string (I): string to hash
-
- Returns hash value
-*/
-static int mfs_hashString(const mac_str255 string)
-{
- int reply;
- int len;
- int i;
-
- len = string[0];
-
- reply = 0;
- for (i=0; i<len; i++)
- {
- reply ^= string[i+1];
- if (reply & 1)
- reply = ((reply >> 1) & 0x7fff) | ~0x7fff;
- else
- reply = ((reply >> 1) & 0x7fff);
- if (! (reply & 0x8000))
- reply = - reply;
- }
-
- return reply;
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark HFS IMPLEMENTATION
-#endif
-
-/*
- HFS extents B-tree key
-*/
-struct hfs_extentKey
-{
- UINT8 keyLength; /* length of key, excluding this field */
- UINT8 forkType; /* 0 = data fork, FF = resource fork */
- UINT32BE fileID; /* file ID */
- UINT16BE startBlock; /* first file allocation block number in this extent */
-};
-enum
-{
- keyLength_hfs_extentKey = sizeof(hfs_extentKey) - sizeof(UINT8)
-};
-
-/*
- HFS catalog B-tree key
-*/
-struct hfs_catKey
-{
- UINT8 keyLen; /* key length */
- UINT8 resrv1; /* reserved */
- UINT32BE parID; /* parent directory ID */
- mac_str31 cName; /* catalog node name */
- /* note that in index nodes, it is a mac_str31, but
- in leaf keys it's a variable-length string */
-};
-
-/*
- HFS catalog data record for a folder - 70 bytes
-*/
-struct hfs_catFolderData
-{
- UINT16BE recordType; /* record type */
- UINT16BE flags; /* folder flags */
- UINT16BE valence; /* folder valence */
- UINT32BE folderID; /* folder ID */
- UINT32BE createDate; /* date and time of creation */
- UINT32BE modifyDate; /* date and time of last modification */
- UINT32BE backupDate; /* date and time of last backup */
- mac_DInfo userInfo; /* Finder information */
- mac_DXInfo finderInfo; /* additional Finder information */
- UINT32BE reserved[4]; /* reserved - set to zero */
-};
-
-/*
- HFS catalog data record for a file - 102 bytes
-*/
-struct hfs_catFileData
-{
- UINT16BE recordType; /* record type */
- UINT8 flags; /* file flags */
- UINT8 fileType; /* file type (reserved, always 0?) */
- mac_FInfo userInfo; /* Finder information */
- UINT32BE fileID; /* file ID */
- UINT16BE dataStartBlock; /* not used - set to zero */
- UINT32BE dataLogicalSize; /* logical EOF of data fork */
- UINT32BE dataPhysicalSize; /* physical EOF of data fork */
- UINT16BE rsrcStartBlock; /* not used - set to zero */
- UINT32BE rsrcLogicalSize; /* logical EOF of resource fork */
- UINT32BE rsrcPhysicalSize; /* physical EOF of resource fork */
- UINT32BE createDate; /* date and time of creation */
- UINT32BE modifyDate; /* date and time of last modification */
- UINT32BE backupDate; /* date and time of last backup */
- mac_FXInfo finderInfo; /* additional Finder information */
- UINT16BE clumpSize; /* file clump size (not used) */
- hfs_extent_3 dataExtents; /* first data fork extent record */
- hfs_extent_3 rsrcExtents; /* first resource fork extent record */
- UINT32BE reserved; /* reserved - set to zero */
-};
-
-/*
- HFS catalog data record for a thread - 46 bytes
-
- The key for a thread record features the CNID of the item and an empty
- name, instead of the CNID of the parent and the item name.
-*/
-struct hfs_catThreadData
-{
- UINT16BE recordType; /* record type */
- UINT32BE reserved[2]; /* reserved - set to zero */
- UINT32BE parID; /* parent ID for this catalog node */
- mac_str31 nodeName; /* name of this catalog node */
-};
-
-/*
- union for all types at once
-*/
-union hfs_catData
-{
- UINT16BE dataType;
- hfs_catFolderData folder;
- hfs_catFileData file;
- hfs_catThreadData thread;
-};
-
-/*
- HFS catalog record types
-*/
-enum
-{
- hcrt_Folder = 0x0100, /* Folder record */
- hcrt_File = 0x0200, /* File record */
- hcrt_FolderThread = 0x0300, /* Folder thread record */
- hcrt_FileThread = 0x0400 /* File thread record */
-};
-
-/*
- Catalog file record flags
-
- This is similar to the MFS catalog flag field, but the "thread exists" flag
- (0x02) is specific to HFS/HFS+, whereas the "Record in use" flag (0x80) is
- only used by MFS.
-*/
-enum
-{
- cfrf_fileLocked = 0x01, /* file is locked and cannot be written to */
- cfrf_threadExists = 0x02 /* a file thread record exists for this file */
-};
-
-/*
- BT functions used by HFS functions
-*/
-struct BT_leaf_rec_enumerator
-{
- mac_BTref *BTref;
- UINT32 cur_node;
- int cur_rec;
-};
-
-static imgtoolerr_t BT_open(mac_BTref *BTref, int (*key_compare_func)(const void *key1, const void *key2), int is_extent);
-static void BT_close(mac_BTref *BTref);
-static imgtoolerr_t BT_search_leaf_rec(mac_BTref *BTref, const void *search_key,
- UINT32 *node_ID, int *record_ID,
- void **record_ptr, int *record_len,
- int search_exact_match, int *match_found);
-static imgtoolerr_t BT_get_keyed_record_data(mac_BTref *BTref, void *rec_ptr, int rec_len, void **data_ptr, int *data_len);
-static imgtoolerr_t BT_leaf_rec_enumerator_open(mac_BTref *BTref, BT_leaf_rec_enumerator *enumerator);
-static imgtoolerr_t BT_leaf_rec_enumerator_read(BT_leaf_rec_enumerator *enumerator, void **record_ptr, int *rec_len);
-
-struct hfs_cat_enumerator
-{
- struct mac_l2_imgref *l2_img;
- BT_leaf_rec_enumerator BT_enumerator;
- UINT32 parID;
-};
-
-/*
- hfs_open_extents_file
-
- Open the file extents B-tree file
-
- l2_img (I/O): level-2 image reference
- mdb (I): copy of the MDB block
- fileref (O): mac open file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_open_extents_file(struct mac_l2_imgref *l2_img, const struct hfs_mdb *mdb, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_HFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = 3;
- fileref->forkType = (mac_forkID)0x00;
-
- fileref->eof = fileref->pLen = get_UINT32BE(mdb->xtFlSize);
- memcpy(fileref->hfs.extents, mdb->xtExtRec, sizeof(hfs_extent_3));
-
- fileref->crPs = 0;
-
- fileref->reload_buf = TRUE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_open_cat_file
-
- Open the disk catalog B-tree file
-
- l2_img (I/O): level-2 image reference
- mdb (I): copy of the MDB block
- fileref (O): mac open file reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_open_cat_file(struct mac_l2_imgref *l2_img, const struct hfs_mdb *mdb, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_HFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = 4;
- fileref->forkType = (mac_forkID)0x00;
-
- fileref->eof = fileref->pLen = get_UINT32BE(mdb->ctFlSize);
- memcpy(fileref->hfs.extents, mdb->ctExtRec, sizeof(hfs_extent_3));
-
- fileref->crPs = 0;
-
- fileref->reload_buf = TRUE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_extentKey_compare
-
- key compare function for file extents B-tree
-
- p1 (I): pointer to first key
- p2 (I): pointer to second key
-
- Return a zero the two keys are equal, a negative value if the key pointed
- to by p1 is less than the key pointed to by p2, and a positive value if the
- key pointed to by p1 is greater than the key pointed to by p2.
-*/
-static int hfs_extentKey_compare(const void *p1, const void *p2)
-{
- const hfs_extentKey *key1 = (const hfs_extentKey*)p1;
- const hfs_extentKey *key2 = (const hfs_extentKey*)p2;
-
- /* let's keep it simple for now */
- return memcmp(key1, key2, sizeof(hfs_extentKey));
-}
-
-/*
- hfs_catKey_compare
-
- key compare function for disk catalog B-tree
-
- p1 (I): pointer to first key
- p2 (I): pointer to second key
-
- Return a zero the two keys are equal, a negative value if the key pointed
- to by p1 is less than the key pointed to by p2, and a positive value if the
- key pointed to by p1 is greater than the key pointed to by p2.
-*/
-static int hfs_catKey_compare(const void *p1, const void *p2)
-{
- const hfs_catKey *key1 = (const hfs_catKey *)p1;
- const hfs_catKey *key2 = (const hfs_catKey *)p2;
-
- if (get_UINT32BE(key1->parID) != get_UINT32BE(key2->parID))
- return (get_UINT32BE(key1->parID) < get_UINT32BE(key2->parID)) ? -1 : +1;
-
- return mac_stricmp(key1->cName, key2->cName);
-}
-
-/*
- hfs_image_open
-
- Open a HFS image. Image must already be open on level 1.
-
- l2_img (I/O): level-2 image reference to open (l1_img and format fields
- must be initialized)
- img_open_buf (I): buffer with the MDB block
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_image_open(imgtool_image *image, imgtool_stream *stream)
-{
- imgtoolerr_t err;
- struct mac_l2_imgref *l2_img;
- img_open_buf buf_local;
- img_open_buf *buf;
-
- l2_img = get_imgref(image);
- l2_img->l1_img.image = image;
- l2_img->l1_img.heads = 2;
- l2_img->format = L2I_HFS;
-
- /* read MDB */
- err = image_read_block(&l2_img->l1_img, 2, &buf_local.raw);
- if (err)
- return err;
- buf = &buf_local;
-
- /* check signature word */
- if ((buf->hfs_mdb.sigWord[0] != 0x42) || (buf->hfs_mdb.sigWord[1] != 0x44)
- || (buf->hfs_mdb.VN[0] > 27))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- l2_img->u.hfs.VBM_start = get_UINT16BE(buf->hfs_mdb.VBMSt);
-
- l2_img->numABs = get_UINT16BE(buf->hfs_mdb.nmAlBlks);
- if (get_UINT32BE(buf->hfs_mdb.alBlkSiz) % 512)
- return IMGTOOLERR_CORRUPTIMAGE;
- l2_img->blocksperAB = get_UINT32BE(buf->hfs_mdb.alBlkSiz) / 512;
- l2_img->u.hfs.ABStart = get_UINT16BE(buf->hfs_mdb.alBlSt);
-
- l2_img->nxtCNID = get_UINT32BE(buf->hfs_mdb.nxtCNID);
-
- l2_img->freeABs = get_UINT16BE(buf->hfs_mdb.freeABs);
-
- mac_strcpy(l2_img->u.hfs.volname, buf->hfs_mdb.VN);
-
- /* open extents and catalog BT */
- err = hfs_open_extents_file(l2_img, &buf->hfs_mdb, &l2_img->u.hfs.extents_BT.fileref);
- if (err)
- return err;
- err = BT_open(&l2_img->u.hfs.extents_BT, hfs_extentKey_compare, TRUE);
- if (err)
- return err;
- if ((l2_img->u.hfs.extents_BT.attributes & btha_bigKeysMask)
- /*|| (l2_img->u.hfs.extents_BT.attributes & kBTVariableIndexKeysMask)*/
- || (l2_img->u.hfs.extents_BT.maxKeyLength != 7))
- { /* This is not supported by the HFS format */
- /* Variable Index keys are not supported either, but hopefully it will
- not break this imgtool module if it set (though it would probably break
- a real macintosh) */
- BT_close(&l2_img->u.hfs.extents_BT);
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- err = hfs_open_cat_file(l2_img, &buf->hfs_mdb, &l2_img->u.hfs.cat_BT.fileref);
- if (err)
- {
- BT_close(&l2_img->u.hfs.extents_BT);
- return err;
- }
- err = BT_open(&l2_img->u.hfs.cat_BT, hfs_catKey_compare, FALSE);
- if (err)
- {
- return err;
- }
- if ((l2_img->u.hfs.cat_BT.attributes & btha_bigKeysMask)
- /*|| (l2_img->u.hfs.cat_BT.attributes & kBTVariableIndexKeysMask)*/
- || (l2_img->u.hfs.cat_BT.maxKeyLength != 37))
- { /* This is not supported by the HFS format */
- /* Variable Index keys are not supported either, but hopefully it will
- not break this imgtool module if it set (though it would probably break
- a real macintosh) */
- BT_close(&l2_img->u.hfs.extents_BT);
- BT_close(&l2_img->u.hfs.cat_BT);
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- /* extract volume bitmap */
- {
- int byte_len = (l2_img->numABs + 7) / 8;
- int cur_byte = 0;
- int cur_block = l2_img->u.hfs.VBM_start;
-
- while (cur_byte < byte_len)
- {
- /* read next block */
- err = image_read_block(&l2_img->l1_img, cur_block, buf->raw);
- if (err)
- return err;
- cur_block++;
-
- /* append this block to VBM */
- memcpy(l2_img->u.hfs.VBM+cur_byte, buf->raw, 512);
- cur_byte += 512;
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- hfs_image_close
-
- Close a HFS image.
-
- l2_img (I/O): level-2 image reference
-*/
-static void hfs_image_close(struct mac_l2_imgref *l2_img)
-{
- assert(l2_img->format == L2I_HFS);
-
- BT_close(&l2_img->u.hfs.extents_BT);
- BT_close(&l2_img->u.hfs.cat_BT);
-}
-#endif
-
-/*
- hfs_get_cat_record_data
-
- extract data from a catalog B-tree leaf record
-
- l2_img (I/O): level-2 image reference
- rec_raw (I): pointer to record key and data, as returned by
- BT_node_get_keyed_record
- rec_len (I): total length of record, as returned by
- BT_node_get_keyed_record
- rec_key (O): set to point to record key
- rec_data (O): set to point to record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_get_cat_record_data(struct mac_l2_imgref *l2_img, void *rec_raw, int rec_len, hfs_catKey **rec_key, hfs_catData **rec_data)
-{
- hfs_catKey *lrec_key;
- void *rec_data_raw;
- hfs_catData *lrec_data;
- int rec_data_len;
- int min_data_size;
- imgtoolerr_t err;
-
-
- assert(l2_img->format == L2I_HFS);
-
- lrec_key = (hfs_catKey*)rec_raw;
- /* check that key is long enough to hold it all */
- if ((lrec_key->keyLen+1) < (offsetof(hfs_catKey, cName) + lrec_key->cName[0] + 1))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* get pointer to record data */
- err = BT_get_keyed_record_data(&l2_img->u.hfs.cat_BT, rec_raw, rec_len, &rec_data_raw, &rec_data_len);
- if (err)
- return err;
- lrec_data = (hfs_catData*)rec_data_raw;
-
- /* extract record type */
- if (rec_data_len < 2)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* check that the record is large enough for its type */
- switch (get_UINT16BE(lrec_data->dataType))
- {
- case hcrt_Folder:
- min_data_size = sizeof(hfs_catFolderData);
- break;
-
- case hcrt_File:
- min_data_size = sizeof(hfs_catFileData);
- break;
-
- case hcrt_FolderThread:
- case hcrt_FileThread:
- min_data_size = sizeof(hfs_catThreadData);
- break;
-
- default:
- /* records of unknown type can be safely ignored */
- min_data_size = 0;
- break;
- }
-
- if (rec_data_len < min_data_size)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (rec_key)
- *rec_key = lrec_key;
- if (rec_data)
- *rec_data = lrec_data;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_cat_open
-
- Open an enumerator on the disk catalog
-
- l2_img (I/O): level-2 image reference
- enumerator (O): open catalog enumerator reference
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_cat_open(struct mac_l2_imgref *l2_img, const char *path, hfs_cat_enumerator *enumerator)
-{
- imgtoolerr_t err;
- UINT32 parID;
- mac_str255 filename;
- mac_dirent cat_info;
-
- assert(l2_img->format == L2I_HFS);
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(l2_img, path, &parID, filename, &cat_info, FALSE);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_Folder)
- return IMGTOOLERR_FILENOTFOUND;
-
- enumerator->l2_img = l2_img;
- enumerator->parID = parID;
-
- return BT_leaf_rec_enumerator_open(&l2_img->u.hfs.cat_BT, &enumerator->BT_enumerator);
-}
-
-/*
- hfs_cat_read
-
- Enumerate the disk catalog
-
- enumerator (I/O): open catalog enumerator reference
- rec_key (O): set to point to record key
- rec_data (O): set to point to record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_cat_read(hfs_cat_enumerator *enumerator, hfs_catKey **rec_key, hfs_catData **rec_data)
-{
- void *rec;
- int rec_len = 0;
- imgtoolerr_t err;
-
-
- *rec_key = NULL;
- *rec_data = NULL;
-
- /* read next record */
- err = BT_leaf_rec_enumerator_read(&enumerator->BT_enumerator, &rec, &rec_len);
- if (err)
- return err;
-
- /* check EOList condition */
- if (rec == NULL)
- return IMGTOOLERR_SUCCESS;
-
- /* extract record data */
- err = hfs_get_cat_record_data(enumerator->l2_img, rec, rec_len, rec_key, rec_data);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_cat_search
-
- Search the catalog for a given file
-
- l2_img (I/O): level-2 image reference
- parID (I): CNID of file parent directory
- cName (I): file name
- rec_key (O): set to point to record key
- rec_data (O): set to point to record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_cat_search(struct mac_l2_imgref *l2_img, UINT32 parID, const mac_str31 cName, hfs_catKey **rec_key, hfs_catData **rec_data)
-{
- hfs_catKey search_key;
- void *rec;
- int rec_len;
- imgtoolerr_t err;
-
- assert(l2_img->format == L2I_HFS);
-
- if (cName[0] > 31)
- return IMGTOOLERR_UNEXPECTED;
-
- /* generate search key */
- search_key.keyLen = search_key.resrv1 = 0; /* these fields do not matter
- to the compare function, so we
- don't fill them */
- set_UINT32BE(&search_key.parID, parID);
- mac_strcpy(search_key.cName, cName);
-
- /* search key */
- err = BT_search_leaf_rec(&l2_img->u.hfs.cat_BT, &search_key, NULL, NULL, &rec, &rec_len, TRUE, NULL);
- if (err)
- return err;
-
- /* extract record data */
- err = hfs_get_cat_record_data(l2_img, rec, rec_len, rec_key, rec_data);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_lookup_path
-
- Resolve a file path
-
- l2_img (I/O): level-2 image reference
- fpath (I): file path (C string)
- parID (O): set to the CNID of the file parent directory
- filename (O): set to the actual name of the file, with capitalization matching
- the one on the volume rather than the one in the fpath parameter (Mac
- string)
- cat_info (O): catalog info for this file extracted from the catalog file
- (may be NULL)
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_lookup_path(struct mac_l2_imgref *l2_img, const char *fpath, UINT32 *parID, mac_str255 filename, mac_dirent *cat_info)
-{
- const char *element_start;
- int element_len;
- mac_str255 mac_element_name;
- //int level;
- imgtoolerr_t err;
- hfs_catKey *catrec_key = NULL;
- hfs_catData *catrec_data = NULL;
- UINT16 dataRecType = hcrt_Folder;
-
- /* iterate each path element */
- element_start = fpath;
- //level = 0;
- *parID = 2; /* root parID is 2 */
-
- while(*element_start)
- {
- /* find next path element */
- element_len = strlen(element_start);
- /* decode path element name */
- c_to_mac_strncpy(mac_element_name, element_start, element_len);
-
- err = hfs_cat_search(l2_img, *parID, mac_element_name, &catrec_key, &catrec_data);
- if (err)
- return err;
-
- dataRecType = get_UINT16BE(catrec_data->dataType);
-
- /* regular folder/file name */
- if (dataRecType == hcrt_Folder)
- *parID = get_UINT32BE(catrec_data->folder.folderID);
- else if (element_start[element_len + 1])
- return IMGTOOLERR_BADFILENAME;
-
- /* iterate */
- element_start += element_len + 1;
- }
-
- if (catrec_key && (dataRecType == hcrt_File))
- {
- /* save ref */
- *parID = get_UINT32BE(catrec_key->parID);
- mac_strcpy(filename, catrec_key->cName);
- }
-
- if (cat_info)
- {
- if (catrec_data && (dataRecType == hcrt_File))
- {
- cat_info->flFinderInfo = catrec_data->file.userInfo;
- cat_info->flXFinderInfo = catrec_data->file.finderInfo;
- cat_info->flags = catrec_data->file.flags;
- cat_info->fileID = get_UINT32BE(catrec_data->file.fileID);
- cat_info->dataLogicalSize = get_UINT32BE(catrec_data->file.dataLogicalSize);
- cat_info->dataPhysicalSize = get_UINT32BE(catrec_data->file.dataPhysicalSize);
- cat_info->rsrcLogicalSize = get_UINT32BE(catrec_data->file.rsrcLogicalSize);
- cat_info->rsrcPhysicalSize = get_UINT32BE(catrec_data->file.rsrcPhysicalSize);
- cat_info->createDate = get_UINT32BE(catrec_data->file.createDate);
- cat_info->modifyDate = get_UINT32BE(catrec_data->file.modifyDate);
- }
- else
- {
- memset(cat_info, 0, sizeof(*cat_info));
- }
- cat_info->dataRecType = dataRecType;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_file_open_internal
-
- Open a file fork, given its catalog entry. This function should not be
- called directly: call hfs_file_open instead.
-
- l2_img (I/O): level-2 image reference
- file_rec (I): catalog entry for the file to open
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_file_open_internal(struct mac_l2_imgref *l2_img, const hfs_catFileData *file_rec, mac_forkID fork, struct mac_fileref *fileref)
-{
- assert(l2_img->format == L2I_HFS);
-
- fileref->l2_img = l2_img;
-
- fileref->fileID = get_UINT32BE(file_rec->fileID);
- fileref->forkType = fork;
-
- switch (fork)
- {
- case data_fork:
- fileref->eof = get_UINT32BE(file_rec->dataLogicalSize);
- fileref->pLen = get_UINT32BE(file_rec->dataPhysicalSize);
- memcpy(fileref->hfs.extents, file_rec->dataExtents, sizeof(hfs_extent_3));
- break;
-
- case rsrc_fork:
- fileref->eof = get_UINT32BE(file_rec->rsrcLogicalSize);
- fileref->pLen = get_UINT32BE(file_rec->rsrcPhysicalSize);
- memcpy(fileref->hfs.extents, file_rec->rsrcExtents, sizeof(hfs_extent_3));
- break;
- }
-
- fileref->crPs = 0;
-
- fileref->reload_buf = TRUE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- hfs_file_open
-
- Open a file located on a HFS volume. This function should not be called
- directly: call mac_file_open instead.
-
- l2_img (I/O): level-2 image reference
- parID (I): CNID of file parent directory
- filename (I): name of the file (Mac string)
- mac_forkID (I): tells which fork should be opened
- fileref (O): mac file reference to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_file_open(struct mac_l2_imgref *l2_img, UINT32 parID, const mac_str255 filename, mac_forkID fork, struct mac_fileref *fileref)
-{
- hfs_catKey *catrec_key;
- hfs_catData *catrec_data;
- UINT16 dataRecType;
- imgtoolerr_t err;
-
- /* lookup file in catalog */
- err = hfs_cat_search(l2_img, parID, filename, &catrec_key, &catrec_data);
- if (err)
- return err;
-
- dataRecType = get_UINT16BE(catrec_data->dataType);
-
- /* file expected */
- if (dataRecType != hcrt_File)
- return IMGTOOLERR_BADFILENAME;
-
- fileref->hfs.parID = get_UINT32BE(catrec_key->parID);
- mac_strcpy(fileref->hfs.filename, catrec_key->cName);
-
- /* open it */
- return hfs_file_open_internal(l2_img, &catrec_data->file, fork, fileref);
-}
-
-/*
- hfs_file_get_nth_block_address
-
- Get the disk block address of a given block in an open file on a MFS image.
- Called by macintosh file code.
-
- fileref (I/O): open mac file reference
- block_num (I): file block index
- block_address (O): disk block address for the file block
-
- Return imgtool error code
-*/
-static imgtoolerr_t hfs_file_get_nth_block_address(struct mac_fileref *fileref, UINT32 block_num, UINT32 *block_address)
-{
- UINT32 AB_num;
- UINT32 cur_AB;
- UINT32 i;
- void *cur_extents_raw;
- hfs_extent *cur_extents;
- int cur_extents_len;
- void *extents_BT_rec;
- int extents_BT_rec_len;
- imgtoolerr_t err;
- UINT16 AB_address;
-
- assert(fileref->l2_img->format == L2I_HFS);
-
- AB_num = block_num / fileref->l2_img->blocksperAB;
- cur_AB = 0;
- cur_extents = fileref->hfs.extents;
-
- /* first look in catalog tree extents */
- for (i=0; i<3; i++)
- {
- if (AB_num < cur_AB+get_UINT16BE(cur_extents[i].numABlks))
- break;
- cur_AB += get_UINT16BE(cur_extents[i].numABlks);
- }
- if (i == 3)
- {
- /* extent not found: read extents record from extents BT */
- hfs_extentKey search_key;
- hfs_extentKey *found_key;
-
- search_key.keyLength = keyLength_hfs_extentKey;
- search_key.forkType = fileref->forkType;
- set_UINT32BE(&search_key.fileID, fileref->fileID);
- set_UINT16BE(&search_key.startBlock, AB_num);
-
- /* search for the record with the largest key lower than or equal to
- search_key. The keys are constructed in such a way that, if a record
- includes AB_num, it is that one. */
- err = BT_search_leaf_rec(&fileref->l2_img->u.hfs.extents_BT, &search_key,
- NULL, NULL, &extents_BT_rec, &extents_BT_rec_len,
- FALSE, NULL);
- if (err)
- return err;
-
- if (extents_BT_rec == NULL)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- found_key = (hfs_extentKey*)extents_BT_rec;
- /* check that this record concerns the correct file */
- if ((found_key->forkType != fileref->forkType)
- || (get_UINT32BE(found_key->fileID) != fileref->fileID))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* extract start AB */
- cur_AB = get_UINT16BE(found_key->startBlock);
- /* get extents pointer */
- err = BT_get_keyed_record_data(&fileref->l2_img->u.hfs.extents_BT, extents_BT_rec, extents_BT_rec_len, &cur_extents_raw, &cur_extents_len);
- if (err)
- return err;
- if (cur_extents_len < 3*sizeof(hfs_extent))
- return IMGTOOLERR_CORRUPTIMAGE;
- cur_extents = (hfs_extent*)cur_extents_raw;
-
- /* pick correct extent in record */
- for (i=0; i<3; i++)
- {
- if (AB_num < cur_AB+get_UINT16BE(cur_extents[i].numABlks))
- break;
- cur_AB += get_UINT16BE(cur_extents[i].numABlks);
- }
- if (i == 3)
- /* extent not found */
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- AB_address = get_UINT16BE(cur_extents[i].stABN) + (AB_num-cur_AB);
-
- if (AB_address >= fileref->l2_img->numABs)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- *block_address = fileref->l2_img->u.hfs.ABStart + AB_address * fileref->l2_img->blocksperAB
- + block_num % fileref->l2_img->blocksperAB;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#if 0
-#pragma mark -
-#pragma mark B-TREE IMPLEMENTATION
-#endif
-
-/*
- B-tree (Balanced search tree) files are used by the HFS and HFS+ file
- systems: the Extents and Catalog files are both B-Tree.
-
- Note that these B-trees are B+-trees: data is only on the leaf level, and
- nodes located on the same level are also linked sequentially, which allows
- fast sequenctial access to the catalog file.
-
- These files are normal files, except for the fact that they are not
- referenced from the catalog but the MDB. They are allocated in fixed-size
- records of 512 bytes (HFS). (HFS+ supports any power of two from 512
- through 32768, and uses a default of 1024 for Extents, and 4096 for both
- Catalog and Attributes.)
-
- Nodes can contain any number of records. The nodes can be of any of four
- types: header node (unique node with b-tree information, pointer to root
- node and start of the node allocation bitmap), map nodes (which are created
- when the node allocation bitmap outgrows the header node), index nodes
- (root and branch node that enable to efficiently search the leaf nodes for
- a specific key value), and leaf nodes (which hold the actual user data
- records with keys and data). The first node is always a header node.
- Other nodes can be of any of the 3 other type, or they can be free.
-*/
-
-/*
- BTNodeHeader
-
- Header of a node record
-*/
-struct BTNodeHeader
-{
- UINT32BE fLink; /* (index of) next node at this level */
- UINT32BE bLink; /* (index of) previous node at this level */
- UINT8 kind; /* kind of node (leaf, index, header, map) */
- UINT8 height; /* zero for header, map; 1 for leaf, 2 through
- treeDepth for index (child is one LESS than
- parent, whatever IM says) */
- UINT16BE numRecords; /* number of records in this node */
- UINT16BE reserved; /* reserved; set to zero */
-};
-
-/*
- Constants for BTNodeHeader kind field
-*/
-enum
-{
- btnk_leafNode = 0xff, /* leaf nodes hold the actual user data records
- with keys and data */
- btnk_indexNode = 0, /* root and branch node that enable to efficiently
- search the leaf nodes for a specific key value */
- btnk_headerNode = 1, /* unique node with b-tree information, pointer to
- root node and start of the node allocation
- bitmap */
- btnk_mapNode = 2 /* map nodes are created when the node allocation
- bitmap outgrows the header node */
-};
-
-/*
- BTHeaderRecord: first record of a B-tree header node (second record is
- unused, and third is node allocation bitmap).
-*/
-struct BTHeaderRecord
-{
- UINT16BE treeDepth; /* maximum height (usually leaf nodes) */
- UINT32BE rootNode; /* node number of root node */
- UINT32BE leafRecords; /* number of leaf records in all leaf nodes */
- UINT32BE firstLeafNode; /* node number of first leaf node */
- UINT32BE lastLeafNode; /* node number of last leaf node */
- UINT16BE nodeSize; /* size of a node, in bytes */
- UINT16BE maxKeyLength; /* maximum length of data (index + leaf) record keys;
- length of all index record keys if
- btha_variableIndexKeysMask attribute flag is not set */
- UINT32BE totalNodes; /* total number of nodes in tree */
- UINT32BE freeNodes; /* number of unused (free) nodes in tree */
-
- UINT16BE reserved1; /* unused */
- UINT32BE clumpSize; /* used in some HFS implementations? (reserved in
- early HFS implementations, and in HFS Plus) */
- UINT8 btreeType; /* reserved - set to 0 */
- UINT8 reserved2; /* reserved */
- UINT32BE attributes; /* persistent attributes about the tree */
- UINT32BE reserved3[16]; /* reserved */
-};
-
-static imgtoolerr_t BT_check(mac_BTref *BTref, int is_extent);
-
-/*
- BT_open
-
- Open a file as a B-tree. The file must be already open as a macintosh
- file.
-
- BTref (I/O): B-tree file handle to open (BTref->fileref must have been
- open previously)
- key_compare_func (I): function that compares two keys
- is_extent (I): TRUE if we are opening the extent B-tree (we want to do
- extra checks in this case because the extent B-Tree may include extent
- records for the extent B-tree itself, and if an extent record for the
- extent B-tree is located in an extent that has not been defined by
- previous extent records, then we can never retreive this extent record)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_open(mac_BTref *BTref, int (*key_compare_func)(const void *key1, const void *key2), int is_extent)
-{
- imgtoolerr_t err;
- BTNodeHeader node_header;
- BTHeaderRecord header_rec;
-
- /* seek to node 0 */
- err = mac_file_seek(&BTref->fileref, 0);
- if (err)
- return err;
-
- /* read node header */
- err = mac_file_read(&BTref->fileref, sizeof(node_header), &node_header);
- if (err)
- return err;
-
- if ((node_header.kind != btnk_headerNode) || (get_UINT16BE(node_header.numRecords) < 3)
- || (node_header.height != 0))
- return IMGTOOLERR_CORRUPTIMAGE; /* right??? */
-
- /* CHEESY HACK: we assume that the header record immediately follows the
- node header. This is because we need to know the node length to know where
- the record pointers are located, but we need to read the header record to
- know the node length. */
- err = mac_file_read(&BTref->fileref, sizeof(header_rec), &header_rec);
- if (err)
- return err;
-
- BTref->nodeSize = get_UINT16BE(header_rec.nodeSize);
- BTref->rootNode = get_UINT32BE(header_rec.rootNode);
- BTref->firstLeafNode = get_UINT32BE(header_rec.firstLeafNode);
- BTref->attributes = get_UINT32BE(header_rec.attributes);
- BTref->treeDepth = get_UINT16BE(header_rec.treeDepth);
- BTref->maxKeyLength = get_UINT16BE(header_rec.maxKeyLength);
-
- BTref->key_compare_func = key_compare_func;
-
- BTref->node_buf = malloc(BTref->nodeSize);
- if (!BTref->node_buf)
- return IMGTOOLERR_OUTOFMEMORY;
-
- if (BTREE_CHECKS)
- {
- /* optional: check integrity of B-tree */
- err = BT_check(BTref, is_extent);
- if (err)
- return err;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_close
-
- Close a B-tree
-
- BTref (I/O): open B-tree file handle
-*/
-static void BT_close(mac_BTref *BTref)
-{
- free(BTref->node_buf);
-}
-
-/*
- BT_read_node
-
- Read a node from a B-tree
-
- BTref (I/O): open B-tree file handle
- node_ID (I): index of the node to read
- expected_kind (I): kind of the node to read
- expected_depth (I): depth of the node to read
- dest (O): destination buffer
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_read_node(mac_BTref *BTref, UINT32 node_ID, int expected_kind, int expected_depth, void *dest)
-{
- imgtoolerr_t err;
-
- /* seek to node */
- err = mac_file_seek(&BTref->fileref, node_ID*BTref->nodeSize);
- if (err)
- return err;
-
- /* read it */
- err = mac_file_read(&BTref->fileref, BTref->nodeSize, dest);
- if (err)
- return err;
-
- /* check node kind and depth */
- if ((((BTNodeHeader *) dest)->kind != expected_kind)
- || (((BTNodeHeader *) dest)->height != expected_depth))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_node_get_record
-
- Extract a raw record from a B-tree node
-
- BTref (I/O): open B-tree file handle
- node_buf (I): buffer with the node the record should be extracted from
- recnum (I): index of record to read
- rec_ptr (O): set to point to start of record (key + data)
- rec_len (O): set to total length of record (key + data)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_node_get_record(mac_BTref *BTref, void *node_buf, unsigned recnum, void **rec_ptr, int *rec_len)
-{
- UINT16 node_numRecords = get_UINT16BE(((BTNodeHeader *) node_buf)->numRecords);
- UINT16 offset;
- UINT16 next_offset;
-
- if (recnum >= node_numRecords)
- return IMGTOOLERR_UNEXPECTED;
-
- offset = get_UINT16BE(((UINT16BE *)((UINT8 *) node_buf + BTref->nodeSize))[-recnum-1]);
- next_offset = get_UINT16BE(((UINT16BE *)((UINT8 *) node_buf + BTref->nodeSize))[-recnum-2]);
-
- if ((offset < sizeof(BTNodeHeader)) || (offset > BTref->nodeSize-2*node_numRecords)
- || (next_offset < sizeof(BTNodeHeader)) || (next_offset > BTref->nodeSize-2*node_numRecords)
- || (offset & 1) || (next_offset & 1)
- || (offset > next_offset))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- *rec_ptr = (UINT8 *)node_buf + offset;
- *rec_len = next_offset - offset;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_node_get_keyed_record
-
- Extract a keyed record from a B-tree node. Equivalent to
- BT_node_get_record, only we do extra checks.
-
- BTref (I/O): open B-tree file handle
- node_buf (I): buffer with the node the record should be extracted from
- node_is_index (I): TRUE if node is index node
- recnum (I): index of record to read
- rec_ptr (O): set to point to start of record (key + data)
- rec_len (O): set to total length of record (key + data)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_node_get_keyed_record(mac_BTref *BTref, void *node_buf, int node_is_index, unsigned recnum, void **rec_ptr, int *rec_len)
-{
- imgtoolerr_t err;
- void *lrec_ptr;
- int lrec_len;
- int key_len;
-
- /* extract record */
- err = BT_node_get_record(BTref, node_buf, recnum, &lrec_ptr, &lrec_len);
- if (err)
- return err;
-
- /* read key len */
- key_len = (BTref->attributes & btha_bigKeysMask)
- ? get_UINT16BE(* (UINT16BE *)lrec_ptr)
- : (* (UINT8 *)lrec_ptr);
-
- /* check that key fits in record */
- if ((key_len + ((BTref->attributes & btha_bigKeysMask) ? 2 : 1)) > lrec_len)
- /* hurk! */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (key_len > BTref->maxKeyLength)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (node_is_index && (! (BTref->attributes & btha_variableIndexKeysMask)) && (key_len != BTref->maxKeyLength))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (rec_ptr)
- *rec_ptr = lrec_ptr;
- if (rec_len)
- *rec_len = lrec_len;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_get_keyed_record_data
-
- extract data from a keyed record
-
- BTref (I/O): open B-tree file handle
- rec_ptr (I): point to start of record (key + data)
- rec_len (I): total length of record (key + data)
- data_ptr (O): set to point to record data
- data_len (O): set to length of record data
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_get_keyed_record_data(mac_BTref *BTref, void *rec_ptr, int rec_len, void **data_ptr, int *data_len)
-{
- int lkey_len;
- int data_offset;
-
- /* read key len */
- lkey_len = (BTref->attributes & btha_bigKeysMask)
- ? get_UINT16BE(* (UINT16BE *)rec_ptr)
- : (* (UINT8 *)rec_ptr);
-
- /* compute offset to data record */
- data_offset = lkey_len + ((BTref->attributes & btha_bigKeysMask) ? 2 : 1);
- if (data_offset > rec_len)
- /* hurk! */
- return IMGTOOLERR_CORRUPTIMAGE;
- /* fix alignment */
- if (data_offset & 1)
- data_offset++;
-
- if (data_ptr)
- *data_ptr = (UINT8 *)rec_ptr + data_offset;
- if (data_len)
- *data_len = (rec_len > data_offset) ? rec_len-data_offset : 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_check
-
- Check integrity of a complete B-tree
-
- BTref (I/O): open B-tree file handle
- is_extent (I): TRUE if we are opening the extent B-tree (we want to do
- extra checks in this case because the extent B-Tree may include extent
- records for the extent B-tree itself, and if an extent record for the
- extent B-tree is located in an extent that has not been defined by
- previous extent records, then we can never retreive this extent record)
-
- Return imgtool error code
-*/
-struct data_nodes_t
-{
- void *buf;
- UINT32 node_num;
- UINT32 cur_rec;
- UINT32 num_recs;
-};
-static imgtoolerr_t BT_check(mac_BTref *BTref, int is_extent)
-{
- UINT16 node_numRecords;
- BTHeaderRecord *header_rec;
- UINT8 *bitmap;
-
- data_nodes_t *data_nodes;
- int i, j;
- UINT32 cur_node, prev_node;
- void *rec1, *rec2;
- int rec1_len, rec2_len;
- void *rec1_data;
- int rec1_data_len;
- UINT32 totalNodes, lastLeafNode;
- UINT32 freeNodes;
- int compare_result;
- UINT32 map_count, map_len;
- UINT32 run_len;
- UINT32 run_bit_len;
- UINT32 actualFreeNodes;
- imgtoolerr_t err;
- UINT32 maxExtentAB = 0, maxExtentNode = 0, extentEOL = 0; /* if is_extent is TRUE */
-
- if (is_extent)
- {
- switch (BTref->fileref.l2_img->format)
- {
- case L2I_MFS:
- /* MFS does not feature any extents B-tree! */
- return IMGTOOLERR_UNEXPECTED;
-
- case L2I_HFS:
- maxExtentAB = 0;
- for (j=0; j<3; j++)
- maxExtentAB += get_UINT16BE(BTref->fileref.hfs.extents[j].numABlks);
- maxExtentNode = (UINT64)maxExtentAB * 512 * BTref->fileref.l2_img->blocksperAB
- / BTref->nodeSize;
- extentEOL = FALSE;
- break;
- }
- }
-
- /* read header node */
- if ((! is_extent) || (0 < maxExtentNode))
- err = BT_read_node(BTref, 0, btnk_headerNode, 0, BTref->node_buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- return err;
-
- /* check we have enough records */
- node_numRecords = get_UINT16BE(((BTNodeHeader *) BTref->node_buf)->numRecords);
- if (node_numRecords < 3)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* get header record */
- err = BT_node_get_record(BTref, BTref->node_buf, 0, &rec1, &rec1_len);
- if (err)
- return err;
- header_rec = (BTHeaderRecord *)rec1;
-
- /* check length of header record */
- if (rec1_len < sizeof(BTHeaderRecord))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- totalNodes = get_UINT32BE(header_rec->totalNodes);
- if (totalNodes == 0)
- /* we need at least one header node */
- return IMGTOOLERR_CORRUPTIMAGE;
- lastLeafNode = get_UINT32BE(header_rec->lastLeafNode);
- freeNodes = get_UINT32BE(header_rec->freeNodes);
-
- /* check file length */
- if ((BTref->nodeSize * totalNodes) > BTref->fileref.pLen)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* initialize for the function postlog ("bail:" tag) */
- err = IMGTOOLERR_SUCCESS;
- bitmap = NULL;
- data_nodes = NULL;
-
- /* alloc buffer for reconstructed bitmap */
- map_len = (totalNodes + 7) / 8;
- bitmap = (UINT8*)malloc(map_len);
- if (! bitmap)
- return IMGTOOLERR_OUTOFMEMORY;
- memset(bitmap, 0, map_len);
-
- /* check B-tree data nodes (i.e. index and leaf nodes) */
- if (BTref->treeDepth == 0)
- {
- /* B-tree is empty */
- if (BTref->rootNode || BTref->firstLeafNode || lastLeafNode)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto bail;
- }
- }
- else
- {
- /* alloc array of buffers for catalog data nodes */
- data_nodes = (data_nodes_t *)malloc(sizeof(data_nodes_t) * BTref->treeDepth);
- if (! data_nodes)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto bail;
- }
- for (i=0; i<BTref->treeDepth; i++)
- data_nodes[i].buf = NULL; /* required for function postlog to work should next loop fail */
- for (i=0; i<BTref->treeDepth; i++)
- {
- data_nodes[i].buf = malloc(BTref->nodeSize);
- if (!data_nodes[i].buf)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto bail;
- }
- }
-
- /* read first data nodes */
- cur_node = BTref->rootNode;
- for (i=BTref->treeDepth-1; i>=0; i--)
- {
- /* check node index */
- if (cur_node >= totalNodes)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* check that node has not been used for another purpose */
- /* this check is unecessary because the current consistency checks
- that forward and back linking match and that node height is correct
- are enough to detect such errors */
-#if 0
- if (bitmap[cur_node >> 3] & (0x80 >> (cur_node & 7)))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-#endif
- /* add node in bitmap */
- bitmap[cur_node >> 3] |= (0x80 >> (cur_node & 7));
- /* read node */
- if ((! is_extent) || (cur_node < maxExtentNode))
- err = BT_read_node(BTref, cur_node, i ? btnk_indexNode : btnk_leafNode, i+1, data_nodes[i].buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- goto bail;
- /* check that it is the first node at this level */
- if (get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->bLink))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* fill other fields */
- data_nodes[i].node_num = cur_node;
- data_nodes[i].cur_rec = 0;
- data_nodes[i].num_recs = get_UINT16BE(((BTNodeHeader *) data_nodes[i].buf)->numRecords);
- /* check that there is at least one record */
- if (data_nodes[i].num_recs == 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* iterate to next level if applicable */
- if (i != 0)
- {
- /* extract first record */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, TRUE, 0, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, rec1, rec1_len, &rec1_data, &rec1_data_len);
- if (err)
- goto bail;
- if (rec1_data_len < sizeof(UINT32BE))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* iterate to next level */
- cur_node = get_UINT32BE(* (UINT32BE *)rec1_data);
- }
- }
-
- /* check that a) the root node has no successor, and b) that we have really
- read the first leaf node */
- if (get_UINT32BE(((BTNodeHeader *) data_nodes[BTref->treeDepth-1].buf)->fLink)
- || (cur_node != BTref->firstLeafNode))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* check that keys are ordered correctly */
- while (1)
- {
- /* iterate through parent nodes */
- i = 0;
- while ((i<BTref->treeDepth) && ((data_nodes[i].cur_rec == 0) || (data_nodes[i].cur_rec == data_nodes[i].num_recs)))
- {
- /* read next node if necessary */
- if (data_nodes[i].cur_rec == data_nodes[i].num_recs)
- {
- /* get link to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->fLink);
- if (cur_node == 0)
- {
- if (i == 0)
- /* normal End of List */
- goto end_of_list;
- else
- {
- /* error */
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
- /* add node in bitmap */
- bitmap[cur_node >> 3] |= (0x80 >> (cur_node & 7));
- /* read node */
- if ((! is_extent) || (cur_node < maxExtentNode))
- err = BT_read_node(BTref, cur_node, i ? btnk_indexNode : btnk_leafNode, i+1, data_nodes[i].buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- goto bail;
- /* check that backward linking match forward linking */
- if (get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->bLink) != data_nodes[i].node_num)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* fill other fields */
- data_nodes[i].node_num = cur_node;
- data_nodes[i].cur_rec = 0;
- data_nodes[i].num_recs = get_UINT16BE(((BTNodeHeader *) data_nodes[i].buf)->numRecords);
- /* check that there is at least one record */
- if (data_nodes[i].num_recs == 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* next test is not necessary because we have checked that
- the root node has no successor */
-#if 0
- if (i < BTref->treeDepth-1)
- {
-#endif
- data_nodes[i+1].cur_rec++;
-#if 0
- }
- else
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-#endif
- }
- i++;
- }
-
- if (is_extent && !extentEOL)
- {
- /* extract current leaf record and update maxExtentAB and
- maxExtentNode */
- hfs_extentKey *extentKey;
- hfs_extent *extentData;
-
- /* extract current leaf record */
- err = BT_node_get_keyed_record(BTref, data_nodes[0].buf, FALSE, data_nodes[0].cur_rec, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- extentKey = (hfs_extentKey*)rec1;
- if ((extentKey->keyLength < 7) || (extentKey->forkType != 0) || (get_UINT32BE(extentKey->fileID) != 3)
- || (get_UINT16BE(extentKey->startBlock) != maxExtentAB))
- /* the key is corrupt or does not concern the extent
- B-tree: set the extentEOL flag so that we stop looking for
- further extent records for the extent B-tree */
- extentEOL = TRUE;
- else
- { /* this key concerns the extent B-tree: update maxExtentAB
- and maxExtentNode */
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, rec1, rec1_len, &rec1_data, &rec1_data_len);
- if (err)
- goto bail;
- if (rec1_data_len < sizeof(hfs_extent)*3)
- /* the record is corrupt: set the extentEOL flag so
- that we stop looking for further extent records for the
- extent B-tree */
- extentEOL = TRUE;
- else
- {
- extentData = (hfs_extent*)rec1_data;
-
- for (j=0; j<3; j++)
- maxExtentAB += get_UINT16BE(extentData[j].numABlks);
- maxExtentNode = (UINT64)maxExtentAB * 512 * BTref->fileref.l2_img->blocksperAB
- / BTref->nodeSize;
- }
- }
- if (extentEOL)
- {
- /* check that the extent B-Tree has been defined entirely */
- if (maxExtentNode < totalNodes)
- { /* no good */
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
- }
-
- if (i<BTref->treeDepth)
- {
- /* extract current record */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, i > 0, data_nodes[i].cur_rec, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- /* extract previous record */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, i > 0, data_nodes[i].cur_rec-1, &rec2, &rec2_len);
- if (err)
- goto bail;
-
- /* check that it is sorted correctly */
- compare_result = (*BTref->key_compare_func)(rec1, rec2);
- if (compare_result <= 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- i--;
- }
- else
- {
- i--;
- if (i>0)
- { /* extract first record of root if it is an index node */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, TRUE, data_nodes[i].cur_rec, &rec1, &rec1_len);
- if (err)
- goto bail;
- }
- i--;
- }
-
- while (i>=0)
- {
- /* extract first record of current level */
- err = BT_node_get_keyed_record(BTref, data_nodes[i].buf, i > 0, data_nodes[i].cur_rec, &rec2, &rec2_len);
- if (err)
- goto bail;
-
- /* compare key with key of current record of upper level */
- compare_result = (*BTref->key_compare_func)(rec1, rec2);
- if (compare_result != 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, rec1, rec1_len, &rec1_data, &rec1_data_len);
- if (err)
- goto bail;
- if (rec1_data_len < sizeof(UINT32BE))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- cur_node = get_UINT32BE(* (UINT32BE *)rec1_data);
-
- /* compare node index with data of current record of upper
- level */
- if (cur_node != data_nodes[i].node_num)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-
- /* iterate to next level */
- rec1 = rec2;
- rec1_len = rec2_len;
- i--;
- }
-
- /* next leaf record */
- data_nodes[0].cur_rec++;
- }
-
-end_of_list:
- /* check that we are at the end of list for each index level */
- for (i=1; i<BTref->treeDepth; i++)
- {
- if ((data_nodes[i].cur_rec != (data_nodes[i].num_recs-1))
- || get_UINT32BE(((BTNodeHeader *) data_nodes[i].buf)->fLink))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
- /* check that the last leaf node is what it is expected to be */
- if (data_nodes[0].node_num != lastLeafNode)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- }
-
- /* check map node chain */
- cur_node = 0; /* node 0 is the header node... */
- bitmap[0] |= 0x80;
- /* check back linking */
- if (get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->bLink))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* get pointer to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->fLink);
- while (cur_node != 0)
- {
- /* save node address */
- prev_node = cur_node;
- /* check that node has not been used for another purpose */
- /* this check is unecessary because the current consistency checks that
- forward and back linking match and that node height is correct are
- enough to detect such errors */
-#if 0
- if (bitmap[cur_node >> 3] & (0x80 >> (cur_node & 7)))
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
-#endif
- /* add node in bitmap */
- bitmap[cur_node >> 3] |= (0x80 >> (cur_node & 7));
- /* read map node */
- if ((! is_extent) || (cur_node < maxExtentNode))
- err = BT_read_node(BTref, cur_node, btnk_mapNode, 0, BTref->node_buf);
- else
- err = IMGTOOLERR_CORRUPTIMAGE;
- if (err)
- goto bail;
- /* check back linking */
- if (get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->bLink) != prev_node)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* get pointer to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->fLink);
- }
-
- /* re-read header node */
- err = BT_read_node(BTref, 0, btnk_headerNode, 0, BTref->node_buf);
- if (err)
- goto bail;
-
- /* get header bitmap record */
- err = BT_node_get_record(BTref, BTref->node_buf, 2, &rec1, &rec1_len);
- if (err)
- goto bail;
-
- /* check bitmap, iterating map nodes */
- map_count = 0;
- actualFreeNodes = 0;
- while (map_count < map_len)
- {
- /* compute compare len */
- run_len = rec1_len;
- if (run_len > (map_len-map_count))
- run_len = map_len-map_count;
- /* check that all used nodes are marked as such in the B-tree bitmap */
- for (i=0; i<run_len; i++)
- if (bitmap[map_count+i] & ~((UINT8 *)rec1)[i])
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* count free nodes */
- run_bit_len = rec1_len*8;
- if (run_bit_len > (totalNodes-map_count*8))
- run_bit_len = totalNodes-map_count*8;
- for (i=0; i<run_bit_len; i++)
- if (! (((UINT8 *)rec1)[i>>3] & (0x80 >> (i & 7))))
- actualFreeNodes++;
- map_count += run_len;
- /* read next map node if required */
- if (map_count < map_len)
- {
- /* get pointer to next node */
- cur_node = get_UINT32BE(((BTNodeHeader *) BTref->node_buf)->fLink);
- if (cur_node == 0)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto bail;
- }
- /* read map node */
- err = BT_read_node(BTref, cur_node, btnk_mapNode, 0, BTref->node_buf);
- if (err)
- goto bail;
- /* get map record */
- err = BT_node_get_record(BTref, BTref->node_buf, 0, &rec1, &rec1_len);
- if (err)
- goto bail;
- header_rec = (BTHeaderRecord *)rec1;
- }
- }
-
- /* check free node count */
- if (freeNodes != actualFreeNodes)
- return IMGTOOLERR_CORRUPTIMAGE;
-
-bail:
- /* free buffers */
- if (data_nodes)
- {
- for (i=0; i<BTref->treeDepth; i++)
- if (data_nodes[i].buf)
- free(data_nodes[i].buf);
- free(data_nodes);
- }
- if (bitmap)
- free(bitmap);
-
- return err;
-}
-
-/*
- BT_search_leaf_rec
-
- Search for a given key in a B-Tree. If exact match found, returns
- corresponding leaf record. Otherwise, may return the greatest record less
- than the requested key (of course, this will fail if the key is lower than
- all keys in the B-Tree).
-
- BTref (I/O): open B-tree file handle
- search_key (I): key to search the B-Tree for
- node_ID (O): set to the node ID of the node the record is located in (may
- be NULL)
- record_ID (O): set to the index of the record in the node (may be NULL)
- record_ptr (O): set to point to record in node buffer (may be NULL)
- record_len (O): set to total record len (may be NULL)
- search_exact_match (I): if TRUE, the function will search for a record
- equal to search_key; if FALSE, the function will search for the
- greatest record less than or equal to search_key
- match_found (O): set to TRUE if an exact match for search_key has been
- found (only makes sense if search_exact_match is FALSE) (may be NULL)
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_search_leaf_rec(mac_BTref *BTref, const void *search_key,
- UINT32 *node_ID, int *record_ID,
- void **record_ptr, int *record_len,
- int search_exact_match, int *match_found)
-{
- imgtoolerr_t err;
- int i;
- UINT32 cur_node;
- void *cur_rec;
- int cur_rec_len;
- void *last_rec;
- int last_rec_len = 0;
- void *rec_data;
- int rec_data_len;
- int depth;
- UINT16 node_numRecords;
- int compare_result = 0;
-
- /* start with root node */
- if ((BTref->rootNode == 0) || (BTref->treeDepth == 0))
- /* tree is empty */
- return ((BTref->rootNode == 0) == (BTref->treeDepth == 0))
- ? IMGTOOLERR_FILENOTFOUND
- : IMGTOOLERR_CORRUPTIMAGE;
-
- cur_node = BTref->rootNode;
- depth = BTref->treeDepth;
-
- while (1)
- {
- /* read current node */
- err = BT_read_node(BTref, cur_node, (depth > 1) ? btnk_indexNode : btnk_leafNode, depth, BTref->node_buf);
- if (err)
- return err;
-
- /* search for key */
- node_numRecords = get_UINT16BE(((BTNodeHeader *) BTref->node_buf)->numRecords);
- last_rec = cur_rec = NULL;
- for (i=0; i<node_numRecords; i++)
- {
- err = BT_node_get_keyed_record(BTref, BTref->node_buf, depth > 1, i, &cur_rec, &cur_rec_len);
- if (err)
- return err;
-
- compare_result = (*BTref->key_compare_func)(cur_rec, search_key);
- if (compare_result > 0)
- break;
- last_rec = cur_rec;
- last_rec_len = cur_rec_len;
- if (compare_result == 0)
- break;
- }
-
- if (! last_rec)
- { /* all keys are greater than the search key: the search key is
- nowhere in the tree */
- if (search_exact_match)
- return IMGTOOLERR_FILENOTFOUND;
-
- if (match_found)
- *match_found = FALSE;
-
- if (node_ID)
- *node_ID = 0;
-
- if (record_ID)
- *record_ID = -1;
-
- if (record_ptr)
- *record_ptr = NULL;
-
- return IMGTOOLERR_SUCCESS;
- }
-
- if (((BTNodeHeader *) BTref->node_buf)->kind == btnk_leafNode)
- /* leaf node -> end of search */
- break;
-
- /* extract record data ptr */
- err = BT_get_keyed_record_data(BTref, last_rec, last_rec_len, &rec_data, &rec_data_len);
- if (err)
- return err;
- if (rec_data_len < sizeof(UINT32BE))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* iterate to next level */
- cur_node = get_UINT32BE(* (UINT32BE *)rec_data);
- depth--;
- }
-
- if (compare_result != 0)
- /* key not found */
- if (search_exact_match)
- return IMGTOOLERR_FILENOTFOUND;
-
- if (match_found)
- *match_found = (compare_result == 0);
-
- if (node_ID)
- *node_ID = cur_node;
-
- if (record_ID)
- *record_ID = i;
-
- if (record_ptr)
- *record_ptr = last_rec;
-
- if (record_len)
- *record_len = last_rec_len;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_leaf_rec_enumerator_open
-
- Open enumerator for leaf records of a B-Tree
-
- BTref (I/O): open B-tree file handle
- enumerator (O): B-Tree enumerator to open
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_leaf_rec_enumerator_open(mac_BTref *BTref, BT_leaf_rec_enumerator *enumerator)
-{
- enumerator->BTref = BTref;
- enumerator->cur_node = BTref->firstLeafNode;
- enumerator->cur_rec = 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- BT_leaf_rec_enumerator_read
-
- Read next leaf record of a B-Tree
-
- enumerator (I/O): open B-Tree enumerator
-
- Return imgtool error code
-*/
-static imgtoolerr_t BT_leaf_rec_enumerator_read(BT_leaf_rec_enumerator *enumerator, void **record_ptr, int *rec_len)
-{
- UINT16 node_numRecords;
- imgtoolerr_t err;
-
-
- *record_ptr = NULL;
-
- /* check EOList condition */
- if (enumerator->cur_node == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* read current node */
- err = BT_read_node(enumerator->BTref, enumerator->cur_node, btnk_leafNode, 1, enumerator->BTref->node_buf);
- if (err)
- return err;
- node_numRecords = get_UINT16BE(((BTNodeHeader *) enumerator->BTref->node_buf)->numRecords);
-
- /* skip nodes until we find a record */
- while ((enumerator->cur_rec >= node_numRecords) && (enumerator->cur_node != 0))
- {
- enumerator->cur_node = get_UINT32BE(((BTNodeHeader *) enumerator->BTref->node_buf)->fLink);
- enumerator->cur_rec = 0;
-
- /* read node */
- err = BT_read_node(enumerator->BTref, enumerator->cur_node, btnk_leafNode, 1, enumerator->BTref->node_buf);
- if (err)
- return err;
- node_numRecords = get_UINT16BE(((BTNodeHeader *) enumerator->BTref->node_buf)->numRecords);
- }
-
- /* check EOList condition */
- if (enumerator->cur_node == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* get current record */
- err = BT_node_get_keyed_record(enumerator->BTref, enumerator->BTref->node_buf, FALSE, enumerator->cur_rec, record_ptr, rec_len);
- if (err)
- return err;
-
- /* iterate to next record */
- enumerator->cur_rec++;
- if (enumerator->cur_rec >= node_numRecords)
- { /* iterate to next node if last record (not required, but will improve
- performance on next iteration) */
- enumerator->cur_node = get_UINT32BE(((BTNodeHeader *) enumerator->BTref->node_buf)->fLink);
- enumerator->cur_rec = 0;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- B-Tree extend EOF algorithm:
- * see if the bitmap will need to be extended
- * extend EOF by min 1 (if bitmap is large engough) or 2 (if bitmap needs
- to be extended) and max ClumpSiz (see extClpSiz and ctClpSiz in MDB)
- ***If we are extending the extent B-Tree, we need to defer the possible
- creation of an additional extent record, or we might enter an endless
- recursion loop***
-
- Empty node alloc algorithm:
-
- * see if there is any free node in B-tree bitmap
- * optionally, try to compact the B-tree if file is full
- * if file is still full, extend EOF and try again
- * mark new block as used and return its index
-
-
- Empty node delete algorithm:
-
- * remove node from link list
- * mark node as free in the B-tree bitmap
- * optionally, if more than N% of the B-tree is free, compact the B-tree and
- free some disk space
- * Count nodes on this level; if there is only one left, delete parent index
- node and mark the relaining node as root; if it was the last leaf node,
- update header node with an empty B-tree; in either case, decrement tree
- depth
-
-
- Record shifting algorithm:
-
- For a given node and its first non-empty successor node:
-
- * compute how much free room there is in the node
- * see if the first record of the first non-empty successor can fit
- * if so, move it (i.e. delete the first record of the later node, and add a
- copy of it to the end of the former)
-
-
- Node merging algorithm
-
- * Consider node and its predecessor. If there is room, shift all records
- from later to former, then delete empty later node, and delete later
- record from parent index node.
-
-
- Node splitting algorithm (non-first)
-
- * Consider node and its predecessor. Create new middle node and split
- records in 3 even sets. Update record for last node and insert record
- for middle node in parent index node.
-
-
- Node splitting algorithm (first node)
-
- * Create new successor node, and split records in 2 1/3 and 2/3 sets.
- Insert record for later node in parent index node.
-
-
- Record delete algorithm:
-
- * remove record from node
- * if record was first in node, test if node is now empty
- * if node is not empty, substitute key of deleted record with key of
- new head record in index tree
- * if node is empty, delete key of deleted record in index tree, then
- delete empty node
- * optionally, look the predecessor node. Merge the two nodes if possible.
-
-
- Record insert algorithm:
-
- * if there room, just insert new record in node; if new record is in first
- position, update record in parent index node
- * else consider predecessor: see if we can make enough room by shifting
- records. If so, do shift records, insert new record, update record in
- parent index node
- * else split the nodes and insert record
-*/
-/*
- Possible additions:
-
- Node compaction algorithm:
-
- This algorithm can be executed with a specific start point and max number
- of nodes, or with all nodes on a level.
-
- * see how many nodes we can save by shifting records left
- * if we will save at least one node, do shift as many records as possible
- (try to leave free space split homogeneously???)
-*/
-
-/*static void*/
-
-#if 0
-#pragma mark -
-#pragma mark RESOURCE IMPLEMENTATION
-#endif
-
-/*
- Resource manager
-
- The resource manager stores arbitrary chunks of data (resource) identified
- by a type/id pair. The resource type is a 4-char code, which generally
- implies the format of the data (e.g. 'PICT' is for a quickdraw picture,
- 'STR ' for a macintosh string, 'CODE' for 68k machine code, etc). The
- resource id is a signed 16-bit number that uniquely identifies each
- resource of a given type. Note that, with most resource types, resources
- with id < 128 are system resources that are available to all applications,
- whereas resources with id >= 128 are application resources visible only to
- the application that defines them.
-
- Each resource can optionally have a resource name, which is a macintosh
- string of 255 chars at most.
-
- Limits:
- 16MBytes of data
- 64kbytes of type+reference lists
- 64kbytes of resource names
-
- The Macintosh toolbox can open several resource files simulteanously to
- overcome these restrictions.
-
- Resources are used virtually everywhere in the Macintosh Toolbox, so it is
- no surprise that file comments and MFS folders are stored in resource files.
-*/
-
-/*
- Resource header
-*/
-struct rsrc_header
-{
- UINT32BE data_offs; /* Offset from beginning of resource fork to resource data */
- UINT32BE map_offs; /* Offset from beginning of resource fork to resource map */
- UINT32BE data_len; /* Length of resource data */
- UINT32BE map_len; /* Length of resource map */
-};
-
-/*
- Resource data: each data entry is preceded by its len (UINT32BE)
- Offset to specific data fields are gotten from the resource map
-*/
-
-/*
- Resource map:
-*/
-struct rsrc_map_header
-{
- rsrc_header reserved0; /* Reserved for copy of resource header */
- UINT32BE reserved1; /* Reserved for handle to next resource map */
- UINT16BE reserved2; /* Reserved for file reference number */
-
- UINT16BE attr; /* Resource fork attributes */
- UINT16BE typelist_offs; /* Offset from beginning of map to resource type list */
- UINT16BE namelist_offs; /* Offset from beginning of map to resource name list */
- UINT16BE type_count; /* Number of types in the map minus 1 */
- /* This is actually part of the type list, which matters for offsets */
-};
-
-/*
- Resource type list entry
-*/
-struct rsrc_type_entry
-{
- UINT32BE type; /* Resource type */
- UINT16BE ref_count; /* Number of resources of this type in map minus 1 */
- UINT16BE ref_offs; /* Offset from beginning of resource type list to reference list for this type */
-};
-
-/*
- Resource reference list entry
-*/
-struct rsrc_ref_entry
-{
- UINT16BE id; /* Resource ID */
- UINT16BE name_offs; /* Offset from beginning of resource name list to resource name */
- /* (-1 if none) */
- UINT8 attr; /* Resource attributes */
- UINT24BE data_offs; /* Offset from beginning of resource data to data for this resource */
- UINT32BE reserved; /* Reserved for handle to resource */
-};
-
-/*
- Resource name list entry: this is just a standard macintosh string
-*/
-
-struct mac_resfileref
-{
- mac_fileref fileref; /* open resource fork ref (you may open resources
- files in data fork, too, if you ever need to,
- but Classic MacOS never does such a thing
- (MacOS X often does so, though)) */
- UINT32 data_offs; /* Offset from beginning of resource file to resource data */
- UINT32 map_offs; /* Offset from beginning of resource file to resource data */
-
- UINT16 typelist_offs; /* Offset from beginning of map to resource type list */
- UINT16 namelist_offs; /* Offset from beginning of map to resource name list */
- UINT16 type_count; /* Number of types in the map minus 1 */
- /* This is actually part of the type list, which matters for offsets */
-};
-
-#ifdef UNUSED_FUNCTION
-/*
- resfile_open
-
- Open a file as a resource file. The file must be already open as a
- macintosh file.
-
- resfileref (I/O): resource file handle to open (resfileref->fileref must
- have been opened previously)
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_open(mac_resfileref *resfileref)
-{
- imgtoolerr_t err;
- rsrc_header header;
- rsrc_map_header map_header;
-
- /* seek to resource header */
- err = mac_file_seek(&resfileref->fileref, 0);
- if (err)
- return err;
-
- err = mac_file_read(&resfileref->fileref, sizeof(header), &header);
- if (err)
- return err;
-
- resfileref->data_offs = get_UINT32BE(header.data_offs);
- resfileref->map_offs = get_UINT32BE(header.map_offs);
-
- /* seek to resource map header */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs);
- if (err)
- return err;
-
- err = mac_file_read(&resfileref->fileref, sizeof(map_header), &map_header);
- if (err)
- return err;
-
- resfileref->typelist_offs = get_UINT16BE(map_header.typelist_offs);
- resfileref->namelist_offs = get_UINT16BE(map_header.namelist_offs);
- resfileref->type_count = get_UINT16BE(map_header.type_count);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_entry
-
- Get the resource entry in the resource map associated with a given type/id
- pair.
-
- resfileref (I/O): open resource file handle
- type (I): type of the resource
- id (I): id of the resource
- entry (O): resource entry that has been read
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_entry(mac_resfileref *resfileref, UINT32 type, UINT16 id, rsrc_ref_entry *entry)
-{
- imgtoolerr_t err;
- rsrc_type_entry type_entry;
- UINT16 ref_count;
- int i;
-
- /* seek to resource type list in resource map */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs+resfileref->typelist_offs+2);
- if (err)
- return err;
-
- if (resfileref->type_count == 0xffff)
- /* type list is empty */
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i=0; i<=resfileref->type_count; i++)
- {
- err = mac_file_read(&resfileref->fileref, sizeof(type_entry), &type_entry);
- if (err)
- return err;
- if (type == get_UINT32BE(type_entry.type))
- break;
- }
- if (i > resfileref->type_count)
- /* type not found in list */
- return IMGTOOLERR_FILENOTFOUND;
-
- ref_count = get_UINT16BE(type_entry.ref_count);
-
- /* seek to resource ref list for this type in resource map */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs+resfileref->typelist_offs+get_UINT16BE(type_entry.ref_offs));
- if (err)
- return err;
-
- if (ref_count == 0xffff)
- /* ref list is empty */
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i=0; i<=ref_count; i++)
- {
- err = mac_file_read(&resfileref->fileref, sizeof(*entry), entry);
- if (err)
- return err;
- if (id == get_UINT16BE(entry->id))
- break;
- }
- if (i > ref_count)
- /* id not found in list */
- return IMGTOOLERR_FILENOTFOUND;
-
- /* type+id have been found... */
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_resname
-
- Get the name of a resource.
-
- resfileref (I/O): open resource file handle
- entry (I): resource entry in the resource map (returned by
- resfile_get_entry)
- string (O): resource name
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_resname(mac_resfileref *resfileref, const rsrc_ref_entry *entry, mac_str255 string)
-{
- imgtoolerr_t err;
- UINT16 name_offs;
- UINT8 len;
-
- name_offs = get_UINT16BE(entry->name_offs);
-
- if (name_offs == 0xffff)
- /* ref list is empty */
- return IMGTOOLERR_UNEXPECTED;
-
- /* seek to resource name in name list in resource map */
- err = mac_file_seek(&resfileref->fileref, resfileref->map_offs+name_offs);
- if (err)
- return err;
-
- /* get string length */
- err = mac_file_read(&resfileref->fileref, 1, &len);
- if (err)
- return err;
-
- string[0] = len;
-
- /* get string data */
- err = mac_file_read(&resfileref->fileref, len, string+1);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_reslen
-
- Get the data length for a given resource.
-
- resfileref (I/O): open resource file handle
- entry (I): resource entry in the resource map (returned by
- resfile_get_entry)
- len (O): resource length
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_reslen(mac_resfileref *resfileref, const rsrc_ref_entry *entry, UINT32 *len)
-{
- imgtoolerr_t err;
- UINT32 data_offs;
- UINT32BE llen;
-
- data_offs = get_UINT24BE(entry->data_offs);
-
- /* seek to resource data in resource data section */
- err = mac_file_seek(&resfileref->fileref, resfileref->data_offs+data_offs);
- if (err)
- return err;
-
- /* get data length */
- err = mac_file_read(&resfileref->fileref, sizeof(llen), &llen);
- if (err)
- return err;
-
- *len = get_UINT32BE(llen);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- resfile_get_resdata
-
- Get the data for a given resource.
-
- resfileref (I/O): open resource file handle
- entry (I): resource entry in the resource map (returned by
- resfile_get_entry)
- offset (I): offset the data should be read from, usually 0
- len (I): length of the data to read, usually the value returned by
- resfile_get_reslen
- dest (O): resource data
-
- Return imgtool error code
-*/
-static imgtoolerr_t resfile_get_resdata(mac_resfileref *resfileref, const rsrc_ref_entry *entry, UINT32 offset, UINT32 len, void *dest)
-{
- imgtoolerr_t err;
- UINT32 data_offs;
- UINT32BE llen;
-
- data_offs = get_UINT24BE(entry->data_offs);
-
- /* seek to resource data in resource data section */
- err = mac_file_seek(&resfileref->fileref, resfileref->data_offs+data_offs);
- if (err)
- return err;
-
- /* get data length */
- err = mac_file_read(&resfileref->fileref, sizeof(llen), &llen);
- if (err)
- return err;
-
- /* check that we do not ask to read more data than avalaible */
- if ((offset + len) > get_UINT32BE(llen))
- return IMGTOOLERR_UNEXPECTED;
-
- if (offset)
- { /* seek to resource data offset in resource data section */
- err = mac_file_seek(&resfileref->fileref, resfileref->data_offs+data_offs+4+offset);
- if (err)
- return err;
- }
-
- /* get data */
- err = mac_file_read(&resfileref->fileref, len, dest);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark DESKTOP FILE IMPLEMENTATION
-#endif
-/*
- All macintosh volumes have information stored in the desktop file or the
- desktop database.
-
- Such information include file comments, copy of BNDL and FREF resources
- that describes supported file types for each application on the volume,
- copy of icons for each file type registered by each application on the
- volume, etc. On MFS volumes, the list of folders is stored in the desktop
- file as well.
-
-
- There have been two implementations of the desktop metadata:
-
- * The original desktop file. The database is stored in the resource fork
- of a (usually invisible) file called "Desktop" (case may change
- according to system versions), located at the root of the volume. The
- desktop file is used by System 6 and earlier for all volumes (unless
- Appleshare 2 is installed and the volume is shared IIRC), and by System
- 7 and later for volumes smaller than 2MBytes (so that floppy disks
- remain fully compatible with earlier versions of system). The desktop
- file is incompletely documented by Apple technote TB06.
-
- * The desktop database. The database is stored in the resource fork is
- stored in the data fork of two (usually invisible) files called
- "Desktop DF" and "Desktop DF". The desktop database is used for
- volumes shared by Appleshare 2, and for most volumes under System 7 and
- later. The format of these file is not documented AFAIK.
-
-
- The reasons for the introduction of the desktop database were:
- * the macintosh resource manager cannot share resource files, which was
- a problem for Appleshare
- * the macintosh resource manager is pretty limited (+/-16MByte of data and
- 2727 resources at most), which was a problem for large hard disks with
- many programs/comments
-*/
-
-#ifdef UNUSED_FUNCTION
-/*
- get_comment
-
- Get a comment from the Desktop file
-
- l2_img (I): macintosh image the data should be read from
- id (I): comment id (from mfs_hashString(), or HFS FXInfo/DXInfo records)
- comment (O): comment that has been read
-
- Return imgtool error code
-*/
-static imgtoolerr_t get_comment(struct mac_l2_imgref *l2_img, UINT16 id, mac_str255 comment)
-{
- static const UINT8 desktop_fname[] = {'\7','D','e','s','k','t','o','p'};
- #define restype_FCMT (('F' << 24) | ('C' << 16) | ('M' << 8) | 'T')
- mac_resfileref resfileref;
- rsrc_ref_entry resentry;
- UINT32 reslen;
- imgtoolerr_t err;
-
- /* open rsrc fork of file Desktop in root directory */
- err = mac_file_open(l2_img, 2, desktop_fname, rsrc_fork, &resfileref.fileref);
- if (err)
- return err;
-
- /* open resource structures */
- err = resfile_open(&resfileref);
- if (err)
- return err;
-
- /* look for resource FCMT #id */
- err = resfile_get_entry(&resfileref, restype_FCMT, id, &resentry);
- if (err)
- return err;
-
- /* extract comment len */
- err = resfile_get_reslen(&resfileref, &resentry, &reslen);
- if (err)
- return err;
-
- /* check comment len */
- if (reslen > 256)
- /* hurk */
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- /* people willing to extend the MFM comment field (you know, the kind
- of masochists that try to support 20-year-old OSes) might append extra
- fields, so we just truncate the resource */
- reslen = 256;
-
- /* extract comment data */
- err = resfile_get_resdata(&resfileref, &resentry, 0, reslen, comment);
- if (err)
- return err;
-
- /* phew, we are done! */
- return IMGTOOLERR_SUCCESS;
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark IMGTOOL MODULE IMPLEMENTATION
-#endif
-
-#ifdef UNUSED_FUNCTION
-static void mac_image_exit(imgtool_image *img);
-#endif
-static void mac_image_info(imgtool_image *img, char *string, size_t len);
-static imgtoolerr_t mac_image_beginenum(imgtool_directory *enumeration, const char *path);
-static imgtoolerr_t mac_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent);
-static imgtoolerr_t mac_image_freespace(imgtool_partition *partition, UINT64 *size);
-static imgtoolerr_t mac_image_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf);
-static imgtoolerr_t mac_image_writefile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *writeoptions);
-
-#ifdef UNUSED_FUNCTION
-/*
- close a mfs/hfs image
-*/
-static void mac_image_exit(imgtool_image *img)
-{
- struct mac_l2_imgref *image = get_imgref(img);
-
- mac_image_close(image);
-}
-#endif
-
-/*
- get basic information on a mfs/hfs image
-
- Currently returns the volume name
-*/
-static void mac_image_info(imgtool_image *img, char *string, size_t len)
-{
- struct mac_l2_imgref *image = get_imgref(img);
-
- switch (image->format)
- {
- case L2I_MFS:
- mac_to_c_strncpy(string, len, image->u.mfs.volname);
- break;
-
- case L2I_HFS:
- mac_to_c_strncpy(string, len, image->u.hfs.volname);
- break;
- }
-}
-
-/*
- MFS/HFS catalog iterator, used when imgtool reads the catalog
-*/
-struct mac_iterator
-{
- mac_format format;
- struct mac_l2_imgref *l2_img;
- union
- {
- struct
- {
- mfs_dirref dirref; /* open directory reference */
- } mfs;
- struct
- {
- hfs_cat_enumerator catref; /* catalog file enumerator */
- } hfs;
- } u;
-};
-
-/*
- Open the disk catalog for enumeration
-*/
-static imgtoolerr_t mac_image_beginenum(imgtool_directory *enumeration, const char *path)
-{
- struct mac_l2_imgref *image = get_imgref(imgtool_directory_image(enumeration));
- mac_iterator *iter = (mac_iterator *) imgtool_directory_extrabytes(enumeration);
- imgtoolerr_t err = IMGTOOLERR_UNEXPECTED;
-
- iter->format = image->format;
- iter->l2_img = image;
-
- switch (iter->format)
- {
- case L2I_MFS:
- err = mfs_dir_open(image, path, &iter->u.mfs.dirref);
- break;
-
- case L2I_HFS:
- err = hfs_cat_open(image, path, &iter->u.hfs.catref);
- break;
- }
-
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Enumerate disk catalog next entry (MFS)
-*/
-static imgtoolerr_t mfs_image_nextenum(mac_iterator *iter, imgtool_dirent *ent)
-{
- mfs_dir_entry *cur_dir_entry;
- imgtoolerr_t err;
-
-
- assert(iter->format == L2I_MFS);
-
- ent->corrupt = 0;
- ent->eof = 0;
-
- err = mfs_dir_read(&iter->u.mfs.dirref, &cur_dir_entry);
- if (err)
- {
- /* error */
- ent->corrupt = 1;
- return err;
- }
- else if (!cur_dir_entry)
- {
- /* EOF */
- ent->eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- /* copy info */
- mac_to_c_strncpy(ent->filename, ARRAY_LENGTH(ent->filename), cur_dir_entry->name);
- ent->filesize = get_UINT32BE(cur_dir_entry->dataPhysicalSize)
- + get_UINT32BE(cur_dir_entry->rsrcPhysicalSize);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#if 0
-/*
- Concatenate path elements in the reverse order
-
- dest (O): destination buffer
- dest_cur_pos (I/O): current position in destination buffer (buffer is
- filled from end to start)
- dest_max_len (I): length of destination buffer (use length minus one if you
- want to preserve a trailing NUL character)
- src (I): source C string
-*/
-static void concat_fname(char *dest, int *dest_cur_pos, int dest_max_len, const char *src)
-{
- static const char ellipsis[] = { '.', '.', '.' };
- int src_len = strlen(src); /* number of chars from src to insert */
-
- if (src_len <= *dest_cur_pos)
- {
- *dest_cur_pos -= src_len;
- memcpy(dest + *dest_cur_pos, src, src_len);
- }
- else
- {
- memcpy(dest, src + src_len - *dest_cur_pos, *dest_cur_pos);
- *dest_cur_pos = 0;
- memcpy(dest, ellipsis, (sizeof(ellipsis) <= dest_max_len)
- ? sizeof(ellipsis)
- : dest_max_len);
- }
-}
-#endif
-
-/*
- Enumerate disk catalog next entry (HFS)
-*/
-static imgtoolerr_t hfs_image_nextenum(mac_iterator *iter, imgtool_dirent *ent)
-{
- hfs_catKey *catrec_key;
- hfs_catData *catrec_data;
- UINT16 dataRecType;
- imgtoolerr_t err;
- /* currently, the mac->C conversion transcodes one mac char with at most 3
- C chars */
- int cur_name_head;
-
- assert(iter->format == L2I_HFS);
-
- ent->corrupt = 0;
- ent->eof = 0;
-
- do
- {
- err = hfs_cat_read(&iter->u.hfs.catref, &catrec_key, &catrec_data);
- if (err)
- {
- /* error */
- ent->corrupt = 1;
- return err;
- }
- else if (!catrec_key)
- {
- /* EOF */
- ent->eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
- dataRecType = get_UINT16BE(catrec_data->dataType);
- } while (((dataRecType != hcrt_Folder) && (dataRecType != hcrt_File))
- || (get_UINT32BE(catrec_key->parID) != iter->u.hfs.catref.parID));
-
- /* copy info */
- switch (get_UINT16BE(catrec_data->dataType))
- {
- case hcrt_Folder:
- ent->directory = 1;
- ent->filesize = 0;
- break;
-
- case hcrt_File:
- ent->directory = 0;
- ent->filesize = get_UINT32BE(catrec_data->file.dataPhysicalSize)
- + get_UINT32BE(catrec_data->file.rsrcPhysicalSize);
- break;
- }
-
- /* initialize file path buffer */
- cur_name_head = ARRAY_LENGTH(ent->filename);
- if (cur_name_head > 0)
- {
- cur_name_head--;
- ent->filename[cur_name_head] = '\0';
- }
-
- /* insert folder/file name in buffer */
- mac_to_c_strncpy(ent->filename, ARRAY_LENGTH(ent->filename), catrec_key->cName);
-// concat_fname(ent->filename, &cur_name_head, ARRAY_LENGTH(ent->filename) - 1, buf);
-
-#if 0
- /* extract parent directory ID */
- parID = get_UINT32BE(catrec_key->parID);
-
- /* looping while (parID != 1) will display the volume name; looping while
- (parID != 2) won't */
- while (parID != /*1*/2)
- {
- /* search catalog for folder thread */
- err = hfs_cat_search(iter->l2_img, parID, mac_empty_str, &catrec_key, &catrec_data);
- if (err)
- {
- /* error */
- concat_fname(ent->filename, &cur_name_head, ARRAY_LENGTH(ent->filename) - 1, ":");
- concat_fname(ent->filename, &cur_name_head, ARRAY_LENGTH(ent->filename) - 1, "???");
-
- memmove(ent->filename, ent->filename+cur_name_head, ARRAY_LENGTH(ent->filename) - cur_name_head);
- ent->corrupt = 1;
- return err;
- }
-
- dataRecType = get_UINT16BE(catrec_data->dataType);
-
- if (dataRecType != hcrt_FolderThread)
- {
- /* error */
- concat_fname(ent->filename, &cur_name_head, ARRAY_LENGTH(ent->filename)-1, ":");
- concat_fname(ent->filename, &cur_name_head, ARRAY_LENGTH(ent->filename)-1, "???");
-
- memmove(ent->filename, ent->filename+cur_name_head, ARRAY_LENGTH(ent->filename)-cur_name_head);
- ent->corrupt = 1;
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- /* got folder thread record: insert the folder name at the start of
- file path, then iterate */
- mac_to_c_strncpy(buf, sizeof(buf), catrec_data->thread.nodeName);
- concat_fname(ent->filename, &cur_name_head, ARRAY_LENGTH(ent->filename) - 1, ":");
- concat_fname(ent->filename, &cur_name_head, ARRAY_LENGTH(ent->filename) - 1, buf);
-
- /* extract parent directory ID */
- parID = get_UINT32BE(catrec_data->thread.parID);
- }
- memmove(ent->filename, ent->filename+cur_name_head, ARRAY_LENGTH(ent->filename) -cur_name_head);
-#endif
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Enumerate disk catalog next entry
-*/
-static imgtoolerr_t mac_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- imgtoolerr_t err;
- mac_iterator *iter = (mac_iterator *) imgtool_directory_extrabytes(enumeration);
-
- switch (iter->format)
- {
- case L2I_MFS:
- err = mfs_image_nextenum(iter, ent);
- break;
-
- case L2I_HFS:
- err = hfs_image_nextenum(iter, ent);
- break;
-
- default:
- assert(1);
- err = IMGTOOLERR_UNEXPECTED;
- break;
- }
- return err;
-}
-
-/*
- Compute free space on disk image in bytes
-*/
-static imgtoolerr_t mac_image_freespace(imgtool_partition *partition, UINT64 *size)
-{
- imgtool_image *image = imgtool_partition_image(partition);
- *size = ((UINT64) get_imgref(image)->freeABs) * 512;
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t mac_get_comment(struct mac_l2_imgref *image, mac_str255 filename, const mac_dirent *cat_info, mac_str255 comment)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- UINT16 commentID;
-
- comment[0] = '\0';
-
- /* get comment from Desktop file */
- switch (image->format)
- {
- case L2I_MFS:
- commentID = mfs_hashString(filename);
- err = get_comment(image, commentID, comment);
- break;
-
- case L2I_HFS:
- /* This is the way to get Finder comments in system <= 7. Attached
- comments use another method, and Finder 8 uses yet another one. */
- commentID = get_UINT16BE(cat_info->flXFinderInfo.comment);
- if (commentID)
- err = get_comment(image, commentID, comment);
- break;
- }
- return err;
-}
-#endif
-
-
-/*
- Extract a file from a disk image.
-*/
-static imgtoolerr_t mac_image_readfile(imgtool_partition *partition, const char *fpath, const char *fork, imgtool_stream *destf)
-{
- imgtoolerr_t err;
- imgtool_image *img = imgtool_partition_image(partition);
- struct mac_l2_imgref *image = get_imgref(img);
- UINT32 parID;
- mac_str255 filename;
- mac_dirent cat_info;
- mac_fileref fileref;
- UINT8 buf[512];
- UINT32 i, run_len, data_len;
- mac_fork_t fork_num;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, fpath, &parID, filename, &cat_info, FALSE);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- /* open file */
- err = mac_file_open(image, parID, filename, fork_num ? rsrc_fork : data_fork, &fileref);
- if (err)
- return err;
-
- data_len = fork_num ? cat_info.rsrcLogicalSize : cat_info.dataLogicalSize;
-
- /* extract DF */
- i = 0;
- while(i < data_len)
- {
- run_len = MIN(data_len - i, sizeof(buf));
-
- err = mac_file_read(&fileref, run_len, buf);
- if (err)
- return err;
- if (stream_write(destf, buf, run_len) != run_len)
- return IMGTOOLERR_WRITEERROR;
- i += run_len;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Add a file to a disk image.
-*/
-static imgtoolerr_t mac_image_writefile(imgtool_partition *partition, const char *fpath, const char *fork, imgtool_stream *sourcef, option_resolution *writeoptions)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- struct mac_l2_imgref *image = get_imgref(img);
- UINT32 parID;
- mac_str255 filename;
- mac_dirent cat_info;
- mac_fileref fileref;
- UINT32 fork_len;
- /*UINT16 commentID;*/
- /*mac_str255 comment;*/
- UINT8 buf[512];
- UINT32 i, run_len;
- imgtoolerr_t err;
- mac_fork_t fork_num;
-
- (void) writeoptions;
-
- if (image->format == L2I_HFS)
- return IMGTOOLERR_UNIMPLEMENTED;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
-#if 0
- if (header.version_old != 0)
- return IMGTOOLERR_UNIMPLEMENTED;
-#endif
- /*mac_strcpy(filename, header.filename);*/
- memset(&cat_info, 0, sizeof(cat_info));
- set_UINT32BE(&cat_info.flFinderInfo.type, 0x3F3F3F3F);
- set_UINT32BE(&cat_info.flFinderInfo.creator, 0x3F3F3F3F);
- fork_len = stream_size(sourcef);
- /*comment[0] = get_UINT16BE(header.comment_len);*/ /* comment length */
- /* Next two fields are set to 0 with MFS volumes. IIRC, 0 normally
- means system script: I don't think MFS stores the file name script code
- anywhere on disk, so it should be a reasonable approximation. */
-
- /* create file */
- /* clear inited flag and file location in window */
- set_UINT16BE(&cat_info.flFinderInfo.flags, get_UINT16BE(cat_info.flFinderInfo.flags) & ~fif_hasBeenInited);
- set_UINT16BE(&cat_info.flFinderInfo.location.v, 0);
- set_UINT16BE(&cat_info.flFinderInfo.location.h, 0);
-
- /* resolve path and create file */
- err = mac_lookup_path(image, fpath, &parID, filename, &cat_info, TRUE);
- if (err)
- return err;
-
- /* open file fork */
- err = mac_file_open(image, parID, filename, (fork_num ? rsrc_fork : data_fork), &fileref);
- if (err)
- return err;
-
- err = mac_file_seteof(&fileref, fork_len);
- if (err)
- return err;
-
- /* extract fork */
- for (i=0; i<fork_len;)
- {
- run_len = fork_len - i;
- if (run_len > 512)
- run_len = 512;
- if (stream_read(sourcef, buf, run_len) != run_len)
- return IMGTOOLERR_READERROR;
- err = mac_file_write(&fileref, run_len, buf);
- if (err)
- return err;
- i += run_len;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t mac_image_listforks(imgtool_partition *partition, const char *path, imgtool_forkent *ents, size_t len)
-{
- imgtoolerr_t err;
- UINT32 parID;
- mac_str255 filename;
- mac_dirent cat_info;
- int fork_num = 0;
- imgtool_image *img = imgtool_partition_image(partition);
- struct mac_l2_imgref *image = get_imgref(img);
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, FALSE);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- /* specify data fork */
- ents[fork_num].type = FORK_DATA;
- ents[fork_num].forkname[0] = '\0';
- ents[fork_num].size = cat_info.dataLogicalSize;
- fork_num++;
-
- if (cat_info.rsrcLogicalSize > 0)
- {
- /* specify the resource fork */
- ents[fork_num].type = FORK_RESOURCE;
- strcpy(ents[fork_num].forkname, "RESOURCE_FORK");
- ents[fork_num].size = cat_info.rsrcLogicalSize;
- fork_num++;
- }
-
- ents[fork_num].type = FORK_END;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t mac_image_getattrs(imgtool_partition *partition, const char *path, const UINT32 *attrs, imgtool_attribute *values)
-{
- imgtoolerr_t err;
- imgtool_image *img = imgtool_partition_image(partition);
- UINT32 parID;
- mac_str255 filename;
- mac_dirent cat_info;
- struct mac_l2_imgref *image = get_imgref(img);
- int i;
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, FALSE);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- values[i].i = get_UINT32BE(cat_info.flFinderInfo.type);
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- values[i].i = get_UINT32BE(cat_info.flFinderInfo.creator);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.flags);
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.location.h);
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.location.v);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- values[i].i = get_UINT16BE(cat_info.flFinderInfo.fldr);
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- values[i].i = get_UINT16BE(cat_info.flXFinderInfo.iconID);
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- values[i].i = cat_info.flXFinderInfo.script;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- values[i].i = cat_info.flXFinderInfo.XFlags;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- values[i].i = get_UINT16BE(cat_info.flXFinderInfo.comment);
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- values[i].i = get_UINT32BE(cat_info.flXFinderInfo.putAway);
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- values[i].t = mac_crack_time(cat_info.createDate);
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- values[i].t = mac_crack_time(cat_info.modifyDate);
- break;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t mac_image_setattrs(imgtool_partition *partition, const char *path, const UINT32 *attrs, const imgtool_attribute *values)
-{
- imgtoolerr_t err;
- UINT32 parID;
- mac_str255 filename;
- mac_dirent cat_info;
- imgtool_image *img = imgtool_partition_image(partition);
- struct mac_l2_imgref *image = get_imgref(img);
- int i;
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, FALSE);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- set_UINT32BE(&cat_info.flFinderInfo.type, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- set_UINT32BE(&cat_info.flFinderInfo.creator, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- set_UINT16BE(&cat_info.flFinderInfo.flags, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- set_UINT16BE(&cat_info.flFinderInfo.location.h, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- set_UINT16BE(&cat_info.flFinderInfo.location.v, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- set_UINT16BE(&cat_info.flFinderInfo.fldr, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- set_UINT16BE(&cat_info.flXFinderInfo.iconID, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- cat_info.flXFinderInfo.script = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- cat_info.flXFinderInfo.XFlags = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- set_UINT16BE(&cat_info.flXFinderInfo.comment, values[i].i);
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- set_UINT32BE(&cat_info.flXFinderInfo.putAway, values[i].i);
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- cat_info.createDate = mac_setup_time(values[i].t);
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- cat_info.modifyDate = mac_setup_time(values[i].t);
- break;
- }
- }
-
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, TRUE);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*************************************
- *
- * Our very own resource manager
- *
- *************************************/
-
-static const void *mac_walk_resources(const void *resource_fork, size_t resource_fork_length,
- UINT32 resource_type,
- int (*discriminator)(const void *resource, UINT16 id, UINT32 length, void *param_),
- void *param, UINT16 *resource_id, UINT32 *resource_length)
-{
- UINT32 resource_data_offset, resource_data_length;
- UINT32 resource_map_offset, resource_map_length;
- UINT32 resource_typelist_count, resource_typelist_offset;
- UINT32 resource_entry_offset, resource_entry_count;
- UINT32 i, this_resource_type;
- UINT32 this_resource_data, this_resource_length;
- UINT16 this_resource_id;
- const void *this_resource_ptr;
-
- if (resource_fork_length < 16)
- return NULL;
-
- /* read resource header; its ok if anything past this point fails */
- resource_data_offset = pick_integer_be(resource_fork, 0, 4);
- resource_map_offset = pick_integer_be(resource_fork, 4, 4);
- resource_data_length = pick_integer_be(resource_fork, 8, 4);
- resource_map_length = pick_integer_be(resource_fork, 12, 4);
- if ((resource_data_offset + resource_data_length) > resource_fork_length)
- return NULL;
- if ((resource_map_offset + resource_map_length) > resource_fork_length)
- return NULL;
- if (resource_map_length < 30)
- return NULL;
-
- /* read resource map and locate the resource type list */
- resource_typelist_offset = pick_integer_be(resource_fork,
- resource_map_offset + 24, 2) + resource_map_offset;
- if ((resource_typelist_offset + 2) > resource_fork_length)
- return NULL;
- resource_typelist_count = pick_integer_be(resource_fork,
- resource_typelist_offset, 2) + 1;
- if ((resource_typelist_offset + resource_typelist_count * 16 + 2) > resource_fork_length)
- return NULL;
-
- /* scan the resource type list and locate the entries for this type */
- resource_entry_count = 0;
- resource_entry_offset = 0;
- for (i = 0; i < resource_typelist_count; i++)
- {
- this_resource_type = pick_integer_be(resource_fork, resource_typelist_offset
- + (i * 8) + 2 + 0, 4);
- if (this_resource_type == resource_type)
- {
- resource_entry_count = pick_integer_be(resource_fork, resource_typelist_offset
- + (i * 8) + 2 + 4, 2) + 1;
- resource_entry_offset = pick_integer_be(resource_fork, resource_typelist_offset
- + (i * 8) + 2 + 6, 2) + resource_typelist_offset;
- break;
- }
- }
-
- /* scan the resource entries, and find the correct resource */
- for (i = 0; i < resource_entry_count; i++)
- {
- this_resource_id = pick_integer_be(resource_fork, resource_entry_offset
- + (i * 12) + 0, 2);
- this_resource_data = pick_integer_be(resource_fork, resource_entry_offset
- + (i * 12) + 5, 3) + resource_data_offset;
- if ((this_resource_data + 4) > resource_fork_length)
- return NULL;
-
- /* gauge the length */
- this_resource_length = pick_integer_be(resource_fork, this_resource_data, 4);
- this_resource_data += 4;
- if ((this_resource_data + this_resource_length) > resource_fork_length)
- return NULL;
-
- this_resource_ptr = ((const UINT8 *) resource_fork) + this_resource_data;
- if (discriminator(this_resource_ptr, this_resource_id,
- this_resource_length, param))
- {
- if (resource_length)
- *resource_length = this_resource_length;
- if (resource_id)
- *resource_id = this_resource_id;
- return this_resource_ptr;
- }
- }
-
- return NULL;
-}
-
-
-
-static int get_resource_discriminator(const void *resource, UINT16 id, UINT32 length, void *param)
-{
- const UINT16 *id_ptr = (const UINT16 *) param;
- return id == *id_ptr;
-}
-
-
-
-static const void *mac_get_resource(const void *resource_fork, size_t resource_fork_length,
- UINT32 resource_type, UINT16 resource_id, UINT32 *resource_length)
-{
- return mac_walk_resources(resource_fork, resource_fork_length,
- resource_type, get_resource_discriminator, &resource_id, NULL, resource_length);
-}
-
-
-
-/*************************************
- *
- * Custom icons
- *
- *************************************/
-
-static int bundle_discriminator(const void *resource, UINT16 id, UINT32 length, void *param)
-{
- UINT32 this_creator_code = pick_integer_be(resource, 0, 4);
- UINT32 desired_creator_code = *((UINT32 *) param);
- return this_creator_code == desired_creator_code;
-}
-
-
-
-static int get_pixel(const UINT8 *src, int width, int height, int bpp,
- int x, int y)
-{
- UINT8 byte, mask;
- int bit_position;
-
- byte = src[(y * width + x) * bpp / 8];
- bit_position = 8 - ((x % (8 / bpp)) + 1) * bpp;
- mask = (1 << bpp) - 1;
- return (byte >> bit_position) & mask;
-}
-
-
-
-static int load_icon(UINT32 *dest, const void *resource_fork, UINT64 resource_fork_length,
- UINT32 resource_type, UINT16 resource_id, int width, int height, int bpp,
- const UINT32 *palette, int has_mask)
-{
- int success = FALSE;
- int y, x, color, is_masked;
- UINT32 pixel;
- const UINT8 *src;
- UINT32 resource_length;
- UINT32 frame_length;
- UINT32 total_length;
-
- frame_length = width * height * bpp / 8;
- total_length = frame_length * (has_mask ? 2 : 1);
-
- /* attempt to fetch resource */
- src = (const UINT8*)mac_get_resource(resource_fork, resource_fork_length, resource_type,
- resource_id, &resource_length);
- if (src && (resource_length == total_length))
- {
- for (y = 0; y < height; y++)
- {
- for (x = 0; x < width; x ++)
- {
- /* first check mask bit */
- if (has_mask)
- is_masked = get_pixel(src + frame_length, width, height, bpp, x, y);
- else
- is_masked = dest[y * width + x] >= 0x80000000;
-
- if (is_masked)
- {
- /* mask is ok; check the actual icon */
- color = get_pixel(src, width, height, bpp, x, y);
- pixel = palette[color] | 0xFF000000;
- }
- else
- {
- /* masked out; nothing */
- pixel = 0;
- }
-
- dest[y * width + x] = pixel;
- }
- }
- success = TRUE;
- }
- return success;
-}
-
-
-
-static imgtoolerr_t mac_image_geticoninfo(imgtool_partition *partition, const char *path, imgtool_iconinfo *iconinfo)
-{
- static const UINT32 mac_palette_1bpp[2] = { 0xFFFFFF, 0x000000 };
-
- static const UINT32 mac_palette_4bpp[16] =
- {
- 0xFFFFFF, 0xFCF305, 0xFF6402, 0xDD0806, 0xF20884, 0x4600A5,
- 0x0000D4, 0x02ABEA, 0x1FB714, 0x006411, 0x562C05, 0x90713A,
- 0xC0C0C0, 0x808080, 0x404040, 0x000000
- };
-
- static const UINT32 mac_palette_8bpp[256] =
- {
- 0xFFFFFF, 0xFFFFCC, 0xFFFF99, 0xFFFF66, 0xFFFF33, 0xFFFF00,
- 0xFFCCFF, 0xFFCCCC, 0xFFCC99, 0xFFCC66, 0xFFCC33, 0xFFCC00,
- 0xFF99FF, 0xFF99CC, 0xFF9999, 0xFF9966, 0xFF9933, 0xFF9900,
- 0xFF66FF, 0xFF66CC, 0xFF6699, 0xFF6666, 0xFF6633, 0xFF6600,
- 0xFF33FF, 0xFF33CC, 0xFF3399, 0xFF3366, 0xFF3333, 0xFF3300,
- 0xFF00FF, 0xFF00CC, 0xFF0099, 0xFF0066, 0xFF0033, 0xFF0000,
- 0xCCFFFF, 0xCCFFCC, 0xCCFF99, 0xCCFF66, 0xCCFF33, 0xCCFF00,
- 0xCCCCFF, 0xCCCCCC, 0xCCCC99, 0xCCCC66, 0xCCCC33, 0xCCCC00,
- 0xCC99FF, 0xCC99CC, 0xCC9999, 0xCC9966, 0xCC9933, 0xCC9900,
- 0xCC66FF, 0xCC66CC, 0xCC6699, 0xCC6666, 0xCC6633, 0xCC6600,
- 0xCC33FF, 0xCC33CC, 0xCC3399, 0xCC3366, 0xCC3333, 0xCC3300,
- 0xCC00FF, 0xCC00CC, 0xCC0099, 0xCC0066, 0xCC0033, 0xCC0000,
- 0x99FFFF, 0x99FFCC, 0x99FF99, 0x99FF66, 0x99FF33, 0x99FF00,
- 0x99CCFF, 0x99CCCC, 0x99CC99, 0x99CC66, 0x99CC33, 0x99CC00,
- 0x9999FF, 0x9999CC, 0x999999, 0x999966, 0x999933, 0x999900,
- 0x9966FF, 0x9966CC, 0x996699, 0x996666, 0x996633, 0x996600,
- 0x9933FF, 0x9933CC, 0x993399, 0x993366, 0x993333, 0x993300,
- 0x9900FF, 0x9900CC, 0x990099, 0x990066, 0x990033, 0x990000,
- 0x66FFFF, 0x66FFCC, 0x66FF99, 0x66FF66, 0x66FF33, 0x66FF00,
- 0x66CCFF, 0x66CCCC, 0x66CC99, 0x66CC66, 0x66CC33, 0x66CC00,
- 0x6699FF, 0x6699CC, 0x669999, 0x669966, 0x669933, 0x669900,
- 0x6666FF, 0x6666CC, 0x666699, 0x666666, 0x666633, 0x666600,
- 0x6633FF, 0x6633CC, 0x663399, 0x663366, 0x663333, 0x663300,
- 0x6600FF, 0x6600CC, 0x660099, 0x660066, 0x660033, 0x660000,
- 0x33FFFF, 0x33FFCC, 0x33FF99, 0x33FF66, 0x33FF33, 0x33FF00,
- 0x33CCFF, 0x33CCCC, 0x33CC99, 0x33CC66, 0x33CC33, 0x33CC00,
- 0x3399FF, 0x3399CC, 0x339999, 0x339966, 0x339933, 0x339900,
- 0x3366FF, 0x3366CC, 0x336699, 0x336666, 0x336633, 0x336600,
- 0x3333FF, 0x3333CC, 0x333399, 0x333366, 0x333333, 0x333300,
- 0x3300FF, 0x3300CC, 0x330099, 0x330066, 0x330033, 0x330000,
- 0x00FFFF, 0x00FFCC, 0x00FF99, 0x00FF66, 0x00FF33, 0x00FF00,
- 0x00CCFF, 0x00CCCC, 0x00CC99, 0x00CC66, 0x00CC33, 0x00CC00,
- 0x0099FF, 0x0099CC, 0x009999, 0x009966, 0x009933, 0x009900,
- 0x0066FF, 0x0066CC, 0x006699, 0x006666, 0x006633, 0x006600,
- 0x0033FF, 0x0033CC, 0x003399, 0x003366, 0x003333, 0x003300,
- 0x0000FF, 0x0000CC, 0x000099, 0x000066, 0x000033, 0xEE0000,
- 0xDD0000, 0xBB0000, 0xAA0000, 0x880000, 0x770000, 0x550000,
- 0x440000, 0x220000, 0x110000, 0x00EE00, 0x00DD00, 0x00BB00,
- 0x00AA00, 0x008800, 0x007700, 0x005500, 0x004400, 0x002200,
- 0x001100, 0x0000EE, 0x0000DD, 0x0000BB, 0x0000AA, 0x000088,
- 0x000077, 0x000055, 0x000044, 0x000022, 0x000011, 0xEEEEEE,
- 0xDDDDDD, 0xBBBBBB, 0xAAAAAA, 0x888888, 0x777777, 0x555555,
- 0x444444, 0x222222, 0x111111, 0x000000
- };
-
- static const UINT32 attrs[4] =
- {
- IMGTOOLATTR_INT_MAC_TYPE,
- IMGTOOLATTR_INT_MAC_CREATOR,
- IMGTOOLATTR_INT_MAC_FINDERFLAGS
- };
-
- imgtoolerr_t err;
- imgtool_attribute attr_values[3];
- UINT32 type_code, creator_code, finder_flags;
- imgtool_stream *stream = NULL;
- const void *resource_fork;
- UINT64 resource_fork_length;
- const void *bundle;
- UINT32 bundle_length, pos, fref_pos, icn_pos, i;
- UINT16 local_id = 0, resource_id;
- UINT32 fref_bundleentry_length, icn_bundleentry_length;
- const void *fref;
- UINT32 resource_length;
-
- assert((ARRAY_LENGTH(attrs) - 1)
- == ARRAY_LENGTH(attr_values));
-
- /* first retrieve type and creator code */
- err = mac_image_getattrs(partition, path, attrs, attr_values);
- if (err)
- goto done;
- type_code = (UINT32) attr_values[0].i;
- creator_code = (UINT32) attr_values[1].i;
- finder_flags = (UINT32) attr_values[2].i;
-
- /* check the bundle bit; if clear (and the type is not 'APPL'), use the
- * desktop file */
- if (!(finder_flags & 0x2000) && (type_code != /* APPL */ 0x4150504C))
- path = "Desktop\0";
-
- stream = stream_open_mem(NULL, 0);
- if (!stream)
- {
- err = IMGTOOLERR_SUCCESS;
- goto done;
- }
-
- /* read in the resource fork */
- err = mac_image_readfile(partition, path, "RESOURCE_FORK", stream);
- if (err)
- goto done;
- resource_fork = stream_getptr(stream);
- resource_fork_length = stream_size(stream);
-
- /* attempt to look up the bundle */
- bundle = mac_walk_resources(resource_fork, resource_fork_length, /* BNDL */ 0x424E444C,
- bundle_discriminator, &creator_code, NULL, &bundle_length);
- if (!bundle)
- goto done;
-
- /* find the FREF and the icon family */
- pos = 8;
- fref_pos = icn_pos = 0;
- fref_bundleentry_length = icn_bundleentry_length = 0;
- while((pos + 10) <= bundle_length)
- {
- UINT32 this_bundleentry_type = pick_integer_be(bundle, pos + 0, 4);
- UINT32 this_bundleentry_length = pick_integer_be(bundle, pos + 4, 2) + 1;
-
- if (this_bundleentry_type == /* FREF */ 0x46524546)
- {
- fref_pos = pos;
- fref_bundleentry_length = this_bundleentry_length;
- }
- if (this_bundleentry_type == /* ICN# */ 0x49434E23)
- {
- icn_pos = pos;
- icn_bundleentry_length = this_bundleentry_length;
- }
- pos += 6 + this_bundleentry_length * 4;
- }
- if (!fref_pos || !icn_pos)
- goto done;
-
- /* look up the FREF */
- for (i = 0; i < fref_bundleentry_length; i++)
- {
- local_id = pick_integer_be(bundle, fref_pos + (i * 4) + 6, 2);
- resource_id = pick_integer_be(bundle, fref_pos + (i * 4) + 8, 2);
-
- fref = mac_get_resource(resource_fork, resource_fork_length,
- /* FREF */ 0x46524546, resource_id, &resource_length);
- if (fref && (resource_length >= 7))
- {
- if (pick_integer_be(fref, 0, 4) == type_code)
- break;
- }
- }
- if (i >= fref_bundleentry_length)
- goto done;
-
- /* now look up the icon family */
- resource_id = 0;
- for (i = 0; i < icn_bundleentry_length; i++)
- {
- if (pick_integer_be(bundle, icn_pos + (i * 4) + 6, 2) == local_id)
- {
- resource_id = pick_integer_be(bundle, icn_pos + (i * 4) + 8, 2);
- break;
- }
- }
- if (i >= icn_bundleentry_length)
- goto done;
-
- /* fetch 32x32 icons (ICN#, icl4, icl8) */
- if (load_icon((UINT32 *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* ICN# */ 0x49434E23, resource_id, 32, 32, 1, mac_palette_1bpp, TRUE))
- {
- iconinfo->icon32x32_specified = 1;
-
- load_icon((UINT32 *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* icl4 */ 0x69636C34, resource_id, 32, 32, 4, mac_palette_4bpp, FALSE);
- load_icon((UINT32 *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* icl8 */ 0x69636C38, resource_id, 32, 32, 8, mac_palette_8bpp, FALSE);
- }
-
- /* fetch 16x16 icons (ics#, ics4, ics8) */
- if (load_icon((UINT32 *) iconinfo->icon16x16, resource_fork, resource_fork_length,
- /* ics# */ 0x69637323, resource_id, 16, 16, 1, mac_palette_1bpp, TRUE))
- {
- iconinfo->icon16x16_specified = 1;
-
- load_icon((UINT32 *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* ics4 */ 0x69637334, resource_id, 32, 32, 4, mac_palette_4bpp, FALSE);
- load_icon((UINT32 *) iconinfo->icon32x32, resource_fork, resource_fork_length,
- /* ics8 */ 0x69637338, resource_id, 32, 32, 8, mac_palette_8bpp, FALSE);
- }
-
-done:
- if (stream)
- stream_close(stream);
- return err;
-}
-
-
-
-/*************************************
- *
- * File transfer suggestions
- *
- *************************************/
-
-static imgtoolerr_t mac_image_suggesttransfer(imgtool_partition *partition, const char *path, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- imgtoolerr_t err;
- UINT32 parID;
- mac_str255 filename;
- mac_dirent cat_info;
- imgtool_image *img = imgtool_partition_image(partition);
- struct mac_l2_imgref *image = get_imgref(img);
- mac_filecategory_t file_category = MAC_FILECATEGORY_DATA;
-
- if (path)
- {
- /* resolve path and fetch file info from directory/catalog */
- err = mac_lookup_path(image, path, &parID, filename, &cat_info, FALSE);
- if (err)
- return err;
- if (cat_info.dataRecType != hcrt_File)
- return IMGTOOLERR_FILENOTFOUND;
-
- file_category = (cat_info.rsrcLogicalSize > 0) ? MAC_FILECATEGORY_FORKED : MAC_FILECATEGORY_DATA;
- }
-
- mac_suggest_transfer(file_category, suggestions, suggestions_length);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*************************************
- *
- * Module population
- *
- *************************************/
-
-static void generic_mac_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_OPEN_IS_STRICT: info->i = 1; break;
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(struct mac_l2_imgref); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct mac_iterator); break;
- case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = ':'; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_EOLN: strcpy(info->s = imgtool_temp_str(), "\r"); 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_CLOSE: /* info->close = mac_image_exit */; break;
- case IMGTOOLINFO_PTR_INFO: info->info = mac_image_info; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = mac_image_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = mac_image_nextenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = mac_image_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = mac_image_readfile; break;
- case IMGTOOLINFO_PTR_LIST_FORKS: info->list_forks = mac_image_listforks; break;
- case IMGTOOLINFO_PTR_GET_ATTRS: info->get_attrs = mac_image_getattrs; break;
- case IMGTOOLINFO_PTR_SET_ATTRS: info->set_attrs = mac_image_setattrs; break;
- case IMGTOOLINFO_PTR_GET_ICON_INFO: info->get_iconinfo = mac_image_geticoninfo; break;
- case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = mac_image_suggesttransfer; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_apple35_mac; break;
- }
-}
-
-
-
-void mac_mfs_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "mac_mfs"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Mac MFS Floppy"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = mfs_image_create; break;
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = mfs_image_open; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = mac_image_writefile; break;
-
- default: generic_mac_get_info(imgclass, state, info); break;
- }
-}
-
-
-
-void mac_hfs_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "mac_hfs"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Mac HFS Floppy"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = hfs_image_open; break;
-
- default: generic_mac_get_info(imgclass, state, info); break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/macbin.c b/src/mess/tools/imgtool/modules/macbin.c
deleted file mode 100644
index 3ef85a039d1..00000000000
--- a/src/mess/tools/imgtool/modules/macbin.c
+++ /dev/null
@@ -1,377 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- macbin.c
-
- MacBinary filter for use with Mac and ProDOS drivers
-
-*****************************************************************************
-
- MacBinary file format
-
- Offset Length Description
- ------ ------ -----------
- 0 1 [I] Magic byte (0x00)
- 1 64 [I] File name (Pascal String)
- 65 4 [I] File Type Code
- 69 4 [I] File Creator Code
- 73 1 [I] Finder Flags (bits 15-8)
- 74 1 [I] Magic byte (0x00)
- 75 2 [I] File Vertical Position
- 77 2 [I] File Horizontal Position
- 79 2 [I] Window/Folder ID
- 81 1 [I] Protected (bit 0)
- 82 1 [I] Magic byte (0x00)
- 83 4 [I] Data Fork Length
- 87 4 [I] Resource Fork Length
- 91 4 [I] Creation Date
- 95 4 [I] Last Modified Date
- 99 2 [I] "Get Info" comment length
- 101 1 [II] Finder Flags (bits 7-0)
- 102 4 [III] MacBinary III Signature 'mBIN'
- 106 1 [III] Script of Filename
- 107 1 [III] Extended Finder Flags
- 116 4 [II] Unpacked Length
- 120 2 [II] Secondary Header Length
- 122 1 [II] MacBinary II Version Number (II: 0x81, III: 0x82)
- 123 1 [II] Minimum Compatible MacBinary II Version Number (0x81)
- 124 2 [II] CRC of previous 124 bytes
-
- For more information, consult http://www.lazerware.com/formats/macbinary.html
-
- TODO: I believe that the script code is some sort of identifier identifying
- the character set used for the filename. If this is true, we are not
- handling that properly
-
-*****************************************************************************/
-
-#include <string.h>
-
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "macutil.h"
-
-
-
-static UINT32 pad128(UINT32 length)
-{
- if (length % 128)
- length += 128 - (length % 128);
- return length;
-}
-
-
-
-static imgtoolerr_t macbinary_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- static const UINT32 attrs[] =
- {
- IMGTOOLATTR_TIME_CREATED,
- IMGTOOLATTR_TIME_LASTMODIFIED,
- IMGTOOLATTR_INT_MAC_TYPE,
- IMGTOOLATTR_INT_MAC_CREATOR,
- IMGTOOLATTR_INT_MAC_FINDERFLAGS,
- IMGTOOLATTR_INT_MAC_COORDX,
- IMGTOOLATTR_INT_MAC_COORDY,
- IMGTOOLATTR_INT_MAC_FINDERFOLDER,
- IMGTOOLATTR_INT_MAC_SCRIPTCODE,
- IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS,
- 0
- };
- imgtoolerr_t err;
- UINT8 header[128];
- const char *basename;
- int i;
-
- UINT32 type_code = 0x3F3F3F3F;
- UINT32 creator_code = 0x3F3F3F3F;
- UINT16 finder_flags = 0;
- UINT16 coord_x = 0;
- UINT16 coord_y = 0;
- UINT16 finder_folder = 0;
- UINT8 script_code = 0;
- UINT8 extended_flags = 0;
-
- imgtool_forkent fork_entries[4];
- const imgtool_forkent *data_fork = NULL;
- const imgtool_forkent *resource_fork = NULL;
- UINT32 creation_time = 0;
- UINT32 lastmodified_time = 0;
- imgtool_attribute attr_values[10];
-
- /* get the forks */
- err = imgtool_partition_list_file_forks(partition, filename, fork_entries, sizeof(fork_entries));
- if (err)
- return err;
- for (i = 0; fork_entries[i].type != FORK_END; i++)
- {
- if (fork_entries[i].type == FORK_DATA)
- data_fork = &fork_entries[i];
- else if (fork_entries[i].type == FORK_RESOURCE)
- resource_fork = &fork_entries[i];
- }
-
- /* get the attributes */
- err = imgtool_partition_get_file_attributes(partition, filename, attrs, attr_values);
- if (err && (ERRORCODE(err) != IMGTOOLERR_UNIMPLEMENTED))
- return err;
- if (err == IMGTOOLERR_SUCCESS)
- {
- creation_time = mac_setup_time(attr_values[0].t);
- lastmodified_time = mac_setup_time(attr_values[1].t);
- type_code = attr_values[2].i;
- creator_code = attr_values[3].i;
- finder_flags = attr_values[4].i;
- coord_x = attr_values[5].i;
- coord_y = attr_values[6].i;
- finder_folder = attr_values[7].i;
- script_code = attr_values[8].i;
- extended_flags = attr_values[9].i;
- }
-
- memset(header, 0, sizeof(header));
-
- /* place filename */
- basename = filename;
- while(basename[strlen(basename) + 1])
- basename += strlen(basename) + 1;
- pascal_from_c_string((unsigned char *) &header[1], 64, basename);
-
- place_integer_be(header, 65, 4, type_code);
- place_integer_be(header, 69, 4, creator_code);
- place_integer_be(header, 73, 1, (finder_flags >> 8) & 0xFF);
- place_integer_be(header, 75, 2, coord_x);
- place_integer_be(header, 77, 2, coord_y);
- place_integer_be(header, 79, 2, finder_folder);
- place_integer_be(header, 83, 4, data_fork ? data_fork->size : 0);
- place_integer_be(header, 87, 4, resource_fork ? resource_fork->size : 0);
- place_integer_be(header, 91, 4, creation_time);
- place_integer_be(header, 95, 4, lastmodified_time);
- place_integer_be(header, 101, 1, (finder_flags >> 0) & 0xFF);
- place_integer_be(header, 102, 4, 0x6D42494E);
- place_integer_be(header, 106, 1, script_code);
- place_integer_be(header, 107, 1, extended_flags);
- place_integer_be(header, 122, 1, 0x82);
- place_integer_be(header, 123, 1, 0x81);
- place_integer_be(header, 124, 2, ccitt_crc16(0, header, 124));
-
- stream_write(destf, header, sizeof(header));
-
- if (data_fork)
- {
- err = imgtool_partition_read_file(partition, filename, "", destf, NULL);
- if (err)
- return err;
-
- stream_fill(destf, 0, pad128(data_fork->size));
- }
-
- if (resource_fork)
- {
- err = imgtool_partition_read_file(partition, filename, "RESOURCE_FORK", destf, NULL);
- if (err)
- return err;
-
- stream_fill(destf, 0, pad128(resource_fork->size));
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t write_fork(imgtool_partition *partition, const char *filename, const char *fork,
- imgtool_stream *sourcef, UINT64 pos, UINT64 fork_len, option_resolution *opts)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- imgtool_stream *mem_stream = NULL;
- size_t len;
-
- if (fork_len > 0)
- {
- mem_stream = stream_open_mem(NULL, 0);
- if (!mem_stream)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- stream_seek(sourcef, pos, SEEK_SET);
- len = stream_transfer(mem_stream, sourcef, fork_len);
- if (len < fork_len)
- stream_fill(mem_stream, 0, fork_len);
-
- stream_seek(mem_stream, 0, SEEK_SET);
- err = imgtool_partition_write_file(partition, filename, fork, mem_stream, opts, NULL);
- if (err)
- goto done;
- }
-
-done:
- if (mem_stream)
- stream_close(mem_stream);
- return err;
-}
-
-
-
-static imgtoolerr_t macbinary_writefile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- static const UINT32 attrs[] =
- {
- IMGTOOLATTR_TIME_CREATED,
- IMGTOOLATTR_TIME_LASTMODIFIED,
- IMGTOOLATTR_INT_MAC_TYPE,
- IMGTOOLATTR_INT_MAC_CREATOR,
- IMGTOOLATTR_INT_MAC_FINDERFLAGS,
- IMGTOOLATTR_INT_MAC_COORDX,
- IMGTOOLATTR_INT_MAC_COORDY,
- IMGTOOLATTR_INT_MAC_FINDERFOLDER,
- IMGTOOLATTR_INT_MAC_SCRIPTCODE,
- IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS,
- 0
- };
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- UINT8 header[128];
- UINT32 datafork_size;
- UINT32 resourcefork_size;
- UINT64 total_size;
- UINT32 creation_time;
- UINT32 lastmodified_time;
- //int version;
- imgtool_attribute attr_values[10];
-
- UINT32 type_code;
- UINT32 creator_code;
- UINT16 finder_flags;
- UINT16 coord_x;
- UINT16 coord_y;
- UINT16 finder_folder;
- UINT8 script_code = 0;
- UINT8 extended_flags = 0;
-
- /* read in the header */
- memset(header, 0, sizeof(header));
- stream_read(sourcef, header, sizeof(header));
-
- /* check magic and zero fill bytes */
- if (header[0] != 0x00)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[74] != 0x00)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[82] != 0x00)
- return IMGTOOLERR_CORRUPTFILE;
-
- datafork_size = pick_integer_be(header, 83, 4);
- resourcefork_size = pick_integer_be(header, 87, 4);
- total_size = stream_size(sourcef);
-
- /* size of a MacBinary header is always 128 bytes */
- if (total_size - pad128(datafork_size) - pad128(resourcefork_size) != 128)
- return IMGTOOLERR_CORRUPTFILE;
-
- /* check filename length byte */
- if ((header[1] <= 0x00) || (header[1] > 0x3F))
- return IMGTOOLERR_CORRUPTFILE;
-
- /* check the CRC */
- if (pick_integer_be(header, 124, 2) != ccitt_crc16(0, header, 124))
- {
- /* the CRC does not match; this file is MacBinary I */
- //version = 1;
- }
- else if (pick_integer_be(header, 102, 4) != 0x6D42494E)
- {
- /* did not see 'mBIN'; this file is MacBinary II */
- if (header[122] < 0x81)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[123] < 0x81)
- return IMGTOOLERR_CORRUPTFILE;
- //version = 2;
- }
- else
- {
- /* we did see 'mBIN'; this file is MacBinary III */
- if (header[122] < 0x82)
- return IMGTOOLERR_CORRUPTFILE;
- if (header[123] < 0x81)
- return IMGTOOLERR_CORRUPTFILE;
- //version = 3;
- }
-
- type_code = pick_integer_be(header, 65, 4);
- creator_code = pick_integer_be(header, 69, 4);
- finder_flags = pick_integer_be(header, 73, 1) << 8;
- coord_x = pick_integer_be(header, 75, 2);
- coord_y = pick_integer_be(header, 77, 2);
- finder_folder = pick_integer_be(header, 79, 2);
- creation_time = pick_integer_be(header, 91, 4);
- lastmodified_time = pick_integer_be(header, 95, 4);
-
- if (image)
- {
- /* write out both forks */
- err = write_fork(partition, filename, "", sourcef, sizeof(header), datafork_size, opts);
- if (err)
- return err;
- err = write_fork(partition, filename, "RESOURCE_FORK", sourcef, sizeof(header) + pad128(datafork_size), resourcefork_size, opts);
- if (err)
- return err;
-
- /* set up attributes */
- attr_values[0].t = mac_crack_time(creation_time);
- attr_values[1].t = mac_crack_time(lastmodified_time);
- attr_values[2].i = type_code;
- attr_values[3].i = creator_code;
- attr_values[4].i = finder_flags;
- attr_values[5].i = coord_x;
- attr_values[6].i = coord_y;
- attr_values[7].i = finder_folder;
- attr_values[8].i = script_code;
- attr_values[9].i = extended_flags;
-
- err = imgtool_partition_put_file_attributes(partition, filename, attrs, attr_values);
- if (err)
- return err;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t macbinary_checkstream(imgtool_stream *stream, imgtool_suggestion_viability_t *viability)
-{
- imgtoolerr_t err;
-
- err = macbinary_writefile(NULL, NULL, NULL, stream, NULL);
- if (err == IMGTOOLERR_CORRUPTFILE)
- {
- /* the filter returned corrupt; this is not a valid file */
- *viability = SUGGESTION_END;
- err = IMGTOOLERR_SUCCESS;
- }
- else if (err == IMGTOOLERR_SUCCESS)
- {
- /* success; lets recommend this filter */
- *viability = SUGGESTION_RECOMMENDED;
- }
- return err;
-}
-
-
-
-void filter_macbinary_getinfo(UINT32 state, union filterinfo *info)
-{
- switch(state)
- {
- case FILTINFO_STR_NAME: info->s = "macbinary"; break;
- case FILTINFO_STR_HUMANNAME: info->s = "MacBinary"; break;
- case FILTINFO_STR_EXTENSION: info->s = "bin"; break;
- case FILTINFO_PTR_READFILE: info->read_file = macbinary_readfile; break;
- case FILTINFO_PTR_WRITEFILE: info->write_file = macbinary_writefile; break;
- case FILTINFO_PTR_CHECKSTREAM: info->check_stream = macbinary_checkstream; break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/macutil.c b/src/mess/tools/imgtool/modules/macutil.c
deleted file mode 100644
index fe2e1ade51a..00000000000
--- a/src/mess/tools/imgtool/modules/macutil.c
+++ /dev/null
@@ -1,89 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- macutil.c
-
- Imgtool Utility code for manipulating certain Apple/Mac data structures
- and conventions
-
-*****************************************************************************/
-
-#include "macutil.h"
-
-
-time_t mac_crack_time(UINT32 t)
-{
- /* not sure if this is correct... */
- return t - (((1970 - 1904) * 365) + 17) * 24 * 60 * 60;
-}
-
-
-
-UINT32 mac_setup_time(time_t t)
-{
- /* not sure if this is correct... */
- return t + (((1970 - 1904) * 365) + 17) * 24 * 60 * 60;
-}
-
-
-
-UINT32 mac_time_now(void)
-{
- time_t now;
- time(&now);
- return mac_setup_time(now);
-}
-
-
-
-imgtoolerr_t mac_identify_fork(const char *fork_string, mac_fork_t *fork_num)
-{
- if (!strcmp(fork_string, ""))
- *fork_num = MAC_FORK_DATA;
- else if (!strcmp(fork_string, "RESOURCE_FORK"))
- *fork_num = MAC_FORK_RESOURCE;
- else
- return IMGTOOLERR_FORKNOTFOUND;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-void mac_suggest_transfer(mac_filecategory_t file_category, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- suggestions[0].viability = (file_category == MAC_FILECATEGORY_FORKED) ? SUGGESTION_RECOMMENDED : SUGGESTION_POSSIBLE;
- suggestions[0].filter = filter_macbinary_getinfo;
- suggestions[0].fork = NULL;
- suggestions[0].description = NULL;
-
- suggestions[1].viability = (file_category == MAC_FILECATEGORY_TEXT) ? SUGGESTION_RECOMMENDED : SUGGESTION_POSSIBLE;
- suggestions[1].filter = filter_eoln_getinfo;
- suggestions[1].fork = NULL;
- suggestions[1].description = NULL;
-
- suggestions[2].viability = (file_category == MAC_FILECATEGORY_DATA) ? SUGGESTION_RECOMMENDED : SUGGESTION_POSSIBLE;
- suggestions[2].filter = NULL;
- suggestions[2].fork = "";
- suggestions[2].description = "Raw (data fork)";
-
- suggestions[3].viability = SUGGESTION_POSSIBLE;
- suggestions[3].filter = NULL;
- suggestions[3].fork = "RESOURCE_FORK";
- suggestions[3].description = "Raw (resource fork)";
-}
-
-
-
-void pascal_from_c_string(unsigned char *pstring, size_t pstring_len, const char *cstring)
-{
- size_t cstring_len, i;
-
- cstring_len = strlen(cstring);
- pstring[0] = MIN(cstring_len, pstring_len - 1);
-
- for (i = 0; i < pstring[0]; i++)
- pstring[1 + i] = cstring[i];
- while(i < pstring_len - 1)
- pstring[1 + i++] = '\0';
-}
diff --git a/src/mess/tools/imgtool/modules/macutil.h b/src/mess/tools/imgtool/modules/macutil.h
deleted file mode 100644
index 71121dade31..00000000000
--- a/src/mess/tools/imgtool/modules/macutil.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- macutil.h
-
- Imgtool Utility code for manipulating certain Apple/Mac data structures
- and conventions
-
-*****************************************************************************/
-
-#ifndef MACUTIL_H
-#define MACUTIL_H
-
-#include "imgtool.h"
-
-enum mac_fork_t
-{
- MAC_FORK_DATA,
- MAC_FORK_RESOURCE
-};
-
-enum mac_filecategory_t
-{
- MAC_FILECATEGORY_DATA,
- MAC_FILECATEGORY_TEXT,
- MAC_FILECATEGORY_FORKED
-};
-
-
-/* converting Classic Mac OS time <==> Imgtool time */
-time_t mac_crack_time(UINT32 t);
-UINT32 mac_setup_time(time_t t);
-UINT32 mac_time_now(void);
-
-imgtoolerr_t mac_identify_fork(const char *fork_string, mac_fork_t *fork_num);
-
-void mac_suggest_transfer(mac_filecategory_t file_category, imgtool_transfer_suggestion *suggestions, size_t suggestions_length);
-
-void pascal_from_c_string(unsigned char *pstring, size_t pstring_len, const char *cstring);
-
-#endif /* MACUTIL_H */
diff --git a/src/mess/tools/imgtool/modules/os9.c b/src/mess/tools/imgtool/modules/os9.c
deleted file mode 100644
index 2a9e2fb0292..00000000000
--- a/src/mess/tools/imgtool/modules/os9.c
+++ /dev/null
@@ -1,1244 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/****************************************************************************
-
- os9.c
-
- CoCo OS-9 disk images
-
-****************************************************************************/
-
-#include <time.h>
-
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/coco_dsk.h"
-#include "iflopimg.h"
-
-enum creation_policy_t
-{
- CREATE_NONE,
- CREATE_FILE,
- CREATE_DIR
-};
-
-struct os9_diskinfo
-{
- UINT32 total_sectors;
- UINT32 sectors_per_track;
- UINT32 allocation_bitmap_bytes;
- UINT32 cluster_size;
- UINT32 root_dir_lsn;
- UINT32 owner_id;
- UINT32 attributes;
- UINT32 disk_id;
- UINT32 format_flags;
- UINT32 bootstrap_lsn;
- UINT32 bootstrap_size;
- UINT32 sector_size;
-
- unsigned int sides : 2;
- unsigned int double_density : 1;
- unsigned int double_track : 1;
- unsigned int quad_track_density : 1;
- unsigned int octal_track_density : 1;
-
- char name[33];
- UINT8 *allocation_bitmap;
-};
-
-
-struct os9_fileinfo
-{
- unsigned int directory : 1;
- unsigned int non_sharable : 1;
- unsigned int public_execute : 1;
- unsigned int public_write : 1;
- unsigned int public_read : 1;
- unsigned int user_execute : 1;
- unsigned int user_write : 1;
- unsigned int user_read : 1;
-
- UINT32 lsn;
- UINT32 owner_id;
- UINT32 link_count;
- UINT32 file_size;
-
- struct
- {
- UINT32 lsn;
- UINT32 count;
- } sector_map[48];
-};
-
-
-struct os9_direnum
-{
- struct os9_fileinfo dir_info;
- UINT32 index;
-};
-
-
-
-static void pick_string(const void *ptr, size_t offset, size_t length, char *dest)
-{
- UINT8 b;
-
- while(length--)
- {
- b = ((UINT8 *) ptr)[offset++];
- *(dest++) = b & 0x7F;
- if (b & 0x80)
- length = 0;
- }
- *dest = '\0';
-}
-
-
-
-static void place_string(void *ptr, size_t offset, size_t length, const char *s)
-{
- size_t i;
- UINT8 b;
- UINT8 *bptr;
-
- bptr = (UINT8 *) ptr;
- bptr += offset;
-
- bptr[0] = 0x80;
-
- for (i = 0; s[i] && (i < length); i++)
- {
- b = ((UINT8) s[i]) & 0x7F;
- if (s[i+1] == '\0')
- b |= 0x80;
- bptr[i] = b;
- }
-}
-
-
-
-static os9_diskinfo *os9_get_diskinfo(imgtool_image *image)
-{
- return (os9_diskinfo *) imgtool_floppy_extrabytes(image);
-}
-
-
-
-static struct os9_direnum *os9_get_dirinfo(imgtool_directory *directory)
-{
- return (struct os9_direnum *) imgtool_directory_extrabytes(directory);
-}
-
-
-
-static imgtoolerr_t os9_locate_lsn(imgtool_image *image, UINT32 lsn, UINT32 *head, UINT32 *track, UINT32 *sector)
-{
- const os9_diskinfo *disk_info;
-
- disk_info = os9_get_diskinfo(image);
- if (lsn > disk_info->total_sectors)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- *track = lsn / (disk_info->sectors_per_track * disk_info->sides);
- *head = (lsn / disk_info->sectors_per_track) % disk_info->sides;
- *sector = (lsn % disk_info->sectors_per_track) + 1;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t os9_read_lsn(imgtool_image *img, UINT32 lsn, int offset, void *buffer, size_t buffer_len)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- UINT32 head, track, sector;
-
- err = os9_locate_lsn(img, lsn, &head, &track, &sector);
- if (err)
- return err;
-
- ferr = floppy_read_sector(imgtool_floppy(img), head, track, sector, offset, buffer, buffer_len);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t os9_write_lsn(imgtool_image *img, UINT32 lsn, int offset, const void *buffer, size_t buffer_len)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- UINT32 head, track, sector;
-
- err = os9_locate_lsn(img, lsn, &head, &track, &sector);
- if (err)
- return err;
-
- ferr = floppy_write_sector(imgtool_floppy(img), head, track, sector, offset, buffer, buffer_len, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static UINT32 os9_lookup_lsn(imgtool_image *img,
- const struct os9_fileinfo *file_info, UINT32 *index)
-{
- int i;
- UINT32 lsn;
- const os9_diskinfo *disk_info;
-
- disk_info = os9_get_diskinfo(img);
- lsn = *index / disk_info->sector_size;
-
- i = 0;
- while(lsn >= file_info->sector_map[i].count)
- lsn -= file_info->sector_map[i++].count;
-
- lsn = file_info->sector_map[i].lsn + lsn;
- *index %= disk_info->sector_size;
- return lsn;
-}
-
-
-
-static int os9_interpret_dirent(void *entry, char **filename, UINT32 *lsn, int *corrupt)
-{
- int i;
- char *entry_b = (char *) entry;
-
- *filename = NULL;
- *lsn = 0;
- if (corrupt)
- *corrupt = FALSE;
-
- if (entry_b[28] != '\0')
- {
- if (corrupt)
- *corrupt = TRUE;
- }
-
- for (i = 0; (i < 28) && !(entry_b[i] & 0x80); i++)
- ;
- entry_b[i] &= 0x7F;
- entry_b[i+1] = '\0';
-
- *lsn = pick_integer_be(entry, 29, 3);
- if (strcmp(entry_b, ".") && strcmp(entry_b, ".."))
- *filename = entry_b;
- return *filename != NULL;
-}
-
-
-
-/*-------------------------------------------------
- os9_decode_file_header - reads a file/directory
- entry from an LSN, and decodes it
--------------------------------------------------*/
-
-static imgtoolerr_t os9_decode_file_header(imgtool_image *image,
- int lsn, struct os9_fileinfo *info)
-{
- imgtoolerr_t err;
- UINT32 attributes, count;
- int max_entries, i;
- const os9_diskinfo *disk_info;
- UINT8 header[256];
-
- disk_info = os9_get_diskinfo(image);
-
- err = os9_read_lsn(image, lsn, 0, header, sizeof(header));
- if (err)
- return err;
-
- info->lsn = lsn;
- attributes = pick_integer_be(header, 0, 1);
- info->owner_id = pick_integer_be(header, 1, 2);
- info->link_count = pick_integer_be(header, 8, 1);
- info->file_size = pick_integer_be(header, 9, 4);
- info->directory = (attributes & 0x80) ? 1 : 0;
- info->non_sharable = (attributes & 0x40) ? 1 : 0;
- info->public_execute = (attributes & 0x20) ? 1 : 0;
- info->public_write = (attributes & 0x10) ? 1 : 0;
- info->public_read = (attributes & 0x08) ? 1 : 0;
- info->user_execute = (attributes & 0x04) ? 1 : 0;
- info->user_write = (attributes & 0x02) ? 1 : 0;
- info->user_read = (attributes & 0x01) ? 1 : 0;
-
- if (info->directory && (info->file_size % 32 != 0))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* read all sector map entries */
- max_entries = (disk_info->sector_size - 16) / 5;
- max_entries = MIN(max_entries, ARRAY_LENGTH(info->sector_map) - 1);
- for (i = 0; i < max_entries; i++)
- {
- lsn = pick_integer_be(header, 16 + (i * 5) + 0, 3);
- count = pick_integer_be(header, 16 + (i * 5) + 3, 2);
- if (count <= 0)
- break;
-
- info->sector_map[i].lsn = lsn;
- info->sector_map[i].count = count;
- }
- info->sector_map[i].lsn = 0;
- info->sector_map[i].count = 0;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t os9_allocate_lsn(imgtool_image *image, UINT32 *lsn)
-{
- UINT32 i;
- os9_diskinfo *disk_info;
- UINT8 b, mask;
-
- disk_info = os9_get_diskinfo(image);
-
- for (i = 0; i < disk_info->total_sectors; i++)
- {
- b = disk_info->allocation_bitmap[i / 8];
- mask = 1 << (7 - (i % 8));
-
- if ((b & mask) == 0)
- {
- disk_info->allocation_bitmap[i / 8] |= mask;
- *lsn = i;
- return os9_write_lsn(image, 1, 0, disk_info->allocation_bitmap, disk_info->allocation_bitmap_bytes);
- }
- }
- return IMGTOOLERR_NOSPACE;
-}
-
-
-
-static imgtoolerr_t os9_deallocate_lsn(imgtool_image *image, UINT32 lsn)
-{
- UINT8 mask;
- os9_diskinfo *disk_info;
-
- disk_info = os9_get_diskinfo(image);
- mask = 1 << (7 - (lsn % 8));
- disk_info->allocation_bitmap[lsn / 8] &= ~mask;
- return os9_write_lsn(image, 1, 0, disk_info->allocation_bitmap, disk_info->allocation_bitmap_bytes);
-}
-
-
-
-static UINT32 os9_get_free_lsns(imgtool_image *image)
-{
- const os9_diskinfo *disk_info;
- UINT32 i, free_lsns;
- UINT8 b;
-
- disk_info = os9_get_diskinfo(image);
- free_lsns = 0;
-
- for (i = 0; i < disk_info->total_sectors; i++)
- {
- b = disk_info->allocation_bitmap[i / 8];
- b >>= (7 - (i % 8));
- free_lsns += ~b & 1;
- }
-
- return free_lsns;
-}
-
-
-
-static imgtoolerr_t os9_corrupt_file_error(const struct os9_fileinfo *file_info)
-{
- imgtoolerr_t err;
- if (file_info->directory)
- err = IMGTOOLERR_CORRUPTDIR;
- else
- err = IMGTOOLERR_CORRUPTFILE;
- return err;
-}
-
-
-
-static imgtoolerr_t os9_set_file_size(imgtool_image *image,
- struct os9_fileinfo *file_info, UINT32 new_size)
-{
- imgtoolerr_t err;
- const os9_diskinfo *disk_info;
- UINT32 new_lsn_count, current_lsn_count;
- UINT32 free_lsns, lsn, i;
- int sector_map_length = -1;
- UINT8 header[256];
-
- /* easy way out? */
- if (file_info->file_size == new_size)
- return IMGTOOLERR_SUCCESS;
-
- disk_info = os9_get_diskinfo(image);
-
- free_lsns = os9_get_free_lsns(image);
- current_lsn_count = (file_info->file_size + disk_info->sector_size - 1) / disk_info->sector_size;
- new_lsn_count = (new_size + disk_info->sector_size - 1) / disk_info->sector_size;
-
- /* check to see if the file is growing and we do not have enough space */
- if ((new_lsn_count > current_lsn_count) && (new_lsn_count - current_lsn_count > free_lsns))
- return IMGTOOLERR_NOSPACE;
-
- if (current_lsn_count != new_lsn_count)
- {
- /* first find out the size of our sector map */
- sector_map_length = 0;
- lsn = 0;
- while((lsn < current_lsn_count) && (sector_map_length < ARRAY_LENGTH(file_info->sector_map)))
- {
- if (file_info->sector_map[sector_map_length].count == 0)
- return os9_corrupt_file_error(file_info);
-
- lsn += file_info->sector_map[sector_map_length].count;
- sector_map_length++;
- }
-
- /* keep in mind that the sector_map might not parallel our expected
- * current LSN count; we should tolerate this abnormality */
- current_lsn_count = lsn;
-
- while(current_lsn_count > new_lsn_count)
- {
- /* shrink this file */
- lsn = file_info->sector_map[sector_map_length - 1].lsn +
- file_info->sector_map[sector_map_length - 1].count - 1;
-
- err = os9_deallocate_lsn(image, lsn);
- if (err)
- return err;
-
- file_info->sector_map[sector_map_length - 1].count--;
- while(sector_map_length > 0 && (file_info->sector_map[sector_map_length - 1].count == 0))
- sector_map_length--;
- current_lsn_count--;
- }
-
- while(current_lsn_count < new_lsn_count)
- {
- /* grow this file */
- err = os9_allocate_lsn(image, &lsn);
- if (err)
- return err;
-
- if ((sector_map_length > 0) && ((file_info->sector_map[sector_map_length - 1].lsn +
- file_info->sector_map[sector_map_length - 1].count) == lsn))
- {
- file_info->sector_map[sector_map_length - 1].count++;
- }
- else if (sector_map_length >= ARRAY_LENGTH(file_info->sector_map))
- {
- return IMGTOOLERR_NOSPACE;
- }
- else
- {
- file_info->sector_map[sector_map_length].lsn = lsn;
- file_info->sector_map[sector_map_length].count = 1;
- sector_map_length++;
- file_info->sector_map[sector_map_length].lsn = 0;
- file_info->sector_map[sector_map_length].count = 0;
- }
- current_lsn_count++;
- }
- }
-
- /* now lets write back the sector */
- err = os9_read_lsn(image, file_info->lsn, 0, header, sizeof(header));
- if (err)
- return err;
-
- file_info->file_size = new_size;
- place_integer_be(header, 9, 4, file_info->file_size);
-
- /* do we have to write the sector map? */
- if (sector_map_length >= 0)
- {
- for (i = 0; i < MIN(sector_map_length + 1, ARRAY_LENGTH(file_info->sector_map)); i++)
- {
- place_integer_be(header, 16 + (i * 5) + 0, 3, file_info->sector_map[i].lsn);
- place_integer_be(header, 16 + (i * 5) + 3, 2, file_info->sector_map[i].count);
- }
- }
-
- err = os9_write_lsn(image, file_info->lsn, 0, header, disk_info->sector_size);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*-------------------------------------------------
- os9_lookup_path - walks an OS-9 directory
- structure to find a file, or optionally, create
- a file
--------------------------------------------------*/
-
-static imgtoolerr_t os9_lookup_path(imgtool_image *img, const char *path,
- creation_policy_t create, struct os9_fileinfo *file_info,
- UINT32 *parent_lsn, UINT32 *dirent_lsn, UINT32 *dirent_index)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- struct os9_fileinfo dir_info;
- UINT32 index, current_lsn, dir_size;
- UINT32 entry_index = 0;
- UINT32 free_entry_index = 0xffffffff;
- UINT32 entry_lsn = 0;
- UINT32 allocated_lsn = 0;
- UINT8 entry[32];
- UINT8 block[64];
- char *filename;
- const os9_diskinfo *disk_info;
-
- disk_info = os9_get_diskinfo(img);
- current_lsn = disk_info->root_dir_lsn;
-
- if (parent_lsn)
- *parent_lsn = 0;
-
- /* we have to transverse each path element */
- while(*path)
- {
- if (parent_lsn)
- *parent_lsn = current_lsn;
-
- /* decode the directory header of this directory */
- err = os9_decode_file_header(img, current_lsn, &dir_info);
- if (err)
- goto done;
- dir_size = dir_info.file_size;
-
- /* sanity check directory */
- if (!dir_info.directory)
- {
- err = (current_lsn == disk_info->root_dir_lsn) ? IMGTOOLERR_CORRUPTIMAGE : IMGTOOLERR_INVALIDPATH;
- goto done;
- }
-
- /* walk the directory */
- for (index = 0; index < dir_size; index += 32)
- {
- entry_index = index;
- entry_lsn = os9_lookup_lsn(img, &dir_info, &entry_index);
-
- err = os9_read_lsn(img, entry_lsn, entry_index, entry, sizeof(entry));
- if (err)
- goto done;
-
- /* remember first free entry found */
- if( free_entry_index == 0xffffffff )
- {
- if( entry[0] == 0 )
- free_entry_index = index;
- }
-
- if (os9_interpret_dirent(entry, &filename, &current_lsn, NULL))
- {
- if (!strcmp(path, filename))
- break;
- }
-
- }
-
- /* at the end of the file? */
- if (index >= dir_size)
- {
- /* if we're not creating, or we are creating but we have not fully
- * transversed the directory, error out */
- if (!create || path[strlen(path) + 1])
- {
- err = IMGTOOLERR_PATHNOTFOUND;
- goto done;
- }
-
- /* allocate a new LSN */
- err = os9_allocate_lsn(img, &allocated_lsn);
- if (err)
- goto done;
-
- /* write the file */
- memset(block, 0, sizeof(block));
- place_integer_be(block, 0, 1, 0x1B | ((create == CREATE_DIR) ? 0x80 : 0x00));
- err = os9_write_lsn(img, allocated_lsn, 0, block, sizeof(block));
- if (err)
- goto done;
-
- if( free_entry_index == 0xffffffff )
- {
- /* expand the directory to hold the new entry */
- err = os9_set_file_size(img, &dir_info, dir_size + 32);
- if (err)
- goto done;
- }
- else
- /* use first unused entry in directory */
- dir_size = free_entry_index;
-
- /* now prepare the directory entry */
- memset(entry, 0, sizeof(entry));
- place_string(entry, 0, 28, path);
- place_integer_be(entry, 29, 3, allocated_lsn);
-
- /* now write the directory entry */
- entry_index = dir_size;
- entry_lsn = os9_lookup_lsn(img, &dir_info, &entry_index);
- err = os9_write_lsn(img, entry_lsn, entry_index, entry, 32);
- if (err)
- goto done;
-
- /* directory entry append complete; no need to hold this lsn */
- current_lsn = allocated_lsn;
- allocated_lsn = 0;
- }
- path += strlen(path) + 1;
- }
-
- if (file_info)
- {
- err = os9_decode_file_header(img, current_lsn, file_info);
- if (err)
- goto done;
- }
-
- if (dirent_lsn)
- *dirent_lsn = entry_lsn;
- if (dirent_index)
- *dirent_index = entry_index;
-
-done:
- if (allocated_lsn != 0)
- os9_deallocate_lsn(img, allocated_lsn);
- return err;
-}
-
-
-
-static imgtoolerr_t os9_diskimage_open(imgtool_image *image, imgtool_stream *stream)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- os9_diskinfo *info;
- UINT32 track_size_in_sectors, i; //, attributes;
- UINT8 header[256];
- UINT32 allocation_bitmap_lsns;
- UINT8 b, mask;
-
- info = os9_get_diskinfo(image);
-
- ferr = floppy_read_sector(imgtool_floppy(image), 0, 0, 1, 0, header, sizeof(header));
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- info->total_sectors = pick_integer_be(header, 0, 3);
- track_size_in_sectors = pick_integer_be(header, 3, 1);
- info->allocation_bitmap_bytes = pick_integer_be(header, 4, 2);
- info->cluster_size = pick_integer_be(header, 6, 2);
- info->root_dir_lsn = pick_integer_be(header, 8, 3);
- info->owner_id = pick_integer_be(header, 11, 2);
-// attributes =
- pick_integer_be(header, 13, 1);
- info->disk_id = pick_integer_be(header, 14, 2);
- info->format_flags = pick_integer_be(header, 16, 1);
- info->sectors_per_track = pick_integer_be(header, 17, 2);
- info->bootstrap_lsn = pick_integer_be(header, 21, 3);
- info->bootstrap_size = pick_integer_be(header, 24, 2);
- info->sector_size = pick_integer_be(header, 104, 2);
-
- info->sides = (info->format_flags & 0x01) ? 2 : 1;
- info->double_density = (info->format_flags & 0x02) ? 1 : 0;
- info->double_track = (info->format_flags & 0x04) ? 1 : 0;
- info->quad_track_density = (info->format_flags & 0x08) ? 1 : 0;
- info->octal_track_density = (info->format_flags & 0x10) ? 1 : 0;
-
- pick_string(header, 31, 32, info->name);
-
- if (info->sector_size == 0)
- info->sector_size = 256;
-
- /* does the root directory and allocation bitmap collide? */
- allocation_bitmap_lsns = (info->allocation_bitmap_bytes + info->sector_size - 1) / info->sector_size;
- if (1 + allocation_bitmap_lsns > info->root_dir_lsn)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* is the allocation bitmap too big? */
- info->allocation_bitmap = (UINT8*)imgtool_image_malloc(image, info->allocation_bitmap_bytes);
- if (!info->allocation_bitmap)
- return IMGTOOLERR_OUTOFMEMORY;
- memset(info->allocation_bitmap, 0, info->allocation_bitmap_bytes);
-
- /* sectors per track and track size don't jive? */
- if (info->sectors_per_track != track_size_in_sectors)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* zero sectors per track? */
- if (info->sectors_per_track == 0)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* do we have an odd number of sectors? */
- if (info->total_sectors % info->sectors_per_track)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* read the allocation bitmap */
- for (i = 0; i < allocation_bitmap_lsns; i++)
- {
- err = os9_read_lsn(image, 1 + i, 0, &info->allocation_bitmap[i * info->sector_size],
- MIN(info->allocation_bitmap_bytes - (i * info->sector_size), info->sector_size));
- if (err)
- return err;
- }
-
- /* check to make sure that the allocation bitmap and root sector are reserved */
- for (i = 0; i <= allocation_bitmap_lsns; i++)
- {
- b = info->allocation_bitmap[i / 8];
- mask = 1 << (7 - (i % 8));
- if ((b & mask) == 0)
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t os9_diskimage_create(imgtool_image *img, imgtool_stream *stream, option_resolution *opts)
-{
- imgtoolerr_t err;
- dynamic_buffer header;
- UINT32 heads, tracks, sectors, sector_bytes, first_sector_id;
- UINT32 cluster_size, owner_id;
- UINT32 allocation_bitmap_bits, allocation_bitmap_lsns;
- UINT32 attributes, format_flags, disk_id;
- UINT32 i;
- INT32 total_allocated_sectors;
- const char *title;
- time_t t;
- struct tm *ltime;
-
- time(&t);
- ltime = localtime(&t);
-
- heads = option_resolution_lookup_int(opts, 'H');
- tracks = option_resolution_lookup_int(opts, 'T');
- sectors = option_resolution_lookup_int(opts, 'S');
- sector_bytes = option_resolution_lookup_int(opts, 'L');
- first_sector_id = option_resolution_lookup_int(opts, 'F');
- title = "";
-
- header.resize(sector_bytes);
-
- if (sector_bytes > 256)
- sector_bytes = 256;
- cluster_size = 1;
- owner_id = 1;
- disk_id = 1;
- attributes = 0;
- allocation_bitmap_bits = heads * tracks * sectors / cluster_size;
- allocation_bitmap_lsns = (allocation_bitmap_bits / 8 + sector_bytes - 1) / sector_bytes;
- format_flags = ((heads > 1) ? 0x01 : 0x00) | ((tracks > 40) ? 0x02 : 0x00);
-
- memset(&header[0], 0, sector_bytes);
- place_integer_be(&header[0], 0, 3, heads * tracks * sectors);
- place_integer_be(&header[0], 3, 1, sectors);
- place_integer_be(&header[0], 4, 2, (allocation_bitmap_bits + 7) / 8);
- place_integer_be(&header[0], 6, 2, cluster_size);
- place_integer_be(&header[0], 8, 3, 1 + allocation_bitmap_lsns);
- place_integer_be(&header[0], 11, 2, owner_id);
- place_integer_be(&header[0], 13, 1, attributes);
- place_integer_be(&header[0], 14, 2, disk_id);
- place_integer_be(&header[0], 16, 1, format_flags);
- place_integer_be(&header[0], 17, 2, sectors);
- place_string(&header[0], 31, 32, title);
- place_integer_be(&header[0], 103, 2, sector_bytes / 256);
-
- /* path descriptor options */
- place_integer_be(&header[0], 0x3f+0x00, 1, 1); /* device class */
- place_integer_be(&header[0], 0x3f+0x01, 1, 1); /* drive number */
- place_integer_be(&header[0], 0x3f+0x03, 1, 0x20); /* device type */
- place_integer_be(&header[0], 0x3f+0x04, 1, 1); /* density capability */
- place_integer_be(&header[0], 0x3f+0x05, 2, tracks); /* number of tracks */
- place_integer_be(&header[0], 0x3f+0x07, 1, heads); /* number of sides */
- place_integer_be(&header[0], 0x3f+0x09, 2, sectors); /* sectors per track */
- place_integer_be(&header[0], 0x3f+0x0b, 2, sectors); /* sectors on track zero */
- place_integer_be(&header[0], 0x3f+0x0d, 1, 3); /* sector interleave factor */
- place_integer_be(&header[0], 0x3f+0x0e, 1, 8); /* default sectors per allocation */
-
- err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */
- if (err)
- goto done;
-
- total_allocated_sectors = 1 + allocation_bitmap_lsns + 1 + 7;
-
- for (i = 0; i < allocation_bitmap_lsns; i++)
- {
- memset(&header[0], 0x00, sector_bytes);
-
- if (total_allocated_sectors > (8 * 256))
- {
- memset(&header[0], 0xff, sector_bytes);
- total_allocated_sectors -= (8 * 256);
- }
- else if (total_allocated_sectors > 1 )
- {
- int offset;
- UINT8 mask;
-
- while( total_allocated_sectors >= 0 )
- {
- offset = total_allocated_sectors / 8;
- mask = 1 << (7 - ( total_allocated_sectors % 8 ) );
-
- header[offset] |= mask;
- total_allocated_sectors--;
- }
- }
-
- err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 1 + i, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */
- if (err)
- goto done;
- }
-
- memset(&header[0], 0, sector_bytes);
- header[0x00] = 0xBF;
- header[0x01] = 0x00;
- header[0x02] = 0x00;
- header[0x03] = (UINT8) ltime->tm_year;
- header[0x04] = (UINT8) ltime->tm_mon + 1;
- header[0x05] = (UINT8) ltime->tm_mday;
- header[0x06] = (UINT8) ltime->tm_hour;
- header[0x07] = (UINT8) ltime->tm_min;
- header[0x08] = 0x02;
- header[0x09] = 0x00;
- header[0x0A] = 0x00;
- header[0x0B] = 0x00;
- header[0x0C] = 0x40;
- header[0x0D] = (UINT8) (ltime->tm_year % 100);
- header[0x0E] = (UINT8) ltime->tm_mon;
- header[0x0F] = (UINT8) ltime->tm_mday;
- place_integer_be(&header[0], 0x10, 3, 1 + allocation_bitmap_lsns + 1);
- place_integer_be(&header[0], 0x13, 2, 8);
-
- err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 1 + allocation_bitmap_lsns, 0, &header[0], sector_bytes, 0); /* TODO: pass ddam argument from imgtool */
- if (err)
- goto done;
-
- memset(&header[0], 0, sector_bytes);
- header[0x00] = 0x2E;
- header[0x01] = 0xAE;
- header[0x1F] = 1 + allocation_bitmap_lsns;
- header[0x20] = 0xAE;
- header[0x3F] = 1 + allocation_bitmap_lsns;
- err = (imgtoolerr_t)floppy_write_sector(imgtool_floppy(img), 0, 0, first_sector_id + 2 + allocation_bitmap_lsns, 0, &header[0], sector_bytes, 0); /* TOOD: pass ddam argument from imgtool */
- if (err)
- goto done;
-
-done:
- return err;
-}
-
-
-
-static imgtoolerr_t os9_diskimage_beginenum(imgtool_directory *enumeration, const char *path)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- struct os9_direnum *os9enum;
- imgtool_image *image;
-
- image = imgtool_directory_image(enumeration);
- os9enum = os9_get_dirinfo(enumeration);
-
- err = os9_lookup_path(image, path, CREATE_NONE, &os9enum->dir_info, NULL, NULL, NULL);
- if (err)
- goto done;
-
- /* this had better be a directory */
- if (!os9enum->dir_info.directory)
- {
- err = IMGTOOLERR_CORRUPTIMAGE;
- goto done;
- }
-
-done:
- return err;
-}
-
-
-
-static imgtoolerr_t os9_diskimage_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- struct os9_direnum *os9enum;
- UINT32 lsn, index;
- imgtoolerr_t err;
- UINT8 dir_entry[32];
- char filename[29];
- struct os9_fileinfo file_info;
- imgtool_image *image;
-
- image = imgtool_directory_image(enumeration);
- os9enum = os9_get_dirinfo(enumeration);
-
- do
- {
- /* check for EOF */
- if (os9enum->index >= os9enum->dir_info.file_size)
- {
- ent->eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- /* locate the LSN and offset for this directory entry */
- index = os9enum->index;
- lsn = os9_lookup_lsn(image, &os9enum->dir_info, &index);
-
- /* read the directory entry out of the lSN */
- err = os9_read_lsn(image, lsn, index, dir_entry, sizeof(dir_entry));
- if (err)
- return err;
-
- if (dir_entry[0])
- {
- /* read the file or directory name */
- pick_string(dir_entry, 0, 28, filename);
-
- /* we have certain expectations of the directory contents; the
- * first directory entry should be "..", the second ".", and
- * subsequent entries should never be "." or ".." */
- switch(os9enum->index)
- {
- case 0:
- if (strcmp(filename, ".."))
- imgtool_warn("First entry in directory should be \"..\" and not \"%s\"", filename);
- break;
-
- case 32:
- if (strcmp(filename, "."))
- imgtool_warn("Second entry in directory should be \".\" and not \"%s\"", filename);
- break;
-
- default:
- if (!strcmp(filename, ".") || !strcmp(filename, ".."))
- imgtool_warn("Directory entry %d should not be \"%s\"", index / 32, filename);
- break;
- }
-
- /* if the filename is ".", the file should point to the current directory */
- if (!strcmp(filename, ".") && (pick_integer_be(dir_entry, 29, 3) != os9enum->dir_info.lsn))
- {
- imgtool_warn("Directory \".\" does not point back to same directory");
- }
- }
- else
- {
- /* no more directory entries */
- filename[0] = '\0';
- }
-
- /* move on to the next directory entry */
- os9enum->index += 32;
- }
- while(!filename[0] || !strcmp(filename, ".") || !strcmp(filename, ".."));
-
- /* read file attributes */
- lsn = pick_integer_be(dir_entry, 29, 3);
- err = os9_decode_file_header(imgtool_directory_image(enumeration), lsn, &file_info);
- if (err)
- return err;
-
- /* fill out imgtool_dirent structure */
- snprintf(ent->filename, ARRAY_LENGTH(ent->filename), "%s", filename);
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "%c%c%c%c%c%c%c%c",
- file_info.directory ? 'd' : '-',
- file_info.non_sharable ? 's' : '-',
- file_info.public_execute ? 'x' : '-',
- file_info.public_write ? 'w' : '-',
- file_info.public_read ? 'r' : '-',
- file_info.user_execute ? 'x' : '-',
- file_info.user_write ? 'w' : '-',
- file_info.user_read ? 'r' : '-');
-
- ent->directory = file_info.directory;
- ent->corrupt = (dir_entry[28] != 0);
- ent->filesize = file_info.file_size;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t os9_diskimage_freespace(imgtool_partition *partition, UINT64 *size)
-{
- imgtool_image *image = imgtool_partition_image(partition);
- const os9_diskinfo *disk_info;
- UINT32 free_lsns;
-
- disk_info = os9_get_diskinfo(image);
- free_lsns = os9_get_free_lsns(image);
-
- *size = free_lsns * disk_info->sector_size;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t os9_diskimage_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- imgtoolerr_t err;
- imgtool_image *img = imgtool_partition_image(partition);
- const os9_diskinfo *disk_info;
- struct os9_fileinfo file_info;
- UINT8 buffer[256];
- int i, j;
- UINT32 file_size;
- UINT32 used_size;
-
- disk_info = os9_get_diskinfo(img);
-
- err = os9_lookup_path(img, filename, CREATE_NONE, &file_info, NULL, NULL, NULL);
- if (err)
- return err;
- if (file_info.directory)
- return IMGTOOLERR_FILENOTFOUND;
- file_size = file_info.file_size;
-
- for (i = 0; file_info.sector_map[i].count > 0; i++)
- {
- for (j = 0; j < file_info.sector_map[i].count; j++)
- {
- used_size = MIN(file_size, disk_info->sector_size);
- err = os9_read_lsn(img, file_info.sector_map[i].lsn + j, 0,
- buffer, used_size);
- if (err)
- return err;
- stream_write(destf, buffer, used_size);
- file_size -= used_size;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t os9_diskimage_writefile(imgtool_partition *partition, const char *path, const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- struct os9_fileinfo file_info;
- size_t write_size;
- dynamic_buffer buf;
- int i = -1;
- UINT32 lsn = 0;
- UINT32 count = 0;
- UINT32 sz;
- const os9_diskinfo *disk_info;
-
- disk_info = os9_get_diskinfo(image);
-
- buf.resize(disk_info->sector_size);
-
- err = os9_lookup_path(image, path, CREATE_FILE, &file_info, NULL, NULL, NULL);
- if (err)
- goto done;
-
- sz = (UINT32) stream_size(sourcef);
-
- err = os9_set_file_size(image, &file_info, sz);
- if (err)
- goto done;
-
- while(sz > 0)
- {
- write_size = (size_t) MIN(sz, (UINT64) disk_info->sector_size);
-
- stream_read(sourcef, &buf[0], write_size);
-
- while(count == 0)
- {
- i++;
- lsn = file_info.sector_map[i].lsn;
- count = file_info.sector_map[i].count;
- }
-
- err = os9_write_lsn(image, lsn, 0, &buf[0], write_size);
- if (err)
- goto done;
-
- lsn++;
- count--;
- sz -= write_size;
- }
-
-done:
- return err;
-}
-
-
-
-static imgtoolerr_t os9_diskimage_delete(imgtool_partition *partition, const char *path,
- unsigned int delete_directory)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- //const os9_diskinfo *disk_info;
- struct os9_fileinfo file_info;
- UINT32 dirent_lsn, dirent_index;
- UINT32 entry_lsn, entry_index;
- UINT32 i, j, lsn;
- UINT8 b;
-
- //disk_info = os9_get_diskinfo(image);
-
- err = os9_lookup_path(image, path, CREATE_NONE, &file_info, NULL, &dirent_lsn, &dirent_index);
- if (err)
- return err;
- if (file_info.directory != delete_directory)
- return IMGTOOLERR_FILENOTFOUND;
-
- /* make sure that if we are deleting a directory, it is empty */
- if (delete_directory)
- {
- for (i = 64; i < file_info.file_size; i += 32)
- {
- entry_index = i;
- entry_lsn = os9_lookup_lsn(image, &file_info, &entry_index);
-
- err = os9_read_lsn(image, entry_lsn, entry_index, &b, 1);
- if (err)
- return err;
-
- /* this had better be a deleted file, if not we can't delete */
- if (b != 0)
- return IMGTOOLERR_DIRNOTEMPTY;
- }
- }
-
- /* zero out the file entry */
- b = '\0';
- err = os9_write_lsn(image, dirent_lsn, dirent_index, &b, 1);
- if (err)
- return err;
-
- /* get the link count */
- err = os9_read_lsn(image, file_info.lsn, 8, &b, 1);
- if (err)
- return err;
-
- if (b > 0)
- b--;
- if (b > 0)
- {
- /* link count is greater than zero */
- err = os9_write_lsn(image, file_info.lsn, 8, &b, 1);
- if (err)
- return err;
- }
- else
- {
- /* no more links; outright delete the file */
- err = os9_deallocate_lsn(image, file_info.lsn);
- if (err)
- return err;
-
- for (i = 0; (i < ARRAY_LENGTH(file_info.sector_map)) && file_info.sector_map[i].count; i++)
- {
- lsn = file_info.sector_map[i].lsn;
- for (j = 0; j < file_info.sector_map[i].count; j++)
- {
- err = os9_deallocate_lsn(image, lsn + j);
- if (err)
- return err;
- }
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t os9_diskimage_deletefile(imgtool_partition *partition, const char *path)
-{
- return os9_diskimage_delete(partition, path, 0);
-}
-
-
-
-static imgtoolerr_t os9_diskimage_createdir(imgtool_partition *partition, const char *path)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- struct os9_fileinfo file_info;
- UINT8 dir_data[64];
- UINT32 parent_lsn;
-
- err = os9_lookup_path(image, path, CREATE_DIR, &file_info, &parent_lsn, NULL, NULL);
- if (err)
- goto done;
-
- err = os9_set_file_size(image, &file_info, 64);
- if (err)
- goto done;
-
- /* create intial directories */
- memset(dir_data, 0, sizeof(dir_data));
- place_string(dir_data, 0, 32, "..");
- place_integer_be(dir_data, 29, 3, parent_lsn);
- place_string(dir_data, 32, 32, ".");
- place_integer_be(dir_data, 61, 3, file_info.lsn);
-
- err = os9_write_lsn(image, file_info.sector_map[0].lsn, 0, dir_data, sizeof(dir_data));
- if (err)
- goto done;
-
-done:
- return err;
-}
-
-
-
-static imgtoolerr_t os9_diskimage_deletedir(imgtool_partition *partition, const char *path)
-{
- return os9_diskimage_delete(partition, path, 1);
-}
-
-
-
-void os9_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_INITIAL_PATH_SEPARATOR: info->i = 1; break;
- case IMGTOOLINFO_INT_OPEN_IS_STRICT: info->i = 1; break;
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(os9_diskinfo); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct os9_direnum); break;
- case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = '/'; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "os9"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "OS-9 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;
-
- /* --- 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_FLOPPY_CREATE: info->create = os9_diskimage_create; break;
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = os9_diskimage_open; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = os9_diskimage_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = os9_diskimage_nextenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = os9_diskimage_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = os9_diskimage_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = os9_diskimage_writefile; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = os9_diskimage_deletefile; break;
- case IMGTOOLINFO_PTR_CREATE_DIR: info->create_dir = os9_diskimage_createdir; break;
- case IMGTOOLINFO_PTR_DELETE_DIR: info->delete_dir = os9_diskimage_deletedir; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_coco; break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/pc_flop.c b/src/mess/tools/imgtool/modules/pc_flop.c
deleted file mode 100644
index 916cf873c46..00000000000
--- a/src/mess/tools/imgtool/modules/pc_flop.c
+++ /dev/null
@@ -1,173 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- pc_flop.c
-
- PC floppies
-
-****************************************************************************/
-
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/pc_dsk.h"
-#include "fat.h"
-#include "iflopimg.h"
-
-#define FAT_SECLEN 512
-
-
-static imgtoolerr_t fat_image_create(imgtool_image *image, imgtool_stream *stream, option_resolution *opts)
-{
- imgtoolerr_t err;
- UINT32 tracks, heads, sectors;
- UINT8 buffer[FAT_SECLEN];
- imgtool_class imgclass = { fat_get_info };
- imgtoolerr_t (*fat_partition_create)(imgtool_image *image, UINT64 first_block, UINT64 block_count);
-
- tracks = option_resolution_lookup_int(opts, 'T');
- heads = option_resolution_lookup_int(opts, 'H');
- sectors = option_resolution_lookup_int(opts, 'S');
-
- /* set up just enough of a boot sector to specify geometry */
- memset(buffer, 0, sizeof(buffer));
- place_integer_le(buffer, 24, 2, sectors);
- place_integer_le(buffer, 26, 2, heads);
- place_integer_le(buffer, 19, 2, (UINT16) (((UINT64) tracks * heads * sectors) >> 0));
- place_integer_le(buffer, 32, 4, (UINT16) (((UINT64) tracks * heads * sectors) >> 16));
- err = imgtool_image_write_block(image, 0, buffer);
- if (err)
- goto done;
-
- /* load fat_partition_create */
- fat_partition_create = (imgtoolerr_t (*)(imgtool_image *, UINT64, UINT64))
- imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_CREATE_PARTITION);
-
- /* actually create the partition */
- err = fat_partition_create(image, 0, ((UINT64) tracks) * heads * sectors);
- if (err)
- goto done;
-
-done:
- return err;
-}
-
-
-
-static imgtoolerr_t fat_image_get_geometry(imgtool_image *image, UINT32 *tracks, UINT32 *heads, UINT32 *sectors)
-{
- imgtoolerr_t err;
- UINT64 total_sectors;
- UINT8 buffer[FAT_SECLEN];
-
- err = imgtool_image_read_block(image, 0, buffer);
- if (err)
- return err;
-
- total_sectors = pick_integer_le(buffer, 19, 2)
- | (pick_integer_le(buffer, 32, 4) << 16);
-
- *sectors = pick_integer_le(buffer, 24, 2);
- *heads = pick_integer_le(buffer, 26, 2);
- *tracks = total_sectors / *heads / *sectors;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_get_sector_position(imgtool_image *image, UINT32 sector_index,
- UINT32 *track, UINT32 *head, UINT32 *sector)
-{
- imgtoolerr_t err;
- UINT32 tracks, heads, sectors;
-
- if (sector_index == 0)
- {
- /* special case */
- *head = 0;
- *track = 0;
- *sector = 1;
- }
- else
- {
- err = imgtool_image_get_geometry(image, &tracks, &heads, &sectors);
- if (err)
- return err;
-
- *track = sector_index / sectors / heads;
- *head = (sector_index / sectors) % heads;
- *sector = 1 + (sector_index % sectors);
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_image_readblock(imgtool_image *image, void *buffer, UINT64 block)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- UINT32 track, head, sector;
- UINT32 block_size;
-
- err = imgtool_image_get_block_size(image, &block_size);
- if (err)
- return err;
-
- err = fat_get_sector_position(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_read_sector(imgtool_floppy(image), head, track, sector, 0, buffer, block_size);
- if (ferr)
- return imgtool_floppy_error(ferr);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t fat_image_writeblock(imgtool_image *image, const void *buffer, UINT64 block)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- UINT32 track, head, sector;
- UINT32 block_size;
-
- err = imgtool_image_get_block_size(image, &block_size);
- if (err)
- return err;
-
- err = fat_get_sector_position(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_write_sector(imgtool_floppy(image), head, track, sector, 0, buffer, block_size, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-void pc_floppy_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_BLOCK_SIZE: info->i = FAT_SECLEN; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "fat"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "FAT format"); 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_FLOPPY_CREATE: info->create = fat_image_create; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_pc; break;
- case IMGTOOLINFO_PTR_READ_BLOCK: info->read_block = fat_image_readblock; break;
- case IMGTOOLINFO_PTR_WRITE_BLOCK: info->write_block = fat_image_writeblock; break;
- case IMGTOOLINFO_PTR_GET_GEOMETRY: info->get_geometry = fat_image_get_geometry; break;
-
- default: fat_get_info(imgclass, state, info); break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/pc_hard.c b/src/mess/tools/imgtool/modules/pc_hard.c
deleted file mode 100644
index 915032932c7..00000000000
--- a/src/mess/tools/imgtool/modules/pc_hard.c
+++ /dev/null
@@ -1,470 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- pc_hard.c
-
- PC hard drives
-
-*****************************************************************************
-
- Master boot record format:
-
- Offset Length Description
- ------ ------ -----------
- 0 446 Boot machine code
- 446 16 Partion #1 info
- 462 16 Partion #2 info
- 478 16 Partion #3 info
- 494 16 Partion #4 info
- 510 2 Magic bytes (0x55 0xAA)
-
-
- Partition info format:
-
- Offset Length Description
- ------ ------ -----------
- 0 1 Bootable (0x80=bootable 0x00=not bootable)
- 1 1 Starting head
- 2 1 Starting sector (bits 5-0) and high bits of starting track (bits 6-5)
- 3 1 Low bits of starting track
- 4 1 Partition type:
- 0x00 Unused
- 0x?1 FAT12 (0-15 MB)
- 0x?2 XENIX
- 0x?4 FAT16 (16-32 MB)
- 0x?6 FAT16` (32 MB-2 GB)
- 0x?7 HPFS or NTFS
- 0x?A Boot Manager
- 0x?B FAT32 (512 MB-2 TB)
- 0x?C FAT32 (512 MB-2 TB LBA)
- 0x1? OS/2 Boot manager/Win95 hidden
- 0xC? DR-DOS secured partition
- 0xD? Multiuser DOS secured partition
- 0xE? SpeedStor extended partition
- 5 1 Ending head
- 6 1 Ending sector (bits 5-0) and high bits of ending track (bits 6-5)
- 7 1 Low bits of ending track
- 8 4 Sector index of beginning of partition
- 12 4 Total sectors in partition
-
-****************************************************************************/
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "imghd.h"
-
-#define FAT_SECLEN 512
-
-static OPTION_GUIDE_START( pc_chd_create_optionguide )
- OPTION_INT('T', "cylinders", "Cylinders" )
- OPTION_INT('H', "heads", "Heads" )
- OPTION_INT('S', "sectors", "Sectors" )
-OPTION_GUIDE_END
-
-static const char pc_chd_create_optionspec[] = "H1-[16]S1-[32]-63T10/20/30/40/50/60/70/80/90/[100]/110/120/130/140/150/160/170/180/190/200";
-
-static const char fat8_string[8] = { 'F', 'A', 'T', ' ', ' ', ' ', ' ', ' ' };
-static const char fat12_string[8] = { 'F', 'A', 'T', '1', '2', ' ', ' ', ' ' };
-static const char fat16_string[8] = { 'F', 'A', 'T', '1', '6', ' ', ' ', ' ' };
-//static const char fat32_string[8] = { 'F', 'A', 'T', '3', '2', ' ', ' ', ' ' };
-
-/* imports from fat.c */
-extern void fat_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info);
-
-
-struct pc_chd_image_info
-{
- struct mess_hard_disk_file hard_disk;
-
- struct
- {
- unsigned int corrupt : 1;
- UINT8 partition_type;
- UINT32 fat_bits;
- UINT32 starting_track;
- UINT32 starting_head;
- UINT32 starting_sector;
- UINT32 ending_track;
- UINT32 ending_head;
- UINT32 ending_sector;
- UINT32 sector_index;
- UINT32 total_sectors;
- } partitions[4];
-};
-
-
-
-static pc_chd_image_info *pc_chd_get_image_info(imgtool_image *image)
-{
- return (pc_chd_image_info *) imgtool_image_extra_bytes(image);
-}
-
-
-
-static void pc_chd_locate_block(imgtool_image *image, UINT64 block, UINT32 *cylinder, UINT32 *head, UINT32 *sector)
-{
- pc_chd_image_info *info;
- const hard_disk_info *hd_info;
-
- info = pc_chd_get_image_info(image);
- hd_info = imghd_get_header(&info->hard_disk);
-
- *sector = block % hd_info->sectors;
- *head = (block / hd_info->sectors) % hd_info->heads;
- *cylinder = block / hd_info->sectors / hd_info->heads;
-}
-
-
-
-static imgtoolerr_t pc_chd_partition_create(imgtool_image *image, int partition_index, UINT64 first_block, UINT64 block_count)
-{
- imgtoolerr_t err;
- UINT8 header_block[FAT_SECLEN];
- UINT8 partition_block[FAT_SECLEN];
- UINT8 partition_type;
- UINT8 *fat_type;
- UINT8 *partition_entry;
- UINT32 first_cylinder, first_head, first_sector;
- UINT32 last_cylinder, last_head, last_sector;
- imgtool_class imgclass = { fat_get_info };
- imgtoolerr_t (*fat_partition_create)(imgtool_image *image, UINT64 first_block, UINT64 block_count);
-
- /* sanity checks */
- assert((partition_index >= 0) && (partition_index <= 3));
-
- /* compute geometry */
- pc_chd_locate_block(image, first_block, &first_cylinder, &first_head, &first_sector);
- pc_chd_locate_block(image, first_block + block_count - 1, &last_cylinder, &last_head, &last_sector);
-
- /* load fat_partition_create */
- fat_partition_create = (imgtoolerr_t (*)(imgtool_image *, UINT64, UINT64))
- imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_CREATE_PARTITION);
-
- /* first create the actual partition */
- err = fat_partition_create(image, first_block, block_count);
- if (err)
- goto done;
-
- /* read the first block of the partition, to determine the type of FAT */
- err = imgtool_image_read_block(image, first_block, partition_block);
- if (err)
- goto done;
- fat_type = &partition_block[54];
- if (!memcmp(fat_type, fat8_string, sizeof(fat8_string)))
- partition_type = 0x01;
- else if (!memcmp(fat_type, fat12_string, sizeof(fat12_string)))
- partition_type = 0x01;
- else if ((!memcmp(fat_type, fat16_string, sizeof(fat16_string))) && (block_count < 32*1024*1024/FAT_SECLEN))
- partition_type = 0x04;
- else if ((!memcmp(fat_type, fat16_string, sizeof(fat16_string))) && (block_count >= 32*1024*1024/FAT_SECLEN))
- partition_type = 0x06;
- else
- partition_type = 0x0B;
-
- /* read the partition header */
- err = imgtool_image_read_block(image, 0, header_block);
- if (err)
- goto done;
-
- /* fill out the partition entry */
- partition_entry = &header_block[446 + (partition_index * 16)];
- place_integer_le(partition_entry, 0, 1, 0x80);
- place_integer_le(partition_entry, 1, 1, first_head);
- place_integer_le(partition_entry, 2, 1, ((first_sector & 0x3F) | (first_cylinder >> 8 << 2)));
- place_integer_le(partition_entry, 3, 1, first_cylinder);
- place_integer_le(partition_entry, 4, 1, partition_type);
- place_integer_le(partition_entry, 5, 1, last_head);
- place_integer_le(partition_entry, 6, 1, ((last_sector & 0x3F) | (last_cylinder >> 8 << 2)));
- place_integer_le(partition_entry, 7, 1, last_cylinder);
- place_integer_le(partition_entry, 8, 4, first_block);
- place_integer_le(partition_entry, 12, 4, block_count);
-
- /* write the partition header */
- err = imgtool_image_write_block(image, 0, header_block);
- if (err)
- goto done;
-
-done:
- return err;
-}
-
-
-
-static imgtoolerr_t pc_chd_read_partition_header(imgtool_image *image)
-{
- imgtoolerr_t err;
- int i;
- const UINT8 *partition_info;
- pc_chd_image_info *info;
- UINT8 buffer[FAT_SECLEN];
-
- info = pc_chd_get_image_info(image);
-
- /* read the initial block */
- err = imgtool_image_read_block(image, 0, buffer);
- if (err)
- return err;
-
- /* magic bytes present? */
- if ((buffer[510] != 0x55) || (buffer[511] != 0xAA))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- for (i = 0; i < ARRAY_LENGTH(info->partitions); i++)
- {
- partition_info = &buffer[446 + i * 16];
-
- info->partitions[i].partition_type = partition_info[4];
- info->partitions[i].starting_head = partition_info[1];
- info->partitions[i].starting_track = ((partition_info[2] << 2) & 0xFF00) | partition_info[3];
- info->partitions[i].starting_sector = partition_info[2] & 0x3F;
- info->partitions[i].ending_head = partition_info[5];
- info->partitions[i].ending_track = ((partition_info[6] << 2) & 0xFF00) | partition_info[7];
- info->partitions[i].ending_sector = partition_info[6] & 0x3F;
-
- info->partitions[i].sector_index = pick_integer_le(partition_info, 8, 4);
- info->partitions[i].total_sectors = pick_integer_le(partition_info, 12, 4);
-
- if (info->partitions[i].starting_track > info->partitions[i].ending_track)
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t pc_chd_image_create(imgtool_image *image, imgtool_stream *f, option_resolution *opts)
-{
- imgtoolerr_t err;
- UINT32 cylinders, heads, sectors;
- pc_chd_image_info *info;
- UINT8 header_block[FAT_SECLEN];
-
- cylinders = option_resolution_lookup_int(opts, 'T');
- heads = option_resolution_lookup_int(opts, 'H');
- sectors = option_resolution_lookup_int(opts, 'S');
-
- info = pc_chd_get_image_info(image);
-
- /* create the hard disk image */
- err = imghd_create(f, 0, cylinders, heads, sectors, FAT_SECLEN);
- if (err)
- goto done;
-
- err = imghd_open(f, &info->hard_disk);
- if (err)
- goto done;
-
- /* set up partition header block */
- memset(header_block, 0, sizeof(header_block));
- header_block[510] = 0x55;
- header_block[511] = 0xAA;
- err = imgtool_image_write_block(image, 0, header_block);
- if (err)
- goto done;
-
- err = pc_chd_partition_create(image, 0, 1, cylinders * heads * sectors - 1);
- if (err)
- goto done;
-
- err = pc_chd_read_partition_header(image);
- if (err)
- goto done;
-
-done:
- if (err)
- imghd_close(&info->hard_disk);
- return err;
-}
-
-
-
-static imgtoolerr_t pc_chd_image_open(imgtool_image *image, imgtool_stream *stream)
-{
- imgtoolerr_t err;
- pc_chd_image_info *info;
-
- info = pc_chd_get_image_info(image);
-
- /* open the hard drive */
- err = imghd_open(stream, &info->hard_disk);
- if (err)
- return err;
-
- err = pc_chd_read_partition_header(image);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void pc_chd_image_close(imgtool_image *image)
-{
- pc_chd_image_info *info;
- info = pc_chd_get_image_info(image);
- imghd_close(&info->hard_disk);
-}
-
-
-
-static imgtoolerr_t pc_chd_image_get_geometry(imgtool_image *image, UINT32 *tracks, UINT32 *heads, UINT32 *sectors)
-{
- pc_chd_image_info *info;
- const hard_disk_info *hd_info;
-
- info = pc_chd_get_image_info(image);
- hd_info = imghd_get_header(&info->hard_disk);
-
- *tracks = hd_info->cylinders;
- *heads = hd_info->heads;
- *sectors = hd_info->sectors;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t pc_chd_image_getsectorsize(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, UINT32 *sector_size)
-{
- pc_chd_image_info *info;
- info = pc_chd_get_image_info(image);
- *sector_size = imghd_get_header(&info->hard_disk)->sectorbytes;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static UINT32 pc_chd_calc_lbasector(pc_chd_image_info *info, UINT32 track, UINT32 head, UINT32 sector)
-{
- UINT32 lbasector;
- const hard_disk_info *hd_info;
-
- hd_info = imghd_get_header(&info->hard_disk);
- lbasector = track;
- lbasector *= hd_info->heads;
- lbasector += head;
- lbasector *= hd_info->sectors;
- lbasector += sector;
- return lbasector;
-}
-
-
-
-static imgtoolerr_t pc_chd_image_readsector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, void *buffer, size_t len)
-{
- pc_chd_image_info *info;
- info = pc_chd_get_image_info(image);
- return imghd_read(&info->hard_disk,
- pc_chd_calc_lbasector(info, track, head, sector),
- buffer);
-}
-
-
-
-static imgtoolerr_t pc_chd_image_writesector(imgtool_image *image, UINT32 track, UINT32 head, UINT32 sector, const void *buffer, size_t len, int ddam)
-{
- pc_chd_image_info *info;
- info = pc_chd_get_image_info(image);
- return imghd_write(&info->hard_disk,
- pc_chd_calc_lbasector(info, track, head, sector),
- buffer);
-}
-
-
-
-static imgtoolerr_t pc_chd_image_readblock(imgtool_image *image, void *buffer, UINT64 block)
-{
- pc_chd_image_info *info;
- info = pc_chd_get_image_info(image);
- return imghd_read(&info->hard_disk, block, buffer);
-}
-
-
-
-static imgtoolerr_t pc_chd_image_writeblock(imgtool_image *image, const void *buffer, UINT64 block)
-{
- pc_chd_image_info *info;
- info = pc_chd_get_image_info(image);
- return imghd_write(&info->hard_disk, block, buffer);
-}
-
-
-
-static imgtoolerr_t pc_chd_list_partitions(imgtool_image *image, imgtool_partition_info *partitions, size_t len)
-{
- pc_chd_image_info *info;
- size_t i;
-
- info = pc_chd_get_image_info(image);
-
- for (i = 0; i < MIN(4, len); i++)
- {
- partitions[i].base_block = info->partitions[i].sector_index;
- partitions[i].block_count = info->partitions[i].total_sectors;
-
- switch(info->partitions[i].partition_type)
- {
- case 0x00: /* Empty Partition */
- partitions[i].get_info = NULL;
- break;
-
- case 0x01: /* FAT12 */
- case 0x04: /* FAT16 (-32 MB) */
- case 0x06: /* FAT16 (32+ MB) */
- case 0x0B: /* FAT32 */
- case 0x0C: /* FAT32 (LBA Mapped) */
- case 0x0E: /* FAT16 (LBA Mapped) */
- case 0x11: /* OS/2 FAT12 */
- case 0x14: /* OS/2 FAT16 (-32 MB) */
- case 0x16: /* OS/2 FAT16 (32+ MB) */
- case 0x1B: /* Hidden Win95 FAT32 */
- case 0x1C: /* Hidden Win95 FAT32 (LBA Mapped) */
- case 0x1D: /* Hidden Win95 FAT16 (LBA Mapped) */
- case 0xC1: /* DR-DOS FAT12 */
- case 0xC4: /* DR-DOS FAT16 (-32 MB) */
- case 0xC6: /* DR-DOS FAT16 (32+ MB) */
- case 0xD1: /* Old Multiuser DOS FAT12 */
- case 0xD4: /* Old Multiuser DOS FAT16 (-32 MB) */
- case 0xD6: /* Old Multiuser DOS FAT16 (32+ MB) */
- partitions[i].get_info = fat_get_info;
- break;
-
- default:
- partitions[i].get_info = unknown_partition_get_info;
- break;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-void pc_chd_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_BLOCK_SIZE: info->i = FAT_SECLEN; break;
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(pc_chd_image_info); break;
- case IMGTOOLINFO_INT_TRACKS_ARE_CALLED_CYLINDERS: info->i = 1; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "pc_chd"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "PC CHD disk image"); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "chd"); break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), pc_chd_create_optionspec); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_CREATE: info->create = pc_chd_image_create; break;
- case IMGTOOLINFO_PTR_OPEN: info->open = pc_chd_image_open; break;
- case IMGTOOLINFO_PTR_CLOSE: info->close = pc_chd_image_close; break;
- case IMGTOOLINFO_PTR_READ_SECTOR: info->read_sector = pc_chd_image_readsector; break;
- case IMGTOOLINFO_PTR_WRITE_SECTOR: info->write_sector = pc_chd_image_writesector; break;
- case IMGTOOLINFO_PTR_READ_BLOCK: info->read_block = pc_chd_image_readblock; break;
- case IMGTOOLINFO_PTR_WRITE_BLOCK: info->write_block = pc_chd_image_writeblock; break;
- case IMGTOOLINFO_PTR_GET_SECTOR_SIZE: info->get_sector_size = pc_chd_image_getsectorsize; break;
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = pc_chd_create_optionguide; break;
- case IMGTOOLINFO_PTR_GET_GEOMETRY: info->get_geometry = pc_chd_image_get_geometry; break;
- case IMGTOOLINFO_PTR_LIST_PARTITIONS: info->list_partitions = pc_chd_list_partitions; break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/prodos.c b/src/mess/tools/imgtool/modules/prodos.c
deleted file mode 100644
index 5800e2bf9f3..00000000000
--- a/src/mess/tools/imgtool/modules/prodos.c
+++ /dev/null
@@ -1,2282 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/****************************************************************************
-
- prodos.c
-
- Apple II ProDOS disk images
-
-*****************************************************************************
-
- Notes:
- - ProDOS disks are split into 512 byte blocks.
-
- ProDOS directory structure:
-
- Offset Length Description
- ------ ------ -----------
- 0 2 ???
- 2 2 Next block (0 if end)
- 4 39 Directory Entry
- 43 39 Directory Entry
- ...
- 472 39 Directory Entry
- 511 1 ???
-
-
- ProDOS directory entry structure:
-
- Offset Length Description
- ------ ------ -----------
- 0 1 Storage type (bits 7-4)
- 10 - Seedling File (1 block)
- 20 - Sapling File (2-256 blocks)
- 30 - Tree File (257-32768 blocks)
- 40 - Pascal Areas on ProFile HDs (???)
- 50 - GS/OS Extended File (data and rsrc fork)
- E0 - Subdirectory Header
- F0 - Volume Header
- 1 15 File name (NUL padded)
- 16 1 File type
- 17 2 Key pointer
- 19 2 Blocks used
- 21 3 File size
- 24 4 Creation date
- 28 1 ProDOS version that created the file
- 29 1 Minimum ProDOS version needed to read the file
- 30 1 Access byte
- 31 2 Auxilary file type
- 33 4 Last modified date
- 37 2 Header pointer
-
-
- In "seedling files", the key pointer points to a single block that is the
- whole file. In "sapling files", the key pointer points to an index block
- that contains 256 2-byte index pointers that point to the actual blocks of
- the files. These 2-byte values are not contiguous; the low order byte is
- in the first half of the block, and the high order byte is in the second
- half of the block. In "tree files", the key pointer points to an index
- block of index blocks.
-
- ProDOS dates are 32-bit little endian values
-
- bits 0- 4 Day
- bits 5- 8 Month (0-11)
- bits 9-15 Year (0-49 is 2000-2049, 50-99 is 1950-1999)
- bits 16-21 Minute
- bits 24-28 Hour
-
-
- ProDOS directory and volume headers have this information:
-
- Offset Length Description
- ------ ------ -----------
- 31 1 Length of the entry; generally is 39
- 32 1 Number of entries per block; generally is 13
- 33 2 Active entry count in directory
- 35 2 Volume bitmap block number
- 37 2 Total blocks on volume
-
- GS/OS Extended Files (storage type $5) point to an extended key block that
- contains information about the two forks. The first half of the extended
- key block contains info about the data form, and the second half the
- resource fork. Both sides have the following format:
-
- Offset Length Description
- ------ ------ -----------
- 0 1 Storage type (bits 3-0, unlike the directory entry)
- 1 2 Key pointer
- 3 2 Blocks used
- 5 3 File size
- 8 1 Size of secondary info #1 (must be 18 to be valid)
- 9 1 Secondary info #1 type (1=FInfo 2=xFInfo)
- 10 16 FInfo or xFInfo
- 26 1 Size of secondary info #2 (must be 18 to be valid)
- 27 1 Secondary info #2 type (1=FInfo 2=xFInfo)
- 28 16 FInfo or xFInfo
-
- FInfo format:
-
- Offset Length Description
- ------ ------ -----------
- 0 4 File type
- 4 4 File creator
- 8 2 Finder flags
- 10 2 X Coordinate
- 12 2 Y Coordinate
- 14 2 Finder folder
-
- xFInfo format:
-
- Offset Length Description
- ------ ------ -----------
- 0 2 Icon ID
- 2 6 Reserved
- 8 1 Script Code
- 9 1 Extended flags
- 10 2 Comment ID
- 12 4 Put Away Directory
-
-
- For more info, consult ProDOS technical note #25
- (http://web.pdx.edu/~heiss/technotes/pdos/tn.pdos.25.html)
-
-*****************************************************************************/
-
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/ap2_dsk.h"
-#include "formats/ap_dsk35.h"
-#include "iflopimg.h"
-#include "macutil.h"
-
-#define ROOTDIR_BLOCK 2
-#define BLOCK_SIZE 512
-
-struct prodos_diskinfo
-{
- imgtoolerr_t (*load_block)(imgtool_image *image, int block, void *buffer);
- imgtoolerr_t (*save_block)(imgtool_image *image, int block, const void *buffer);
- UINT8 dirent_size;
- UINT8 dirents_per_block;
- UINT16 volume_bitmap_block;
- UINT16 total_blocks;
-};
-
-struct prodos_direnum
-{
- UINT32 block;
- UINT32 index;
- UINT8 block_data[BLOCK_SIZE];
-};
-
-struct prodos_dirent
-{
- char filename[16];
- UINT8 storage_type;
- UINT16 extkey_pointer;
- UINT16 key_pointer[2];
- UINT32 filesize[2];
- int depth[2];
- UINT32 lastmodified_time;
- UINT32 creation_time;
-
- /* FInfo */
- UINT32 file_type;
- UINT32 file_creator;
- UINT16 finder_flags;
- UINT16 coord_x;
- UINT16 coord_y;
- UINT16 finder_folder;
-
- /* xFInfo */
- UINT16 icon_id;
- UINT8 script_code;
- UINT8 extended_flags;
- UINT16 comment_id;
- UINT32 putaway_directory;
-};
-
-enum creation_policy_t
-{
- CREATE_NONE,
- CREATE_FILE,
- CREATE_DIR
-};
-
-
-
-static time_t prodos_crack_time(UINT32 prodos_time)
-{
- struct tm t;
- time_t now;
-
- time(&now);
- t = *localtime(&now);
-
- t.tm_sec = 0;
- t.tm_min = (prodos_time >> 16) & 0x3F;
- t.tm_hour = (prodos_time >> 24) & 0x1F;
- t.tm_mday = (prodos_time >> 0) & 0x1F;
- t.tm_mon = (prodos_time >> 5) & 0x0F;
- t.tm_year = (prodos_time >> 9) & 0x7F;
-
- if (t.tm_year <= 49)
- t.tm_year += 100;
- return mktime(&t);
-}
-
-
-
-static UINT32 prodos_setup_time(time_t ansi_time)
-{
- struct tm t;
- UINT32 result = 0;
-
- t = *localtime(&ansi_time);
- if ((t.tm_year >= 100) && (t.tm_year <= 149))
- t.tm_year -= 100;
-
- result |= (((UINT32) t.tm_min) & 0x003F) << 16;
- result |= (((UINT32) t.tm_hour) & 0x001F) << 24;
- result |= (((UINT32) t.tm_mday) & 0x001F) << 0;
- result |= (((UINT32) t.tm_mon) & 0x000F) << 5;
- result |= (((UINT32) t.tm_year) & 0x007F) << 9;
- return result;
-}
-
-
-
-static UINT32 prodos_time_now(void)
-{
- time_t now;
- time(&now);
- return prodos_setup_time(now);
-}
-
-
-
-static int is_file_storagetype(UINT8 storage_type)
-{
- return ((storage_type >= 0x10) && (storage_type <= 0x3F))
- || ((storage_type >= 0x50) && (storage_type <= 0x5F));
-}
-
-
-
-static int is_normalfile_storagetype(UINT8 storage_type)
-{
- return ((storage_type >= 0x10) && (storage_type <= 0x3F));
-}
-
-
-
-static int is_extendedfile_storagetype(UINT8 storage_type)
-{
- return ((storage_type >= 0x50) && (storage_type <= 0x5F));
-}
-
-
-
-static int is_dir_storagetype(UINT8 storage_type)
-{
- return (storage_type >= 0xE0) && (storage_type <= 0xEF);
-}
-
-
-
-static prodos_diskinfo *get_prodos_info(imgtool_image *image)
-{
- prodos_diskinfo *info;
- info = (prodos_diskinfo *) imgtool_floppy_extrabytes(image);
- return info;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static void prodos_find_block_525(imgtool_image *image, int block,
- UINT32 *track, UINT32 *head, UINT32 *sector1, UINT32 *sector2)
-{
- static const UINT8 skewing[] =
- {
- 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
- 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F
- };
-
- block *= 2;
-
- *track = block / APPLE2_SECTOR_COUNT;
- *head = 0;
- *sector1 = skewing[block % APPLE2_SECTOR_COUNT + 0];
- *sector2 = skewing[block % APPLE2_SECTOR_COUNT + 1];
-}
-
-
-
-static imgtoolerr_t prodos_load_block_525(imgtool_image *image,
- int block, void *buffer)
-{
- floperr_t ferr;
- UINT32 track, head, sector1, sector2;
-
- prodos_find_block_525(image, block, &track, &head, &sector1, &sector2);
-
- /* read first sector */
- ferr = floppy_read_sector(imgtool_floppy(image), head, track,
- sector1, 0, ((UINT8 *) buffer) + 0, 256);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- /* read second sector */
- ferr = floppy_read_sector(imgtool_floppy(image), head, track,
- sector2, 0, ((UINT8 *) buffer) + 256, 256);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_save_block_525(imgtool_image *image,
- int block, const void *buffer)
-{
- floperr_t ferr;
- UINT32 track, head, sector1, sector2;
-
- prodos_find_block_525(image, block, &track, &head, &sector1, &sector2);
-
- /* read first sector */
- ferr = floppy_write_sector(imgtool_floppy(image), head, track,
- sector1, 0, ((const UINT8 *) buffer) + 0, 256, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- /* read second sector */
- ferr = floppy_write_sector(imgtool_floppy(image), head, track,
- sector2, 0, ((const UINT8 *) buffer) + 256, 256, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void prodos_setprocs_525(imgtool_image *image)
-{
- prodos_diskinfo *info;
- info = get_prodos_info(image);
- info->load_block = prodos_load_block_525;
- info->save_block = prodos_save_block_525;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_find_block_35(imgtool_image *image, int block,
- UINT32 *track, UINT32 *head, UINT32 *sector)
-{
- int sides = 2;
-
- *track = 0;
- while(block >= (apple35_sectors_per_track(imgtool_floppy(image), *track) * sides))
- {
- block -= (apple35_sectors_per_track(imgtool_floppy(image), (*track)++) * sides);
- if (*track >= 80)
- return IMGTOOLERR_SEEKERROR;
- }
-
- *head = block / apple35_sectors_per_track(imgtool_floppy(image), *track);
- *sector = block % apple35_sectors_per_track(imgtool_floppy(image), *track);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_load_block_35(imgtool_image *image,
- int block, void *buffer)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- UINT32 track, head, sector;
-
- err = prodos_find_block_35(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_read_sector(imgtool_floppy(image), head, track, sector, 0, buffer, 512);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_save_block_35(imgtool_image *image,
- int block, const void *buffer)
-{
- imgtoolerr_t err;
- floperr_t ferr;
- UINT32 track, head, sector;
-
- err = prodos_find_block_35(image, block, &track, &head, &sector);
- if (err)
- return err;
-
- ferr = floppy_write_sector(imgtool_floppy(image), head, track, sector, 0, buffer, 512, 0); /* TODO: pass ddam argument from imgtool */
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void prodos_setprocs_35(imgtool_image *image)
-{
- prodos_diskinfo *info;
- info = get_prodos_info(image);
- info->load_block = prodos_load_block_35;
- info->save_block = prodos_save_block_35;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_load_block(imgtool_image *image,
- int block, void *buffer)
-{
- prodos_diskinfo *diskinfo;
- diskinfo = get_prodos_info(image);
- return diskinfo->load_block(image, block, buffer);
-}
-
-
-
-static imgtoolerr_t prodos_save_block(imgtool_image *image,
- int block, const void *buffer)
-{
- prodos_diskinfo *diskinfo;
- diskinfo = get_prodos_info(image);
- return diskinfo->save_block(image, block, buffer);
-}
-
-
-
-static imgtoolerr_t prodos_clear_block(imgtool_image *image, int block)
-{
- UINT8 buffer[BLOCK_SIZE];
- memset(buffer, 0, sizeof(buffer));
- return prodos_save_block(image, block, buffer);
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_diskimage_open(imgtool_image *image)
-{
- imgtoolerr_t err;
- UINT8 buffer[BLOCK_SIZE];
- prodos_diskinfo *di;
- const UINT8 *ent;
-
- di = get_prodos_info(image);
-
- /* specify defaults */
- di->dirent_size = 39;
- di->dirents_per_block = 13;
-
- /* load the first block, hoping that the volume header is first */
- err = prodos_load_block(image, ROOTDIR_BLOCK, buffer);
- if (err)
- return err;
-
- ent = &buffer[4];
-
- /* did we find the volume header? */
- if ((ent[0] & 0xF0) == 0xF0)
- {
- di->dirent_size = pick_integer_le(ent, 31, 1);
- di->dirents_per_block = pick_integer_le(ent, 32, 1);
- di->volume_bitmap_block = pick_integer_le(ent, 35, 2);
- di->total_blocks = pick_integer_le(ent, 37, 2);
- }
-
- /* sanity check these values */
- if (di->dirent_size < 39)
- return IMGTOOLERR_CORRUPTIMAGE;
- if (di->dirents_per_block * di->dirent_size >= BLOCK_SIZE)
- return IMGTOOLERR_CORRUPTIMAGE;
- if (di->volume_bitmap_block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_open_525(imgtool_image *image, imgtool_stream *stream)
-{
- prodos_setprocs_525(image);
- return prodos_diskimage_open(image);
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_open_35(imgtool_image *image, imgtool_stream *stream)
-{
- prodos_setprocs_35(image);
- return prodos_diskimage_open(image);
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_load_volume_bitmap(imgtool_image *image, UINT8 **bitmap)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- UINT8 *alloc_bitmap;
- UINT32 bitmap_blocks, i;
-
- di = get_prodos_info(image);
-
- bitmap_blocks = (di->total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
- alloc_bitmap = (UINT8*)malloc(bitmap_blocks * BLOCK_SIZE);
- if (!alloc_bitmap)
- {
- err = IMGTOOLERR_OUTOFMEMORY;
- goto done;
- }
-
- for (i = 0; i < bitmap_blocks; i++)
- {
- err = prodos_load_block(image, di->volume_bitmap_block + i,
- &alloc_bitmap[i * BLOCK_SIZE]);
- if (err)
- goto done;
- }
-
- err = IMGTOOLERR_SUCCESS;
-
-done:
- if (err && alloc_bitmap)
- {
- free(alloc_bitmap);
- alloc_bitmap = NULL;
- }
- *bitmap = alloc_bitmap;
- return err;
-}
-
-
-
-static imgtoolerr_t prodos_save_volume_bitmap(imgtool_image *image, const UINT8 *bitmap)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- UINT32 bitmap_blocks, i;
-
- di = get_prodos_info(image);
-
- bitmap_blocks = (di->total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
-
- for (i = 0; i < bitmap_blocks; i++)
- {
- err = prodos_save_block(image, di->volume_bitmap_block + i,
- &bitmap[i * BLOCK_SIZE]);
- if (err)
- return err;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void prodos_set_volume_bitmap_bit(UINT8 *buffer, UINT16 block, int value)
-{
- UINT8 mask;
- buffer += block / 8;
- mask = 1 << (7 - (block % 8));
- if (value)
- *buffer |= mask;
- else
- *buffer &= ~mask;
-}
-
-
-
-static int prodos_get_volume_bitmap_bit(const UINT8 *buffer, UINT16 block)
-{
- UINT8 mask;
- buffer += block / 8;
- mask = 1 << (7 - (block % 8));
- return (*buffer & mask) ? 1 : 0;
-}
-
-
-
-static imgtoolerr_t prodos_alloc_block(imgtool_image *image, UINT8 *bitmap,
- UINT16 *block)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- prodos_diskinfo *di;
- UINT16 bitmap_blocks, i;
- UINT8 *alloc_bitmap = NULL;
-
- di = get_prodos_info(image);
- *block = 0;
- bitmap_blocks = (di->total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
-
- if (!bitmap)
- {
- err = prodos_load_volume_bitmap(image, &alloc_bitmap);
- if (err)
- goto done;
- bitmap = alloc_bitmap;
- }
-
- for (i = (di->volume_bitmap_block + bitmap_blocks); i < di->total_blocks; i++)
- {
- if (!prodos_get_volume_bitmap_bit(bitmap, i))
- {
- prodos_set_volume_bitmap_bit(bitmap, i, 1);
- *block = i;
- break;
- }
- }
-
- if (*block > 0)
- {
- if (alloc_bitmap)
- {
- err = prodos_save_volume_bitmap(image, bitmap);
- if (err)
- goto done;
- }
- }
- else
- {
- err = IMGTOOLERR_NOSPACE;
- }
-
-done:
- if (err)
- *block = 0;
- if (alloc_bitmap)
- free(alloc_bitmap);
- return err;
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_diskimage_create(imgtool_image *image, option_resolution *opts)
-{
- imgtoolerr_t err;
- UINT32 heads, tracks, sectors, sector_bytes;
- UINT32 dirent_size, volume_bitmap_block, i;
- UINT32 volume_bitmap_block_count, total_blocks;
- UINT8 buffer[BLOCK_SIZE];
-
- heads = option_resolution_lookup_int(opts, 'H');
- tracks = option_resolution_lookup_int(opts, 'T');
- sectors = option_resolution_lookup_int(opts, 'S');
- sector_bytes = option_resolution_lookup_int(opts, 'L');
-
- dirent_size = 39;
- volume_bitmap_block = 6;
- total_blocks = tracks * heads * sectors * sector_bytes / BLOCK_SIZE;
- volume_bitmap_block_count = (total_blocks + (BLOCK_SIZE * 8) - 1) / (BLOCK_SIZE * 8);
-
- /* prepare initial dir block */
- memset(buffer, 0, sizeof(buffer));
- place_integer_le(buffer, 4 + 0, 1, 0xF0);
- place_integer_le(buffer, 4 + 31, 1, dirent_size);
- place_integer_le(buffer, 4 + 32, 1, BLOCK_SIZE / dirent_size);
- place_integer_le(buffer, 4 + 35, 2, volume_bitmap_block);
- place_integer_le(buffer, 4 + 37, 2, total_blocks);
-
- err = prodos_save_block(image, ROOTDIR_BLOCK, buffer);
- if (err)
- return err;
-
- /* setup volume bitmap */
- memset(buffer, 0, sizeof(buffer));
- for (i = 0; i < (volume_bitmap_block + volume_bitmap_block_count); i++)
- prodos_set_volume_bitmap_bit(buffer, i, 1);
- prodos_save_block(image, volume_bitmap_block, buffer);
-
- /* and finally open the image */
- return prodos_diskimage_open(image);
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_create_525(imgtool_image *image, imgtool_stream *stream, option_resolution *opts)
-{
- prodos_setprocs_525(image);
- return prodos_diskimage_create(image, opts);
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_create_35(imgtool_image *image, imgtool_stream *stream, option_resolution *opts)
-{
- prodos_setprocs_35(image);
- return prodos_diskimage_create(image, opts);
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-
-static imgtoolerr_t prodos_enum_seek(imgtool_image *image,
- prodos_direnum *appleenum, UINT32 block, UINT32 index)
-{
- imgtoolerr_t err;
- UINT8 buffer[BLOCK_SIZE];
-
- if (appleenum->block != block)
- {
- if (block != 0)
- {
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
- memcpy(appleenum->block_data, buffer, sizeof(buffer));
- }
- appleenum->block = block;
- }
-
- appleenum->index = index;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static UINT8 *next_info_block(UINT8 *buffer, size_t *position)
-{
- size_t side = *position & 0x100;
- size_t subpos = *position & 0x0FF;
- UINT8 *result;
-
- if (subpos < 8)
- {
- subpos = 8;
- *position = side + subpos;
- }
-
- while((buffer[side + subpos] == 0x00) || (subpos + buffer[side + subpos] > 0x100))
- {
- if (side)
- return NULL;
-
- side = 0x100;
- subpos = 8;
- }
-
- result = &buffer[side + subpos];
- subpos += *result;
- *position = side + subpos;
- return result;
-}
-
-
-
-static UINT8 *alloc_info_block(UINT8 *buffer, size_t block_size, UINT8 block_type)
-{
- size_t position = 0;
- size_t side;
- size_t subpos;
- UINT8 *result;
-
- while(next_info_block(buffer, &position))
- ;
-
- side = position & 0x100;
- subpos = position & 0x0FF;
-
- if ((subpos + block_size) > 0x100)
- return NULL;
-
- result = &buffer[side + subpos];
- *(result++) = (UINT8) block_size;
- *(result++) = block_type;
- memset(result, 0, block_size - 2);
- return result;
-}
-
-
-
-static imgtoolerr_t prodos_get_next_dirent(imgtool_image *image,
- prodos_direnum *appleenum, prodos_dirent *ent)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- size_t finfo_offset;
- UINT32 next_block, next_index;
- UINT32 offset;
- UINT8 buffer[BLOCK_SIZE];
- const UINT8 *info_ptr;
- int fork_num;
-
- di = get_prodos_info(image);
- memset(ent, 0, sizeof(*ent));
-
- /* have we hit the end of the file? */
- if (appleenum->block == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* populate the resulting dirent */
- offset = appleenum->index * di->dirent_size + 4;
- ent->storage_type = appleenum->block_data[offset + 0];
- memcpy(ent->filename, &appleenum->block_data[offset + 1], 15);
- ent->filename[15] = '\0';
- ent->creation_time = pick_integer_le(appleenum->block_data, offset + 24, 4);
- ent->lastmodified_time = pick_integer_le(appleenum->block_data, offset + 33, 4);
- ent->file_type = 0x3F3F3F3F;
- ent->file_creator = 0x3F3F3F3F;
- ent->finder_flags = 0;
- ent->coord_x = 0;
- ent->coord_y = 0;
- ent->finder_folder = 0;
- ent->icon_id = 0;
- ent->script_code = 0;
- ent->extended_flags = 0;
- ent->comment_id = 0;
- ent->putaway_directory = 0;
-
- if (is_extendedfile_storagetype(ent->storage_type))
- {
- /* this is a ProDOS extended file; we need to get the extended info
- * block */
- ent->extkey_pointer = pick_integer_le(appleenum->block_data, offset + 17, 2);
-
- err = prodos_load_block(image, ent->extkey_pointer, buffer);
- if (err)
- return err;
-
- for (fork_num = 0; fork_num <= 1; fork_num++)
- {
- ent->key_pointer[fork_num] = pick_integer_le(buffer, 1 + (fork_num * 256), 2);
- ent->filesize[fork_num] = pick_integer_le(buffer, 5 + (fork_num * 256), 3);
- ent->depth[fork_num] = buffer[fork_num * 256] & 0x0F;
- }
-
- finfo_offset = 0;
- while((info_ptr = next_info_block(buffer, &finfo_offset)) != NULL)
- {
- if (*(info_ptr++) == 18)
- {
- switch(*(info_ptr++))
- {
- case 1: /* FInfo */
- ent->file_type = pick_integer_be(info_ptr, 0, 4);
- ent->file_creator = pick_integer_be(info_ptr, 4, 4);
- ent->finder_flags = pick_integer_be(info_ptr, 8, 2);
- ent->coord_x = pick_integer_be(info_ptr, 10, 2);
- ent->coord_y = pick_integer_be(info_ptr, 12, 2);
- ent->finder_folder = pick_integer_be(info_ptr, 14, 4);
- break;
-
- case 2: /* xFInfo */
- ent->icon_id = pick_integer_be(info_ptr, 0, 2);
- ent->script_code = pick_integer_be(info_ptr, 8, 1);
- ent->extended_flags = pick_integer_be(info_ptr, 9, 1);
- ent->comment_id = pick_integer_be(info_ptr, 10, 2);
- ent->putaway_directory = pick_integer_be(info_ptr, 12, 4);
- break;
- }
- }
- }
- }
- else
- {
- /* normal ProDOS files have all of the info right here */
- ent->key_pointer[0] = pick_integer_le(appleenum->block_data, offset + 17, 2);
- ent->filesize[0] = pick_integer_le(appleenum->block_data, offset + 21, 3);
- ent->depth[0] = ent->storage_type >> 4;
- }
-
- /* identify next entry */
- next_block = appleenum->block;
- next_index = appleenum->index + 1;
- if (next_index >= di->dirents_per_block)
- {
- next_block = pick_integer_le(appleenum->block_data, 2, 2);
- next_index = 0;
- }
-
- /* seek next block */
- err = prodos_enum_seek(image, appleenum, next_block, next_index);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/* changes a normal file to a ProDOS extended file */
-static imgtoolerr_t prodos_promote_file(imgtool_image *image, UINT8 *bitmap, prodos_dirent *ent)
-{
- imgtoolerr_t err;
- UINT16 new_block;
- UINT8 buffer[BLOCK_SIZE];
-
- assert(is_normalfile_storagetype(ent->storage_type));
-
- err = prodos_alloc_block(image, bitmap, &new_block);
- if (err)
- return err;
-
- /* create raw extended info block */
- memset(buffer, 0, sizeof(buffer));
- err = prodos_save_block(image, new_block, buffer);
- if (err)
- return err;
-
- ent->storage_type = (ent->storage_type & 0x0F) | 0x50;
- ent->extkey_pointer = new_block;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_put_dirent(imgtool_image *image,
- prodos_direnum *appleenum, prodos_dirent *ent)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- UINT32 offset;
- size_t finfo_offset;
- UINT8 buffer[BLOCK_SIZE];
- int fork_num;
- int needs_finfo = FALSE;
- int needs_xfinfo = FALSE;
- UINT8 *info_ptr;
- UINT8 *finfo;
- UINT8 *xfinfo;
-
- di = get_prodos_info(image);
- offset = appleenum->index * di->dirent_size + 4;
-
- /* determine whether we need FInfo and/or xFInfo */
- if (is_normalfile_storagetype(ent->storage_type))
- {
- needs_finfo = (ent->file_type != 0x3F3F3F3F) ||
- (ent->file_creator != 0x3F3F3F3F) ||
- (ent->finder_flags != 0) ||
- (ent->coord_x != 0) ||
- (ent->coord_y != 0) ||
- (ent->finder_folder != 0);
-
- needs_xfinfo = (ent->icon_id != 0) ||
- (ent->script_code != 0) ||
- (ent->extended_flags != 0) ||
- (ent->comment_id != 0) ||
- (ent->putaway_directory != 0);
- }
-
- /* do we need to promote this file to an extended file? */
- if (!is_extendedfile_storagetype(ent->storage_type)
- && (needs_finfo || needs_xfinfo))
- {
- err = prodos_promote_file(image, NULL, ent);
- if (err)
- return err;
- }
-
- /* write out the storage type, filename, creation and lastmodified times */
- appleenum->block_data[offset + 0] = ent->storage_type;
- memcpy(&appleenum->block_data[offset + 1], ent->filename, 15);
- place_integer_le(appleenum->block_data, offset + 24, 4, ent->creation_time);
- place_integer_le(appleenum->block_data, offset + 33, 4, ent->lastmodified_time);
-
- if (is_extendedfile_storagetype(ent->storage_type))
- {
- /* ProDOS extended file */
- err = prodos_load_block(image, ent->extkey_pointer, buffer);
- if (err)
- return err;
-
- finfo = NULL;
- xfinfo = NULL;
-
- for (fork_num = 0; fork_num <= 1; fork_num++)
- {
- place_integer_le(buffer, 1 + (fork_num * 256), 2, ent->key_pointer[fork_num]);
- place_integer_le(buffer, 5 + (fork_num * 256), 3, ent->filesize[fork_num]);
- buffer[fork_num * 256] = ent->depth[fork_num];
- }
-
- finfo_offset = 0;
- while((info_ptr = next_info_block(buffer, &finfo_offset)) != NULL)
- {
- if (*(info_ptr++) == 18)
- {
- switch(*(info_ptr++))
- {
- case 1: /* FInfo */
- finfo = info_ptr;
- break;
-
- case 2: /* xFInfo */
- xfinfo = info_ptr;
- break;
- }
- }
- }
-
- /* allocate the finfo and/or xinfo blocks, if we need them */
- if (needs_finfo && !finfo)
- finfo = alloc_info_block(buffer, 18, 1);
- if (needs_xfinfo && !xfinfo)
- xfinfo = alloc_info_block(buffer, 18, 2);
-
- if (finfo)
- {
- place_integer_be(finfo, 0, 4, ent->file_type);
- place_integer_be(finfo, 4, 4, ent->file_creator);
- place_integer_be(finfo, 8, 2, ent->finder_flags);
- place_integer_be(finfo, 10, 2, ent->coord_x);
- place_integer_be(finfo, 12, 2, ent->coord_y);
- place_integer_be(finfo, 14, 4, ent->finder_folder);
- }
-
- if (xfinfo)
- {
- place_integer_be(xfinfo, 0, 2, ent->icon_id);
- place_integer_be(xfinfo, 8, 1, ent->script_code);
- place_integer_be(xfinfo, 9, 1, ent->extended_flags);
- place_integer_be(xfinfo, 10, 2, ent->comment_id);
- place_integer_be(xfinfo, 12, 4, ent->putaway_directory);
- }
-
- err = prodos_save_block(image, ent->extkey_pointer, buffer);
- if (err)
- return err;
-
- place_integer_le(appleenum->block_data, offset + 17, 2, ent->extkey_pointer);
- place_integer_le(appleenum->block_data, offset + 21, 3, BLOCK_SIZE);
- }
- else
- {
- /* normal file */
- place_integer_le(appleenum->block_data, offset + 17, 2, ent->key_pointer[0]);
- place_integer_le(appleenum->block_data, offset + 21, 3, ent->filesize[0]);
- }
-
- err = prodos_save_block(image, appleenum->block, appleenum->block_data);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_lookup_path(imgtool_image *image, const char *path,
- creation_policy_t create, prodos_direnum *direnum, prodos_dirent *ent)
-{
- imgtoolerr_t err;
- prodos_direnum my_direnum;
- UINT32 block = ROOTDIR_BLOCK;
- const char *old_path;
- UINT16 this_block;
- UINT32 this_index;
- UINT16 free_block = 0;
- UINT32 free_index = 0;
- UINT16 new_file_block;
- UINT8 buffer[BLOCK_SIZE];
-
- if (!direnum)
- direnum = &my_direnum;
-
- while(*path)
- {
- memset(direnum, 0, sizeof(*direnum));
- err = prodos_enum_seek(image, direnum, block, 0);
- if (err)
- goto done;
-
- do
- {
- this_block = direnum->block;
- this_index = direnum->index;
-
- err = prodos_get_next_dirent(image, direnum, ent);
- if (err)
- goto done;
-
- /* if we need to create a file entry and this is free, track it */
- if (create && this_block && !free_block && !ent->storage_type)
- {
- free_block = this_block;
- free_index = this_index;
- }
- }
- while(direnum->block && (strcmp(path, ent->filename) || (
- !is_file_storagetype(ent->storage_type) &&
- !is_dir_storagetype(ent->storage_type))));
-
- old_path = path;
- path += strlen(path) + 1;
- if (*path)
- {
- /* we have found part of the path; we are not finished yet */
- if (!is_dir_storagetype(ent->storage_type))
- {
- err = IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
- block = ent->key_pointer[0];
- }
- else if (!direnum->block)
- {
- /* did not find file; maybe we need to create it */
- if (create == CREATE_NONE)
- {
- err = IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
-
- /* do we need to expand the directory? */
- if (!free_block)
- {
- if (this_block == 0)
- {
- err = IMGTOOLERR_CORRUPTFILE;
- goto done;
- }
-
- err = prodos_load_block(image, this_block, buffer);
- if (err)
- goto done;
-
- /* allocate a block */
- err = prodos_alloc_block(image, NULL, &free_block);
- if (err)
- goto done;
-
- /* clear out this new block */
- err = prodos_clear_block(image, free_block);
- if (err)
- goto done;
-
- /* save this link */
- place_integer_le(buffer, 2, 2, free_block);
- err = prodos_save_block(image, this_block, buffer);
- if (err)
- goto done;
-
- free_index = 0;
- }
-
- /* seek back to the free space */
- err = prodos_enum_seek(image, direnum, free_block, free_index);
- if (err)
- goto done;
-
- new_file_block = 0;
- if (create == CREATE_DIR)
- {
- /* if we are creating a directory, we need to create a new block */
- err = prodos_alloc_block(image, NULL, &new_file_block);
- if (err)
- goto done;
-
- err = prodos_clear_block(image, new_file_block);
- if (err)
- goto done;
- }
-
- /* prepare the dirent */
- memset(ent, 0, sizeof(*ent));
- ent->storage_type = (create == CREATE_DIR) ? 0xe0 : 0x10;
- ent->creation_time = ent->lastmodified_time = prodos_time_now();
- ent->key_pointer[0] = new_file_block;
- ent->file_type = 0x3F3F3F3F;
- ent->file_creator = 0x3F3F3F3F;
- strncpy(ent->filename, old_path, ARRAY_LENGTH(ent->filename));
-
- /* and place it */
- err = prodos_put_dirent(image, direnum, ent);
- if (err)
- goto done;
-
- this_block = free_block;
- this_index = free_index;
- }
- else
- {
- /* we've found the file; seek that dirent */
- err = prodos_enum_seek(image, direnum, this_block, this_index);
- if (err)
- goto done;
- }
- }
-
- err = IMGTOOLERR_SUCCESS;
-done:
- return err;
-}
-
-
-
-static imgtoolerr_t prodos_fill_file(imgtool_image *image, UINT8 *bitmap,
- UINT16 key_block, int key_block_allocated,
- int depth, UINT32 blockcount, UINT32 block_index)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- int dirty;
- int sub_block_allocated;
- UINT16 i, sub_block, new_sub_block;
- UINT8 buffer[BLOCK_SIZE];
-
- di = get_prodos_info(image);
-
- if (key_block_allocated)
- {
- /* we are on a recently allocated key block; start fresh */
- memset(buffer, 0, sizeof(buffer));
- dirty = TRUE;
- }
- else
- {
- /* this is a preexisting key block */
- err = prodos_load_block(image, key_block, buffer);
- if (err)
- return err;
- dirty = FALSE;
- }
-
- for (i = 0; i < 256; i++)
- {
- sub_block_allocated = FALSE;
-
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block += buffer[i + 0];
-
- new_sub_block = sub_block;
- if ((block_index < blockcount) && (sub_block == 0))
- {
- err = prodos_alloc_block(image, bitmap, &new_sub_block);
- if (err)
- return err;
- sub_block_allocated = TRUE;
- }
- else if ((block_index >= blockcount) && (sub_block != 0))
- {
- new_sub_block = 0;
- if (sub_block < di->total_blocks)
- prodos_set_volume_bitmap_bit(bitmap, sub_block, 0);
- }
-
- /* did we change the block? */
- if (new_sub_block != sub_block)
- {
- dirty = TRUE;
- buffer[i + 0] = new_sub_block >> 0;
- buffer[i + 256] = new_sub_block >> 8;
- if (sub_block == 0)
- sub_block = new_sub_block;
- }
-
- /* call recursive function */
- if (depth > 2)
- {
- err = prodos_fill_file(image, bitmap, sub_block, sub_block_allocated, depth - 1, blockcount, block_index);
- if (err)
- return err;
- }
-
- /* increment index */
- block_index += 1 << ((depth - 2) * 8);
- }
-
- /* if we changed anything, then save the block */
- if (dirty)
- {
- err = prodos_save_block(image, key_block, buffer);
- if (err)
- return err;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_set_file_block_count(imgtool_image *image, prodos_direnum *direnum,
- prodos_dirent *ent, UINT8 *bitmap, int fork_num, UINT32 new_blockcount)
-{
- imgtoolerr_t err;
- int depth, new_depth, i;
- UINT16 new_block, block;
- UINT8 buffer[BLOCK_SIZE];
- UINT16 key_pointer;
-
- if (fork_num && (new_blockcount > 0) && !is_extendedfile_storagetype(ent->storage_type))
- {
- /* need to change a normal file to an extended file */
- err = prodos_promote_file(image, bitmap, ent);
- if (err)
- return err;
- }
-
- key_pointer = ent->key_pointer[fork_num];
- depth = ent->depth[fork_num];
-
- /* determine the new tree depth */
- if (new_blockcount <= 1)
- new_depth = 1;
- else if (new_blockcount <= 256)
- new_depth = 2;
- else
- new_depth = 3;
-
- /* are we zero length, and do we have to create a block? */
- if ((new_blockcount >= 1) && (key_pointer == 0))
- {
- err = prodos_alloc_block(image, bitmap, &new_block);
- if (err)
- return err;
- key_pointer = new_block;
- }
-
- /* do we have to grow the tree? */
- while(new_depth > depth)
- {
- err = prodos_alloc_block(image, bitmap, &new_block);
- if (err)
- return err;
-
- /* create this new key block, with a link to the previous one */
- memset(buffer, 0, sizeof(buffer));
- buffer[0] = (UINT8) (key_pointer >> 0);
- buffer[256] = (UINT8) (key_pointer >> 8);
- err = prodos_save_block(image, new_block, buffer);
- if (err)
- return err;
-
- depth++;
- key_pointer = new_block;
- }
-
- /* do we have to shrink the tree? */
- while(new_depth < depth)
- {
- err = prodos_load_block(image, key_pointer, buffer);
- if (err)
- return err;
-
- for (i = 1; i < 256; i++)
- {
- block = buffer[i + 256];
- block <<= 8;
- block |= buffer[i + 0];
-
- if (block > 0)
- {
- if (depth > 2)
- {
- /* remove this block's children */
- err = prodos_fill_file(image, bitmap, block, FALSE, depth - 1, 0, 0);
- if (err)
- return err;
- }
-
- /* and remove this block */
- prodos_set_volume_bitmap_bit(bitmap, block, 0);
- }
- }
-
- /* remove this key block */
- prodos_set_volume_bitmap_bit(bitmap, key_pointer, 0);
-
- /* set the new key pointer */
- block = buffer[256];
- block <<= 8;
- block |= buffer[0];
- key_pointer = block;
-
- depth--;
- }
-
- if (new_blockcount > 0)
- {
- /* fill out the file tree */
- err = prodos_fill_file(image, bitmap, key_pointer, FALSE, depth, new_blockcount, 0);
- if (err)
- return err;
- }
- else if (key_pointer != 0)
- {
- /* we are now zero length, and don't need a key pointer */
- prodos_set_volume_bitmap_bit(bitmap, key_pointer, 0);
- key_pointer = 0;
- }
-
- /* change the depth if we are not an extended file */
- if (is_normalfile_storagetype(ent->storage_type))
- {
- ent->storage_type &= ~0xF0;
- ent->storage_type |= depth * 0x10;
- }
-
- ent->key_pointer[fork_num] = key_pointer;
- ent->depth[fork_num] = depth;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_set_file_size(imgtool_image *image, prodos_direnum *direnum,
- prodos_dirent *ent, int fork_num, UINT32 new_size)
-{
- imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- UINT32 blockcount, new_blockcount;
- UINT8 *bitmap = NULL;
-
- if (ent->filesize[fork_num] != new_size)
- {
- blockcount = (ent->filesize[fork_num] + BLOCK_SIZE - 1) / BLOCK_SIZE;
- new_blockcount = (new_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
-
- /* do we need to change the block chain? */
- if (new_blockcount != blockcount)
- {
- err = prodos_load_volume_bitmap(image, &bitmap);
- if (err)
- goto done;
-
- err = prodos_set_file_block_count(image, direnum, ent, bitmap, fork_num, new_blockcount);
- if (err)
- goto done;
-
- err = prodos_save_volume_bitmap(image, bitmap);
- if (err)
- goto done;
- }
-
- ent->filesize[fork_num] = new_size;
- err = prodos_put_dirent(image, direnum, ent);
- if (err)
- goto done;
- }
-
-done:
- if (bitmap)
- free(bitmap);
- return err;
-}
-
-
-
-static UINT32 prodos_get_storagetype_maxfilesize(UINT8 storage_type)
-{
- UINT32 max_filesize = 0;
- switch(storage_type & 0xF0)
- {
- case 0x10:
- max_filesize = BLOCK_SIZE * 1;
- break;
- case 0x20:
- max_filesize = BLOCK_SIZE * 256;
- break;
- case 0x30:
- case 0x50:
- max_filesize = BLOCK_SIZE * 32768;
- break;
- }
- return max_filesize;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_beginenum(imgtool_directory *enumeration, const char *path)
-{
- imgtoolerr_t err;
- imgtool_image *image;
- prodos_direnum *appleenum;
- prodos_dirent ent;
- UINT16 block = ROOTDIR_BLOCK;
-
- image = imgtool_directory_image(enumeration);
- appleenum = (prodos_direnum *) imgtool_directory_extrabytes(enumeration);
-
- /* find subdirectory, if appropriate */
- if (*path)
- {
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- /* only work on directories */
- if (!is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- block = ent.key_pointer[0];
- }
-
- /* seek initial block */
- err = prodos_enum_seek(image, appleenum, block, 0);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- imgtoolerr_t err;
- imgtool_image *image;
- prodos_direnum *appleenum;
- prodos_dirent pd_ent;
- UINT32 max_filesize;
-
- image = imgtool_directory_image(enumeration);
- appleenum = (prodos_direnum *) imgtool_directory_extrabytes(enumeration);
-
- do
- {
- err = prodos_get_next_dirent(image, appleenum, &pd_ent);
- if (err)
- return err;
- }
- while(appleenum->block
- && !is_file_storagetype(pd_ent.storage_type)
- && !is_dir_storagetype(pd_ent.storage_type));
-
- /* end of file? */
- if (pd_ent.storage_type == 0x00)
- {
- ent->eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- strcpy(ent->filename, pd_ent.filename);
- ent->directory = is_dir_storagetype(pd_ent.storage_type);
- ent->creation_time = prodos_crack_time(pd_ent.creation_time);
- ent->lastmodified_time = prodos_crack_time(pd_ent.lastmodified_time);
-
- if (!ent->directory)
- {
- ent->filesize = pd_ent.filesize[0];
-
- max_filesize = prodos_get_storagetype_maxfilesize(pd_ent.storage_type);
- if (ent->filesize > max_filesize)
- {
- ent->corrupt = 1;
- ent->filesize = max_filesize;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_read_file_tree(imgtool_image *image, UINT32 *filesize,
- UINT32 block, int nest_level, imgtool_stream *destf)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- UINT8 buffer[BLOCK_SIZE];
- UINT16 sub_block;
- size_t bytes_to_write;
- int i;
-
- /* check bounds */
- di = get_prodos_info(image);
- if (block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTFILE;
-
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
-
- if (nest_level > 0)
- {
- /* this is an index block */
- for (i = 0; i < 256; i++)
- {
- /* retrieve the block pointer; the two bytes are on either half
- * of the block */
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block |= buffer[i + 0];
-
- if (sub_block != 0)
- {
- err = prodos_read_file_tree(image, filesize, sub_block, nest_level - 1, destf);
- if (err)
- return err;
- }
- }
- }
- else
- {
- /* this is a leaf block */
- bytes_to_write = MIN(*filesize, sizeof(buffer));
- stream_write(destf, buffer, bytes_to_write);
- *filesize -= bytes_to_write;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_write_file_tree(imgtool_image *image, UINT32 *filesize,
- UINT32 block, int nest_level, imgtool_stream *sourcef)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- UINT8 buffer[BLOCK_SIZE];
- UINT16 sub_block;
- size_t bytes_to_read;
- int i;
-
- /* nothing more to read? bail */
- if (*filesize == 0)
- return IMGTOOLERR_SUCCESS;
-
- /* check bounds */
- di = get_prodos_info(image);
- if (block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTFILE;
-
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
-
- if (nest_level > 0)
- {
- for (i = 0; i < 256; i++)
- {
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block |= buffer[i + 0];
-
- if (sub_block != 0)
- {
- err = prodos_write_file_tree(image, filesize, sub_block, nest_level - 1, sourcef);
- if (err)
- return err;
- }
- }
- }
- else
- {
- /* this is a leaf block */
- bytes_to_read = MIN(*filesize, sizeof(buffer));
- stream_read(sourcef, buffer, bytes_to_read);
- *filesize -= bytes_to_read;
-
- err = prodos_save_block(image, block, buffer);
- if (err)
- return err;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_freespace(imgtool_partition *partition, UINT64 *size)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- prodos_diskinfo *di;
- UINT8 *bitmap = NULL;
- UINT16 i;
-
- di = get_prodos_info(image);
- *size = 0;
-
- err = prodos_load_volume_bitmap(image, &bitmap);
- if (err)
- goto done;
-
- for (i = 0; i < di->total_blocks; i++)
- {
- if (!prodos_get_volume_bitmap_bit(bitmap, i))
- *size += BLOCK_SIZE;
- }
-
-done:
- if (bitmap)
- free(bitmap);
- return err;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- prodos_dirent ent;
- UINT16 key_pointer;
- int nest_level;
- mac_fork_t fork_num;
-
- err = prodos_lookup_path(image, filename, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
- key_pointer = ent.key_pointer[fork_num];
- nest_level = ent.depth[fork_num] - 1;
-
- if (key_pointer != 0)
- {
- err = prodos_read_file_tree(image, &ent.filesize[fork_num], key_pointer,
- nest_level, destf);
- if (err)
- return err;
- }
-
- /* have we not actually received the correct amount of bytes? if not, fill in the rest */
- if (ent.filesize[fork_num] > 0)
- stream_fill(destf, 0, ent.filesize[fork_num]);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_writefile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- prodos_dirent ent;
- prodos_direnum direnum;
- UINT64 file_size;
- mac_fork_t fork_num;
-
- file_size = stream_size(sourcef);
-
- err = prodos_lookup_path(image, filename, CREATE_FILE, &direnum, &ent);
- if (err)
- return err;
-
- /* only work on files */
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- err = mac_identify_fork(fork, &fork_num);
- if (err)
- return err;
-
- /* set the file size */
- err = prodos_set_file_size(image, &direnum, &ent, fork_num, file_size);
- if (err)
- return err;
-
- err = prodos_write_file_tree(image, &ent.filesize[fork_num], ent.key_pointer[fork_num],
- ent.depth[fork_num] - 1, sourcef);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_deletefile(imgtool_partition *partition, const char *path)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- prodos_dirent ent;
- prodos_direnum direnum;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- return err;
-
- /* only work on files */
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- /* empty out both forks */
- err = prodos_set_file_size(image, &direnum, &ent, 0, 0);
- if (err)
- return err;
- err = prodos_set_file_size(image, &direnum, &ent, 1, 0);
- if (err)
- return err;
-
- memset(&ent, 0, sizeof(ent));
- err = prodos_put_dirent(image, &direnum, &ent);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_listforks(imgtool_partition *partition, const char *path, imgtool_forkent *ents, size_t len)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- prodos_dirent ent;
- prodos_direnum direnum;
- int fork_num = 0;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- return err;
-
- if (is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- /* specify data fork */
- ents[fork_num].type = FORK_DATA;
- ents[fork_num].forkname[0] = '\0';
- ents[fork_num].size = ent.filesize[0];
- fork_num++;
-
- if (is_extendedfile_storagetype(ent.storage_type))
- {
- /* specify the resource fork */
- ents[fork_num].type = FORK_RESOURCE;
- strcpy(ents[fork_num].forkname, "RESOURCE_FORK");
- ents[fork_num].size = ent.filesize[1];
- fork_num++;
- }
-
- ents[fork_num].type = FORK_END;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_createdir(imgtool_partition *partition, const char *path)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- prodos_dirent ent;
- prodos_direnum direnum;
-
- err = prodos_lookup_path(image, path, CREATE_DIR, &direnum, &ent);
- if (err)
- return err;
-
- /* only work on directories */
- if (!is_dir_storagetype(ent.storage_type))
- return IMGTOOLERR_FILENOTFOUND;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_free_directory(imgtool_image *image, UINT8 *volume_bitmap, UINT16 key_pointer)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- int i;
- UINT16 next_block;
- UINT32 offset;
- UINT8 buffer[BLOCK_SIZE];
-
- di = get_prodos_info(image);
-
- if (key_pointer != 0)
- {
- err = prodos_load_block(image, key_pointer, buffer);
- if (err)
- return err;
-
- for (i = 0; i < di->dirents_per_block; i++)
- {
- offset = i * di->dirent_size + 4;
-
- if (is_file_storagetype(buffer[offset]) || is_file_storagetype(buffer[offset]))
- return IMGTOOLERR_DIRNOTEMPTY;
- }
-
- next_block = pick_integer_le(buffer, 2, 2);
-
- err = prodos_free_directory(image, volume_bitmap, next_block);
- if (err)
- return err;
-
- prodos_set_volume_bitmap_bit(volume_bitmap, key_pointer, 0);
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_deletedir(imgtool_partition *partition, const char *path)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- prodos_dirent ent;
- prodos_direnum direnum;
- UINT8 *volume_bitmap = NULL;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- goto done;
-
- /* only work on directories */
- if (!is_dir_storagetype(ent.storage_type))
- {
- err = IMGTOOLERR_FILENOTFOUND;
- goto done;
- }
-
- err = prodos_load_volume_bitmap(image, &volume_bitmap);
- if (err)
- goto done;
-
- err = prodos_free_directory(image, volume_bitmap, ent.key_pointer[0]);
- if (err)
- goto done;
-
- err = prodos_save_volume_bitmap(image, volume_bitmap);
- if (err)
- goto done;
-
- memset(&ent, 0, sizeof(ent));
- err = prodos_put_dirent(image, &direnum, &ent);
- if (err)
- goto done;
-
-done:
- if (volume_bitmap)
- free(volume_bitmap);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_get_file_tree(imgtool_image *image, imgtool_chainent *chain, size_t chain_size,
- size_t *chain_pos, UINT16 block, UINT8 total_depth, UINT8 cur_depth)
-{
- imgtoolerr_t err;
- prodos_diskinfo *di;
- int i;
- UINT16 sub_block;
- UINT8 buffer[BLOCK_SIZE];
-
- if (block == 0)
- return IMGTOOLERR_SUCCESS;
- if (*chain_pos >= chain_size)
- return IMGTOOLERR_SUCCESS;
-
- /* check bounds */
- di = get_prodos_info(image);
- if (block >= di->total_blocks)
- return IMGTOOLERR_CORRUPTFILE;
-
- chain[*chain_pos].level = cur_depth;
- chain[*chain_pos].block = block;
- (*chain_pos)++;
-
- /* must we recurse into the tree? */
- if (cur_depth < total_depth)
- {
- err = prodos_load_block(image, block, buffer);
- if (err)
- return err;
-
- for (i = 0; i < 256; i++)
- {
- sub_block = buffer[i + 256];
- sub_block <<= 8;
- sub_block |= buffer[i + 0];
-
- err = prodos_get_file_tree(image, chain, chain_size, chain_pos, sub_block, total_depth, cur_depth + 1);
- if (err)
- return err;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_getattrs(imgtool_partition *partition, const char *path, const UINT32 *attrs, imgtool_attribute *values)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- prodos_dirent ent;
- int i;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- values[i].i = ent.file_type;
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- values[i].i = ent.file_creator;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- values[i].i = ent.finder_flags;
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- values[i].i = ent.coord_x;
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- values[i].i = ent.coord_y;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- values[i].i = ent.finder_folder;
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- values[i].i = ent.icon_id;
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- values[i].i = ent.script_code;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- values[i].i = ent.extended_flags;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- values[i].i = ent.comment_id;
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- values[i].i = ent.putaway_directory;
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- values[i].t = prodos_crack_time(ent.creation_time);
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- values[i].t = prodos_crack_time(ent.lastmodified_time);
- break;
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_setattrs(imgtool_partition *partition, const char *path, const UINT32 *attrs, const imgtool_attribute *values)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- prodos_dirent ent;
- prodos_direnum direnum;
- int i;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, &direnum, &ent);
- if (err)
- return err;
-
- for (i = 0; attrs[i]; i++)
- {
- switch(attrs[i])
- {
- case IMGTOOLATTR_INT_MAC_TYPE:
- ent.file_type = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_CREATOR:
- ent.file_creator = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFLAGS:
- ent.finder_flags = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COORDX:
- ent.coord_x = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COORDY:
- ent.coord_y = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_FINDERFOLDER:
- ent.finder_folder = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_ICONID:
- ent.icon_id = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_SCRIPTCODE:
- ent.script_code = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_EXTENDEDFLAGS:
- ent.extended_flags = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_COMMENTID:
- ent.comment_id = values[i].i;
- break;
- case IMGTOOLATTR_INT_MAC_PUTAWAYDIRECTORY:
- ent.putaway_directory = values[i].i;
- break;
-
- case IMGTOOLATTR_TIME_CREATED:
- ent.creation_time = prodos_setup_time(values[i].t);
- break;
- case IMGTOOLATTR_TIME_LASTMODIFIED:
- ent.lastmodified_time = prodos_setup_time(values[i].t);
- break;
- }
- }
-
- err = prodos_put_dirent(image, &direnum, &ent);
- if (err)
- return err;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_suggesttransfer(imgtool_partition *partition, const char *path, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- prodos_dirent ent;
- mac_filecategory_t file_category = MAC_FILECATEGORY_DATA;
-
- if (path)
- {
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- file_category = is_extendedfile_storagetype(ent.storage_type)
- ? MAC_FILECATEGORY_FORKED : MAC_FILECATEGORY_DATA;
- }
-
- mac_suggest_transfer(file_category, suggestions, suggestions_length);
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t prodos_diskimage_getchain(imgtool_partition *partition, const char *path, imgtool_chainent *chain, size_t chain_size)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- prodos_dirent ent;
- size_t chain_pos = 0;
- int fork_num;
-
- err = prodos_lookup_path(image, path, CREATE_NONE, NULL, &ent);
- if (err)
- return err;
-
- switch(ent.storage_type & 0xF0)
- {
- case 0x10:
- case 0x20:
- case 0x30:
- /* normal ProDOS file */
- err = prodos_get_file_tree(image, chain, chain_size, &chain_pos,
- ent.key_pointer[0], ent.depth[0] - 1, 0);
- if (err)
- return err;
- break;
-
- case 0x50:
- /* extended ProDOS file */
- chain[chain_pos].level = 0;
- chain[chain_pos].block = ent.extkey_pointer;
- chain_pos++;
-
- for (fork_num = 0; fork_num <= 1; fork_num++)
- {
- if (ent.key_pointer[fork_num])
- {
- err = prodos_get_file_tree(image, chain, chain_size, &chain_pos,
- ent.key_pointer[fork_num], ent.depth[fork_num] - 1, 1);
- if (err)
- return err;
- }
- }
- break;
-
- case 0xE0:
- /* directory */
- return IMGTOOLERR_UNIMPLEMENTED;
-
- default:
- return IMGTOOLERR_UNEXPECTED;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static void generic_prodos_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case IMGTOOLINFO_INT_INITIAL_PATH_SEPARATOR: info->i = 1; break;
- case IMGTOOLINFO_INT_OPEN_IS_STRICT: info->i = 1; break;
- case IMGTOOLINFO_INT_SUPPORTS_CREATION_TIME: info->i = 1; break;
- case IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME: info->i = 1; break;
- case IMGTOOLINFO_INT_WRITING_UNTESTED: info->i = 1; break;
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(prodos_diskinfo); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(prodos_direnum); break;
- case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = '/'; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "ProDOS 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;
-
- /* --- 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_BEGIN_ENUM: info->begin_enum = prodos_diskimage_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = prodos_diskimage_nextenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = prodos_diskimage_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = prodos_diskimage_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = prodos_diskimage_writefile; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = prodos_diskimage_deletefile; break;
- case IMGTOOLINFO_PTR_LIST_FORKS: info->list_forks = prodos_diskimage_listforks; break;
- case IMGTOOLINFO_PTR_CREATE_DIR: info->create_dir = prodos_diskimage_createdir; break;
- case IMGTOOLINFO_PTR_DELETE_DIR: info->delete_dir = prodos_diskimage_deletedir; break;
- case IMGTOOLINFO_PTR_GET_ATTRS: info->get_attrs = prodos_diskimage_getattrs; break;
- case IMGTOOLINFO_PTR_SET_ATTRS: info->set_attrs = prodos_diskimage_setattrs; break;
- case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = prodos_diskimage_suggesttransfer; break;
- case IMGTOOLINFO_PTR_GET_CHAIN: info->get_chain = prodos_diskimage_getchain; break;
- }
-}
-
-
-
-void prodos_525_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "prodos_525"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = prodos_diskimage_create_525; break;
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = prodos_diskimage_open_525; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_apple2; break;
-
- default: generic_prodos_get_info(imgclass, state, info); break;
- }
-}
-
-
-
-void prodos_35_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "prodos_35"); break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = prodos_diskimage_create_35; break;
- case IMGTOOLINFO_PTR_FLOPPY_OPEN: info->open = prodos_diskimage_open_35; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_apple35_iigs; break;
-
- default: generic_prodos_get_info(imgclass, state, info); break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/psion.c b/src/mess/tools/imgtool/modules/psion.c
deleted file mode 100644
index d343dde5c6a..00000000000
--- a/src/mess/tools/imgtool/modules/psion.c
+++ /dev/null
@@ -1,683 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Sandro Ronco
-/***************************************************************************
-
- Psion Organiser II Datapack
-
- 08/18/2010 Sandro Ronco
-
- Known file types:
- 0x00 invalid record
- 0x01 - 0x7e deleted record
- 0x7f invalid deleted record
- 0x80 long record
- 0x81 file name
- 0x82 diary
- 0x83 OPL/OB3 procedure
- 0x84 RS232 setup
- 0x85 - 0x8f reserved
- 0x90 MAIN Record
- 0x91 - 0xfe data records from files
- 0xff invalid record
-
-****************************************************************************/
-
-#include "imgtool.h"
-
-#define MAXFILES 256
-
-struct psion_file
-{
- char filename[9];
- UINT8 type;
- UINT8 id;
-
- UINT16 name_rec;
- UINT16 data_rec;
-};
-
-struct psion_pack
-{
- imgtool_stream *stream;
-
- UINT16 eop;
- struct psion_file pack_index[MAXFILES];
-};
-
-struct psion_iter
-{
- UINT16 index;
-};
-
-UINT16 head_checksum(UINT8* data)
-{
- UINT16 checksum = 0;
-
- for (int i=0; i<6; i+=2)
- checksum += (data[i]<<8 | data[i+1]);
-
- return checksum;
-}
-
-UINT16 get_long_rec_size(imgtool_stream *stream)
-{
- UINT8 size_h, size_l;
-
- stream_read(stream, &size_h, 1);
- stream_read(stream, &size_l, 1);
-
- return (size_h<<8) | size_l;
-}
-
-UINT32 update_pack_index(psion_pack *pack)
-{
- UINT8 data, type;
- UINT16 size;
- UINT16 index = 0;
-
- memset(pack->pack_index, 0, sizeof(psion_file) * MAXFILES);
-
- // start at the first record
- stream_seek(pack->stream, 0x10, SEEK_SET);
-
- do
- {
- stream_read(pack->stream, &data, 1);
-
- if(data == 0xff)
- {
- pack->eop = stream_tell(pack->stream) - 1;
- return TRUE;
- }
- else if (data == 0x02)
- {
- // long record without name are ignored
- stream_read(pack->stream, &data, 1);
- size = get_long_rec_size(pack->stream);
- stream_seek(pack->stream, size, SEEK_CUR);
- }
- else
- {
- stream_read(pack->stream, &type, 1);
-
- // deleted record are not listed
- if (type < 0x90 && (type & 0x80))
- {
- pack->pack_index[index].type = type;
- stream_read(pack->stream, &pack->pack_index[index].filename, 8);
- stream_read(pack->stream, &pack->pack_index[index].id, 1);
- pack->pack_index[index].name_rec = stream_tell(pack->stream) - 11;
-
- //check for data record
- stream_read(pack->stream, &data, 1);
- if (data == 0x02)
- pack->pack_index[index].data_rec = stream_tell(pack->stream) - 1;
-
- stream_seek(pack->stream, -1, SEEK_CUR);
-
- index++;
- }
- else
- stream_seek(pack->stream, data, SEEK_CUR);
- }
-
- } while (stream_size(pack->stream) > stream_tell(pack->stream));
-
- // corrupted image
- return FALSE;
-}
-
-int seek_next_record(imgtool_stream *stream, UINT8 id)
-{
- UINT8 data, rec_id;
- UINT16 size;
-
- do
- {
- stream_read(stream, &data, 1);
-
- if(data == 0xff)
- break;
-
- if (data == 2)
- {
- stream_read(stream, &rec_id, 1);
- size = get_long_rec_size(stream);
-
- }
- else
- {
- stream_read(stream, &rec_id, 1);
- if (id == rec_id)
- {
- stream_seek(stream, -2, SEEK_CUR);
- return TRUE;
- }
- size = data;
- }
-
- // next record
- stream_seek(stream, size, SEEK_CUR);
-
- } while (stream_size(stream) > stream_tell(stream));
-
- return FALSE;
-}
-
-// if there are multiple files with the same name, only the first is found
-int seek_file_name(psion_pack *pack, const char *filename)
-{
- UINT16 index = 0;
-
- while (pack->pack_index[index].name_rec)
- {
- if (!strncmp(filename, pack->pack_index[index].filename, strlen(filename)))
- return index;
- index++;
- }
-
- // filename not found
- return -1;
-}
-
-UINT8 get_free_file_id(psion_pack *pack)
-{
- for (UINT8 file_id=0x91; file_id<0xff; file_id++)
- {
- int index = 0;
-
- while (pack->pack_index[index].id != file_id)
- if (pack->pack_index[index++].name_rec == 0)
- return file_id;
- }
-
- return 0xff;
-}
-
-void put_name_record(imgtool_stream *stream, const char* filename, UINT8 record_type, UINT8 record_id)
-{
- char data[0x10];
- int i = 0;
-
- data[i++] = 0x09;
- data[i++] = record_type;
-
- // filename is 8 char long space filled
- for (int j=0; j<8; j++)
- if (j < strlen(filename))
- data[i++] = filename[j];
- else
- data[i++] = 0x20;
-
- data[i++] = record_id;
-
- stream_write(stream, data, i);
-}
-
-void update_opk_head(imgtool_stream *stream)
-{
- UINT16 size = stream_size(stream) - 6;
-
- stream_seek(stream, 4, SEEK_SET);
- stream_putc(stream, (size>>8) & 0xff);
- stream_putc(stream, size & 0xff);
-}
-
-char *stream_getline(imgtool_stream *source, UINT16 max_len)
-{
- UINT16 pos = 0;
- char data;
- char *line = (char*)malloc(max_len);
- memset(line, 0, max_len);
-
- while (pos < max_len && stream_size(source) > stream_tell(source))
- {
- stream_read(source, &data, 1);
-
- switch(data)
- {
- case '\r':
- stream_read(source, &data, 1);
- if (data != '\n')
- stream_seek(source, -1, SEEK_CUR);
- case '\n':
- return line;
- default:
- line[pos++] = data;
- break;
- }
- }
-
- if (pos)
- return line;
-
- free(line);
- return NULL;
-}
-
-UINT16 put_odb(imgtool_stream *instream, imgtool_stream *outstream, UINT8 file_id)
-{
- char *line;
- UINT16 out_size = 0;
-
- // reset stream
- stream_seek(instream, 0, SEEK_SET);
-
- while ((line = stream_getline(instream, 256)))
- {
- UINT16 len = strlen(line);
-
- stream_putc(outstream, (UINT8)len);
- stream_putc(outstream, file_id);
- stream_write(outstream, line, len);
-
- out_size += (len + 1);
-
- free(line);
- }
-
- // end of pack
- stream_fill(outstream, 0xff, 2);
-
- return out_size + 4;
-}
-
-UINT16 put_ob3(imgtool_stream *instream, imgtool_stream *outstream)
-{
- UINT16 size = stream_size(instream) - 6;
- dynamic_buffer buffer(size);
-
- stream_seek(instream, 6, SEEK_SET);
- stream_read(instream, &buffer[0], size);
-
- stream_write(outstream, &buffer[0], size);
-
- // end of pack
- stream_fill(outstream, 0xff, 2);
-
- return size;
-}
-
-UINT16 put_opl(imgtool_stream *instream, imgtool_stream *outstream)
-{
- UINT16 out_size = 0;
- UINT32 rec_start = stream_tell(outstream);
- char *line;
-
- // reset stream
- stream_seek(instream, 0, SEEK_SET);
-
- stream_fill(outstream, 0x00, 4);
-
- // replace all eol with 0x00
- while ((line = stream_getline(instream, 256)))
- {
- // replace tab with space
- for (int i=0; i<strlen(line); i++)
- if (line[i] == '\t') line[i] = ' ';
-
- stream_write(outstream, line, strlen(line));
- stream_putc(outstream, 0x00);
- out_size += strlen(line) + 1;
- free(line);
- }
-
- // end of pack
- stream_fill(outstream, 0xff, 2);
-
- // update the size in the head
- stream_seek(outstream, rec_start + 2, SEEK_SET);
- stream_putc(outstream, (out_size>>8) & 0xff);
- stream_putc(outstream, out_size & 0xff);
-
- return out_size + 4;
-}
-
-UINT16 get_odb(imgtool_stream *instream, imgtool_stream *outstream, UINT8 type, UINT8 file_id)
-{
- UINT8 data, *buffer;
- UINT16 out_size = 0;
-
- if (file_id >= 0x90)
- while (seek_next_record(instream, file_id))
- {
- stream_read(instream, &data, 1);
- stream_seek(instream, 1, SEEK_CUR);
- buffer = (UINT8*)malloc(data);
- stream_read(instream, buffer, data);
- stream_write(outstream, buffer, data);
- stream_putc(outstream, '\r');
- stream_putc(outstream, '\n');
- free (buffer);
- out_size += data;
- }
-
- return out_size;
-}
-
-UINT16 get_ob3(imgtool_stream *instream, imgtool_stream *outstream, UINT8 type, UINT8 file_id)
-{
- UINT8 data, *buffer = NULL;
- UINT16 size = 0;
- static const char ob3_magic[3] = {'O', 'R', 'G'};
-
- stream_read(instream, &data, 1);
-
- if (data == 0x02)
- {
- stream_seek(instream, 1, SEEK_CUR);
- size = get_long_rec_size(instream);
- buffer = (UINT8*)malloc(size);
- stream_read(instream, buffer, size);
- }
-
- stream_write(outstream, ob3_magic, 3);
- stream_putc(outstream, (size>>8) & 0xff);
- stream_putc(outstream, size & 0xff);
- stream_putc(outstream, type | 0x80);
-
- if (buffer)
- {
- stream_write(outstream, buffer, size);
- free (buffer);
- }
-
- return size;
-}
-
-static imgtoolerr_t datapack_open( imgtool_image *image, imgtool_stream *stream)
-{
- psion_pack *pack = (psion_pack*)imgtool_image_extra_bytes(image);
- char opk_magic[4];
-
- stream_read(stream, opk_magic, 4);
-
- if(strcmp(opk_magic, "OPK\0"))
- return IMGTOOLERR_UNEXPECTED;
-
- pack->stream = stream;
-
- if (update_pack_index(pack))
- return IMGTOOLERR_SUCCESS;
- else
- return IMGTOOLERR_CORRUPTIMAGE;
-}
-
-static imgtoolerr_t datapack_create( imgtool_image *image, imgtool_stream *stream, option_resolution *opts)
-{
- psion_pack *pack = (psion_pack*)imgtool_image_extra_bytes(image);
- static const UINT8 opk_magic[4] = {'O', 'P', 'K', 0x00};
- UINT8 pack_head[8] = {0x40, 0x00, 0x59, 0x01, 0x01, 0x01, 0x00, 0x00};
- UINT16 checksum;
-
- pack_head[0] |= (option_resolution_lookup_int(opts, 'R')) ? 0x00 : 0x02;
- pack_head[0] |= (option_resolution_lookup_int(opts, 'P')) ? 0x04 : 0x00;
- pack_head[0] |= (option_resolution_lookup_int(opts, 'W')) ? 0x00 : 0x08;
- pack_head[0] |= (option_resolution_lookup_int(opts, 'B')) ? 0x00 : 0x10;
- pack_head[0] |= (option_resolution_lookup_int(opts, 'C')) ? 0x20 : 0x00;
- pack_head[1] = option_resolution_lookup_int(opts, 'S');
-
- checksum = head_checksum(pack_head);
-
- stream_write(stream, opk_magic, 4);
- stream_fill(stream, 0x00, 2);
- stream_write(stream, pack_head, 8);
-
- stream_putc(stream, (checksum>>8) & 0xff);
- stream_putc(stream, checksum & 0xff);
-
- put_name_record(stream, "MAIN", 0x81, 0x90);
-
- stream_fill(stream, 0xff, 2);
-
- update_opk_head(stream);
-
- pack->stream = stream;
-
- if (update_pack_index(pack))
- return IMGTOOLERR_SUCCESS;
- else
- return IMGTOOLERR_CORRUPTIMAGE;
-}
-
-static void datapack_close( imgtool_image *image)
-{
- psion_pack *pack = (psion_pack*)imgtool_image_extra_bytes(image);
-
- stream_close( pack->stream );
-}
-
-static imgtoolerr_t datapack_begin_enum(imgtool_directory *enumeration, const char *path)
-{
- psion_iter *iter = (psion_iter*)imgtool_directory_extrabytes(enumeration);
- iter->index = 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t datapack_next_enum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- imgtool_image *image = imgtool_directory_image(enumeration);
- psion_pack *pack = (psion_pack*)imgtool_image_extra_bytes(image);
- psion_iter *iter = (psion_iter*)imgtool_directory_extrabytes(enumeration);
- UINT8 data = 0;
-
- if (!pack->pack_index[iter->index].name_rec)
- {
- ent->eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
- memcpy(ent->filename, pack->pack_index[iter->index].filename, 8);
- sprintf(ent->attr, "Type: %02x ID: %02x", pack->pack_index[iter->index].type, pack->pack_index[iter->index].id);
-
- if (pack->pack_index[iter->index].data_rec)
- {
- stream_seek(pack->stream, pack->pack_index[iter->index].data_rec + 2, SEEK_SET);
- ent->filesize = get_long_rec_size(pack->stream);
- }
-
- // seek all file's records
- if (pack->pack_index[iter->index].id >= 0x90)
- {
- stream_seek(pack->stream, 0x10, SEEK_SET);
- while (seek_next_record(pack->stream, pack->pack_index[iter->index].id))
- {
- stream_read(pack->stream, &data, 1);
- stream_seek(pack->stream, data + 1, SEEK_CUR);
- ent->filesize +=data;
- }
- }
-
- iter->index++;
- return IMGTOOLERR_SUCCESS;
-}
-
-static void datapack_close_enum( imgtool_directory *enumeration)
-{
-}
-
-static imgtoolerr_t datapack_free_space( imgtool_partition *partition, UINT64 *size)
-{
- imgtool_image *image = imgtool_partition_image( partition);
- psion_pack *pack = (psion_pack*)imgtool_image_extra_bytes(image);
- UINT32 pack_size = 0;
-
- stream_seek(pack->stream, 0x07, SEEK_SET);
- stream_read(pack->stream, &pack_size, 1);
-
- if (size)
- *size = (pack_size * 0x2000) - pack->eop;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t datapack_read_file(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- imgtool_image *image = imgtool_partition_image(partition);
- psion_pack *pack = (psion_pack*)imgtool_image_extra_bytes(image);
- int index = seek_file_name(pack, filename);
-
- if (index >= 0)
- {
- if ((pack->pack_index[index].type & 0x7f) == 0x01)
- {
- // ODB files
- stream_seek(pack->stream, 0x10, SEEK_SET);
- get_odb(pack->stream, destf, pack->pack_index[index].type, pack->pack_index[index].id);
- }
- else if ((pack->pack_index[index].type & 0x7f) == 0x03)
- {
- // OB3/OPL files
- stream_seek(pack->stream, pack->pack_index[index].data_rec, SEEK_SET);
- get_ob3(pack->stream, destf, pack->pack_index[index].type, pack->pack_index[index].id);
- }
- else
- {
- // Other files
- return IMGTOOLERR_UNIMPLEMENTED;
- }
-
- return IMGTOOLERR_SUCCESS;
- }
- else
- return IMGTOOLERR_FILENOTFOUND;
-}
-
-static imgtoolerr_t datapack_write_file( imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- imgtool_image *image = imgtool_partition_image(partition);
- psion_pack *pack = (psion_pack*)imgtool_image_extra_bytes(image);
- static const UINT8 data_head[4] = {0x02, 0x80, 0x00, 0x00};
- UINT8 head[3];
- UINT16 size = 0;
- UINT8 type = option_resolution_lookup_int(opts, 'T');
- UINT8 file_id = option_resolution_lookup_int(opts, 'I');
-
- if (!pack->eop)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- // if not file_id is specified get the first free (for ODB only)
- if (file_id == 0 && type == 3)
- {
- file_id = get_free_file_id(pack);
-
- if (file_id == 0xff)
- return IMGTOOLERR_NOSPACE;
- }
-
- stream_read(sourcef, head, 3);
- stream_seek(pack->stream, pack->eop, SEEK_SET);
-
- if (type == 0)
- type = (!strncmp((char*)head, "ORG", 3)) ? 1 : 2;
-
- switch (type)
- {
- case 1: //OB3 file
- put_name_record(pack->stream, filename, 0x83, file_id);
- stream_write(pack->stream, data_head, 4);
- size = put_ob3(sourcef, pack->stream);
- break;
- case 2: //OPL file
- put_name_record(pack->stream, filename, 0x83, file_id);
- stream_write(pack->stream, data_head, 4);
- size = put_opl(sourcef, pack->stream);
- break;
- case 3: //ODB file
- put_name_record(pack->stream, filename, 0x81, file_id);
- size = put_odb(sourcef, pack->stream, file_id);
- break;
- }
-
- if (type != 3)
- {
- // update the OB3/OPL long record size
- stream_seek(pack->stream, pack->eop + 13, SEEK_SET);
- stream_putc(pack->stream, (size>>8) & 0xff);
- stream_putc(pack->stream, size & 0xff);
- }
-
- update_opk_head(pack->stream);
-
- if (update_pack_index(pack))
- return IMGTOOLERR_SUCCESS;
- else
- return IMGTOOLERR_CORRUPTIMAGE;
-}
-
-static imgtoolerr_t datapack_delete_file( imgtool_partition *partition, const char *filename)
-{
- imgtool_image *image = imgtool_partition_image(partition);
- psion_pack *pack = (psion_pack*)imgtool_image_extra_bytes(image);
- int index = seek_file_name(pack, filename);
-
- if (index >= 0)
- {
- // clear the bit 7 of the file type to mark the file as deleted
- stream_seek(pack->stream, pack->pack_index[index].name_rec + 1, SEEK_SET);
- stream_putc(pack->stream, pack->pack_index[index].type & 0x7f);
-
- if (update_pack_index(pack))
- return IMGTOOLERR_SUCCESS;
- else
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- else
- return IMGTOOLERR_FILENOTFOUND;
-}
-
-static OPTION_GUIDE_START( psion_create_optguide )
- OPTION_ENUM_START( 'S', "size", "datapack size" )
- OPTION_ENUM( 1, "8k", "8 kbyte" )
- OPTION_ENUM( 2, "16k", "16 kbyts" )
- OPTION_ENUM( 4, "32k", "32 kbyte" )
- OPTION_ENUM( 8, "64k", "64 kbyte" )
- OPTION_ENUM( 16, "128k", "128 kbyte" ) // only paged datapacks can have this size
- OPTION_ENUM_END
- OPTION_INT('R', "ram", "EPROM/RAM datapack" )
- OPTION_INT('P', "paged", "linear/paged datapack" )
- OPTION_INT('W', "protect", "write-protected datapack" )
- OPTION_INT('B', "boot", "bootable datapack" )
- OPTION_INT('C', "copy", "copyable datapack" )
-OPTION_GUIDE_END
-
-static OPTION_GUIDE_START( psion_write_optguide )
- OPTION_ENUM_START( 'T', "type", "file type" )
- OPTION_ENUM( 1, "OB3", "OB3 files" )
- OPTION_ENUM( 2, "OPL", "OPL files" )
- OPTION_ENUM( 3, "ODB", "ODB or text files" )
- OPTION_ENUM_END
- OPTION_INT( 'I', "id", "File ID" )
-OPTION_GUIDE_END
-
-void psion_get_info( const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch (state)
- {
- // --- the following bits of info are returned as 64-bit signed integers ---
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES : info->i = sizeof(psion_pack); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES : info->i = sizeof(psion_iter); break;
-
- // --- the following bits of info are returned as pointers to data or functions ---
- case IMGTOOLINFO_PTR_OPEN : info->open = datapack_open; break;
- case IMGTOOLINFO_PTR_CREATE : info->create = datapack_create; break;
- case IMGTOOLINFO_PTR_CLOSE : info->close = datapack_close; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM : info->begin_enum = datapack_begin_enum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM : info->next_enum = datapack_next_enum; break;
- case IMGTOOLINFO_PTR_CLOSE_ENUM : info->close_enum = datapack_close_enum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE : info->free_space = datapack_free_space; break;
- case IMGTOOLINFO_PTR_READ_FILE : info->read_file = datapack_read_file; break;
- case IMGTOOLINFO_PTR_WRITE_FILE : info->write_file = datapack_write_file; break;
- case IMGTOOLINFO_PTR_DELETE_FILE : info->delete_file = datapack_delete_file; break;
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE : info->createimage_optguide = psion_create_optguide; break;
- case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE : info->createimage_optguide = psion_write_optguide; break;
-
- // --- the following bits of info are returned as NULL-terminated strings ---
- case IMGTOOLINFO_STR_NAME : strcpy( info->s = imgtool_temp_str(), "psionpack"); break;
- case IMGTOOLINFO_STR_DESCRIPTION : strcpy( info->s = imgtool_temp_str(), "Psion Organiser II Datapack"); break;
- case IMGTOOLINFO_STR_FILE : strcpy( info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS : strcpy( info->s = imgtool_temp_str(), "opk"); break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC : strcpy( info->s = imgtool_temp_str(), "S1/2/[4]/8/16;R[0]/1;P[0]/1;W0/[1];B[0]/1;C0/[1]"); break;
- case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC : strcpy( info->s = imgtool_temp_str(), "T[1]/2/3;I[0]/145-255"); break;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/rsdos.c b/src/mess/tools/imgtool/modules/rsdos.c
deleted file mode 100644
index 8323574b001..00000000000
--- a/src/mess/tools/imgtool/modules/rsdos.c
+++ /dev/null
@@ -1,623 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/****************************************************************************
-
- rsdos.c
-
- CoCo RS-DOS disk images
-
-****************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include "imgtool.h"
-#include "formats/coco_dsk.h"
-#include "iflopimg.h"
-
-/* this structure mirrors the structure of an RS-DOS directory entry on disk */
-struct rsdos_dirent
-{
- char fname[8];
- char fext[3];
- 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;
- int eof;
-};
-
-#define RSDOS_OPTIONS_FTYPE 'T'
-#define RSDOS_OPTIONS_ASCII 'M'
-
-
-
-/*********************************************************************
- Imgtool module code
-*********************************************************************/
-
-#define MAX_DIRENTS ((18-2)*(256/32))
-static floperr_t get_rsdos_dirent(imgtool_image *f, int index_loc, struct rsdos_dirent *ent)
-{
- return floppy_read_sector(imgtool_floppy(f), 0, 17, 3, index_loc * 32, (void *) ent, sizeof(*ent));
-}
-
-
-
-static floperr_t put_rsdos_dirent(imgtool_image *f, int index_loc, const struct 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 */
-}
-
-
-
-/* fnamebuf must have at least 13 bytes */
-static void get_dirent_fname(char *fnamebuf, const struct rsdos_dirent *ent)
-{
- char *s;
-
- memset(fnamebuf, 0, 13);
- memcpy(fnamebuf, ent->fname, sizeof(ent->fname));
- rtrim(fnamebuf);
- s = fnamebuf + strlen(fnamebuf);
- *(s++) = '.';
- memcpy(s, ent->fext, sizeof(ent->fext));
- rtrim(s);
-
- /* If no extension, remove period */
- if (*s == '\0')
- s[-1] = '\0';
-}
-
-
-
-static imgtoolerr_t lookup_rsdos_file(imgtool_image *f, const char *fname, struct rsdos_dirent *ent, int *position)
-{
- int i;
- floperr_t ferr;
- char fnamebuf[13];
-
- i = 0;
- fnamebuf[0] = '\0';
-
- do
- {
- do
- {
- ferr = get_rsdos_dirent(f, i++, ent);
- if (ferr)
- return imgtool_floppy_error(ferr);
- }
- while(ent->fname[0] == '\0');
-
-
- if (ent->fname[0] != -1)
- get_dirent_fname(fnamebuf, ent);
- }
- while((ent->fname[0] != -1) && core_stricmp(fnamebuf, fname));
-
- if (ent->fname[0] == -1)
- return IMGTOOLERR_FILENOTFOUND;
-
- if (position)
- *position = i - 1;
- return (imgtoolerr_t)0;
-}
-
-
-
-static UINT8 get_granule_count(imgtool_image *img)
-{
- UINT16 tracks;
- UINT16 granules;
-
- tracks = floppy_get_tracks_per_disk(imgtool_floppy(img));
- granules = (tracks - 1) * 2;
- return (granules > 255) ? 255 : (UINT8) granules;
-}
-
-#define MAX_GRANULEMAP_SIZE 256
-
-/* granule_map must be an array of MAX_GRANULEMAP_SIZE bytes */
-static floperr_t get_granule_map(imgtool_image *img, UINT8 *granule_map, UINT8 *granule_count)
-{
- UINT8 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);
-}
-
-
-
-static floperr_t put_granule_map(imgtool_image *img, const UINT8 *granule_map, UINT8 granule_count)
-{
- return floppy_write_sector(imgtool_floppy(img), 0, 17, 2, 0, granule_map, granule_count, 0); /* TODO: pass ddam argument from imgtool */
-}
-
-
-
-
-static imgtoolerr_t transfer_granule(imgtool_image *img, UINT8 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 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;
-}
-
-
-
-static imgtoolerr_t transfer_from_granule(imgtool_image *img, UINT8 granule, int length, imgtool_stream *destf)
-{
- return transfer_granule(img, granule, length, destf, imgtool_floppy_read_sector_to_stream);
-}
-
-
-
-static imgtoolerr_t transfer_to_granule(imgtool_image *img, UINT8 granule, int length, imgtool_stream *sourcef)
-{
- return transfer_granule(img, granule, length, sourcef, imgtool_floppy_write_sector_from_stream);
-}
-
-
-
-static imgtoolerr_t process_rsdos_file(struct rsdos_dirent *ent, imgtool_image *img, imgtool_stream *destf, size_t *size)
-{
- floperr_t ferr;
- size_t s, lastgransize;
- UINT8 granule_count;
- unsigned char i = 0, granule;
- UINT8 usedmap[MAX_GRANULEMAP_SIZE]; /* Used to detect infinite loops */
- UINT8 granule_map[MAX_GRANULEMAP_SIZE];
-
- ferr = get_granule_map(img, granule_map, &granule_count);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- memset(usedmap, 0, granule_count);
-
- lastgransize = ent->lastsectorbytes_lsb + (((int) ent->lastsectorbytes_msb) << 8);
- s = 0;
- granule = ent->first_granule;
-
- while(!usedmap[granule] && ((i = granule_map[granule]) < granule_count))
- {
- usedmap[granule] = 1;
- if (destf)
- transfer_from_granule(img, granule, 9*256, destf);
-
- /* i is the next granule */
- s += (256 * 9);
- granule = i;
- }
-
- if ((i < 0xc0) || (i > 0xc9))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (lastgransize)
- i--;
- lastgransize += (256 * (i - 0xc0));
-
- if (destf)
- transfer_from_granule(img, granule, lastgransize, destf);
-
- if (size)
- *size = s + lastgransize;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/* create a new directory entry with a specified name */
-static imgtoolerr_t prepare_dirent(struct rsdos_dirent *ent, const char *fname)
-{
- const char *fname_end;
- const char *fname_ext;
- int fname_ext_len;
-
- memset(ent, '\0', sizeof(*ent));
- memset(ent->fname, ' ', sizeof(ent->fname));
- memset(ent->fext, ' ', sizeof(ent->fext));
-
- fname_end = strchr(fname, '.');
- if (fname_end)
- fname_ext = fname_end + 1;
- else
- fname_end = fname_ext = fname + strlen(fname);
-
- fname_ext_len = strlen(fname_ext);
-
- /* We had better be an 8.3 filename */
- if (((fname_end - fname) > 8) || (fname_ext_len > 3))
- return IMGTOOLERR_BADFILENAME;
-
- memcpy(ent->fname, fname, fname_end - fname);
- memcpy(ent->fext, fname_ext, fname_ext_len);
-
- /* For now, all files are type 2 binary files */
- ent->ftype = 2;
- ent->asciiflag = 0;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t rsdos_diskimage_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- floperr_t ferr;
- imgtoolerr_t err;
- size_t filesize;
- struct rsdos_direnum *rsenum;
- struct rsdos_dirent rsent;
- char fname[13];
- imgtool_image *image;
-
- image = imgtool_directory_image(enumeration);
- rsenum = (struct rsdos_direnum *) imgtool_directory_extrabytes(enumeration);
-
- /* Did we hit the end of file before? */
- if (rsenum->eof)
- goto eof;
-
- do
- {
- if (rsenum->index >= MAX_DIRENTS)
- goto eof;
-
- ferr = get_rsdos_dirent(image, rsenum->index++, &rsent);
- if (ferr)
- return imgtool_floppy_error(ferr);
- }
- while(rsent.fname[0] == '\0');
-
- /* Now are we at the eof point? */
- if (rsent.fname[0] == -1)
- {
- rsenum->eof = 1;
-eof:
- ent->eof = 1;
- }
- else
- {
- /* Not the end of file */
- err = process_rsdos_file(&rsent, image, NULL, &filesize);
- if (err)
- return err;
-
- if (filesize == ((size_t) -1))
- {
- /* corrupt! */
- ent->filesize = 0;
- ent->corrupt = 1;
- }
- else
- {
- ent->filesize = filesize;
- ent->corrupt = 0;
- }
- ent->eof = 0;
-
- get_dirent_fname(fname, &rsent);
-
- snprintf(ent->filename, ARRAY_LENGTH(ent->filename), "%s", fname);
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "%d %c", (int) rsent.ftype, (char) (rsent.asciiflag + 'B'));
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t rsdos_diskimage_freespace(imgtool_partition *partition, UINT64 *size)
-{
- floperr_t ferr;
- UINT8 i;
- size_t s = 0;
- UINT8 granule_count;
- UINT8 granule_map[MAX_GRANULEMAP_SIZE];
- imgtool_image *image = imgtool_partition_image(partition);
-
- ferr = get_granule_map(image, granule_map, &granule_count);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- for (i = 0; i < granule_count; i++)
- {
- if (granule_map[i] == 0xff)
- s += (9 * 256);
- }
- *size = s;
- return (imgtoolerr_t)FLOPPY_ERROR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t delete_entry(imgtool_image *img, struct rsdos_dirent *ent, int pos)
-{
- floperr_t ferr;
- unsigned char g, i;
- UINT8 granule_count;
- UINT8 granule_map[MAX_GRANULEMAP_SIZE];
-
- /* Write a NUL in the filename, marking it deleted */
- ent->fname[0] = 0;
- ferr = put_rsdos_dirent(img, pos, ent);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- ferr = get_granule_map(img, granule_map, &granule_count);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- /* Now free up the granules */
- g = ent->first_granule;
- while (g < granule_count)
- {
- i = granule_map[g];
- granule_map[g] = 0xff;
- g = i;
- }
-
- ferr = put_granule_map(img, granule_map, granule_count);
- if (ferr)
- return imgtool_floppy_error(ferr);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-static imgtoolerr_t rsdos_diskimage_readfile(imgtool_partition *partition, const char *fname, const char *fork, imgtool_stream *destf)
-{
- imgtoolerr_t err;
- struct rsdos_dirent ent;
- size_t size;
- imgtool_image *img = imgtool_partition_image(partition);
-
- err = lookup_rsdos_file(img, fname, &ent, NULL);
- if (err)
- return err;
-
- err = process_rsdos_file(&ent, img, destf, &size);
- if (err)
- return err;
-
- if (size == (size_t) -1)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- return (imgtoolerr_t)0;
-}
-
-
-
-static imgtoolerr_t rsdos_diskimage_writefile(imgtool_partition *partition, const char *fname, const char *fork, imgtool_stream *sourcef, option_resolution *writeoptions)
-{
- floperr_t ferr;
- imgtoolerr_t err;
- imgtool_image *img = imgtool_partition_image(partition);
- struct rsdos_dirent ent, ent2;
- size_t i;
- UINT64 sz;
- UINT64 freespace = 0;
- unsigned char g;
- unsigned char *gptr;
- UINT8 granule_count;
- UINT8 granule_map[MAX_GRANULEMAP_SIZE];
-
- /* can we write to this image? */
- if (floppy_is_read_only(imgtool_floppy(img)))
- return IMGTOOLERR_READONLY;
-
- err = rsdos_diskimage_freespace(partition, &freespace);
- if (err)
- return err;
-
- /* is there enough space? */
- sz = stream_size(sourcef);
- if (sz > freespace)
- return IMGTOOLERR_NOSPACE;
-
- /* setup our directory entry */
- err = prepare_dirent(&ent, fname);
- if (err)
- return err;
-
- ent.ftype = option_resolution_lookup_int(writeoptions, RSDOS_OPTIONS_FTYPE);
- ent.asciiflag = ((UINT8) option_resolution_lookup_int(writeoptions, RSDOS_OPTIONS_ASCII)) - 1;
- ent.lastsectorbytes_lsb = sz % 256;
- ent.lastsectorbytes_msb = (((sz % 256) == 0) && (sz > 0)) ? 1 : 0;
- gptr = &ent.first_granule;
-
- ferr = get_granule_map(img, granule_map, &granule_count);
- if (ferr)
- return imgtool_floppy_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 = MIN(sz, (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.fname[0] != '\0') && strcmp(ent.fname, ent2.fname) && (ent2.fname[0] != -1));
-
- /* delete file if it already exists */
- if (ent2.fname[0] && (ent2.fname[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;
-}
-
-
-
-static imgtoolerr_t rsdos_diskimage_deletefile(imgtool_partition *partition, const char *fname)
-{
- imgtoolerr_t err;
- imgtool_image *image = imgtool_partition_image(partition);
- int pos;
- struct rsdos_dirent ent;
-
- err = lookup_rsdos_file(image, fname, &ent, &pos);
- if (err)
- return err;
-
- return delete_entry(image, &ent, pos);
-}
-
-
-
-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 = imgtool_partition_image(partition);
- 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 = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = filter_eoln_getinfo;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
- }
- else if (ent.ftype == 0)
- {
- /* tokenized BASIC file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = filter_cocobas_getinfo;
- }
- }
- else
- {
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = filter_eoln_getinfo;
- suggestions[2].viability = SUGGESTION_POSSIBLE;
- suggestions[2].filter = filter_cocobas_getinfo;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-
-/*********************************************************************
- Imgtool module declaration
-*********************************************************************/
-
-static 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 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 NULL-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;
- }
-}
diff --git a/src/mess/tools/imgtool/modules/thomson.c b/src/mess/tools/imgtool/modules/thomson.c
deleted file mode 100644
index 43684bc0aea..00000000000
--- a/src/mess/tools/imgtool/modules/thomson.c
+++ /dev/null
@@ -1,1681 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Antoine Mine
-/****************************************************************************
-
- Copyright (C) Antoine Mine' 2006
-
- Thomson 8-bit micro-computers.
-
- Handles SAP, QD and FD floppy formats with a BASIC-DOS filesystem
- (most floppies except some games and demo).
-
-*****************************************************************************/
-
-/* TODO:
- - improve two-sided floppy support
- - check & correct BASIC read filter
- - implement BASIC write filter
- - handle accented letters
- */
-
-
-/* Thomson floppy geometry are:
- - 5"1/4 single density: 40 tracks, 16 sectors/track, 128 bytes/sector
- - 5"1/4 double density: 40 tracks, 16 sectors/track, 256 bytes/sector
- - 3"1/2 double density: 80 tracks, 16 sectors/track, 256 bytes/sector
- - 2"8: 25 logical tracks, 16 logical sectors/track, 128 bytes/sector
-
- Notes:
-
- - 2"8 QDD actually contain a single spiraling track, with 400 128-byte
- sectors; however, the filesystem considers it has 25 virtual tracks of
- 16 sectors => we do the same in imgtool (but thomflop.c uses a 400-sector
- addressing to emulate the device hardware)
-
- - tracks always have 16 sectors, this is requred by the filesystem
-
- - two-sided floppies are handled as two one-sided floppies in two
- logical floppy drives on the original Thomsons; each has its own
- independent FAT and directory.
- In imgtool, we handle two-sided images as two partitions.
- For now, only 3"1/2 .fd and QDD .qd files can be two-sided.
-
- - it seems possible to create 3"1/2 single density floppies on the TO9,
- I am not sure this is standard, and we do not support it...
-
-*/
-
-
-/* Microsoft BASIC Filesystem.
-
- The floppy is divided into blocks, with always two blocks / track.
- Also, in double density, only the first 255 bytes of each 256-byte
- sector is used. Thus, blocks are 1024 bytes in single density, and
- 2040 bytes in double density.
- Depending on the number of tracks, there can be 50, 80 or 160 blocks.
-
- Filesystem data always occupy track 20, whatever the floppy geometry.
-
- * sector 1:
- - bytes 0-7: floppy name
- - remaining bytes: undocumented, seem unused
-
- * sector 2: FAT, 1 byte info per block
- - byte 0: always 0
- - byte 1: block 0
- ...
- - byte i: block i-1
- ...
- - byte 160: block 159
- - remaining bytes: undocumented, seem unused
-
- The byte has the following meaning:
- - ff: block is free
- - fb: block is reserved
- - 00-bf: block allocated, points to then next file block
- - c1-c8: last block in file, (value & 15) is the number of sectors
- actually allocated to the file
-
- Note: in single density, we can reference only 127 blocks. This is not
- a problem because single density floppies can only have 50 or 80 blocks,
- never 160.
-
- * sector 3-16: directory
-
- no subdirectories
-
- each file entry occupies 32 bytes:
- - bytes 00-07: filename, padded with whitespaces
- - bytes 08-0A: file extension, padedd with whitespaces
- - byte 0B: file type
- . 0 = BASIC, ASCII or binary program (B)
- . 1 = BASIC or ASCII data (D)
- . 2 = machine code (M)
- . 3 = ASCII assembler file (A)
- - byte 0C: format flag
- . 00 = binary (tokenized)
- . ff = ASCII
- - byte 0D: first block
- - bytes 0E-0F: bytes used in the last sector
- - bytes 10-17: comment
- - byte 18: day (of month)
- - byte 19: month
- - byte 1A: year (two last digits)
- - bytes 1B-1f: unknown
-
- Note that byte 0 has a special significance:
- - 00: free directory entry
- - 20-7F: actual directory entry, value is the first character ini filename
- - ff: end of directory
-
- There can be 56 files in single density, 112 in double density.
- */
-
-#include "imgtool.h"
-#include "iflopimg.h"
-
-#include <time.h>
-
-
-#define MAXSIZE 80*16*256*2 /* room for two faces, double-density, 80 tracks */
-
-struct thom_floppy {
- imgtool_stream *stream;
-
- UINT16 sector_size; /* 128 or 256 */
- UINT16 sectuse_size; /* bytes used in sector: 128 or 255 */
- UINT8 tracks; /* 25, 40, or 80 */
- UINT8 heads; /* 1 or 2 */
- UINT8 data[MAXSIZE]; /* image data */
-
- int modified; /* data need to be copied back to image file */
-
-};
-
-
-enum thom_dirent_type {
- THOM_DIRENT_END,
- THOM_DIRENT_FREE,
- THOM_DIRENT_FILE,
- THOM_DIRENT_INVALID,
-
-};
-
-
-struct thom_dirent {
- thom_dirent_type type;
- int index;
-
- char name[9];
- char ext[4];
- char comment[9];
- UINT8 ftype;
- UINT8 format;
- UINT8 firstblock;
- UINT16 lastsectsize;
- UINT8 day;
- UINT8 month;
- UINT8 year;
-
-};
-
-
-static void thom_basic_get_info(const imgtool_class *clas, UINT32 param,
- union imgtoolinfo *info);
-
-static UINT8* thom_get_sector(thom_floppy* f, unsigned head,
- unsigned track, unsigned sector);
-
-
-/*********************** .fd / .qd format ************************/
-
-/* .fd and .qd formats are very simple: the sectors are simply put one after
- another, starting at sector 1 of track 0 to sector 16 track 0, then
- starting again at sector 1 of track 1, and so on.
- There is no image or sector header, and no gap between sectors.
- The number of tracks and sector size are determined by the extension
- (.fd have 40 or 80 tracks, .qd have 25 tracks) and the file size.
-*/
-
-static imgtoolerr_t thom_open_fd_qd(imgtool_image *img, imgtool_stream *stream)
-{
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- int size = stream_size( stream );
-
- f->stream = stream;
- f->modified = 0;
-
- /* guess format */
- switch ( size ) {
- case 81920:
- f->tracks = 40;
- f->sector_size = 128;
- f->sectuse_size = 128;
- f->heads = 1;
- break;
-
- case 163840:
- f->tracks = 40;
- f->sector_size = 256;
- f->sectuse_size = 255;
- f->heads = 1;
- /* could also be: sector_size=128, heads=2 */
- /* maight even be: tracks=80, sector_size=128 */
- break;
-
- case 327680:
- f->tracks = 80;
- f->sector_size = 256;
- f->sectuse_size = 255;
- f->heads = 1;
- /* could also be: tracks=40, heads=2 */
- break;
-
- case 655360:
- f->tracks = 80;
- f->sector_size = 256;
- f->sectuse_size = 255;
- f->heads = 2;
- break;
-
- case 51200:
- f->tracks = 25;
- f->sector_size = 128;
- f->sectuse_size = 128;
- f->heads = 1;
- break;
-
- case 62400:
- f->tracks = 25;
- f->sector_size = 128;
- f->sectuse_size = 128;
- f->heads = 2;
- break;
-
- default:
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- assert( size == f->heads * f->tracks * 16 * f->sector_size );
-
- stream_seek( stream, 0, SEEK_SET );
- if ( stream_read( stream, f->data, size ) < size )
- return IMGTOOLERR_READERROR;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static void thom_close_fd_qd(imgtool_image *img)
-{
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
-
- /* save image */
- if ( f->modified ) {
- int size = f->heads * f->tracks * 16 * f->sector_size;
- stream_seek( f->stream, 0, SEEK_SET );
- if ( stream_write( f->stream, f->data, size ) < size )
- {
- /* logerror( "thom_diskimage_close_fd_qd: write error\n" ); */
- }
- }
-
- stream_close( f->stream );
-}
-
-
-/*********************** .sap format ************************/
-
-/* SAP format, Copyright 1998 by Alexandre Pukall
-
- image is composed of:
- - byte 0: version (0 or 1)
- - bytes 1..65: signature
- - bytes 66..end: sectors
-
- each sector is composed of
- - a 4-byte header:
- . byte 0: format
- 0 3"1/2 double density
- 1 5"1/4 low density
- . byte 1: protection (?)
- . byte 2: track index, in 0..79
- . byte 3: sector index, in 1..16
- - sector data, XOR 0xB3
- - 2-byte CRC of header + data, high byte first
-
- there is no provision for two-sided images in sap
- */
-
-static const int sap_magic_num = 0xB3; /* simple XOR crypt */
-
-static const char sap_header[]=
- "\001SYSTEME D'ARCHIVAGE PUKALL S.A.P. "
- "(c) Alexandre PUKALL Avril 1998";
-
-static const UINT16 sap_crc[] = {
- 0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387,
- 0x8408, 0x9489, 0xa50a, 0xb58b, 0xc60c, 0xd68d, 0xe70e, 0xf78f,
-};
-
-static UINT16 thom_sap_crc( UINT8* data, int size )
-{
- int i;
- UINT16 crc = 0xffff, crc2;
- for ( i = 0; i < size; i++ ) {
- crc2 = ( crc >> 4 ) ^ sap_crc[ ( crc ^ data[i] ) & 15 ];
- crc = ( crc2 >> 4 ) ^ sap_crc[ ( crc2 ^ (data[i] >> 4) ) & 15 ];
- }
- return crc;
-}
-
-static imgtoolerr_t thom_open_sap(imgtool_image *img, imgtool_stream *stream)
-{
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- UINT8 buf[262];
-
- f->stream = stream;
- f->modified = 0;
-
- /* check image header */
- stream_seek( stream, 0, SEEK_SET );
- stream_read( stream, buf, 66 );
- if ( memcmp( buf+1, sap_header+1, 65 ) ) return IMGTOOLERR_CORRUPTIMAGE;
-
- /* guess format */
- stream_read( stream, buf, 1 );
- switch ( buf[0] ) {
- case 1:
- case 3:
- f->heads = 1;
- f->tracks = 40;
- f->sector_size = 128;
- f->sectuse_size = 128;
- break;
- case 0:
- case 2:
- case 4:
- f->heads = 1;
- f->tracks = 80;
- f->sector_size = 256;
- f->sectuse_size = 255;
- break;
- default: return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- stream_seek( stream, 66, SEEK_SET );
- while ( 1) {
- int i, sector, track;
- UINT16 crc;
-
- /* load sector */
- if ( stream_read( stream, buf, 6 + f->sector_size ) < 6 + f->sector_size )
- break;
-
- /* parse sector header */
- track = buf[2];
- sector = buf[3];
- if ( sector < 1 || sector > 16 || track >= f->tracks )
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* decrypt */
- for ( i = 0; i < f->sector_size; i++ ) buf[ i + 4 ] ^= sap_magic_num;
- memcpy( thom_get_sector( f, 0, track, sector ), buf + 4, f->sector_size );
-
- /* check CRC */
- crc = thom_sap_crc( buf, f->sector_size + 4 );
- if ( ( (crc >> 8) != buf[ f->sector_size + 4 ] ) ||
- ( (crc & 0xff) != buf[ f->sector_size + 5 ] ) )
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static void thom_close_sap(imgtool_image *img)
-{
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
-
- if ( f->modified ) {
- int i, sector, track;
- UINT8 buf[262];
- UINT16 crc;
-
- /* rewind */
- stream_seek( f->stream, 0, SEEK_SET );
-
- /* image header */
- if ( stream_write( f->stream, sap_header, 66 ) < 66 ) {
- /* logerror( "thom_diskimage_close_sap: write error\n" ); */
- return;
- }
-
- for ( track = 0; track < f->tracks; track++ )
- for ( sector = 1; sector <= 16; sector++ ) {
- /* sector header & data */
- buf[0] = ( f->tracks == 80 ) ? 2 : 1;
- buf[1] = 0;
- buf[2] = track;
- buf[3] = sector;
- memcpy( buf + 4,
- thom_get_sector( f, 0, track, sector), f->sector_size );
-
- /* compute crc */
- crc = thom_sap_crc( buf, f->sector_size + 4 );
- buf[ f->sector_size + 4 ] = crc >> 8;
- buf[ f->sector_size + 5 ] = crc & 0xff;
-
- /* crypt */
- for ( i = 0; i < f->sector_size; i++ ) buf[ i + 4 ] ^= sap_magic_num;
-
- /* save */
- if ( stream_write( f->stream, buf, f->sector_size + 6 ) <
- f->sector_size + 6 ) {
- /* logerror( "thom_diskimage_close_sap: write error\n" ); */
- return;
- }
- }
- }
-
- stream_close( f->stream );
-}
-
-
-/*********************** low-level functions *********************/
-
-static UINT8* thom_get_sector(thom_floppy* f, unsigned head,
- unsigned track, unsigned sector)
-{
- assert( head < f->heads);
- assert( track < f->tracks );
- assert( sector > 0 && sector <= 16 );
- return & f->data[ ( (head * f->tracks + track) * 16 + (sector-1) ) *
- f->sector_size ];
-}
-
-static int thom_nb_blocks(thom_floppy* f)
-{
- int n1 = f->tracks * 2; /* 2 blocks per track */
- int n2 = f->sector_size - 1; /* FAT entries */
- return (n1 < n2) ? n1 : n2;
-}
-
-static int thom_max_dirent(thom_floppy* f)
-{
- return 14 * f->sector_size / 32;
-}
-
-/* remove trailing spaces */
-static void thom_stringify(char* str)
-{
- char* s = str + strlen(str) - 1;
- while ( s >= str && *s == ' ' ) { *s = 0; s--; }
- for ( s = str; *s; s++ )
- if ( (UINT8)*s == 0xff ) *s = 0;
- else if ( *s < ' ' || *s >= 127 ) *s = '?';
-}
-
-/* pad with spaces until the length is nb */
-static void thom_unstringity(char* str, int nb)
-{
- char* s = str;
- while ( s < str + nb && *s ) s++;
- while ( s < str + nb ) { *s = ' '; s++; }
-}
-
-/* get filename and extension & truncate them to 8 + 3 */
-static void thom_conv_filename(const char* s, char name[9], char ext[4])
-{
- int i;
- memset( name, 0, 9 );
- memset( ext, 0, 4 );
- for ( i = 0; i < 8 && *s && *s != '.'; i++, s++ ) name[i] = *s;
- while ( *s && *s != '.' ) s++;
- if ( *s == '.' ) {
- s++;
- for ( i = 0; i < 3 && *s; i++, s++ ) ext[i] = *s;
- }
-}
-
-static time_t thom_crack_time(thom_dirent* d)
-{
- struct tm t;
- time_t now;
-
- /* check */
- if ( d->day < 1 || d->day > 31 || d->month < 1 || d->month > 12 ) return 0;
-
- /* converts */
- time( &now );
- t = *localtime( &now );
- t.tm_sec = 0;
- t.tm_min = 0;
- t.tm_hour = 0;
- t.tm_mday = d->day;
- t.tm_mon = d->month - 1;
- t.tm_year = (d->year < 65 ) ? d->year + 100 : d->year;
- return mktime(&t);
-}
-
-static void thom_make_time(thom_dirent* d, time_t time)
-{
- if ( ! time ) {
- d->day = d->month = d->year = 0;
- }
- else {
- struct tm t = *localtime( &time );
- d->day = t.tm_mday;
- d->month = t.tm_mon + 1;
- d->year = t.tm_year % 100;
- }
-}
-
-static void thom_make_time_now(thom_dirent* d)
-{
- time_t now;
- time( &now );
- thom_make_time( d, now );
-}
-
-static void thom_get_dirent(thom_floppy* f, unsigned head,
- unsigned n, thom_dirent* d)
-{
- UINT8* base = thom_get_sector( f, head, 20, 3 ) + n * 32;
- memset( d, 0, sizeof(*d) );
- d->index = n;
- if ( n >= thom_max_dirent( f ) )
- d->type = THOM_DIRENT_END;
- else if ( *base == 0xff )
- d->type = THOM_DIRENT_END;
- else if ( *base == 0 )
- d->type = THOM_DIRENT_FREE;
- else {
- int i;
- /* fill regular entry */
- d->type = THOM_DIRENT_FILE;
- memcpy( d->name, base, 8 );
- memcpy( d->ext, base + 8, 3 );
- memcpy( d->comment, base + 16, 8 );
- thom_stringify( d->name );
- thom_stringify( d->ext );
- thom_stringify( d->comment );
- d->ftype = base[11];
- d->format = base[12];
- d->firstblock = base[13];
- d->lastsectsize = ((int)base[14] << 8) + base[15];
- d->day = base[24];
- d->month = base[25];
- d->year = base[26];
- /* sanity check */
- for ( i = 0; i < 11; i++ )
- if ( base[i] < ' ' || base[i] > 127 ) d->type = THOM_DIRENT_INVALID;
- }
-}
-
-static void thom_set_dirent(thom_floppy* f, unsigned head,
- unsigned n, thom_dirent* d)
-{
- UINT8* base = thom_get_sector( f, head, 20, 3 ) + n * 32;
- if ( n >= thom_max_dirent( f ) ) return;
- memset( base, 0, 32 );
- if ( d->type == THOM_DIRENT_END ) base[ 0 ] = 0xff;
- else if ( d->type == THOM_DIRENT_FREE ) base[ 0 ] = 0;
- else {
- memcpy( base, d->name, 8 );
- memcpy( base + 8, d->ext, 3 );
- memcpy( base + 16, d->comment, 8 );
- thom_unstringity( (char*)base, 8 );
- thom_unstringity( (char*)base + 8, 3 );
- if ( base[16] ) thom_unstringity( (char*)base + 16, 8 );
- base[11] = d->ftype;
- base[12] = d->format;
- base[13] = d->firstblock;
- base[14] = d->lastsectsize >> 8;
- base[15] = d->lastsectsize & 0xff;
- base[24] = d->day;
- base[25] = d->month;
- base[26] = d->year;
- }
- f->modified = 1;
-}
-
-/* returns 1 if file found, 0 if not */
-static int thom_find_dirent(thom_floppy* f, unsigned head,
- const char* name, thom_dirent* d)
-{
- int n = 0;
- while ( 1 ) {
- thom_get_dirent( f, head, n, d );
- if ( d->type == THOM_DIRENT_END ) return 0;
- if ( d->type == THOM_DIRENT_FILE ) {
- char buf[13];
- sprintf( buf, "%s.%s", d->name, d->ext );
- if ( ! strcmp( buf, name ) ) return 1;
- }
- n++;
- }
-}
-
-/* returns 1 if free entry found, 0 if none available */
-static int thom_find_free_dirent(thom_floppy* f, unsigned head, thom_dirent* d)
-{
- int n = 0;
- while ( 1 ) {
- thom_get_dirent( f, head, n, d );
- if ( d->type == THOM_DIRENT_FREE ) return 1;
- if ( d->type == THOM_DIRENT_END ) break;
- n++;
- }
- if ( n + 1 >= thom_max_dirent( f ) ) return 0;
- thom_set_dirent( f, head, n+1, d );
- d->type = THOM_DIRENT_FREE;
- return 1;
-}
-
-/* returns the file size in bytes, or -1 if error */
-static int thom_get_file_size(thom_floppy* f, unsigned head, thom_dirent* d)
-{
- UINT8* fat = thom_get_sector( f, head, 20, 2 );
- int nbblocks = thom_nb_blocks(f);
- int block = d->firstblock;
- int size = 0;
- int timeout = nbblocks;
- if ( d->type != THOM_DIRENT_FILE ) return -1;
- if ( block >= nbblocks ) return -1;
- block = fat[ block + 1 ];
- while ( 1 ) {
- if ( block < nbblocks ) {
- /* full block */
- size += 8 * f->sectuse_size;
- block = fat[ block + 1 ];
- }
- else if ( block >= 0xc1 && block <= 0xc8 ) {
- /* last block in file */
- size += (block-0xc1) * f->sectuse_size;
- size += d->lastsectsize;
- return size;
- }
- else return -1;
- timeout--;
- if ( timeout < 0 ) return -1;
- }
-}
-
-/* number of blocks used by file */
-static int thom_get_file_blocks(thom_floppy* f, unsigned head, thom_dirent* d)
-{
- UINT8* fat = thom_get_sector( f, head, 20, 2 );
- int nbblocks = thom_nb_blocks(f);
- int block = d->firstblock;
- int nb = 0;
- if ( d->type != THOM_DIRENT_FILE ) return 0;
- if ( block >= nbblocks ) return 0;
- block = fat[ block + 1 ];
- while ( 1 ) {
- if ( block < nbblocks ) {
- /* full block */
- nb++;
- block = fat[ block + 1 ];
- }
- else if ( block >= 0xc1 && block <= 0xc8 ) {
- /* last block in file */
- nb++;
- return nb;
- }
- else return nb;
- }
-}
-
-/* number of free blocks */
-static int thom_get_free_blocks(thom_floppy* f, unsigned head)
-{
- UINT8* fat = thom_get_sector( f, head, 20, 2 );
- int nbblocks = thom_nb_blocks(f);
- int i, nb = 0;
- for ( i = 1; i <= nbblocks; i++ )
- if ( fat[i] == 0xff ) nb++;
- return nb;
-}
-
-/* dump file contents into dst */
-static void thom_get_file(thom_floppy* f, unsigned head,
- thom_dirent* d, imgtool_stream *dst)
-{
- UINT8* fat = thom_get_sector( f, head, 20, 2 );
- int nbblocks = thom_nb_blocks(f);
- int block = d->firstblock;
- if ( block >= nbblocks ) return;
- while ( 1 ) {
- int nextblock = fat[ block + 1 ];
- int track = block / 2;
- int firstsect = (block % 2) ? 9 : 1;
- if ( nextblock < nbblocks ) {
- /* full block */
- int i;
- for ( i = 0; i < 8; i++ ) {
- UINT8* data = thom_get_sector( f, head, track, firstsect + i );
- stream_write( dst, data, f->sectuse_size );
- }
- block = fat[ block + 1 ];
- }
- else if ( nextblock >= 0xc1 && nextblock <= 0xc8 ) {
- /* last block in file */
- int i;
- UINT8* data;
- for ( i = 0; i < nextblock - 0xc1; i++ ) {
- data = thom_get_sector( f, head, track, firstsect + i );
- stream_write( dst, data, f->sectuse_size );
- }
- data = thom_get_sector( f, head, track, firstsect + i );
- stream_write( dst, data, d->lastsectsize );
- return;
- }
- else {
- /* invalid, assume last block */
- UINT8* data = thom_get_sector( f, head, track, firstsect );
- stream_write( dst, data, d->lastsectsize );
- return;
- }
- block = nextblock;
- }
-}
-
-static void thom_del_file(thom_floppy* f, unsigned head, thom_dirent* d)
-{
- UINT8* fat = thom_get_sector( f, head, 20, 2 );
- int nbblocks = thom_nb_blocks(f);
- int block = d->firstblock;
- if ( d->type != THOM_DIRENT_FILE ) return;
- if ( block >= nbblocks ) return;
- while ( 1 ) {
- int nextblock = fat[ block + 1 ];
- fat[ block ] = 0xff;
- if ( nextblock < nbblocks ) block = fat[ block + 1 ];
- else break;
- }
- d->type = THOM_DIRENT_FREE;
- thom_set_dirent( f, head, d->index, d );
- f->modified = 1;
-}
-
-/* create a new file or overwrite an old one, with the contents of src */
-static void thom_put_file(thom_floppy* f, unsigned head,
- thom_dirent* d, imgtool_stream *src)
-{
- int size = stream_size( src );
- UINT8* fat = thom_get_sector( f, head, 20, 2 );
- int nbblocks = thom_nb_blocks(f);
- int block;
-
- /* find first free block */
- for ( block = 0; block < nbblocks && fat[ block + 1 ] != 0xff; block++ );
- if ( block >= nbblocks ) return;
- d->firstblock = block;
-
- /* store file */
- while (1) {
- int track = block / 2;
- int firstsect = (block % 2) ? 9 : 1;
- int i;
-
- /* store data, full sectors */
- for ( i = 0; i < 8 && size > f->sectuse_size; i++ ) {
- UINT8* dst = thom_get_sector( f, head, track, firstsect + i );
- stream_read( src, dst, f->sectuse_size );
- size -= f->sectuse_size;
- }
-
- /* store data, last sector */
- if ( i < 8 ) {
- UINT8* dst = thom_get_sector( f, head, track, firstsect + i );
- stream_read( src, dst, size );
- fat[ block + 1 ] = 0xc1 + i;
- d->lastsectsize = size;
- break;
- }
-
- /* find next free block & update fat */
- i = block;
- for ( block++; block < nbblocks && fat[ block + 1 ] != 0xff; block++ );
- if ( block >= nbblocks ) {
- /* out of memory! */
- fat[ i + 1 ] = 0;
- d->lastsectsize = 0;
- break;
- }
- fat[ i + 1 ] = block;
- }
-
- d->type = THOM_DIRENT_FILE;
- thom_set_dirent( f, head, d->index, d );
- f->modified = 1;
-}
-
-
-/********************** module functions ***********************/
-
-static imgtoolerr_t thom_get_sector_size(imgtool_image* img, UINT32 track,
- UINT32 head, UINT32 sector,
- UINT32 *sector_size)
-{
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
-
- if ( head >= f->heads || sector < 1 || sector > 16 || track >= f->tracks ) {
- if ( sector_size ) *sector_size = 0;
- return IMGTOOLERR_SEEKERROR;
- }
- if ( sector_size ) *sector_size = f->sector_size;
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_get_geometry(imgtool_image* img, UINT32* tracks,
- UINT32* heads, UINT32* sectors)
-{
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- if ( tracks ) *tracks = f->tracks;
- if ( heads ) *heads = f->heads;
- if ( sectors ) *sectors = 16;
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_read_sector(imgtool_image* img, UINT32 track,
- UINT32 head, UINT32 sector, void *buf,
- size_t len)
-{
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- if ( head >= f->heads || sector < 1 || sector > 16 || track >= f->tracks )
- return IMGTOOLERR_SEEKERROR;
- if ( len > f->sector_size) return IMGTOOLERR_READERROR;
- memcpy( buf, thom_get_sector( f, head, track, sector ), len );
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_write_sector(imgtool_image *img, UINT32 track,
- UINT32 head, UINT32 sector,
- const void *buf, size_t len, int ddam)
-{
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- if ( stream_isreadonly( f->stream ) ) return IMGTOOLERR_WRITEERROR;
- if ( head >= f->heads || sector < 1 || sector > 16 || track >= f->tracks )
- return IMGTOOLERR_SEEKERROR;
- if ( len > f->sector_size) return IMGTOOLERR_WRITEERROR;
- f->modified = 1;
- memcpy( thom_get_sector( f, head, track, sector ), buf, len );
- return IMGTOOLERR_SUCCESS;
-}
-
-/* returns floopy name */
-/* actually, each side has its own name, but we only return the one on side 0.
- */
-static void thom_info(imgtool_image *img, char *string, size_t len)
-{
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- UINT8* base = thom_get_sector( f, 0, 20, 1 );
- char buf[9];
- memcpy( buf, base, 8 );
- buf[8] = 0;
- thom_stringify( buf );
- strncpy( string, buf, len );
-}
-
-/* each side of a floppy has its own filesystem, we treat them as'partitions'
- */
-static imgtoolerr_t thom_list_partitions(imgtool_image *img,
- imgtool_partition_info *partitions,
- size_t len)
-{
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- if ( len >= 1 ) {
- partitions[0].get_info = thom_basic_get_info;
- partitions[0].base_block = 0;
- partitions[0].block_count = 1;
- }
- if ( len >= 2 && f->heads >= 2 ) {
- partitions[1].get_info = thom_basic_get_info;
- partitions[1].base_block = 1;
- partitions[1].block_count = 1;
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_open_partition(imgtool_partition *part,
- UINT64 first_block, UINT64 block_count)
-{
- imgtool_image* img = imgtool_partition_image( part );
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- if ( first_block >= f->heads )
- return IMGTOOLERR_INVALIDPARTITION;
- * ( (int*) imgtool_partition_extra_bytes( part ) ) = first_block;
- return IMGTOOLERR_SUCCESS;
-}
-
-
-static imgtoolerr_t thom_begin_enum(imgtool_directory *enumeration,
- const char *path)
-{
- int* n = (int*) imgtool_directory_extrabytes( enumeration );
- *n = 0;
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_next_enum(imgtool_directory *enumeration,
- imgtool_dirent *ent)
-{
- imgtool_partition *part = imgtool_directory_partition( enumeration);
- int head = *( (int*) imgtool_partition_extra_bytes( part ) );
- imgtool_image* img = imgtool_partition_image( part );
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- int* n = (int*) imgtool_directory_extrabytes( enumeration );
- thom_dirent d;
-
- do {
- thom_get_dirent( f, head, *n, &d );
- (*n) ++;
- }
- while ( d.type == THOM_DIRENT_FREE );
- if ( d.type == THOM_DIRENT_END ) ent->eof = 1;
- else if ( d.type == THOM_DIRENT_INVALID ) {
- ent->corrupt = 1;
- }
- else {
- int size;
- snprintf( ent->filename, sizeof(ent->filename), "%s.%s", d.name, d.ext );
- snprintf( ent->attr, sizeof(ent->attr), "%c %c %s",
- (d.ftype == 0) ? 'B' : (d.ftype == 1) ? 'D' :
- (d.ftype == 2) ? 'M' : (d.ftype == 3) ? 'A' : '?',
- (d.format == 0) ? 'B' : (d.format == 0xff) ? 'A' : '?',
- d.comment );
- ent->creation_time = thom_crack_time( &d );
- size = thom_get_file_size( f, head, &d );
- if ( size >= 0 ) ent->filesize = size;
- else {
- ent->filesize = 0;
- ent->corrupt = 1;
- }
- }
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_free_space(imgtool_partition *part, UINT64 *size)
-{
- int head = *( (int*) imgtool_partition_extra_bytes( part ) );
- imgtool_image* img = imgtool_partition_image( part );
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- int nb = thom_get_free_blocks( f, head );
- (*size) = nb * f->sectuse_size * 8;
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_read_file(imgtool_partition *part,
- const char *filename,
- const char *fork,
- imgtool_stream *destf)
-{
- int head = *( (int*) imgtool_partition_extra_bytes( part ) );
- imgtool_image* img = imgtool_partition_image( part );
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- thom_dirent d;
- char name[9], ext[4], fname[14];
- int size;
-
- /* convert filename */
- thom_conv_filename( filename, name, ext );
- sprintf( fname, "%s.%s", name, ext );
-
- if ( ! thom_find_dirent( f, head, fname, &d ) )
- return IMGTOOLERR_FILENOTFOUND;
- size = thom_get_file_size( f, head, &d );
- if ( size < 0 ) return IMGTOOLERR_CORRUPTFILE;
- thom_get_file( f, head, &d, destf );
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_delete_file(imgtool_partition *part,
- const char *filename)
-{
- int head = *( (int*) imgtool_partition_extra_bytes( part ) );
- imgtool_image* img = imgtool_partition_image( part );
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- thom_dirent d;
- char name[9], ext[4], fname[14];
-
- /* convert filename */
- thom_conv_filename( filename, name, ext );
- sprintf( fname, "%s.%s", name, ext );
-
- if ( ! thom_find_dirent( f, head, fname, &d ) )
- return IMGTOOLERR_FILENOTFOUND;
- /*if ( thom_get_file_size( f, head, &d ) < 0 ) return IMGTOOLERR_CORRUPTFILE;*/
- if ( stream_isreadonly( f->stream ) ) return IMGTOOLERR_WRITEERROR;
- thom_del_file( f, head, &d );
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_write_file(imgtool_partition *part,
- const char *filename,
- const char *fork,
- imgtool_stream *sourcef,
- option_resolution *opts)
-{
- int head = *( (int*) imgtool_partition_extra_bytes( part ) );
- imgtool_image* img = imgtool_partition_image( part );
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- thom_dirent d;
- int size = stream_size( sourcef );
- int blocks = thom_get_free_blocks( f, head );
- char name[9], ext[4], fname[14];
- const char* comment;
- int is_new = 1;
-
- if ( stream_isreadonly( f->stream ) ) return IMGTOOLERR_WRITEERROR;
-
- /* convert filename */
- thom_conv_filename( filename, name, ext );
- sprintf( fname, "%s.%s", name, ext );
-
- /* check available space & find dir entry */
- if ( thom_find_dirent( f, head, fname, &d ) ) {
- /* file already exists: delete it */
- if ( thom_get_file_size( f, head, &d ) < 0 ) return IMGTOOLERR_CORRUPTFILE;
- blocks += thom_get_file_blocks( f, head, &d );
- if ( blocks * 8 * f->sectuse_size < size ) return IMGTOOLERR_NOSPACE;
- thom_del_file( f, head, &d );
- is_new = 0;
- }
- else {
- /* new file, need new dir entry */
- if ( blocks * 8 * f->sectuse_size < size ) return IMGTOOLERR_NOSPACE;
- if ( ! thom_find_free_dirent( f, head, &d ) ) return IMGTOOLERR_NOSPACE;
- thom_make_time_now( &d );
- }
-
- /* fill-in dir entry */
- memcpy( d.name, name, 9 );
- memcpy( d.ext, ext, 4 );
-
- /* file type */
- switch ( option_resolution_lookup_int( opts, 'T' ) ) {
- case 0:
- if ( ! is_new ) break;
- if ( ! core_stricmp( ext, "BAS" ) ) d.ftype = 0;
- else if ( ! core_stricmp( ext, "BAT" ) ) d.ftype = 0;
- else if ( ! core_stricmp( ext, "DAT" ) ) d.ftype = 1;
- else if ( ! core_stricmp( ext, "ASC" ) ) d.ftype = 1;
- else if ( ! core_stricmp( ext, "BIN" ) ) d.ftype = 2;
- else if ( ! core_stricmp( ext, "MAP" ) ) d.ftype = 2;
- else if ( ! core_stricmp( ext, "CFG" ) ) d.ftype = 2;
- else if ( ! core_stricmp( ext, "ASM" ) ) d.ftype = 3;
- else d.ftype = 2;
- break;
- case 1: d.ftype = 0; break;
- case 2: d.ftype = 1; break;
- case 3: d.ftype = 2; break;
- case 4: d.ftype = 3; break;
- }
-
- /* format flag */
- switch ( option_resolution_lookup_int( opts, 'F' ) ) {
- case 0:
- if ( ! is_new ) break;
- if ( ! core_stricmp( ext, "DAT" ) ) d.format = 0xff;
- else if ( ! core_stricmp( ext, "ASC" ) ) d.format = 0xff;
- else if ( ! core_stricmp( ext, "ASM" ) ) d.format = 0xff;
- else d.format = 0;
- break;
- case 1: d.format = 0; break;
- case 2: d.format = 0xff; break;
- }
-
- /* comment */
- comment = option_resolution_lookup_string( opts, 'C' );
- if ( comment && *comment )
- strncpy( d.comment, comment, 8 );
-
- /* write file */
- thom_put_file( f, head, &d, sourcef );
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_suggest_transfer(imgtool_partition *part,
- const char *fname,
- imgtool_transfer_suggestion *suggestions,
- size_t suggestions_length)
-{
- int head = *( (int*) imgtool_partition_extra_bytes( part ) );
- imgtool_image* img = imgtool_partition_image( part );
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- thom_dirent d;
- int is_basic = 0;
-
- if ( suggestions_length < 1 ) return IMGTOOLERR_SUCCESS;
-
- if ( fname ) {
- if ( ! thom_find_dirent( f, head, fname, &d ) )
- return IMGTOOLERR_FILENOTFOUND;
- if ( d.ftype == 0 && d.format == 0 ) is_basic = 1;
- }
-
- if ( is_basic ) {
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = filter_thombas128_getinfo;
- if ( suggestions_length >= 2 ) {
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = filter_thombas7_getinfo;
- }
- if ( suggestions_length >= 3 ) {
- suggestions[2].viability = SUGGESTION_POSSIBLE;
- suggestions[2].filter = filter_thombas5_getinfo;
- }
- if ( suggestions_length >= 4 ) {
- suggestions[3].viability = SUGGESTION_POSSIBLE;
- suggestions[3].filter = NULL;
- }
- }
- else {
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_create(imgtool_image* img,
- imgtool_stream *stream,
- option_resolution *opts)
-{
- thom_floppy* f = (thom_floppy*) imgtool_image_extra_bytes( img );
- int i;
- UINT8* buf;
- const char* name;
-
- f->stream = stream;
- f->modified = 0;
-
- /* get parameters */
- f->heads = option_resolution_lookup_int( opts, 'H' );
- f->tracks = option_resolution_lookup_int( opts, 'T' );
- name = option_resolution_lookup_string( opts, 'N' );
- switch ( option_resolution_lookup_int( opts, 'D' ) ) {
- case 0: f->sector_size = 128; f->sectuse_size = 128; break;
- case 1: f->sector_size = 256; f->sectuse_size = 255; break;
- default: return IMGTOOLERR_PARAMCORRUPT;
- }
-
- /* sanity checks */
- switch ( f->tracks ) {
- case 25: if ( f->sector_size != 128 ) return IMGTOOLERR_PARAMCORRUPT; break;
- case 40: break;
- case 80: if ( f->sector_size != 256 ) return IMGTOOLERR_PARAMCORRUPT; break;
- default: return IMGTOOLERR_PARAMCORRUPT;
- }
-
- memset( f->data, 0xe5, sizeof( f->data ) );
-
- for ( i = 0; i < f->heads; i++ ) {
- /* disk info */
- buf = thom_get_sector( f, i, 20, 1 );
- memset( buf, 0xff, f->sector_size );
- if ( name ) {
- strncpy( (char*)buf, name, 8 );
- thom_unstringity( (char*)buf, 8 );
- }
- else memset( buf, ' ', 8 );
-
- /* FAT */
- buf = thom_get_sector( f, i, 20, 2 );
- memset( buf, 0, f->sector_size );
- memset( buf + 1, 0xff, thom_nb_blocks( f ) );
- buf[ 41 ] = buf[ 42 ] = 0xfe; /* reserved for FAT */
-
- /* (empty) directory */
- buf = thom_get_sector( f, i, 20, 3 );
- memset( buf, 0xff, 14 * f->sector_size );
- }
-
- f->modified = 1;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-
-/****************** BASIC tokenization *********************/
-
-/* character codes >= 128 are reserved for BASIC keywords */
-
-static const char *const thombas7[2][128] = {
- { /* statements */
- "END", "FOR", "NEXT", "DATA", "DIM", "READ", "LET", "GO", "RUN", "IF",
- "RESTORE", "RETURN", "REM", "'", "STOP", "ELSE", "TRON", "TROFF", "DEFSTR",
- "DEFINT", "DEFSNG", "DEFDBL", "ON", "WAIT", "ERROR", "RESUME", "AUTO",
- "DELETE", "LOCATE", "CLS", "CONSOLE", "PSET", "MOTOR", "SKIP", "EXEC",
- "BEEP", "COLOR", "LINE", "BOX", "UNMASK", "ATTRB", "DEF", "POKE", "PRINT",
- "CONT", "LIST", "CLEAR", "WHILE", "WHEN", "NEW", "SAVE", "LOAD", "MERGE",
- "OPEN", "CLOSE", "INPEN", "PEN", "PLAY", "TAB(", "TO", "SUB", "FN",
- "SPC(", "USING", "USR", "ERL", "ERR", "OFF", "THEN", "NOT", "STEP",
- "+", "-", "*", "/", "^", "AND", "OR", "XOR", "EQV", "IMP", "MOD", "@",
- ">", "=", "<",
- /* DOS specific */
- "DSKINI", "DSKO$", "KILL", "NAME", "FIELD", "LSET", "RSET",
- "PUT", "GET", "VERIFY", "DEVICE", "DIR", "FILES", "WRITE", "UNLOAD",
- "BACKUP", "COPY", "CIRCLE", "PAINT", "DRAW", "RENUM", "SWAP", "DENSITY",
- },
- { /* functions: 0xff prefix */
- "SGN", "INT", "ABS", "FRE", "SQR", "LOG", "EXP", "COS", "SIN",
- "TAN", "PEEK", "LEN", "STR$", "VAL", "ASC", "CHR$", "EOF", "CINT", "CSNG",
- "CDBL", "FIX", "HEX$", "OCT$", "STICK", "STRIG", "GR$", "LEFT$", "RIGHT$",
- "MID$", "INSTR", "VARPTR", "RND", "INKEY$", "INPUT", "CSRLIN", "POINT",
- "SCREEN", "POS", "PTRIG",
- /* DOS specific */
- "DSKL", "CVI", "CVS", "CVD", "MKI$", "MKS$", "MKD$", "LOC", "LOF",
- "SPACE$", "STRING$", "DSKI$",
- }
-};
-
-/* MO5: some keywords ar missing; DOS and TUNE are added */
-static const char *const thombas5[2][128] = {
- { /* statements */
- "END", "FOR", "NEXT", "DATA", "DIM", "READ", NULL, "GO", "RUN", "IF",
- "RESTORE", "RETURN", "REM", "'", "STOP", "ELSE", "TRON", "TROFF", "DEFSTR",
- "DEFINT", "DEFSNG", NULL, "ON", "TUNE", "ERROR", "RESUME", "AUTO",
- "DELETE", "LOCATE", "CLS", "CONSOLE", "PSET", "MOTOR", "SKIP", "EXEC",
- "BEEP", "COLOR", "LINE", "BOX", NULL, "ATTRB", "DEF", "POKE", "PRINT",
- "CONT", "LIST", "CLEAR", "DOS", NULL, "NEW", "SAVE", "LOAD", "MERGE",
- "OPEN", "CLOSE", "INPEN", "PEN", "PLAY", "TAB(", "TO", "SUB", "FN",
- "SPC(", "USING", "USR", "ERL", "ERR", "OFF", "THEN", "NOT", "STEP",
- "+", "-", "*", "/", "^", "AND", "OR", "XOR", "EQV", "IMP", "MOD", "@",
- ">", "=", "<",
- /* DOS specific */
- "DSKINI", "DSKO$", "KILL", "NAME", "FIELD", "LSET", "RSET",
- "PUT", "GET", "VERIFY", "DEVICE", "DIR", "FILES", "WRITE", "UNLOAD",
- "BACKUP","COPY", "CIRCLE", "PAINT", "DRAW", "RENUM", "SWAP", "SEARCH",
- "DENSITY",
- },
- { /* functions: 0xff prefix */
- "SGN", "INT", "ABS", "FRE", "SQR", "LOG", "EXP", "COS", "SIN",
- "TAN", "PEEK", "LEN", "STR$", "VAL", "ASC", "CHR$", "EOF", "CINT", NULL,
- NULL, "FIX", "HEX$", NULL, "STICK", "STRIG", "GR$", "LEFT$", "RIGHT$",
- "MID$", "INSTR", "VARPTR", "RND", "INKEY$", "INPUT", "CSRLIN", "POINT",
- "SCREEN", "POS", "PTRIG",
- /* DOS specific */
- "DSKL", "CVI", "CVS", "CVD", "MKI$", "MKS$", "MKD$", "LOC", "LOF",
- "SPACE$", "STRING$", "DSKI$",
- }
-};
-
-/* BASIC 128 has many new keywords */
-/* DENSITY is missing on BASIC 512 & BASIC 128 for MO6 but, otherwise, they
- have the same tokens
-*/
-static const char *const thombas128[2][128] = {
- { /* statements */
- "END", "FOR", "NEXT", "DATA", "DIM", "READ", "LET", "GO", "RUN", "IF",
- "RESTORE", "RETURN", "REM", "'", "STOP", "ELSE", "TRON", "TROFF", "DEFSTR",
- "DEFINT", "DEFSNG", "DEFDBL", "ON", "WAIT", "ERROR", "RESUME", "AUTO",
- "DELETE", "LOCATE", "CLS", "CONSOLE", "PSET", "MOTOR", "SKIP", "EXEC",
- "BEEP", "COLOR", "LINE", "BOX", "UNMASK", "ATTRB", "DEF", "POKE", "PRINT",
- "CONT", "LIST", "CLEAR", "INTERVAL", "KEY", "NEW", "SAVE", "LOAD", "MERGE",
- "OPEN", "CLOSE", "INPEN", "PEN", "PLAY", "TAB(", "TO", "SUB", "FN",
- "SPC(", "USING", "USR", "ERL", "ERR", "OFF", "THEN", "NOT", "STEP",
- "+", "-", "*", "/", "^", "AND", "OR", "XOR", "EQV", "IMP", "MOD", "@",
- ">", "=", "<",
- "DSKINI", "DSKO$", "KILL", "NAME", "FIELD", "LSET", "RSET",
- "PUT", "GET", "VERIFY", "DEVICE", "DIR", "FILES", "WRITE", "UNLOAD",
- "BACKUP", "COPY", "CIRCLE", "PAINT", "RESET", "RENUM", "SWAP", "DENSITY",
- "WINDOW", "PATTERN", "DO", "LOOP", "EXIT", "INMOUSE", "MOUSE", "CHAINE",
- "COMMON", "SEARCH", "FWD", "TURTLE",
- },
- { /* functions: 0xff prefix */
- "SGN", "INT", "ABS", "FRE", "SQR", "LOG", "EXP", "COS", "SIN",
- "TAN", "PEEK", "LEN", "STR$", "VAL", "ASC", "CHR$", "EOF", "CINT", "CSNG",
- "CDBL", "FIX", "HEX$", "OCT$", "STICK", "STRIG", "GR$", "LEFT$", "RIGHT$",
- "MID$", "INSTR", "VARPTR", "RND", "INKEY$", "INPUT", "CSRLIN", "POINT",
- "SCREEN", "POS", "PTRIG",
- "DSKL", "CVI", "CVS", "CVD", "MKI$", "MKS$", "MKD$", "LOC", "LOF",
- "SPACE$", "STRING$", "DSKI$",
- "FKEY$", "MIN(", "MAX(", "ATN", "CRUNCH$", "MTRIG", "EVAL", "PALETTE",
- "BANK", "HEAD", "ROT", "SHOW", "ZOOM", "TRACE",
- }
-};
-
-/* tables for simple XOR encryption sieve */
-static const UINT8 crypt1[11] = {
- 0x80, 0x19, 0x56, 0xAA, 0x80, 0x76, 0x22, 0xF1, 0x82, 0x38, 0xAA
-};
-
-static const UINT8 crypt2[13] = {
- 0x86, 0x1E, 0xD7, 0xBA, 0x87, 0x99, 0x26, 0x64, 0x87, 0x23, 0x34, 0x58, 0x86
-};
-
-/* decrypt BASIC protected files */
-static void thom_decrypt(imgtool_stream* out, imgtool_stream* in)
-{
- int i1 = 11, i2 = 13;
- while ( 1 ) {
- UINT8 b;
- if ( stream_read( in, &b, 1) < 1 ) break;
- b = ( (UINT8)(b - i2) ^ crypt2[i2-1] ^ crypt1[i1-1] ) + i1;
- stream_putc( out, b );
- i1--; i2--;
- if ( !i1 ) i1 = 11;
- if ( !i2 ) i2 = 13;
- }
-}
-
-/* encrypt BASIC protected files */
-static void thom_encrypt(imgtool_stream* out, imgtool_stream* in)
-{
- int i1 = 11, i2 = 13;
- while ( 1 ) {
- UINT8 b;
- if ( stream_read( in, &b, 1) < 1 ) break;
- b = ( (UINT8)(b - i1) ^ crypt2[i2-1] ^ crypt1[i1-1] ) + i2;
- stream_putc( out, b );
- i1--; i2--;
- if ( !i1 ) i1 = 11;
- if ( !i2 ) i2 = 13;
- }
-}
-
-static imgtoolerr_t thomcrypt_read_file(imgtool_partition *part,
- const char *name,
- const char *fork, imgtool_stream *dst)
-{
- UINT8 buf[3];
- imgtool_stream *org = stream_open_mem( NULL, 0 );
- imgtoolerr_t err;
- if ( !org ) return IMGTOOLERR_OUTOFMEMORY;
-
- /* read file */
- err = thom_read_file( part, name, fork, org );
- if ( err ) {
- stream_close( org );
- return err;
- }
-
- stream_seek( org, 0, SEEK_SET );
- if ( stream_read( org, buf, 3 ) < 3 || buf[0] != 0xfe ) {
- /* regular file */
- stream_seek( org, 0, SEEK_SET );
- stream_transfer_all( dst, org );
- }
- else {
- /* encrypted file */
- stream_putc( dst, '\xff' );
- stream_write( dst, buf+1, 2 );
- thom_decrypt( dst, org );
- }
-
- stream_close( org );
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thomcrypt_write_file(imgtool_partition *part,
- const char *name,
- const char *fork, imgtool_stream *src,
- option_resolution *opts)
-{
- UINT8 buf[3];
-
- if ( stream_read( src, buf, 3 ) < 3 || buf[0] == 0xfe ) {
- /* too short or already encrypted file */
- stream_seek( src, 0, SEEK_SET );
- return thom_write_file( part, name, fork, src, opts );
- }
- else {
- /* regular file */
- imgtool_stream *dst = stream_open_mem( NULL, 0 );
- imgtoolerr_t err;
- if ( !dst ) return IMGTOOLERR_OUTOFMEMORY;
- stream_putc( dst, '\xfe' );
- stream_write( dst, buf+1, 2 );
- thom_encrypt( dst, src );
- stream_seek( dst, 0, SEEK_SET );
- err = thom_write_file( part, name, fork, dst, opts );
- stream_close( dst);
- return err;
- }
-}
-
-void filter_thomcrypt_getinfo(UINT32 state, union filterinfo *info)
-{
- switch(state) {
- case FILTINFO_STR_NAME:
- info->s = "thomcrypt";
- break;
- case FILTINFO_STR_HUMANNAME:
- info->s = "Thomson BASIC, Protected file encryption (no tokenization)";
- break;
- case FILTINFO_PTR_READFILE:
- info->read_file = thomcrypt_read_file;
- break;
- case FILTINFO_PTR_WRITEFILE:
- info->write_file = thomcrypt_write_file;
- break;
- }
-}
-
-/* untokenization automatically decrypt protected files */
-static imgtoolerr_t thom_basic_read_file(imgtool_partition *part,
- const char *name,
- const char *fork,
- imgtool_stream *dst,
- const char *const table[2][128])
-{
- imgtool_stream *org = stream_open_mem( NULL, 0 );
- imgtoolerr_t err;
- UINT8 buf[4];
- int i;
-
- if ( !org ) return IMGTOOLERR_OUTOFMEMORY;
-
- err = thomcrypt_read_file( part, name, fork, org );
- if ( err ) {
- stream_close( org );
- return err;
- }
- stream_seek( org, 3, SEEK_SET ); /* skip header */
-
- while ( 1 ) {
- int in_str = 0, in_fun = 0;
- int linelength, linenum;
-
- /* line header: line length and line number */
- /* I am not sure this is 100% correct but it works in many cases */
- if ( stream_read( org, buf, 2 ) < 2 ) goto end;
- linelength = ((int)buf[0] << 8) + (int)buf[1] - 4;
- if ( linelength <= 0 ) goto end;
- if ( stream_read( org, buf, 2 ) < 2 ) goto end;
- linenum = ((int)buf[0] << 8) + buf[1];
- stream_printf( dst, "%u ", linenum );
-
- /* process line */
- for ( i = 0; i < linelength; i++ ) {
- UINT8 c;
- if ( stream_read( org, &c, 1 ) < 1 ) break;
- if ( c == 0 ) {
- /* Sometimes, linelength seems wrong and we must rely on the fact that
- BASIC lines are 0-terminated.
- At other times, there are 0 embedded within lines or extra stuff
- between the 0 and the following line, and so, we must rely
- on linelength to cut the line (!)
- */
- if ( linelength > 256 ) break;
- }
- else if ( c == 0xff && ! in_str ) in_fun = 1; /* function prefix */
- else {
- if ( c >= 0x80 && ! in_str ) {
- /* token */
- const char* token = table[ in_fun ][ c - 0x80 ];
- if ( token ) stream_puts( dst, token );
- else stream_puts( dst, "???" );
- }
- else {
- /* regular character */
- if ( c == '"' ) in_str = 1 - in_str;
- stream_putc( dst, c ); /* normal letter */
- }
- in_fun = 0;
- }
- }
- stream_putc( dst, '\n' );
- }
- end:
-
- stream_close( org );
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t thom_basic_write_file(imgtool_partition *part,
- const char *name,
- const char *fork,
- imgtool_stream *src,
- option_resolution *opts,
- const char *const table[2][128])
-{
- return IMGTOOLERR_UNIMPLEMENTED;
-}
-
-
-#define FILTER(short,long) \
- static imgtoolerr_t short##_read_file(imgtool_partition *part, \
- const char *name, \
- const char *fork, \
- imgtool_stream *dst) \
- { \
- return thom_basic_read_file( part, name, fork, dst, short ); \
- } \
- static imgtoolerr_t short##_write_file(imgtool_partition *part, \
- const char *name, \
- const char *fork, \
- imgtool_stream *src, \
- option_resolution *opts) \
- { \
- return thom_basic_write_file( part, name, fork, src, opts, short ); \
- } \
- void filter_##short##_getinfo(UINT32 state, union filterinfo *info) \
- { \
- switch(state) \
- { \
- case FILTINFO_STR_NAME: \
- info->s = #short; \
- break; \
- case FILTINFO_STR_HUMANNAME: \
- info->s = long; \
- break; \
- case FILTINFO_PTR_READFILE: \
- info->read_file = short##_read_file; \
- break; \
- case FILTINFO_PTR_WRITEFILE: \
- info->write_file = short##_write_file; \
- break; \
- } \
- }
-
-FILTER( thombas5,
- "Thomson MO5 w/ BASIC 1.0, Tokenized Files (read-only, auto-decrypt)" )
-FILTER( thombas7,
- "Thomson TO7 w/ BASIC 1.0, Tokenized Files (read-only, auto-decrypt)" )
-FILTER( thombas128,
- "Thomson w/ BASIC 128/512, Tokenized Files (read-only, auto-decrypt)" )
-
-
-/************************* driver ***************************/
-
-static OPTION_GUIDE_START( thom_createimage_optguide )
- OPTION_INT( 'H', "heads", "Heads" )
- OPTION_INT( 'T', "tracks", "Tracks" )
- OPTION_ENUM_START( 'D', "density", "Density" )
- OPTION_ENUM( 0, "SD", "Single density (128 bytes)" )
- OPTION_ENUM( 1, "DD", "Double density (256 bytes)" )
- OPTION_ENUM_END
- OPTION_STRING( 'N', "name", "Floppy name" )
-OPTION_GUIDE_END
-
-static OPTION_GUIDE_START( thom_writefile_optguide )
- OPTION_ENUM_START( 'T', "ftype", "File type" )
- OPTION_ENUM( 0, "auto", "Automatic (by extension)" )
- OPTION_ENUM( 1, "B", "Program" )
- OPTION_ENUM( 2, "D", "Data" )
- OPTION_ENUM( 3, "M", "Machine Code" )
- OPTION_ENUM( 4, "A", "Assembler Source" )
- OPTION_ENUM_END
- OPTION_ENUM_START( 'F', "format", "Format flag" )
- OPTION_ENUM( 0, "auto", "Automatic (by extension)" )
- OPTION_ENUM( 1, "B", "Binary, Tokenized BASIC" )
- OPTION_ENUM( 2, "A", "ASCII" )
- OPTION_ENUM_END
- OPTION_STRING( 'C', "comment", "Comment" )
-OPTION_GUIDE_END
-
-static void thom_basic_get_info(const imgtool_class *clas,
- UINT32 param,
- union imgtoolinfo *info)
-{
- switch ( param ) {
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES:
- info->i = sizeof(thom_floppy); break;
- case IMGTOOLINFO_INT_PARTITION_EXTRA_BYTES:
- info->i = sizeof(int); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES:
- info->i = sizeof(int); break;
- case IMGTOOLINFO_INT_SUPPORTS_CREATION_TIME:
- case IMGTOOLINFO_INT_PREFER_UCASE:
- info->i = 1; break;
- case IMGTOOLINFO_INT_PATH_SEPARATOR:
- info->i = 0; break;
- case IMGTOOLINFO_STR_FILE:
- strcpy( info->s = imgtool_temp_str(), __FILE__ ); break;
- case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom" ); break;
- case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(), "Thomson BASIC filesystem" );
- break;
- case IMGTOOLINFO_PTR_CREATE:
- info->create = thom_create; break;
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE:
- info->createimage_optguide = thom_createimage_optguide; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM:
- info->begin_enum = thom_begin_enum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM:
- info->next_enum = thom_next_enum; break;
- case IMGTOOLINFO_PTR_READ_FILE:
- info->read_file = thom_read_file; break;
- case IMGTOOLINFO_PTR_WRITE_FILE:
- info->write_file = thom_write_file; break;
- case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE:
- info->writefile_optguide = thom_writefile_optguide; break;
- case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "T[0]-4;F[0]-2;C" ); break;
- case IMGTOOLINFO_PTR_SUGGEST_TRANSFER:
- info->suggest_transfer = thom_suggest_transfer; break;
- case IMGTOOLINFO_PTR_DELETE_FILE:
- info->delete_file = thom_delete_file; break;
- case IMGTOOLINFO_PTR_FREE_SPACE:
- info->free_space = thom_free_space; break;
- case IMGTOOLINFO_PTR_GET_SECTOR_SIZE:
- info->get_sector_size = thom_get_sector_size; break;
- case IMGTOOLINFO_PTR_GET_GEOMETRY:
- info->get_geometry = thom_get_geometry; break;
- case IMGTOOLINFO_PTR_INFO:
- info->info = thom_info; break;
- case IMGTOOLINFO_PTR_READ_SECTOR:
- info->read_sector = thom_read_sector; break;
- case IMGTOOLINFO_PTR_WRITE_SECTOR:
- info->write_sector = thom_write_sector; break;
- case IMGTOOLINFO_PTR_LIST_PARTITIONS:
- info->list_partitions = thom_list_partitions; break;
- case IMGTOOLINFO_PTR_OPEN_PARTITION:
- info->open_partition = thom_open_partition; break;
- }
-}
-
-void thom_fd_basic_get_info(const imgtool_class *clas,
- UINT32 param,
- union imgtoolinfo *info)
-{
- switch ( param ) {
- case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom_fd" ); break;
- case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(),
- "Thomson .fd disk image, BASIC format" );
- break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS:
- strcpy( info->s = imgtool_temp_str(), "fd" ); break;
- case IMGTOOLINFO_PTR_OPEN:
- info->open = thom_open_fd_qd; break;
- case IMGTOOLINFO_PTR_CLOSE:
- info->close = thom_close_fd_qd; break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "H[1]-2;T40/[80];D0-[1];N" ); break;
- default:
- thom_basic_get_info( clas, param, info );
- }
-}
-
-void thom_qd_basic_get_info(const imgtool_class *clas,
- UINT32 param,
- union imgtoolinfo *info)
-{
- switch ( param ) {
- case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom_qd" ); break;
- case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(),
- "Thomson .qd disk image, BASIC format" );
- break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS:
- strcpy( info->s = imgtool_temp_str(), "qd" ); break;
- case IMGTOOLINFO_PTR_OPEN:
- info->open = thom_open_fd_qd; break;
- case IMGTOOLINFO_PTR_CLOSE:
- info->close = thom_close_fd_qd; break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "H[1]-2;T[25];D[0];N" ); break;
- default:
- thom_basic_get_info( clas, param, info );
- }
-}
-
-void thom_sap_basic_get_info(const imgtool_class *clas,
- UINT32 param,
- union imgtoolinfo *info)
-{
- switch ( param ) {
- case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom_sap" ); break;
- case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(),
- "Thomson .sap disk image, BASIC format" );
- break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS:
- strcpy( info->s = imgtool_temp_str(), "sap" ); break;
- case IMGTOOLINFO_PTR_OPEN:
- info->open = thom_open_sap; break;
- case IMGTOOLINFO_PTR_CLOSE:
- info->close = thom_close_sap; break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "H[1];T40/[80];D0-[1];N" ); break;
- default:
- thom_basic_get_info( clas, param, info );
- }
-}
diff --git a/src/mess/tools/imgtool/modules/ti99.c b/src/mess/tools/imgtool/modules/ti99.c
deleted file mode 100644
index 220cbebdb27..00000000000
--- a/src/mess/tools/imgtool/modules/ti99.c
+++ /dev/null
@@ -1,5360 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/*
- Handlers for ti99 disk images
-
- We support the following types of image:
- * floppy disks ("DSK format") in v9t9, pc99 and old mess image format
- * hard disks ("WIN format") in MAME harddisk format (256-byte sectors only,
- i.e. no SCSI)
- Files are extracted in TIFILES format. There is a compile-time option to
- extract text files in flat format instead, but I need to re-implement it
- properly (using filters comes to mind).
-
- Raphael Nabet, 2002-2004
-
- TODO:
- - finish and test hd support ***test sibling FDR support***
- - check allocation bitmap against corruption when an image is opened
-*/
-
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-#include "imgtool.h"
-#include "harddisk.h"
-#include "imghd.h"
-
-/*
- Concepts shared by both disk structures:
- ----------------------------------------
-
- In both formats, the entire disk surface is split into physical records,
- each 256-byte-long. For best efficiency, the sector size is usually 256
- bytes so that one sector is equivalent to a physical record (this is true
- with floppies and HFDC hard disks). If the sector size is not 256 bytes
- (e.g. 512 bytes with SCSI hard disks, possibly 128 bytes on a TI-99
- simulator running on TI-990), sectors are grouped or split to form 256-byte
- physical records. Physical records are numbered from 0, with the first
- starting on sector 0 track 0. To avoid confusion with physical records in
- files, such physical records will be called "absolute physical records",
- abbreviated as "absolute physrecs" or "aphysrecs".
-
- Disk space is allocated in units referred to as AUs. Each AU represents an
- integral number of 256-byte physical records. The number of physrecs per
- AU varies depending on the disk format and size. AUs are numbered from 0,
- with the first starting with absolute physrec 0.
-
- Absolute physrec 0 contains a 256-byte record with volume information,
- which is called "Volume Information Block", abbreviated as "vib".
-
- To keep track of which areas on the disk are allocated and which are free,
- disk managers maintain a bit map of allocated AUs (called "allocation
- bitmap", abbreviated as "abm"). Each bit in the allocation bitmap
- represents an AU: if a bit is 0, the AU is free; if a bit is 1, the AU is
- allocated (or possibly bad if the disk manager can track bad sectors).
- Where on the disk the abm is located depends on the disk structure (see
- structure-specific description for details).
-
- Files are implemented as a succession of 256-byte physical records. To
- avoid confusion with absolute physical records, these physical records will
- be called "file physical records", abbreviated as "file physrecs" or
- "fphysrecs".
-
- Programs do normally not access file physical records directly. They may
- call high-level file routines that enable to create either fixed-length
- logical records of any size from 1 through 255, or variable-length records
- of any size from 0 through 254: logical records are grouped by file
- managers into 256-byte physical records. Some disk managers (HFDC and
- SCSI) allow programs to create fixed-length records larger than 255 bytes,
- too, but few programs use this possibility. Additionally, program files
- can be created: program files do not implement any logical record, and can
- be seen as a flat byte stream, not unlike files under MSDOS, UNIX and the C
- standard library. (Unfortunately, the API for program files lacks
- flexibility, and most programs that need to process a flat byte stream
- will use fixed-size records of 128 bytes.)
-
- Fixed-length records (reclen < 256) are grouped like this:
- fphysrec 0 fphysrec 1
- _______________ _______________
- |R0 |R1 |R2 |X| |R3 |R4 |R5 |X|
- --------------- ---------------
- \_/ \_/
- unused unused
- (size < reclen) (size < reclen)
-
- Fixed-length records (reclen > 256) are grouped like this:
- fphysrec 0 fphysrec 1 fphysrec 2 fphysrec 3 ...
- _________________ _________________ _________________ _________________
- | R0 (#0-255) | | R0 (#256-511) | |R0 (#512-end)|X| | R1 (#0-255) | ...
- ----------------- ----------------- ----------------- -----------------
- \_/
- unused
-
- Variable length records are grouped like this:
- fphysrec 0:
- byte:
- ------------------------------
- 0 |l0 = length of record 0 data|
- |----------------------------|
- 1 | |
- | |
- : | record 0 data |
- | |
- l0 | |
- |----------------------------|
- l0+1 |l1 = length of record 1 data|
- |----------------------------|
- l0+2 | |
- | |
- : | record 1 data |
- | |
- l0+l1+1 | |
- |----------------------------|
- : : :
- : : :
- |----------------------------|
- n |lm = length of record m data|
- |----------------------------|
- n+1 | |
- | |
- : | record m data |
- | |
- n+lm | |
- |----------------------------|
- n+lm+1 |>ff: EOR mark |
- |----------------------------|
- n+lm+2 | |
- | |
- : | unused |
- : |(we should have size < lm+1)|
- | |
- 255 | |
- ------------------------------
-
- fphysrec 1:
- byte:
- ------------------------------
- 0 |lm+1=length of record 0 data|
- |----------------------------|
- 1 | |
- | |
- : | record m+1 data |
- | |
- lm+1 | |
- |----------------------------|
- : : :
- : : :
-
- I think the EOR mark is not required if all 256 bytes of a physical
- record are used by logical records.
-
-
- All files are associated with a "file descriptor record" ("fdr") that holds
- file information (name, format, length) and points to the data AUs. The WIN
- disk structure also supports sibling FDRs, in case a file is so fragmented
- that all the data pointers cannot fit in one FDR; the DSK disk structure
- does not implement any such feature, and you may be unable to append data
- to an existing file if it is too fragmented, even though the disk is not
- full.
-
-
- DSK disk structure:
- -------------------
-
- The DSK disk structure is used for floppy disks, and a few RAMDISKs as
- well. It supports 1600 AUs and 16 MBytes at most (the 16 MByte value is a
- theorical maximum, as I doubt anyone has ever created so big a DSK volume).
-
- The disk sector size is always 256 bytes (the only potential exceptions are
- the SCSI floppy disk units and the TI-99 simulator on TI-990, but I don't
- know anything about either).
-
- For some reason, the number of physrecs per AU is always a power of 2.
- Originally, AUs always were one physical record each. However, since the
- allocation bitmap cannot support more than 1600 AUs, disks larger than
- 400kbytes need to have several physical records per AU. Note that
- relatively few disk controllers implement AUs that span multiple physical
- records (IIRC, these are Myarc's HFDC, SCSI DSR with floppy disk interface,
- and some upgraded Myarc and Corcomp DD floppy controllers).
-
- The allocation bitmap is located in the VIB. It is 200 bytes long, and
- supports 1600 AUs at most.
-
- Directories are implemented with a "File Descriptor Index Record" (FDIR)
- for each directory. The FDIR is array of 0 through 128 words, containing
- the aphysrec address of each fdr in the directory, sorted by ascending file
- name, terminated with a 0. Note that, while we should be prepared to read
- images images with 128 entries, I think (not 100% sure) that we should
- write no more than 127 for compatibility with some existing disk managers.
-
- Originally, the DSK structure only supported one directory level (i.e. the
- root directory level). The FDIR record for the root directory is always
- located in aphysrec 1. Moreover, Myarc extended the DSK structure to
- support up to 3 subdirectories in the root directory (note that there is no
- support for more subdirs, or for subdirs located in subdirs). To do so,
- they used an unused field of the VIB to hold the 10-char name of each
- directory and the aphysrec address of the associated FDIR record.
-
- aphysrec 0: Volume Information Block (VIB): see below
- aphysrec 1: FDIR for root directory
- Remaining AUs are used for fdr and data (and subdirectory FDIR if
- applicable). There is one FDIR record per directory; the FDIR points to
- the FDR for each file in the directory. The FDR (File Descriptor Record)
- contains the file information (name, format, length, pointers to data
- physrecs/AUs, etc).
-
-
- WIN disk structure:
- -------------------
-
- The WIN disk structure is used for hard disks. It supports 65535 AUs and
- 256 MBytes at most.
-
- The disk sector size is 256 bytes on HFDC, 512 bytes on SCSI. 512-byte
- sectors are split into 256-byte physical records.
-
- We may have from 1 through 16 physrecs per AUs. Since we cannot have more
- than 65535 AUs, we need to have several physical records per AU in disks
- larger than 16 Mbytes.
-
- Contrary to the DSK disk structure, the WIN disk structure supports
- hierarchic subdirectories, with a limit of 114 subdirectories and 127 files
- per directory. Each directory is associated with both a "Directory
- Descriptor Record" (DDR) and a "File Descriptor Index Record" (FDIR). The
- only exception is the root directory, which uses the VIB instead of a DDR
- (the VIB includes all the important fields of the DDR). The DDR contains
- some directory info (name, number of files and subdirectories directly
- enclosed in the directory, AU address of the FDIR of the parent directory,
- etc), the AU address of the associated FDIR, and the AU address of the DDR
- of up to 114 subdirectories, sorted by ascending directory name. The WIN
- FDIR is similar to, yet different from, the DSK FDIR: it contains up to 127
- (vs. 128) AU address (vs. aphysrec address) of each fdr in the directory,
- sorted by ascending file name. Additionally, it includes the AU address of
- the associated DDR.
-
- When a file has more than 54 data fragments, the disk manager creates
- sibling FDRs that hold additional fragments. (Sibling FDRs are called
- offspring FDRs in most existing documentation, but I prefer "sibling FDRs"
- as "offspring FDRs" wrongly suggests a directory-like hierarchy.
- Incidentally, I cannot really figure out why they chose to duplicate the
- FDR rather than create a file extension record, but there must be a
- reason.) Note that sibling FDRs usually fill unused physrecs in the AU
- allocated for the eldest FDR, and a new AU is allocated for new sibling
- FDRs only when the first AU is full.
-
- aphysrec 0: Volume Information Block (VIB): see below
- aphysrec 1-n (where n = 1+SUP(number_of_AUs/2048)): Volume bitmap
- Remaining AUs are used for ddr, fdir, fdr and data.
-*/
-
-/* Since string length is encoded with a byte, the maximum length of a string
-is 255. Since we need to add a device name (1 char minimum, typically 4 chars)
-and a '.' separator, we chose a practical value of 250 (though few applications
-will accept paths of such length). */
-#define MAX_PATH_LEN 253
-#define MAX_SAFE_PATH_LEN 250
-
-#define MAX_DIR_LEVEL 125 /* We need to put a recursion limit to avoid endless recursion hazard */
-
-
-#if 0
-#pragma mark MISCELLANEOUS UTILITIES
-#endif
-
-/*
- Miscellaneous utilities that are used to handle TI data types
-*/
-
-struct UINT16BE
-{
- UINT8 bytes[2];
-};
-
-struct UINT16LE
-{
- UINT8 bytes[2];
-};
-
-INLINE UINT16 get_UINT16BE(UINT16BE word)
-{
- return (word.bytes[0] << 8) | word.bytes[1];
-}
-
-INLINE void set_UINT16BE(UINT16BE *word, UINT16 data)
-{
- word->bytes[0] = (data >> 8) & 0xff;
- word->bytes[1] = data & 0xff;
-}
-
-INLINE UINT16 get_UINT16LE(UINT16LE word)
-{
- return word.bytes[0] | (word.bytes[1] << 8);
-}
-
-INLINE void set_UINT16LE(UINT16LE *word, UINT16 data)
-{
- word->bytes[0] = data & 0xff;
- word->bytes[1] = (data >> 8) & 0xff;
-}
-
-/*
- Convert a C string to a 10-character file name (padded with spaces if necessary)
-
- dst (O): destination 10-character array
- src (I): source C string
-*/
-static void str_to_fname(char dst[10], const char *src)
-{
- int i;
-
-
- i = 0;
-
- /* copy 10 characters at most */
- if (src)
- while ((i<10) && (src[i]!='\0'))
- {
- dst[i] = src[i];
- i++;
- }
-
- /* pad with spaces */
- while (i<10)
- {
- dst[i] = ' ';
- i++;
- }
-}
-
-/*
- Convert a 10-character file name to a C string (removing trailing spaces if necessary)
-
- dst (O): destination C string
- src (I): source 10-character array
- n (I): length of dst buffer (string may be truncated if less than 11)
-*/
-static void fname_to_str(char *dst, const char src[10], int n)
-{
- int i;
- int last_nonspace;
-
-
- /* copy 10 characters at most */
- if (--n > 10)
- n = 10;
-
- /* copy filename */
- i = 0;
- last_nonspace = -1;
-
- while (i<n)
- {
- dst[i] = src[i];
- if (src[i] != ' ')
- last_nonspace = i;
- i++;
- }
-
- /* terminate with '\0' */
- dst[last_nonspace+1] = '\0';
-}
-
-/*
- Check a 10-character file name.
-
- filename (I): 10-character array with file name
-
- Return non-zero if the file name is invalid.
-*/
-static int check_fname(const char filename[10])
-{
- int i;
- int space_found_flag;
-
-
- /* check and copy file name */
- space_found_flag = FALSE;
- for (i=0; i<10; i++)
- {
- switch (filename[i])
- {
- case '.':
- case '\0':
- /* illegal characters */
- return 1;
- case ' ':
- /* illegal in a file name, but file names shorter than 10
- characters are padded with spaces */
- space_found_flag = TRUE;
- break;
- default:
- /* all other characters are legal (though non-ASCII characters,
- control characters and even lower-case characters are not
- recommended) */
- if (space_found_flag)
- return 1;
- break;
- }
- }
-
- return 0;
-}
-
-/*
- Check a file path.
-
- fpath (I): C string with file path
-
- Return non-zero if the file path is invalid.
-*/
-static int check_fpath(const char *fpath)
-{
- const char *element_start, *element_end;
- int element_len;
-
-
- /* first check that the path is not too long and that there is no space
- character */
- if ((strlen(fpath) > MAX_PATH_LEN) || strchr(fpath, ' '))
- return 1;
-
- /* check that each path element has an acceptable length */
- element_start = fpath;
- do
- {
- /* find next path element */
- element_end = strchr(element_start, '.');
- element_len = element_end ? (element_end - element_start) : strlen(element_start);
- if ((element_len > 10) || (element_len == 0))
- return 1;
-
- /* iterate */
- if (element_end)
- element_start = element_end+1;
- else
- element_start = NULL;
- }
- while (element_start);
-
- return 0;
-}
-
-#if 0
-#pragma mark -
-#pragma mark LEVEL 1 DISK ROUTINES
-#endif
-
-/*
- Level 1 deals with accessing the disk hardware (in our case, the raw disk
- image).
-
- Higher level routines will only know the disk as a succession of
- 256-byte-long physical records addressed by a linear address.
-*/
-
-/*
- Disk geometry
-*/
-struct ti99_geometry
-{
- int secspertrack;
- int cylinders;
- int heads;
-};
-
-/*
- Physical sector address
-*/
-struct ti99_sector_address
-{
- int sector;
- int cylinder;
- int side;
-};
-
-/*
- Time stamp (used in fdr, and WIN VIB/DDR)
-*/
-struct ti99_date_time
-{
- UINT8 time_MSB, time_LSB;/* 0-4: hour, 5-10: minutes, 11-15: seconds/2 */
- UINT8 date_MSB, date_LSB;/* 0-6: year, 7-10: month, 11-15: day */
-};
-
-/*
- Subdirectory descriptor (HFDC only)
-
- The HFDC supports up to 3 subdirectories.
-*/
-struct dsk_subdir
-{
- char name[10]; /* subdirectory name (10 characters, pad with spaces) */
- UINT16BE fdir_aphysrec; /* aphysrec address of fdir record for this subdirectory */
-};
-
-/*
- DSK VIB record
-
- Most fields in this record are only relevant to level 2 routines, but level
- 1 routines need the disk geometry information extracted from the VIB.
-*/
-struct dsk_vib
-{
- char name[10]; /* disk volume name (10 characters, pad with spaces) */
- UINT16BE totphysrecs; /* total number of physrecs on disk (usually 360, */
- /* 720, 640, 1280 or 1440). (TI originally */
- /* said it should be the total number of AUs, */
- /* but, in practice, DSRs that supports disks */
- /* over 400kbytes (e.g. HFDC) write the total */
- /* number of physrecs.) */
- UINT8 secspertrack; /* sectors per track (usually 9 (FM SD), */
- /* 16 or 18 (MFM DD), or 36 (MFM HD) */
- UINT8 id[3]; /* 'DSK' */
- UINT8 protection; /* 'P' if disk is protected, ' ' otherwise. */
- UINT8 cylinders; /* tracks per side (usually 40) */
- UINT8 heads; /* sides (1 or 2) */
- UINT8 density; /* density: 1 (FM SD), 2 (MFM DD), or 3 (MFM HD) */
- dsk_subdir subdir[3]; /* descriptor for up to 3 subdirectories (HFDC only) */
- /* reserved by TI */
- UINT8 abm[200]; /* allocation bitmap: there is one bit per AU. */
- /* A binary 1 in a bit position indicates that */
- /* the allocation unit associated with that */
- /* bit has been allocated. */
- /* Bits corresponding to system reserved AUs, */
- /* non-existant AUs, and bad AUs, are set to one, too. */
- /* (AU 0 is associated to LSBit of byte 0, */
- /* AU 7 to MSBit of byte 0, AU 8 to LSBit */
- /* of byte 1, etc.) */
-};
-
-enum ti99_img_format
-{
- if_mess,
- if_v9t9,
- if_pc99_fm,
- if_pc99_mfm,
- if_harddisk
-};
-
-/*
- level-1 disk image descriptor
-*/
-struct ti99_lvl1_imgref
-{
- ti99_img_format img_format; /* tells the image format */
- imgtool_stream *file_handle; /* imgtool file handle */
- struct mess_hard_disk_file harddisk_handle; /* MAME harddisk handle (harddisk format) */
- ti99_geometry geometry; /* geometry */
- unsigned pc99_track_len; /* unformatted track length (pc99 format) */
- UINT32 *pc99_data_offset_array; /* offset for each sector (pc99 format) */
-};
-
-/*
- calculate CRC for data address marks or sector data
-
- crc (I/O): current CRC value to be updated (initialize to 0xffff before
- calling this function for the first time)
- value: new byte of data to update the CRC with
-*/
-static void calc_crc(UINT16 *crc, UINT8 value)
-{
- UINT8 l, h;
-
- l = value ^ (*crc >> 8);
- *crc = (*crc & 0xff) | (l << 8);
- l >>= 4;
- l ^= (*crc >> 8);
- *crc <<= 8;
- *crc = (*crc & 0xff00) | l;
- l = (l << 4) | (l >> 4);
- h = l;
- l = (l << 2) | (l >> 6);
- l &= 0x1f;
- *crc = *crc ^ (l << 8);
- l = h & 0xf0;
- *crc = *crc ^ (l << 8);
- l = (h << 1) | (h >> 7);
- l &= 0xe0;
- *crc = *crc ^ l;
-}
-
-/*
- Parse a PC99 disk image
-
- file_handle (I/O): imgtool file handle
- fm_format (I): if true, the image is in FM format, otherwise it is in MFM
- format
- pass (I): 0 for first pass, 1 for second pass
- vib (O): buffer where the vib should be stored (first pass)
- geometry (O): disk image geometry (second pass)
- data_offset_array (O): array of data offset to generate (second pass)
- out_track_len (O): track length is returned there
-
- Return imgtool error code
-*/
-#define MAX_TRACK_LEN 6872
-#define DATA_OFFSET_NONE 0xffffffff
-static int parse_pc99_image(imgtool_stream *file_handle, int fm_format, int pass, dsk_vib *vib, const ti99_geometry *geometry, UINT32 *data_offset_array, unsigned *out_track_len)
-{
- int track_len, num_tracks; /* length of a track in bytes, and number of tracks */
- int phys_track;
- int expected_cylinder, expected_head;
- int track_start_pos, track_pos;
- UINT8 c;
- UINT8 cylinder, head, sector;
- int seclen;
- UINT8 crc1, crc2;
- UINT16 crc;
- long data_offset;
- UINT8 track_buf[MAX_TRACK_LEN];
- int i;
-
- if (fm_format)
- track_len = 3253;
- else
- track_len = 6872;
-
- if (out_track_len)
- *out_track_len = track_len;
-
- if (stream_size(file_handle) % track_len)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- num_tracks = stream_size(file_handle) / track_len;
- if (num_tracks <= 0)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* we only support 40-track-per-side images */
- if ((num_tracks != 40) && (num_tracks != 80))
- return IMGTOOLERR_UNIMPLEMENTED;
-
- if (pass == 1)
- {
- /* initialize offset map */
- for (head = 0; head < geometry->heads; head++)
- for (cylinder = 0; cylinder < geometry->cylinders; cylinder++)
- for (sector = 0; sector < geometry->secspertrack; sector++)
- data_offset_array[(head*geometry->cylinders + cylinder)*geometry->secspertrack + sector] = DATA_OFFSET_NONE;
- }
- /* rewind to start of file */
- stream_seek(file_handle, 0, SEEK_SET);
-
- /* pass 0 only looks for vib in track 0; pass 1 scans every track */
- for (phys_track=0; phys_track < ((pass == 1) ? num_tracks : 1); phys_track++)
- {
- if (stream_read(file_handle, track_buf, track_len) != track_len)
- return IMGTOOLERR_READERROR;
-
- /* we only support 40-track-per-side images */
- expected_cylinder = phys_track % 40;
- expected_head = phys_track / 40;
-
- track_start_pos = 0;
-
- while (track_start_pos < track_len)
- {
- if (fm_format)
- {
- do
- {
- c = track_buf[track_start_pos];
- track_start_pos++;
- } while ((c != 0xfe) && (track_start_pos < track_len));
-
- if (c != 0xfe)
- break;
-
- track_pos = track_start_pos;
-
- crc = 0xffff;
- calc_crc(& crc, c);
- }
- else
- {
- do
- {
- c = track_buf[track_start_pos];
- track_start_pos++;
- } while ((c != 0xa1) && (track_start_pos < track_len));
-
- if (c != 0xa1)
- break;
-
- track_pos = track_start_pos;
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- if (c != 0xa1)
- continue;
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- if (c != 0xa1)
- continue;
-
- crc = 0xffff;
- calc_crc(& crc, c);
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- if (c != 0xfe)
- continue;
- }
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- cylinder = c;
- calc_crc(& crc, c);
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- head = c;
- calc_crc(& crc, c);
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- sector = c;
- calc_crc(& crc, c);
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- seclen = 128 << c;
- calc_crc(& crc, c);
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- crc1 = c;
- calc_crc(& crc, c);
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- crc2 = c;
- calc_crc(& crc, c);
-
-#if 0
- /* CRC seems to be completely hosed */
- if (crc)
- printf("aargh!");
-#endif
- if ((seclen != 256) || (crc1 != 0xf7) || (crc2 != 0xf7)
- || (cylinder != expected_cylinder) || (head != expected_head)
- || ((pass == 1) && ((cylinder >= geometry->cylinders)
- || (head >= geometry->heads)
- || (sector >= geometry->secspertrack))))
- continue;
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- while (c == (fm_format ? 0xff : 0x4e))
- {
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
- }
-
- while (c == 0x00)
- {
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
- }
-
- if (fm_format)
- {
- if (c != 0xfb)
- continue;
-
- crc = 0xffff;
- calc_crc(& crc, c);
- }
- else
- {
- if (c != 0xa1)
- continue;
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- if (c != 0xa1)
- continue;
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- if (c != 0xa1)
- continue;
-
- crc = 0xffff;
- calc_crc(& crc, c);
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- if (c != 0xfb)
- continue;
- }
- data_offset = track_pos;
- for (i=0; i<seclen; i++)
- {
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- calc_crc(& crc, c);
- }
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- crc1 = c;
- calc_crc(& crc, c);
-
- c = track_buf[track_pos];
- track_pos++;
- if (track_pos == track_len)
- track_pos = 0;
-
- crc2 = c;
- calc_crc(& crc, c);
-
-#if 0
- /* CRC seems to be completely hosed */
- if (crc)
- printf("aargh!");
-#endif
- if ((crc1 != 0xf7) || (crc2 != 0xf7))
- continue;
-
- switch (pass)
- {
- case 0:
- if ((cylinder == 0) && (head == 0) && (sector == 0))
- {
- /* return vib */
- if ((data_offset + 256) <= track_len)
- memcpy(vib, track_buf + data_offset, 256);
- else
- {
- memcpy((UINT8 *)vib, track_buf + data_offset, track_len-data_offset);
- memcpy((UINT8 *)vib + (track_len-data_offset), track_buf, 256-(track_len-data_offset));
- }
- return 0;
- }
- break;
-
- case 1:
- /* set up offset map */
- if (data_offset_array[(head*geometry->cylinders + cylinder)*geometry->secspertrack + sector] != DATA_OFFSET_NONE)
- /* error: duplicate sector */
- return IMGTOOLERR_CORRUPTIMAGE;
- data_offset_array[(head*geometry->cylinders + cylinder)*geometry->secspertrack + sector] = data_offset;
- break;
- }
- }
- }
-
- if (pass == 0)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (pass == 1)
- {
- /* check offset map */
- for (head = 0; head < geometry->heads; head++)
- for (cylinder = 0; cylinder < geometry->cylinders; cylinder++)
- for (sector = 0; sector < geometry->secspertrack; sector++)
- if (data_offset_array[(head*geometry->cylinders + cylinder)*geometry->secspertrack + sector] == DATA_OFFSET_NONE)
- /* error: missing sector */
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- return 0;
-}
-
-
-/*
- Read the volume information block (aphysrec 0) assuming no geometry
- information. (Called when an image is opened to figure out the
- geometry information.)
-
- file_handle (I/O): imgtool file handle
- img_format (I): image format (MESS, V9T9 or PC99)
- dest (O): pointer to 256-byte destination buffer
-
- Return imgtool error code
-*/
-static int read_image_vib_no_geometry(imgtool_stream *file_handle, ti99_img_format img_format, dsk_vib *dest)
-{
- int reply;
-
- switch (img_format)
- {
- case if_mess:
- case if_v9t9:
- /* seek to sector */
- reply = stream_seek(file_handle, 0, SEEK_SET);
- if (reply)
- return IMGTOOLERR_READERROR;
- /* read it */
- reply = stream_read(file_handle, dest, 256);
- if (reply != 256)
- return IMGTOOLERR_READERROR;
- return 0;
-
- case if_pc99_fm:
- case if_pc99_mfm:
- return parse_pc99_image(file_handle, img_format == if_pc99_fm, 0, dest, NULL, NULL, NULL);
-
- case if_harddisk:
- /* not implemented, because we don't need it */
- break;
- }
-
- return IMGTOOLERR_UNIMPLEMENTED;
-}
-
-/*
- Open a disk image at level 1
-
- file_handle (I/O): imgtool file handle
- img_format (I): image format (MESS, V9T9, PC99, or MAME harddisk)
- l1_img (O): level-1 image handle
- vib (O): buffer where the vib should be stored (floppy images only)
-
- Return imgtool error code
-*/
-static imgtoolerr_t open_image_lvl1(imgtool_stream *file_handle, ti99_img_format img_format, ti99_lvl1_imgref *l1_img, dsk_vib *vib)
-{
- imgtoolerr_t err;
- int reply;
- UINT16 totphysrecs;
-
-
- l1_img->img_format = img_format;
- l1_img->file_handle = file_handle;
-
- if (img_format == if_harddisk)
- {
- const hard_disk_info *info;
-
- err = imghd_open(file_handle, &l1_img->harddisk_handle);
- if (err)
- return err;
-
- info = imghd_get_header(&l1_img->harddisk_handle);
- l1_img->geometry.cylinders = info->cylinders;
- l1_img->geometry.heads = info->heads;
- l1_img->geometry.secspertrack = info->sectors;
- if (info->sectorbytes != 256)
- {
- imghd_close(&l1_img->harddisk_handle);
- return IMGTOOLERR_CORRUPTIMAGE; /* TODO: support 512-byte sectors */
- }
-
-#if 0
- /* read vib */
- reply = read_absolute_physrec(l1_img, 0, vib);
- if (reply)
- return reply;
-#endif
- }
- else
- {
- /* read vib */
- reply = read_image_vib_no_geometry(file_handle, img_format, vib);
- if (reply)
- return (imgtoolerr_t)reply;
-
- /* extract geometry information */
- totphysrecs = get_UINT16BE(vib->totphysrecs);
-
- l1_img->geometry.secspertrack = vib->secspertrack;
- if (l1_img->geometry.secspertrack == 0)
- /* Some images might be like this, because the original SSSD TI
- controller always assumes 9. */
- l1_img->geometry.secspertrack = 9;
- l1_img->geometry.cylinders = vib->cylinders;
- if (l1_img->geometry.cylinders == 0)
- /* Some images are like this, because the original SSSD TI
- controller always assumes 40. */
- l1_img->geometry.cylinders = 40;
- l1_img->geometry.heads = vib->heads;
- if (l1_img->geometry.heads == 0)
- /* Some images are like this, because the original SSSD TI
- controller always assumes that tracks beyond 40 are on side 2. */
- l1_img->geometry.heads = totphysrecs / (l1_img->geometry.secspertrack * l1_img->geometry.cylinders);
-
- /* check information */
- if ((totphysrecs != (l1_img->geometry.secspertrack * l1_img->geometry.cylinders * l1_img->geometry.heads))
- || (totphysrecs < 2)
- || memcmp(vib->id, "DSK", 3) || (! strchr(" P", vib->protection))
- || (((img_format == if_mess) || (img_format == if_v9t9))
- && (stream_size(file_handle) != totphysrecs*256U)))
- return (imgtoolerr_t)IMGTOOLERR_CORRUPTIMAGE;
-
- if ((img_format == if_pc99_fm) || (img_format == if_pc99_mfm))
- {
- l1_img->pc99_data_offset_array = (UINT32*)malloc(sizeof(*l1_img->pc99_data_offset_array)*totphysrecs);
- if (! l1_img->pc99_data_offset_array)
- return IMGTOOLERR_OUTOFMEMORY;
- reply = parse_pc99_image(file_handle, img_format == if_pc99_fm, 1, NULL, & l1_img->geometry, l1_img->pc99_data_offset_array, &l1_img->pc99_track_len);
- if (reply)
- {
- free(l1_img->pc99_data_offset_array);
- return (imgtoolerr_t)reply;
- }
- }
- }
-
- return (imgtoolerr_t)0;
-}
-
-/*
- Close a disk image at level 1
-
- l1_img (I/O): level-1 image handle
-
- Return imgtool error code
-*/
-static void close_image_lvl1(ti99_lvl1_imgref *l1_img)
-{
- if (l1_img->img_format == if_harddisk)
- {
- imghd_close(&l1_img->harddisk_handle);
- }
-
- stream_close(l1_img->file_handle);
-
- if ((l1_img->img_format == if_pc99_fm) || (l1_img->img_format == if_pc99_mfm))
- free(l1_img->pc99_data_offset_array);
-}
-
-/*
- Convert physical sector address to offset in disk image (old MESS and V9T9
- formats only)
-
- l1_img (I/O): level-1 image handle
- address (I): physical sector address
-
- Return offset in image
-*/
-INLINE int sector_address_to_image_offset(const ti99_lvl1_imgref *l1_img, const ti99_sector_address *address)
-{
- int offset = 0;
-
- switch (l1_img->img_format)
- {
- case if_mess:
- /* old MESS format */
- offset = (((address->cylinder*l1_img->geometry.heads) + address->side)*l1_img->geometry.secspertrack + address->sector)*256;
- break;
-
- case if_v9t9:
- /* V9T9 format */
- if (address->side & 1)
- /* on side 1, tracks are stored in the reverse order */
- offset = (((address->side*l1_img->geometry.cylinders) + (l1_img->geometry.cylinders-1 - address->cylinder))*l1_img->geometry.secspertrack + address->sector)*256;
- else
- offset = (((address->side*l1_img->geometry.cylinders) + address->cylinder)*l1_img->geometry.secspertrack + address->sector)*256;
- break;
-
- case if_pc99_fm:
- case if_pc99_mfm:
- /* pc99 format */
- case if_harddisk:
- /* harddisk format */
- assert(1); /* not implemented */
- break;
- }
-
- return offset;
-}
-
-/*
- Read one 256-byte sector from a disk image
-
- l1_img (I/O): level-1 image handle
- address (I): physical sector address
- dest (O): pointer to 256-byte destination buffer
-
- Return non-zero on error
-*/
-static int read_sector(ti99_lvl1_imgref *l1_img, const ti99_sector_address *address, void *dest)
-{
- int reply;
- UINT32 track_len, track_offset, sector_offset;
-
- switch (l1_img->img_format)
- {
- case if_mess:
- /* old MESS format */
- case if_v9t9:
- /* V9T9 format */
- /* seek to sector */
- reply = stream_seek(l1_img->file_handle, sector_address_to_image_offset(l1_img, address), SEEK_SET);
- if (reply)
- return 1;
- /* read it */
- reply = stream_read(l1_img->file_handle, dest, 256);
- if (reply != 256)
- return 1;
- break;
-
- case if_pc99_fm:
- case if_pc99_mfm:
- /* pc99 format */
- track_len = l1_img->pc99_track_len;
- track_offset = (address->side*l1_img->geometry.cylinders + address->cylinder)*track_len;
- sector_offset = l1_img->pc99_data_offset_array[(address->side*l1_img->geometry.cylinders + address->cylinder)*l1_img->geometry.secspertrack + address->sector];
-
- if ((sector_offset + 256) <= track_len)
- {
- /* seek to sector */
- reply = stream_seek(l1_img->file_handle, track_offset+sector_offset, SEEK_SET);
- if (reply)
- return 1;
- /* read it */
- reply = stream_read(l1_img->file_handle, dest, 256);
- if (reply != 256)
- return 1;
- }
- else
- {
- /* seek to sector */
- reply = stream_seek(l1_img->file_handle, track_offset+sector_offset, SEEK_SET);
- if (reply)
- return 1;
- /* read first chunk (until end of track) */
- reply = stream_read(l1_img->file_handle, (UINT8 *)dest, track_len-sector_offset);
- if (reply != track_len-sector_offset)
- return 1;
-
- /* wrap to start of track */
- reply = stream_seek(l1_img->file_handle, track_offset, SEEK_SET);
- if (reply)
- return 1;
- /* read remnant of sector */
- reply = stream_read(l1_img->file_handle, (UINT8 *)dest + (track_len-sector_offset), 256-(track_len-sector_offset));
- if (reply != 256-(track_len-sector_offset))
- return 1;
- }
- break;
-
- case if_harddisk:
- /* not implemented */
- assert(1);
- /*return imghd_read(l1_img->harddisk_handle, ((address->cylinder*l1_img->geometry.heads) + address->side)*l1_img->geometry.secspertrack + address->sector, 1, dest) != 1;*/
- break;
- }
-
- return 0;
-}
-
-/*
- Write one 256-byte sector to a disk image
-
- l1_img (I/O): level-1 image handle
- address (I): physical sector address
- src (I): pointer to 256-byte source buffer
-
- Return non-zero on error
-*/
-static int write_sector(ti99_lvl1_imgref *l1_img, const ti99_sector_address *address, const void *src)
-{
- int reply;
- UINT32 track_len, track_offset, sector_offset;
-
- switch (l1_img->img_format)
- {
- case if_mess:
- /* old MESS format */
- case if_v9t9:
- /* V9T9 format */
- /* seek to sector */
- reply = stream_seek(l1_img->file_handle, sector_address_to_image_offset(l1_img, address), SEEK_SET);
- if (reply)
- return 1;
- /* write it */
- reply = stream_write(l1_img->file_handle, src, 256);
- if (reply != 256)
- return 1;
- break;
-
- case if_pc99_fm:
- case if_pc99_mfm:
- /* pc99 format */
- track_len = l1_img->pc99_track_len;
- track_offset = (address->side*l1_img->geometry.cylinders + address->cylinder)*track_len;
- sector_offset = l1_img->pc99_data_offset_array[(address->side*l1_img->geometry.cylinders + address->cylinder)*l1_img->geometry.secspertrack + address->sector];
-
- if ((sector_offset + 256) <= track_len)
- {
- /* seek to sector */
- reply = stream_seek(l1_img->file_handle, track_offset+sector_offset, SEEK_SET);
- if (reply)
- return 1;
- /* write it */
- reply = stream_write(l1_img->file_handle, src, 256);
- if (reply != 256)
- return 1;
- }
- else
- {
- /* seek to sector */
- reply = stream_seek(l1_img->file_handle, track_offset+sector_offset, SEEK_SET);
- if (reply)
- return 1;
- /* write first chunk (until end of track) */
- reply = stream_write(l1_img->file_handle, (UINT8 *)src, track_len-sector_offset);
- if (reply != track_len-sector_offset)
- return 1;
-
- /* wrap to start of track */
- reply = stream_seek(l1_img->file_handle, track_offset, SEEK_SET);
- if (reply)
- return 1;
- /* write remnant of sector */
- reply = stream_write(l1_img->file_handle, (UINT8 *)src + (track_len-sector_offset), 256-(track_len-sector_offset));
- if (reply != 256-(track_len-sector_offset))
- return 1;
- }
- break;
-
- case if_harddisk:
- /* not implemented */
- assert(1);
- /*return imghd_write(l1_img->harddisk_handle, ((address->cylinder*l1_img->geometry.heads) + address->side)*l1_img->geometry.secspertrack + address->sector, 1, src) != 1;*/
- break;
- }
-
- return 0;
-}
-
-/*
- Convert physical record address to sector address (DSK format)
-
- aphysrec (I): absolute physrec address
- geometry (I): disk image geometry
- address (O): physical sector address
-*/
-static void dsk_aphysrec_to_sector_address(int aphysrec, const ti99_geometry *geometry, ti99_sector_address *address)
-{
- address->sector = aphysrec % geometry->secspertrack;
- aphysrec /= geometry->secspertrack;
- address->cylinder = aphysrec % geometry->cylinders;
- address->side = aphysrec / geometry->cylinders;
- if (address->side & 1)
- /* on side 1, tracks are stored in the reverse order */
- address->cylinder = geometry->cylinders-1 - address->cylinder;
-}
-
-/*
- Convert physical record address to sector address (WIN format for HFDC)
-
- Note that physical address translation makes sense for HFDC, but not SCSI.
-
- aphysrec (I): absolute physrec address
- geometry (I): disk image geometry
- address (O): physical sector address
-*/
-#ifdef UNUSED_FUNCTION
-static void win_aphysrec_to_sector_address(int aphysrec, const ti99_geometry *geometry, ti99_sector_address *address)
-{
- address.sector = aphysrec % l1_img->geometry.secspertrack;
- aphysrec /= l1_img->geometry.secspertrack;
- address.side = aphysrec % l1_img->geometry.heads;
- address.cylinder = aphysrec / l1_img->geometry.heads;
-}
-#endif
-
-/*
- Read one 256-byte physical record from a disk image
-
- l1_img (I/O): level-1 image handle
- aphysrec (I): absolute physrec address
- dest (O): pointer to 256-byte destination buffer
-
- Return non-zero on error
-*/
-static int read_absolute_physrec(ti99_lvl1_imgref *l1_img, unsigned aphysrec, void *dest)
-{
- ti99_sector_address address;
-
-
- if (l1_img->img_format == if_harddisk)
- {
-#if 0
- win_aphysrec_to_sector_address(aphysrec, & l1_img->geometry, & address);
- return read_sector(l1_img, & address, dest);
-#endif
-
- return imghd_read(&l1_img->harddisk_handle, aphysrec, dest) != IMGTOOLERR_SUCCESS;
- }
- else
- {
- dsk_aphysrec_to_sector_address(aphysrec, & l1_img->geometry, & address);
-
- return read_sector(l1_img, & address, dest);
- }
-}
-
-/*
- Write one 256-byte physical record to a disk image
-
- l1_img (I/O): level-1 image handle
- aphysrec (I): absolute physrec address
- src (I): pointer to 256-byte source buffer
-
- Return non-zero on error
-*/
-static int write_absolute_physrec(ti99_lvl1_imgref *l1_img, unsigned aphysrec, const void *src)
-{
- ti99_sector_address address;
-
-
- if (l1_img->img_format == if_harddisk)
- {
-#if 0
- win_aphysrec_to_sector_address(aphysrec, & l1_img->geometry, & address);
- return write_sector(l1_img, & address, dest);
-#endif
-
- return imghd_write(&l1_img->harddisk_handle, aphysrec, src) != IMGTOOLERR_SUCCESS;
- }
- else
- {
- dsk_aphysrec_to_sector_address(aphysrec, & l1_img->geometry, & address);
-
- return write_sector(l1_img, & address, src);
- }
-}
-
-#if 0
-#pragma mark -
-#pragma mark LEVEL 2 DISK ROUTINES
-#endif
-
-/*
- Level 2 implements files as a succession of 256-byte-long physical records.
-
- Level 2 implements allocation bitmap (and AU), disk catalog, etc.
-*/
-
-/*
- WIN VIB/DDR record
-*/
-struct win_vib_ddr
-{
- char name[10]; /* disk volume name (10 characters, pad with spaces) */
- UINT16BE totAUs; /* total number of AUs */
- UINT8 secspertrack; /* HFDC: sectors per track (typically 32) */
- /* SCSI: reserved */
- union
- {
- struct
- {
- UINT8 id[3]; /* V1 VIB: 'WIN' */
- } vib_v1;
-
- struct /* V2 VIB: extra params */
- {
- UINT8 res_AUs; /* # AUs reserved for vib, bitmap, ddr, fdir and fdr, divided by 64 */
- UINT8 step_spd; /* HFDC: step speed (0-7) */
- /* SCSI: reserved */
- UINT8 red_w_cur;/* HFDC: reduced write current cylinder, divided by 8 */
- /* SCSI: reserved */
- } vib_v2;
-
- struct
- {
- UINT8 id[3]; /* DDR: 'DIR' */
- } ddr;
- } u;
- UINT16BE params; /* bits 0-3: sectors/AU - 1 */
- /* HFDC: */
- /* bits 4-7: # heads - 1 */
- /* bit 8: V1: buffered head stepping flag */
- /* V2: reserved */
- /* bit 9-15: write precompensation track, divided by 16 */
- /* SCSI: */
- /* bits 4-15: reserved */
- ti99_date_time creation;/* date and time of creation */
- UINT8 num_files; /* number of files in directory */
- UINT8 num_subdirs; /* number of subdirectories in directory */
- UINT16BE fdir_AU; /* points to root directory fdir */
- union
- {
- struct
- {
- UINT16BE dsk1_AU; /* HFDC: points to current dsk1 emulation image (0 if none) */
- /* SCSI: reserved */
- } vib;
-
- struct
- {
- UINT16BE parent_ddr_AU; /* points to parent directory DDR */
- } ddr;
- } u2;
- UINT16BE subdir_AU[114];/* points to all subdirectory DDRs */
-};
-
-/*
- AU format
-*/
-struct ti99_AUformat
-{
- int totAUs; /* total number of AUs */
- int physrecsperAU; /* number of 256-byte physical records per AU */
-};
-
-/*
- DSK directory reference: 0 for root, 1 for 1st subdir, 2 for 2nd subdir, 3
- for 3rd subdir
-*/
-/*typedef int dir_ref;*/
-
-/*
- catalog entry (used for in-memory catalog)
-*/
-struct dir_entry
-{
- UINT16 dir_ptr; /* DSK: unused */
- /* WIN: AU address of the DDR for this directory */
- char name[10]; /* name of this directory (copied from the VIB for DSK, DDR for WIN) */
-};
-
-struct file_entry
-{
- UINT16 fdr_ptr; /* DSK: aphysrec address of the FDR for this file */
- /* WIN: AU address of the FDR for this file */
- char name[10]; /* name of this file (copied from FDR) */
-};
-
-struct ti99_catalog
-{
- int num_subdirs; /* number of subdirectories */
- int num_files; /* number of files */
- dir_entry subdirs[114]; /* description of each subdir */
- file_entry files[128]; /* description of each file */
-};
-
-/*
- level-2 disk image descriptor
-*/
-struct ti99_lvl2_imgref_dsk
-{
- UINT16 totphysrecs; /* total number of aphysrecs (extracted from vib record in aphysrec 0) */
- ti99_catalog catalogs[4]; /* catalog of root directory and up to 3 subdirectories */
- UINT16 fdir_aphysrec[4]; /* fdir aphysrec address for root directory
- and up to 3 subdirectories */
-};
-
-enum win_vib_t
-{
- win_vib_v1,
- win_vib_v2
-};
-struct ti99_lvl2_imgref_win
-{
- win_vib_t vib_version; /* version of the vib record in aphysrec 0 (see win_vib_ddr) */
-};
-
-enum l2i_t
-{
- L2I_DSK,
- L2I_WIN
-};
-
-struct ti99_lvl2_imgref
-{
- ti99_lvl1_imgref l1_img;/* image format, imgtool image handle, image geometry */
- ti99_AUformat AUformat; /* AU format */
- int data_offset; /* In order to reduce seek times when searching the
- disk for a given file name, fdr (and ddr, and
- fdir) records are preferentially allocated in
- AUs n to data_offset, whereas data records are
- preferentially allocated in AUs starting at
- data_offset. */
- /* With the DSK disk structure, n is always 2 (if 1
- physrec per AU) or 1 (if 2 physrecs per AU or
- more), and data_offset is arbitrarily chosen as
- 34. */
- /* With the WIN disk structure, n depends on the
- size of the volume bitmap, which itself depends
- on the number of AUs on disk (we always have n
- <= 33), and data_offset is read from the vib
- record (except with the obsolete v1 VIB, where
- we use a default value of 64). */
- char vol_name[10]; /* cached volume name (extracted from vib record in aphysrec 0) */
-
- UINT8 abm[8192]; /* allocation bitmap */
-
- l2i_t type; /* structure format */
-
- union
- {
- ti99_lvl2_imgref_dsk dsk;
- ti99_lvl2_imgref_win win;
- }; /* structure-specific info */
-};
-
-/*
- file flags found in fdr (and tifiles)
-*/
-enum
-{
- fdr99_f_program = 0x01, /* set for program files */
- fdr99_f_int = 0x02, /* set for binary files */
- fdr99_f_wp = 0x08, /* set if file is write-protected */
- /*fdr99_f_backup = 0x10,*/ /* set if file has been modified since last backup */
- /*fdr99_f_dskimg = 0x20,*/ /* set if file is a DSK image (HFDC HD only) */
- fdr99_f_var = 0x80 /* set if file uses variable-length records*/
-};
-
-/*
- DSK FDR record
-*/
-struct dsk_fdr
-{
- char name[10]; /* file name (10 characters, pad with spaces) */
- UINT16BE xreclen; /* extended record len: if record len is >= 256, */
- /* reclen is set to 0 and the actual reclen is */
- /* stored here (Myarc HFDC only). TI reserved */
- /* this field for data chain pointer extension, */
- /* but this was never implemented. */
- UINT8 flags; /* file status flags (see enum above) */
- UINT8 recsperphysrec; /* logical records per physrec */
- /* ignored for variable length record files and */
- /* program files */
- UINT16BE fphysrecs; /* file length in physrecs */
- /* Note that the HFDC defines this field as the */
- /* number of allocated physrecs in the cluster */
- /* chain (i.e. rounded on the next AU */
- /* boundary), so level-3 routines should use */
- /* the fixrecs field instead to determine the */
- /* logical length of field. IIRC, the HFDC */
- /* implementation is regarded as a bug because */
- /* program files do not define the fixrecs field */
- /* field, so program field saved by the HFDC */
- /* DSR may be larger whan they should. */
- UINT8 eof; /* EOF offset in last physrec for variable length */
- /* record files and program files (0->256)*/
- UINT8 reclen; /* logical record size in bytes ([1,255] 0->256) */
- /* Maximum allowable record size for variable */
- /* length record files. Reserved for program */
- /* files (set to 0). Set to 0 if reclen >=256 */
- /* (HFDC only). */
- UINT16LE fixrecs; /* file length in logical records */
- /* For variable length record files, number of */
- /* 256-byte records actually used. */
- ti99_date_time creation;/* date and time of creation (HFDC and BwG only; */
- /* reserved in TI) */
- ti99_date_time update; /* date and time of last write to file (HFDC and */
- /* BwG only; reserved in TI) */
- UINT8 clusters[76][3]; /* data cluster table: 0 through 76 entries (3 */
- /* bytes each), one entry for each file cluster. */
- /* 12 bits: address of first AU of cluster */
- /* 12 bits: offset of last 256-byte record in cluster */
-};
-
-/*
- WIN FDR record
-*/
-struct win_fdr
-{
- char name[10]; /* file name (10 characters, pad with spaces) */
- UINT16BE xreclen; /* extended record len: if record len is >= 256, */
- /* reclen is set to 0 and the actual reclen is */
- /* stored here (Myarc HFDC only). TI reserved */
- /* this field for data chain pointer extension, */
- /* but this was never implemented. */
- UINT8 flags; /* file status flags (see enum above) */
- UINT8 recsperphysrec; /* logical records per physrec */
- /* ignored for variable length record files and */
- /* program files */
- UINT16BE fphysrecs_LSW; /* eldest FDR: file length in physrecs */
- /* Note that the HFDC defines this field as the */
- /* number of allocated physrecs in the cluster */
- /* chain (i.e. rounded on the next AU */
- /* boundary), so level-3 routines should use */
- /* the fixrecs field instead to determine the */
- /* logical length of field. IIRC, the HFDC */
- /* implementation is regarded as a bug because */
- /* program files do not define the fixrecs field */
- /* field, so program field saved by the HFDC */
- /* DSR may be larger whan they should. */
- /* other sibling FDRs: index of the first file */
- /* physrec in this particular sibling FDR */
- UINT8 eof; /* EOF offset in last physrec for variable length */
- /* record files and program files (0->256)*/
- UINT8 reclen; /* logical record size in bytes ([1,255]) */
- /* Maximum allowable record size for variable */
- /* length record files. Reserved for program */
- /* files (set to 0). Set to 0 if reclen >=256 */
- /* (HFDC only). */
- UINT16LE fixrecs_LSW; /* file length in logical records */
- /* For variable length record files, number of */
- /* 256-byte records actually used. */
- ti99_date_time creation;/* date and time of creation */
- ti99_date_time update; /* date and time of last write to file */
-
- char id[2]; /* 'FI' */
- UINT16BE prevsibFDR_AU; /* address of the AU where previous sibling FDR is */
- /* (see also xinfo_LSB) */
- UINT16BE nextsibFDR_AU; /* address of the AU where next sibling FDR is */
- /* (see also xinfo_LSB) */
- UINT16BE sibFDR_AUlen; /* total number of data AUs allocated in this particular sibling FDR */
- UINT16BE parent_FDIR_AU;/* FDIR the file is listed in */
- UINT8 xinfo_MSB; /* extended information (MSByte) */
- /* bits 0-3: MSN of fphysrecs */
- /* bits 4-7: MSN of fixrecs */
- UINT8 xinfo_LSB; /* extended information (LSByte) */
- /* bits 8-11: physrec offset within AU for */
- /* previous sibling FDR (see prevsibFDR_AU) */
- /* bits 12-15: physrec offset within AU for */
- /* next sibling FDR (see nextsibFDR_AU) */
- UINT16BE clusters[54][2];/* data cluster table: 0 through 54 entries (4 */
- /* bytes each), one entry for each file cluster. */
- /* 16 bits: address of first AU of cluster */
- /* 16 bits: address of last AU of cluster */
-};
-
-/*
- tifile header: stand-alone file
-*/
-struct tifile_header
-{
- char tifiles[8]; /* always '\7TIFILES' */
- UINT16BE fphysrecs; /* file length in physrecs */
- UINT8 flags; /* see enum above */
- UINT8 recsperphysrec; /* records per physrec */
- UINT8 eof; /* current position of eof in last physrec (0->255)*/
- UINT8 reclen; /* bytes per record ([1,255] 0->256) */
- UINT16BE fixrecs; /* file length in records */
- UINT8 res[128-16]; /* reserved */
- /* * variant a: */
- /* 112 chars: 0xCA53 repeated 56 times */
- /* * variant b: */
- /* 4 chars: unknown */
- /* 108 chars: 0xCA53 repeated 54 times */
- /* * variant c: */
- /* 10 chars: original TI file name filed with spaces */
- /* 102 chars: spaces */
- /* * variant d: */
- /* 10 chars: original TI file name filed with spaces */
- /* 2 chars: CR+LF */
- /* 98 chars: spaces */
- /* 2 chars: CR+LF */
- /* * variant e: */
- /* 10 chars: original TI file name */
- /* 4 bytes: unknown */
- /* 4 bytes: time & date of creation */
- /* 4 bytes: time & date of last update */
- /* 90 chars: spaces */
- /* * variant f: */
- /* 6 bytes: 'MYTERM' */
- /* 4 bytes: time & date of creation */
- /* 4 bytes: time & date of last update */
- /* 2 bytes: unknown (always >0000) */
- /* 96 chars: 0xCA53 repeated 56 times */
-};
-
-/*
- level-2 file descriptor
-*/
-struct ti99_lvl2_fileref_dsk
-{
- struct ti99_lvl2_imgref *l2_img;
- int fdr_aphysrec;
- dsk_fdr fdr;
-};
-
-struct ti99_lvl2_fileref_win
-{
- struct ti99_lvl2_imgref *l2_img;
- unsigned fphysrecs; /* copy of field in the eldest FDR */
- unsigned eldestfdr_aphysrec; /* aphysrec address of the eldest FDR */
- unsigned curfdr_aphysrec; /* aphysrec address of the currently open sibling FDR */
- win_fdr curfdr; /* buffer with currently open sibling FDR */
-};
-
-struct ti99_lvl2_fileref_tifiles
-{
- imgtool_stream *file_handle;
- tifile_header hdr;
-};
-
-enum l2f_type_t
-{
- L2F_DSK,
- L2F_WIN,
- L2F_TIFILES
-};
-
-struct ti99_lvl2_fileref
-{
- l2f_type_t type;
- union
- {
- ti99_lvl2_fileref_dsk dsk;
- ti99_lvl2_fileref_win win;
- ti99_lvl2_fileref_tifiles tifiles;
- };
-};
-
-/*
- Compare two (possibly empty) catalog entry for qsort
-*/
-static int cat_file_compare_qsort(const void *p1, const void *p2)
-{
- const file_entry *entry1 = (const file_entry *)p1;
- const file_entry *entry2 = (const file_entry *)p2;
-
- if ((entry1->fdr_ptr == 0) && (entry2->fdr_ptr == 0))
- return 0;
- else if (entry1->fdr_ptr == 0)
- return +1;
- else if (entry2->fdr_ptr == 0)
- return -1;
- else
- return memcmp(entry1->name, entry2->name, 10);
-}
-
-static int cat_dir_compare_qsort(const void *p1, const void *p2)
-{
- const dir_entry *entry1 = (const dir_entry *)p1;
- const dir_entry *entry2 = (const dir_entry *)p2;
-
- if ((entry1->dir_ptr == 0) && (entry2->dir_ptr == 0))
- return 0;
- else if (entry1->dir_ptr == 0)
- return +1;
- else if (entry2->dir_ptr == 0)
- return -1;
- else
- return memcmp(entry1->name, entry2->name, 10);
-}
-
-/*
- Read a directory catalog from disk image
-
- l2_img: image reference
- aphysrec: physical record address of the FDIR
- dest: pointer to the destination buffer where the catalog should be written
-
- Return an error code if there was an error, 0 otherwise.
-*/
-static int dsk_read_catalog(struct ti99_lvl2_imgref *l2_img, int aphysrec, ti99_catalog *dest)
-{
- int totphysrecs = l2_img->dsk.totphysrecs;
- UINT16BE fdir_buf[128];
- dsk_fdr fdr;
- int i;
- int reply;
-
-
- /* Read FDIR record */
- reply = read_absolute_physrec(& l2_img->l1_img, aphysrec, fdir_buf);
- if (reply)
- return IMGTOOLERR_READERROR;
-
- /* Copy FDIR info to catalog structure */
- for (i=0; i<128; i++)
- dest->files[i].fdr_ptr = get_UINT16BE(fdir_buf[i]);
-
- /* Check FDIR pointers and check and extract file names from DDRs */
- for (i=0; i<128; i++)
- {
- if (dest->files[i].fdr_ptr >= totphysrecs)
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- else if (dest->files[i].fdr_ptr)
- {
- reply = read_absolute_physrec(& l2_img->l1_img, dest->files[i].fdr_ptr, &fdr);
- if (reply)
- return IMGTOOLERR_READERROR;
-
- /* check and copy file name */
- if (check_fname(fdr.name))
- return IMGTOOLERR_CORRUPTIMAGE;
- memcpy(dest->files[i].name, fdr.name, 10);
- }
- }
-
- /* Check catalog */
- for (i=0; i<127; i++)
- {
- if (((! dest->files[i].fdr_ptr) && dest->files[i+1].fdr_ptr)
- || ((dest->files[i].fdr_ptr && dest->files[i+1].fdr_ptr) && (memcmp(dest->files[i].name, dest->files[i+1].name, 10) >= 0)))
- {
- /* if the catalog is not sorted, we repair it */
- qsort(dest->files, ARRAY_LENGTH(dest->files), sizeof(dest->files[0]),
- cat_file_compare_qsort);
- break;
- }
- }
-
- /* Set file count */
- for (i=0; (i<128) && (dest->files[i].fdr_ptr != 0); i++)
- ;
- dest->num_files = i;
-
- /* Set subdir count to 0 (subdirs are loaded elsewhere) */
- dest->num_subdirs = 0;
-
- return 0;
-}
-
-/*
- Read a directory catalog from disk image
-
- l2_img: image reference
- DDR_AU: AU address of the VIB/DDR
- dest: pointer to the destination buffer where the catalog should be written
-
- Return an error code if there was an error, 0 otherwise.
-*/
-static int win_read_catalog(struct ti99_lvl2_imgref *l2_img, int DDR_AU, ti99_catalog *dest)
-{
- win_vib_ddr ddr_buf;
- UINT16BE fdir_buf[128];
- win_fdr fdr_buf;
- int i;
- int reply;
-
-
- /* Read DDR record */
- reply = read_absolute_physrec(& l2_img->l1_img, DDR_AU*l2_img->AUformat.physrecsperAU, &ddr_buf);
- if (reply)
- return IMGTOOLERR_READERROR;
-
- /* sanity checks */
- if ((ddr_buf.num_files > 127) || (ddr_buf.num_subdirs > 114) || (get_UINT16BE(ddr_buf.fdir_AU) > l2_img->AUformat.totAUs))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* set file count and subdir count */
- dest->num_files = ddr_buf.num_files;
- dest->num_subdirs = ddr_buf.num_subdirs;
-
- /* Copy DDR info to catalog structure */
- for (i=0; i<ddr_buf.num_subdirs; i++)
- dest->subdirs[i].dir_ptr = get_UINT16BE(ddr_buf.subdir_AU[i]);
-
- /* Read FDIR record */
- reply = read_absolute_physrec(& l2_img->l1_img, get_UINT16BE(ddr_buf.fdir_AU)*l2_img->AUformat.physrecsperAU, fdir_buf);
- if (reply)
- return IMGTOOLERR_READERROR;
-
- /* Copy FDIR info to catalog structure */
- for (i=0; i<dest->num_files; i++)
- dest->files[i].fdr_ptr = get_UINT16BE(fdir_buf[i]);
-
- /* Check DDR pointers and check and extract file names from FDRs */
- for (i=0; i<dest->num_subdirs; i++)
- {
- if (dest->subdirs[i].dir_ptr >= l2_img->AUformat.totAUs)
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- else if (dest->subdirs[i].dir_ptr)
- {
- reply = read_absolute_physrec(& l2_img->l1_img, dest->subdirs[i].dir_ptr*l2_img->AUformat.physrecsperAU, &ddr_buf);
- if (reply)
- return IMGTOOLERR_READERROR;
-
- /* check and copy file name */
- if (check_fname(ddr_buf.name))
- return IMGTOOLERR_CORRUPTIMAGE;
- memcpy(dest->subdirs[i].name, ddr_buf.name, 10);
- }
- }
-
- /* Check FDIR pointers and check and extract file names from FDRs */
- for (i=0; i<dest->num_files; i++)
- {
- if (dest->files[i].fdr_ptr >= l2_img->AUformat.totAUs)
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- else if (dest->files[i].fdr_ptr)
- {
- reply = read_absolute_physrec(& l2_img->l1_img, dest->files[i].fdr_ptr*l2_img->AUformat.physrecsperAU, &fdr_buf);
- if (reply)
- return IMGTOOLERR_READERROR;
-
- /* check and copy file name */
- if (check_fname(fdr_buf.name))
- return IMGTOOLERR_CORRUPTIMAGE;
- memcpy(dest->files[i].name, fdr_buf.name, 10);
- }
- }
-
- /* Check catalog */
-
- /* Check subdir order */
- for (i=0; i<dest->num_subdirs-1; i++)
- {
- if (((! dest->subdirs[i].dir_ptr) && dest->subdirs[i+1].dir_ptr)
- || ((dest->subdirs[i].dir_ptr && dest->subdirs[i+1].dir_ptr) && (memcmp(dest->subdirs[i].name, dest->subdirs[i+1].name, 10) >= 0)))
- {
- /* if the subdir catalog is not sorted, we repair it */
- qsort(dest->subdirs, dest->num_subdirs, sizeof(dest->subdirs[0]), cat_dir_compare_qsort);
- break;
- }
- }
-
- /* Fix subdir count */
- while (dest->num_subdirs && (dest->subdirs[dest->num_subdirs-1].dir_ptr == 0))
- dest->num_subdirs--;
-
- /* Check file order */
- for (i=0; i<dest->num_files-1; i++)
- {
- if (((! dest->files[i].fdr_ptr) && dest->files[i+1].fdr_ptr)
- || ((dest->files[i].fdr_ptr && dest->files[i+1].fdr_ptr) && (memcmp(dest->files[i].name, dest->files[i+1].name, 10) >= 0)))
- {
- /* if the file catalog is not sorted, we repair it */
- qsort(dest->files, dest->num_files, sizeof(dest->files[0]), cat_file_compare_qsort);
- break;
- }
- }
-
- /* Fix file count */
- while (dest->num_files && (dest->files[dest->num_files-1].fdr_ptr == 0))
- dest->num_files--;
-
- return 0;
-}
-
-/*
- Search for a file path on a floppy image
-
- l2_img: image reference
- fpath: path of the file to search
- parent_ref_valid: set to TRUE if either the file was found or the file was
- not found but its parent dir was
- parent_ref: reference to parent dir (0 for root)
- out_is_dir: TRUE if element is a directory
- catalog_index: on output, index of file catalog entry (may be NULL)
-*/
-static int dsk_find_catalog_entry(struct ti99_lvl2_imgref *l2_img, const char *fpath, int *parent_ref_valid, int *parent_ref, int *out_is_dir, int *catalog_index)
-{
- int i;
- const ti99_catalog *cur_catalog;
- const char *element_start, *element_end;
- int element_len;
- char element[10];
- int is_dir = FALSE;
-
-
- cur_catalog = & l2_img->dsk.catalogs[0];
- if (parent_ref_valid)
- (* parent_ref_valid) = FALSE;
- if (parent_ref)
- *parent_ref = 0;
-
- element_start = fpath;
- do
- {
- /* find next path element */
- element_end = strchr(element_start, '.');
- element_len = element_end ? (element_end - element_start) : strlen(element_start);
- if ((element_len > 10) || (element_len == 0))
- return IMGTOOLERR_BADFILENAME;
- /* last path element */
- if ((!element_end) && parent_ref_valid)
- (* parent_ref_valid) = TRUE;
-
- /* generate file name */
- memcpy(element, element_start, element_len);
- memset(element+element_len, ' ', 10-element_len);
-
- /* search entry in subdirectories */
- for (i = 0; i<cur_catalog->num_subdirs; i++)
- {
- if (! memcmp(element, cur_catalog->subdirs[i].name, 10))
- {
- is_dir = TRUE;
- break;
- }
- }
-
- /* if it failed, search entry in files */
- if (i == cur_catalog->num_subdirs)
- {
- for (i = 0; i<cur_catalog->num_files; i++)
- {
- if (! memcmp(element, cur_catalog->files[i].name, 10))
- {
- is_dir = FALSE;
- break;
- }
- }
- /* exit if not found */
- if (i == cur_catalog->num_files)
- {
- return IMGTOOLERR_FILENOTFOUND;
- }
- }
-
- /* iterate */
- if (element_end)
- {
- element_start = element_end+1;
-
- if (! is_dir)
- /* this is not a directory */
- return IMGTOOLERR_BADFILENAME;
-
- /* initialize cur_catalog */
- cur_catalog = & l2_img->dsk.catalogs[i+1];
- if (parent_ref)
- *parent_ref = i+1;
- }
- else
- element_start = NULL;
- }
- while (element_start);
-
- if (out_is_dir)
- *out_is_dir = is_dir;
-
- if (catalog_index)
- *catalog_index = i;
-
- return 0;
-}
-
-/*
- Search for a file path on a harddisk image
-
- l2_img: image reference
- fpath: path of the file to search
- parent_ref_valid: set to TRUE if either the file was found or the file was
- not found but its parent dir was
- parent_ddr_AU: parent DDR AU address (0 for root)
- parent_catalog: catalog of parent dir (cannot be NULL)
- out_is_dir: TRUE if element is a directory
- catalog_index: on output, index of file catalog entry (may be NULL)
-*/
-static int win_find_catalog_entry(struct ti99_lvl2_imgref *l2_img, const char *fpath,
- int *parent_ref_valid, int *parent_ddr_AU, ti99_catalog *parent_catalog,
- int *out_is_dir, int *catalog_index)
-{
- int i;
- const char *element_start, *element_end;
- int element_len;
- char element[10];
- int is_dir = FALSE;
- int errorcode;
-
- if (parent_ref_valid)
- (* parent_ref_valid) = FALSE;
- if (parent_ddr_AU)
- *parent_ddr_AU = 0;
-
- errorcode = win_read_catalog(l2_img, 0, parent_catalog);
- if (errorcode)
- return errorcode;
-
- element_start = fpath;
- do
- {
- /* find next path element */
- element_end = strchr(element_start, '.');
- element_len = element_end ? (element_end - element_start) : strlen(element_start);
- if ((element_len > 10) || (element_len == 0))
- return IMGTOOLERR_BADFILENAME;
- /* last path element */
- if ((!element_end) && parent_ref_valid)
- (* parent_ref_valid) = TRUE;
-
- /* generate file name */
- memcpy(element, element_start, element_len);
- memset(element+element_len, ' ', 10-element_len);
-
- /* search entry in subdirectories */
- for (i = 0; i<parent_catalog->num_subdirs; i++)
- {
- if (! memcmp(element, parent_catalog->subdirs[i].name, 10))
- {
- is_dir = TRUE;
- break;
- }
- }
-
- /* if it failed, search entry in files */
- if (i == parent_catalog->num_subdirs)
- {
- for (i = 0; i<parent_catalog->num_files; i++)
- {
- if (! memcmp(element, parent_catalog->files[i].name, 10))
- {
- is_dir = FALSE;
- break;
- }
- }
- /* exit if not found */
- if (i == parent_catalog->num_files)
- {
- return IMGTOOLERR_FILENOTFOUND;
- }
- }
-
- /* iterate */
- if (element_end)
- {
- element_start = element_end+1;
-
- if (! is_dir)
- /* this is not a directory */
- return IMGTOOLERR_BADFILENAME;
-
- if (parent_ddr_AU)
- *parent_ddr_AU = parent_catalog->subdirs[i].dir_ptr;
-
- errorcode = win_read_catalog(l2_img, parent_catalog->subdirs[i].dir_ptr, parent_catalog);
- if (errorcode)
- return errorcode;
- }
- else
- element_start = NULL;
- }
- while (element_start);
-
- if (out_is_dir)
- *out_is_dir = is_dir;
-
- if (catalog_index)
- *catalog_index = i;
-
- return 0;
-}
-
-/*
- Allocate one AU on disk, for use as a fdr record
-
- l2_img: image reference
- fdr_AU: on output, address of allocated AU
-*/
-static int alloc_fdr_AU(struct ti99_lvl2_imgref *l2_img, unsigned *fdr_AU)
-{
- int totAUs = l2_img->AUformat.totAUs;
- int i;
-
- for (i=0; i<totAUs; i++)
- {
- if (! (l2_img->abm[i >> 3] & (1 << (i & 7))))
- {
- *fdr_AU = i;
- l2_img->abm[i >> 3] |= 1 << (i & 7);
-
- return 0;
- }
- }
-
- return IMGTOOLERR_NOSPACE;
-}
-
-INLINE int get_dsk_fdr_cluster_baseAU(struct ti99_lvl2_imgref *l2_img, dsk_fdr *fdr, int cluster_index)
-{
- int reply;
-
- /* read base AU/physrec for this cluster */
- reply = ((fdr->clusters[cluster_index][1] & 0xf) << 8) | fdr->clusters[cluster_index][0];
- /* convert to AU address */
- if (l2_img->AUformat.physrecsperAU <= 2)
- reply /= l2_img->AUformat.physrecsperAU;
-
- return reply;
-}
-
-INLINE int get_dsk_fdr_cluster_baseaphysrec(struct ti99_lvl2_imgref *l2_img, dsk_fdr *fdr, int cluster_index)
-{
- int reply;
-
- /* read base AU/physrec for this cluster */
- reply = ((fdr->clusters[cluster_index][1] & 0xf) << 8) | fdr->clusters[cluster_index][0];
- /* convert to physrec address */
- if (l2_img->AUformat.physrecsperAU > 2)
- reply *= l2_img->AUformat.physrecsperAU;
-
- return reply;
-}
-
-INLINE int get_dsk_fdr_cluster_lastfphysrec(dsk_fdr *fdr, int cluster_index)
-{
- return (fdr->clusters[cluster_index][2] << 4) | (fdr->clusters[cluster_index][1] >> 4);
-}
-
-INLINE void set_dsk_fdr_cluster_lastfphysrec(dsk_fdr *fdr, int cluster_index, int data)
-{
- fdr->clusters[cluster_index][1] = (fdr->clusters[cluster_index][1] & 0x0f) | (data << 4);
- fdr->clusters[cluster_index][2] = data >> 4;
-}
-
-INLINE void set_dsk_fdr_cluster(struct ti99_lvl2_imgref *l2_img, dsk_fdr *fdr, int cluster_index, int baseAU, int lastfphysrec)
-{
- /* convert AU address to FDR value */
- if (l2_img->AUformat.physrecsperAU <= 2)
- baseAU *= l2_img->AUformat.physrecsperAU;
-
- /* write cluster entry */
- fdr->clusters[cluster_index][0] = baseAU;
- fdr->clusters[cluster_index][1] = ((baseAU >> 8) & 0x0f) | (lastfphysrec << 4);
- fdr->clusters[cluster_index][2] = lastfphysrec >> 4;
-}
-
-INLINE unsigned get_win_fdr_fphysrecs(win_fdr *fdr)
-{
- return (((unsigned) fdr->xinfo_MSB << 12) & 0xf0000) | get_UINT16BE(fdr->fphysrecs_LSW);
-}
-
-INLINE void set_win_fdr_fphysrecs(win_fdr *fdr, unsigned data)
-{
- fdr->xinfo_MSB = (fdr->xinfo_MSB & 0x0f) | ((data >> 12) & 0xf0);
- set_UINT16BE(&fdr->fphysrecs_LSW, data & 0xffff);
-}
-
-INLINE unsigned get_win_fdr_fixrecs(win_fdr *fdr)
-{
- return (((unsigned) fdr->xinfo_MSB << 16) & 0xf0000) | get_UINT16LE(fdr->fixrecs_LSW);
-}
-
-INLINE void set_win_fdr_fixrecs(win_fdr *fdr, unsigned data)
-{
- fdr->xinfo_MSB = (fdr->xinfo_MSB & 0xf0) | ((data >> 16) & 0x0f);
- set_UINT16LE(&fdr->fixrecs_LSW, data & 0xffff);
-}
-
-INLINE unsigned get_win_fdr_prevsibFDR_aphysrec(struct ti99_lvl2_imgref *l2_img, win_fdr *fdr)
-{
- unsigned prevsibFDR_AU = get_UINT16BE(fdr->prevsibFDR_AU);
-
- return prevsibFDR_AU
- ? (prevsibFDR_AU * l2_img->AUformat.physrecsperAU + ((fdr->xinfo_LSB >> 4) & 0xf))
- : 0;
-}
-
-INLINE unsigned get_win_fdr_nextsibFDR_aphysrec(struct ti99_lvl2_imgref *l2_img, win_fdr *fdr)
-{
- unsigned nextsibFDR_AU = get_UINT16BE(fdr->nextsibFDR_AU);
-
- return nextsibFDR_AU
- ? (nextsibFDR_AU * l2_img->AUformat.physrecsperAU + (fdr->xinfo_LSB & 0xf))
- : 0;
-}
-
-INLINE unsigned get_win_fdr_cursibFDR_basefphysrec(win_fdr *fdr)
-{
- return get_UINT16BE(fdr->prevsibFDR_AU) ? get_win_fdr_fphysrecs(fdr) : 0;
-}
-
-/*
- Advance to next sibling FDR
-*/
-static int win_goto_next_sibFDR(ti99_lvl2_fileref_win *win_file)
-{
- if (get_UINT16BE(win_file->curfdr.nextsibFDR_AU) == 0)
- return IMGTOOLERR_UNEXPECTED;
-
- win_file->curfdr_aphysrec = get_win_fdr_nextsibFDR_aphysrec(win_file->l2_img, &win_file->curfdr);
- if (read_absolute_physrec(& win_file->l2_img->l1_img, win_file->curfdr_aphysrec, &win_file->curfdr))
- return IMGTOOLERR_READERROR;
-
- return 0;
-}
-
-/*
- Back to previous sibling FDR
-*/
-static int win_goto_prev_sibFDR(ti99_lvl2_fileref_win *win_file)
-{
- if (get_UINT16BE(win_file->curfdr.prevsibFDR_AU) == 0)
- return IMGTOOLERR_UNEXPECTED;
-
- win_file->curfdr_aphysrec = get_win_fdr_prevsibFDR_aphysrec(win_file->l2_img, &win_file->curfdr);
- if (read_absolute_physrec(& win_file->l2_img->l1_img, win_file->curfdr_aphysrec, &win_file->curfdr))
- return IMGTOOLERR_READERROR;
-
- return 0;
-}
-
-/*
- Append a new sibling FDR at the end of the sibling FDR list, and open it.
-
- You must have gone to the end of the list.
-*/
-static int win_alloc_sibFDR(ti99_lvl2_fileref_win *win_file)
-{
- unsigned oldfdr_AU, oldfdr_physrecinAU;
- unsigned newfdr_AU, newfdr_physrecinAU;
- int allocated = FALSE;
- int errorcode;
- unsigned cursibFDR_basefphysrec;
-
- if (get_UINT16BE(win_file->curfdr.nextsibFDR_AU))
- return IMGTOOLERR_UNEXPECTED;
-
- oldfdr_AU = win_file->curfdr_aphysrec / win_file->l2_img->AUformat.physrecsperAU;
- oldfdr_physrecinAU = win_file->curfdr_aphysrec % win_file->l2_img->AUformat.physrecsperAU;
-
- if (oldfdr_physrecinAU != (win_file->l2_img->AUformat.physrecsperAU - 1))
- { /* current AU is not full */
- newfdr_AU = oldfdr_AU;
- newfdr_physrecinAU = oldfdr_physrecinAU + 1;
- }
- else
- { /* current AU is full: allocate another */
- errorcode = alloc_fdr_AU(win_file->l2_img, &newfdr_AU);
- if (errorcode)
- return errorcode;
- newfdr_physrecinAU = 0;
- allocated = TRUE;
- }
-
- set_UINT16BE(&win_file->curfdr.nextsibFDR_AU, newfdr_AU);
- win_file->curfdr.xinfo_LSB = (win_file->curfdr.xinfo_LSB & 0xf0) | newfdr_physrecinAU;
-
- /* save current sibling FDR */
- if (write_absolute_physrec(& win_file->l2_img->l1_img, win_file->curfdr_aphysrec, &win_file->curfdr))
- {
- /* clear pointer */
- set_UINT16BE(&win_file->curfdr.nextsibFDR_AU, 0);
- win_file->curfdr.xinfo_LSB = win_file->curfdr.xinfo_LSB & 0xf0;
- if (allocated)
- /* free AU */
- win_file->l2_img->abm[newfdr_AU >> 3] |= 1 << (newfdr_AU & 7);
- return IMGTOOLERR_WRITEERROR;
- }
-
- /* now update in-memory structure to describe new sibling FDR */
- cursibFDR_basefphysrec = get_win_fdr_cursibFDR_basefphysrec(&win_file->curfdr)
- + get_UINT16BE(win_file->curfdr.sibFDR_AUlen) * win_file->l2_img->AUformat.physrecsperAU;
-
- set_UINT16BE(&win_file->curfdr.nextsibFDR_AU, 0);
- set_UINT16BE(&win_file->curfdr.prevsibFDR_AU, oldfdr_AU);
- win_file->curfdr.xinfo_LSB = oldfdr_physrecinAU << 4;
-
- win_file->curfdr_aphysrec = newfdr_AU * win_file->l2_img->AUformat.physrecsperAU + newfdr_physrecinAU;
-
- set_win_fdr_fphysrecs(&win_file->curfdr, cursibFDR_basefphysrec);
- set_UINT16BE(&win_file->curfdr.sibFDR_AUlen, 0);
- memset(win_file->curfdr.clusters, 0, sizeof(win_file->curfdr.clusters));
-
- return 0;
-}
-
-/*
- Extend a file with nb_alloc_physrecs extra physrecs
-
- dsk_file: file reference
- nb_alloc_physrecs: number of physical records to allocate
-*/
-static int dsk_alloc_file_physrecs(ti99_lvl2_fileref_dsk *dsk_file, int nb_alloc_physrecs)
-{
- int totAUs = dsk_file->l2_img->AUformat.totAUs;
- int free_physrecs;
- int fphysrecs;
- int i;
- int cluster_index;
- int last_sec, p_last_sec = 0;
- int cur_block_seclen;
- int cluster_baseAU, cluster_AUlen;
- int first_best_block_baseAU = 0, first_best_block_seclen;
- int second_best_block_baseAU = 0, second_best_block_seclen;
- int search_start;
-
- /* compute free space */
- free_physrecs = 0;
- for (i=0; i<totAUs; i++)
- {
- if (! (dsk_file->l2_img->abm[i >> 3] & (1 << (i & 7))))
- free_physrecs += dsk_file->l2_img->AUformat.physrecsperAU;
- }
-
- /* check we have enough free space */
- if (free_physrecs < nb_alloc_physrecs)
- return IMGTOOLERR_NOSPACE;
-
- /* current number of data physrecs in file */
- fphysrecs = get_UINT16BE(dsk_file->fdr.fphysrecs);
-
- if (fphysrecs == 0)
- { /* cluster array must be empty */
- cluster_index = 0;
- }
- else
- { /* try to extend last block */
- last_sec = -1;
- for (cluster_index=0; cluster_index<76; cluster_index++)
- {
- p_last_sec = last_sec;
- last_sec = get_dsk_fdr_cluster_lastfphysrec(&dsk_file->fdr, cluster_index);
- if (last_sec >= (fphysrecs-1))
- break;
- }
- if (cluster_index == 76)
- /* that sucks */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (last_sec > (fphysrecs-1))
- { /* some extra space has already been allocated */
- cur_block_seclen = last_sec - (fphysrecs-1);
- if (cur_block_seclen > nb_alloc_physrecs)
- cur_block_seclen = nb_alloc_physrecs;
-
- fphysrecs += cur_block_seclen;
- set_UINT16BE(& dsk_file->fdr.fphysrecs, fphysrecs);
- nb_alloc_physrecs -= cur_block_seclen;
- if (! nb_alloc_physrecs)
- return 0; /* done */
- }
-
- /* round up to next AU boundary */
- last_sec = last_sec + dsk_file->l2_img->AUformat.physrecsperAU - (last_sec % dsk_file->l2_img->AUformat.physrecsperAU) - 1;
-
- if (last_sec > (fphysrecs-1))
- { /* some extra space has already been allocated */
- cur_block_seclen = last_sec - (fphysrecs-1);
- if (cur_block_seclen > nb_alloc_physrecs)
- cur_block_seclen = nb_alloc_physrecs;
-
- fphysrecs += cur_block_seclen;
- set_UINT16BE(& dsk_file->fdr.fphysrecs, fphysrecs);
- set_dsk_fdr_cluster_lastfphysrec(&dsk_file->fdr, cluster_index, fphysrecs-1);
- nb_alloc_physrecs -= cur_block_seclen;
- if (! nb_alloc_physrecs)
- return 0; /* done */
- }
-
- /* read base AU address for this cluster */
- cluster_baseAU = get_dsk_fdr_cluster_baseAU(dsk_file->l2_img, &dsk_file->fdr, cluster_index);
- /* point past cluster end */
- cluster_baseAU += (last_sec-p_last_sec/*+file->l2_img->AUformat.physrecsperAU-1*/) / dsk_file->l2_img->AUformat.physrecsperAU;
- /* count free physrecs after last block */
- cur_block_seclen = 0;
- for (i=cluster_baseAU; (! (dsk_file->l2_img->abm[i >> 3] & (1 << (i & 7)))) && (cur_block_seclen < nb_alloc_physrecs) && (i < totAUs); i++)
- cur_block_seclen += dsk_file->l2_img->AUformat.physrecsperAU;
- if (cur_block_seclen)
- { /* extend last block */
- if (cur_block_seclen > nb_alloc_physrecs)
- cur_block_seclen = nb_alloc_physrecs;
-
- fphysrecs += cur_block_seclen;
- set_UINT16BE(& dsk_file->fdr.fphysrecs, fphysrecs);
- last_sec += cur_block_seclen;
- nb_alloc_physrecs -= cur_block_seclen;
- set_dsk_fdr_cluster_lastfphysrec(&dsk_file->fdr, cluster_index, last_sec);
- cluster_AUlen = (cur_block_seclen + dsk_file->l2_img->AUformat.physrecsperAU - 1) / dsk_file->l2_img->AUformat.physrecsperAU;
- for (i=0; i<cluster_AUlen; i++)
- dsk_file->l2_img->abm[(i+cluster_baseAU) >> 3] |= 1 << ((i+cluster_baseAU) & 7);
- if (! nb_alloc_physrecs)
- return 0; /* done */
- }
- cluster_index++;
- if (cluster_index == 76)
- /* that sucks */
- return IMGTOOLERR_NOSPACE;
- }
-
- search_start = dsk_file->l2_img->data_offset; /* initially, search for free space only in data space */
- while (nb_alloc_physrecs)
- {
- /* find smallest data block at least nb_alloc_physrecs in length, and largest data block less than nb_alloc_physrecs in length */
- first_best_block_seclen = INT_MAX;
- second_best_block_seclen = 0;
- for (i=search_start; i<totAUs; i++)
- {
- if (! (dsk_file->l2_img->abm[i >> 3] & (1 << (i & 7))))
- { /* found one free block */
- /* compute its length */
- cluster_baseAU = i;
- cur_block_seclen = 0;
- while ((i<totAUs) && (! (dsk_file->l2_img->abm[i >> 3] & (1 << (i & 7)))))
- {
- cur_block_seclen += dsk_file->l2_img->AUformat.physrecsperAU;
- i++;
- }
- /* compare to previous best and second-best blocks */
- if ((cur_block_seclen < first_best_block_seclen) && (cur_block_seclen >= nb_alloc_physrecs))
- {
- first_best_block_baseAU = cluster_baseAU;
- first_best_block_seclen = cur_block_seclen;
- if (cur_block_seclen == nb_alloc_physrecs)
- /* no need to search further */
- break;
- }
- else if ((cur_block_seclen > second_best_block_seclen) && (cur_block_seclen < nb_alloc_physrecs))
- {
- second_best_block_baseAU = cluster_baseAU;
- second_best_block_seclen = cur_block_seclen;
- }
- }
- }
-
- if (first_best_block_seclen != INT_MAX)
- { /* found one contiguous block which can hold it all */
- fphysrecs += nb_alloc_physrecs;
- set_UINT16BE(& dsk_file->fdr.fphysrecs, fphysrecs);
-
- set_dsk_fdr_cluster(dsk_file->l2_img, &dsk_file->fdr, cluster_index, first_best_block_baseAU, fphysrecs-1);
- cluster_AUlen = (nb_alloc_physrecs + dsk_file->l2_img->AUformat.physrecsperAU - 1) / dsk_file->l2_img->AUformat.physrecsperAU;
- for (i=0; i<cluster_AUlen; i++)
- dsk_file->l2_img->abm[(i+first_best_block_baseAU) >> 3] |= 1 << ((i+first_best_block_baseAU) & 7);
-
- nb_alloc_physrecs = 0;
- }
- else if (second_best_block_seclen != 0)
- { /* jeez, we need to fragment it. We use the largest smaller block to limit fragmentation. */
- fphysrecs += second_best_block_seclen;
- set_UINT16BE(& dsk_file->fdr.fphysrecs, fphysrecs);
-
- set_dsk_fdr_cluster(dsk_file->l2_img, &dsk_file->fdr, cluster_index, second_best_block_baseAU, fphysrecs-1);
- cluster_AUlen = (second_best_block_seclen + dsk_file->l2_img->AUformat.physrecsperAU - 1) / dsk_file->l2_img->AUformat.physrecsperAU;
- for (i=0; i<cluster_AUlen; i++)
- dsk_file->l2_img->abm[(i+second_best_block_baseAU) >> 3] |= 1 << ((i+second_best_block_baseAU) & 7);
-
- nb_alloc_physrecs -= second_best_block_seclen;
-
- cluster_index++;
- if (cluster_index == 76)
- /* that sucks */
- return IMGTOOLERR_NOSPACE;
- }
- else if (search_start != 0)
- { /* we did not find any free physrec in the data section of the disk */
- search_start = 0; /* time to fall back to fdr space */
- }
- else
- return IMGTOOLERR_NOSPACE; /* This should never happen, as we pre-check that there is enough free space */
- }
-
- return 0;
-}
-
-/*
- Extend a file with nb_alloc_physrecs extra physrecs
-
- win_file: file reference
- nb_alloc_physrecs: number of physical records to allocate
-*/
-static int win_alloc_file_physrecs(ti99_lvl2_fileref_win *win_file, int nb_alloc_physrecs)
-{
- int totAUs = win_file->l2_img->AUformat.totAUs;
- int free_physrecs;
- int fphysrecs;
- int i;
- int cluster_index;
- int num_fphysrec;
- int cur_block_seclen;
- int cluster_baseAU, cluster_AUlen;
- int first_best_block_baseAU = 0, first_best_block_seclen;
- int second_best_block_baseAU = 0, second_best_block_seclen;
- int search_start;
- int errorcode;
-
- /* compute free space */
- free_physrecs = 0;
- for (i=0; i<totAUs; i++)
- {
- if (! (win_file->l2_img->abm[i >> 3] & (1 << (i & 7))))
- free_physrecs += win_file->l2_img->AUformat.physrecsperAU;
- }
-
- /* check we have enough free space */
- if (free_physrecs < nb_alloc_physrecs)
- return IMGTOOLERR_NOSPACE;
-
- /* move to last sibling non-empty FDR */
- while ((get_UINT16BE(win_file->curfdr.nextsibFDR_AU) != 0) &&
- (get_UINT16BE(win_file->curfdr.clusters[53][0]) != 0))
- {
- errorcode = win_goto_next_sibFDR(win_file);
- if (errorcode)
- return errorcode;
- }
- if ((get_UINT16BE(win_file->curfdr.clusters[0][0]) == 0) && (get_UINT16BE(win_file->curfdr.prevsibFDR_AU) != 0))
- { /* this is annoying: we have found a sibling FDR filled with 0s: rewind
- to last non-empty sibling if applicable */
- errorcode = win_goto_prev_sibFDR(win_file);
- if (errorcode)
- return errorcode;
- }
-
- /* current number of data physrecs in file */
- fphysrecs = win_file->fphysrecs;
-
- /* current number of allocated physrecs */
- num_fphysrec = get_win_fdr_cursibFDR_basefphysrec(&win_file->curfdr)
- + get_UINT16BE(win_file->curfdr.sibFDR_AUlen) * win_file->l2_img->AUformat.physrecsperAU;
-
- if (num_fphysrec > fphysrecs)
- { /* some extra space has already been allocated */
- cur_block_seclen = num_fphysrec - fphysrecs;
- if (cur_block_seclen > nb_alloc_physrecs)
- cur_block_seclen = nb_alloc_physrecs;
-
- fphysrecs += cur_block_seclen;
- win_file->fphysrecs = fphysrecs;
- /* TODO: update eldest FDR fphysrecs field */
- /*set_win_fdr_fphysrecs(& win_file->rootfdr.fphysrecs, fphysrecs);*/
- nb_alloc_physrecs -= cur_block_seclen;
- if (! nb_alloc_physrecs)
- return 0; /* done */
- }
-
- /* find last non-empty cluster */
- for (cluster_index=0; (cluster_index<54) && (get_UINT16BE(win_file->curfdr.clusters[cluster_index][0]) != 0); cluster_index++)
- ;
- /* if we are dealing with an empty file, we will have (cluster_index == 0)... */
- if (cluster_index != 0)
- {
- cluster_index--;
- /* try to extend last cluster */
- /* point past cluster end */
- cluster_baseAU = get_UINT16BE(win_file->curfdr.clusters[cluster_index][1]) + 1;
- /* count free physrecs after last block */
- cur_block_seclen = 0;
- for (i=cluster_baseAU; (! (win_file->l2_img->abm[i >> 3] & (1 << (i & 7)))) && (cur_block_seclen < nb_alloc_physrecs) && (i < totAUs); i++)
- cur_block_seclen += win_file->l2_img->AUformat.physrecsperAU;
- if (cur_block_seclen)
- { /* extend last block */
- if (cur_block_seclen > nb_alloc_physrecs)
- cur_block_seclen = nb_alloc_physrecs;
-
- fphysrecs += cur_block_seclen;
- cluster_AUlen = (cur_block_seclen + win_file->l2_img->AUformat.physrecsperAU - 1) / win_file->l2_img->AUformat.physrecsperAU;
- win_file->fphysrecs = fphysrecs;
- /* TODO: update eldest FDR fphysrecs field */
- /*set_win_fdr_fphysrecs(& win_file->rootfdr.fphysrecs, fphysrecs);*/
- set_UINT16BE(&win_file->curfdr.sibFDR_AUlen,
- get_UINT16BE(win_file->curfdr.sibFDR_AUlen)+cluster_AUlen);
- set_UINT16BE(&win_file->curfdr.clusters[cluster_index][1],
- get_UINT16BE(win_file->curfdr.clusters[cluster_index][1])+cluster_AUlen);
- for (i=0; i<cluster_AUlen; i++)
- win_file->l2_img->abm[(i+cluster_baseAU) >> 3] |= 1 << ((i+cluster_baseAU) & 7);
- nb_alloc_physrecs -= cur_block_seclen;
- if (! nb_alloc_physrecs)
- return 0; /* done */
- }
- /* now point to first free entry in cluster table */
- cluster_index++;
- }
-
- search_start = win_file->l2_img->data_offset; /* initially, search for free space only in data space */
- while (nb_alloc_physrecs)
- {
- /* find smallest data block at least nb_alloc_physrecs in length, and largest data block less than nb_alloc_physrecs in length */
- first_best_block_seclen = INT_MAX;
- second_best_block_seclen = 0;
- for (i=search_start; i<totAUs; i++)
- {
- if (! (win_file->l2_img->abm[i >> 3] & (1 << (i & 7))))
- { /* found one free block */
- /* compute its length */
- cluster_baseAU = i;
- cur_block_seclen = 0;
- while ((i<totAUs) && (! (win_file->l2_img->abm[i >> 3] & (1 << (i & 7)))))
- {
- cur_block_seclen += win_file->l2_img->AUformat.physrecsperAU;
- i++;
- }
- /* compare to previous best and second-best blocks */
- if ((cur_block_seclen < first_best_block_seclen) && (cur_block_seclen >= nb_alloc_physrecs))
- {
- first_best_block_baseAU = cluster_baseAU;
- first_best_block_seclen = cur_block_seclen;
- if (cur_block_seclen == nb_alloc_physrecs)
- /* no need to search further */
- break;
- }
- else if ((cur_block_seclen > second_best_block_seclen) && (cur_block_seclen < nb_alloc_physrecs))
- {
- second_best_block_baseAU = cluster_baseAU;
- second_best_block_seclen = cur_block_seclen;
- }
- }
- }
-
- if ((first_best_block_seclen != INT_MAX) || (second_best_block_seclen != 0))
- {
- if (cluster_index == 54)
- {
- /* end of cluster list: go to next sibling FDR */
- if (write_absolute_physrec(& win_file->l2_img->l1_img, win_file->curfdr_aphysrec, &win_file->curfdr))
- return IMGTOOLERR_WRITEERROR;
- if (get_UINT16BE(win_file->curfdr.nextsibFDR_AU) != 0)
- { /* read next sibling FDR */
- errorcode = win_goto_next_sibFDR(win_file);
- if (errorcode)
- return errorcode;
- }
- else
- { /* allocate new sibling FDR */
- errorcode = win_alloc_sibFDR(win_file);
- if (errorcode)
- return errorcode;
- }
- cluster_index = 0;
- }
- }
-
- if (first_best_block_seclen != INT_MAX)
- { /* found one contiguous block which can hold it all */
- fphysrecs += nb_alloc_physrecs;
- cluster_AUlen = (nb_alloc_physrecs + win_file->l2_img->AUformat.physrecsperAU - 1) / win_file->l2_img->AUformat.physrecsperAU;
- win_file->fphysrecs = fphysrecs;
- /* TODO: update eldest FDR fphysrecs field */
- /*set_win_fdr_fphysrecs(& win_file->rootfdr.fphysrecs, fphysrecs);*/
- set_UINT16BE(&win_file->curfdr.sibFDR_AUlen,
- get_UINT16BE(win_file->curfdr.sibFDR_AUlen)+cluster_AUlen);
- set_UINT16BE(&win_file->curfdr.clusters[cluster_index][0], first_best_block_baseAU);
- set_UINT16BE(&win_file->curfdr.clusters[cluster_index][1],
- first_best_block_baseAU+cluster_AUlen-1);
-
- for (i=0; i<cluster_AUlen; i++)
- win_file->l2_img->abm[(i+first_best_block_baseAU) >> 3] |= 1 << ((i+first_best_block_baseAU) & 7);
-
- nb_alloc_physrecs = 0;
- }
- else if (second_best_block_seclen != 0)
- { /* jeez, we need to fragment it. We use the largest smaller block to limit fragmentation. */
- fphysrecs += second_best_block_seclen;
- cluster_AUlen = (second_best_block_seclen + win_file->l2_img->AUformat.physrecsperAU - 1) / win_file->l2_img->AUformat.physrecsperAU;
- win_file->fphysrecs = fphysrecs;
- /* TODO: update eldest FDR fphysrecs field */
- /*set_win_fdr_fphysrecs(& win_file->rootfdr.fphysrecs, fphysrecs);*/
- set_UINT16BE(&win_file->curfdr.sibFDR_AUlen,
- get_UINT16BE(win_file->curfdr.sibFDR_AUlen)+cluster_AUlen);
- set_UINT16BE(&win_file->curfdr.clusters[cluster_index][0], second_best_block_baseAU);
- set_UINT16BE(&win_file->curfdr.clusters[cluster_index][1],
- second_best_block_baseAU+cluster_AUlen-1);
-
- for (i=0; i<cluster_AUlen; i++)
- win_file->l2_img->abm[(i+second_best_block_baseAU) >> 3] |= 1 << ((i+second_best_block_baseAU) & 7);
-
- nb_alloc_physrecs -= second_best_block_seclen;
-
- /* now point to first free entry in cluster table */
- cluster_index++;
- }
- else if (search_start != 0)
- { /* we did not find any free physrec in the data section of the disk */
- search_start = 0; /* time to fall back to fdr space */
- }
- else
- return IMGTOOLERR_NOSPACE; /* This should never happen, as we pre-check that there is enough free space */
- }
-
- return 0;
-}
-
-/*
- Allocate a new (empty) file
-*/
-static int new_file_lvl2_dsk(struct ti99_lvl2_imgref *l2_img, int parent_ref, char filename[10], struct ti99_lvl2_fileref *l2_file)
-{
- ti99_catalog *catalog = &l2_img->dsk.catalogs[parent_ref];
- unsigned fdr_AU, fdr_aphysrec;
- int catalog_index, i;
- int reply = 0;
- int errorcode;
-
-
- if (catalog->num_files >= 127)
- /* if num_files == 128, catalog is full */
- /* if num_files == 127, catalog is not full, but we don't want to write
- a 128th entry for compatibility with some existing DSRs that detect the
- end of the FDIR array with a 0 entry (and do not check that the index
- has not reached 128) */
- return IMGTOOLERR_NOSPACE;
-
- /* find insertion point in catalog */
- for (i=0; (i < catalog->num_files) && ((reply = memcmp(catalog->files[i].name, filename, 10)) < 0); i++)
- ;
-
- if ((i<catalog->num_files) && (reply == 0))
- /* file already exists */
- return IMGTOOLERR_BADFILENAME;
- else
- {
- /* otherwise insert new entry */
- catalog_index = i;
- errorcode = alloc_fdr_AU(l2_img, &fdr_AU);
- if (errorcode)
- return errorcode;
- fdr_aphysrec = fdr_AU * l2_img->AUformat.physrecsperAU;
-
- /* shift catalog entries until the insertion point */
- for (i=catalog->num_files; i>catalog_index; i--)
- catalog->files[i] = catalog->files[i-1];
-
- /* write new catalog entry */
- catalog->files[catalog_index].fdr_ptr = fdr_aphysrec;
- memcpy(catalog->files[catalog_index].name, filename, 10);
-
- /* update catalog len */
- catalog->num_files++;
- }
-
- /* set up file handle */
- l2_file->type = L2F_DSK;
- l2_file->dsk.l2_img = l2_img;
- l2_file->dsk.fdr_aphysrec = fdr_aphysrec;
- memset(&l2_file->dsk.fdr, 0, sizeof(l2_file->dsk.fdr));
- memcpy(l2_file->dsk.fdr.name, filename, 10);
-
- return 0;
-}
-
-/*
- Allocate a new (empty) file
-*/
-static int new_file_lvl2_win(struct ti99_lvl2_imgref *l2_img, ti99_catalog *parent_catalog, char filename[10], struct ti99_lvl2_fileref *l2_file)
-{
- unsigned fdr_AU;
- int catalog_index, i;
- int reply = 0;
- int errorcode;
-
-
- if (parent_catalog->num_files >= 127)
- /* if num_files == 127, catalog is full */
- return IMGTOOLERR_NOSPACE;
-
- /* find insertion point in catalog */
- for (i=0; (i < parent_catalog->num_files) && ((reply = memcmp(parent_catalog->files[i].name, filename, 10)) < 0); i++)
- ;
-
- if ((i<parent_catalog->num_files) && (reply == 0))
- /* file already exists */
- return IMGTOOLERR_BADFILENAME;
- else
- {
- /* otherwise insert new entry */
- catalog_index = i;
- errorcode = alloc_fdr_AU(l2_img, &fdr_AU);
- if (errorcode)
- return errorcode;
-
- /* shift catalog entries until the insertion point */
- for (i=parent_catalog->num_files; i>catalog_index; i--)
- parent_catalog->files[i] = parent_catalog->files[i-1];
-
- /* write new catalog entry */
- parent_catalog->files[catalog_index].fdr_ptr = fdr_AU;
- memcpy(parent_catalog->files[catalog_index].name, filename, 10);
-
- /* update catalog len */
- parent_catalog->num_files++;
- }
-
- /* set up file handle */
- l2_file->type = L2F_WIN;
- l2_file->win.l2_img = l2_img;
- l2_file->win.fphysrecs = 0;
- l2_file->win.eldestfdr_aphysrec = fdr_AU * l2_img->AUformat.physrecsperAU;
- l2_file->win.curfdr_aphysrec = l2_file->win.eldestfdr_aphysrec;
- memset(&l2_file->win.curfdr, 0, sizeof(l2_file->win.curfdr));
- memcpy(l2_file->win.curfdr.name, filename, 10);
-
- return 0;
-}
-
-/*
- Allocate a new (empty) file
-*/
-static int new_file_lvl2_tifiles(imgtool_stream *file_handle, struct ti99_lvl2_fileref *l2_file)
-{
- /* set up file handle */
- l2_file->type = L2F_TIFILES;
- l2_file->tifiles.file_handle = file_handle;
- memset(&l2_file->tifiles.hdr, 0, sizeof(l2_file->tifiles.hdr));
- l2_file->tifiles.hdr.tifiles[0] = '\7';
- l2_file->tifiles.hdr.tifiles[1] = 'T';
- l2_file->tifiles.hdr.tifiles[2] = 'I';
- l2_file->tifiles.hdr.tifiles[3] = 'F';
- l2_file->tifiles.hdr.tifiles[4] = 'I';
- l2_file->tifiles.hdr.tifiles[5] = 'L';
- l2_file->tifiles.hdr.tifiles[6] = 'E';
- l2_file->tifiles.hdr.tifiles[7] = 'S';
-
- return 0;
-}
-
-/*
- Open an existing file on a floppy image
-
- l2_img: level 2 image the file is located on
- fpath: access path to the file
- file: set up if open is successful
-*/
-static int open_file_lvl2_dsk(struct ti99_lvl2_imgref *l2_img, const char *fpath, struct ti99_lvl2_fileref *l2_file)
-{
- int parent_ref, is_dir, catalog_index;
- int reply;
-
-
- reply = dsk_find_catalog_entry(l2_img, fpath, NULL, &parent_ref, &is_dir, &catalog_index);
- if (reply)
- return reply;
-
- if (is_dir)
- /* this is not a file */
- return IMGTOOLERR_BADFILENAME;
-
- l2_file->type = L2F_DSK;
- l2_file->dsk.l2_img = l2_img;
- l2_file->dsk.fdr_aphysrec = l2_img->dsk.catalogs[parent_ref].files[catalog_index].fdr_ptr;
- if (read_absolute_physrec(& l2_img->l1_img, l2_file->dsk.fdr_aphysrec, &l2_file->dsk.fdr))
- return IMGTOOLERR_READERROR;
-
- return 0;
-}
-
-/*
- Open an existing file on a harddisk image
-
- l2_img: level 2 image the file is located on
- fpath: access path to the file
- file: set up if open is successful
-*/
-static int open_file_lvl2_win(struct ti99_lvl2_imgref *l2_img, const char *fpath, struct ti99_lvl2_fileref *l2_file)
-{
- int parent_ref, is_dir, catalog_index;
- ti99_catalog catalog;
- int reply;
-
- reply = win_find_catalog_entry(l2_img, fpath, NULL, &parent_ref, &catalog, &is_dir, &catalog_index);
- if (reply)
- return reply;
-
- if (is_dir)
- /* this is not a file */
- return IMGTOOLERR_BADFILENAME;
-
- l2_file->type = L2F_WIN;
- l2_file->win.l2_img = l2_img;
- l2_file->win.eldestfdr_aphysrec = catalog.files[catalog_index].fdr_ptr * l2_img->AUformat.physrecsperAU;
- l2_file->win.curfdr_aphysrec = l2_file->win.eldestfdr_aphysrec;
- if (read_absolute_physrec(& l2_img->l1_img, l2_file->win.curfdr_aphysrec, &l2_file->win.curfdr))
- return IMGTOOLERR_READERROR;
- l2_file->win.fphysrecs = get_win_fdr_fphysrecs(&l2_file->win.curfdr);
-
- /* check integrity of FDR sibling chain */
- /* note that as we check that the back chain is consistent with the forward
- chain, we will also detect any cycle in the sibling chain, so we do not
- need to check against them explicitely */
- if (get_UINT16BE(l2_file->win.curfdr.prevsibFDR_AU) != 0)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- {
- int i, pastendoflist_flag;
- unsigned cur_fphysrec, sibFDR_AUlen;
- win_fdr *cur_fdr, fdr_buf;
- unsigned curfdr_aphysrec, prevfdr_aphysrec;
-
- cur_fphysrec = 0;
- pastendoflist_flag = 0;
- cur_fdr = &l2_file->win.curfdr;
- curfdr_aphysrec = l2_file->win.eldestfdr_aphysrec;
-
- while (1)
- {
- sibFDR_AUlen = 0;
- i=0;
- if (! pastendoflist_flag)
- {
- /* compute number of allocated AUs and check number of AUs */
- for (; i<54; i++)
- {
- if (get_UINT16BE(cur_fdr->clusters[i][0]) == 0)
- {
- pastendoflist_flag = TRUE;
- break;
- }
- sibFDR_AUlen += get_UINT16BE(cur_fdr->clusters[i][1])
- - get_UINT16BE(cur_fdr->clusters[i][0])
- + 1;
- }
- }
- /* clear remainder of cluster table */
- for (; i<54; i++)
- {
-#if 0
- set_UINT16BE(&cur_fdr->clusters[i][0], 0);
- set_UINT16BE(&cur_fdr->clusters[i][1], 0);
-#endif
- if ((get_UINT16BE(cur_fdr->clusters[i][0]) != 0) || (get_UINT16BE(cur_fdr->clusters[i][1]) != 0))
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- /* check sibFDR_AUlen field */
- if (get_UINT16BE(cur_fdr->sibFDR_AUlen) != sibFDR_AUlen)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* update current file physrec position to point to end of sibling FDR */
- cur_fphysrec += sibFDR_AUlen * l2_file->win.l2_img->AUformat.physrecsperAU;
-
- /* exit loop if end of sibling chain */
- if (! get_UINT16BE(cur_fdr->nextsibFDR_AU))
- break;
-
- /* otherwise read next FDR */
- if (get_UINT16BE(cur_fdr->nextsibFDR_AU) >= l2_file->win.l2_img->AUformat.totAUs)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- prevfdr_aphysrec = curfdr_aphysrec;
- curfdr_aphysrec = get_win_fdr_nextsibFDR_aphysrec(l2_file->win.l2_img, cur_fdr);
- if (read_absolute_physrec(& l2_file->win.l2_img->l1_img, curfdr_aphysrec, &fdr_buf))
- return IMGTOOLERR_READERROR;
- cur_fdr = &fdr_buf;
-
- /* check that back chaining is consistent with forward chaining */
- if (get_win_fdr_prevsibFDR_aphysrec(l2_file->win.l2_img, &fdr_buf) != prevfdr_aphysrec)
- return IMGTOOLERR_CORRUPTIMAGE;
- /* check fphysrecs field */
- if (get_win_fdr_fphysrecs(&fdr_buf) != cur_fphysrec)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* check consistency of informative fields (name, record format, flags, etc) */
- if (memcmp(fdr_buf.name, l2_file->win.curfdr.name, 10)
- || (get_UINT16BE(fdr_buf.xreclen) != get_UINT16BE(l2_file->win.curfdr.xreclen))
- || (fdr_buf.flags != l2_file->win.curfdr.flags)
- || (fdr_buf.recsperphysrec != l2_file->win.curfdr.recsperphysrec)
- || (fdr_buf.eof != l2_file->win.curfdr.eof)
- || (fdr_buf.reclen != l2_file->win.curfdr.reclen)
- || (get_UINT16LE(fdr_buf.fixrecs_LSW) != get_UINT16LE(l2_file->win.curfdr.fixrecs_LSW))
- || memcmp(&fdr_buf.creation, &l2_file->win.curfdr.creation, 4)
- || memcmp(&fdr_buf.update, &l2_file->win.curfdr.update, 4)
- /*|| memcmp(fdr_buf.id, l2_file->win.curfdr.id, 2)*/
- || (get_UINT16BE(fdr_buf.parent_FDIR_AU) != get_UINT16BE(l2_file->win.curfdr.parent_FDIR_AU))
- || ((fdr_buf.xinfo_MSB & 0xf) != (l2_file->win.curfdr.xinfo_MSB & 0xf)))
- return IMGTOOLERR_CORRUPTIMAGE;
- }
- if (cur_fphysrec < l2_file->win.fphysrecs)
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- return 0;
-}
-
-/*
- Open an existing file in TIFILES format
-*/
-static int open_file_lvl2_tifiles(imgtool_stream *file_handle, struct ti99_lvl2_fileref *l2_file)
-{
- /* set up file handle */
- l2_file->type = L2F_TIFILES;
- l2_file->tifiles.file_handle = file_handle;
-
- /* seek to header */
- if (stream_seek(l2_file->tifiles.file_handle, 0, SEEK_SET))
- return IMGTOOLERR_READERROR;
- /* read it */
- if (stream_read(l2_file->tifiles.file_handle, &l2_file->tifiles.hdr, sizeof(l2_file->tifiles.hdr)) != sizeof(l2_file->tifiles.hdr))
- return IMGTOOLERR_READERROR;
-
- return 0;
-}
-
-/*
- compute the aphysrec address for a given file physical record (fphysrec)
-
- l2_img: image where the file is located
-*/
-static int dsk_fphysrec_to_aphysrec(ti99_lvl2_fileref_dsk *dsk_file, unsigned fphysrec, unsigned *aphysrec)
-{
- int cluster_index;
- int cluster_firstfphysrec, cluster_lastfphysrec;
- int cluster_baseaphysrec;
-
-
- /* check parameter */
- if (fphysrec >= get_UINT16BE(dsk_file->fdr.fphysrecs))
- return IMGTOOLERR_UNEXPECTED;
-
-
- /* search for the cluster in the data chain pointers array */
- cluster_firstfphysrec = 0;
- for (cluster_index=0; cluster_index<76; cluster_index++)
- {
- /* read curent file block table entry */
- cluster_lastfphysrec = get_dsk_fdr_cluster_lastfphysrec(&dsk_file->fdr, cluster_index);
- if (cluster_lastfphysrec >= fphysrec)
- break;
- cluster_firstfphysrec = cluster_lastfphysrec+1;
- }
- if (cluster_index == 76)
- /* if not found, the file is corrupt */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* read base aphysrec address for this cluster */
- cluster_baseaphysrec = get_dsk_fdr_cluster_baseaphysrec(dsk_file->l2_img, &dsk_file->fdr, cluster_index);
- /* return absolute physrec address */
- *aphysrec = cluster_baseaphysrec + (fphysrec - cluster_firstfphysrec);
- return 0;
-}
-
-/*
- compute the aphysrec address for a given file physical record (fphysrec)
-
- l2_img: image where the file is located
-*/
-static int win_fphysrec_to_aphysrec(ti99_lvl2_fileref_win *win_file, unsigned fphysrec, unsigned *aphysrec)
-{
- int cluster_index;
- int cluster_firstfphysrec, cluster_lastfphysrec;
- int cluster_baseaphysrec;
- int errorcode;
-
-
- /* check parameter */
- if (fphysrec >= win_file->fphysrecs)
- return IMGTOOLERR_UNEXPECTED;
-
- /* look for correct sibling */
- if (fphysrec < get_win_fdr_cursibFDR_basefphysrec(& win_file->curfdr))
- {
- while (fphysrec < get_win_fdr_cursibFDR_basefphysrec(& win_file->curfdr))
- {
- if (get_UINT16BE(win_file->curfdr.prevsibFDR_AU) == 0)
- return IMGTOOLERR_CORRUPTIMAGE;
- errorcode = win_goto_prev_sibFDR(win_file);
- if (errorcode)
- return errorcode;
- }
- }
- else /*if (fphysrec >= get_win_fdr_cursibFDR_basefphysrec(& dsk_file->curfdr))*/
- {
- while (fphysrec >= (get_win_fdr_cursibFDR_basefphysrec(& win_file->curfdr)
- + get_UINT16BE(win_file->curfdr.sibFDR_AUlen) * win_file->l2_img->AUformat.physrecsperAU))
- {
- if (get_UINT16BE(win_file->curfdr.nextsibFDR_AU) == 0)
- return IMGTOOLERR_CORRUPTIMAGE;
- errorcode = win_goto_next_sibFDR(win_file);
- if (errorcode)
- return errorcode;
- }
- }
-
-
- /* search for the cluster in the data chain pointers array */
- cluster_firstfphysrec = get_win_fdr_cursibFDR_basefphysrec(& win_file->curfdr);
- for (cluster_index = 0; cluster_index<54; cluster_index++)
- {
- cluster_lastfphysrec = cluster_firstfphysrec
- + (get_UINT16BE(win_file->curfdr.clusters[cluster_index][1])
- - get_UINT16BE(win_file->curfdr.clusters[cluster_index][0])
- + 1)
- * win_file->l2_img->AUformat.physrecsperAU;
- if (fphysrec < cluster_lastfphysrec)
- break;
-
- cluster_firstfphysrec = cluster_lastfphysrec;
- }
-
- if (cluster_index == 54)
- return IMGTOOLERR_CORRUPTIMAGE;
-
-
- /* read base aphysrec address for this cluster */
- cluster_baseaphysrec = get_UINT16BE(win_file->curfdr.clusters[cluster_index][0]) * win_file->l2_img->AUformat.physrecsperAU;
- /* return absolute physrec address */
- *aphysrec = cluster_baseaphysrec + (fphysrec - cluster_firstfphysrec);
- return 0;
-}
-
-/*
- read a 256-byte physical record from a file
-*/
-static int read_file_physrec(struct ti99_lvl2_fileref *l2_file, unsigned fphysrec, void *dest)
-{
- int errorcode;
- unsigned aphysrec;
-
- switch (l2_file->type)
- {
- case L2F_DSK:
- /* compute absolute physrec address */
- errorcode = dsk_fphysrec_to_aphysrec(&l2_file->dsk, fphysrec, &aphysrec);
- if (errorcode)
- return errorcode;
- /* read physrec */
- if (read_absolute_physrec(& l2_file->dsk.l2_img->l1_img, aphysrec, dest))
- return IMGTOOLERR_READERROR;
- break;
-
- case L2F_WIN:
- /* compute absolute physrec address */
- errorcode = win_fphysrec_to_aphysrec(&l2_file->win, fphysrec, &aphysrec);
- if (errorcode)
- return errorcode;
- /* read physrec */
- if (read_absolute_physrec(& l2_file->win.l2_img->l1_img, aphysrec, dest))
- return IMGTOOLERR_READERROR;
- break;
-
- case L2F_TIFILES:
- /* seek to physrec */
- if (stream_seek(l2_file->tifiles.file_handle, 128+256*fphysrec, SEEK_SET))
- return IMGTOOLERR_READERROR;
- /* read it */
- if (stream_read(l2_file->tifiles.file_handle, dest, 256) != 256)
- return IMGTOOLERR_READERROR;
- break;
- }
-
- return 0;
-}
-
-/*
- read a 256-byte physical record from a file
-*/
-static int write_file_physrec(struct ti99_lvl2_fileref *l2_file, unsigned fphysrec, const void *src)
-{
- int errorcode;
- unsigned aphysrec;
-
- switch (l2_file->type)
- {
- case L2F_DSK:
- /* compute absolute physrec address */
- errorcode = dsk_fphysrec_to_aphysrec(&l2_file->dsk, fphysrec, &aphysrec);
- if (errorcode)
- return errorcode;
- /* write physrec */
- if (write_absolute_physrec(& l2_file->dsk.l2_img->l1_img, aphysrec, src))
- return IMGTOOLERR_WRITEERROR;
- break;
-
- case L2F_WIN:
- /* compute absolute physrec address */
- errorcode = win_fphysrec_to_aphysrec(&l2_file->win, fphysrec, &aphysrec);
- if (errorcode)
- return errorcode;
- /* write physrec */
- if (write_absolute_physrec(& l2_file->win.l2_img->l1_img, aphysrec, src))
- return IMGTOOLERR_WRITEERROR;
- break;
-
- case L2F_TIFILES:
- /* seek to physrec */
- if (stream_seek(l2_file->tifiles.file_handle, 128+256*fphysrec, SEEK_SET))
- return IMGTOOLERR_WRITEERROR;
- /* write it */
- if (stream_write(l2_file->tifiles.file_handle, src, 256) != 256)
- return IMGTOOLERR_WRITEERROR;
- break;
- }
-
- return 0;
-}
-
-/*
- Write a field in every fdr record associated to a file
-*/
-#ifdef UNUSED_FUNCTION
-static int set_win_fdr_field(struct ti99_lvl2_fileref *l2_file, size_t offset, size_t size, void *data)
-{
- win_fdr fdr_buf;
- unsigned fdr_aphysrec;
- int errorcode = 0;
-
- for (fdr_aphysrec = l2_file->win.eldestfdr_aphysrec;
- fdr_aphysrec && ((errorcode = (read_absolute_physrec(&l2_file->win.l2_img->l1_img, fdr_aphysrec, &fdr_buf) ? IMGTOOLERR_READERROR : 0)) == 0);
- fdr_aphysrec = get_win_fdr_nextsibFDR_physrec(l2_file->win.l2_img, &fdr_buf))
- {
- memcpy(((UINT8 *) &fdr_buf) + offset, data, size);
- if (write_absolute_physrec(&l2_file->win.l2_img->l1_img, fdr_aphysrec, &fdr_buf))
- {
- errorcode = IMGTOOLERR_WRITEERROR;
- break;
- }
- }
-
- return errorcode;
-}
-#endif
-
-static UINT8 get_file_flags(struct ti99_lvl2_fileref *l2_file)
-{
- int reply = 0;
-
- switch (l2_file->type)
- {
- case L2F_DSK:
- reply = l2_file->dsk.fdr.flags;
- break;
-
- case L2F_WIN:
- reply = l2_file->win.curfdr.flags;
- break;
-
- case L2F_TIFILES:
- reply = l2_file->tifiles.hdr.flags;
- break;
- }
-
- return reply;
-}
-
-static void set_file_flags(struct ti99_lvl2_fileref *l2_file, UINT8 data)
-{
- switch (l2_file->type)
- {
- case L2F_DSK:
- l2_file->dsk.fdr.flags = data;
- break;
-
- case L2F_WIN:
- l2_file->win.curfdr.flags = data;
- break;
-
- case L2F_TIFILES:
- l2_file->tifiles.hdr.flags = data;
- break;
- }
-}
-
-static UINT8 get_file_recsperphysrec(struct ti99_lvl2_fileref *l2_file)
-{
- int reply = 0;
-
- switch (l2_file->type)
- {
- case L2F_DSK:
- reply = l2_file->dsk.fdr.recsperphysrec;
- break;
-
- case L2F_WIN:
- reply = l2_file->win.curfdr.recsperphysrec;
- break;
-
- case L2F_TIFILES:
- reply = l2_file->tifiles.hdr.recsperphysrec;
- break;
- }
-
- return reply;
-}
-
-static void set_file_recsperphysrec(struct ti99_lvl2_fileref *l2_file, UINT8 data)
-{
- switch (l2_file->type)
- {
- case L2F_DSK:
- l2_file->dsk.fdr.recsperphysrec = data;
- break;
-
- case L2F_WIN:
- l2_file->win.curfdr.recsperphysrec = data;
- break;
-
- case L2F_TIFILES:
- l2_file->tifiles.hdr.recsperphysrec = data;
- break;
- }
-}
-
-static unsigned get_file_fphysrecs(struct ti99_lvl2_fileref *l2_file)
-{
- int reply = 0;
-
- switch (l2_file->type)
- {
- case L2F_DSK:
- reply = get_UINT16BE(l2_file->dsk.fdr.fphysrecs);
- break;
-
- case L2F_WIN:
- reply = l2_file->win.fphysrecs;
- break;
-
- case L2F_TIFILES:
- reply = get_UINT16BE(l2_file->tifiles.hdr.fphysrecs);
- break;
- }
-
- return reply;
-}
-
-static int set_file_fphysrecs(struct ti99_lvl2_fileref *l2_file, unsigned data)
-{
- switch (l2_file->type)
- {
- case L2F_DSK:
- if (data >= 65536)
- return IMGTOOLERR_UNIMPLEMENTED;
- set_UINT16BE(&l2_file->dsk.fdr.fphysrecs, data);
- break;
-
- case L2F_WIN:
- l2_file->win.fphysrecs = data;
- break;
-
- case L2F_TIFILES:
- if (data >= 65536)
- return IMGTOOLERR_UNIMPLEMENTED;
- set_UINT16BE(&l2_file->tifiles.hdr.fphysrecs, data);
- break;
- }
-
- return 0;
-}
-
-static UINT8 get_file_eof(struct ti99_lvl2_fileref *l2_file)
-{
- int reply = 0;
-
- switch (l2_file->type)
- {
- case L2F_DSK:
- reply = l2_file->dsk.fdr.eof;
- break;
-
- case L2F_WIN:
- reply = l2_file->win.curfdr.eof;
- break;
-
- case L2F_TIFILES:
- reply = l2_file->tifiles.hdr.eof;
- break;
- }
-
- return reply;
-}
-
-static void set_file_eof(struct ti99_lvl2_fileref *l2_file, UINT8 data)
-{
- switch (l2_file->type)
- {
- case L2F_DSK:
- l2_file->dsk.fdr.eof = data;
- break;
-
- case L2F_WIN:
- l2_file->win.curfdr.eof = data;
- break;
-
- case L2F_TIFILES:
- l2_file->tifiles.hdr.eof = data;
- break;
- }
-}
-
-static UINT16 get_file_reclen(struct ti99_lvl2_fileref *l2_file)
-{
- int reply = 0;
-
- switch (l2_file->type)
- {
- case L2F_DSK:
- reply = l2_file->dsk.fdr.reclen;
- if ((reply == 0) && (! (l2_file->dsk.fdr.flags & (fdr99_f_program /*| fdr99_f_var*/))))
- reply = get_UINT16BE(l2_file->dsk.fdr.xreclen);
- break;
-
- case L2F_WIN:
- reply = l2_file->win.curfdr.reclen;
- if ((reply == 0) && (! (l2_file->win.curfdr.flags & (fdr99_f_program /*| fdr99_f_var*/))))
- reply = get_UINT16BE(l2_file->win.curfdr.xreclen);
- break;
-
- case L2F_TIFILES:
- reply = l2_file->tifiles.hdr.reclen;
- break;
- }
-
- return reply;
-}
-
-static int set_file_reclen(struct ti99_lvl2_fileref *l2_file, UINT16 data)
-{
- switch (l2_file->type)
- {
- case L2F_DSK:
- if (data < 256)
- {
- l2_file->dsk.fdr.reclen = data;
- set_UINT16BE(&l2_file->dsk.fdr.xreclen, 0);
- }
- else
- {
- l2_file->dsk.fdr.reclen = 0;
- set_UINT16BE(&l2_file->dsk.fdr.xreclen, data);
- }
- break;
-
- case L2F_WIN:
- if (data < 256)
- {
- l2_file->win.curfdr.reclen = data;
- set_UINT16BE(&l2_file->win.curfdr.xreclen, 0);
- }
- else
- {
- l2_file->win.curfdr.reclen = 0;
- set_UINT16BE(&l2_file->win.curfdr.xreclen, data);
- }
- break;
-
- case L2F_TIFILES:
- if (data >= 256)
- return IMGTOOLERR_UNIMPLEMENTED;
- l2_file->tifiles.hdr.reclen = data;
- break;
- }
-
- return 0;
-}
-
-static unsigned get_file_fixrecs(struct ti99_lvl2_fileref *l2_file)
-{
- int reply = 0;
-
- switch (l2_file->type)
- {
- case L2F_DSK:
- reply = get_UINT16LE(l2_file->dsk.fdr.fixrecs);
- break;
-
- case L2F_WIN:
- reply = get_win_fdr_fixrecs(&l2_file->win.curfdr);
- break;
-
- case L2F_TIFILES:
- reply = get_UINT16BE(l2_file->tifiles.hdr.fixrecs);
- break;
- }
-
- return reply;
-}
-
-static int set_file_fixrecs(struct ti99_lvl2_fileref *l2_file, unsigned data)
-{
- switch (l2_file->type)
- {
- case L2F_DSK:
- if (data >= 65536)
- return IMGTOOLERR_UNIMPLEMENTED;
- set_UINT16LE(&l2_file->dsk.fdr.fixrecs, data);
- break;
-
- case L2F_WIN:
- set_win_fdr_fixrecs(&l2_file->win.curfdr, data);
- break;
-
- case L2F_TIFILES:
- if (data >= 65536)
- return IMGTOOLERR_UNIMPLEMENTED;
- set_UINT16BE(&l2_file->tifiles.hdr.fixrecs, data);
- break;
- }
-
- return 0;
-}
-
-static void get_file_creation_date(struct ti99_lvl2_fileref *l2_file, ti99_date_time *reply)
-{
- switch (l2_file->type)
- {
- case L2F_DSK:
- *reply = l2_file->dsk.fdr.creation;
- break;
-
- case L2F_WIN:
- *reply = l2_file->win.curfdr.creation;
- break;
-
- case L2F_TIFILES:
- memset(reply, 0, sizeof(*reply));
- break;
- }
-}
-
-static void set_file_creation_date(struct ti99_lvl2_fileref *l2_file, ti99_date_time data)
-{
- switch (l2_file->type)
- {
- case L2F_DSK:
- l2_file->dsk.fdr.creation = data;
- break;
-
- case L2F_WIN:
- l2_file->win.curfdr.creation = data;
- break;
-
- case L2F_TIFILES:
- break;
- }
-}
-
-static void get_file_update_date(struct ti99_lvl2_fileref *l2_file, ti99_date_time *reply)
-{
- switch (l2_file->type)
- {
- case L2F_DSK:
- *reply = l2_file->dsk.fdr.update;
- break;
-
- case L2F_WIN:
- *reply = l2_file->win.curfdr.update;
- break;
-
- case L2F_TIFILES:
- memset(reply, 0, sizeof(*reply));
- break;
- }
-}
-
-static void set_file_update_date(struct ti99_lvl2_fileref *l2_file, ti99_date_time data)
-{
- switch (l2_file->type)
- {
- case L2F_DSK:
- l2_file->dsk.fdr.update = data;
- break;
-
- case L2F_WIN:
- l2_file->win.curfdr.update = data;
- break;
-
- case L2F_TIFILES:
- break;
- }
-}
-
-#ifdef UNUSED_FUNCTION
-static void current_date_time(ti99_date_time *reply)
-{
- /* All these functions should be ANSI */
- time_t cur_time = time(NULL);
- struct tm expanded_time = *localtime(& cur_time);
-
- reply->time_MSB = (expanded_time.tm_hour << 3) | (expanded_time.tm_min >> 3);
- reply->time_LSB = (expanded_time.tm_min << 5) | (expanded_time.tm_sec >> 1);
- reply->date_MSB = ((expanded_time.tm_year % 100) << 1) | ((expanded_time.tm_mon+1) >> 3);
- reply->date_LSB = ((expanded_time.tm_mon+1) << 5) | expanded_time.tm_mday;
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark LEVEL 3 DISK ROUTINES
-#endif
-
-/*
- Level 3 implements files as a succession of logical records.
-
- There are three types of files:
- * program files that are not implemented at level 3 (no logical record)
- * files with fixed-size records (random-access files)
- * files with variable-size records (sequential-access)
-*/
-
-struct ti99_lvl3_fileref
-{
- ti99_lvl2_fileref l2_file;
-
- int cur_log_rec;
- int cur_phys_rec;
- int cur_pos_in_phys_rec;
-};
-
-#ifdef UNUSED_FUNCTION
-/*
- Open a file on level 3.
-
- To open a file on level 3, you must open (or create) the file on level 2,
- then pass the file reference to open_file_lvl3.
-*/
-static int open_file_lvl3(ti99_lvl3_fileref *l3_file)
-{
- l3_file->cur_log_rec = 0;
- l3_file->cur_phys_rec = 0;
- l3_file->cur_pos_in_phys_rec = 0;
-
- /*if ()*/
-
- return 0;
-}
-
-/*
- Test a file for EOF
-*/
-static int is_eof(ti99_lvl3_fileref *l3_file)
-{
- int flags = get_file_flags(&l3_file->l2_file);
- int fphysrecs = get_file_fphysrecs(&l3_file->l2_file);
- int fdr_eof = get_file_eof(&l3_file->l2_file);
-
- if (flags & fdr99_f_var)
- {
- return (l3_file->cur_phys_rec >= fphysrecs);
- }
- else
- {
- return ((l3_file->cur_phys_rec >= fphysrecs)
- || ((l3_file->cur_phys_rec == (fphysrecs-1))
- && (l3_file->cur_pos_in_phys_rec >= (fdr_eof ? fdr_eof : 256))));
- }
-}
-
-/*
- Read next record from a file
-*/
-static int read_next_record(ti99_lvl3_fileref *l3_file, void *dest, int *out_reclen)
-{
- int errorcode;
- UINT8 physrec_buf[256];
- int reclen;
- int flags = get_file_flags(&l3_file->l2_file);
- int fphysrecs = get_file_fphysrecs(&l3_file->l2_file);
- int fdr_eof = get_file_eof(&l3_file->l2_file);
-
- if (flags & fdr99_f_program)
- {
- /* program files have no level-3 record */
- return IMGTOOLERR_UNEXPECTED;
- }
- else if (flags & fdr99_f_var)
- {
- /* variable-length records */
- if (is_eof(l3_file))
- return IMGTOOLERR_UNEXPECTED;
- errorcode = read_file_physrec(&l3_file->l2_file, l3_file->cur_phys_rec, physrec_buf);
- if (errorcode)
- return errorcode;
- /* read reclen */
- reclen = physrec_buf[l3_file->cur_pos_in_phys_rec];
- /* check integrity */
- if ((reclen == 0xff) || (reclen > get_file_reclen(&l3_file->l2_file))
- || ((l3_file->cur_pos_in_phys_rec + 1 + reclen) > 256))
- return IMGTOOLERR_CORRUPTIMAGE;
- /* copy to buffer */
- memcpy(dest, physrec_buf + l3_file->cur_pos_in_phys_rec + 1, reclen);
- l3_file->cur_pos_in_phys_rec += reclen + 1;
- /* skip to next physrec if needed */
- if ((l3_file->cur_pos_in_phys_rec == 256)
- || (physrec_buf[l3_file->cur_pos_in_phys_rec] == 0xff))
- {
- l3_file->cur_pos_in_phys_rec = 0;
- l3_file->cur_phys_rec++;
- }
- (* out_reclen) = reclen;
- }
- else
- {
- /* fixed len records */
- reclen = get_file_reclen(&l3_file->l2_file);
- if (is_eof(l3_file))
- return IMGTOOLERR_UNEXPECTED;
- if ((l3_file->cur_pos_in_phys_rec + reclen) > 256)
- {
- l3_file->cur_pos_in_phys_rec = 0;
- l3_file->cur_phys_rec++;
- }
- if ((l3_file->cur_phys_rec >= fphysrecs)
- || ((l3_file->cur_phys_rec == (fphysrecs-1))
- && ((l3_file->cur_pos_in_phys_rec + reclen) >= (fdr_eof ? fdr_eof : 256))))
- return IMGTOOLERR_CORRUPTIMAGE;
- errorcode = read_file_physrec(&l3_file->l2_file, l3_file->cur_phys_rec, physrec_buf);
- if (errorcode)
- return errorcode;
- memcpy(dest, physrec_buf + l3_file->cur_pos_in_phys_rec, reclen);
- l3_file->cur_pos_in_phys_rec += reclen;
- if (l3_file->cur_pos_in_phys_rec == 256)
- {
- l3_file->cur_pos_in_phys_rec = 0;
- l3_file->cur_phys_rec++;
- }
- (* out_reclen) = reclen;
- }
-
- return 0;
-}
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark IMGTOOL MODULE IMPLEMENTATION
-#endif
-
-/*
- ti99 catalog iterator, used when imgtool reads the catalog
-*/
-struct dsk_iterator
-{
- struct ti99_lvl2_imgref *image;
- int level;
- int listing_subdirs; /* true if we are listing subdirectories at current level */
- int index[2]; /* current index in the disk catalog */
- ti99_catalog *cur_catalog; /* current catalog */
-};
-
-struct win_iterator
-{
- struct ti99_lvl2_imgref *image;
- int level;
- int listing_subdirs; /* true if we are listing subdirectories at current level */
- int index[MAX_DIR_LEVEL]; /* current index in the disk catalog */
- ti99_catalog catalog[MAX_DIR_LEVEL]; /* current catalog */
-};
-
-
-static imgtoolerr_t dsk_image_init_mess(imgtool_image *image, imgtool_stream *f);
-static imgtoolerr_t dsk_image_init_v9t9(imgtool_image *image, imgtool_stream *f);
-static imgtoolerr_t dsk_image_init_pc99_fm(imgtool_image *image, imgtool_stream *f);
-static imgtoolerr_t dsk_image_init_pc99_mfm(imgtool_image *image, imgtool_stream *f);
-static imgtoolerr_t win_image_init(imgtool_image *image, imgtool_stream *f);
-static void ti99_image_exit(imgtool_image *img);
-static void ti99_image_info(imgtool_image *img, char *string, size_t len);
-static imgtoolerr_t dsk_image_beginenum(imgtool_directory *enumeration, const char *path);
-static imgtoolerr_t dsk_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent);
-static imgtoolerr_t win_image_beginenum(imgtool_directory *enumeration, const char *path);
-static imgtoolerr_t win_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent);
-static imgtoolerr_t ti99_image_freespace(imgtool_partition *partition, UINT64 *size);
-static imgtoolerr_t ti99_image_readfile(imgtool_partition *partition, const char *fpath, const char *fork, imgtool_stream *destf);
-static imgtoolerr_t ti99_image_writefile(imgtool_partition *partition, const char *fpath, const char *fork, imgtool_stream *sourcef, option_resolution *writeoptions);
-static imgtoolerr_t dsk_image_deletefile(imgtool_partition *partition, const char *fpath);
-static imgtoolerr_t win_image_deletefile(imgtool_partition *partition, const char *fpath);
-static imgtoolerr_t dsk_image_create_mess(imgtool_image *image, imgtool_stream *f, option_resolution *createoptions);
-static imgtoolerr_t dsk_image_create_v9t9(imgtool_image *image, imgtool_stream *f, option_resolution *createoptions);
-
-enum
-{
- dsk_createopts_volname = 'A',
- dsk_createopts_sides = 'B',
- dsk_createopts_tracks = 'C',
- dsk_createopts_sectors = 'D',
- dsk_createopts_protection = 'E',
- dsk_createopts_density = 'F'
-};
-
-static OPTION_GUIDE_START( dsk_create_optionguide )
- OPTION_STRING(dsk_createopts_volname, "label", "Volume name" )
- OPTION_INT(dsk_createopts_sides, "sides", "Sides" )
- OPTION_INT(dsk_createopts_tracks, "tracks", "Tracks" )
- OPTION_INT(dsk_createopts_sectors, "sectors", "Sectors (1->9 for SD, 1->18 for DD, 1->36 for HD)" )
- OPTION_INT(dsk_createopts_protection, "protection", "Protection (0 for normal, 1 for protected)" )
- OPTION_ENUM_START(dsk_createopts_density, "density", "Density" )
- OPTION_ENUM( 0, "Auto", "Auto" )
- OPTION_ENUM( 1, "SD", "Single Density" )
- OPTION_ENUM( 2, "DD", "Double Density" )
- OPTION_ENUM( 3, "HD", "High Density" )
- OPTION_ENUM_END
-OPTION_GUIDE_END
-
-#define dsk_create_optionspecs "B1-[2];C1-[40]-80;D1-[18]-36;E[0]-1;F[0]-3"
-
-static void ti99_getinfo(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(ti99_lvl2_imgref); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(dsk_iterator); break;
-
- case IMGTOOLINFO_STR_EOLN: strcpy(info->s = imgtool_temp_str(), "\r"); break;
- case IMGTOOLINFO_PTR_CLOSE: info->close = ti99_image_exit; break;
- case IMGTOOLINFO_PTR_INFO: info->info = ti99_image_info; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = ti99_image_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = ti99_image_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = ti99_image_writefile; break;
- }
-}
-
-static void ti99_dsk_getinfo(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "dsk"); break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = dsk_image_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = dsk_image_nextenum; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = dsk_image_deletefile; break;
- default: ti99_getinfo(imgclass, state, info);
- }
-}
-
-void ti99_old_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "ti99_old"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "TI99 Diskette (old MESS format)"); break;
- case IMGTOOLINFO_PTR_OPEN: info->open = dsk_image_init_mess; break;
- case IMGTOOLINFO_PTR_CREATE: info->create = dsk_image_create_mess; break;
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = dsk_create_optionguide; break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), dsk_create_optionspecs); break;
- default: ti99_dsk_getinfo(imgclass, state, info); break;
- }
-}
-
-void ti99_v9t9_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "v9t9"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "TI99 Diskette (V9T9 format)"); break;
- case IMGTOOLINFO_PTR_OPEN: info->open = dsk_image_init_v9t9; break;
- case IMGTOOLINFO_PTR_CREATE: info->create = dsk_image_create_v9t9; break;
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = dsk_create_optionguide; break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), dsk_create_optionspecs); break;
- default: ti99_dsk_getinfo(imgclass, state, info); break;
- }
-}
-
-void ti99_pc99fm_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "pc99fm"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "TI99 Diskette (PC99 FM format)"); break;
- case IMGTOOLINFO_PTR_OPEN: info->open = dsk_image_init_pc99_fm; break;
- case IMGTOOLINFO_PTR_CREATE: /* info->create = dsk_image_create_pc99fm; */ break;
- default: ti99_dsk_getinfo(imgclass, state, info); break;
- }
-}
-
-void ti99_pc99mfm_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "pc99mfm"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "TI99 Diskette (PC99 MFM format)"); break;
- case IMGTOOLINFO_PTR_OPEN: info->open = dsk_image_init_pc99_mfm; break;
- case IMGTOOLINFO_PTR_CREATE: /* info->create = dsk_image_create_pc99mfm; */ break;
- default: ti99_dsk_getinfo(imgclass, state, info); break;
- }
-}
-
-void ti99_ti99hd_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "ti99hd"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "TI99 Harddisk"); break;
- case IMGTOOLINFO_PTR_OPEN: info->open = win_image_init; break;
- case IMGTOOLINFO_PTR_CREATE: /* info->create = hd_image_create; */ break;
-
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "hd"); break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = win_image_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = win_image_nextenum; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = win_image_deletefile; break;
- default: ti99_getinfo(imgclass, state, info);
- }
-}
-
-
-
-/*
- Open a file as a ti99_image (common code).
-*/
-static int dsk_image_init(imgtool_image *img, imgtool_stream *f, ti99_img_format img_format)
-{
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(img);
- dsk_vib vib;
- int reply;
- int totphysrecs;
- unsigned fdir_aphysrec;
- int i;
-
- /* open disk image at level 1 */
- reply = open_image_lvl1(f, img_format, &image->l1_img, &vib);
- if (reply)
- return reply;
-
- /* open disk image at level 2 */
- image->type = L2I_DSK;
-
- /* @BN@ */
- /* Copy in the allocation bit map! */
- memcpy(image->abm, vib.abm, 200);
- /* first compute AU size and number of AUs */
- totphysrecs = get_UINT16BE(vib.totphysrecs);
-
- image->AUformat.physrecsperAU = (totphysrecs + 1599) / 1600;
- /* round to next larger power of 2 */
- for (i = 1; i < image->AUformat.physrecsperAU; i <<= 1)
- ;
- image->AUformat.physrecsperAU = i;
- image->AUformat.totAUs = totphysrecs / image->AUformat.physrecsperAU;
-
- /* extract number of physrecs */
- image->dsk.totphysrecs = get_UINT16BE(vib.totphysrecs);
-
- /* read and check main volume catalog */
- reply = dsk_read_catalog(image, 1, &image->dsk.catalogs[0]);
- if (reply)
- return reply;
-
- image->dsk.fdir_aphysrec[0] = 1;
-
- /* read and check subdirectory catalogs */
- /* Note that the reserved areas used for HFDC subdirs may be used for other
- purposes by other FDRs, so, if we get any error, we will assume there is no
- subdir after all... */
- image->dsk.catalogs[0].num_subdirs = 0;
- for (i=0; i<3; i++)
- {
- fdir_aphysrec = get_UINT16BE(vib.subdir[i].fdir_aphysrec);
- if ((! memcmp(vib.subdir[i].name, "\0\0\0\0\0\0\0\0\0\0", 10))
- || (! memcmp(vib.subdir[i].name, " ", 10)))
- {
- /* name is empty: fine with us unless there is a fdir pointer */
- if (fdir_aphysrec != 0)
- {
- image->dsk.catalogs[0].num_subdirs = 0;
- break;
- }
- }
- else if (check_fname(vib.subdir[i].name))
- {
- /* name is invalid: this is not an HFDC format floppy */
- image->dsk.catalogs[0].num_subdirs = 0;
- break;
- }
- else
- {
- /* there is a non-empty name */
- if ((fdir_aphysrec == 0) || (fdir_aphysrec >= totphysrecs))
- {
- /* error: fdir pointer is invalid or NULL */
- image->dsk.catalogs[0].num_subdirs = 0;
- break;
- }
- /* fill in descriptor fields */
- image->dsk.fdir_aphysrec[image->dsk.catalogs[0].num_subdirs+1] = fdir_aphysrec;
- /*image->dsk.catalogs[0].subdirs[image->dsk.catalogs[0].num_subdirs].dir_ptr = fdir_aphysrec;*/
- memcpy(image->dsk.catalogs[0].subdirs[image->dsk.catalogs[0].num_subdirs].name, vib.subdir[i].name, 10);
- reply = dsk_read_catalog(image, fdir_aphysrec, &image->dsk.catalogs[image->dsk.catalogs[0].num_subdirs+1]);
- if (reply)
- {
- /* error: invalid fdir */
- image->dsk.catalogs[0].num_subdirs = 0;
- break;
- }
- /* found valid subdirectory: increment subdir count */
- image->dsk.catalogs[0].num_subdirs++;
- }
- }
-
- /* extract volume name */
- memcpy(image->vol_name, vib.name, 10);
-
- /* initialize default data_offset */
- image->data_offset = 32+2;
-
- return 0;
-}
-
-/*
- Open a file as a ti99_image (MESS format).
-*/
-static imgtoolerr_t dsk_image_init_mess(imgtool_image *image, imgtool_stream *f)
-{
- return (imgtoolerr_t)dsk_image_init(image, f, if_mess);
-}
-
-/*
- Open a file as a ti99_image (V9T9 format).
-*/
-static imgtoolerr_t dsk_image_init_v9t9(imgtool_image *image, imgtool_stream *f)
-{
- return (imgtoolerr_t)dsk_image_init(image, f, if_v9t9);
-}
-
-/*
- Open a file as a ti99_image (PC99 FM format).
-*/
-static imgtoolerr_t dsk_image_init_pc99_fm(imgtool_image *image, imgtool_stream *f)
-{
- return (imgtoolerr_t)dsk_image_init(image, f, if_pc99_fm);
-}
-
-/*
- Open a file as a ti99_image (PC99 MFM format).
-*/
-static imgtoolerr_t dsk_image_init_pc99_mfm(imgtool_image *image, imgtool_stream *f)
-{
- return (imgtoolerr_t)dsk_image_init(image, f, if_pc99_mfm);
-}
-
-/*
- Open a file as a ti99_image (harddisk format).
-*/
-static imgtoolerr_t win_image_init(imgtool_image *img, imgtool_stream *f)
-{
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(img);
- win_vib_ddr vib;
- int reply;
- int i;
-
- /* open disk image at level 1 */
- reply = open_image_lvl1(f, if_harddisk, & image->l1_img, NULL);
- if (reply)
- return (imgtoolerr_t)reply;
-
- /* open disk image at level 2 */
- image->type = L2I_WIN;
-
- /* read VIB */
- reply = read_absolute_physrec(&image->l1_img, 0, &vib);
- if (reply)
- return (imgtoolerr_t)reply;
-
- /* guess VIB version */
- image->win.vib_version = memcmp(vib.u.vib_v1.id, "WIN", 3) ? win_vib_v2 : win_vib_v1;
-
- /* extract AU size and number of AUs */
- image->AUformat.physrecsperAU = ((get_UINT16BE(vib.params) >> 12) & 0xf) + 1;
- image->AUformat.totAUs = get_UINT16BE(vib.totAUs);
-
- /* extract volume name */
- memcpy(image->vol_name, vib.name, 10);
-
- /* extract data_offset */
- switch (image->win.vib_version)
- {
- case win_vib_v1:
- image->data_offset = 64;
- break;
-
- case win_vib_v2:
- image->data_offset = vib.u.vib_v2.res_AUs * 64;
- break;
- }
-
- /* read allocation bitmap (aphysrecs 1 through n, n<=33) */
- for (i=0; i < (image->AUformat.totAUs+2047)/2048; i++)
- {
- reply = read_absolute_physrec(&image->l1_img, i+1, image->abm+i*256);
- if (reply)
- return (imgtoolerr_t)reply;
- }
-
- return (imgtoolerr_t)0;
-}
-
-/*
- close a ti99_image
-*/
-static void ti99_image_exit(imgtool_image *img)
-{
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(img);
-
- close_image_lvl1(&image->l1_img);
-}
-
-/*
- get basic information on a ti99_image
-
- Currently returns the volume name
-*/
-static void ti99_image_info(imgtool_image *img, char *string, size_t len)
-{
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(img);
- char vol_name[11];
-
- fname_to_str(vol_name, image->vol_name, 11);
-
- snprintf(string, len, "%s", vol_name);
-}
-
-/*
- Open the disk catalog for enumeration
-*/
-static imgtoolerr_t dsk_image_beginenum(imgtool_directory *enumeration, const char *path)
-{
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(imgtool_directory_image(enumeration));
- dsk_iterator *iter = (dsk_iterator *) imgtool_directory_extrabytes(enumeration);
-
- iter->image = image;
- iter->level = 0;
- iter->listing_subdirs = 1;
- iter->index[0] = 0;
- iter->cur_catalog = &iter->image->dsk.catalogs[0];
-
- return (imgtoolerr_t)0;
-}
-
-/*
- Enumerate disk catalog next entry
-*/
-static imgtoolerr_t dsk_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- dsk_iterator *iter = (dsk_iterator*) imgtool_directory_extrabytes(enumeration);
- dsk_fdr fdr;
- int reply;
- unsigned fdr_aphysrec;
-
-
- ent->corrupt = 0;
- ent->eof = 0;
-
- /* iterate through catalogs to next file or dir entry */
- while ((iter->level >= 0)
- && (iter->index[iter->level] >= (iter->listing_subdirs
- ? iter->cur_catalog->num_subdirs
- : iter->cur_catalog->num_files)))
- {
- if (iter->listing_subdirs)
- {
- iter->listing_subdirs = 0;
- iter->index[iter->level] = 0;
- }
- else
- {
- iter->listing_subdirs = 1;
- if (! iter->level)
- iter->level = -1;
- else
- {
- iter->level = 0;
- iter->index[0]++;
- iter->cur_catalog = &iter->image->dsk.catalogs[0];
- }
- }
- }
-
- if (iter->level < 0)
- {
- ent->eof = 1;
- }
- else
- {
- if (iter->listing_subdirs)
- {
- fname_to_str(ent->filename, iter->image->dsk.catalogs[0].subdirs[iter->index[iter->level]].name, ARRAY_LENGTH(ent->filename));
-
- /* set type of DIR */
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "DIR");
-
- /* len in physrecs */
- /* @BN@ return length in bytes */
- /* ent->filesize = 1; */
- ent->filesize = 256;
-
- /* recurse subdirectory */
- iter->listing_subdirs = 0; /* no need to list subdirs as only the
- root dir has subdirs in DSK format */
- iter->level = 1;
- iter->cur_catalog = &iter->image->dsk.catalogs[iter->index[0]+1];
- iter->index[iter->level] = 0;
- }
- else
- {
- fdr_aphysrec = iter->cur_catalog->files[iter->index[iter->level]].fdr_ptr;
- reply = read_absolute_physrec(& iter->image->l1_img, fdr_aphysrec, & fdr);
- if (reply)
- return IMGTOOLERR_READERROR;
-#if 0
- fname_to_str(ent->filename, fdr.name, ARRAY_LENGTH(ent->filename));
-#else
- {
- char buf[11];
-
- ent->filename[0] = '\0';
- if (iter->level)
- {
- fname_to_str(ent->filename, iter->image->dsk.catalogs[0].subdirs[iter->index[0]].name, ARRAY_LENGTH(ent->filename));
- strncat(ent->filename, ".", ARRAY_LENGTH(ent->filename) - 1);
- }
- fname_to_str(buf, fdr.name, 11);
- strncat(ent->filename, buf, ARRAY_LENGTH(ent->filename) - 1);
- }
-#endif
- /* parse flags */
- if (fdr.flags & fdr99_f_program)
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "PGM%s",
- (fdr.flags & fdr99_f_wp) ? " R/O" : "");
- else
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "%c/%c %d%s",
- (fdr.flags & fdr99_f_int) ? 'I' : 'D',
- (fdr.flags & fdr99_f_var) ? 'V' : 'F',
- fdr.reclen,
- (fdr.flags & fdr99_f_wp) ? " R/O" : "");
- /* len in physrecs */
- /* @BN@ return length in bytes */
- /* ent->filesize = get_UINT16BE(fdr.fphysrecs); */
- ent->filesize = (get_UINT16BE(fdr.fphysrecs)+1)*256;
-
- iter->index[iter->level]++;
- }
- }
-
- return (imgtoolerr_t)0;
-}
-
-/*
- Open the disk catalog for enumeration
-*/
-static imgtoolerr_t win_image_beginenum(imgtool_directory *enumeration, const char *path)
-{
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(imgtool_directory_image(enumeration));
- win_iterator *iter = (win_iterator *) imgtool_directory_extrabytes(enumeration);
- imgtoolerr_t errorcode;
-
- iter->image = image;
- iter->level = 0;
- iter->listing_subdirs = 1;
- iter->index[0] = 0;
- errorcode = (imgtoolerr_t)win_read_catalog(image, 0, &iter->catalog[0]);
- if (errorcode)
- return errorcode;
-
- return (imgtoolerr_t)0;
-}
-
-/*
- Enumerate disk catalog next entry
-*/
-static imgtoolerr_t win_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- win_iterator *iter = (win_iterator *) imgtool_directory_extrabytes(enumeration);
- unsigned fdr_aphysrec;
- win_fdr fdr;
- int reply;
- int i;
-
-
- ent->corrupt = 0;
- ent->eof = 0;
-
- /* iterate through catalogs to next file or dir entry */
- while ((iter->level >= 0)
- && (iter->index[iter->level] >= (iter->listing_subdirs
- ? iter->catalog[iter->level].num_subdirs
- : iter->catalog[iter->level].num_files)))
- {
- if (iter->listing_subdirs)
- {
- iter->listing_subdirs = 0;
- iter->index[iter->level] = 0;
- }
- else
- {
- iter->listing_subdirs = 1;
- iter->level--;
- iter->index[iter->level]++;
- }
- }
-
- if (iter->level < 0)
- {
- ent->eof = 1;
- }
- else
- {
- if (iter->listing_subdirs)
- {
-#if 0
- fname_to_str(ent->filename, iter->catalog[iter->level].subdirs[iter->index[iter->level]].name, ARRAY_LENGTH(ent->filename));
-#else
- {
- char buf[11];
-
- ent->filename[0] = '\0';
- for (i=0; i<iter->level; i++)
- {
- fname_to_str(buf, iter->catalog[i].subdirs[iter->index[i]].name, 11);
- strncat(ent->filename, buf, ARRAY_LENGTH(ent->filename) - 1);
- strncat(ent->filename, ".", ARRAY_LENGTH(ent->filename) - 1);
- }
- fname_to_str(buf, iter->catalog[iter->level].subdirs[iter->index[iter->level]].name, 11);
- strncat(ent->filename, buf, ARRAY_LENGTH(ent->filename) - 1);
- }
-#endif
-
- /* set type of DIR */
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "DIR");
-
- /* len in physrecs */
- /* @BN@ return length in bytes */
- /* ent->filesize = 2; */
- ent->filesize = 512;
-
- /* recurse subdirectory */
- /*iter->listing_subdirs = 1;*/
- iter->level++;
- iter->index[iter->level] = 0;
- reply = win_read_catalog(iter->image, iter->catalog[iter->level-1].subdirs[iter->index[iter->level-1]].dir_ptr, &iter->catalog[iter->level]);
- if (reply)
- {
- ent->corrupt = 1;
- return (imgtoolerr_t)reply;
- }
- }
- else
- {
- fdr_aphysrec = iter->catalog[iter->level].files[iter->index[iter->level]].fdr_ptr*iter->image->AUformat.physrecsperAU;
- reply = read_absolute_physrec(& iter->image->l1_img, fdr_aphysrec, & fdr);
- if (reply)
- return IMGTOOLERR_READERROR;
-#if 0
- fname_to_str(ent->filename, iter->catalog[iter->level].files[iter->index[iter->level]].name, ARRAY_LENGTH(ent->filename));
-#else
- {
- char buf[11];
-
- ent->filename[0] = '\0';
- for (i=0; i<iter->level; i++)
- {
- fname_to_str(buf, iter->catalog[i].subdirs[iter->index[i]].name, 11);
- strncat(ent->filename, buf, ARRAY_LENGTH(ent->filename) - 1);
- strncat(ent->filename, ".", ARRAY_LENGTH(ent->filename) - 1);
- }
- fname_to_str(buf, iter->catalog[iter->level].files[iter->index[iter->level]].name, 11);
- strncat(ent->filename, buf, ARRAY_LENGTH(ent->filename) - 1);
- }
-#endif
- /* parse flags */
- if (fdr.flags & fdr99_f_program)
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "PGM%s",
- (fdr.flags & fdr99_f_wp) ? " R/O" : "");
- else
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "%c/%c %d%s",
- (fdr.flags & fdr99_f_int) ? 'I' : 'D',
- (fdr.flags & fdr99_f_var) ? 'V' : 'F',
- fdr.reclen,
- (fdr.flags & fdr99_f_wp) ? " R/O" : "");
- /* len in physrecs */
- /* @BN@ return length in bytes */
- /* ent->filesize = get_win_fdr_fphysrecs(&fdr); */
- ent->filesize = (get_win_fdr_fphysrecs(&fdr)+1)*256;
-
- iter->index[iter->level]++;
- }
- }
-
- return (imgtoolerr_t)0;
-}
-
-/*
- Compute free space on disk image (in AUs)
-*/
-static imgtoolerr_t ti99_image_freespace(imgtool_partition *partition, UINT64 *size)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(img);
- size_t freeAUs;
- int i;
-
- freeAUs = 0;
- for (i=0; i<image->AUformat.totAUs; i++)
- {
- if (! (image->abm[i >> 3] & (1 << (i & 7))))
- freeAUs++;
- }
-
- /* @BN@ return free space in bytes */
- /* *size = freeAUs; */
- *size = freeAUs*256;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Extract a file from a ti99_image. The file is saved in tifile format.
-*/
-static imgtoolerr_t ti99_image_readfile(imgtool_partition *partition, const char *fpath, const char *fork, imgtool_stream *destf)
-{
- imgtool_image *img = imgtool_partition_image(partition);
-#if 1
-
- /* extract data as TIFILES */
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(img);
- ti99_lvl2_fileref src_file;
- ti99_lvl2_fileref dst_file;
- ti99_date_time date_time;
- int fphysrecs;
- int i;
- UINT8 buf[256];
- imgtoolerr_t errorcode;
-
-
- if (check_fpath(fpath))
- return IMGTOOLERR_BADFILENAME;
-
- /* open file on TI image */
- switch (image->type)
- {
- case L2I_DSK:
- errorcode = (imgtoolerr_t)open_file_lvl2_dsk(image, fpath, &src_file);
- break;
-
- case L2I_WIN:
- errorcode = (imgtoolerr_t)open_file_lvl2_win(image, fpath, &src_file);
- break;
-
- default:
- errorcode = (imgtoolerr_t)-1;
- break;
- }
- if (errorcode)
- return errorcode;
-
- errorcode = (imgtoolerr_t)new_file_lvl2_tifiles(destf, &dst_file);
- if (errorcode)
- return errorcode;
-
- /* write TIFILE header */
- /* set up parameters */
- set_file_flags(&dst_file, get_file_flags(&src_file));
- set_file_recsperphysrec(&dst_file, get_file_recsperphysrec(&src_file));
- errorcode = (imgtoolerr_t)set_file_fphysrecs(&dst_file, get_file_fphysrecs(&src_file));
- if (errorcode)
- return errorcode;
- set_file_eof(&dst_file, get_file_eof(&src_file));
- errorcode = (imgtoolerr_t)set_file_reclen(&dst_file, get_file_reclen(&src_file));
- if (errorcode)
- return errorcode;
- errorcode = (imgtoolerr_t)set_file_fixrecs(&dst_file, get_file_fixrecs(&src_file));
- if (errorcode)
- return errorcode;
-
- get_file_creation_date(&src_file, &date_time);
-#if 0
- if ((date_time.time_MSB == 0) || (date_time.time_LSB == 0)
- || (date_time.date_MSB == 0) || (date_time.date_LSB == 0))
- current_date_time(&date_time);
-#endif
- set_file_creation_date(&dst_file, date_time);
-
- get_file_update_date(&src_file, &date_time);
-#if 0
- if ((date_time.time_MSB == 0) || (date_time.time_LSB == 0)
- || (date_time.date_MSB == 0) || (date_time.date_LSB == 0))
- current_date_time(&date_time);
-#endif
- set_file_update_date(&dst_file, date_time);
-
- if (stream_write(destf, & dst_file.tifiles.hdr, 128) != 128)
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
-
- /* copy data to TIFILE */
- fphysrecs = get_file_fphysrecs(&src_file);
-
- for (i=0; i<fphysrecs; i++)
- {
- errorcode = (imgtoolerr_t)read_file_physrec(& src_file, i, buf);
- if (errorcode)
- return errorcode;
-
- errorcode = (imgtoolerr_t)write_file_physrec(& dst_file, i, buf);
- if (errorcode)
- return errorcode;
- }
-
- return (imgtoolerr_t)0;
-
-#else
-
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(img);
- ti99_lvl3_fileref src_file;
- UINT8 buf[256];
- int reclen;
- char lineend = '\r';
- int errorcode;
-
-
- if (check_fpath(fpath))
- return IMGTOOLERR_BADFILENAME;
-
- /* open file on TI image */
- switch (image->type)
- {
- case L2I_DSK:
- errorcode = open_file_lvl2_dsk(image, fpath, &src_file.l2_file);
- break;
-
- case L2I_WIN:
- errorcode = open_file_lvl2_win(image, fpath, &src_file.l2_file);
- break;
- }
- if (errorcode)
- return errorcode;
-
- errorcode = open_file_lvl3(& src_file);
- if (errorcode)
- return errorcode;
-
- /* write text data */
- while (! is_eof(& src_file))
- {
- errorcode = read_next_record(& src_file, buf, & reclen);
- if (errorcode)
- return errorcode;
- if (stream_write(destf, buf, reclen) != reclen)
- return IMGTOOLERR_WRITEERROR;
- if (stream_write(destf, &lineend, 1) != 1)
- return IMGTOOLERR_WRITEERROR;
- }
-
- return 0;
-
-#endif
-}
-
-/*
- Add a file to a ti99_image. The file must be in tifile format.
-*/
-static imgtoolerr_t ti99_image_writefile(imgtool_partition *partition, const char *fpath, const char *fork, imgtool_stream *sourcef, option_resolution *writeoptions)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(img);
- const char *filename;
- char ti_fname[10];
- ti99_lvl2_fileref src_file;
- ti99_lvl2_fileref dst_file;
- ti99_date_time date_time;
- int i;
- int fphysrecs;
- UINT8 buf[256];
- imgtoolerr_t errorcode;
- int parent_ref_valid, parent_ref = 0;
- ti99_catalog *catalog, catalog_buf = {0, };
-
-
- (void) writeoptions;
-
- if (check_fpath(fpath))
- return IMGTOOLERR_BADFILENAME;
-
- switch (image->type)
- {
- case L2I_DSK:
- errorcode = (imgtoolerr_t)dsk_find_catalog_entry(image, fpath, &parent_ref_valid, &parent_ref, NULL, NULL);
- if (errorcode == 0)
- /* file already exists: causes an error for now */
- return (imgtoolerr_t)IMGTOOLERR_UNEXPECTED;
- else if ((! parent_ref_valid) || (errorcode != IMGTOOLERR_FILENOTFOUND))
- return (imgtoolerr_t)errorcode;
- break;
-
- case L2I_WIN:
- errorcode = (imgtoolerr_t)win_find_catalog_entry(image, fpath, &parent_ref_valid, &parent_ref, &catalog_buf, NULL, NULL);
- if (errorcode == 0)
- /* file already exists: causes an error for now */
- return (imgtoolerr_t)IMGTOOLERR_UNEXPECTED;
- else if ((! parent_ref_valid) || (errorcode != IMGTOOLERR_FILENOTFOUND))
- return (imgtoolerr_t)errorcode;
- break;
- }
-
- errorcode =(imgtoolerr_t) open_file_lvl2_tifiles(sourcef, & src_file);
- if (errorcode)
- return (imgtoolerr_t)errorcode;
-
- /* create new file */
- filename = strrchr(fpath, '.');
- if (filename)
- filename++;
- else
- filename = fpath;
- str_to_fname(ti_fname, filename);
- switch (image->type)
- {
- case L2I_DSK:
- errorcode = (imgtoolerr_t)new_file_lvl2_dsk(image, parent_ref, ti_fname, &dst_file);
- if (errorcode)
- return (imgtoolerr_t)errorcode;
- break;
-
- case L2I_WIN:
- errorcode = (imgtoolerr_t)new_file_lvl2_win(image, &catalog_buf, ti_fname, &dst_file);
- if (errorcode)
- return (imgtoolerr_t)errorcode;
- break;
- }
-
- /* set up parameters */
- set_file_flags(&dst_file, get_file_flags(&src_file));
- set_file_recsperphysrec(&dst_file, get_file_recsperphysrec(&src_file));
- errorcode = (imgtoolerr_t)set_file_fphysrecs(&dst_file, /*get_file_fphysrecs(&src_file)*/0);
- if (errorcode)
- return (imgtoolerr_t)errorcode;
- set_file_eof(&dst_file, get_file_eof(&src_file));
- errorcode = (imgtoolerr_t)set_file_reclen(&dst_file, get_file_reclen(&src_file));
- if (errorcode)
- return (imgtoolerr_t)errorcode;
- errorcode = (imgtoolerr_t)set_file_fixrecs(&dst_file, get_file_fixrecs(&src_file));
- if (errorcode)
- return (imgtoolerr_t)errorcode;
-
- get_file_creation_date(&src_file, &date_time);
-#if 0
- if ((date_time.time_MSB == 0) || (date_time.time_LSB == 0)
- || (date_time.date_MSB == 0) || (date_time.date_LSB == 0))
- current_date_time(&date_time);
-#endif
- set_file_creation_date(&dst_file, date_time);
-
- get_file_update_date(&src_file, &date_time);
-#if 0
- if ((date_time.time_MSB == 0) || (date_time.time_LSB == 0)
- || (date_time.date_MSB == 0) || (date_time.date_LSB == 0))
- current_date_time(&date_time);
-#endif
- set_file_update_date(&dst_file, date_time);
-
- /* alloc data physrecs */
- fphysrecs = get_file_fphysrecs(&src_file);
- switch (dst_file.type)
- {
- case L2F_DSK:
- errorcode = (imgtoolerr_t)dsk_alloc_file_physrecs(&dst_file.dsk, fphysrecs);
- if (errorcode)
- return (imgtoolerr_t)errorcode;
- break;
-
- case L2F_WIN:
- errorcode = (imgtoolerr_t)win_alloc_file_physrecs(&dst_file.win, fphysrecs);
- if (errorcode)
- return (imgtoolerr_t)errorcode;
- break;
-
- case L2F_TIFILES:
- break;
- }
-
- /* copy data */
- for (i=0; i<fphysrecs; i++)
- {
- if (stream_read(sourcef, buf, 256) != 256)
- return (imgtoolerr_t)IMGTOOLERR_READERROR;
-
- errorcode = (imgtoolerr_t)write_file_physrec(& dst_file, i, buf);
- if (errorcode)
- return (imgtoolerr_t)errorcode;
- }
-
- /* write fdr */
- switch (image->type)
- {
- case L2I_DSK:
- if (write_absolute_physrec(& image->l1_img, dst_file.dsk.fdr_aphysrec, &dst_file.dsk.fdr))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- break;
-
- case L2I_WIN:
- /* save fphysrecs field as well */
- if (dst_file.win.curfdr_aphysrec == dst_file.win.eldestfdr_aphysrec)
- set_win_fdr_fphysrecs(&dst_file.win.curfdr, dst_file.win.fphysrecs);
- if (write_absolute_physrec(& image->l1_img, dst_file.win.curfdr_aphysrec, &dst_file.win.curfdr))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- if (dst_file.win.curfdr_aphysrec != dst_file.win.eldestfdr_aphysrec)
- {
- dst_file.win.curfdr_aphysrec = dst_file.win.eldestfdr_aphysrec;
- if (read_absolute_physrec(& image->l1_img, dst_file.win.curfdr_aphysrec, &dst_file.win.curfdr))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- set_win_fdr_fphysrecs(&dst_file.win.curfdr, dst_file.win.fphysrecs);
- if (write_absolute_physrec(& image->l1_img, dst_file.win.curfdr_aphysrec, &dst_file.win.curfdr))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- }
- break;
- }
-
- /* update catalog */
- switch (image->type)
- {
- case L2I_DSK:
- catalog = &image->dsk.catalogs[parent_ref];
- for (i=0; i<128; i++)
- {
- buf[2*i] = catalog->files[i].fdr_ptr >> 8;
- buf[2*i+1] = catalog->files[i].fdr_ptr & 0xff;
- }
- if (write_absolute_physrec(& image->l1_img, image->dsk.fdir_aphysrec[parent_ref], buf))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- break;
-
- case L2I_WIN:
- {
- win_vib_ddr parent_ddr;
- int fdir_AU;
-
- /* update VIB/DDR and get FDIR AU address */
- if (read_absolute_physrec(& image->l1_img, parent_ref * image->AUformat.physrecsperAU, &parent_ddr))
- return (imgtoolerr_t)IMGTOOLERR_READERROR;
- parent_ddr.num_files = catalog_buf.num_files;
- if (write_absolute_physrec(& image->l1_img, parent_ref * image->AUformat.physrecsperAU, &parent_ddr))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- fdir_AU = get_UINT16BE(parent_ddr.fdir_AU);
-
- /* generate FDIR and save it */
- for (i=0; i<127; i++)
- {
- buf[2*i] = catalog_buf.files[i].fdr_ptr >> 8;
- buf[2*i+1] = catalog_buf.files[i].fdr_ptr & 0xff;
- }
- buf[254] = parent_ref >> 8;
- buf[255] = parent_ref & 0xff;
- if (write_absolute_physrec(& image->l1_img, fdir_AU * image->AUformat.physrecsperAU, buf))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- }
- break;
- }
-
- /* update bitmap */
- switch (image->type)
- {
- case L2I_DSK:
- {
- dsk_vib vib;
-
- if (read_absolute_physrec(& image->l1_img, 0, &vib))
- return (imgtoolerr_t)IMGTOOLERR_READERROR;
- memcpy(vib.abm, image->abm, 200);
- if (write_absolute_physrec(& image->l1_img, 0, &vib))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- }
- break;
-
- case L2I_WIN:
- /* save allocation bitmap (aphysrecs 1 through n, n<=33) */
- for (i=0; i < (image->AUformat.totAUs+2047)/2048; i++)
- if (write_absolute_physrec(&image->l1_img, i+1, image->abm+i*256))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- break;
- }
-
- return (imgtoolerr_t)0;
-}
-
-/*
- Delete a file from a ti99_image.
-*/
-static imgtoolerr_t dsk_image_deletefile(imgtool_partition *partition, const char *fpath)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(img);
- dsk_fdr fdr;
- int i, cluster_index;
- unsigned cur_AU, cluster_lastfphysrec;
-// int fphysrecs;
- int parent_ref, is_dir, catalog_index;
- imgtoolerr_t errorcode;
- UINT8 buf[256];
- ti99_catalog *catalog;
-
-
- if (check_fpath(fpath))
- return IMGTOOLERR_BADFILENAME;
-
- errorcode = (imgtoolerr_t)dsk_find_catalog_entry(image, fpath, NULL, &parent_ref, &is_dir, &catalog_index);
- if (errorcode)
- return errorcode;
-
- if (is_dir)
- {
- catalog = &image->dsk.catalogs[catalog_index+1];
-
- if ((catalog->num_files != 0) || (catalog->num_subdirs != 0))
- return IMGTOOLERR_UNIMPLEMENTED;
-
- catalog = &image->dsk.catalogs[0];
-
- /* free fdir AU */
- cur_AU = image->dsk.fdir_aphysrec[catalog_index+1] / image->AUformat.physrecsperAU;
- image->abm[cur_AU >> 3] &= ~ (1 << (cur_AU & 7));
-
- /* delete catalog entry */
- for (i=catalog_index; i<2; i++)
- {
- catalog->subdirs[i] = catalog->subdirs[i+1];
- image->dsk.fdir_aphysrec[i+1] = image->dsk.fdir_aphysrec[i+2];
- }
- memset(catalog->subdirs[2].name, 0, 10);
- catalog->subdirs[2].dir_ptr = 0;
- image->dsk.fdir_aphysrec[3] = 0;
- catalog->num_subdirs--;
-
- /* update directory and bitmap in vib */
- {
- dsk_vib vib;
-
- if (read_absolute_physrec(& image->l1_img, 0, &vib))
- return IMGTOOLERR_READERROR;
-
- for (i=0; i<3; i++)
- {
- memcpy(vib.subdir[i].name, catalog->subdirs[i].name, 10);
- set_UINT16BE(&vib.subdir[i].fdir_aphysrec, image->dsk.fdir_aphysrec[i+1]);
- }
-
- memcpy(vib.abm, image->abm, 200);
-
- if (write_absolute_physrec(& image->l1_img, 0, &vib))
- return IMGTOOLERR_WRITEERROR;
- }
- }
- else
- {
- catalog = &image->dsk.catalogs[parent_ref];
-
- if (read_absolute_physrec(& image->l1_img, catalog->files[catalog_index].fdr_ptr, &fdr))
- return IMGTOOLERR_READERROR;
-
- /* free data AUs */
-// fphysrecs =
- get_UINT16BE(fdr.fphysrecs);
-
- i = 0;
- cluster_index = 0;
- while (cluster_index < 76)
- {
- cur_AU = get_dsk_fdr_cluster_baseAU(image, & fdr, cluster_index);
- if (cur_AU == 0)
- /* end of cluster list */
- break;
- cluster_lastfphysrec = get_dsk_fdr_cluster_lastfphysrec(& fdr, cluster_index);
-
- while (i<=cluster_lastfphysrec)
- {
- /* the condition below is an error, but it should not prevent
- us from deleting the file */
- if (cur_AU >= image->AUformat.totAUs)
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- break;
-
- image->abm[cur_AU >> 3] &= ~ (1 << (cur_AU & 7));
-
- i += image->AUformat.physrecsperAU;
- cur_AU++;
- }
-
- cluster_index++;
- }
- /* the condition below is an error, but it should not prevent us from
- deleting the file */
-#if 0
- if (i<fphysrecs)
- return IMGTOOLERR_CORRUPTIMAGE;
-#endif
-
- /* free fdr AU */
- cur_AU = catalog->files[catalog_index].fdr_ptr / image->AUformat.physrecsperAU;
- image->abm[cur_AU >> 3] &= ~ (1 << (cur_AU & 7));
-
- /* delete catalog entry */
- for (i=catalog_index; i<127; i++)
- catalog->files[i] = catalog->files[i+1];
- catalog->files[127].fdr_ptr = 0;
- catalog->num_files--;
-
- /* update parent fdir */
- for (i=0; i<128; i++)
- {
- buf[2*i] = catalog->files[i].fdr_ptr >> 8;
- buf[2*i+1] = catalog->files[i].fdr_ptr & 0xff;
- }
- if (write_absolute_physrec(& image->l1_img, image->dsk.fdir_aphysrec[parent_ref], buf))
- return IMGTOOLERR_WRITEERROR;
-
- /* update bitmap */
- {
- dsk_vib vib;
-
- if (read_absolute_physrec(& image->l1_img, 0, &vib))
- return IMGTOOLERR_READERROR;
- memcpy(vib.abm, image->abm, 200);
- if (write_absolute_physrec(& image->l1_img, 0, &vib))
- return IMGTOOLERR_WRITEERROR;
- }
- }
-
- return (imgtoolerr_t)0;
-}
-
-static imgtoolerr_t win_image_deletefile(imgtool_partition *partition, const char *fpath)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- struct ti99_lvl2_imgref *image = (struct ti99_lvl2_imgref *) imgtool_image_extra_bytes(img);
- int parent_ddr_AU, is_dir, catalog_index;
- win_fdr fdr;
- int i;
- unsigned cur_AU, end_AU;
- unsigned curfdr_aphysrec;
- unsigned cursibFDR_index, endsibFDR_index = 0;
- int errorcode;
- UINT8 buf[256];
- ti99_catalog catalog;
-
-
- if (check_fpath(fpath))
- return (imgtoolerr_t)IMGTOOLERR_BADFILENAME;
-
- errorcode = win_find_catalog_entry(image, fpath, NULL, &parent_ddr_AU, &catalog, &is_dir, &catalog_index);
- if (errorcode)
- return (imgtoolerr_t)errorcode;
-
- if (is_dir)
- {
- unsigned DDR_AU;
- win_vib_ddr ddr_buf;
-
- /* Read DDR record */
- DDR_AU = catalog.subdirs[catalog_index].dir_ptr;
- if (read_absolute_physrec(& image->l1_img, DDR_AU*image->AUformat.physrecsperAU, &ddr_buf))
- return (imgtoolerr_t)IMGTOOLERR_READERROR;
-
- /* read FDIR AU pointer */
- cur_AU = get_UINT16BE(ddr_buf.fdir_AU);
-
- /* sanity checks */
- if ((ddr_buf.num_files > 127) || (ddr_buf.num_subdirs > 114) || (cur_AU > image->AUformat.totAUs))
- return (imgtoolerr_t)IMGTOOLERR_CORRUPTIMAGE;
-
- if ((ddr_buf.num_files != 0) || (ddr_buf.num_subdirs != 0))
- return (imgtoolerr_t)IMGTOOLERR_UNIMPLEMENTED;
-
- /* free fdir AU */
- image->abm[cur_AU >> 3] &= ~ (1 << (cur_AU & 7));
-
- /* free ddr AU */
- image->abm[DDR_AU >> 3] &= ~ (1 << (DDR_AU & 7));
-
- /* delete parent catalog entry */
- for (i=catalog_index; i<113; i++)
- catalog.subdirs[i] = catalog.subdirs[i+1];
- catalog.subdirs[113].dir_ptr = 0;
- catalog.num_subdirs--;
-
- /* update parent VIB/DDR */
- if (read_absolute_physrec(& image->l1_img, parent_ddr_AU * image->AUformat.physrecsperAU, &ddr_buf))
- return (imgtoolerr_t)IMGTOOLERR_READERROR;
- ddr_buf.num_subdirs = catalog.num_subdirs;
- for (i=0; i<114; i++)
- set_UINT16BE(&ddr_buf.subdir_AU[i], catalog.subdirs[i].dir_ptr);
- if (write_absolute_physrec(& image->l1_img, parent_ddr_AU * image->AUformat.physrecsperAU, &ddr_buf))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
-
- /* save allocation bitmap (aphysrecs 1 through n, n<=33) */
- for (i=0; i < (image->AUformat.totAUs+2047)/2048; i++)
- if (write_absolute_physrec(&image->l1_img, i+1, image->abm+i*256))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- }
- else
- {
- /* check integrity of FDR sibling chain, and go to last sibling */
- /* note that as we check that the back chain is consistent with the forward
- chain, we will also detect any cycle in the sibling chain, so we do not
- need to check against them explicitely */
- {
- int pastendoflist_flag;
- unsigned prevfdr_aphysrec;
-
-
- pastendoflist_flag = 0;
- cursibFDR_index = 0;
- curfdr_aphysrec = catalog.files[catalog_index].fdr_ptr * image->AUformat.physrecsperAU;
- if (read_absolute_physrec(& image->l1_img, curfdr_aphysrec, &fdr))
- return (imgtoolerr_t)IMGTOOLERR_READERROR;
-
- if (get_UINT16BE(fdr.prevsibFDR_AU) != 0)
- return (imgtoolerr_t)IMGTOOLERR_CORRUPTIMAGE;
-
- while (1)
- {
- if (! pastendoflist_flag)
- {
- /* look for end of list */
- for (i=0; i<54; i++)
- {
- if (get_UINT16BE(fdr.clusters[i][0]) == 0)
- {
- endsibFDR_index = cursibFDR_index;
- pastendoflist_flag = TRUE;
- break;
- }
- }
- }
-
- /* exit loop if end of sibling chain */
- if (! get_UINT16BE(fdr.nextsibFDR_AU))
- break;
-
- /* otherwise read next FDR */
- if (get_UINT16BE(fdr.nextsibFDR_AU) >= image->AUformat.totAUs)
- return (imgtoolerr_t)IMGTOOLERR_CORRUPTIMAGE;
-
- prevfdr_aphysrec = curfdr_aphysrec;
- curfdr_aphysrec = get_win_fdr_nextsibFDR_aphysrec(image, &fdr);
- if (read_absolute_physrec(& image->l1_img, curfdr_aphysrec, &fdr))
- return (imgtoolerr_t)IMGTOOLERR_READERROR;
- cursibFDR_index++;
-
- /* check that back chaining is consistent with forward chaining */
- if (get_win_fdr_prevsibFDR_aphysrec(image, &fdr) != prevfdr_aphysrec)
- return (imgtoolerr_t)IMGTOOLERR_CORRUPTIMAGE;
- }
- if (! pastendoflist_flag)
- endsibFDR_index = cursibFDR_index;
- }
-
-
- while (1)
- {
- if (cursibFDR_index <= endsibFDR_index)
- {
- for (i = 0; i < 54; i++)
- {
- cur_AU = get_UINT16BE(fdr.clusters[i][0]);
- if (cur_AU == 0)
- /* end of cluster list */
- break;
- end_AU = get_UINT16BE(fdr.clusters[i][1]);
-
- while (cur_AU<=end_AU)
- {
- /* the condition below is an error, but it should not prevent
- us from deleting the file */
- if (cur_AU >= image->AUformat.totAUs)
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- break;
-
- image->abm[cur_AU >> 3] &= ~ (1 << (cur_AU & 7));
-
- cur_AU++;
- }
- }
- }
-
- /* free fdr AU if applicable */
- if ((curfdr_aphysrec % image->AUformat.physrecsperAU) == 0)
- {
- cur_AU = curfdr_aphysrec / image->AUformat.physrecsperAU;
- image->abm[cur_AU >> 3] &= ~ (1 << (cur_AU & 7));
- }
-
- if (cursibFDR_index == 0)
- break;
- curfdr_aphysrec = get_win_fdr_prevsibFDR_aphysrec(image, &fdr);
- if (read_absolute_physrec(& image->l1_img, curfdr_aphysrec, &fdr))
- return (imgtoolerr_t)IMGTOOLERR_READERROR;
- cursibFDR_index--;
- }
-
-
- /* delete catalog entry */
- for (i=catalog_index; i<127; i++)
- catalog.files[i] = catalog.files[i+1];
- catalog.files[127].fdr_ptr = 0;
- catalog.num_files--;
-
-
- /* update VIB/DDR and get FDIR AU address */
- {
- win_vib_ddr parent_ddr;
-
- if (read_absolute_physrec(& image->l1_img, parent_ddr_AU * image->AUformat.physrecsperAU, &parent_ddr))
- return (imgtoolerr_t)IMGTOOLERR_READERROR;
- parent_ddr.num_files = catalog.num_files;
- if (write_absolute_physrec(& image->l1_img, parent_ddr_AU * image->AUformat.physrecsperAU, &parent_ddr))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- cur_AU = get_UINT16BE(parent_ddr.fdir_AU);
- }
-
- /* generate FDIR and save it */
- for (i=0; i<127; i++)
- {
- buf[2*i] = catalog.files[i].fdr_ptr >> 8;
- buf[2*i+1] = catalog.files[i].fdr_ptr & 0xff;
- }
- buf[254] = parent_ddr_AU >> 8;
- buf[255] = parent_ddr_AU & 0xff;
- if (write_absolute_physrec(& image->l1_img, cur_AU * image->AUformat.physrecsperAU, buf))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
-
- /* save allocation bitmap (aphysrecs 1 through n, n<=33) */
- for (i=0; i < (image->AUformat.totAUs+2047)/2048; i++)
- if (write_absolute_physrec(&image->l1_img, i+1, image->abm+i*256))
- return (imgtoolerr_t)IMGTOOLERR_WRITEERROR;
- }
-
- return (imgtoolerr_t)0;
-}
-
-/*
- Create a blank ti99_image (common code).
-
- Supports MESS and V9T9 formats only
-*/
-static imgtoolerr_t dsk_image_create(imgtool_image *image, imgtool_stream *f, option_resolution *createoptions, ti99_img_format img_format)
-{
- const char *volname;
- int density;
- ti99_lvl1_imgref l1_img;
- int protected_var;
-
- int totphysrecs, physrecsperAU, totAUs;
-
- dsk_vib vib;
- UINT8 empty_sec[256];
-
- int i;
-
- l1_img.img_format = img_format;
- l1_img.file_handle = f;
-
- /* read options */
- volname = option_resolution_lookup_string(createoptions, dsk_createopts_volname);
- l1_img.geometry.heads = option_resolution_lookup_int(createoptions, dsk_createopts_sides);
- l1_img.geometry.cylinders = option_resolution_lookup_int(createoptions, dsk_createopts_tracks);
- l1_img.geometry.secspertrack = option_resolution_lookup_int(createoptions, dsk_createopts_sectors);
- protected_var = option_resolution_lookup_int(createoptions, dsk_createopts_protection);
- density = option_resolution_lookup_int(createoptions, dsk_createopts_density);
-
- /* NPW 03-DEC-2003 - Fixes a crash if volname is NULL */
- if (!volname)
- volname = "";
-
- totphysrecs = l1_img.geometry.secspertrack * l1_img.geometry.cylinders * l1_img.geometry.heads;
- physrecsperAU = (totphysrecs + 1599) / 1600;
- /* round to next larger power of 2 */
- for (i = 1; i < physrecsperAU; i <<= 1)
- ;
- physrecsperAU = i;
- totAUs = totphysrecs / physrecsperAU;
-
- /* auto-density */
- if (density == 0)
- {
- if (l1_img.geometry.secspertrack <= 9)
- density = 1;
- else if (l1_img.geometry.secspertrack <= 18)
- density = 2;
- else
- density = 3;
- }
-
- /* check volume name */
- if (strchr(volname, '.') || strchr(volname, ' ') || (strlen(volname) > 10))
- return /*IMGTOOLERR_BADFILENAME*/IMGTOOLERR_PARAMCORRUPT;
-
- /* FM disks can hold fewer sector per track than MFM disks */
- if ((density == 1) && (l1_img.geometry.secspertrack > 9))
- return IMGTOOLERR_PARAMTOOLARGE;
-
- /* DD disks can hold fewer sector per track than HD disks */
- if ((density == 2) && (l1_img.geometry.secspertrack > 18))
- return IMGTOOLERR_PARAMTOOLARGE;
-
- /* check total disk size */
- if (totphysrecs < 2)
- return IMGTOOLERR_PARAMTOOSMALL;
-
- /* initialize vib in aphysrec 0 */
-
- /* set volume name */
- str_to_fname(vib.name, volname);
-
- /* set every header field */
- set_UINT16BE(& vib.totphysrecs, totphysrecs);
- vib.secspertrack = l1_img.geometry.secspertrack;
- vib.id[0] = 'D';
- vib.id[1] = 'S';
- vib.id[2] = 'K';
- vib.protection = protected_var ? 'P' : ' ';
- vib.cylinders = l1_img.geometry.cylinders;
- vib.heads = l1_img.geometry.heads;
- vib.density = density;
- for (i=0; i<3; i++)
- {
- memset(vib.subdir[i].name, '\0', 10);
- set_UINT16BE(& vib.subdir[i].fdir_aphysrec, 0);
- }
-
- /* clear bitmap */
- for (i=0; i < (totAUs>>3); i++)
- vib.abm[i] = 0;
-
- if (totAUs & 7)
- {
- vib.abm[i] = 0xff << (totAUs & 7);
- i++;
- }
-
- for (; i < 200; i++)
- vib.abm[i] = 0xff;
-
- /* mark first 2 aphysrecs (vib and fdir) as used */
- vib.abm[0] |= (physrecsperAU == 1) ? 3 : 1;
-
- /* write aphysrec 0 */
- if (write_absolute_physrec(& l1_img, 0, &vib))
- return IMGTOOLERR_WRITEERROR;
-
-
- /* now clear every other physrecs, including the FDIR record */
- memset(empty_sec, 0, sizeof(empty_sec));
-
- for (i=1; i<totphysrecs; i++)
- if (write_absolute_physrec(& l1_img, i, empty_sec))
- return IMGTOOLERR_WRITEERROR;
-
-
- return (imgtoolerr_t)dsk_image_init(image, f, img_format);
-}
-
-/*
- Create a blank ti99_image (MESS format).
-*/
-static imgtoolerr_t dsk_image_create_mess(imgtool_image *image, imgtool_stream *f, option_resolution *createoptions)
-{
- return dsk_image_create(image, f, createoptions, if_mess);
-}
-
-/*
- Create a blank ti99_image (V9T9 format).
-*/
-static imgtoolerr_t dsk_image_create_v9t9(imgtool_image *image, imgtool_stream *f, option_resolution *createoptions)
-{
- return dsk_image_create(image, f, createoptions, if_v9t9);
-}
diff --git a/src/mess/tools/imgtool/modules/ti990hd.c b/src/mess/tools/imgtool/modules/ti990hd.c
deleted file mode 100644
index 2c2a6c3a13c..00000000000
--- a/src/mess/tools/imgtool/modules/ti990hd.c
+++ /dev/null
@@ -1,1818 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Raphael Nabet
-/*
- Handlers for ti990 disk images
-
- Disk images are in MESS format.
-
- Raphael Nabet, 2003
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include "imgtool.h"
-
-/* Max sector length is bytes. Generally 256, except for a few older disk
-units which use 288-byte-long sectors, and SCSI units which generally use
-standard 512-byte-long sectors. */
-/* I chose a limit of 512. No need to use more until someone creates CD-ROMs
-for TI990. */
-#define MAX_SECTOR_SIZE 512
-#define MIN_SECTOR_SIZE 256
-
-#define MAX_CYLINDERS 2047
-#define MAX_HEADS 31
-#define MAX_SECTORS_PER_TRACK 256 /* 255 for 512-byte-long sector, so that the total number of words that can be recorded on a track may fit in one 16-bit word (store registers command) */
-
-/* Max path len in chars: this value is 48 characters in DX10, but since the
-path includes at least a leading '.', our value is 47. */
-/* Since path generally include a volume name that can be up to 8 character
-long, we should display a warning message when the user wants to create a path
-that is longer than 39 characters. */
-#define MAX_PATH_LEN 47
-#define MAX_SAFE_PATH_LEN 39
-
-#define MAX_DIR_LEVEL 25 /* We need to put a recursion limit to avoid endless recursion hazard */
-
-
-struct UINT16BE
-{
- UINT8 bytes[2];
-};
-
-struct UINT32BE
-{
- UINT8 bytes[4];
-};
-
-INLINE UINT16 get_UINT16BE(UINT16BE word)
-{
- return (word.bytes[0] << 8) | word.bytes[1];
-}
-
-INLINE void set_UINT16BE(UINT16BE *word, UINT16 data)
-{
- word->bytes[0] = (data >> 8) & 0xff;
- word->bytes[1] = data & 0xff;
-}
-
-INLINE UINT32 get_UINT32BE(UINT32BE word)
-{
- return (word.bytes[0] << 24) | (word.bytes[1] << 16) | (word.bytes[2] << 8) | word.bytes[3];
-}
-
-INLINE void set_UINT32BE(UINT32BE *word, UINT32 data)
-{
- word->bytes[0] = (data >> 24) & 0xff;
- word->bytes[1] = (data >> 16) & 0xff;
- word->bytes[2] = (data >> 8) & 0xff;
- word->bytes[3] = data & 0xff;
-}
-
-/*
- disk image header
-*/
-struct disk_image_header
-{
- UINT32BE cylinders; /* number of cylinders on hard disk (big-endian) */
- UINT32BE heads; /* number of heads on hard disk (big-endian) */
- UINT32BE sectors_per_track; /* number of sectors per track on hard disk (big-endian) */
- UINT32BE bytes_per_sector; /* number of bytes of data per sector on hard disk (big-endian) */
-};
-
-enum
-{
- header_len = sizeof(disk_image_header)
-};
-
-/*
- Disk structure:
-
- Track 0 Sector 0: see below
- Track 0 Sector 1: list of bad ADU
- Track 0 Sector 2 through N: disk allocation bitmap
- Track 1 Sector 0 through N-2: optional disk program image loader
- Track 1 Sector N-1: copy of Track 0 Sector 0
- Track 1 Sector N: copy of Track 0 Sector 1
- Last cylinder has disagnostic information (reported as .S$DIAG)
- Remaining sectors are used for fdr and data.
-*/
-
-/*
- SC0 record (Disk sector 0)
-*/
-struct ti990_sc0
-{
- char vnm[8]; /* volume name */
- UINT16BE tna; /* total number of ADUs */
- UINT8 sbm; /* starting sector of bit maps */
- UINT8 tbm; /* total bit maps */
- UINT16BE rl; /* track 01 record length */
- UINT16BE slt; /* system loader track address */
- UINT8 fill00[6]; /* * * RESERVED * * */
- UINT16BE nba; /* total number of bad ADUs on disk */
- UINT16BE sle; /* system loader entry point */
- UINT16BE sll; /* system loader length */
- UINT8 fill01[8]; /* * * RESERVED * * */
- UINT16BE lt1; /* system loader track (copy 2) */
- UINT8 fill02[8]; /* * * RESERVED * * */
- char pi1[8]; /* primary system file name */
- char pi2[8]; /* secondary system file name */
- UINT16BE pif; /* system selector */
- UINT16BE vda; /* volume directory ADU */
- UINT16BE vpl; /* vcatalog physical record length */
- UINT16BE spa; /* sectors per ADU */
- UINT8 dcd[4]; /* disk creation date */
- char pf1[8]; /* primary program file */
- char pf2[8]; /* secondary program file */
- UINT16BE pff; /* program file switch */
- char of1[8]; /* primary overlay file */
- char of2[8]; /* secondary overlay file */
- UINT16BE off; /* overlay file switch */
- char il1[8]; /* primary intermediate loader */
- char il2[8]; /* secondary intermediate loader */
- UINT16BE ilf; /* intermediate loader flag */
- char din[8]; /* diagnostic file name */
- UINT16BE dif; /* diagnostic flag */
- UINT16BE drs; /* default physical record size "DBUILD DETERMINES DEFAULT PRS" (whatever it means) */
- UINT16BE bal; /* starting sector of bad ADU list */
- UINT16BE spr; /* track 0 sectors per record */
- char wf1[8]; /* WCS primary microcode file */
- char wf2[8]; /* WCS secondary microcode file */
- UINT16BE wff; /* WCS flag switch */
- UINT16BE vif; /* track 1 select flag (whatever it means) volume information copied flag */
- UINT16BE sta; /* state of disk: */
- /* 1 = disk surface has not been tested for defects */
- /* 2 = disk surface has been tested, but no file system has been installed */
- /* 3 = a file system has been installed */
- UINT16BE dct; /* disk creation time */
- UINT16BE fsf; /* * * RESERVED * * */
- /* SCOSIZ = >AA */
-};
-
-/*
- DOR (Directory Overhead Record)
-*/
-struct ti990_dor
-{
- UINT16BE nrc; /* # records in directory (minus DOR) nrc = nfl + nar (+ tfc???) */
- UINT16BE nfl; /* # files currently in directory */
- UINT16BE nar; /* # of available records */
- UINT16BE tfc; /* number of temporary files */
- char dnm[8]; /* directory file name (VCATALOG for root) */
- UINT16BE lvl; /* level # of directory (0 for root, 1 for children of root, 2 for grandchildren, etc) */
- char pnm[8]; /* name of parent directory (VCATALOG for root, even though it makes little sense) */
- UINT16BE prs; /* "default physical record length (used for file creation)" */
- /* DORSIZ = >1C */
-};
-
-/*
- file flags found in fdr
-*/
-enum
-{
- ace_flg_rdf = 0x8000, /* read access flag */
- ace_flg_wrf = 0x4000, /* write access flag */
- ace_flg_dlf = 0x2000, /* delete access flag */
- ace_flg_exf = 0x1000, /* execute access flag */
- ace_flg_ctf = 0x0800, /* control access flag */
-
- fdr_fl1_sec = 0x8000, /* file secured flag */
-
- fdr_flg_fu = 0xc000, /* file usage bits */
- fdr_flg_fu_shift = 14,
- fdr_flg_fmt = 0x3000, /* file format bits */
- fdr_flg_fmt_shift = 12,
- fdr_flg_all = 0x0800, /* extendable file flag */
- fdr_flg_ft = 0x0600, /* file type bits */
- fdr_flg_ft_shift = 9,
- fdr_flg_wpb = 0x0100, /* write protect bit */
- fdr_flg_dpb = 0x0080, /* delete protect bit */
- fdr_flg_tmp = 0x0040, /* temporary file flag */
- fdr_flg_blb = 0x0020, /* blocked file flag */
- fdr_flg_ali = 0x0010, /* alias flag bit */
- fdr_flg_fwt = 0x0008, /* forced write / partial logging */
- fdr_flg_cdr = 0x0001 /* record is CDR */
-};
-
-/*
- ACE subrecord found in FDR
-*/
-struct ti990_ace
-{
- char agn[8]; /* access group name */
- UINT16BE flg; /* flags */
-};
-
-/*
- FDR record
-*/
-struct ti990_fdr
-{
- UINT16BE hkc; /* hask key count: the number of file descriptor records that are present in the directory that hashed to this record number */
- UINT16BE hkv; /* hask key value: the result of the hash algorithm for the file name actually covered in this record */
- char fnm[8]; /* file name */
- UINT8 rsv[2]; /* reserved */
- UINT16BE fl1; /* flags word 1 */
- UINT16BE flg; /* flags word 2 */
- UINT16BE prs; /* physical record size */
- UINT16BE lrs; /* logical record size */
- UINT16BE pas; /* primary allocation size: # of ADUs allocated in primary allocation block? */
- UINT16BE paa; /* primary allocation address: first ADU of primary allocation block? */
- UINT16BE sas; /* secondary allocation size: used to determinate the # of blocks allocated per secondary allocation */
- UINT16BE saa; /* offset of secondary table: ???? "offset into this FDR of the secondary allocation table, if any. No secondary allocation table is denoted by 0. Secondary allocations are present only for unbounded files." */
- UINT16BE rfa; /* record number of first alias */
- UINT32BE eom; /* end of medium record number */
- UINT32BE bkm; /* end of medium block number */
- UINT16BE ofm; /* end of medium offset / */
- /* prelog number for KIF */
- UINT32BE fbq; /* free block queue head */
- UINT16BE btr; /* B-tree roots block # */
- UINT32BE ebq; /* empty block queue head */
- UINT16BE kdr; /* key descriptions record # */
- UINT8 ud[6]; /* last update date */
- UINT8 cd[6]; /* creation date */
- UINT8 apb; /* ADU's per block */
- UINT8 bpa; /* blocks per ADU */
- UINT16BE mrs; /* minimumu KIF record size */
- UINT8 sat[64]; /* secondary allocation table: 16 2-word entries. The first word of an entry contains the size, in ADUs, of the secondary allocation. The second word contains the starting ADU of the allocation. */
-
-/* bytes >86 to >100 are optional */
- UINT8 res[10]; /* reserved: seem to be actually meaningful (at least under DX10 3.6.x) */
- char uid[8]; /* user id of file creator */
- UINT16BE psa; /* public security attribute */
- ti990_ace ace[9]; /* 9 access control entries */
- UINT8 fil[2]; /* not used */
-};
-
-/*
- ADR record: variant of FDR for Aliases
-
- The fields marked here with *** are in the ADR template to maintain
- compatability with the FDR template.
-*/
-struct ti990_adr
-{
- UINT16BE hkc; /* hask key count */
- UINT16BE hkv; /* hask key value */
- char fnm[8]; /* file name */
- char psw[4]; /* "password" (whatever it means) */
- UINT16BE flg; /* flags (same as fdr.flg) */
- UINT16BE fill00; /* *** physical record size */
- UINT16BE fill01; /* *** logical record size */
- UINT16BE fill02; /* *** primary allocation size */
- UINT16BE fill03; /* *** primary allocation address */
- UINT16BE fill04; /* *** secondary allocation size */
- UINT16BE fill05; /* *** secondary allocation address */
- UINT16BE rna; /* record number of next ADR */
- UINT16BE raf; /* record # of actual FDR (from 1 through dor.nrc) */
-};
-
-/*
- CDR record: variant of FDR for Channel
-
- The CDR is the permanent record of a channel. It is carried as an alias
- of the program file in which the channel owner task resides.
-*/
-struct ti990_cdr
-{
- UINT16BE hkc; /* hask key count */
- UINT16BE hkv; /* hask key value */
- char fnm[8]; /* file name */
- UINT16BE fill00; /* reserved */
- UINT16BE fill01; /* reserved */
- UINT16BE fdf; /* flags (same as fdr.flg) */
- UINT8 flg; /* channel flzgs */
- UINT8 iid; /* owner task installed ID */
- UINT8 typ; /* default resource type */
- UINT8 tf; /* resource type flags */
- UINT16BE mxl; /* maximum message length */
- UINT8 fill04[6]; /* reserved (and, no, I don't know where fill02 and fill03 have gone) */
- UINT16BE rna; /* record number of next CDR or ADR */
- UINT16BE raf; /* record # of actual FDR */
- UINT8 fill05[110]; /* reserved */
- char uid[8]; /* user ID of channel creator */
- UINT16BE psa; /* public security attribute */
- UINT8 scg[94]; /* "SDT with 9 control groups" (whatever it means - and, no, 94 is not dividable by 9) */
- UINT8 fill06[8]; /* reserved */
-};
-
-/*
- Based on contents of the flags field, catalog entries may be either an FDR,
- an ADR or a CDR.
-
- They may be a KDR, too, but confusion is impossible because the KDR FILL00
- field starts at offset 4, and therefore if we try to interpret a KDR as an
- FDR (or ADR, CDR), we will find fnm[0] and assume the FDR is empty.
-*/
-union directory_entry
-{
- ti990_fdr fdr;
- ti990_adr adr;
- ti990_cdr cdr;
-};
-
-#if 0
-
-/*
- tifile header: stand-alone file
-*/
-struct tifile_header
-{
- char tifiles[8]; /* always '\7TIFILES' */
- UINT8 secsused_MSB; /* file length in sectors (big-endian) */
- UINT8 secsused_LSB;
- UINT8 flags; /* see enum above */
- UINT8 recspersec; /* records per sector */
- UINT8 eof; /* current position of eof in last sector (0->255)*/
- UINT8 reclen; /* bytes per record ([1,255] 0->256) */
- UINT8 fixrecs_MSB; /* file length in records (big-endian) */
- UINT8 fixrecs_LSB;
- UINT8 res[128-16]; /* reserved */
-};
-
-
-/*
- catalog entry (used for in-memory catalog)
-*/
-struct catalog_entry
-{
- UINT16 fdr_secnum;
- char filename[10];
-};
-
-#endif
-
-/*
- Disk geometry
-*/
-struct ti990_geometry
-{
- unsigned int cylinders, heads, sectors_per_track, bytes_per_sector;
-};
-
-/*
- Physical sector address
-*/
-struct ti990_phys_sec_address
-{
- int cylinder;
- int head;
- int sector;
-};
-
-/*
- ti99 disk image descriptor
-*/
-struct ti990_image
-{
- imgtool_stream *file_handle; /* imgtool file handle */
- ti990_geometry geometry; /* geometry */
- ti990_sc0 sec0; /* cached copy of sector 0 */
-};
-
-/*
- ti990 catalog iterator, used when imgtool reads the catalog
-*/
-struct ti990_iterator
-{
- ti990_image *image;
- int level; /* current recursion level */
- int nrc[MAX_DIR_LEVEL]; /* length of disk catalogs in records */
- int index[MAX_DIR_LEVEL]; /* current index in the disk catalog */
- directory_entry xdr[MAX_DIR_LEVEL]; /* fdr records */
-};
-
-
-static imgtoolerr_t ti990_image_init(imgtool_image *img, imgtool_stream *f);
-static void ti990_image_exit(imgtool_image *img);
-static void ti990_image_info(imgtool_image *img, char *string, size_t len);
-static imgtoolerr_t ti990_image_beginenum(imgtool_directory *enumeration, const char *path);
-static imgtoolerr_t ti990_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent);
-static void ti990_image_closeenum(imgtool_directory *enumeration);
-static imgtoolerr_t ti990_image_freespace(imgtool_partition *partition, UINT64 *size);
-#ifdef UNUSED_FUNCTION
-static imgtoolerr_t ti990_image_readfile(imgtool_partition *partition, const char *fpath, imgtool_stream *destf);
-static imgtoolerr_t ti990_image_writefile(imgtool_partition *partition, const char *fpath, imgtool_stream *sourcef, option_resolution *writeoptions);
-static imgtoolerr_t ti990_image_deletefile(imgtool_partition *partition, const char *fpath);
-#endif
-static imgtoolerr_t ti990_image_create(imgtool_image *image, imgtool_stream *f, option_resolution *createoptions);
-
-enum
-{
- /*ti990_createopts_volname = 'A',*/
- ti990_createopts_cylinders = 'B',
- ti990_createopts_heads = 'C',
- ti990_createopts_sectors = 'D',
- ti990_createopts_sectorsize = 'E'
-};
-
-static OPTION_GUIDE_START( ti990_create_optionguide )
- /*OPTION_STRING(ti990_createopts_volname, "label", "Volume name" )*/
- OPTION_INT(ti990_createopts_cylinders, "cylinders", "Cylinders" )
- OPTION_INT(ti990_createopts_heads, "heads", "Heads" )
- OPTION_INT(ti990_createopts_sectors, "sectors", "Sectors" )
- OPTION_INT(ti990_createopts_sectorsize, "bytes per sector (typically 256)", "Bytes Per Sector" )
-OPTION_GUIDE_END
-
-#define symb2str2(a) #a
-#define symb2str(a) symb2str2(a)
-#define ti990_create_optionspecs "B1-[145]-" symb2str(MAX_CYLINDERS)";C1-[4]-" symb2str(MAX_HEADS)";D1-[32]-" symb2str(MAX_SECTORS_PER_TRACK)";E" symb2str(MIN_SECTOR_SIZE)"-[256]-" symb2str(MAX_SECTOR_SIZE)";"
-
-void ti990_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo *info)
-{
- switch(state)
- {
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "ti990hd"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "TI990 Hard Disk"); break;
- case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "hd"); break;
- case IMGTOOLINFO_STR_EOLN: /* strcpy(info->s = imgtool_temp_str(), "\r"); */ break;
-
- case IMGTOOLINFO_PTR_OPEN: info->open = ti990_image_init; break;
- case IMGTOOLINFO_PTR_CLOSE: info->close = ti990_image_exit; break;
- case IMGTOOLINFO_PTR_INFO: info->info = ti990_image_info; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = ti990_image_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = ti990_image_nextenum; break;
- case IMGTOOLINFO_PTR_CLOSE_ENUM: info->close_enum = ti990_image_closeenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = ti990_image_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: /* info->read_file = ti990_image_readfile; */ break;
- case IMGTOOLINFO_PTR_WRITE_FILE: /* info->write_file = ti990_image_writefile; */ break;
- case IMGTOOLINFO_PTR_DELETE_FILE: /* info->delete_file = ti990_image_deletefile; */ break;
- case IMGTOOLINFO_PTR_CREATE: info->create = ti990_image_create; break;
-
- case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = ti990_create_optionguide; break;
- case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), ti990_create_optionspecs); break;
- }
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- Convert a C string to a 8-character file name (padded with spaces if necessary)
-*/
-static void str_to_fname(char dst[8], const char *src)
-{
- int i;
-
-
- i = 0;
-
- /* copy 8 characters at most */
- if (src)
- while ((i<8) && (src[i]!='\0'))
- {
- dst[i] = src[i];
- i++;
- }
-
- /* pad with spaces */
- while (i<8)
- {
- dst[i] = ' ';
- i++;
- }
-}
-#endif
-
-/*
- Convert a 8-character file name to a C string (removing trailing spaces if necessary)
-*/
-static void fname_to_str(char *dst, const char src[8], int n)
-{
- int i;
- int last_nonspace;
-
-
- /* copy 8 characters at most */
- if (--n > 8)
- n = 8;
-
- /* copy filename */
- i = 0;
- last_nonspace = -1;
-
- while (i<n)
- {
- dst[i] = src[i];
- if (src[i] != ' ')
- last_nonspace = i;
- i++;
- }
-
- /* terminate with '\0' */
- dst[last_nonspace+1] = '\0';
-}
-
-#if 0
-#pragma mark -
-#pragma mark DISK ROUTINES
-#endif
-
-/*
- Convert physical sector address to offset
-*/
-static unsigned phys_address_to_offset(const ti990_phys_sec_address *address, const ti990_geometry *geometry)
-{
- unsigned offset;
-
- /* current MESS format */
- offset = (((address->cylinder*geometry->heads) + address->head)*geometry->sectors_per_track + address->sector)*geometry->bytes_per_sector + header_len;
-
- return offset;
-}
-
-/*
- Read one sector from a disk image
-
- file_handle: imgtool file handle
- address: physical sector address
- geometry: disk geometry (sectors per track, tracks per side, sides)
- dest: pointer to destination buffer
- len: length of data to read
-*/
-static int read_sector_physical_len(imgtool_stream *file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, void *dest, int len)
-{
- int reply;
-
- if (len > geometry->bytes_per_sector)
- return 1;
-
- /* seek to sector */
- reply = stream_seek(file_handle, phys_address_to_offset(address, geometry), SEEK_SET);
- if (reply)
- return 1;
- /* read it */
- reply = stream_read(file_handle, dest, len);
- if (reply != len)
- return 1;
-
- return 0;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- Read one sector from a disk image
-
- file_handle: imgtool file handle
- address: physical sector address
- geometry: disk geometry (sectors per track, tracks per side, sides)
- dest: pointer to a destination buffer of geometry->bytes_per_sector bytes
-*/
-static int read_sector_physical(imgtool_stream *file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, void *dest)
-{
- return read_sector_physical_len(file_handle, address, geometry, dest, geometry->bytes_per_sector);
-}
-#endif
-
-/*
- Write one sector to a disk image
-
- file_handle: imgtool file handle
- address: physical sector address
- geometry: disk geometry (sectors per track, tracks per side, sides)
- src: pointer to source buffer
- len: length of source buffer
-*/
-static int write_sector_physical_len(imgtool_stream *file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, const void *src, int len)
-{
- int reply;
-
- if (len > geometry->bytes_per_sector)
- return 1;
-
- /* seek to sector */
- reply = stream_seek(file_handle, phys_address_to_offset(address, geometry), SEEK_SET);
- if (reply)
- return 1;
- /* write it */
- reply = stream_write(file_handle, src, len);
- if (reply != len)
- return 1;
- /* pad with 0s if needed */
- if (len < geometry->bytes_per_sector)
- {
- reply = stream_fill(file_handle, 0, geometry->bytes_per_sector - len);
-
- if (reply != geometry->bytes_per_sector - len)
- return 1;
- }
-
- return 0;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- Write one sector to a disk image
-
- file_handle: imgtool file handle
- address: physical sector address
- geometry: disk geometry (sectors per track, tracks per side, sides)
- dest: pointer to a source buffer of geometry->bytes_per_sector bytes
-*/
-static int write_sector_physical(imgtool_stream *file_handle, const ti990_phys_sec_address *address, const ti990_geometry *geometry, const void *src)
-{
- return write_sector_physical_len(file_handle, address, geometry, src, geometry->bytes_per_sector);
-}
-#endif
-
-/*
- Convert logical sector address to physical sector address
-*/
-static void log_address_to_phys_address(int secnum, const ti990_geometry *geometry, ti990_phys_sec_address *address)
-{
- address->sector = secnum % geometry->sectors_per_track;
- secnum /= geometry->sectors_per_track;
- address->head = secnum % geometry->heads;
- address->cylinder = secnum / geometry->heads;
-}
-
-/*
- Read one sector from a disk image
-
- file_handle: imgtool file handle
- secnum: logical sector address
- geometry: disk geometry (sectors per track, tracks per side, sides)
- dest: pointer to destination buffer
- len: length of data to read
-*/
-static int read_sector_logical_len(imgtool_stream *file_handle, int secnum, const ti990_geometry *geometry, void *dest, int len)
-{
- ti990_phys_sec_address address;
-
-
- log_address_to_phys_address(secnum, geometry, &address);
-
- return read_sector_physical_len(file_handle, &address, geometry, dest, len);
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- Read one sector from a disk image
-
- file_handle: imgtool file handle
- secnum: logical sector address
- geometry: disk geometry (sectors per track, tracks per side, sides)
- dest: pointer to a destination buffer of geometry->bytes_per_sector bytes
-*/
-static int read_sector_logical(imgtool_stream *file_handle, int secnum, const ti990_geometry *geometry, void *dest)
-{
- return read_sector_logical_len(file_handle, secnum, geometry, dest, geometry->bytes_per_sector);
-}
-#endif
-
-/*
- Write one sector to a disk image
-
- file_handle: imgtool file handle
- secnum: logical sector address
- geometry: disk geometry (sectors per track, tracks per side, sides)
- src: pointer to source buffer
- len: length of source buffer
-*/
-static int write_sector_logical_len(imgtool_stream *file_handle, int secnum, const ti990_geometry *geometry, const void *src, int len)
-{
- ti990_phys_sec_address address;
-
-
- log_address_to_phys_address(secnum, geometry, &address);
-
- return write_sector_physical_len(file_handle, &address, geometry, src, len);
-}
-
-/*
- Write one sector to a disk image
-
- file_handle: imgtool file handle
- secnum: logical sector address
- geometry: disk geometry (sectors per track, tracks per side, sides)
- dest: pointer to a source buffer of geometry->bytes_per_sector bytes
-*/
-static int write_sector_logical(imgtool_stream *file_handle, int secnum, const ti990_geometry *geometry, const void *src)
-{
- return write_sector_logical_len(file_handle, secnum, geometry, src, geometry->bytes_per_sector);
-}
-
-#if 0
-#pragma mark -
-#pragma mark CATALOG FILE ROUTINES
-#endif
-
-#ifdef UNUSED_FUNCTION
-/*
- Find the catalog entry and fdr record associated with a file name
-
- image: ti990_image image record
- fpath: path of the file to search
- fdr: pointer to buffer where the fdr record should be stored (may be NULL)
- catalog_index: on output, index of file catalog entry (may be NULL)
- out_fdr_secnum: on output, sector address of the fdr (may be NULL)
- out_parent_fdr_secnum: on output, sector offset of the fdr for the parent
- directory fdr (-1 if root) (may be NULL)
-*/
-static int find_fdr(ti990_image *image, const char fpath[MAX_PATH_LEN+1], int *catalog_index, int *out_fdr_secnum, int *out_parent_fdr_secnum)
-{
- int fdr_secnum = -1, parent_fdr_secnum;
- int i;
- const char *element_start, *element_end;
- int element_len;
- char element[8];
- ti990_dor dor;
- directory_entry xdr;
- int hash_key;
- int nrc;
- unsigned base;
- int reply;
- int flag;
-
-
- base = (unsigned) get_UINT16BE(image->sec0.vda) * get_UINT16BE(image->sec0.spa);
-
- element_start = fpath;
- do
- {
- /* read directory header */
- reply = read_sector_logical_len(image->file_handle, base, & image->geometry, &dor, sizeof(dor));
- if (reply)
- return IMGTOOLERR_READERROR;
-
- nrc = get_UINT16BE(dor.nrc);
-
- /* find next path element */
- element_end = strchr(element_start, '.');
- element_len = element_end ? (element_end - element_start) : strlen(element_start);
- if ((element_len > 8) || (element_len == 0))
- return IMGTOOLERR_BADFILENAME;
- /* generate file name and hash key */
- hash_key = 1;
- for (i=0; i<element_len; i++)
- {
- element[i] = element_start[i];
- hash_key = ((hash_key * (unsigned char) element_start[i]) % nrc) + 1;
- }
- while (i<8)
- {
- element[i] = ' ';
- i++;
- }
-
- /* search entry in directory */
- i = hash_key;
- while (1)
- {
- reply = read_sector_logical_len(image->file_handle, base + i, & image->geometry,
- & xdr, 0x86);
- if (reply)
- return IMGTOOLERR_READERROR;
- if (!memcmp(element, xdr.fdr.fnm, 8))
- { /* found match !!! */
- parent_fdr_secnum = fdr_secnum;
- fdr_secnum = base + i;
- break;
- }
-
- /* next record */
- if (i != nrc)
- i++;
- else
- i = 1;
-
- /* exit if we have tested every record */
- if (i == hash_key)
- return IMGTOOLERR_FILENOTFOUND;
- }
-
- /* iterate */
- if (element_end)
- {
- element_start = element_end+1;
- /* we need to check that this is a directory */
- /* if it is an alias to a directory, we need to follow it, too. */
-
- /* parse flags */
- flag = get_UINT16BE(xdr.fdr.flg);
-
- if (flag & fdr_flg_ali)
- {
- /* read original fdr */
- reply = read_sector_logical_len(image->file_handle, base + get_UINT16BE(xdr.adr.raf),
- & image->geometry, & xdr, 0x86);
-
- flag = get_UINT16BE(xdr.fdr.flg);
- }
-
- if (flag & fdr_flg_cdr)
- /* This is a channel, not a file */
- return IMGTOOLERR_BADFILENAME;
- else if (flag & fdr_flg_ali)
- /* WTH??? */
- return IMGTOOLERR_CORRUPTIMAGE;
- else if (((flag >> fdr_flg_fu_shift) & 3) != 1)
- {
- /* This file is not a directory */
- return IMGTOOLERR_BADFILENAME;
- }
-
- /* initialize base */
- base = (unsigned) get_UINT16BE(xdr.fdr.paa) * get_UINT16BE(image->sec0.spa);
- }
- else
- element_start = NULL;
- }
- while (element_start);
-
- if (catalog_index)
- *catalog_index = i;
-
- if (out_fdr_secnum)
- *out_fdr_secnum = fdr_secnum;
-
- if (out_parent_fdr_secnum)
- *out_parent_fdr_secnum = parent_fdr_secnum;
-
- return 0;
-}
-#endif
-
-#if 0
-/*
- Allocate one sector on disk, for use as a fdr record
-
- image: ti99_image image record
- fdr_secnum: on output, logical address of a free sector
-*/
-static int alloc_fdr_sector(ti99_image *image, int *fdr_secnum)
-{
- int totsecs = (image->sec0.totsecsMSB << 8) | image->sec0.totsecsLSB;
- int i;
-
-
- for (i=0; i<totsecs; i++)
- {
- if (! (image->sec0.abm[i >> 3] & (1 << (i & 7))))
- {
- *fdr_secnum = i;
- image->sec0.abm[i >> 3] |= 1 << (i & 7);
-
- return 0;
- }
- }
-
- return IMGTOOLERR_NOSPACE;
-}
-
-/*
- Extend a file with nb_alloc_sectors extra sectors
-
- image: ti99_image image record
- fdr: file fdr record
- nb_alloc_sectors: number of sectors to allocate
-*/
-static int alloc_file_sectors(ti99_image *image, ti99_fdr *fdr, int nb_alloc_sectors)
-{
- int totsecs = (image->sec0.totsecsMSB << 8) | image->sec0.totsecsLSB;
- int free_sectors;
- int secsused;
- int i;
- int lnks_index;
- int cur_sec, last_sec, p_last_sec;
- int cur_block_len, cur_block_start;
- int first_best_block_len, first_best_block_start = 0;
- int second_best_block_len, second_best_block_start = 0;
- int search_start;
-
- /* compute free space */
- free_sectors = 0;
- for (i=0; i<totsecs; i++)
- {
- if (! (image->sec0.abm[i >> 3] & (1 << (i & 7))))
- free_sectors++;
- }
-
- /* check we have enough free space */
- if (free_sectors < nb_alloc_sectors)
- return IMGTOOLERR_NOSPACE;
-
- /* current number of data sectors in file */
- secsused = get_fdr_secsused(fdr);
-
- if (secsused == 0)
- { /* links array must be empty */
- lnks_index = 0;
- }
- else
- { /* try to extend last block */
- last_sec = -1;
- for (lnks_index=0; lnks_index<76; lnks_index++)
- {
- p_last_sec = last_sec;
- last_sec = (fdr->lnks[lnks_index][2] << 4) | (fdr->lnks[lnks_index][1] >> 4);
- if (last_sec >= (secsused-1))
- break;
- }
- if (lnks_index == 76)
- /* that sucks */
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (last_sec > (secsused-1))
- { /* some extra space has already been allocated */
- cur_block_len = last_sec - (secsused-1);
- if (cur_block_len > nb_alloc_sectors)
- cur_block_len = nb_alloc_sectors;
-
- secsused += cur_block_len;
- set_fdr_secsused(fdr, secsused);
- nb_alloc_sectors -= cur_block_len;
- if (! nb_alloc_sectors)
- return 0; /* done */
- }
-
- /* block base */
- cur_sec = ((fdr->lnks[lnks_index][1] & 0xf) << 8) | fdr->lnks[lnks_index][0];
- /* point past block end */
- cur_sec += last_sec-p_last_sec;
- /* count free sectors after last block */
- cur_block_len = 0;
- for (i=cur_sec; (! (image->sec0.abm[i >> 3] & (1 << (i & 7)))) && (cur_block_len < nb_alloc_sectors) && (i < totsecs); i++)
- cur_block_len++;
- if (cur_block_len)
- { /* extend last block */
- secsused += cur_block_len;
- set_fdr_secsused(fdr, secsused);
- last_sec += cur_block_len;
- nb_alloc_sectors -= cur_block_len;
- fdr->lnks[lnks_index][1] = (fdr->lnks[lnks_index][1] & 0x0f) | (last_sec << 4);
- fdr->lnks[lnks_index][2] = last_sec >> 4;
- for (i=0; i<cur_block_len; i++)
- image->sec0.abm[(i+cur_sec) >> 3] |= 1 << ((i+cur_sec) & 7);
- if (! nb_alloc_sectors)
- return 0; /* done */
- }
- lnks_index++;
- if (lnks_index == 76)
- /* that sucks */
- return IMGTOOLERR_NOSPACE;
- }
-
- search_start = image->data_offset; /* initially, search for free space only in data space */
- while (nb_alloc_sectors)
- {
- /* find smallest data block at least nb_alloc_sectors in length, and largest data block less than nb_alloc_sectors in length */
- first_best_block_len = INT_MAX;
- second_best_block_len = 0;
- for (i=search_start; i<totsecs; i++)
- {
- if (! (image->sec0.abm[i >> 3] & (1 << (i & 7))))
- { /* found one free block */
- /* compute its length */
- cur_block_start = i;
- cur_block_len = 0;
- while ((i<totsecs) && (! (image->sec0.abm[i >> 3] & (1 << (i & 7)))))
- {
- cur_block_len++;
- i++;
- }
- /* compare to previous best and second-best blocks */
- if ((cur_block_len < first_best_block_len) && (cur_block_len >= nb_alloc_sectors))
- {
- first_best_block_start = cur_block_start;
- first_best_block_len = cur_block_len;
- if (cur_block_len == nb_alloc_sectors)
- /* no need to search further */
- break;
- }
- else if ((cur_block_len > second_best_block_len) && (cur_block_len < nb_alloc_sectors))
- {
- second_best_block_start = cur_block_start;
- second_best_block_len = cur_block_len;
- }
- }
- }
-
- if (first_best_block_len != INT_MAX)
- { /* found one contiguous block which can hold it all */
- secsused += nb_alloc_sectors;
- set_fdr_secsused(fdr, secsused);
-
- fdr->lnks[lnks_index][0] = first_best_block_start;
- fdr->lnks[lnks_index][1] = ((first_best_block_start >> 8) & 0x0f) | ((secsused-1) << 4);
- fdr->lnks[lnks_index][2] = (secsused-1) >> 4;
- for (i=0; i<nb_alloc_sectors; i++)
- image->sec0.abm[(i+first_best_block_start) >> 3] |= 1 << ((i+first_best_block_start) & 7);
-
- nb_alloc_sectors = 0;
- }
- else if (second_best_block_len != 0)
- { /* jeez, we need to fragment it. We use the largest smaller block to limit fragmentation. */
- secsused += second_best_block_len;
- set_fdr_secsused(fdr, secsused);
-
- fdr->lnks[lnks_index][0] = second_best_block_start;
- fdr->lnks[lnks_index][1] = ((second_best_block_start >> 8) & 0x0f) | ((secsused-1) << 4);
- fdr->lnks[lnks_index][2] = (secsused-1) >> 4;
- for (i=0; i<second_best_block_len; i++)
- image->sec0.abm[(i+second_best_block_start) >> 3] |= 1 << ((i+second_best_block_start) & 7);
-
- nb_alloc_sectors -= second_best_block_len;
-
- lnks_index++;
- if (lnks_index == 76)
- /* that sucks */
- return IMGTOOLERR_NOSPACE;
- }
- else if (search_start != 0)
- { /* we did not find any free sector in the data section of the disk */
- search_start = 0; /* time to fall back to fdr space */
- }
- else
- return IMGTOOLERR_NOSPACE; /* This should never happen, as we pre-check that there is enough free space */
- }
-
- return 0;
-}
-
-/*
- Allocate a new (empty) file
-*/
-static int new_file(ti99_image *image, char filename[10], int *out_fdr_secnum/*, ti99_fdr *fdr,*/)
-{
- int fdr_secnum;
- int catalog_index, i;
- int reply = 0;
-
-
- /* find insertion point in catalog */
- i = 0;
- if ((image->catalog[0].fdr_secnum == 0) && (image->catalog[1].fdr_secnum != 0))
- i = 1; /* skip empty entry 0 (it must be a non-listable catalog) */
-
- for (; (i<128) && ((fdr_secnum = image->catalog[i].fdr_secnum) != 0) && ((reply = memcmp(image->catalog[i].filename, filename, 10)) < 0); i++)
- ;
-
- if (i == 128)
- /* catalog is full */
- return IMGTOOLERR_NOSPACE;
- else if (fdr_secnum && (reply == 0))
- /* file already exists */
- return IMGTOOLERR_BADFILENAME;
- else
- {
- catalog_index = i;
- reply = alloc_fdr_sector(image, &fdr_secnum);
- if (reply)
- return reply;
-
- /* look for first free entry in catalog */
- for (i=catalog_index; image->catalog[i].fdr_secnum != 0; i++)
- ;
-
- if (i == 128)
- /* catalog is full */
- return IMGTOOLERR_NOSPACE;
-
- /* shift catalog entries until the insertion point */
- for (/*i=127*/; i>catalog_index; i--)
- image->catalog[i] = image->catalog[i-1];
-
- /* write new catalog entry */
- image->catalog[catalog_index].fdr_secnum = fdr_secnum;
- memcpy(image->catalog[catalog_index].filename, filename, 10);
- if (out_fdr_secnum)
- *out_fdr_secnum = fdr_secnum;
- }
-
- return 0;
-}
-
-/*
- Compare two (possibly empty) catalog entry for qsort
-*/
-static int qsort_catalog_compare(const void *p1, const void *p2)
-{
- const catalog_entry *entry1 = p1;
- const catalog_entry *entry2 = p2;
-
- if ((entry1->fdr_secnum == 0) && (entry2->fdr_secnum == 0))
- return 0;
- else if (entry1->fdr_secnum == 0)
- return +1;
- else if (entry2->fdr_secnum == 0)
- return -1;
- else
- return memcmp(entry1->filename, entry2->filename, 10);
-}
-#endif
-
-/*
- Open a file as a ti990_image.
-*/
-static imgtoolerr_t ti990_image_init(imgtool_image *img, imgtool_stream *f)
-{
- ti990_image *image = (ti990_image *) imgtool_image_extra_bytes(img);
- disk_image_header header;
- int reply;
- unsigned totsecs;
-
- image->file_handle = f;
- reply = stream_read(f, &header, sizeof(header));
- if (reply != sizeof(header))
- return IMGTOOLERR_READERROR;
-
- image->geometry.cylinders = get_UINT32BE(header.cylinders);
- image->geometry.heads = get_UINT32BE(header.heads);
- image->geometry.sectors_per_track = get_UINT32BE(header.sectors_per_track);
- image->geometry.bytes_per_sector = get_UINT32BE(header.bytes_per_sector);
-
- totsecs = image->geometry.cylinders*image->geometry.heads*image->geometry.sectors_per_track;
-
- if ((image->geometry.bytes_per_sector < MIN_SECTOR_SIZE)
- || (image->geometry.bytes_per_sector > MAX_SECTOR_SIZE)
- || (image->geometry.sectors_per_track > MAX_SECTORS_PER_TRACK)
- || (image->geometry.heads > MAX_HEADS)
- || (image->geometry.cylinders > MAX_CYLINDERS)
- || (totsecs < 1)
- || (stream_size(f) != header_len + totsecs*image->geometry.bytes_per_sector))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- {
- ti990_phys_sec_address address = { 0, 0, 0 };
- reply = read_sector_physical_len(f, &address, &image->geometry, & image->sec0, sizeof(image->sec0));
- }
- if (reply)
- {
- return IMGTOOLERR_READERROR;
- }
-
- if ((get_UINT16BE(image->sec0.tna)*get_UINT16BE(image->sec0.spa) > totsecs)
- || ((get_UINT16BE(image->sec0.spa) != 1) && (get_UINT16BE(image->sec0.spa) % 3)))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- if ((get_UINT16BE(image->sec0.vpl) != 0x86) && (get_UINT16BE(image->sec0.vpl) != 0x100))
- {
- return IMGTOOLERR_CORRUPTIMAGE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- close a ti990_image
-*/
-static void ti990_image_exit(imgtool_image *img)
-{
- ti990_image *image = (ti990_image *) imgtool_image_extra_bytes(img);
- stream_close(image->file_handle);
-}
-
-/*
- get basic information on a ti990_image
-
- Currently returns the volume name
-*/
-static void ti990_image_info(imgtool_image *img, char *string, size_t len)
-{
- ti990_image *image = (ti990_image *) imgtool_image_extra_bytes(img);
- char vol_name[9];
-
- fname_to_str(vol_name, image->sec0.vnm, 9);
-
- snprintf(string, len, "%s", vol_name);
-}
-
-/*
- Open the disk catalog for enumeration
-*/
-static imgtoolerr_t ti990_image_beginenum(imgtool_directory *enumeration, const char *path)
-{
- ti990_image *image = (ti990_image *) imgtool_image_extra_bytes(imgtool_directory_image(enumeration));
- ti990_iterator *iter = (ti990_iterator *) imgtool_directory_extrabytes(enumeration);
- ti990_dor dor;
- int reply;
-
- iter->image = image;
-
- reply = read_sector_logical_len(iter->image->file_handle,
- (unsigned) get_UINT16BE(iter->image->sec0.vda) * get_UINT16BE(iter->image->sec0.spa),
- & iter->image->geometry, &dor, sizeof(dor));
-
- if (reply)
- return IMGTOOLERR_READERROR;
-
- iter->level = 0;
- iter->nrc[0] = get_UINT16BE(dor.nrc);
- iter->index[0] = 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*
- Enumerate disk catalog next entry
-*/
-static imgtoolerr_t ti990_image_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- ti990_iterator *iter = (ti990_iterator *) imgtool_directory_extrabytes(enumeration);
- int flag;
- int reply = 0;
-
-
- ent->corrupt = 0;
- ent->eof = 0;
-
- while ((iter->level >= 0)
- && (! (reply = read_sector_logical_len(iter->image->file_handle,
- iter->level ? (unsigned) get_UINT16BE(iter->xdr[iter->level-1].fdr.paa) * get_UINT16BE(iter->image->sec0.spa) + (iter->index[iter->level]+1)
- : (unsigned) get_UINT16BE(iter->image->sec0.vda) * get_UINT16BE(iter->image->sec0.spa) + (iter->index[iter->level]+1),
- & iter->image->geometry, &iter->xdr[iter->level],
- iter->level ? get_UINT16BE(iter->xdr[iter->level-1].fdr.prs)
- : get_UINT16BE(iter->image->sec0.vpl))))
- && (iter->xdr[iter->level].fdr.fnm[0] == 0))
- {
- iter->index[iter->level]++;
- while (iter->index[iter->level] >= iter->nrc[iter->level])
- iter->level--;
- }
-
- if (iter->level < 0)
- {
- ent->eof = 1;
- }
- else if (reply)
- return IMGTOOLERR_READERROR;
- else
- {
-#if 0
- fname_to_str(ent->filename, iter->xdr[iter->level].fdr.fnm, ARRAY_LENGTH(ent->filename));
-#else
- {
- int i;
- char buf[9];
-
- ent->filename[0] = '\0';
- for (i=0; i<iter->level; i++)
- {
- fname_to_str(buf, iter->xdr[i].fdr.fnm, 9);
- strncat(ent->filename, buf, ARRAY_LENGTH(ent->filename) - 1);
- strncat(ent->filename, ".", ARRAY_LENGTH(ent->filename) - 1);
- }
- fname_to_str(buf, iter->xdr[iter->level].fdr.fnm, 9);
- strncat(ent->filename, buf, ARRAY_LENGTH(ent->filename) - 1);
- }
-#endif
-
- /* parse flags */
- flag = get_UINT16BE(iter->xdr[iter->level].fdr.flg);
- if (flag & fdr_flg_cdr)
- {
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "CHANNEL");
-
- ent->filesize = 0;
- }
- else if (flag & fdr_flg_ali)
- {
- ti990_fdr target_fdr;
- char buf[9];
-
- reply = read_sector_logical_len(iter->image->file_handle,
- iter->level ? ((unsigned) get_UINT16BE(iter->xdr[iter->level-1].fdr.paa) * get_UINT16BE(iter->image->sec0.spa) + get_UINT16BE(iter->xdr[iter->level].adr.raf))
- : ((unsigned) get_UINT16BE(iter->image->sec0.vda) * get_UINT16BE(iter->image->sec0.spa) + get_UINT16BE(iter->xdr[iter->level].adr.raf)),
- & iter->image->geometry, &target_fdr,
- iter->level ? get_UINT16BE(iter->xdr[iter->level-1].fdr.prs)
- : get_UINT16BE(iter->image->sec0.vpl));
-
- fname_to_str(buf, target_fdr.fnm, 9);
-
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "ALIAS OF %s", buf);
-
- ent->filesize = 0;
- }
- else
- {
- const char *fmt, *type;
-
- switch ((flag >> fdr_flg_fmt_shift) & 3)
- {
- case 0:
- fmt = "NBS";
- break;
- case 1:
- fmt = "BS ";
- break;
- default:
- fmt = "???";
- break;
- }
-
- switch ((flag >> fdr_flg_fu_shift) & 3)
- {
- case 1:
- type = "DIR";
- break;
- case 2:
- type = "PRO";
- break;
- case 3:
- type = "IMG";
- break;
- default:
- switch ((flag >> fdr_flg_ft_shift) & 3)
- {
- case 1:
- type = "SEQ";
- break;
- case 2:
- type = "REL";
- break;
- case 3:
- type = "KIF";
- break;
- default:
- type = "???";
- break;
- }
- break;
- }
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr),
- "%s %c %s%s%s%s%s", fmt, (flag & fdr_flg_all) ? 'N' : 'C', type,
- (flag & fdr_flg_blb) ? "" : " BLK",
- (flag & fdr_flg_tmp) ? " TMP" : "",
- (flag & fdr_flg_wpb) ? " WPT" : "",
- (flag & fdr_flg_dpb) ? " DPT" : "");
-
- /* len in blocks */
- ent->filesize = get_UINT32BE(iter->xdr[iter->level].fdr.bkm);
- if ((((flag >> fdr_flg_ft_shift) & 3) == 3) || get_UINT16BE(iter->xdr[iter->level].fdr.ofm))
- ent->filesize++;
-
- /* convert to ADUs */
- if (iter->xdr[iter->level].fdr.apb > 1)
- /* more than one ADU per block */
- ent->filesize *= iter->xdr[iter->level].fdr.apb;
- else if (iter->xdr[iter->level].fdr.bpa > 1)
- /* more than one block per ADU */
- ent->filesize = (ent->filesize + iter->xdr[iter->level].fdr.bpa - 1) / iter->xdr[iter->level].fdr.bpa;
- }
- iter->index[iter->level]++;
-
- if (get_UINT16BE(iter->xdr[iter->level].fdr.saa) != 0)
- printf("roupoupou");
- else
- {
- int i;
- for (i=0; i<64; i++)
- if (iter->xdr[iter->level].fdr.sat[i])
- {
- printf("roupoupou");
- break;
- }
- }
-
- /* recurse subdirectory if applicable */
- if ((((flag >> fdr_flg_fu_shift) & 3) == 1)
- && (! (flag & fdr_flg_ali))
- && (! (flag & fdr_flg_cdr))
- && (iter->level < MAX_DIR_LEVEL)
- && ! ((iter->level == 0) && ! memcmp(iter->xdr[iter->level].fdr.fnm, "VCATALOG", 8)))
- {
- ti990_dor dor;
-
- if (get_UINT16BE(iter->xdr[iter->level].fdr.saa) != 0)
- printf("ninou");
-
- read_sector_logical_len(iter->image->file_handle,
- get_UINT16BE(iter->xdr[iter->level].fdr.paa) * get_UINT16BE(iter->image->sec0.spa),
- & iter->image->geometry, &dor, sizeof(dor));
-
- iter->level++;
- iter->nrc[iter->level] = get_UINT16BE(dor.nrc)/*get_UINT32BE(iter->fdr[iter->level-1].eom)-1*/;
- iter->index[iter->level] = 0;
-#if 0
- if (get_UINT16BE(dor.nrc) != (get_UINT32BE(iter->xdr[iter->level-1].fdr.eom)-1))
- printf("hiha");
-#endif
- }
-
- /* go to upper level if applicable */
- while (iter->index[iter->level] >= iter->nrc[iter->level])
- iter->level--;
- }
-
- return (imgtoolerr_t)0;
-}
-
-/*
- Free enumerator
-*/
-static void ti990_image_closeenum(imgtool_directory *enumeration)
-{
-}
-
-/*
- Compute free space on disk image (in ADUs)
-*/
-static imgtoolerr_t ti990_image_freespace(imgtool_partition *partition, UINT64 *size)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- ti990_image *image = (ti990_image *) imgtool_image_extra_bytes(img);
- int totadus = get_UINT16BE(image->sec0.tna);
- int adu, record, sub_adu;
- char buf[256];
- size_t freeadus = 0;
-
- if ((totadus+2031)/2032 != image->sec0.tbm)
- /*return IMGTOOLERR_CORRUPTIMAGE;*/
- return (imgtoolerr_t)0;
-
- adu = 0;
- record = 0;
- sub_adu = 0;
- while (adu<totadus)
- {
- read_sector_logical_len(image->file_handle, image->sec0.sbm + record, &image->geometry, buf, sizeof(buf));
-
- while ((adu < totadus) && (sub_adu < 2032))
- {
- if (! (buf[(sub_adu >> 3) + 2] & (1 << (sub_adu & 7))))
- freeadus++;
- sub_adu++;
- adu++;
- }
- sub_adu = 0;
- record++;
- }
-
- * size = freeadus;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-#ifdef UNUSED_FUNCTION
-/*
- Extract a file from a ti990_image.
-*/
-static imgtoolerr_t ti990_image_readfile(imgtool_partition *partition, const char *fpath, imgtool_stream *destf)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- ti990_image *image = (ti990_image *) imgtool_image_extra_bytes(img);
- int catalog_index, fdr_secnum, parent_fdr_secnum;
- imgtoolerr_t reply;
-
-
- reply = find_fdr(image, fpath, &catalog_index, &fdr_secnum, &parent_fdr_secnum);
- if (reply)
- return reply;
-
- /* ... */
-
- return 0;
-
-#if 0
- ti99_image *image = (ti99_image*) img;
- int totsecs = (image->sec0.totsecsMSB << 8) | image->sec0.totsecsLSB;
- char ti_fname[10];
- ti99_fdr fdr;
- tifile_header dst_header;
- int i, lnks_index;
- int cur_sec, last_sec;
- int secsused;
- UINT8 buf[256];
- int reply;
-
- str_to_fname(ti_fname, filename);
-
- reply = find_fdr(image, ti_fname, &fdr, NULL);
- if (reply)
- return reply;
-
- dst_header.tifiles[0] = '\7';
- dst_header.tifiles[1] = 'T';
- dst_header.tifiles[2] = 'I';
- dst_header.tifiles[3] = 'F';
- dst_header.tifiles[4] = 'I';
- dst_header.tifiles[5] = 'L';
- dst_header.tifiles[6] = 'E';
- dst_header.tifiles[7] = 'S';
- dst_header.secsused_MSB = fdr.secsused_MSB;
- dst_header.secsused_LSB = fdr.secsused_LSB;
- dst_header.flags = fdr.flags;
- dst_header.recspersec = fdr.recspersec;
- dst_header.eof = fdr.eof;
- dst_header.reclen = fdr.reclen;
- dst_header.fixrecs_MSB = fdr.fixrecs_MSB;
- dst_header.fixrecs_LSB = fdr.fixrecs_LSB;
- for (i=0; i<(128-14); i++)
- dst_header.res[i] = 0;
-
- if (stream_write(destf, & dst_header, 128) != 128)
- return IMGTOOLERR_WRITEERROR;
-
-
- secsused = get_fdr_secsused(&fdr);
-
- i = 0; /* file logical sector #0 */
- lnks_index = 0; /* start of file block table */
- while (i<secsused)
- {
- if (lnks_index == 76)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* read curent file block table entry */
- cur_sec = ((fdr.lnks[lnks_index][1] & 0xf) << 8) | fdr.lnks[lnks_index][0];
- last_sec = (fdr.lnks[lnks_index][2] << 4) | (fdr.lnks[lnks_index][1] >> 4);
-
- /* copy current file block */
- while ((i<=last_sec) && (i<secsused))
- {
- if (cur_sec >= totsecs)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (read_sector_logical(image->file_handle, cur_sec, & image->geometry, buf))
- return IMGTOOLERR_READERROR;
-
- if (stream_write(destf, buf, 256) != 256)
- return IMGTOOLERR_WRITEERROR;
-
- i++;
- cur_sec++;
- }
-
- /* next entry in file block table */
- lnks_index++;
- }
-
- return 0;
-#endif
-}
-
-/*
- Add a file to a ti990_image.
-*/
-static imgtoolerr_t ti990_image_writefile(imgtool_partition *partition, const char *fpath, imgtool_stream *sourcef, option_resolution *writeoptions)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- ti990_image *image = (ti990_image *) imgtool_image_extra_bytes(img);
- int catalog_index, fdr_secnum, parent_fdr_secnum;
- imgtoolerr_t reply;
-
-
- /* check that file does not exist */
- reply = find_fdr(image, fpath, &catalog_index, &fdr_secnum, &parent_fdr_secnum);
- if ((reply) && (reply != IMGTOOLERR_FILENOTFOUND))
- return reply;
-
- /* ... */
-
- return 0;
-
-#if 0
- ti99_image *image = (ti99_image*) img;
- int totsecs = (image->sec0.totsecsMSB << 8) | image->sec0.totsecsLSB;
- char ti_fname[10];
- ti99_fdr fdr;
- tifile_header src_header;
- int i, lnks_index;
- int cur_sec, last_sec;
- int secsused;
- UINT8 buf[256];
- int reply;
- int fdr_secnum;
-
- str_to_fname(ti_fname, filename);
-
- reply = find_fdr(image, ti_fname, &fdr, NULL);
- if (reply == 0)
- { /* file already exists: causes an error for now */
- return IMGTOOLERR_UNEXPECTED;
- }
- else if (reply != IMGTOOLERR_FILENOTFOUND)
- {
- return reply;
- }
-
- if (stream_read(sourcef, & src_header, 128) != 128)
- return IMGTOOLERR_READERROR;
-
- /* create new file */
- reply = new_file(image, ti_fname, &fdr_secnum);
- if (reply)
- return reply;
-
- memcpy(fdr.name, ti_fname, 10);
- fdr.res10[1] = fdr.res10[0] = 0;
- fdr.flags = src_header.flags;
- fdr.recspersec = src_header.recspersec;
- fdr.secsused_MSB = /*src_header.secsused_MSB*/0;
- fdr.secsused_LSB = /*src_header.secsused_LSB*/0;
- fdr.eof = src_header.eof;
- fdr.reclen = src_header.reclen;
- fdr.fixrecs_LSB = src_header.fixrecs_LSB;
- fdr.fixrecs_MSB = src_header.fixrecs_MSB;
- for (i=0; i<8; i++)
- fdr.res20[i] = 0;
- for (i=0; i<76; i++)
- fdr.lnks[i][2] = fdr.lnks[i][1] = fdr.lnks[i][0] = 0;
-
- /* alloc data sectors */
- secsused = (src_header.secsused_MSB << 8) | src_header.secsused_LSB;
- reply = alloc_file_sectors(image, &fdr, secsused);
- if (reply)
- return reply;
-
- /* copy data */
- i = 0;
- lnks_index = 0;
- while (i<secsused)
- {
- if (lnks_index == 76)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- cur_sec = ((fdr.lnks[lnks_index][1] & 0xf) << 8) | fdr.lnks[lnks_index][0];
- last_sec = (fdr.lnks[lnks_index][2] << 4) | (fdr.lnks[lnks_index][1] >> 4);
-
- while ((i<secsused) && (i<=last_sec))
- {
- if (cur_sec >= totsecs)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- if (stream_read(sourcef, buf, 256) != 256)
- return IMGTOOLERR_READERROR;
-
- if (write_sector_logical(image->file_handle, cur_sec, & image->geometry, buf))
- return IMGTOOLERR_WRITEERROR;
-
- i++;
- cur_sec++;
- }
-
- lnks_index++;
- }
-
- /* write fdr */
- if (write_sector_logical(image->file_handle, fdr_secnum, & image->geometry, &fdr))
- return IMGTOOLERR_WRITEERROR;
-
- /* update catalog */
- for (i=0; i<128; i++)
- {
- buf[2*i] = image->catalog[i].fdr_secnum >> 8;
- buf[2*i+1] = image->catalog[i].fdr_secnum & 0xff;
- }
- if (write_sector_logical(image->file_handle, 1, & image->geometry, buf))
- return IMGTOOLERR_WRITEERROR;
-
- /* update bitmap */
- if (write_sector_logical(image->file_handle, 0, & image->geometry, &image->sec0))
- return IMGTOOLERR_WRITEERROR;
-
- return 0;
-#endif
-}
-
-/*
- Delete a file from a ti990_image.
-*/
-static imgtoolerr_t ti990_image_deletefile(imgtool_partition *partition, const char *fpath)
-{
- imgtool_image *img = imgtool_partition_image(partition);
- ti990_image *image = (ti990_image *) imgtool_image_extra_bytes(img);
- int catalog_index, fdr_secnum, parent_fdr_secnum;
- imgtoolerr_t reply;
-
-
- reply = find_fdr(image, fpath, &catalog_index, &fdr_secnum, &parent_fdr_secnum);
- if (reply)
- return reply;
-
- /* ... */
-
- return 0;
-
-#if 0
- ti99_image *image = (ti99_image*) img;
- int totsecs = (image->sec0.totsecsMSB << 8) | image->sec0.totsecsLSB;
- char ti_fname[10];
- ti99_fdr fdr;
- int i, lnks_index;
- int cur_sec, last_sec;
- int secsused;
- int catalog_index;
- int reply;
- UINT8 buf[256];
-
- str_to_fname(ti_fname, filename);
-
- reply = find_fdr(image, ti_fname, &fdr, &catalog_index);
- if (reply)
- return reply;
-
- /* free data sectors */
- secsused = get_fdr_secsused(&fdr);
-
- i = 0;
- lnks_index = 0;
- while (i<secsused)
- {
- if (lnks_index == 76)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- cur_sec = ((fdr.lnks[lnks_index][1] & 0xf) << 8) | fdr.lnks[lnks_index][0];
- last_sec = (fdr.lnks[lnks_index][2] << 4) | (fdr.lnks[lnks_index][1] >> 4);
-
- while ((i<secsused) && (i<=last_sec))
- {
- if (cur_sec >= totsecs)
- return IMGTOOLERR_CORRUPTIMAGE;
-
- image->sec0.abm[cur_sec >> 3] &= ~ (1 << (cur_sec & 7));
-
- i++;
- cur_sec++;
- }
-
- lnks_index++;
- }
-
- /* free fdr sector */
- image->sec0.abm[image->catalog[catalog_index].fdr_secnum >> 3] &= ~ (1 << (image->catalog[catalog_index].fdr_secnum & 7));
-
- /* delete catalog entry */
- for (i=catalog_index; i<127; i++)
- image->catalog[i] = image->catalog[i+1];
- image->catalog[127].fdr_secnum = 0;
-
- /* update catalog */
- for (i=0; i<128; i++)
- {
- buf[2*i] = image->catalog[i].fdr_secnum >> 8;
- buf[2*i+1] = image->catalog[i].fdr_secnum & 0xff;
- }
- if (write_sector_logical(image->file_handle, 1, & image->geometry, buf))
- return IMGTOOLERR_WRITEERROR;
-
- /* update bitmap */
- if (write_sector_logical(image->file_handle, 0, & image->geometry, &image->sec0))
- return IMGTOOLERR_WRITEERROR;
-
- return 0;
-#endif
-}
-#endif
-
-/*
- Create a blank ti990_image.
-*/
-static imgtoolerr_t ti990_image_create(imgtool_image *image, imgtool_stream *f, option_resolution *createoptions)
-{
- //const char *volname;
- ti990_geometry geometry;
- unsigned totsecs;
- disk_image_header header;
- ti990_sc0 sec0;
- UINT8 empty_sec[MAX_SECTOR_SIZE];
- int reply;
- int i;
-
- /* read options */
- //volname = option_resolution_lookup_string(createoptions, ti990_createopts_volname);
- geometry.cylinders = option_resolution_lookup_int(createoptions, ti990_createopts_cylinders);
- geometry.heads = option_resolution_lookup_int(createoptions, ti990_createopts_heads);
- geometry.sectors_per_track = option_resolution_lookup_int(createoptions, ti990_createopts_sectors);
- geometry.bytes_per_sector = option_resolution_lookup_int(createoptions, ti990_createopts_sectorsize);
-
- totsecs = geometry.cylinders * geometry.heads * geometry.sectors_per_track;
-
- /* write header */
- set_UINT32BE(& header.cylinders, geometry.cylinders);
- set_UINT32BE(& header.heads, geometry.heads);
- set_UINT32BE(& header.sectors_per_track, geometry.sectors_per_track);
- set_UINT32BE(& header.bytes_per_sector, geometry.bytes_per_sector);
-
- reply = stream_write(f, &header, sizeof(header));
- if (reply != sizeof(header))
- {
- return IMGTOOLERR_WRITEERROR;
- }
-
-
- /* initialize sector 0 */
- /* mark disk as uninitialized */
- set_UINT16BE(& sec0.sta, 2);
-
-
- /* write sector 0 */
- if (write_sector_logical(f, 0, & geometry, &sec0))
- return IMGTOOLERR_WRITEERROR;
-
-
- /* now clear every other sector, including catalog */
- memset(empty_sec, 0, geometry.bytes_per_sector);
-
- for (i=1; i<totsecs; i++)
- if (write_sector_logical(f, i, & geometry, empty_sec))
- return IMGTOOLERR_WRITEERROR;
-
- return (imgtoolerr_t)0;
-}
diff --git a/src/mess/tools/imgtool/modules/vzdos.c b/src/mess/tools/imgtool/modules/vzdos.c
deleted file mode 100644
index bacaa448ef8..00000000000
--- a/src/mess/tools/imgtool/modules/vzdos.c
+++ /dev/null
@@ -1,960 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
-/****************************************************************************
-
- vzdos.c
-
- Laser/VZ disk images
-
-****************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-#include "imgtool.h"
-#include "formats/imageutl.h"
-#include "formats/vt_dsk.h"
-#include "iflopimg.h"
-
-/*
-
-sector format
-
-| GAP1 | IDAM | GAP2 | DATA | CHECKSUM | ...
-
-GAP1 = 80 80 80 80 80 00 6
-IDAM = FE E7 18 C3 Track# Sector# Checksum-8 of prev. 2 bytes 7
-GAP2 = 80 80 80 80 80 80 00 C3 18 E7 FE 11
-DATA = 126 bytes actual data 126
- = nextTrack# nextSector# 2
-CHECKSUM = Checksum-16 of the previous 128 bytes 2
- ---
- 154 bytes
-
-sectors 0 to 14 are used for the disk directory. sector 15 is used
-as track map, with one bit for each sector used.
-
-*/
-
-#define DATA_SIZE (126)
-#define SECTOR_SIZE (0x9b)
-#define MAX_DIRENTS (15*8)
-
-/* vzdos directry entry */
-struct vzdos_dirent
-{
- char ftype;
- char delimitor;
- char fname[8];
- UINT8 start_track;
- UINT8 start_sector;
- UINT16 start_address;
- UINT16 end_address;
-};
-
-struct vz_iterator
-{
- int index;
- int eof;
-};
-
-static const UINT8 sector_order[] =
-{
- 0, 3, 6, 9, 12, 15, 2, 5, 8, 11, 14, 1, 4, 7, 10, 13
-};
-
-/*********************************************************************
- Internal functions
-*********************************************************************/
-
-/* get length of filename without trailing spaces */
-static int vzdos_get_fname_len(const char *fname)
-{
- int len;
-
- for (len = 7; len > 0; len--)
- if (fname[len] != 0x20)
- break;
-
- return len;
-}
-
-/* calculate checksum-16 of buffer */
-static UINT16 chksum16(UINT8 *buffer, int len)
-{
- int i;
- UINT16 sum = 0;
-
- for (i = 0; i < len; i++)
- sum += buffer[i];
-
- return sum;
-}
-
-/* returns the offset where the actual sector data starts */
-static imgtoolerr_t vzdos_get_data_start(imgtool_image *img, int track, int sector, int *start)
-{
- imgtoolerr_t ret;
- UINT8 buffer[25]; /* enough to read the sector header */
-
- ret = (imgtoolerr_t)floppy_read_sector(imgtool_floppy(img), 0, track, sector_order[sector], 0, &buffer, sizeof(buffer));
- if (ret) return ret;
-
- /* search for start of data */
- if (memcmp(buffer + 19, "\xC3\x18\xE7\xFE", 4) == 0)
- *start = 23;
- else if (memcmp(buffer + 20, "\xC3\x18\xE7\xFE", 4) == 0)
- *start = 24;
- else if (memcmp(buffer + 21, "\xC3\x18\xE7\xFE", 4) == 0)
- *start = 25;
- else
- return IMGTOOLERR_CORRUPTIMAGE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/* return the actual data of a sector */
-static imgtoolerr_t vzdos_read_sector_data(imgtool_image *img, int track, int sector, UINT8 *data)
-{
- int ret, data_start;
- UINT8 buffer[DATA_SIZE + 4]; /* data + checksum */
-
- ret = vzdos_get_data_start(img, track, sector, &data_start);
- if (ret) return (imgtoolerr_t)ret;
-
- ret = floppy_read_sector(imgtool_floppy(img), 0, track, sector_order[sector], data_start, &buffer, sizeof(buffer));
- if (ret) return (imgtoolerr_t)ret;
-
- /* verify sector checksums */
- if (pick_integer_le(buffer, DATA_SIZE + 2, 2) != chksum16(buffer, DATA_SIZE + 2))
- return IMGTOOLERR_CORRUPTFILE;
-
- memcpy(data, &buffer, DATA_SIZE + 2);
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/* write data to sector */
-static imgtoolerr_t vzdos_write_sector_data(imgtool_image *img, int track, int sector, UINT8 *data)
-{
- int ret, data_start;
- UINT8 buffer[DATA_SIZE + 4]; /* data + checksum */
-
- ret = vzdos_get_data_start(img, track, sector, &data_start);
- if (ret) return (imgtoolerr_t)ret;
-
- memcpy(buffer, data, DATA_SIZE + 2);
- place_integer_le(buffer, DATA_SIZE + 2, 2, chksum16(data, DATA_SIZE + 2));
-
- ret = floppy_write_sector(imgtool_floppy(img), 0, track, sector_order[sector], data_start, buffer, sizeof(buffer), 0); /* TODO: pass ddam argument from imgtool */
- if (ret) return (imgtoolerr_t)ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/* write formatted empty sector */
-static imgtoolerr_t vzdos_clear_sector(imgtool_image *img, int track, int sector)
-{
- UINT8 data[DATA_SIZE + 2];
-
- memset(data, 0x00, sizeof(data));
-
- return vzdos_write_sector_data(img, track, sector, data);
-}
-
-/* return a directory entry for an index */
-static imgtoolerr_t vzdos_get_dirent(imgtool_image *img, int index, vzdos_dirent *ent)
-{
- int ret, entry;
- UINT8 buffer[DATA_SIZE + 2];
-
- ret = vzdos_read_sector_data(img, 0, (int) index / 8, buffer);
- if (ret) return (imgtoolerr_t)ret;
-
- entry = ((index % 8) * sizeof(vzdos_dirent));
-
- memcpy(ent, &buffer[entry], 10);
- ent->start_track = pick_integer_le(&buffer[entry], 10, 1);
- ent->start_sector = pick_integer_le(&buffer[entry], 11, 1);
- ent->start_address = pick_integer_le(&buffer[entry], 12, 2);
- ent->end_address = pick_integer_le(&buffer[entry], 14, 2);
-
- if (ent->ftype == 0x00)
- return IMGTOOLERR_FILENOTFOUND;
-
- /* check values */
- if (ent->start_track > 39)
- return IMGTOOLERR_CORRUPTFILE;
-
- if (ent->start_sector > 15)
- return IMGTOOLERR_CORRUPTFILE;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/* save a directory entry to disk */
-static imgtoolerr_t vzdos_set_dirent(imgtool_image *img, int index, vzdos_dirent ent)
-{
- int ret, entry;
- UINT8 buffer[DATA_SIZE + 2];
-
- /* read current sector with entries */
- ret = vzdos_read_sector_data(img, 0, (int) index / 8, buffer);
- if (ret) return (imgtoolerr_t)ret;
-
- entry = ((index % 8) * sizeof(vzdos_dirent));
-
- memcpy(&buffer[entry], &ent, 10);
- place_integer_le(buffer, entry + 10, 1, ent.start_track);
- place_integer_le(buffer, entry + 11, 1, ent.start_sector);
- place_integer_le(buffer, entry + 12, 2, ent.start_address);
- place_integer_le(buffer, entry + 14, 2, ent.end_address);
-
- /* save new sector */
- ret = vzdos_write_sector_data(img, 0, (int) index / 8, buffer);
- if (ret) return (imgtoolerr_t)ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/* clear a directory entry */
-static imgtoolerr_t vzdos_clear_dirent(imgtool_image *img, int index)
-{
- int ret;
- vzdos_dirent entry;
-
- memset(&entry, 0x00, sizeof(vzdos_dirent));
-
- ret = vzdos_set_dirent(img, index, entry);
- if (ret) return (imgtoolerr_t)ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/* search the index for a directory entry */
-static imgtoolerr_t vzdos_searchentry(imgtool_image *image, const char *fname, int *entry) {
- int i, len, ret;
- vzdos_dirent ent;
- char filename[9];
-
- /* check for invalid filenames */
- if (strlen(fname) > 8)
- return IMGTOOLERR_BADFILENAME;
-
- /* TODO: check for invalid characters */
-
- *entry = -1;
-
- for (i = 0; i < MAX_DIRENTS; i++) {
- ret = vzdos_get_dirent(image, i, &ent);
- if (ret) return (imgtoolerr_t)ret;
-
- len = vzdos_get_fname_len(ent.fname) + 1;
-
- if (strlen(fname) != len)
- continue;
-
- memset(filename, 0x00, sizeof(filename));
- memcpy(filename, ent.fname, len);
-
- if (!core_stricmp(fname, filename)) {
- *entry = i;
- break;
- }
-
- }
-
- if (*entry == -1)
- return IMGTOOLERR_FILENOTFOUND;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/* return a directory entry for a filename */
-static imgtoolerr_t vzdos_get_dirent_fname(imgtool_image *img, const char *fname, vzdos_dirent *ent)
-{
- int ret, index;
-
- ret = vzdos_searchentry(img, fname, &index);
- if (ret) return (imgtoolerr_t)ret;
-
- ret = vzdos_get_dirent(img, index, ent);
- if (ret) return (imgtoolerr_t)ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t vzdos_toggle_trackmap(imgtool_image *img, int track, int sector, int clear)
-{
- int ret, value, bit;
- UINT8 buffer[DATA_SIZE + 2];
-
- /* get trackmap from image */
- ret = vzdos_read_sector_data(img, 0, 15, buffer);
- if (ret) return (imgtoolerr_t)ret;
-
- value = (int) (floor(((double)track * 16 + sector) / 8) - 1);
- bit = 0x01 << ((track * 16 + sector) % 8);
-
- if (clear)
- buffer[value-1] &= ~bit;
- else
- buffer[value-1] |= bit;
-
- ret = vzdos_write_sector_data(img, 0, 15, buffer);
- if (ret) return (imgtoolerr_t)ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/* clear a trackmap entry */
-static imgtoolerr_t vzdos_clear_trackmap(imgtool_image *img, int track, int sector)
-{
- return vzdos_toggle_trackmap(img, track, sector, 1);
-}
-
-/* enable a trackmap entry */
-static imgtoolerr_t vzdos_set_trackmap(imgtool_image *img, int track, int sector)
-{
- return vzdos_toggle_trackmap(img, track, sector, 0);
-}
-
-/* return the status of a trackmap entry */
-static imgtoolerr_t vzdos_get_trackmap(imgtool_image *img, int track, int sector, int *used)
-{
- int ret, value, bit;
- UINT8 buffer[DATA_SIZE + 2];
-
- /* get trackmap from image */
- ret = vzdos_read_sector_data(img, 0, 15, buffer);
- if (ret) return (imgtoolerr_t)ret;
-
- value = (int) (floor(((double)track * 16 + sector) / 8) - 1);
- bit = 0x01 << ((track * 16 + sector) % 8);
-
- if (buffer[value-1] & bit)
- *used = 1;
- else
- *used = 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/* return the next free sector */
-static imgtoolerr_t vzdos_free_trackmap(imgtool_image *img, int *track, int *sector)
-{
- int ret, used = 0;
-
- for (*track = 1; *track < 40; (*track)++) {
- for (*sector = 0; *sector < 16; (*sector)++) {
- ret = vzdos_get_trackmap(img, *track, *sector, &used);
- if (ret) return (imgtoolerr_t)ret;
- if (!used) return IMGTOOLERR_SUCCESS;
- }
- }
-
- return IMGTOOLERR_NOSPACE;
-}
-
-static imgtoolerr_t vzdos_write_formatted_sector(imgtool_image *img, int track, int sector)
-{
- int ret;
- UINT8 sector_data[DATA_SIZE + 4 + 24];
-
- static const UINT8 sector_header[24] = {
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xFE, 0xE7,
- 0x18, 0xC3, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x00, 0xC3, 0x18, 0xE7, 0xFE
- };
-
- memset(sector_data, 0x00, sizeof(sector_data));
- memcpy(sector_data, sector_header, sizeof(sector_header));
-
- sector_data[10] = (UINT8) track; /* current track */
- sector_data[11] = (UINT8) sector; /* current sector */
- sector_data[12] = (UINT8) track + sector; /* checksum-8 */
-
- ret = floppy_write_sector(imgtool_floppy(img), 0, track, sector_order[sector], 0, sector_data, sizeof(sector_data), 0); /* TODO: pass ddam argument from imgtool */
- if (ret) return (imgtoolerr_t)ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*********************************************************************
- Imgtool module code
-*********************************************************************/
-
-static imgtoolerr_t vzdos_diskimage_beginenum(imgtool_directory *enumeration, const char *path)
-{
- vz_iterator *iter;
-
- iter = (vz_iterator *) imgtool_directory_extrabytes(enumeration);
- if (!iter) return IMGTOOLERR_OUTOFMEMORY;
-
- iter->index = 1;
- iter->eof = 0;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t vzdos_diskimage_nextenum(imgtool_directory *enumeration, imgtool_dirent *ent)
-{
- vz_iterator *iter = (vz_iterator *) imgtool_directory_extrabytes(enumeration);
-
- if (iter->eof == 1 || iter->index > MAX_DIRENTS) {
- ent->eof = 1;
-
- } else {
- const char *type;
- int ret, len;
- vzdos_dirent dirent;
-
- ret = vzdos_get_dirent(imgtool_directory_image(enumeration), iter->index - 1, &dirent);
-
- if (ret == IMGTOOLERR_FILENOTFOUND)
- {
- iter->eof = 1;
- ent->eof = 1;
- return IMGTOOLERR_SUCCESS;
- }
-
- if (ret == IMGTOOLERR_CORRUPTFILE)
- ent->corrupt = 1;
-
- /* kill trailing spaces */
- for (len = 7; len > 0; len--) {
- if (dirent.fname[len] != 0x20) {
- break;
- }
- }
-
- memcpy(ent->filename, &dirent.fname, len + 1);
- ent->filesize = dirent.end_address - dirent.start_address;
-
- switch (dirent.ftype)
- {
- case 0x01: type = "Deleted"; break;
- case 'T': type = "Basic"; break;
- case 'B': type = "Binary"; break;
- case 'D': type = "Data"; break;
- case 'F': type = "Quickwrite"; break;
- case 'A': type = "Assembler"; break;
- case 'S': type = "Diskops"; break;
- case 'W': type = "Wordpro"; break;
- default: type = "Unknown";
- }
-
- snprintf(ent->attr, ARRAY_LENGTH(ent->attr), "%s", type);
-
- iter->index++;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/* TRK 0 sector 15 is used to hold the track map of the disk with one bit
- corresponding to a sector used. */
-static imgtoolerr_t vzdos_diskimage_freespace(imgtool_partition *partition, UINT64 *size)
-{
- imgtoolerr_t ret;
- int i;
- imgtool_image *image = imgtool_partition_image(partition);
- UINT8 c, v, buffer[DATA_SIZE + 2];
- *size = 0;
-
- ret = vzdos_read_sector_data(image, 0, 15, buffer);
- if (ret) return ret;
-
- for (i = 0; i < DATA_SIZE; i++) {
- v = buffer[i];
- for (c = 0; v; c++) {
- v &= v - 1;
- }
- *size += c * DATA_SIZE;
- }
- *size = (DATA_SIZE * 16 * 39) - *size;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t vzdos_diskimage_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- imgtoolerr_t ret;
- imgtool_image *image = imgtool_partition_image(partition);
- int filesize, track, sector;
- vzdos_dirent ent;
- UINT8 buffer[DATA_SIZE + 2];
-
- ret = vzdos_get_dirent_fname(image, filename, &ent);
- if (ret) return ret;
-
- filesize = ent.end_address - ent.start_address;
- track = ent.start_track;
- sector = ent.start_sector;
-
- while (filesize > 0) {
- int towrite;
-
- ret = vzdos_read_sector_data(image, track, sector, buffer);
- if (ret) return ret;
-
- /* detect sectors pointing to themselfs */
- if ((track == (int)pick_integer_le(buffer, DATA_SIZE, 1)) && (sector == (int)pick_integer_le(buffer, DATA_SIZE + 1, 1)))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* load next track and sector values */
- track = pick_integer_le(buffer, DATA_SIZE, 1);
- sector = pick_integer_le(buffer, DATA_SIZE + 1, 1);
-
- /* track 0 is invalid */
- if ((track == 0) && (filesize > DATA_SIZE))
- return IMGTOOLERR_CORRUPTIMAGE;
-
- /* write either DATA_SIZE or the remaining bytes */
- towrite = filesize > DATA_SIZE ? DATA_SIZE : filesize;
-
- if (stream_write(destf, buffer, towrite) != towrite)
- return IMGTOOLERR_WRITEERROR;
-
- filesize -= DATA_SIZE;
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/* deletes directory entry, clears trackmap entries and sectors */
-static imgtoolerr_t vzdos_diskimage_deletefile(imgtool_partition *partition, const char *fname)
-{
- imgtoolerr_t ret;
- imgtool_image *img = imgtool_partition_image(partition);
- int index, filesize, track, sector, next_track, next_sector;
- vzdos_dirent entry, next_entry;
- UINT8 buffer[DATA_SIZE + 2];
-
- ret = vzdos_get_dirent_fname(img, fname, &entry);
- if (ret) return ret;
-
- ret = (imgtoolerr_t)floppy_read_sector(imgtool_floppy(img), 0, entry.start_track, sector_order[entry.start_sector], 24, &buffer, DATA_SIZE + 2);
- if (ret) return ret;
-
- filesize = entry.end_address - entry.start_address;
- track = entry.start_track;
- sector = entry.start_sector;
-
- /* delete directory entry */
- ret = vzdos_searchentry(img, fname, &index);
- if (ret) return ret;
-
- ret = vzdos_get_dirent(img, index + 1, &next_entry);
-
- if (ret == IMGTOOLERR_FILENOTFOUND) {
- /* we are the last directory entry, just delete it */
- ret = vzdos_clear_dirent(img, index);
- if (ret) return ret;
-
- } else if (ret) {
- /* an error occurred */
- return ret;
-
- } else {
- ret = vzdos_set_dirent(img, index++, next_entry);
- if (ret) return ret;
-
- while ((ret = vzdos_get_dirent(img, index + 1, &next_entry)) != IMGTOOLERR_FILENOTFOUND) {
- if (ret) return ret;
- ret = vzdos_set_dirent(img, index++, next_entry);
- if (ret) return ret;
- }
-
- ret = vzdos_clear_dirent(img, index);
- if (ret) return ret;
-
- }
-
- /* clear sectors and trackmap entries */
- while (filesize > 0) {
- filesize -= DATA_SIZE;
-
- /* clear trackmap entry */
- ret = vzdos_clear_trackmap(img, track, sector);
- if (ret) return ret;
-
- /* load next track and sector values */
- next_track = pick_integer_le(buffer, DATA_SIZE, 1);
- next_sector = pick_integer_le(buffer, DATA_SIZE + 1, 1);
-
- /* overwrite sector with default values */
- ret = vzdos_clear_sector(img, track, sector);
- if (ret) return ret;
-
- /* read next sector */
- track = next_track;
- sector = next_sector;
-
- if (filesize > 0) {
- ret = (imgtoolerr_t)floppy_read_sector(imgtool_floppy(img), 0, track, sector_order[sector], 24, &buffer, DATA_SIZE + 2);
- if (ret) return ret;
- }
-
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t vzdos_writefile(imgtool_partition *partition, int offset, imgtool_stream *sourcef, vzdos_dirent *entry)
-{
- imgtoolerr_t ret;
- imgtool_image *img = imgtool_partition_image(partition);
- int index, track, sector, toread, next_track, next_sector;
- vzdos_dirent temp_entry;
- UINT64 filesize = 0, freespace = 0;
- UINT8 buffer[DATA_SIZE + 2];
- char filename[9];
-
- /* is the image writeable? */
- if (floppy_is_read_only(imgtool_floppy(img)))
- return IMGTOOLERR_READONLY;
-
- /* check for already existing filename -> overwrite */
- strcpy(filename, entry->fname);
- filename[vzdos_get_fname_len(entry->fname) + 1] = 0x00;
- ret = vzdos_get_dirent_fname(img, filename, &temp_entry);
- if (!ret) {
- /* file already exists, delete it */
- ret = vzdos_diskimage_deletefile(partition, filename);
- if (ret) return ret;
- } else if (ret != IMGTOOLERR_FILENOTFOUND) {
- /* another error occurred, return it */
- return ret;
- }
-
- ret = (imgtoolerr_t)stream_seek(sourcef, offset, SEEK_SET);
- if (ret) return ret;
-
- /* check if there is enough space */
- filesize = stream_size(sourcef) - offset;
-
- ret = vzdos_diskimage_freespace(partition, &freespace);
- if (ret) return ret;
-
- if (filesize > freespace)
- return IMGTOOLERR_NOSPACE;
-
- /* get next free track and sector */
- ret = vzdos_free_trackmap(img, &track, &sector);
- if (ret) return ret;
-
- entry->end_address = entry->start_address + (unsigned int) filesize;
- entry->start_track = track;
- entry->start_sector = sector;
-
- /* search for next free directory entry */
- for (index = 0; index < MAX_DIRENTS; index++) {
- ret = vzdos_get_dirent(img, index, &temp_entry);
- if (ret == IMGTOOLERR_FILENOTFOUND)
- break;
- else if (ret)
- return (ret);
- }
-
- /* write directory entry to disk */
- ret = vzdos_set_dirent(img, index, *entry);
- if (ret) return ret;
-
- next_track = 0;
- next_sector = 0;
-
- /* write data to disk */
- while (filesize > 0) {
- toread = filesize > DATA_SIZE ? DATA_SIZE : filesize;
- stream_read(sourcef, buffer, toread);
-
- filesize -= toread;
-
- /* mark sector as used */
- ret = vzdos_set_trackmap(img, track, sector);
- if (ret) return ret;
-
- /* get track and sector for next sector */
- if (filesize > 0) {
- ret = vzdos_free_trackmap(img, &next_track, &next_sector);
- if (ret) return ret;
- } else {
- next_track = 0;
- next_sector = 0;
- }
- buffer[DATA_SIZE] = next_track;
- buffer[DATA_SIZE + 1] = next_sector;
-
- /* write sector to disk */
- ret = vzdos_write_sector_data(img, track, sector, buffer);
- if (ret) return ret;
-
- track = next_track;
- sector = next_sector;
- }
-
- return IMGTOOLERR_SUCCESS;
-
-}
-
-/* create a new file or overwrite a file */
-static imgtoolerr_t vzdos_diskimage_writefile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- imgtoolerr_t ret;
- int ftype;
- vzdos_dirent entry;
-
- /* TODO: check for leading spaces and strip */
- if (strlen(filename) > 8 || strlen(filename) < 1)
- return IMGTOOLERR_BADFILENAME;
-
- /* prepare directory entry */
- ftype = option_resolution_lookup_int(opts, 'T');
-
- switch (ftype) {
- case 0:
- entry.ftype = 'T';
- entry.start_address = 31465;
- break;
- case 1:
- entry.ftype = 'B';
- entry.start_address = 31465; /* ??? */
- break;
- case 2:
- entry.ftype = 'D';
- entry.start_address = 31465; /* ??? */
- break;
- default:
- break;
- }
-
- entry.delimitor = ':';
- memset(&entry.fname, 0x20, 8); /* pad with spaces */
- memcpy(&entry.fname, filename, strlen(filename));
-
- /* write file to disk */
- ret = vzdos_writefile(partition, 0, sourcef, &entry);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t vzdos_diskimage_suggesttransfer(imgtool_partition *partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
-{
- imgtoolerr_t ret;
- imgtool_image *image = imgtool_partition_image(partition);
- vzdos_dirent entry;
-
- if (fname) {
- ret = vzdos_get_dirent_fname(image, fname, &entry);
- if (ret) return ret;
-
- switch (entry.ftype) {
- case 'B':
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = filter_vzsnapshot_getinfo;
- suggestions[0].description = "VZ Snapshot";
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
- suggestions[1].description = "Raw";
- break;
- case 'T':
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = filter_vzsnapshot_getinfo;
- suggestions[0].description = "VZ Snapshot";
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
- suggestions[1].description = "Raw";
- suggestions[2].viability = SUGGESTION_POSSIBLE;
- suggestions[2].filter = filter_vzbas_getinfo;
- suggestions[2].description = "Tokenized Basic";
- break;
- default:
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[0].description = "Raw";
- }
-
- } else {
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[0].description = "Raw";
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = filter_vzsnapshot_getinfo;
- suggestions[1].description = "VZ Snapshot";
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t vzdos_diskimage_create(imgtool_image *img, imgtool_stream *stream, option_resolution *opts)
-{
- imgtoolerr_t ret;
- int track, sector;
-
- for (track = 0; track < 40; track++) {
- for (sector = 0; sector < 16; sector++) {
- ret = vzdos_write_formatted_sector(img, track, sector);
- if (ret) return ret;
- }
- }
-
- return IMGTOOLERR_SUCCESS;
-}
-
-/*********************************************************************
- Imgtool vz filter code
-*********************************************************************/
-
-static imgtoolerr_t vzsnapshot_readfile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *destf)
-{
- imgtoolerr_t ret;
- imgtool_image *image = imgtool_partition_image(partition);
- vzdos_dirent entry;
- UINT8 header[24];
-
- /* get directory entry from disk */
- ret = vzdos_get_dirent_fname(image, filename, &entry);
- if (ret) return ret;
-
- /* prepare header */
- header[0] = 'V';
- header[1] = 'Z';
- header[2] = 'F';
-
- switch (entry.ftype) {
- case 'B':
- header[3] = '1';
- header[21] = 0xF1;
- break;
- case 'T':
- header[3] = '0';
- header[21] = 0xF0;
- break;
- default:
- memset(header, 0x00, 4);
- header[21] = 0x00;
- }
-
- memset(header + 4, 0x00, 17);
- memcpy(header + 4, entry.fname, vzdos_get_fname_len(entry.fname) + 1);
- place_integer_le(header, 22, 2, entry.start_address);
-
- /* write header to file */
- stream_write(destf, header, sizeof(header));
-
- /* write data to file */
- ret = vzdos_diskimage_readfile(partition, filename, "", destf);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-static imgtoolerr_t vzsnapshot_writefile(imgtool_partition *partition, const char *filename, const char *fork, imgtool_stream *sourcef, option_resolution *opts)
-{
- imgtoolerr_t ret;
- int fnameopt;
- vzdos_dirent entry;
- UINT8 header[24];
-
- /* get header infos from file */
- stream_read(sourcef, header, sizeof(header));
-
- /* prepare directory entry */
- entry.ftype = header[21] == 0xF1 ? 'B' : 'T';
- entry.delimitor = ':';
- entry.start_address = pick_integer_le(header, 22, 2);
-
- /* filename from header or directly? */
- fnameopt = option_resolution_lookup_int(opts, 'F');
-
- if (fnameopt == 0) {
- memcpy(&entry.fname, &header[4], 8);
- } else {
- /* TODO: check for leading spaces and strip */
- if (strlen(filename) > 8 || strlen(filename) < 1)
- return IMGTOOLERR_BADFILENAME;
-
- memcpy(&entry.fname, filename, strlen(filename) - 3);
- }
-
- /* write file to disk */
- ret = vzdos_writefile(partition, 24, sourcef, &entry);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
-}
-
-void filter_vzsnapshot_getinfo(UINT32 state, union filterinfo *info)
-{
- switch(state)
- {
- case FILTINFO_STR_NAME: info->s = "vzsnapshot"; break;
- case FILTINFO_STR_HUMANNAME: info->s = "VZ Snapshot"; break;
- case FILTINFO_STR_EXTENSION: info->s = "vz"; break;
- case FILTINFO_PTR_READFILE: info->read_file = vzsnapshot_readfile; break;
- case FILTINFO_PTR_WRITEFILE: info->write_file = vzsnapshot_writefile; break;
- }
-}
-
-/*********************************************************************
- Imgtool module declaration
-*********************************************************************/
-
-static OPTION_GUIDE_START(vzdos_writefile_optionguide)
- OPTION_ENUM_START( 'T', "ftype", "File type" )
- OPTION_ENUM( 0, "basic", "Basic" )
- OPTION_ENUM( 1, "binary", "Binary" )
- OPTION_ENUM( 2, "data", "Data" )
- OPTION_ENUM_END
- OPTION_ENUM_START( 'F', "fname", "Filename" )
- OPTION_ENUM( 0, "intern", "Filename from VZ-Header" )
- OPTION_ENUM( 1, "extern", "Actual filename" )
- OPTION_ENUM_END
-OPTION_GUIDE_END
-
-/*
-T Basic Editor File
-B Binary File
-D Sequential Access Program Data File
-F Quickwrite Document
-A Russell Harrison's Edit Ass. File
-S Dave Mitchell/Mark Hardwood Edit Ass. File Start Addr A280H
-S Quickwrite/Diskops System File/Label Except Above
-W Edit Ass. with Diskops File Start Addr A813H
-W E & F Word Pro with Patch 3.3 File End Addr D000H
-W Russell Harrison Word Pro File Except above two
-*/
-
-void vzdos_get_info(const imgtool_class *imgclass, UINT32 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(vz_iterator); break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "vzdos"); break;
- case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "VZ-DOS format"); break;
- case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
- case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), "T[0]-2;F[0]-1"); break;
- case IMGTOOLINFO_STR_EOLN: info->s = NULL; 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_OPEN: info->open = NULL; break;
- case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = vzdos_diskimage_beginenum; break;
- case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = vzdos_diskimage_nextenum; break;
- case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = vzdos_diskimage_freespace; break;
- case IMGTOOLINFO_PTR_READ_FILE: info->read_file = vzdos_diskimage_readfile; break;
- case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = vzdos_diskimage_writefile; break;
- case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = vzdos_diskimage_deletefile; break;
- case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = vzdos_diskimage_create; break;
- case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: info->writefile_optguide = vzdos_writefile_optionguide; break;
- case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = vzdos_diskimage_suggesttransfer; break;
- case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_vz; break;
- }
-}
diff --git a/src/mess/tools/imgtool/stream.c b/src/mess/tools/imgtool/stream.c
deleted file mode 100644
index 5c9cf4050c6..00000000000
--- a/src/mess/tools/imgtool/stream.c
+++ /dev/null
@@ -1,536 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- stream.c
-
- Code for implementing Imgtool streams
-
-***************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <zlib.h>
-
-#include "unzip.h"
-#include "osdcore.h"
-#include "imgtool.h"
-
-enum imgtype_t
-{
- IMG_FILE,
- IMG_MEM
-};
-
-struct imgtool_stream
-{
- imgtype_t imgtype;
- int write_protect;
- const char *name; // needed for clear
- UINT64 position;
- UINT64 filesize;
-
- union
- {
- core_file *file;
- UINT8 *buffer;
- } u;
-};
-
-
-
-static imgtool_stream *stream_open_zip(const char *zipname, const char *subname, int read_or_write)
-{
- imgtool_stream *imgfile = NULL;
-// zip_error ziperr;
- zip_file *z = NULL;
- const zip_file_header *zipent;
- FILE *f;
-
- if (read_or_write)
- goto error;
-
- /* check to see if the file exists */
- f = fopen(zipname, "r");
- if (!f)
- goto error;
- fclose(f);
-
- imgfile = (imgtool_stream *)malloc(sizeof(imgtool_stream));
- if (!imgfile)
- goto error;
-
- memset(imgfile, 0, sizeof(*imgfile));
- imgfile->imgtype = IMG_MEM;
- imgfile->write_protect = 1;
- imgfile->position = 0;
-
-// ziperr =
- zip_file_open(zipname, &z);
- if (!z)
- goto error;
-
- zipent = zip_file_first_file(z);
- while(zipent && subname && strcmp(subname, zipent->filename))
- zipent = zip_file_next_file(z);
- if (!zipent)
- goto error;
-
- imgfile->filesize = zipent->uncompressed_length;
- imgfile->u.buffer = (UINT8*)malloc(zipent->uncompressed_length);
- if (!imgfile->u.buffer)
- goto error;
-
- if (zip_file_decompress(z, imgfile->u.buffer, zipent->uncompressed_length))
- goto error;
-
- zip_file_close(z);
- return imgfile;
-
-error:
- if (z)
- zip_file_close(z);
- if (imgfile)
- {
- if (imgfile->u.buffer)
- free(imgfile->u.buffer);
- free(imgfile);
- }
- return NULL;
-}
-
-
-
-imgtool_stream *stream_open(const char *fname, int read_or_write)
-{
- file_error filerr;
- const char *ext;
- imgtool_stream *imgfile = NULL;
- static const UINT32 write_modes[] =
- {
- OPEN_FLAG_READ,
- OPEN_FLAG_WRITE | OPEN_FLAG_CREATE,
- OPEN_FLAG_READ | OPEN_FLAG_WRITE,
- OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE
- };
- core_file *f = NULL;
- char *buf = NULL;
- int len, i;
- imgtool_stream *s = NULL;
- char c;
-
- /* maybe we are just a ZIP? */
- ext = strrchr(fname, '.');
- if (ext && !core_stricmp(ext, ".zip"))
- return stream_open_zip(fname, NULL, read_or_write);
-
- filerr = core_fopen(fname, write_modes[read_or_write], &f);
- if (filerr != FILERR_NONE)
- {
- if (!read_or_write)
- {
- len = strlen(fname);
-
- /* can't open the file; try opening ZIP files with other names */
- buf = (char*)malloc(len + 1);
- if (!buf)
- goto error;
- strcpy(buf, fname);
-
- for(i = len-1; !s && (i >= 0); i--)
- {
- if ((buf[i] == '\\') || (buf[i] == '/'))
- {
- c = buf[i];
- buf[i] = '\0';
- s = stream_open_zip(buf, buf + i + 1, read_or_write);
- buf[i] = c;
- }
- }
- free(buf);
- buf = NULL;
-
- if (s)
- return s;
- }
-
- /* ah well, it was worth a shot */
- goto error;
- }
-
- imgfile = (imgtool_stream *)malloc(sizeof(imgtool_stream));
- if (!imgfile)
- goto error;
-
- /* Normal file */
- memset(imgfile, 0, sizeof(*imgfile));
- imgfile->imgtype = IMG_FILE;
- imgfile->position = 0;
- imgfile->filesize = core_fsize(f);
- imgfile->write_protect = read_or_write ? 0 : 1;
- imgfile->u.file = f;
- imgfile->name = fname;
- return imgfile;
-
-error:
- if (imgfile != NULL)
- free((void *) imgfile);
- if (f != NULL)
- core_fclose(f);
- if (buf)
- free(buf);
- return (imgtool_stream *) NULL;
-}
-
-
-
-imgtool_stream *stream_open_write_stream(int size)
-{
- imgtool_stream *imgfile;
-
- imgfile = (imgtool_stream *)malloc(sizeof(imgtool_stream));
- if (!imgfile)
- return NULL;
-
- imgfile->imgtype = IMG_MEM;
- imgfile->write_protect = 0;
- imgfile->position = 0;
- imgfile->filesize = size;
- imgfile->u.buffer = (UINT8*)malloc(size);
-
- if (!imgfile->u.buffer)
- {
- free(imgfile);
- return NULL;
- }
-
- return imgfile;
-}
-
-
-
-imgtool_stream *stream_open_mem(void *buf, size_t sz)
-{
- imgtool_stream *imgfile;
-
- imgfile = (imgtool_stream *)malloc(sizeof(imgtool_stream));
- if (!imgfile)
- return NULL;
-
- memset(imgfile, 0, sizeof(*imgfile));
- imgfile->imgtype = IMG_MEM;
- imgfile->position = 0;
- imgfile->write_protect = 0;
-
- imgfile->filesize = sz;
- imgfile->u.buffer = (UINT8*)buf;
- return imgfile;
-}
-
-
-
-void stream_close(imgtool_stream *s)
-{
- assert(s != NULL);
-
- switch(s->imgtype)
- {
- case IMG_FILE:
- if (s->u.file != NULL)
- {
- core_fclose(s->u.file);
- s->u.file = NULL;
- }
- break;
-
- case IMG_MEM:
- if (s->u.buffer != NULL)
- {
- free(s->u.buffer);
- s->u.buffer = NULL;
- }
- break;
-
- default:
- assert(0);
- break;
- }
- free((void *) s);
-}
-
-
-
-core_file *stream_core_file(imgtool_stream *stream)
-{
- return (stream->imgtype == IMG_FILE) ? stream->u.file : NULL;
-}
-
-
-
-UINT32 stream_read(imgtool_stream *stream, void *buf, UINT32 sz)
-{
- UINT32 result = 0;
-
- switch(stream->imgtype)
- {
- case IMG_FILE:
- assert(sz == (UINT32) sz);
- core_fseek(stream->u.file, stream->position, SEEK_SET);
- result = core_fread(stream->u.file, buf, (UINT32) sz);
- break;
-
- case IMG_MEM:
- /* do we have to limit sz? */
- if (sz > (stream->filesize - stream->position))
- sz = (UINT32) (stream->filesize - stream->position);
-
- memcpy(buf, stream->u.buffer + stream->position, sz);
- result = sz;
- break;
-
- default:
- assert(0);
- break;
- }
- stream->position += result;
- return result;
-}
-
-
-
-UINT32 stream_write(imgtool_stream *s, const void *buf, UINT32 sz)
-{
- void *new_buffer;
- UINT32 result = 0;
-
- switch(s->imgtype)
- {
- case IMG_MEM:
- if (!s->write_protect)
- {
- /* do we have to expand the buffer? */
- if (s->filesize < s->position + sz)
- {
- /* try to expand the buffer */
- if (s->u.buffer) free(s->u.buffer);
- new_buffer = malloc(s->position + sz);
- if (new_buffer)
- {
- s->u.buffer = (UINT8*)new_buffer;
- s->filesize = s->position + sz;
- }
- }
-
- /* do we have to limit sz? */
- if (sz > (s->filesize - s->position))
- sz = (UINT32) (s->filesize - s->position);
-
- memcpy(s->u.buffer + s->position, buf, sz);
- result = sz;
- }
- break;
-
- case IMG_FILE:
- core_fseek(s->u.file, s->position, SEEK_SET);
- result = core_fwrite(s->u.file, buf, sz);
- break;
-
- default:
- assert(0);
- break;
- }
-
- /* advance the file pointer */
- s->position += result;
-
- /* did we grow the file */
- if (s->position > s->filesize)
- s->filesize = s->position;
- return result;
-}
-
-
-
-UINT64 stream_size(imgtool_stream *s)
-{
- return s->filesize;
-}
-
-
-
-void *stream_getptr(imgtool_stream *f)
-{
- void *ptr;
-
- switch(f->imgtype)
- {
- case IMG_MEM:
- ptr = f->u.buffer;
- break;
-
- default:
- ptr = NULL;
- break;
- }
- return ptr;
-}
-
-
-
-int stream_seek(imgtool_stream *s, INT64 pos, int where)
-{
- UINT64 size;
-
- size = stream_size(s);
-
- switch(where)
- {
- case SEEK_CUR:
- pos += s->position;
- break;
- case SEEK_END:
- pos += size;
- break;
- }
-
- if (pos < 0)
- s->position = 0;
- else
- s->position = MIN(size, pos);
-
- if (s->position < pos)
- stream_fill(s, '\0', pos - s->position);
-
- return 0;
-}
-
-
-
-UINT64 stream_tell(imgtool_stream *s)
-{
- return s->position;
-}
-
-
-
-UINT64 stream_transfer(imgtool_stream *dest, imgtool_stream *source, UINT64 sz)
-{
- UINT64 result = 0;
- UINT64 readsz;
- char buf[1024];
-
- while(sz && (readsz = stream_read(source, buf, MIN(sz, sizeof(buf)))))
- {
- stream_write(dest, buf, readsz);
- sz -= readsz;
- result += readsz;
- }
- return result;
-}
-
-
-
-UINT64 stream_transfer_all(imgtool_stream *dest, imgtool_stream *source)
-{
- return stream_transfer(dest, source, stream_size(source));
-}
-
-
-
-int stream_crc(imgtool_stream *s, unsigned long *result)
-{
- size_t sz;
- void *ptr;
-
- switch(s->imgtype)
- {
- case IMG_MEM:
- *result = crc32(0, (unsigned char *) s->u.buffer, (size_t) s->filesize);
- break;
-
- default:
- sz = stream_size(s);
- ptr = malloc(sz);
- if (!ptr)
- return IMGTOOLERR_OUTOFMEMORY;
- stream_seek(s, 0, SEEK_SET);
- if (stream_read(s, ptr, sz) != sz)
- {
- free(ptr);
- return IMGTOOLERR_READERROR;
- }
- *result = crc32(0, (const Bytef*)ptr, sz);
- free(ptr);
- break;
- }
- return 0;
-}
-
-
-
-int file_crc(const char *fname, unsigned long *result)
-{
- int err;
- imgtool_stream *f;
-
- f = stream_open(fname, OSD_FOPEN_READ);
- if (!f)
- return IMGTOOLERR_FILENOTFOUND;
-
- err = stream_crc(f, result);
- stream_close(f);
- return err;
-}
-
-
-
-UINT64 stream_fill(imgtool_stream *f, unsigned char b, UINT64 sz)
-{
- UINT64 outsz;
- char buf[1024];
-
- outsz = 0;
- memset(buf, b, MIN(sz, sizeof(buf)));
-
- while(sz)
- {
- outsz += stream_write(f, buf, MIN(sz, sizeof(buf)));
- sz -= MIN(sz, sizeof(buf));
- }
- return outsz;
-}
-
-
-
-int stream_isreadonly(imgtool_stream *s)
-{
- return s->write_protect;
-}
-
-
-
-UINT32 stream_putc(imgtool_stream *stream, char c)
-{
- return stream_write(stream, &c, 1);
-}
-
-
-
-UINT32 stream_puts(imgtool_stream *stream, const char *s)
-{
- return stream_write(stream, s, strlen(s));
-}
-
-
-
-UINT32 stream_printf(imgtool_stream *stream, const char *fmt, ...)
-{
- va_list va;
- char buf[256];
-
- va_start(va, fmt);
- vsprintf(buf, fmt, va);
- va_end(va);
-
- return stream_puts(stream, buf);
-}
diff --git a/src/mess/tools/imgtool/stream.h b/src/mess/tools/imgtool/stream.h
deleted file mode 100644
index 13e6e0d727f..00000000000
--- a/src/mess/tools/imgtool/stream.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/***************************************************************************
-
- stream.h
-
- Code for implementing Imgtool streams
-
-***************************************************************************/
-
-#ifndef STREAM_H
-#define STREAM_H
-
-#include "imgterrs.h"
-#include "corefile.h"
-
-struct imgtool_stream;
-
-imgtool_stream *stream_open(const char *fname, int read_or_write); /* similar params to mame_fopen */
-imgtool_stream *stream_open_write_stream(int filesize);
-imgtool_stream *stream_open_mem(void *buf, size_t sz);
-void stream_close(imgtool_stream *stream);
-core_file *stream_core_file(imgtool_stream *stream);
-UINT32 stream_read(imgtool_stream *stream, void *buf, UINT32 sz);
-UINT32 stream_write(imgtool_stream *stream, const void *buf, UINT32 sz);
-UINT64 stream_size(imgtool_stream *stream);
-int stream_seek(imgtool_stream *stream, INT64 pos, int where);
-UINT64 stream_tell(imgtool_stream *stream);
-void *stream_getptr(imgtool_stream *stream);
-UINT32 stream_putc(imgtool_stream *stream, char c);
-UINT32 stream_puts(imgtool_stream *stream, const char *s);
-UINT32 stream_printf(imgtool_stream *stream, const char *fmt, ...) ATTR_PRINTF(2,3);
-
-/* Transfers sz bytes from source to dest */
-UINT64 stream_transfer(imgtool_stream *dest, imgtool_stream *source, UINT64 sz);
-UINT64 stream_transfer_all(imgtool_stream *dest, imgtool_stream *source);
-
-/* Fills sz bytes with b */
-UINT64 stream_fill(imgtool_stream *f, unsigned char b, UINT64 sz);
-
-/* Returns the CRC of a file */
-int stream_crc(imgtool_stream *f, unsigned long *result);
-int file_crc(const char *fname, unsigned long *result);
-
-/* Returns whether a stream is read only or not */
-int stream_isreadonly(imgtool_stream *f);
-
-#endif /* STREAM_H */