1 /*
2 * Create a 320KB boot disk image compatible to the Sharp MZ2500 computer family
3 *
4 * $Id: mz2500.c $
5 */
6
7
8 #include "appmake.h"
9 #include <string.h>
10 #include <ctype.h>
11
12
13
14 static char *binname = NULL;
15 static char *crtfile = NULL;
16 static char *outfile = NULL;
17 static char *blockname = NULL;
18 static char help = 0;
19
20
21 /* Options that are available for this module */
22 option_t mz2500_options[] = {
23 { 'h', "help", "Display this help", OPT_BOOL, &help},
24 { 'b', "binfile", "Linked binary file", OPT_STR, &binname },
25 { 'o', "output", "Name of output file", OPT_STR, &outfile },
26 { 0 , "blockname", "Name for the code block", OPT_STR, &blockname},
27 { 0, NULL, NULL, OPT_NONE, NULL }
28 };
29
30 static disc_spec spec = {
31 .name = "MZ2500",
32 .sectors_per_track = 16,
33 .tracks = 40,
34 .sides = 2,
35 .sector_size = 256,
36 .gap3_length = 0x17,
37 .filler_byte = 0xe5,
38 .first_sector_offset = 1,
39 .alternate_sides = 1
40 };
41
42 static uint8_t sectorbuf[256];
43
44
45 void write_sector(disc_handle *h, int track, int sector, int head)
46 {
47 int i;
48
49 for ( i = 0; i < sizeof(sectorbuf);i++ ) {
50 sectorbuf[i] ^= 0xff;
51 }
52 disc_write_sector(h, track, sector, head, sectorbuf);
53
54 }
55
56
57 /*
58 * Execution starts here
59 */
60
msx_bit(FILE * fpout,unsigned char bit)61 int mz2500_exec(char* target)
62 {
63 char filename[FILENAME_MAX + 1];
64 FILE* fpin;
65 int len;
66 int i;
67 int track, sector, head;
68 size_t bytes_read;
69 int bytes_to_write;
70 disc_handle *h;
71
72 if (help)
73 return -1;
74
75 if (binname == NULL ) {
76 return -1;
77 }
78
79 if (outfile == NULL) {
80 strcpy(filename, binname);
81 } else {
82 strcpy(filename, outfile);
83 }
84
85
86 suffix_change(filename, ".dsk");
87
88
89 if (strcmp(binname, filename) == 0) {
90 exit_log(1, "Input and output file names must be different\n");
91 }
92
93 if (blockname == NULL)
94 blockname = zbasename(binname);
95
96 if ((fpin = fopen_bin(binname, crtfile)) == NULL) {
97 exit_log(1, "Can't open input file %s\n", binname);
98 }
99
100 suffix_change(blockname, "");
101
102 if (fseek(fpin, 0, SEEK_END)) {
103 fclose(fpin);
104 exit_log(1,"Couldn't determine size of file\n");
105 }
106
107 len = ftell(fpin);
108 fseek(fpin, 0L, SEEK_SET);
109
110 h = disc_create(&spec);
111
112 /* Disk block #2 (directory) */
113 memset(sectorbuf, 0, sizeof(sectorbuf));
114 sectorbuf[0] = 1; /* OBJ (machine language program) */
115 memcpy(sectorbuf + 1,"IPLPRO", 6);
116
117 /* Now the filename from offset 8 */
118 for ( i = 7 ; i < 20; i++ ) {
119 int slen = i - 7;
120 sectorbuf[i] = strlen(blockname) > slen ? blockname[slen] : ' ';
121 }
122 sectorbuf[20] = 0x0d; // Terminate name
123 // sectorbuf[22] = 0; //
124 // sectorbuf[23] = 0x80;
125 sectorbuf[24] = 0; // Load address
126 sectorbuf[25] = 0x80;
127 sectorbuf[30] = 0x30; // Start sector
128 sectorbuf[31] = 0x00;
129
130 sectorbuf[32] = 12; // Memory bank for $2000...$e000
131 sectorbuf[33] = 13; // Next bank
132 sectorbuf[34] = 14; // Next bank
133 sectorbuf[35] = 0xff; // Terminate
134
135 // Banking at start of execution
136 sectorbuf[48] = 8; // for $000
137 sectorbuf[49] = 9;
138 sectorbuf[50] = 10;
139 sectorbuf[51] = 11;
140 sectorbuf[52] = 12;
141 sectorbuf[53] = 13;
142 sectorbuf[54] = 14;
143 sectorbuf[55] = 15;
144 write_sector(h, 0, 0, 1);
145
146 // Write info from input file to dsk per sector (in blocks of 256)
147 // Append trailing blanks if bytes_read is smaller than the size of a sector
148 // Start writing on track 2, first sector (block 0x30)
149 track = 1; sector = 0; head = 0;
150 bytes_to_write = len;
151
152 while ( 0 < bytes_to_write ) {
153 memset(sectorbuf, 0, sizeof(sector)); // Fill sector buffer with data (and evt trailing blanks)
154 bytes_read = fread(sectorbuf, sizeof(uint8_t), 256, fpin);
155 if (bytes_read == 0) { fclose(fpin); exit_log(1, "Could not read required data from <%s>\n", binname); }
156
157 write_sector(h, track, sector, head); // Write sector buffer to sector on dsk
158 bytes_to_write -= bytes_read;
159
160 sector++; // Adjust track, sector, head to write next
161 if ( sector == 16 ) {
162 sector = 0;
163 head ^= 1;
164 if ( head == 1 ) track++;
165 }
166 }
167
168 fclose(fpin);
169 disc_write_edsk(h, filename);
170 disc_free(h);
171
172 return 0;
173 }
174