10

I am trying to convert my own BASIC TAP files (containing BASIC programs) to text so that they are readable on my Debian GNU/Linux machine.

If I open them as is, I get this, which gives me some hope, as at least some parts are readable:

rainbow2  <o�$�>�
 �Rainbowtype 2.0

 �0
    �0
( �
2 �b=0
< �b

The first line is evidently a header with the filename, and the rest corresponds to:

10 REM Rainbowtype 2.0
20 BORDER 0
30 PAPER 0
40 CLS
50 LET b=0
60 BRIGHT b

This gives me hope that it might be a simple conversion, which could be done with tr or sed etc.

Here is the output od -x as requested by @cup (first ten lines):

0000000 0013 0000 6172 6e69 6f62 3277 2020 033c
0000020 806f 0324 3eab ff03 0a00 0012 ea20 6152
0000040 6e69 6f62 7477 7079 2065 2e32 0d30 1400
0000060 000a e720 0e30 0000 0000 0d00 1e00 0009
0000100 30da 000e 0000 0000 000d 0328 2000 0dfb
0000120 3200 000c f120 3d62 0e30 0000 0000 0d00
0000140 3c00 0004 dc20 0d62 4600 000a d920 0e37
0000160 0000 0007 0d00 6400 0007 ea20 614d 6e69
0000200 000d 0a6e 2000 30f2 000e 0000 0000 000d
0000220 2778 2000 a6fa 3d20 c220 3231 0e20 0000

Here is the output of xxd (entire program) as requested by @wizzwizz4:

00000000: 1300 0000 7261 696e 626f 7732 2020 3c03  ....rainbow2  <.
00000010: 6f80 2403 ab3e 03ff 000a 1200 20ea 5261  o.$..>...... .Ra
00000020: 696e 626f 7774 7970 6520 322e 300d 0014  inbowtype 2.0...
00000030: 0a00 20e7 300e 0000 0000 000d 001e 0900  .. .0...........
00000040: da30 0e00 0000 0000 0d00 2803 0020 fb0d  .0........(.. ..
00000050: 0032 0c00 20f1 623d 300e 0000 0000 000d  .2.. .b=0.......
00000060: 003c 0400 20dc 620d 0046 0a00 20d9 370e  .<.. .b..F.. .7.
00000070: 0000 0700 000d 0064 0700 20ea 4d61 696e  .......d.. .Main
00000080: 0d00 6e0a 0020 f230 0e00 0000 0000 0d00  ..n.. .0........
00000090: 7827 0020 faa6 203d 20c2 3132 200e 0000  x'. .. = .12 ...
000000a0: 0c00 00cb ed35 3030 0e00 00f4 0100 3aed  .....500......:.
000000b0: 3130 300e 0000 6400 000d 0082 2500 20fa  100...d.....%. .
000000c0: a620 3d20 c237 200e 0000 0700 00cb d931  . = .7 ........1
000000d0: 0e00 0001 0000 3a20 ed31 3030 0e00 0064  ......: .100...d
000000e0: 0000 0d00 8c25 0020 faa6 203d 20c2 3620  .....%. .. = .6 
000000f0: 0e00 0006 0000 cbd9 320e 0000 0200 003a  ........2......:
00000100: 20ed 3130 300e 0000 6400 000d 0096 2500   .100...d.....%.
00000110: 20fa a620 3d20 c234 200e 0000 0400 00cb   .. = .4 .......
00000120: d933 0e00 0003 0000 3a20 ed31 3030 0e00  .3......: .100..
00000130: 0064 0000 0d00 a025 0020 faa6 203d 20c2  .d.....%. .. = .
00000140: 3520 0e00 0005 0000 cbd9 340e 0000 0400  5 ........4.....
00000150: 003a 20ed 3130 300e 0000 6400 000d 00aa  .: .100...d.....
00000160: 2500 20fa a620 3d20 c238 200e 0000 0800  %. .. = .8 .....
00000170: 00cb d935 0e00 0005 0000 3a20 ed31 3030  ...5......: .100
00000180: 0e00 0064 0000 0d00 b426 0020 faa6 203d  ...d.....&. .. =
00000190: 20c2 3130 200e 0000 0a00 00cb d936 0e00   .10 ........6..
000001a0: 0006 0000 3a20 ed31 3030 0e00 0064 0000  ....: .100...d..
000001b0: 0d00 be26 0020 faa6 203d 20c2 3131 200e  ...&. .. = .11 .
000001c0: 0000 0b00 00cb d937 0e00 0007 0000 3a20  .......7......: 
000001d0: ed31 3030 0e00 0064 0000 0d00 c828 0020  .100...d.....(. 
000001e0: faa6 203d 20c2 3920 0e00 0009 0000 cbf1  .. = .9 ........
000001f0: 6220 3d20 c362 3a20 dc62 3a20 ed31 3030  b = .b: .b: .100
00000200: 0e00 0064 0000 0d00 d21f 0020 faa6 203d  ...d....... .. =
00000210: 20c2 3135 200e 0000 0f00 00cb fb3a 20ed   .15 ........: .
00000220: 3130 300e 0000 6400 000d 00dc 0400 f5a6  100...d.........
00000230: 3b0d 00fa 0c00 20ed 3130 300e 0000 6400  ;..... .100...d.
00000240: 000d 01f4 0800 ea44 656c 6574 650d 01fe  .......Delete...
00000250: 2400 20f1 7970 6f73 203d 2028 2032 3420  $. .ypos = ( 24 
00000260: 0e00 0018 0000 2d20 be32 3336 3839 0e00  ......- .23689..
00000270: 0089 5c00 290d 0208 2400 f178 706f 7320  ..\.)...$..xpos 
00000280: 3d20 2820 3332 200e 0000 2000 002d 20be  = ( 32 ... ..- .
00000290: 3233 3638 3820 0e00 0088 5c00 290d 0212  23688 ....\.)...
000002a0: 2600 20fa 7870 6f73 203d 202d 3120 0e00  &. .xpos = -1 ..
000002b0: 0001 0000 c620 7970 6f73 203d 2030 200e  ..... ypos = 0 .
000002c0: 0000 0000 00cb fe0d 021c 3b00 20fa 7870  ..........;. .xp
000002d0: 6f73 203d 202d 3120 0e00 0001 0000 cbf1  os = -1 ........
000002e0: 7870 6f73 203d 2033 310e 0000 1f00 003a  xpos = 31......:
000002f0: 20f1 7970 6f73 203d 2079 706f 7320 2d31   .ypos = ypos -1
00000300: 0e00 0001 0000 0d02 2613 0020 f5ac 7970  ........&.. ..yp
00000310: 6f73 2c20 7870 6f73 3b20 2220 220d 0230  os, xpos; " "..0
00000320: 1300 20f5 ac79 706f 732c 2078 706f 733b  .. ..ypos, xpos;
00000330: 2022 223b 0d02 5803 0020 fe0d 6200 0001   "";..X.. ..b...
00000340: 0000 b970 6ff3 0000 0100 00b8 706f f300  ...po.......po..
00000350: 0015 0000 92                             .....

I looked at World of Spectrum Utilities, but most utilities seem to be for Windows. There is one for Linux, but it converts SNA files. In the Debian repositories I found zmakebas, but that does the opposite (converts text to TAP).

  • Could you od -x the file and add it to the post? The ? looks like it is different characters. – cup Feb 24 '18 at 15:26
  • @cup, I've done as you suggested - see above! – harlandski Feb 24 '18 at 15:48
  • ZX-Editor (mostly compatible with WINE) should be able to open these files. Does this work? – wizzwizz4 Feb 24 '18 at 15:50
  • @wizzwizz4 I'd rather not install wine yet - would prefer to find a native option, but I'll consider it if all else fails :-) – harlandski Feb 24 '18 at 15:52
  • @harlandski Could you xxd the data? I'm having trouble reversing the od. – wizzwizz4 Feb 24 '18 at 15:59
12

listbasic, from the fuse-emulator-utils Debian package:

$ listbasic rainbow2.tap
   10 REM Rainbowtype 2.0
   20 BORDER 0
   30 PAPER 0
   40 CLS 
   50 LET b=0
   60 BRIGHT b
   70 INK 7
  100 REM Main
  110 PAUSE 0
  120 IF INKEY$ = CHR$ 12 THEN GO SUB 500: GO SUB 100
  130 IF INKEY$ = CHR$ 7 THEN INK 1: GO SUB 100
  140 IF INKEY$ = CHR$ 6 THEN INK 2: GO SUB 100
  150 IF INKEY$ = CHR$ 4 THEN INK 3: GO SUB 100
  160 IF INKEY$ = CHR$ 5 THEN INK 4: GO SUB 100
  170 IF INKEY$ = CHR$ 8 THEN INK 5: GO SUB 100
  180 IF INKEY$ = CHR$ 10 THEN INK 6: GO SUB 100
  190 IF INKEY$ = CHR$ 11 THEN INK 7: GO SUB 100
  200 IF INKEY$ = CHR$ 9 THEN LET b = NOT b: BRIGHT b: GO SUB 100
  210 IF INKEY$ = CHR$ 15 THEN CLS : GO SUB 100
  220 PRINT INKEY$;
  250 GO SUB 100
  500 REM Delete
  510 LET ypos = ( 24 - PEEK 23689)
  520 LET xpos = ( 32 - PEEK 23688 )
  530 IF xpos = -1 AND  ypos = 0 THEN RETURN 
  540 IF xpos = -1 THEN LET xpos = 31: LET ypos = ypos -1
  550 PRINT AT ypos, xpos; " "
  560 PRINT AT ypos, xpos; "";
  600 RETURN 
  • 1
    Just what I was looking for, and checked on my system! – harlandski Feb 25 '18 at 12:03
8

TAP files are basicly memory dumps of whatever is saved. In this case the tokenized BASIC program. Check here for a format description.

It seems that the simplest way would be to load it into an emulator and 'print' it into a text file. fuse should be able to automate most of this.

I'm not sure, but think I remember several utilities to convert TAP into some kind of disk files, where again a different set of tools might be available.

Or just hack your own conversion tool and become incredibly famous among Sinclair-Linux users - it shouldn't be that hard :)

  • 4
    In addition to the TAP format, in order to decode it yourself, you'll also need to know (1) the Spectrum character set (which includes the token bytes used by BASIC) and (2) the memory format used by the BASIC interpreter, both of which are reasonably simple. (While the latter link is technically about the 128K ROM's version of BASIC, it is backward compatible ... otherwise it wouldn't have been able to load existing programs) – Jules Feb 24 '18 at 22:08
6

There is a Windows program called ZX-Editor that runs perfectly well on Debian (via Wine). Simply open the .TAP file, and save a .BAS file. It allowed me to extract this:

# BAS file "rainbow2" created by ZX-Modules

# Run-time Variables

Var b: Num = 1
Var ypos: Num = 1
Var xpos: Num = 21

# End Run-time Variables

  10 REM Rainbowtype 2.0
  20 BORDER 0
  30 PAPER 0
  40 CLS 
  50 LET b=0
  60 BRIGHT b
  70 INK 7
 100 REM Main
 110 PAUSE 0
 120 IF INKEY$ = CHR$ 12 THEN GO SUB 500: GO SUB 100
 130 IF INKEY$ = CHR$ 7 THEN INK 1: GO SUB 100
 140 IF INKEY$ = CHR$ 6 THEN INK 2: GO SUB 100
 150 IF INKEY$ = CHR$ 4 THEN INK 3: GO SUB 100
 160 IF INKEY$ = CHR$ 5 THEN INK 4: GO SUB 100
 170 IF INKEY$ = CHR$ 8 THEN INK 5: GO SUB 100
 180 IF INKEY$ = CHR$ 10 THEN INK 6: GO SUB 100
 190 IF INKEY$ = CHR$ 11 THEN INK 7: GO SUB 100
 200 IF INKEY$ = CHR$ 9 THEN LET b = NOT b: BRIGHT b: GO SUB 100
 210 IF INKEY$ = CHR$ 15 THEN CLS : GO SUB 100
 220 PRINT INKEY$;
 250 GO SUB 100
 500 REM Delete
 510 LET ypos = ( 24 - PEEK 23689)
 520 LET xpos = ( 32 - PEEK 23688 )
 530 IF xpos = -1 AND  ypos = 0 THEN RETURN 
 540 IF xpos = -1 THEN LET xpos = 31: LET ypos = ypos -1
 550 PRINT AT ypos, xpos; " "
 560 PRINT AT ypos, xpos; "";
 600 RETURN 

There are a few bugs, such as the possible replacement of all GO TOs with GO SUBs(? unverified), but it seems to work mostly fine. The program was actually written that way. No bugs to be seen!

  • 2
    Should all those GO SUBs be GO TOs? – Jim Garrison Feb 24 '18 at 18:28
  • 2
    @harlandski: The GO SUBs probably make the program crash if you type enough text into it, since the call stack grows on every keypress. But it's possible that your kids' patience typically runs out before the stack space does. :) And at least if the crash is interesting enough, you might be able to turn it into an educational opportunity. (Alas, this page suggests that it just prints "Out of memory". How boring.) – Ilmari Karonen Feb 25 '18 at 15:07
  • 1
    @harlandski In BASIC, you can't really avoid GO TO. GO SUB is worse if you're using it like GO TO. The only thing that should be a GO SUB is GO SUB 500; everything else should be GO TO. – wizzwizz4 Feb 25 '18 at 17:00
  • 1
    @harlandski "never use GOTO" is the second worst -- after OOP -- idea ever foisted upon programmers by Comp Sci professors, and is was lead to the horrendous COBOL textbooks by Shelley & Cashman. – RonJohn Feb 27 '18 at 4:54
  • 1
    @RonJohn Never use GOTO unless you absolutely have to. Better? (Also, this is getting a bit off-topic.) – wizzwizz4 Feb 27 '18 at 8:07
2

well some time ago I coded Win32 utility to convert MDOS 3.0 *.P files (which are the same as BASIC tap files) into text. You need the keyword/command table for that. Here is the VCL/C++ code extracted from the tool of mine:

// all ZX ASCII codes from 165 to 255 are BASIC commands
const AnsiString zx_table[91]=
    {
    " RND "," INKEY$ "," PI "," FN "," POINT "," SCREEN$ "," ATTR "," AT "," TAB "," VAL$ "," CODE "," VAL "," LEN "," SIN "," COS "," TAN "," ASN "," ACS ",
    " ATN "," LN "," EXP "," INT "," SOR "," SGN "," ABS "," PEEK "," IN "," USR "," STR$ "," CHR$ "," NOT "," BIN "," OR "," AND "," <="," >="," <>"," LINE ",
    " THEN "," TO "," STEP "," DEF "," CAT "," FORMAT "," MOVE "," ERASE "," OPEN# "," CLOSE# "," MERGE "," VERIFY "," BEEP "," CIRCLE "," INK "," PAPER ",
    " FLASH "," BRIGHT "," INVERSE "," OVER "," OUT "," LPRINT "," LLIST "," STOP "," READ "," DATA "," RESTORE "," NEW "," BORDER "," CONTINUE "," DIM ",
    " REM "," FOR "," GOTO "," GOSUB "," INPUT "," LOAD "," LIST "," LET "," PAUSE "," NEXT "," POKE "," PRINT "," PLOT "," RUN "," SAVE "," RANDOMIZE ",
    " IF "," CLS "," DRAW "," CLEAR "," RETURN "," COPY "
    };


void editor::loadzxbas(AnsiString file)
    {
    txt="";
    win_adr=1;
    win_x0=0;
    win_y0=0;
    sbys=0;
    _redraw=true;       
    _change=false;

    int hnd,siz;
    BYTE *dat;
    hnd=FileOpen(file,fmOpenRead);
    if (hnd<0) return;
    siz=FileSeek(hnd,0,2);
        FileSeek(hnd,0,0);
    dat=new char[siz];
    if (dat==NULL) { FileClose(hnd); return; }
    siz=FileRead(hnd,dat,siz);
    FileClose(hnd);

    int i,l,a,_a,linenum;
    AnsiString s;
    DWORD a0,a1,a2,a3,a4;
    for (hnd=0;hnd<siz;)    // copy and count lines
        {
        if (hnd>=siz) break;    // line number
        a0=dat[hnd]; hnd++;
        if (hnd>=siz) break;
        a1=dat[hnd]; hnd++;
        linenum=(a1+(a0<<8));
        if (linenum<10000) txt+=" ";
        if (linenum< 1000) txt+=" ";
        if (linenum<  100) txt+=" ";
        if (linenum<   10) txt+=" ";
        txt+=linenum;
        txt+=" ";
        if (hnd>=siz) break;    // line length
        a0=dat[hnd]; hnd++;
        if (hnd>=siz) break;
        a1=dat[hnd]; hnd++;
        l=(a0+(a1<<8));
        for (s="",i=0;i<l;i++)  // load line
            {
            if (hnd>=siz) break;
            a=dat[hnd]; hnd++;
            s+=char(a);
            }
        l=i;
        if (linenum<=9999)          // BASIC lines
         for (a=0,i=1;i<=l;)
            {
            _a=a;
            a=BYTE(s[i]); i++;
            if (a>=165)  txt+=zx_table[a-165];
            else if (a>=32) txt+=char(a);
            if (a==14)  // number
                {
                if (i+5>l) break;
                a0=BYTE(s[i]); i++;
                a1=BYTE(s[i]); i++;
                a2=BYTE(s[i]); i++;
                a3=BYTE(s[i]); i++;
                a4=BYTE(s[i]); i++;
                if ((_a<'0')||(_a>'9'))
                    {
                    if (a0==0)  // int
                        {
                        int x;
                        x=a2+(a3<<8);
                        if (a1) x=-x;
                        txt+=x;
                        }
                    else{       // float
                        txt+="/float/";
                        }
                    }
                }
            }
        else{                   // Data area
            int x=0,n=8;
            AnsiString t;
            for (i=1;i<=l;)
                {
                a=BYTE(s[i]); i++;
                if (x) txt+=",";
                else { if (i>2) txt+="      "; txt+=" db "; t=" // "; }
                if (a<16) txt+="0";
                txt+=AnsiString().sprintf("%X",BYTE(a));  x++;
                if ((a<32)||(a>164)) t+="."; else t+=char(BYTE(a));
                if (x>=n) { txt+=t+"\n"; x=0; sbys++; }
                }
            if (x)
                {
                for (;x<n;x++) txt+="   ";
                txt+=t+"\n"; x=0; sbys++;
                }
            }

        txt+="\n"; sbys++;
        }
    delete dat;
    }
//---------------------------------------------------------------------------

where editor::txt is AnsiString containing your decoded text. You can ignore the _redraw,_change bools they are just for proper redraw and save of teh editor class. There are 2 things going on.

  1. ASCII codes above 164

    are the BASIC keywords/commands so you need to swap them with the string from the zx_table[]

  2. numbers

    ASCII code 14 marks number and needs to be properly decoded to string.

The AnsiString is a VCL string variable type indexed from 1. With all this you should have all you need to code/port this on your own to Linux ...

btw the tool of mine recognize x86 asm, Z80 asm and BASIC files with syntax highlight. Here a META thread related to its syntax highlight:

And here non class code with syntax highlight tables (from another tool of mine):

//---------------------------------------------------------------------------
//--- syntax ver: 1.02 ------------------------------------------------------
//---------------------------------------------------------------------------
#include "font_DG89.h"
//---------------------------------------------------------------------------
const _editor_syntax syntax_Z80_asm=
    {
    // keywords
    { "ADC","ADD","AND","BIT","CALL","CCF","CP","CPD","CPDR","CPI","CPIR","CPL","DAA",
    "DEC","DI","DJNZ","EI","EX","EXX","HALT","IM0","IM1","IM2","IN","INC","IND","INDR",
    "INI","INIR","JP","JR","LD","LDD","LDDR","LDI","LDIR","neg","NOP","OR","OTDR","OTIR",
    "OUT","OUTD","OUTI","POP","PUSH","RES","ret","RETI","RETN","RL","RLA","RLC","RLCA",
    "RLD","RR","RRA","RRA","RRC","RRCA","RRD","RST","SBC","SCF","SET","SLA","SLL","SRA",
    "SRL","SUB","XOR",
    "adc","add","and","bit","call","ccf","cp","cpd","cpdr","cpi","cpir","cpl","daa",
    "dec","di","djnz","ei","ex","exx","halt","im0","im1","im2","in","inc","ind","indr",
    "ini","inir","jp","jr","ld","ldd","lddr","ldi","ldir","neg","nop","or","otdr","otir",
    "out","outd","outi","pop","push","res","ret","reti","retn","rl","rla","rlc","rlca",
    "rld","rr","rra","rra","rrc","rrca","rrd","rst","sbc","scf","set","sla","sll","sra",
    "srl","sub","xor",""
    },
    // brackets
    { "(",")","[","]","{","}","PUSH","POP","push","pop","" },
    // operators
    { "+","-","*","/","%","&","|","^","!",":",",","" },
    // remblck
    { "" },
    // remline
    { "rem","REM" },
    // preproc
    { "" },
    // wordspc
    { "" },
    };
//---------------------------------------------------------------------------
const _editor_syntax syntax_Z80_bas=
    {
    // keywords
    { "RND","INKEY$","PI","FN","POINT","SCREEN$","ATTR","AT","TAB","VAL$","CODE","VAL","LEN","SIN","COS","TAN","ASN","ACS",
    "ATN","LN","EXP","INT","SOR","SGN","ABS","PEEK","IN","USR","STR$","CHR$","NOT","BIN","OR","AND","<=",">=","<>","LINE",
    "THEN","TO","STEP","DEF","CAT","FORMAT","MOVE","ERASE","OPEN#","CLOSE#","MERGE","VERIFY","BEEP","CIRCLE","INK","PAPER",
    "FLASH","BRIGHT","INVERSE","OVER","OUT","LPRINT","LLIST","STOP","READ","DATA","RESTORE","NEW","BORDER","CONTINUE","DIM",
    "REM","FOR","GOTO","GOSUB","INPUT","LOAD","LIST","LET","PAUSE","NEXT","POKE","PRINT","PLOT","RUN","SAVE","RANDOMIZE",
    "IF","CLS","DRAW","CLEAR","RETURN","COPY",
/*
    "rnd","inkey$","pi","fn","point","screen$","attr","at","tab","val$","code","val","len","sin","cos","tan","asn","acs",
    "atn","ln","exp","int","sor","sgn","abs","peek","in","usr","str$","chr$","not","bin","or","and","<=",">=","<>","line",
    "then","to","step","def","cat","format","move","erase","open#","close#","merge","verify","beep","circle","ink","paper",
    "flash","bright","inverse","over","out","lprint","llist","stop","read","data","restore","new","border","continue","dim",
    "rem","for","goto","gosub","input","load","list","let","pause","next","poke","print","plot","run","save","randomize",
    "if","cls","draw","clear","return","copy",
*/
    "" },
    // brackets
    { "(",")","[","]","" },
    // operators
    { "+","-","*","/","%","&","|","^","!","<=",">=","<>","=",":",",",";","" },
    // remblck
    { "" },
    // remline
    { ";","" },
    // preproc
    { "" },
    // wordspc
    { "" },
    };
//---------------------------------------------------------------------------
// all ZX ASCII codes from 165 to 255 are BASIC commands
const AnsiString zx_table[91]=
    {
    "RND ","INKEY$ ","PI ","FN ","POINT ","SCREEN$ ","ATTR ","AT ","TAB ","VAL$ ","CODE ","VAL ","LEN ","SIN ","COS ","TAN ","ASN ","ACS ",
    "ATN ","LN ","EXP ","INT ","SOR ","SGN ","ABS ","PEEK ","IN ","USR ","STR$ ","CHR$ ","NOT ","BIN ","OR ","AND ","<=",">=","<>","LINE ",
    "THEN ","TO ","STEP ","DEF ","CAT ","FORMAT ","MOVE ","ERASE ","OPEN# ","CLOSE# ","MERGE ","VERIFY ","BEEP ","CIRCLE ","INK ","PAPER ",
    "FLASH ","BRIGHT ","INVERSE ","OVER ","OUT ","LPRINT ","LLIST ","STOP ","READ ","DATA ","RESTORE ","NEW ","BORDER ","CONTINUE ","DIM ",
    "REM ","FOR ","GOTO ","GOSUB ","INPUT ","LOAD ","LIST ","LET ","PAUSE ","NEXT ","POKE ","PRINT ","PLOT ","RUN ","SAVE ","RANDOMIZE ",
    "IF ","CLS ","DRAW ","CLEAR ","RETURN ","COPY "
    };
//---------------------------------------------------------------------------
void Z80_load_asm(editor &dst,AnsiString file)
    {
    dst.load(file);
    dst.set_font(&font_DG89,1,2);
    dst.tab=8;
    dst.syntax    =(_editor_syntax*)&syntax_Z80_asm;
    dst.syntax_asm=(_editor_syntax*)&syntax_Z80_asm;
    dst.scann();
    }
//---------------------------------------------------------------------------
void Z80_load_bas(editor &dst,AnsiString file)
    {
    dst.loadtext("");
    int hnd,siz;
    BYTE *dat;
    hnd=FileOpen(file,fmOpenRead);
    if (hnd<0) return;
    siz=FileSeek(hnd,0,2);
        FileSeek(hnd,0,0);
    dat=new char[siz];
    if (dat==NULL) { FileClose(hnd); return; }
    siz=FileRead(hnd,dat,siz);
    FileClose(hnd);

    int i,l,a,_a,linenum;
    AnsiString s;
    DWORD a0,a1,a2,a3,a4;
    for (hnd=0;hnd<siz;)    // copy and count lines
        {
        if (hnd>=siz) break;    // line number
        a0=dat[hnd]; hnd++;
        if (hnd>=siz) break;
        a1=dat[hnd]; hnd++;
        linenum=(a1+(a0<<8));
        if (linenum<10000) dst.txt+=" ";
        if (linenum< 1000) dst.txt+=" ";
        if (linenum<  100) dst.txt+=" ";
        if (linenum<   10) dst.txt+=" ";
        dst.txt+=linenum;
        dst.txt+=" ";
        if (hnd>=siz) break;    // line length
        a0=dat[hnd]; hnd++;
        if (hnd>=siz) break;
        a1=dat[hnd]; hnd++;
        l=(a0+(a1<<8));
        for (s="",i=0;i<l;i++)  // load line
            {
            if (hnd>=siz) break;
            a=dat[hnd]; hnd++;
            s+=char(a);
            }
        l=i;
        if (linenum<=9999)          // BASIC lines
         for (a=0,i=1;i<=l;)
            {
            _a=a;
            a=BYTE(s[i]); i++;
            if (a>=165)
                {
                if ((dst.txt!="")&&(dst.txt[dst.txt.Length()]!=' ')) dst.txt+=" ";
                dst.txt+=zx_table[a-165];
                }
            else if (a>=32) dst.txt+=char(a);
            if (a==14)  // number
                {
                if (i+5>l) break;
                a0=BYTE(s[i]); i++;
                a1=BYTE(s[i]); i++;
                a2=BYTE(s[i]); i++;
                a3=BYTE(s[i]); i++;
                a4=BYTE(s[i]); i++;
                if ((_a<'0')||(_a>'9'))
                    {
                    if (a0==0)  // int
                        {
                        int x;
                        x=a2+(a3<<8);
                        if (a1) x=-x;
                        dst.txt+=x;
                        }
                    else{       // float
                        dst.txt+="/float/";
                        }
                    }
                }
            }
        else{                   // Data area
            int x=0,n=8;
            AnsiString t;
            for (i=1;i<=l;)
                {
                a=BYTE(s[i]); i++;
                if (x) dst.txt+=",";
                else { if (i>2) dst.txt+="      "; dst.txt+=" db "; t=" // "; }
                if (a<16) dst.txt+="0";
                dst.txt+=AnsiString().sprintf("0%Xh",BYTE(a));  x++;
                if ((a<32)||(a>164)) t+="."; else t+=char(BYTE(a));
                if (x>=n) { dst.txt+=t+dst.endl; x=0; }
                }
            if (x)
                {
                for (;x<n;x++) dst.txt+="     ";
                dst.txt+=t+dst.endl; x=0;
                }
            }
        dst.txt+=dst.endl;
        }
    delete dat;
    dst.set_font(&font_DG89,1,2);
    dst.syntax    =(_editor_syntax*)&syntax_Z80_bas;
    dst.syntax_asm=(_editor_syntax*)&syntax_Z80_asm;
    dst.scann();
    }
//---------------------------------------------------------------------------
void Z80_load_txt(editor &dst,AnsiString file)
    {
    dst.loadtext("");
    int hnd,siz;
    BYTE *dat;
    hnd=FileOpen(file,fmOpenRead);
    if (hnd<0) return;
    siz=FileSeek(hnd,0,2);
        FileSeek(hnd,0,0);
    dat=new char[siz];
    if (dat==NULL) { FileClose(hnd); return; }
    siz=FileRead(hnd,dat,siz);
    FileClose(hnd);
    int x=0;
    BYTE a;
    for (hnd=0;hnd<siz;)    // copy and count lines
        {
        BYTE a=dat[hnd]; hnd++;

             if (a==128) a='e';
        else if (a==130) a='s';
        else if (a==131) a='c';
        else if (a==133) a='y';
        else if (a==134) a='a';
        else if (a==135) a='i';
        else if (a==136) a='u';
        else if (a==137) a='o';
        else if (a==138) a='o';
        else if (a==139) a='d';
        else if (a==143) a='z';
//      else if (a>127) a=a;

        dst.txt+=char(a);
        x++; if (x>=64) { dst.txt+=dst.endl; x=0; }
        }
    delete dat;
    dst.set_font(&font_DG89,1,2);
    dst.syntax    =(_editor_syntax*)NULL;
    dst.syntax_asm=(_editor_syntax*)NULL;
    dst.scann();
    }
//---------------------------------------------------------------------------
void Z80_load(editor &dst,AnsiString file)
    {
    AnsiString ext=ExtractFileExt(file).LowerCase();
    dst.syntax    =(_editor_syntax*)NULL;
    dst.syntax_asm=(_editor_syntax*)NULL;
         if (ext==".asm") Z80_load_asm(dst,file);
    else if (ext==".p"  ) Z80_load_bas(dst,file);
    else                  Z80_load_txt(dst,file);
    }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.