1 
2 #include "appmake.h"
3 
4 #include "ff.h"			/* Obtains integer types */
5 #include "diskio.h"		/* Declarations of disk functions */
6 
7 
8 static char             *c_binary_name      = NULL;
9 static char             *c_crt_filename      = NULL;
10 static char             *c_disc_format       = NULL;
11 static char             *c_output_file      = NULL;
12 static char             *c_boot_filename     = NULL;
13 static char             *c_disc_container    = "raw";
14 static char              help         = 0;
15 
16 
17 
18 /* Options that are available for this module */
19 option_t fat_options[] = {
20     { 'h', "help",     "Display this help",          OPT_BOOL,  &help},
21     { 'f', "format",   "Disk format",                OPT_STR,   &c_disc_format},
22     { 'b', "binfile",  "Linked binary file",         OPT_STR|OPT_INPUT,   &c_binary_name },
23     { 'c', "crt0file", "crt0 file used in linking",  OPT_STR,   &c_crt_filename },
24     { 'o', "output",   "Name of output file",        OPT_STR|OPT_OUTPUT,   &c_output_file },
25     { 's', "bootfile", "Name of the boot file",      OPT_STR,   &c_boot_filename },
26     {  0,  "container", "Type of container (raw,dsk)", OPT_STR, &c_disc_container },
27     {  0 ,  NULL,       NULL,                        OPT_NONE,  NULL }
28 };
29 
30 static disc_spec msxdos_bluemsx_fat12 = {
31     .name = "MSXDOS-F12",
32     .sectors_per_track = 9,
33     .tracks = 80,
34     .sides = 2,
35     .sector_size = 512,
36     .gap3_length = 0x2a,
37     .filler_byte = 0xe5,
38     .boottracks = 0,
39     .directory_entries = 112,
40     .number_of_fats = 2,
41     .cluster_size = 1024,
42     .fat_format_flags = FM_FAT|FM_SFD,
43     .alternate_sides = 0,
44     .first_sector_offset = 1	// Required for .dsk
45 };
46 
47 static disc_spec msxdos_takeda_fat12 = {
48     .name = "MSXDOS-F12",
49     .sectors_per_track = 9,
50     .tracks = 80,
51     .sides = 2,
52     .sector_size = 512,
53     .gap3_length = 0x2a,
54     .filler_byte = 0xe5,
55     .boottracks = 0,
56     .directory_entries = 112,
57     .number_of_fats = 2,
58     .cluster_size = 1024,
59     .fat_format_flags = FM_FAT|FM_SFD,
60     .alternate_sides = 1,
61     .first_sector_offset = 1	// Required for .dsk
62 };
63 
64 
65 
66 static struct formats {
67      const char    *name;
68      const char    *description;
69      disc_spec  *spec;
70      size_t         bootlen;
71      void          *bootsector;
72      char           force_com_extension;
73 } formats[] = {
74     { "msxdos",    "MSXDOS DSDD",         &msxdos_bluemsx_fat12, 0, NULL, 1 },
75     { "msxdos-tak","MSXDOS DSDD (takeda)",&msxdos_takeda_fat12, 0, NULL, 1 },
76     { "msxbasic",  "MSXDOS DSDD (BASIC)", &msxdos_bluemsx_fat12, 0, NULL, 0 },
77     { NULL, NULL }
78 };
79 
dump_formats()80 static void dump_formats()
81 {
82     struct formats* f = &formats[0];
83 
84     printf("Supported FAT formats:\n\n");
85 
86     while (f->name) {
87         printf("%-20s%s\n", f->name, f->description);
88         printf("%d tracks, %d sectors/track, %d bytes/sector, %d entries, %d bytes/cluster\n\n", f->spec->tracks, f->spec->sectors_per_track, f->spec->sector_size, f->spec->directory_entries, f->spec->cluster_size);
89         f++;
90     }
91 
92     printf("\nSupported containers:\n\n");
93     disc_print_writers(stdout);
94     exit(1);
95 }
96 
97 
fat_exec(char * target)98 int fat_exec(char *target)
99 {
100     if (help)
101         return -1;
102     if (c_binary_name == NULL) {
103         return -1;
104     }
105     if (c_disc_format == NULL || c_disc_container == NULL ) {
106         dump_formats();
107         return -1;
108     }
109     return fat_write_file_to_image(c_disc_format, c_disc_container, c_output_file, c_binary_name, c_crt_filename, c_boot_filename);
110 }
111 
112 
fat_write_file_to_image(const char * disc_format,const char * container,const char * output_file,const char * binary_name,const char * crt_filename,const char * boot_filename)113 int fat_write_file_to_image(const char *disc_format, const char *container, const char* output_file, const char* binary_name, const char* crt_filename, const char* boot_filename)
114 {
115     disc_handle      *h;
116     char              dos_filename[20];
117     struct formats   *f = &formats[0];
118     disc_spec        *spec = NULL;
119     char              disc_name[FILENAME_MAX+1];
120     const char       *extension;
121     disc_writer_func  writer = disc_get_writer(container, &extension);
122     FILE             *binary_fp;
123     size_t            binlen;
124     void             *filebuf;
125 
126 
127     while (f->name != NULL) {
128         if (strcasecmp(disc_format, f->name) == 0) {
129             spec = f->spec;
130             break;
131         }
132         f++;
133     }
134     if ( spec == NULL || writer == NULL ) {
135         return -1;
136     }
137 
138     if (output_file == NULL) {
139         strcpy(disc_name, binary_name);
140         suffix_change(disc_name, extension);
141     } else {
142         strcpy(disc_name, output_file);
143     }
144 
145     cpm_create_filename(binary_name, dos_filename, f->force_com_extension, 1);
146 
147     // Open the binary file
148     if ((binary_fp = fopen_bin(binary_name, crt_filename)) == NULL) {
149         exit_log(1, "Can't open input file %s\n", binary_name);
150     }
151     if (fseek(binary_fp, 0, SEEK_END)) {
152         fclose(binary_fp);
153         exit_log(1, "Couldn't determine size of file\n");
154     }
155     binlen = ftell(binary_fp);
156     fseek(binary_fp, 0L, SEEK_SET);
157     filebuf = malloc(binlen);
158     if (1 != fread(filebuf, binlen, 1, binary_fp)) { fclose(binary_fp); exit_log(1, "Could not read required data from <%s>\n",binary_name); }
159     fclose(binary_fp);
160 
161     h = fat_create(spec);
162     disc_write_file(h, dos_filename, filebuf, binlen);
163 
164     if (writer(h, disc_name) < 0) {
165         exit_log(1, "Can't write disc image");
166     }
167     disc_free(h);
168     return 0;
169 }
170 
171 
172