package turgen.plugin.kblock;

import turgen.plugin.*;
import turgen.generator.SignalGenerator;
import java.io.*;
import javax.swing.*;
import turgen.PulsesException;
import turgen.Turgen;
import turgen.Utils;
import turgen.dtb.DOS2Binary;
import turgen.playlist.AbstractPlayListItem;
import turgen.config.*;
import turgen.plugin.csturbo.LoaderBinaryData;
import turgen.tapeimage.TapeImageChunk;

public class KBlockPlugin implements Plugin {
    
    
    private String lastError;
    private KBlockPluginPanel panel;
    private InOutProvider ioProvider;
    private int[] casChunkName={116,114,50,107};

    private ConfigClass cfcKBlock;
    private IntegerConfigEntry cfgPilotLenA;
    private IntegerConfigEntry cfgPilotLenKBlock;
    private IntegerConfigEntry cfgPilotLenLoaderA;
    private IntegerConfigEntry cfgPilotLenLoaderB;
    private IntegerConfigEntry cfgSilenceAfterLoader;
    private IntegerConfigEntry cfgSilenceAfterHeader;
    private BooleanConfigEntry cfgLoaderNamedAsFile;
    private BooleanConfigEntry cfgPrependLoader;

    public static final int BL_NONE=0;
    public static final int BL_MINITBL=1;
    public static final int BL_NANOTBL=2;
    public static final int BL_NANOTBL_UR=3;
    public static final int BL_NANOTBL_U2=4;

    /** Nova instance KBlockPlugin */
    public KBlockPlugin() {
    }
    
    /** Identifikacni jmeno modulu*/
    public String getName() {
        return "Turbo 2000 - kilobyte blocks";
    }
    
    
    /*************************************************************/
    
    /**Tvorba instrukci pro generator*/
    public int[] getInstructions(AbstractPlayListItem _pl) {
        
        KBlockPlayListItem pl;
        
        pl=(KBlockPlayListItem)_pl;
        RandomAccessFile raf = null;
        
        try {
            
            
            /*Nacteni vstupniho souboru jako pole int[]*/
            int[] fileData;
            byte[] b;
            raf = new RandomAccessFile(pl.inFile,"r");
            if (raf.length()>1024*1024) throw new FileTooLargeException(pl.inFile);
            b=new byte[(int)raf.length()];
            raf.readFully(b);

            /*Uzavreni vstupniho souboru*/
            raf.close();

            /*Konverze na int*/
            fileData = new int[b.length];
            for(int i=0;i<b.length;i++) {
                fileData[i]=b[i]<0?b[i]+256:b[i];
            }

            /*Check for binary file*/
            int[] initLocations;
            try {
                DOS2Binary dtb = new DOS2Binary(pl.inFile);
                dtb.analyzeFromData(fileData);
                initLocations = dtb.getInitLocations();
            }
            catch (Exception e) {
                initLocations = new int[0];
            }
            
            InstructionStream is = new InstructionStream();
            
            /*If loader is to be prepended, then we prepend it*/
            if (cfgPrependLoader.getAsBoolean()==true) {
                for(int i=0;i<LoaderBinaryData.universalTurboLoader.length;i++) {
                    is.add(LoaderBinaryData.universalTurboLoader[i]);
                }
            }
            
            /*Pripadne pridani zavadece*/
            prependLoader(is,pl);

            /*Nastaveni*/
            Utils.addSetupInstruction(is, pl.pulses, casChunkName,SignalGenerator.FLAG_POLARITY_10,SignalGenerator.FLAG_ORDER_HL);
            
            /*Hlavicka*/
            is.add(SignalGenerator.INSTR_PILOTTONE);
            is.add(cfgPilotLenA.getAsInt());
            is.add(SignalGenerator.INSTR_SYNC);
            is.add(SignalGenerator.INSTR_DATA);
            is.add(19);
            
            int[] header = new int[19];
            header[0]=0;
            header[1]=0;
            
            /*Vymezerovat nazev*/
            for(int i=2;i<18;i++) {
                header[i]=32;
            }
            
            /*Nazev - 16 bajtu*/
            int bar=pl.fname.length()<16 ? pl.fname.length() :16;
            byte[] nameBytes = pl.fname.substring(0,bar).getBytes();
            /*Konverze na int*/
            for(int i=0;i<nameBytes.length;i++) {
                header[2+i]=(nameBytes[i]<0) ? nameBytes[i]+256 : nameBytes[i];
            }
            
            /*Kontrolni soucet hlavicky*/
            int chsum=header[0];
            for(int i=1;i<18;i++) {
                chsum=chsum ^ header[i];
            }
            /*Chsum*/
            header[18]=chsum;
            is.add(header);

            /*Safety pulse + safety pause*/
            is.add(SignalGenerator.INSTR_NARROW);
            is.add(SignalGenerator.INSTR_BLOCKSEP);
            
            /*Dalsi pauza*/
            is.add(SignalGenerator.INSTR_LONGSILENCE);
            is.add(cfgSilenceAfterHeader.getAsInt());
            
            /*Vlastni bloky dat, po 1024 bytech*/
            int ptr=0;  /*Pozice v datech*/
            
            int dl=fileData.length-1;   /*Index posledniho prvku dat*/
            int bcount=0;
            
            
            int startPtr;
            int endPtr;

            /*Pokud nejsou poslana vsechna data*/
            while (ptr<fileData.length) {

                startPtr=ptr;
                
                /*Zavadeci ton bloku*/
                is.add(SignalGenerator.INSTR_PILOTTONE);
                is.add(cfgPilotLenKBlock.getAsInt());

                /*Synchropulz*/
                is.add(SignalGenerator.INSTR_SYNC);
                
                /*Vlastni blok*/
                is.add(SignalGenerator.INSTR_DATA);
                is.add(1026);
                
                
                /*Typ bloku*/
                /*Zbyva 1024 a vice bytu - 255*/
                if ((dl-ptr+1)>=1024) {
                    is.add(255);
                    chsum=255;
                    bcount=1024;
                }
                /*Zbyva mene nez 1024 bajtu*/
                else {
                    /*Kdyz je to vice nez 0, je to neuplny blok*/
                    if ((dl-ptr+1)>0) {
                        /*Kolik je to stranek ?*/
                        is.add(((dl-ptr+1)/256)+251);
                        chsum=((dl-ptr+1)/256)+251;
                        bcount=dl-ptr+1;
                    }
                    /*Je to 0, to bude koncovy blok*/
                    else {
                        is.add(250);
                        chsum=250;
                        bcount=0;
                    }
                }
                
                /*Data bloku*/
                 
                 for(int i=0;i<bcount;i++) {
                     chsum=chsum^fileData[ptr];
                     is.add(fileData[ptr]);ptr++;
                     
                 }
                 /*Doplnit nulami na 1023*/
                 for (int i=0;i<(1023-bcount);i++) {
                     chsum=chsum^0;
                     is.add(0);
                 }
                
                 if (bcount<1024) {
                     chsum=chsum^(bcount % 256);
                     is.add(bcount % 256);
                 }
                 
                 is.add(chsum);

                 endPtr=ptr;
                 
                /*Safety pulse*/
                is.add(SignalGenerator.INSTR_NARROW);

                /*Silence after init or simple block separation*/
                int wait=Utils.calculateInitSilence(startPtr, endPtr-1, initLocations, pl.pauses);
                if (wait==0) {
                    is.add(SignalGenerator.INSTR_BLOCKSEP);
                }
                else {
                    is.add(SignalGenerator.INSTR_LONGSILENCE);
                    is.add(Math.min(240, wait));
                }
                 
            }
            
            /*EOF BLOK*/
            /*Zavadeci ton bloku*/
            is.add(SignalGenerator.INSTR_PILOTTONE);
            is.add(cfgPilotLenKBlock.getAsInt());
            /*Synchropulz*/
            is.add(SignalGenerator.INSTR_SYNC);
            
            is.add(SignalGenerator.INSTR_DATA);
            is.add(1026);
            is.add(250);
            chsum=250;
            for(int i=0;i<1024;i++) {
                     chsum=chsum^0;
                     is.add(0);
            }
            is.add(chsum);

            /*Safety pulse + safety pause*/
            is.add(SignalGenerator.INSTR_NARROW);
            is.add(SignalGenerator.INSTR_BLOCKSEP);

            
            is.add(SignalGenerator.INSTR_END);
            
            return is.getInstructions();
            
        }
        
        catch(Exception e) {
            
            /*Uklidit*/
            try {
                
                raf.close();
                
            }
            catch(Exception xe) {
                
            }
            e.printStackTrace();
            if (e.getMessage()==null) lastError="Unable to produce instructions: "+e.toString();
            else lastError=e.toString();
            return null;
            
        }
        
        
    }
    
    public String getLastError() {
        return lastError;
    }
    
    public AbstractPlayListItem createItem() {
        SimplePlaylistItem dpr = panel.getRecord();
        dpr.pluginClass=Turgen.pluginManager.getPluginClassName(this);
        return dpr;
    }
    
    public void resetPanel() {
        panel.clear();
    }
    
    public String validateInput() {
        return panel.verify();
    }
    
    public JPanel getItemPanel() {
        return panel;
    }
    
    public void init() {
        panel = new KBlockPluginPanel();

        /*Initialize configuration class*/
        cfcKBlock = new ConfigClass("KBlock", "Turbo 2000 - kilobyte blocks");

        /*Initialize configuration entries*/
        cfgPilotLenA=new IntegerConfigEntry("pilotLenA","Header block pilot tone length [pulse]",3072,256,8192);
        cfgPilotLenKBlock=new IntegerConfigEntry("pilotLenBlock","Data block pilot tone length [pulse]",2048,256,8192);
        cfgPilotLenLoaderA=new IntegerConfigEntry("pilotLenLoaderA","Loader header block pilot tone length [pulse]",3072,256,8192);
        cfgPilotLenLoaderB=new IntegerConfigEntry("pilotLenLoaderB","Loader data block pilot tone length [pulse]",3072,256,8192);
        cfgSilenceAfterHeader=new IntegerConfigEntry("silenceAfterHeader","Silence after header [s]",0,0,30);
        cfgSilenceAfterLoader=new IntegerConfigEntry("silenceAfterLoader","Silence after loader [s]",3,0,30);
        cfgLoaderNamedAsFile = new BooleanConfigEntry("loaderNamedAsFile","Name loader same as file",false);
        cfgPrependLoader = new BooleanConfigEntry("prependLoader","Prepend Universal Turbo loader",false);

        /*Add entries to the class*/
        cfcKBlock.addEntry(cfgPilotLenA);
        cfcKBlock.addEntry(cfgPilotLenKBlock);
        cfcKBlock.addEntry(cfgPilotLenLoaderA);
        cfcKBlock.addEntry(cfgPilotLenLoaderB);
        cfcKBlock.addEntry(cfgSilenceAfterHeader);
        cfcKBlock.addEntry(cfgSilenceAfterLoader);
        cfcKBlock.addEntry(cfgLoaderNamedAsFile);
        cfcKBlock.addEntry(cfgPrependLoader);

        /*Register configuration class*/
        Configuration.registerClass(cfcKBlock);
    }
    
    public void fillPanel(AbstractPlayListItem plr) {
        KBlockPlayListItem dpr = (KBlockPlayListItem)plr;
        panel.fill(dpr);
    }

    

    public void setInOutProvider(InOutProvider prov) {
        ioProvider=prov;
        panel.ioProvider=prov;
    }


    private void prependLoader(InstructionStream is,KBlockPlayListItem pli) throws IOException,PulsesException {

        int[] t2kcasChunkName = {116, 114, 50, 107};
        String fname;
        int[] loaderData;

        int lload = 0;
        int lrun = 0;
        int llength = 0;

        /*Rozhodnuti, o jaky binarni loader se jedna*/
        switch (pli.loader) {
            case BL_MINITBL: {
                loaderData = minitbl_data;
                fname = "MINITBL";
                lload = 2750;
                lrun = 3560;
                llength = loaderData.length;
                break;
            }
            case BL_NANOTBL: {
                loaderData = nanotbl_data;
                fname = "NANOTBL";
                lload = 2818;
                lrun = 2818;
                llength = loaderData.length;
                break;
            }
            case BL_NANOTBL_UR: {
                loaderData = nanotbl_ur_data;
                fname = "NANOTBL_UR";
                lload = 1794;
                lrun = 1794;
                llength = loaderData.length;
                break;
            }
            case BL_NANOTBL_U2: {
                loaderData = nanotbl_u2_data;
                fname = "NANOTBL_U2";
                lload = 1794;
                lrun = 1794;
                llength = loaderData.length;
                break;
            }
            default: {
                return;
            }
        }

       

       /*Instrukce pro nastaveni*/
       Utils.addSetupInstruction(is, Turgen.pulseCache.getPulsesForPlugin(this)[0], t2kcasChunkName,SignalGenerator.FLAG_POLARITY_10,SignalGenerator.FLAG_ORDER_HL);

       /*BL header*/
       int[] hdr=null;
       
       /*Modify fname of loader if needed*/
        if (cfgLoaderNamedAsFile.getAsBoolean()==true) {
            fname=pli.fname;
            hdr = Utils.createT2KHeader(fname, 3, lload, llength, lrun,true);
        }
        else {
           hdr = Utils.createT2KHeader(fname, 3, lload, llength, lrun);
        }

       
       
       is.add(SignalGenerator.INSTR_PILOTTONE);
       is.add(cfgPilotLenLoaderA.getAsInt());
       is.add(SignalGenerator.INSTR_SYNC);

       is.add(SignalGenerator.INSTR_DATA);
       is.add(19);

       
       is.add(hdr);
       

       /*Safety pulse + safety pause*/
       is.add(SignalGenerator.INSTR_NARROW);
       is.add(SignalGenerator.INSTR_BLOCKSEP);

       /*BL data*/
       is.add(SignalGenerator.INSTR_PILOTTONE);
       is.add(cfgPilotLenLoaderB.getAsInt());
       is.add(SignalGenerator.INSTR_SYNC);

       int tmp = loaderData.length+2;
       int bar = loaderData.length;

       is.add(SignalGenerator.INSTR_DATA);
       is.add(tmp);

       int chsum = 255;
       is.add(255);
       for (int l = 0; l < bar; l++) {
            chsum = chsum ^ loaderData[l];
       }

       is.add(loaderData);
       is.add(chsum);

       /*Bezpecnostni pulz*/
       is.add(SignalGenerator.INSTR_NARROW);

       /*Pauza*/
       is.add(SignalGenerator.INSTR_LONGSILENCE);
       is.add(cfgSilenceAfterLoader.getAsInt());
       

    }
    
    
    private static int[] minitbl_data = {0xa0,0x00,0xb9,0x1a,0x03,0xf0,0x07,0xc8,0xc8,0xc8,0xc0,0x21,0x90,0xf4,0xa9,0x54,0x99,0x1a,0x03,0xa9,0x9a,0x99,0x1b,0x03,0xa9,0x0c,0x99,0x1c,0x03,0x60,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x20,0x12,0x0b,0xa9,0xff,0x20,0x7d,0x0b,0x90,0x03,0xa0,0x00,0x60,0xa0,0x80,0x60,0xa9,0x00,0x85,0x32,0xa9,0x07,0x85,0x33,0xa9,0x00,0x85,0x34,0xa9,
0x0b,0x85,0x35,0x60,0x20,0x12,0x0b,0xa6,0x39,0xe0,0x05,0xf0,0x1e,0xe0,0x00,0xd0,0x01,0x60,0x86,0x36,0xa9,0x04,0x38,0xe5,0x36,0x18,0x69,0x07,0xaa,0x18,0xa9,0x00,
0x6d,0xff,0x0a,0x85,0x34,0x90,0x01,0xe8,0x86,0x35,0x60,0xa9,0x07,0x85,0x35,0xa9,0x00,0x85,0x34,0x60,0xa5,0x32,0xc5,0x34,0xd0,0x16,0xa5,0x33,0xc5,0x35,0xd0,0x10,
0xa5,0x39,0xc9,0x00,0xd0,0x15,0x20,0x02,0x0b,0xc0,0x00,0xd0,0x0d,0x20,0x23,0x0b,0xa0,0x00,0xb1,0x32,0xe6,0x32,0xd0,0x02,0xe6,0x33,0x60,0xa0,0x88,0x60,0x85,0x36,
0xa9,0x34,0x8d,0x02,0xd3,0x8d,0x03,0xd3,0xa9,0x80,0x85,0x10,0x8d,0x0e,0xd2,0x18,0xa0,0x00,0x84,0x30,0x84,0x31,0x8c,0x0e,0xd4,0x8c,0x00,0xd4,0x08,0xd0,0x71,0x20,
0x28,0x0c,0x90,0xf9,0xa9,0x00,0x85,0x43,0x85,0x37,0xa0,0xb4,0x20,0x23,0x0c,0x90,0xec,0xc0,0xd8,0x90,0xea,0xe6,0x43,0xd0,0xf1,0xc6,0x37,0xa0,0xd1,0x20,0x28,0x0c,
0x90,0xdb,0xc0,0xde,0xb0,0xf5,0x20,0x28,0x0c,0x90,0x45,0xa0,0xc6,0x4c,0xea,0x0b,0x28,0xd0,0x09,0xa5,0x36,0x45,0x44,0x85,0x39,0x4c,0xe7,0x0b,0xa0,0x00,0xa5,0x44,
0x91,0x32,0xe6,0x32,0xd0,0x02,0xe6,0x33,0xa0,0xc8,0x08,0xa9,0x01,0x85,0x44,0x20,0x23,0x0c,0x90,0x1c,0xc0,0xe3,0x26,0x44,0xa0,0xc6,0x90,0xf3,0xa5,0x31,0x45,0x44,
0x85,0x31,0xa5,0x32,0xc5,0x34,0xa5,0x33,0xe5,0x35,0x90,0xc4,0xa9,0x00,0xc5,0x31,0x68,0xa9,0xc0,0x8d,0x0e,0xd4,0x85,0x10,0x8d,0x0e,0xd2,0xa9,0x3c,0x8d,0x02,0xd3,
0x8d,0x03,0xd3,0x60,0x20,0x28,0x0c,0x90,0x24,0xa2,0x04,0xca,0xd0,0xfd,0xa5,0x30,0x4a,0x25,0x37,0x8d,0x1a,0xd0,0xc8,0xf0,0x13,0xa5,0x11,0xf0,0x0d,0xad,0x0f,0xd2,
0x29,0x10,0xc5,0x30,0xf0,0xf0,0x85,0x30,0x38,0x60,0xc6,0x11,0x18,0x60,0xa9,0xff,0x8d,0xfc,0x02,0xa9,0x01,0x20,0xfc,0xfd,0x60,0xa5,0x2a,0x29,0x0c,0xc9,0x04,0xd0,
0x2f,0x20,0x4d,0x0c,0xa9,0x00,0x85,0x32,0xa9,0x07,0x85,0x33,0xa9,0x11,0x85,0x34,0xa9,0x07,0x85,0x35,0xa9,0x00,0x20,0x7d,0x0b,0x90,0xe9,0xa9,0x9b,0x8d,0x11,0x07,
0xa2,0x01,0xa0,0x07,0xa9,0x00,0x85,0x32,0x85,0x34,0xa9,0x0b,0x85,0x33,0x85,0x35,0xa0,0x00,0x84,0x39,0x60,0xa0,0x01,0x60,0xa0,0x00,0x60,0x57,0x0c,0x93,0x0c,0x52,
0x0b,0x96,0x0c,0xcb,0xfd,0xe4,0xfc,0x4c,0x94,0x0c,0x00,0x20,0xd7,0x0d,0x20,0xa1,0x0d,0xad,0x53,0x03,0x10,0x42,0x4c,0xc3,0x0d,0xa9,0x87,0x8d,0xe2,0x02,0xa9,0x0d,
0x8d,0xe3,0x02,0x20,0x53,0x0d,0xad,0x89,0x0d,0x85,0x36,0xad,0x8a,0x0d,0x85,0x37,0xad,0x88,0x0d,0xa0,0x00,0x91,0x36,0xad,0x89,0x0d,0xcd,0x8b,0x0d,0xd0,0x0e,0xad,
0x8a,0x0d,0xcd,0x8c,0x0d,0xd0,0x06,0x20,0x84,0x0d,0x4c,0xf7,0x0c,0xee,0x89,0x0d,0xd0,0x03,0xee,0x8a,0x0d,0x4c,0xc2,0x0c,0x20,0x53,0x0d,0xad,0x88,0x0d,0x8d,0x89,
0x0d,0x20,0x53,0x0d,0xad,0x88,0x0d,0x8d,0x8a,0x0d,0xc9,0xff,0xd0,0x0f,0xad,0x89,0x0d,0xc9,0xff,0xd0,0x08,0xa9,0x00,0x8d,0x8e,0x0d,0x4c,0xf7,0x0c,0xad,0x8e,0x0d,
0xc9,0x01,0xd0,0x03,0x4c,0xcd,0x0d,0x20,0x53,0x0d,0xad,0x88,0x0d,0x8d,0x8b,0x0d,0x20,0x53,0x0d,0xad,0x88,0x0d,0x8d,0x8c,0x0d,0xad,0x8d,0x0d,0xc9,0x01,0xd0,0x11,
0xad,0x89,0x0d,0x8d,0xe0,0x02,0xad,0x8a,0x0d,0x8d,0xe1,0x02,0xa9,0x00,0x8d,0x8d,0x0d,0x4c,0xb8,0x0c,0xa2,0x10,0xa9,0x07,0x9d,0x42,0x03,0xa9,0x88,0x9d,0x44,0x03,
0xa9,0x0d,0x9d,0x45,0x03,0xa9,0x01,0x9d,0x48,0x03,0xa9,0x00,0x9d,0x49,0x03,0x20,0x56,0xe4,0xad,0x53,0x03,0x30,0x01,0x60,0xaa,0x68,0x8a,0xc9,0x88,0xd0,0x45,0x20,
0x96,0x0d,0x6c,0xe0,0x02,0x6c,0xe2,0x02,0x60,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x54,0x3a,0x9b,0x42,0x9b,0x45,0x9b,0xa2,0x10,0xa9,0x0c,0x9d,0x42,0x03,0x20,0x56,
0xe4,0x60,0xa2,0x10,0xa9,0x03,0x9d,0x42,0x03,0xa9,0x04,0x9d,0x4a,0x03,0xa9,0x8f,0x9d,0x44,0x03,0xa9,0x0d,0x9d,0x45,0x03,0x20,0x56,0xe4,0xa9,0x01,0x8d,0x8d,0x0d,
0x8d,0x8e,0x0d,0x60,0xa2,0x94,0xa0,0x0d,0x20,0x42,0xc6,0x4c,0xaa,0x0c,0xa2,0x94,0xa0,0x0d,0x20,0x42,0xc6,0x4c,0xaa,0x0c,0xa9,0x00,0x8d,0x44,0x02,0xa9,0x01,0x85,
0x09,0xa2,0x8f,0xa0,0x0d,0x20,0x42,0xc6,0x60,0x20,0xbe,0x0a,0x4c,0xaa,0x0c,0x00};

    private static int nanotbl_data[] = {0x20,0x34,0x0d,0x20,0x01,0x0d,0x20,0x9d,0x0b,0x20,0xc3,0x0b,0x4c,0x50,0x0b,0xa9,0x27,0x8d,0xe2,0x02,0xa9,0x0c,0x8d,0xe3,0x02,0x20,0xf3,0x0b,0xad,0x1f,0x0c,0x85,0x36,
0xad,0x20,0x0c,0x85,0x37,0xad,0x1e,0x0c,0xa0,0x00,0x91,0x36,0xad,0x1f,0x0c,0xcd,0x21,0x0c,0xd0,0x0e,0xad,0x20,0x0c,0xcd,0x22,0x0c,0xd0,0x06,0x20,0x24,0x0c,0x4c,
0x50,0x0b,0xee,0x1f,0x0c,0xd0,0x03,0xee,0x20,0x0c,0x4c,0x1b,0x0b,0x20,0xf3,0x0b,0xad,0x1e,0x0c,0x8d,0x1f,0x0c,0x20,0xf3,0x0b,0xad,0x1e,0x0c,0x8d,0x20,0x0c,0xc9,
0xff,0xd0,0x0a,0xad,0x1f,0x0c,0xc9,0xff,0xd0,0x03,0x4c,0x50,0x0b,0x20,0xf3,0x0b,0xad,0x1e,0x0c,0x8d,0x21,0x0c,0x20,0xf3,0x0b,0xad,0x1e,0x0c,0x8d,0x22,0x0c,0xad,
0x23,0x0c,0xc9,0x01,0xd0,0x11,0xad,0x1f,0x0c,0x8d,0xe0,0x02,0xad,0x20,0x0c,0x8d,0xe1,0x02,0xa9,0x00,0x8d,0x23,0x0c,0x4c,0x11,0x0b,0x20,0xb2,0x0b,0xa9,0xff,0x20,
0x28,0x0c,0x90,0x01,0x60,0x68,0x68,0xa9,0xff,0x20,0xf8,0x0c,0x4c,0x05,0x0b,0xa9,0x00,0x85,0x34,0xa9,0x0b,0x85,0x35,0xa9,0x00,0x85,0x32,0xa9,0x07,0x85,0x33,0x60,
0x20,0xb2,0x0b,0xa6,0x39,0xe0,0x05,0xf0,0x1e,0xe0,0x00,0xd0,0x01,0x60,0x86,0x36,0xa9,0x04,0x38,0xe5,0x36,0x18,0x69,0x07,0xaa,0x18,0xa9,0x00,0x6d,0xff,0x0a,0x85,
0x34,0x90,0x01,0xe8,0x86,0x35,0x60,0xa9,0x07,0x85,0x35,0xa9,0x00,0x85,0x34,0x60,0xa5,0x32,0xc5,0x34,0xd0,0x12,0xa5,0x33,0xc5,0x35,0xd0,0x0c,0xa5,0x39,0xc9,0x00,
0xd0,0x14,0x20,0x9d,0x0b,0x20,0xc3,0x0b,0xa0,0x00,0xb1,0x32,0x8d,0x1e,0x0c,0xe6,0x32,0xd0,0x02,0xe6,0x33,0x60,0x68,0x6c,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x6c,0xe2,0x02,0x60,0x85,0x36,0xa9,0x34,0x8d,0x02,0xd3,0x8d,0x03,0xd3,0xa9,0x80,0x85,0x10,0x8d,0x0e,0xd2,0x18,0xa0,0x00,0x84,0x30,0x84,0x31,0x8c,0x0e,0xd4,
0x8c,0x00,0xd4,0x08,0xd0,0x71,0x20,0xd3,0x0c,0x90,0xf9,0xa9,0x00,0x85,0x2e,0x85,0x37,0xa0,0xb4,0x20,0xce,0x0c,0x90,0xec,0xc0,0xd8,0x90,0xea,0xe6,0x2e,0xd0,0xf1,
0xc6,0x37,0xa0,0xd1,0x20,0xd3,0x0c,0x90,0xdb,0xc0,0xde,0xb0,0xf5,0x20,0xd3,0x0c,0x90,0x45,0xa0,0xc6,0x4c,0x95,0x0c,0x28,0xd0,0x09,0xa5,0x36,0x45,0x2f,0x85,0x39,
0x4c,0x92,0x0c,0xa0,0x00,0xa5,0x2f,0x91,0x32,0xe6,0x32,0xd0,0x02,0xe6,0x33,0xa0,0xc8,0x08,0xa9,0x01,0x85,0x2f,0x20,0xce,0x0c,0x90,0x1c,0xc0,0xe3,0x26,0x2f,0xa0,
0xc6,0x90,0xf3,0xa5,0x31,0x45,0x2f,0x85,0x31,0xa5,0x32,0xc5,0x34,0xa5,0x33,0xe5,0x35,0x90,0xc4,0xa9,0x00,0xc5,0x31,0x68,0xa9,0xc0,0x85,0x10,0x8d,0x0e,0xd4,0x8d,
0x0e,0xd2,0xa9,0x3c,0x8d,0x02,0xd3,0x8d,0x03,0xd3,0x60,0x20,0xd3,0x0c,0x90,0x24,0xa2,0x04,0xca,0xd0,0xfd,0xa5,0x30,0x4a,0x25,0x37,0x8d,0x1a,0xd0,0xc8,0xf0,0x13,
0xa5,0x11,0xf0,0x0d,0xad,0x0f,0xd2,0x29,0x10,0xc5,0x30,0xf0,0xf0,0x85,0x30,0x38,0x60,0xc6,0x11,0x18,0x60,0x8d,0xfc,0x02,0xa9,0x01,0x20,0xfc,0xfd,0x60,0xa9,0x00,
0x85,0x32,0xa9,0x20,0x85,0x33,0xa9,0x11,0x85,0x34,0xa9,0x20,0x85,0x35,0xa9,0x01,0x8d,0x23,0x0c,0xa9,0x00,0x20,0x28,0x0c,0x90,0xe4,0xa9,0x9b,0x8d,0x11,0x20,0xa2,
0x01,0xa0,0x20,0x20,0x42,0xc6,0xa9,0x00,0x85,0x14,0xa5,0x14,0xc9,0x4b,0xd0,0xfa,0x60,0xa9,0x05,0x85,0x0c,0xa9,0x0b,0x85,0x0d,0xa9,0x00,0x8d,0x44,0x02,0xa9,0x01,
0x85,0x09,0xa2,0x52,0xa0,0x0d,0x20,0x42,0xc6,0xa9,0x01,0x20,0xf8,0x0c,0x60,0x4e,0x41,0x4e,0x4f,0x54,0x42,0x4c,0x9b};

    private static int nanotbl_ur_data[] = {0x20,0x71,0x09,0x20,0x38,0x09,0x20,0x09,0x09,0x20,0xa3,0x07,0x20,0xcc,0x07,0x20,0x21,0x09,0x4c,0x56,0x07,0xa9,0x39,0x8d,0xe2,0x02,0xa9,0x08,0x8d,0xe3,0x02,0x20,0xfc,
0x07,0xad,0x31,0x08,0x85,0x36,0xad,0x32,0x08,0x85,0x37,0xad,0x30,0x08,0xa0,0x00,0x91,0x36,0xad,0x31,0x08,0xcd,0x33,0x08,0xd0,0x0e,0xad,0x32,0x08,0xcd,0x34,0x08,
0xd0,0x06,0x20,0x36,0x08,0x4c,0x56,0x07,0xee,0x31,0x08,0xd0,0x03,0xee,0x32,0x08,0x4c,0x21,0x07,0x20,0xfc,0x07,0xad,0x30,0x08,0x8d,0x31,0x08,0x20,0xfc,0x07,0xad,
0x30,0x08,0x8d,0x32,0x08,0xc9,0xff,0xd0,0x0a,0xad,0x31,0x08,0xc9,0xff,0xd0,0x03,0x4c,0x56,0x07,0x20,0xfc,0x07,0xad,0x30,0x08,0x8d,0x33,0x08,0x20,0xfc,0x07,0xad,
0x30,0x08,0x8d,0x34,0x08,0xad,0x35,0x08,0xc9,0x01,0xd0,0x11,0xad,0x31,0x08,0x8d,0xe0,0x02,0xad,0x32,0x08,0x8d,0xe1,0x02,0xa9,0x00,0x8d,0x35,0x08,0x4c,0x17,0x07,
0x20,0xbb,0x07,0xa9,0xff,0x20,0x3a,0x08,0x90,0x01,0x60,0x68,0x68,0x20,0x21,0x09,0xa9,0xff,0x20,0x2f,0x09,0x4c,0x05,0x07,0xa9,0x00,0x85,0x34,0xa9,0xc4,0x85,0x35,
0xa9,0x00,0x85,0x32,0xa9,0xc0,0x85,0x33,0x60,0x20,0xbb,0x07,0xa6,0x39,0xe0,0x05,0xf0,0x1e,0xe0,0x00,0xd0,0x01,0x60,0x86,0x36,0xa9,0x04,0x38,0xe5,0x36,0x18,0x69,
0xc0,0xaa,0x18,0xa9,0x00,0x6d,0xff,0xc3,0x85,0x34,0x90,0x01,0xe8,0x86,0x35,0x60,0xa9,0xc0,0x85,0x35,0xa9,0x00,0x85,0x34,0x60,0x20,0x09,0x09,0xa5,0x32,0xc5,0x34,
0xd0,0x12,0xa5,0x33,0xc5,0x35,0xd0,0x0c,0xa5,0x39,0xc9,0x00,0xd0,0x17,0x20,0xa3,0x07,0x20,0xcc,0x07,0xa0,0x00,0xb1,0x32,0x8d,0x30,0x08,0xe6,0x32,0xd0,0x02,0xe6,
0x33,0x20,0x21,0x09,0x60,0x20,0x21,0x09,0x68,0x6c,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x6c,0xe2,0x02,0x60,0x85,0x36,0xa9,0x34,0x8d,0x02,0xd3,0x8d,0x03,
0xd3,0xa9,0x80,0x85,0x10,0x8d,0x0e,0xd2,0x18,0xa0,0x00,0x84,0x30,0x84,0x31,0x8c,0x0e,0xd4,0x8c,0x00,0xd4,0x08,0xd0,0x71,0x20,0xe2,0x08,0x90,0xf9,0xa9,0x00,0x85,
0x2e,0x85,0x37,0xa0,0xb4,0x20,0xdd,0x08,0x90,0xec,0xc0,0xd8,0x90,0xea,0xe6,0x2e,0xd0,0xf1,0xc6,0x37,0xa0,0xd1,0x20,0xe2,0x08,0x90,0xdb,0xc0,0xde,0xb0,0xf5,0x20,
0xe2,0x08,0x90,0x45,0xa0,0xc6,0x4c,0xa7,0x08,0x28,0xd0,0x09,0xa5,0x36,0x45,0x2f,0x85,0x39,0x4c,0xa4,0x08,0xa0,0x00,0xa5,0x2f,0x91,0x32,0xe6,0x32,0xd0,0x02,0xe6,
0x33,0xa0,0xc8,0x08,0xa9,0x01,0x85,0x2f,0x20,0xdd,0x08,0x90,0x1c,0xc0,0xe3,0x26,0x2f,0xa0,0xc6,0x90,0xf3,0xa5,0x31,0x45,0x2f,0x85,0x31,0xa5,0x32,0xc5,0x34,0xa5,
0x33,0xe5,0x35,0x90,0xc4,0xa9,0x00,0xc5,0x31,0x68,0xa9,0xc0,0x85,0x10,0x8d,0x0e,0xd2,0xa9,0x3c,0x8d,0x02,0xd3,0x8d,0x03,0xd3,0x60,0x20,0xe2,0x08,0x90,0x24,0xa2,
0x04,0xca,0xd0,0xfd,0xa5,0x30,0x4a,0x25,0x37,0x8d,0x1a,0xd0,0xc8,0xf0,0x13,0xa5,0x11,0xf0,0x0d,0xad,0x0f,0xd2,0x29,0x10,0xc5,0x30,0xf0,0xf0,0x85,0x30,0x38,0x60,
0xc6,0x11,0x18,0x60,0x00,0x00,0x78,0xad,0x0e,0xd4,0x8d,0x07,0x09,0xa9,0x00,0x8d,0x0e,0xd4,0xad,0x01,0xd3,0x8d,0x08,0x09,0x29,0xfe,0x8d,0x01,0xd3,0x60,0xad,0x08,
0x09,0x8d,0x01,0xd3,0xad,0x07,0x09,0x8d,0x0e,0xd4,0x58,0x60,0x8d,0xfc,0x02,0xa9,0x01,0x20,0xfc,0xfd,0x60,0xa9,0x00,0x85,0x32,0xa9,0x20,0x85,0x33,0xa9,0x11,0x85,
0x34,0xa9,0x20,0x85,0x35,0xa9,0x01,0x8d,0x35,0x08,0x20,0x09,0x09,0xa9,0x00,0x20,0x3a,0x08,0x20,0x21,0x09,0x90,0xde,0xa9,0x9b,0x8d,0x11,0x20,0xa2,0x01,0xa0,0x20,
0x20,0x42,0xc6,0xa9,0x00,0x85,0x14,0xa5,0x14,0xc9,0x4b,0xd0,0xfa,0x60,0xa9,0x05,0x85,0x0c,0xa9,0x07,0x85,0x0d,0xa9,0x00,0x8d,0x44,0x02,0xa9,0x01,0x85,0x09,0xa2,
0x8f,0xa0,0x09,0x20,0x42,0xc6,0xa9,0x01,0x20,0x2f,0x09,0x60,0x4e,0x41,0x4e,0x4f,0x54,0x42,0x4c,0x5b,0x55,0x52,0x5d,0x9b};

    private static int nanotbl_u2_data[] = {0x20,0x71,0x09,0x20,0x38,0x09,0x20,0x09,0x09,0x20,0xa3,0x07,0x20,0xcc,0x07,0x20,0x21,0x09,0x4c,0x56,0x07,0xa9,0x39,0x8d,0xe2,0x02,0xa9,0x08,0x8d,0xe3,0x02,0x20,0xfc,
0x07,0xad,0x31,0x08,0x85,0x36,0xad,0x32,0x08,0x85,0x37,0xad,0x30,0x08,0xa0,0x00,0x91,0x36,0xad,0x31,0x08,0xcd,0x33,0x08,0xd0,0x0e,0xad,0x32,0x08,0xcd,0x34,0x08,
0xd0,0x06,0x20,0x36,0x08,0x4c,0x56,0x07,0xee,0x31,0x08,0xd0,0x03,0xee,0x32,0x08,0x4c,0x21,0x07,0x20,0xfc,0x07,0xad,0x30,0x08,0x8d,0x31,0x08,0x20,0xfc,0x07,0xad,
0x30,0x08,0x8d,0x32,0x08,0xc9,0xff,0xd0,0x0a,0xad,0x31,0x08,0xc9,0xff,0xd0,0x03,0x4c,0x56,0x07,0x20,0xfc,0x07,0xad,0x30,0x08,0x8d,0x33,0x08,0x20,0xfc,0x07,0xad,
0x30,0x08,0x8d,0x34,0x08,0xad,0x35,0x08,0xc9,0x01,0xd0,0x11,0xad,0x31,0x08,0x8d,0xe0,0x02,0xad,0x32,0x08,0x8d,0xe1,0x02,0xa9,0x00,0x8d,0x35,0x08,0x4c,0x17,0x07,
0x20,0xbb,0x07,0xa9,0xff,0x20,0x3a,0x08,0x90,0x01,0x60,0x68,0x68,0x20,0x21,0x09,0xa9,0xff,0x20,0x2f,0x09,0x4c,0x05,0x07,0xa9,0x00,0x85,0x34,0xa9,0xfc,0x85,0x35,
0xa9,0x00,0x85,0x32,0xa9,0xf8,0x85,0x33,0x60,0x20,0xbb,0x07,0xa6,0x39,0xe0,0x05,0xf0,0x1e,0xe0,0x00,0xd0,0x01,0x60,0x86,0x36,0xa9,0x04,0x38,0xe5,0x36,0x18,0x69,
0xf8,0xaa,0x18,0xa9,0x00,0x6d,0xff,0xfb,0x85,0x34,0x90,0x01,0xe8,0x86,0x35,0x60,0xa9,0xf8,0x85,0x35,0xa9,0x00,0x85,0x34,0x60,0x20,0x09,0x09,0xa5,0x32,0xc5,0x34,
0xd0,0x12,0xa5,0x33,0xc5,0x35,0xd0,0x0c,0xa5,0x39,0xc9,0x00,0xd0,0x17,0x20,0xa3,0x07,0x20,0xcc,0x07,0xa0,0x00,0xb1,0x32,0x8d,0x30,0x08,0xe6,0x32,0xd0,0x02,0xe6,
0x33,0x20,0x21,0x09,0x60,0x20,0x21,0x09,0x68,0x6c,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x6c,0xe2,0x02,0x60,0x85,0x36,0xa9,0x34,0x8d,0x02,0xd3,0x8d,0x03,
0xd3,0xa9,0x80,0x85,0x10,0x8d,0x0e,0xd2,0x18,0xa0,0x00,0x84,0x30,0x84,0x31,0x8c,0x0e,0xd4,0x8c,0x00,0xd4,0x08,0xd0,0x71,0x20,0xe2,0x08,0x90,0xf9,0xa9,0x00,0x85,
0x2e,0x85,0x37,0xa0,0xb4,0x20,0xdd,0x08,0x90,0xec,0xc0,0xd8,0x90,0xea,0xe6,0x2e,0xd0,0xf1,0xc6,0x37,0xa0,0xd1,0x20,0xe2,0x08,0x90,0xdb,0xc0,0xde,0xb0,0xf5,0x20,
0xe2,0x08,0x90,0x45,0xa0,0xc6,0x4c,0xa7,0x08,0x28,0xd0,0x09,0xa5,0x36,0x45,0x2f,0x85,0x39,0x4c,0xa4,0x08,0xa0,0x00,0xa5,0x2f,0x91,0x32,0xe6,0x32,0xd0,0x02,0xe6,
0x33,0xa0,0xc8,0x08,0xa9,0x01,0x85,0x2f,0x20,0xdd,0x08,0x90,0x1c,0xc0,0xe3,0x26,0x2f,0xa0,0xc6,0x90,0xf3,0xa5,0x31,0x45,0x2f,0x85,0x31,0xa5,0x32,0xc5,0x34,0xa5,
0x33,0xe5,0x35,0x90,0xc4,0xa9,0x00,0xc5,0x31,0x68,0xa9,0xc0,0x85,0x10,0x8d,0x0e,0xd2,0xa9,0x3c,0x8d,0x02,0xd3,0x8d,0x03,0xd3,0x60,0x20,0xe2,0x08,0x90,0x24,0xa2,
0x04,0xca,0xd0,0xfd,0xa5,0x30,0x4a,0x25,0x37,0x8d,0x1a,0xd0,0xc8,0xf0,0x13,0xa5,0x11,0xf0,0x0d,0xad,0x0f,0xd2,0x29,0x10,0xc5,0x30,0xf0,0xf0,0x85,0x30,0x38,0x60,
0xc6,0x11,0x18,0x60,0x00,0x00,0x78,0xad,0x0e,0xd4,0x8d,0x07,0x09,0xa9,0x00,0x8d,0x0e,0xd4,0xad,0x01,0xd3,0x8d,0x08,0x09,0x29,0xfe,0x8d,0x01,0xd3,0x60,0xad,0x08,
0x09,0x8d,0x01,0xd3,0xad,0x07,0x09,0x8d,0x0e,0xd4,0x58,0x60,0x8d,0xfc,0x02,0xa9,0x01,0x20,0xfc,0xfd,0x60,0xa9,0x00,0x85,0x32,0xa9,0x20,0x85,0x33,0xa9,0x11,0x85,
0x34,0xa9,0x20,0x85,0x35,0xa9,0x01,0x8d,0x35,0x08,0x20,0x09,0x09,0xa9,0x00,0x20,0x3a,0x08,0x20,0x21,0x09,0x90,0xde,0xa9,0x9b,0x8d,0x11,0x20,0xa2,0x01,0xa0,0x20,
0x20,0x42,0xc6,0xa9,0x00,0x85,0x14,0xa5,0x14,0xc9,0x4b,0xd0,0xfa,0x60,0xa9,0x05,0x85,0x0c,0xa9,0x07,0x85,0x0d,0xa9,0x00,0x8d,0x44,0x02,0xa9,0x01,0x85,0x09,0xa2,
0x8f,0xa0,0x09,0x20,0x42,0xc6,0xa9,0x01,0x20,0x2f,0x09,0x60,0x4e,0x41,0x4e,0x4f,0x54,0x42,0x4c,0x5b,0x55,0x52,0x5d,0x9b};

    public String[] getSupportedTapeImageChunks() {
        return new String[0];
    }

    public void addInstructionsForChunk(InstructionStream is, TapeImageChunk chunk) throws Exception {
        
    }

    public BinaryConvertor[] getBinaryConvertors() {
        BinaryConvertor bcs[] = new BinaryConvertor[5];
        bcs[0]=new KBlockBinaryConvertor(this,"Turbo 2000 KB blocks + MINITBL", 2818, 3489, 1792, 1792+1023,BL_MINITBL);
        bcs[1]=new KBlockBinaryConvertor(this,"Turbo 2000 KB blocks + NANOTBL",2818, 3318, 1792, 1792+1023 ,BL_NANOTBL);
        bcs[2]=new KBlockBinaryConvertor(this,"Turbo 2000 KB blocks + NANOTBL[UR]",1794, 2349, 49152, 49152+1023,BL_NANOTBL_UR);
        bcs[3]=new KBlockBinaryConvertor(this,"Turbo 2000 KB blocks + NANOTBL[U2]",1794, 2349, 63488, 63488+1023,BL_NANOTBL_U2);
        bcs[4]=new KBlockBinaryConvertor(this,"Turbo 2000 KB blocks",0, 0, 0, 0,BL_NONE);
        return bcs;
    }

    public String getCountry() {
        return "CS";
    }

    public boolean isUsingAlternateFileChooser() {
        return false;
    }
    
}
