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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1127 - (hide annotations)
Fri May 9 20:01:39 2014 UTC (5 years, 5 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 dbug 70
2     #include "infos.h"
3    
4     #include "common.h"
5    
6     #include <stdlib.h>
7     #include <stdio.h>
8 Jylam 1125 #ifdef _WIN32
9 dbug 70 #include <conio.h>
10 Jylam 1125 #else
11     #define memicmp strncasecmp
12     #endif
13 dbug 70 #include <string.h>
14    
15 dbug 1119 //
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 dbug 70
21 Jylam 1125 char *keywords[]=
22     {
23 dbug 1119 "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 dbug 70 };
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 dbug 1119 unsigned int i, car;
44 dbug 70
45 Jylam 1125 if (ptr_buffer[0]!=0x16 || ptr_buffer[3]!=0x24)
46     {
47 dbug 1119 ShowError("Not an Oric file");
48     }
49 Jylam 1125 if (ptr_buffer[6])
50     {
51     ShowError("Not a BASIC file");
52 dbug 1119 }
53 Jylam 1125 i=13;
54 dbug 1119 while (ptr_buffer[i++]);
55 Jylam 1125 while (ptr_buffer[i] || ptr_buffer[i+1])
56 dbug 1119 {
57     i+=2;
58     printf(" %u ",ptr_buffer[i]+(ptr_buffer[i+1]<<8));
59     i+=2;
60 Jylam 1125 while (car=ptr_buffer[i++])
61 dbug 1119 {
62 Jylam 1125 if (car<128)
63 dbug 1119 putchar(car);
64 Jylam 1125 else
65 dbug 1119 printf("%s",keywords[car-128]);
66     }
67     putchar('\n');
68     }
69 dbug 70 }
70    
71    
72    
73     // tap2bas
74     int search_keyword(const char *str)
75     {
76 dbug 1119 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 dbug 70 }
85    
86    
87    
88 dbug 1119 void Bas2Tap(const char *sourceFile,const char *destFile,bool autoRun,bool useColor)
89 dbug 70 {
90 dbug 1119 unsigned char buf[48192];
91     unsigned int end, lastptr, adr;
92     int j,ptr,keyw,string,rem,data;
93 dbug 70
94 Jylam 1125 // Mike: Need to improve the parsing of this with a global function to split
95 dbug 1119 // 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 dbug 70
102 dbug 1119 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 dbug 70
110 dbug 1119 ++currentLineNumber;
111 dbug 70
112 dbug 1119 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 Jylam 1125 buf[i++]=0;
137 dbug 70
138 dbug 1119 int number=get_value(ligne,-1);
139 Jylam 1125 if (number<0)
140 dbug 1119 {
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 Jylam 1125 buf[i++]=number&0xFF;
146 dbug 1119 buf[i++]=number>>8;
147 dbug 70
148 Jylam 1125 ptr=0;
149 dbug 1119 rem=0;
150     bool color=useColor;
151 Jylam 1125 string=0;
152 dbug 1119 data=0;
153     if (ligne[ptr]==' ') ptr++;
154 dbug 70
155 Jylam 1125 while (ligne[ptr])
156 dbug 1119 {
157 Jylam 1125 if (rem)
158 dbug 1119 {
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 Jylam 1125 }
167     else
168     if (string)
169 dbug 1119 {
170     if (ligne[ptr]=='"') string=0;
171     buf[i++]=ligne[ptr++];
172 Jylam 1125 }
173     else
174     if (data)
175 dbug 1119 {
176     if (ligne[ptr]==':') data=0;
177     buf[i++]=ligne[ptr++];
178 Jylam 1125 }
179     else
180 dbug 1119 {
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 Jylam 1125 if (keyw>=0)
187 dbug 1119 {
188 Jylam 1125 buf[i++]=keyw+128;
189 dbug 1119 ptr+=strlen(keywords[keyw]);
190 Jylam 1125 }
191     else
192 dbug 1119 {
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 dbug 70
205 dbug 1119 //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 Jylam 1125 //Let's assume a 1 byte program, it starts at address #501 and ends at address #501 (Address=Address+1-1) !
208 dbug 1119 //It was a blocking issue for various utilities (tap2wav for instance)
209     //end=0x501+i-1; //end=0x501+i;
210     end=0x501+i;
211 dbug 208
212 dbug 1119 if (autoRun) head[7]=0x80; // Autorun for basic :)
213     else head[7]=0;
214 dbug 70
215 dbug 1119 head[8]=end>>8;
216     head[9]=end&0xFF;
217 dbug 70
218 dbug 1119 for(j=4,lastptr=0;j<i;j++)
219     {
220 Jylam 1125 if (buf[j]==0)
221 dbug 1119 {
222 Jylam 1125 adr=0x501+j+1;
223     buf[lastptr]=adr&0xFF;
224 dbug 1119 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 Jylam 1125 if (out==NULL)
235     {
236     printf("Can't open file for writing\n");
237     exit(1);
238 dbug 1119 }
239 Hialmar 1127 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 Jylam 1125 fwrite(buf,1,i+1,out);
269 Hialmar 1127 // oricutron bug work around
270     //fwrite("\x00", 1, 1, out);
271 dbug 1119 fclose(out);
272 dbug 70 }
273    
274    
275    
276    
277     #define NB_ARG 2
278    
279 Jylam 1125 int main(int argc, char **argv)
280 dbug 70 {
281 dbug 1119 //
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 Jylam 1125 "Parameters:\r\n"
299 dbug 1119 " <options> <sourcefile> <destinationfile>\r\n"
300     "\r\n"
301 Jylam 1125 "Options:\r\n"
302 dbug 1119 " -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 Hialmar 1127 "\r\n"
306 dbug 1119 "Exemple:\r\n"
307     " {ApplicationName} -b2t1 final.txt osdk.tap\r\n"
308     " {ApplicationName} -t2b osdk.tap program.txt\r\n"
309     );
310 dbug 70
311 dbug 1119 bool basicToTape=true;
312 Jylam 1125 bool autoRun=true;
313 dbug 1119 bool useColor=false;
314 dbug 70
315 dbug 1119 ArgumentParser argumentParser(argc,argv);
316 dbug 70
317 dbug 1119 while (argumentParser.ProcessNextArgument())
318     {
319     if (argumentParser.IsSwitch("-t2b"))
320 dbug 70 {
321 dbug 1119 // Tape to BASIC source code
322     basicToTape=false;
323 dbug 70 }
324 Jylam 1125 else
325 dbug 1119 if (argumentParser.IsSwitch("-b2t"))
326     {
327     // BASIC source code to tape
328     basicToTape=true;
329     autoRun=argumentParser.GetBooleanValue(true);
330     }
331 Jylam 1125 else
332 dbug 1119 if (argumentParser.IsSwitch("-color"))
333     {
334     // Handling of color codes
335     useColor=argumentParser.GetBooleanValue(false);
336     }
337     }
338 dbug 70
339 dbug 1119 if (argumentParser.GetParameterCount()!=NB_ARG)
340     {
341     ShowError(0);
342     }
343 dbug 70
344    
345 dbug 1119 std::string nameSrc(argumentParser.GetParameter(0));
346     std::string nameDst(argumentParser.GetParameter(1));
347 dbug 70
348 dbug 1119 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 dbug 70 }

  ViewVC Help
Powered by ViewVC 1.1.26