29 #ifdef CBM_BASIC_TEXT_SUPPORT
179 {0xce07,
"rspcolor" },
190 {0xfe08,
"sprcolor" },
192 {0xfe0a,
"envelope" },
206 {0xfe17,
"collision"},
229 static const char *ERROR_HEAD =
"BASIC program exporting error:\n";
231 static const char *end_of_line =
NL;
232 static const char *tex_head =
"\\verbatimfont{\\codefont}\n\\begin{verbatim}\n";
233 static const char *tex_end =
"\\end{verbatim}\n";
236 #define CONTEXT_POINTER0 0
237 #define CONTEXT_POINTER1 1
238 #define CONTEXT_LINENO0 2
239 #define CONTEXT_LINENO1 3
240 #define CONTEXT_NORMAL 4
241 #define CONTEXT_QUOTED 5
242 #define CONTEXT_REM 6
243 #define CONTEXT_BEGIN 7
244 #define CONTEXT_END 8
247 int xemu_basic_to_text_malloc (
Uint8 **buffer,
int output_super_limit,
const Uint8 *
prg,
int real_addr,
const Uint8 *prg_limit,
int basic_dialect,
int flags )
249 int size = xemu_basic_to_text(NULL, output_super_limit,
prg, real_addr, prg_limit, basic_dialect,
flags);
254 *buffer = malloc(
size + 1);
259 size = xemu_basic_to_text(*buffer,
size,
prg, real_addr, prg_limit, basic_dialect,
flags);
269 int xemu_basic_to_text (
Uint8 *output,
int output_size,
const Uint8 *
prg,
int real_addr,
const Uint8 *prg_limit,
int basic_dialect,
int flags )
273 const char *o = NULL;
274 int num = -1, old_num = -1;
276 int context = CONTEXT_BEGIN;
280 ERROR_WINDOW(
"%sProgram flows outside of the allowed memory area after line %d", ERROR_HEAD, old_num);
285 if (context == CONTEXT_BEGIN) {
287 context = CONTEXT_POINTER1;
288 if ((
flags & BASIC_TO_TEXT_FLAG_TEX))
292 }
else if (context == CONTEXT_POINTER0) {
293 printf(
"ptr_to_here=%d real_addr=%d, delta=%d\n", ptr, real_addr, real_addr-ptr);
294 if (ptr != real_addr - 1) {
295 ERROR_WINDOW(
"%sBad BASIC chaining near line %d", ERROR_HEAD, num);
299 context = CONTEXT_POINTER1;
301 }
else if (context == CONTEXT_POINTER1) {
304 if ((
flags & BASIC_TO_TEXT_FLAG_TEX)) {
305 context = CONTEXT_END;
310 context = CONTEXT_LINENO0;
313 }
else if (context == CONTEXT_LINENO0) {
314 context = CONTEXT_LINENO1;
318 }
else if (context == CONTEXT_LINENO1) {
320 context = CONTEXT_NORMAL;
321 sprintf(outbuf,
"%5d ", num);
323 }
else if (context == CONTEXT_NORMAL && (c >= 0x80 || token != 0)) {
324 if ((c == 0xCE || c == 0xFE) && token == 0) {
328 for (
int a = 0 ;; a++) {
329 if (basic_tokens[a].token == token) {
330 o = basic_tokens[a].str;
332 }
else if (basic_tokens[a].token == 0) {
333 ERROR_WINDOW(
"%sUnknown token $%04X in line %d", ERROR_HEAD, token, num);
338 context = CONTEXT_REM;
343 ERROR_WINDOW(
"%sUnfinished extended token sequence in line %d", ERROR_HEAD, num);
346 context = CONTEXT_POINTER0;
350 if (context == CONTEXT_NORMAL)
351 context = CONTEXT_QUOTED;
352 else if (context == CONTEXT_QUOTED)
353 context = CONTEXT_NORMAL;
355 if (c >=
'A' && c <=
'Z')
357 else if (c >= (
'A' | 0x80) && c <= (
'Z' | 0x80))
365 ERROR_WINDOW(
"%sInternal error, uninitialized output buffer in line %d", ERROR_HEAD, num);
370 ERROR_WINDOW(
"%sOutput buffer is too small for this program in line %d", ERROR_HEAD, num);
389 static const struct {
392 } conv_tab_screen[] = {
405 { 0x82,
"{uloff}"}, { 0x83,
"{stop}" }, { 0x85,
"{wht}" }, { 0x87,
"{bell}" },
406 { 0x89,
"{ht}" }, { 0x8A,
"{lf}" }, { 0x8B,
"{shen}" }, { 0x8C,
"{shdi}" }, { 0x8D,
"{ret}" }, { 0x8E,
"{text}" }, { 0x8F,
"{flon}" },
407 { 0x90,
"{f9}" }, { 0x91,
"{down}" }, { 0x92,
"{rvon}" }, { 0x93,
"{home}" }, { 0x94,
"{del}" }, { 0x95,
"{f10}" }, { 0x96,
"{f11}" }, { 0x97,
"{f12}" },
408 { 0x98,
"{tab}" }, { 0x99,
"{f13}" }, { 0x9A,
"{f14}" }, { 0x9B,
"{esc}" }, { 0x9C,
"{red}" }, { 0x9D,
"{right}"}, { 0x9E,
"{grn}" }, { 0x9F,
"{blu}" },
410 { 0xE1,
"{orng}" }, { 0xE2,
"{ulon}" }, { 0xE3,
"{run}" }, { 0xE4,
"{help}" }, { 0xE5,
"{f1}" }, { 0xE6,
"{f3}" }, { 0xE7,
"{f5}" },
411 { 0xE8,
"{f7}" }, { 0xE9,
"{f2}" }, { 0xEA,
"{f4}" }, { 0xEB,
"{f6}" }, { 0xEC,
"{f8}" }, { 0xED,
"{sret}" }, { 0xEE,
"{gfx}" }, { 0xEF,
"{floff}"},
412 { 0xD0,
"{blk}" }, { 0xD1,
"{up}" }, { 0xD2,
"{rvoff}"}, { 0xD3,
"{clr}" }, { 0xD4,
"{inst}" }, { 0xD5,
"{brn}" }, { 0xD6,
"{lred}" }, { 0xD7,
"{gry1}" },
413 { 0xD8,
"{gry2}" }, { 0xD9,
"{lgrn}" }, { 0xDA,
"{lblu}" }, { 0xDB,
"{gry3}" }, { 0xDC,
"{pur}" }, { 0xDD,
"{left}" }, { 0xDE,
"{yel}" }, { 0xDF,
"{cyn}" },
422 for (
int y = 0;
y < rows;
y++) {
423 for (
int x = 0;
x < cols;
x++) {
425 ERROR_WINDOW(
"Sorry, ASCII converted screen does not fit into the output buffer");
430 for (
int a = 0; conv_tab_screen[a].text; a++) {
432 t += sprintf(t,
"%s", conv_tab_screen[a].
text);
438 if (c >= 0x01 && c <= 0x1A) {
439 *t++ = c - 1 + (lowercase ?
'a' :
'A');
442 if (c >= 0x20 && c <= 0x3F) {
446 if (c >= 0x41 && c <= 0x5A) {
450 t += sprintf(t,
"{%c}", c);
454 t += sprintf(t,
"{$%02X}", c);
459 while (t > buffer && t[-1] ==
' ')
461 t += sprintf(t,
"%s",
NL);
464 while (t > buffer && (t[-1] ==
'\r' || t[-1] ==
'\n'))
468 while (*buffer ==
'\r' || *buffer ==
'\n')
477 const Uint8 *start = v;
478 const Uint8 *end = v + (cols * rows);
479 char ch_prev, ch = 0;
481 while (*buffer && v < end) {
484 for (
int a = 0; conv_tab_screen[a].text; a++) {
485 const int l = strlen(conv_tab_screen[a].
text);
486 if (!strncmp(conv_tab_screen[a].
text, buffer, l)) {
487 *v++ = conv_tab_screen[a].screen_code;
497 const char *p = strchr(buffer,
'}');
502 const int l = (int)(p - buffer);
505 }
else if (l == 3 && *buffer ==
'$') {
507 const Uint8 h = (
Uint8)strtol(buffer + 1, &e, 16);
518 if (ch ==
'\n' || ch ==
'\r') {
519 if ((ch_prev ==
'\n' || ch_prev ==
'\r') && ch_prev != ch) {
524 while ((v - start) % cols)
532 if ((
signed char)ch < 32)
534 if (ch >= 0x61 && ch <= 0x7A) {
535 *v++ = ch - 0x61 + 1;
538 if (ch >= 0x41 && ch <= 0x5A) {
539 *v++ = lowercase ? ch : ch - 0x41 + 1;
542 if (ch >= 0x20 && ch <= 0x3F) {
547 DEBUGPRINT(
"PASTE: unknown ASCII character: %c (%d)" NL, ch, (
unsigned int)ch);
552 while (v < end && ((v - start) % cols))