/[projet1]/public/pc/tools/osdk/main/bas2tap/sources/bas2tap.cpp
Defence Force logotype

Contents of /public/pc/tools/osdk/main/bas2tap/sources/bas2tap.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1127 - (show annotations)
Fri May 9 20:01:39 2014 UTC (5 years, 6 months ago) by Hialmar
File size: 9353 byte(s)
Bas2tap now adds names to the generated tape (either from the #file directive or from the name of the file).
1
2 #include "infos.h"
3
4 #include "common.h"
5
6 #include <stdlib.h>
7 #include <stdio.h>
8 #ifdef _WIN32
9 #include <conio.h>
10 #else
11 #define memicmp strncasecmp
12 #endif
13 #include <string.h>
14
15 //
16 // Things to do:
17 // - Handle auto-numeration and labels
18 // - Option to optimize the programs (truncate variables to two characters, remove comments)
19 //
20
21 char *keywords[]=
22 {
23 "END","EDIT","STORE","RECALL","TRON","TROFF","POP","PLOT",
24 "PULL","LORES","DOKE","REPEAT","UNTIL","FOR","LLIST","LPRINT","NEXT","DATA",
25 "INPUT","DIM","CLS","READ","LET","GOTO","RUN","IF","RESTORE","GOSUB","RETURN",
26 "REM","HIMEM","GRAB","RELEASE","TEXT","HIRES","SHOOT","EXPLODE","ZAP","PING",
27 "SOUND","MUSIC","PLAY","CURSET","CURMOV","DRAW","CIRCLE","PATTERN","FILL",
28 "CHAR","PAPER","INK","STOP","ON","WAIT","CLOAD","CSAVE","DEF","POKE","PRINT",
29 "CONT","LIST","CLEAR","GET","CALL","!","NEW","TAB(","TO","FN","SPC(","@",
30 "AUTO","ELSE","THEN","NOT","STEP","+","-","*","/","^","AND","OR",">","=","<",
31 "SGN","INT","ABS","USR","FRE","POS","HEX$","&","SQR","RND","LN","EXP","COS",
32 "SIN","TAN","ATN","PEEK","DEEK","LOG","LEN","STR$","VAL","ASC","CHR$","PI",
33 "TRUE","FALSE","KEY$","SCRN","POINT","LEFT$","RIGHT$","MID$"
34 };
35
36 unsigned char head[14]={ 0x16,0x16,0x16,0x24,0,0,0,0,0,0,5,1,0,0 };
37
38
39
40
41 void Tap2Bas(unsigned char *ptr_buffer,size_t file_size)
42 {
43 unsigned int i, car;
44
45 if (ptr_buffer[0]!=0x16 || ptr_buffer[3]!=0x24)
46 {
47 ShowError("Not an Oric file");
48 }
49 if (ptr_buffer[6])
50 {
51 ShowError("Not a BASIC file");
52 }
53 i=13;
54 while (ptr_buffer[i++]);
55 while (ptr_buffer[i] || ptr_buffer[i+1])
56 {
57 i+=2;
58 printf(" %u ",ptr_buffer[i]+(ptr_buffer[i+1]<<8));
59 i+=2;
60 while (car=ptr_buffer[i++])
61 {
62 if (car<128)
63 putchar(car);
64 else
65 printf("%s",keywords[car-128]);
66 }
67 putchar('\n');
68 }
69 }
70
71
72
73 // tap2bas
74 int search_keyword(const char *str)
75 {
76 for (int i=0;i<sizeof(keywords)/sizeof(char *);i++)
77 {
78 if (strncmp(keywords[i],str,strlen(keywords[i]))==0)
79 {
80 return i;
81 }
82 }
83 return -1;
84 }
85
86
87
88 void Bas2Tap(const char *sourceFile,const char *destFile,bool autoRun,bool useColor)
89 {
90 unsigned char buf[48192];
91 unsigned int end, lastptr, adr;
92 int j,ptr,keyw,string,rem,data;
93
94 // Mike: Need to improve the parsing of this with a global function to split
95 // a text file in separate lines.
96 std::vector<std::string> textData;
97 if (!LoadText(sourceFile,textData))
98 {
99 ShowError("Unable to load source file");
100 }
101
102 std::string currentFile=sourceFile;
103 int currentLineNumber=0;
104 int i=0;
105 std::vector<std::string>::const_iterator lineIt=textData.begin();
106 while (lineIt!=textData.end())
107 {
108 const std::string& currentLine=*lineIt;
109
110 ++currentLineNumber;
111
112 if (!currentLine.empty())
113 {
114 const char* ligne=currentLine.c_str();
115 if (ligne[0]=='#')
116 {
117 // Preprocessor directive
118 if (memicmp(ligne,"#file",5)==0)
119 {
120 //"#file font.BAS""
121 // Very approximative "get the name of the file and reset the line counter" code.
122 // Will clean up that when I will have some more time.
123 ligne+=5;
124 currentFile=ligne;
125 currentLineNumber=0;
126 }
127 else
128 {
129 ShowError("Unknown preprocessor directive in file %s line number line %d",currentFile.c_str(),currentLineNumber);
130 }
131 }
132 else
133 {
134 // Standard line
135 buf[i++]=0;
136 buf[i++]=0;
137
138 int number=get_value(ligne,-1);
139 if (number<0)
140 {
141 // Mike: Need to add better diagnostic here
142 ShowError("Missing line number in file %s line %d",currentFile.c_str(),currentLineNumber);
143 break;
144 }
145 buf[i++]=number&0xFF;
146 buf[i++]=number>>8;
147
148 ptr=0;
149 rem=0;
150 bool color=useColor;
151 string=0;
152 data=0;
153 if (ligne[ptr]==' ') ptr++;
154
155 while (ligne[ptr])
156 {
157 if (rem)
158 {
159 if (color)
160 {
161 color=false;
162 buf[i++]=27; // ESCAPE
163 buf[i++]='B'; // GREEN labels
164 }
165 buf[i++]=ligne[ptr++];
166 }
167 else
168 if (string)
169 {
170 if (ligne[ptr]=='"') string=0;
171 buf[i++]=ligne[ptr++];
172 }
173 else
174 if (data)
175 {
176 if (ligne[ptr]==':') data=0;
177 buf[i++]=ligne[ptr++];
178 }
179 else
180 {
181 const char* pLine=(ligne+ptr);
182 keyw=search_keyword(pLine);
183 if (keyw==29 || ligne[ptr]=='\'') rem=1;
184 if (keyw==17) data=1;
185 if (ligne[ptr]=='"') string=1;
186 if (keyw>=0)
187 {
188 buf[i++]=keyw+128;
189 ptr+=strlen(keywords[keyw]);
190 }
191 else
192 {
193 buf[i++]=ligne[ptr++];
194 }
195 }
196 }
197 buf[i++]=0;
198 }
199 }
200 ++lineIt;
201 }
202 buf[i++]=0;
203 buf[i++]=0;
204
205 //following line modified by Wilfrid AVRILLON (Waskol) 06/20/2009
206 //It should follow this rule of computation : End_Address=Start_Address+File_Size-1
207 //Let's assume a 1 byte program, it starts at address #501 and ends at address #501 (Address=Address+1-1) !
208 //It was a blocking issue for various utilities (tap2wav for instance)
209 //end=0x501+i-1; //end=0x501+i;
210 end=0x501+i;
211
212 if (autoRun) head[7]=0x80; // Autorun for basic :)
213 else head[7]=0;
214
215 head[8]=end>>8;
216 head[9]=end&0xFF;
217
218 for(j=4,lastptr=0;j<i;j++)
219 {
220 if (buf[j]==0)
221 {
222 adr=0x501+j+1;
223 buf[lastptr]=adr&0xFF;
224 buf[lastptr+1]=adr>>8;
225 lastptr=j+1;
226 j+=4;
227 }
228 }
229
230 //
231 // Save file
232 //
233 FILE *out=fopen(destFile,"wb");
234 if (out==NULL)
235 {
236 printf("Can't open file for writing\n");
237 exit(1);
238 }
239 fwrite(head,1,13,out);
240 // write the name
241 if (currentFile.length > 0) {
242 char *fileName = strdup(currentFile.c_str());
243 // only take the file name from the path
244 // try to find \\
245 char *lastsep = strrchr(fileName, '\\');
246 if (lastsep != NULL) {
247 // if there is something after the separator
248 if (lastsep + 1 != 0)
249 fileName = lastsep + 1;
250 }
251 else {
252 // try to find /
253 lastsep = strrchr(fileName, '/');
254 if (lastsep != NULL) {
255 // if there is something after the separator
256 if (lastsep + 1 != 0)
257 fileName = lastsep + 1;
258 }
259 }
260 // remove the extension if there is one
261 char *lastdot = strrchr(fileName, '.');
262 if (lastdot != NULL)
263 *lastdot = 0;
264 fwrite(fileName, 1, strlen(fileName), out);
265 free(fileName);
266 }
267 fwrite("\x00", 1, 1, out);
268 fwrite(buf,1,i+1,out);
269 // oricutron bug work around
270 //fwrite("\x00", 1, 1, out);
271 fclose(out);
272 }
273
274
275
276
277 #define NB_ARG 2
278
279 int main(int argc, char **argv)
280 {
281 //
282 // Some initialization for the common library
283 //
284 SetApplicationParameters(
285 "Bas2Tap",
286 TOOL_VERSION_MAJOR,
287 TOOL_VERSION_MINOR,
288 "{ApplicationName} - Version {ApplicationVersion} - This program is a part of the OSDK\r\n"
289 "\r\n"
290 "Author:\r\n"
291 " Fabrice Frances \r\n"
292 "\r\n"
293 "Purpose:\r\n"
294 " Converting a text file containing a BASIC source code to a binary\r\n"
295 " encoded TAPE file that can be loaded using the CLOAD command.\r\n"
296 " (and the opposite operation as well).\r\n"
297 "\r\n"
298 "Parameters:\r\n"
299 " <options> <sourcefile> <destinationfile>\r\n"
300 "\r\n"
301 "Options:\r\n"
302 " -b2t[0|1] for converting to tape format with autorun (1) or not (0)\r\n"
303 " -t2b for converting from tape format text\r\n"
304 " -color[0|1] for enabling colored comments"
305 "\r\n"
306 "Exemple:\r\n"
307 " {ApplicationName} -b2t1 final.txt osdk.tap\r\n"
308 " {ApplicationName} -t2b osdk.tap program.txt\r\n"
309 );
310
311 bool basicToTape=true;
312 bool autoRun=true;
313 bool useColor=false;
314
315 ArgumentParser argumentParser(argc,argv);
316
317 while (argumentParser.ProcessNextArgument())
318 {
319 if (argumentParser.IsSwitch("-t2b"))
320 {
321 // Tape to BASIC source code
322 basicToTape=false;
323 }
324 else
325 if (argumentParser.IsSwitch("-b2t"))
326 {
327 // BASIC source code to tape
328 basicToTape=true;
329 autoRun=argumentParser.GetBooleanValue(true);
330 }
331 else
332 if (argumentParser.IsSwitch("-color"))
333 {
334 // Handling of color codes
335 useColor=argumentParser.GetBooleanValue(false);
336 }
337 }
338
339 if (argumentParser.GetParameterCount()!=NB_ARG)
340 {
341 ShowError(0);
342 }
343
344
345 std::string nameSrc(argumentParser.GetParameter(0));
346 std::string nameDst(argumentParser.GetParameter(1));
347
348 if (basicToTape)
349 {
350 Bas2Tap(nameSrc.c_str(),nameDst.c_str(),autoRun,useColor);
351 }
352 else
353 {
354 // Load the source file
355 void* ptr_buffer_void;
356 size_t file_size;
357 if (!LoadFile(nameSrc.c_str(),ptr_buffer_void,file_size))
358 {
359 ShowError("Unable to load the source file");
360 }
361 unsigned char *ptr_buffer=(unsigned char*)ptr_buffer_void;
362
363 Tap2Bas(ptr_buffer,file_size);
364 }
365
366 exit(0);
367 }

  ViewVC Help
Powered by ViewVC 1.1.26