package turgen.plugin.btape;

import turgen.plugin.*;
import turgen.generator.SignalGenerator;

import turgen.*;
import java.io.*;
import javax.swing.*;
import turgen.dtb.DOS2Binary;
import turgen.playlist.AbstractPlayListItem;
import turgen.config.*;
import turgen.generator.PulseCrate;
import turgen.generator.PulseCreator;
import turgen.plugin.csturbo.LoaderBinaryData;
import turgen.tapeimage.DataChunk;
import turgen.tapeimage.TapeImageChunk;
import turgen.tapeimage.TurboChunk;

public class BTapePlugin implements Plugin {
    
    private String lastError;
    private BTapePluginPanel panel;
    private InOutProvider ioProvider;
    private final int[] casChunkName={116,114,98,116};
    private final int[] casChunkNameTr2k = {116,114,50,107};

    private ConfigClass cfcBTape;

    private IntegerConfigEntry cfgPilotLenBlock;
    private BooleanConfigEntry cfgProlongatePilotTone;
    private IntegerConfigEntry cfgPilotLenLoaderA;
    private IntegerConfigEntry cfgPilotLenLoaderB;
    private IntegerConfigEntry cfgSilenceAfterLoader;
    private IntegerConfigEntry cfgSilenceAfterFirstBlock;
    private BooleanConfigEntry cfgLoaderNamedAsFile;
    private BooleanConfigEntry cfgForceTr2kTapeImageChunk;
    private BooleanConfigEntry cfgPrependLoader;

    public static final int BL_NONE=0;
    public static final int BL_NANOBTAPE=1;
    public static final int BL_NANOBTAPE_UR=2;
    public static final int BL_NANOBTAPE_U2=3;

    
    /** Nova instance BTapePlugin */
    public BTapePlugin() {
    }
    
    
    
    /** Identifikacni jmeno zasuvneho modulu*/
    public String getName() {
        return "B-TAPE";
    }
    
    /*************************************************************/
    
    /**Tvorba instrukci pro generator*/
    public int[] getInstructions(AbstractPlayListItem _pl) {
        
        int[] instr=null;
        
        InstructionStream is = new InstructionStream();
        RandomAccessFile raf = null;
        
        
        BTapePlayListItem pl;
        pl=(BTapePlayListItem)_pl;
        
        /*Mirne navyseni poctu zavadecich pulzu*/
        int headPulses = cfgPilotLenBlock.getAsInt();
        if (cfgProlongatePilotTone.getAsBoolean()==true) {
            headPulses=PulseCreator.prolongatePilotTone(headPulses,32,pl.pulses.pilotTonePulseWidth);
        }
        
        try {
            
            /*Otevreni vsech souboru a docasnych proudu*/
            raf = new RandomAccessFile(pl.inFile,"r");
            int l = (int)raf.length();
            if (l>1024*1024) throw new FileTooLargeException(pl.inFile);

            /*Read all data from file and close it*/
            byte[] fData = new byte[l];
            int[] fileData = new int[l];

            raf.readFully(fData);
            raf.close();

            for(int i=0;i<fData.length;i++) {
                fileData[i]=fData[i]<0?fData[i]+256:fData[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];
            }
            
            
            
            /*If loader is to be prepended, then we prepend it*/
            if (cfgPrependLoader.getAsBoolean()==true) {
                    is.add(LoaderBinaryData.universalTurboLoader);
            }
            
            /*Pripadne pridani zavadece*/
            if (pl.loader!=BL_NONE) {
                prependLoader(is,pl);
            }
            
            /*Nastaveni*/
            if (cfgForceTr2kTapeImageChunk.getAsBoolean()==false) {
                Utils.addSetupInstruction(is, pl.pulses, casChunkName,SignalGenerator.FLAG_POLARITY_10,SignalGenerator.FLAG_ORDER_HL);
            }
            else {
                Utils.addSetupInstruction(is, Turgen.pulseCache.getPulsesForPlugin(this)[0], casChunkNameTr2k,SignalGenerator.FLAG_POLARITY_10,SignalGenerator.FLAG_ORDER_HL);
            }
            
            
            /*ZAPIS JEDNOTLIVYCH BLOKU*/
            int[] block = new int[1026];
            int fptr=0;
            int chsum=0;
            int rest=0;
            int blockCount=1;
            byte randomByte=(byte)System.currentTimeMillis();
            
            int[] nameArray = new int[11];
            /*Vymezerovat nazev*/
            for(int i=0;i<11;i++) {
                nameArray[i]=32;
            }
            
            if (Utils.createBTapeFilename(pl.fname,nameArray)==false) {
                throw new Exception("Invalid B-TAPE file name");
            }
            
            /*Instrukce pred kazdym blokem*/
            int[] heading= new int[5];
            heading[0]=SignalGenerator.INSTR_PILOTTONE;
            heading[1]=headPulses;
            heading[2]=SignalGenerator.INSTR_NARROW;
            heading[3]=SignalGenerator.INSTR_DATA;
            heading[4]=1026;
            
            /*Instukce za kazdym blokem*/
            int[] leadOut;
            if (pl.longGaps==false) {
                leadOut = new int[2];
                /*Safety pulse + safety pause*/
                leadOut[0]=SignalGenerator.INSTR_NARROW;
                leadOut[1]=SignalGenerator.INSTR_BLOCKSEP;
            }
            
            else {
                leadOut = new int[3];
                /*Safety pulse + pause*/
                leadOut[0]=SignalGenerator.INSTR_NARROW;
                leadOut[1]=SignalGenerator.INSTR_LONGSILENCE;
                leadOut[2]=1;
            }
            
            
            int aux2=128;
            if (pl.longGaps==true) aux2-=128;
            if (pl.doubleBlocks==true) aux2+=64;


            int startPtr;
            int endPtr;


            /*Pokud neni vse zapsano*/
            while (fptr<l) {
               
                startPtr=fptr;
                
                /*Kolik zbyva do konce a je-li to vice nez 3072 bytu*/
                rest=l-fptr;
                boolean lastTag=true;
                if (rest>1008) {rest=1008;lastTag=false;}
                
                /*Cislo bloku*/
                block[0]=blockCount;
                
                /*Rezim zapisu*/
                block[1]=aux2;
                
                /*Delka bloku a priznak konce*/
                int tmp=16+(rest&0x07FF);
                block[2]=tmp % 256;
                if (lastTag==false) {
                    block[3]=tmp / 256;
                }
                else {
                    block[3]=(tmp/256)|128;
                }
                
                /*Nepouzite*/
                block[4]=0;
                
                /*Nahodne cislo*/
                block[5]=randomByte;
                
                /*Jmeno souboru*/
                for(int i=0;i<11;i++) {
                    block[6+i]=nameArray[i];
                }
                
                
                /*1008 dat bloku*/
                for(int i=0;i<rest;i++) {
                    block[i+17]=fileData[fptr];fptr++;
                }
                
                endPtr=fptr;
                
                /*Doplnit nulami*/
                for (int i=rest;i<1008;i++) {
                    block[i+17]=0;
                }
                
                /*Kontrolni soucet a zapis dat*/
                chsum=blockCount;
                for (int i=1;i<1025;i++) {
                    chsum^=block[i];
                }
                block[1025]=chsum;
                
                /*Zapis tri poli*/
                int cnt=1;
                if (blockCount==1 || pl.doubleBlocks==true) cnt=2;
                for(int k=0;k<cnt;k++) {
                    
                    
                    is.add(heading);
                    is.add(block);
                    is.add(leadOut);

                    if (blockCount==1 && k==0) {
                        is.add(SignalGenerator.INSTR_LONGSILENCE);
                        is.add(cfgSilenceAfterFirstBlock.getAsInt());
                    }
                    
                }

                /*Silence after init or simple block separation*/
                int wait=Utils.calculateInitSilence(startPtr, endPtr-1, initLocations, pl.pauses);
                if (wait!=0) {
                    is.add(SignalGenerator.INSTR_LONGSILENCE);
                    is.add(Math.min(240, wait));
                }
                
                /*Dalsi blok*/
                blockCount++;
                
            }
            
            is.add(SignalGenerator.INSTR_END);
            return is.getInstructions();
     
            
        }
        
        catch(Exception e) {
            e.printStackTrace();
            if (e.getMessage()==null) lastError="Unable to produce instructions: "+e.toString();
            else lastError=e.toString();
            return null;
            
        }
        
        finally {
            try {
            raf.close();
            }
            catch(Exception e) {
                /*No reactions*/
            }
        }
       
        
    }
    
    public String getLastError() {
        return lastError;
    }
    
    public AbstractPlayListItem createItem() {
        BTapePlayListItem 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 BTapePluginPanel();

        /*Initialize configuration class*/
        cfcBTape = new ConfigClass("BTape","B-TAPE");

        /*Initialize configuration entries*/
        cfgPilotLenBlock=new IntegerConfigEntry("pilotLenBlock","Pilot tone length [pulse]",2048,256,8192);
        cfgProlongatePilotTone=new BooleanConfigEntry("prolongatePilotTone","Prolongate pilot tone",true);
        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);
        cfgSilenceAfterFirstBlock=new IntegerConfigEntry("silenceAfterFirstBlock","Silence after first block [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);
        cfgForceTr2kTapeImageChunk = new BooleanConfigEntry("forceTr2kTapeImageChunk","Force tr2k tape image chunks",false);
        cfgPrependLoader = new BooleanConfigEntry("prependLoader","Prepend Universal Turbo loader",false);
        
        /*Add entries to the class*/
        cfcBTape.addEntry(cfgPilotLenBlock);
        cfcBTape.addEntry(cfgProlongatePilotTone);
        cfcBTape.addEntry(cfgPilotLenLoaderA);
        cfcBTape.addEntry(cfgPilotLenLoaderB);
        cfcBTape.addEntry(cfgSilenceAfterFirstBlock);
        cfcBTape.addEntry(cfgSilenceAfterLoader);
        cfcBTape.addEntry(cfgLoaderNamedAsFile);
        cfcBTape.addEntry(cfgForceTr2kTapeImageChunk);
        cfcBTape.addEntry(cfgPrependLoader);

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

   

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

    
    
    
    
    private void prependLoader(InstructionStream is,BTapePlayListItem pli) throws IOException,PulsesException {
       
       
       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_NANOBTAPE: {
               loaderData=nanobtape_data;
               fname="NANOBTAPE";
               lload=2820;
               lrun=2820;
               llength=loaderData.length;
               break;
           }
           case BL_NANOBTAPE_UR: {
               loaderData=nanobtape_ur_data;
               fname="NANOBT_UR";
               lload=1796;
               lrun=1796;
               llength=loaderData.length;
               break;
           }
           case BL_NANOBTAPE_U2: {
               loaderData=nanobtape_u2_data;
               fname="NANOBT_U2";
               lload=1796;
               lrun=1796;
               llength=loaderData.length;
               break;
           }
           default: {
               return;
           }
       }
        
       /*Instrukce pro nastaveni*/
       
       Utils.addSetupInstruction(is, Turgen.pulseCache.getPulsesForPlugin(this)[0], casChunkNameTr2k,SignalGenerator.FLAG_POLARITY_10,SignalGenerator.FLAG_ORDER_HL);
       
       /*BL header*/
       int[] hdr=null;
       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());
       
    }


     public String[] getSupportedTapeImageChunks() {
        return new String[] {"trbt","trtt"};
    }



    int nanobtape_data[] = {0x20,0x98,0x0d,0x20,0x6b,0x0d,0x20,0xa2,0x0b,0xee,0x4b,0x0c,0x20,0xfd,0x0b,0x4c,0x55,0x0b,0xa9,0x50,0x8d,0xe2,0x02,0xa9,0x0c,0x8d,0xe3,0x02,0x20,0x18,0x0c,0xad,0x47,
0x0c,0x85,0x36,0xad,0x48,0x0c,0x85,0x37,0xad,0x46,0x0c,0xa0,0x00,0x91,0x36,0xad,0x47,0x0c,0xcd,0x49,0x0c,0xd0,0x0e,0xad,0x48,0x0c,0xcd,0x4a,0x0c,0xd0,0x06,0x20,
0x4d,0x0c,0x4c,0x55,0x0b,0xee,0x47,0x0c,0xd0,0x03,0xee,0x48,0x0c,0x4c,0x20,0x0b,0x20,0x18,0x0c,0xad,0x46,0x0c,0x8d,0x47,0x0c,0x20,0x18,0x0c,0xad,0x46,0x0c,0x8d,
0x48,0x0c,0xc9,0xff,0xd0,0x0a,0xad,0x47,0x0c,0xc9,0xff,0xd0,0x03,0x4c,0x55,0x0b,0x20,0x18,0x0c,0xad,0x46,0x0c,0x8d,0x49,0x0c,0x20,0x18,0x0c,0xad,0x46,0x0c,0x8d,
0x4a,0x0c,0xad,0x4c,0x0c,0xc9,0x01,0xd0,0x11,0xad,0x47,0x0c,0x8d,0xe0,0x02,0xad,0x48,0x0c,0x8d,0xe1,0x02,0xa9,0x00,0x8d,0x4c,0x0c,0x4c,0x16,0x0b,0xa9,0x34,0x8d,
0x02,0xd3,0x8d,0x03,0xd3,0x20,0xec,0x0b,0x20,0xe9,0x0c,0x20,0xfa,0x0c,0x20,0xb1,0x0c,0xa5,0x38,0xc9,0xb4,0x90,0x09,0xad,0x4b,0x0c,0x20,0x51,0x0c,0x4c,0xcb,0x0b,
0xad,0x4b,0x0c,0x20,0xba,0x0c,0xa9,0xfd,0x8d,0x02,0xd3,0x8d,0x03,0xd3,0x90,0x01,0x60,0xa2,0x03,0xa5,0x3c,0xcd,0x4b,0x0c,0xf0,0x06,0xa2,0x01,0x90,0x02,0xa2,0x02,
0x8a,0x20,0xfc,0xfd,0x4c,0xa2,0x0b,0xa9,0x00,0x85,0x32,0xa9,0x07,0x85,0x33,0xa9,0x00,0x85,0x34,0xa9,0x0b,0x85,0x35,0x60,0xa9,0x10,0x85,0x32,0xa9,0x07,0x85,0x33,
0x18,0xa9,0x00,0x6d,0x01,0x07,0xaa,0xad,0x02,0x07,0x29,0x07,0x69,0x07,0x85,0x35,0x86,0x34,0x60,0xa5,0x32,0xc5,0x34,0xd0,0x1a,0xa5,0x33,0xc5,0x35,0xd0,0x14,0xad,
0x02,0x07,0x29,0x80,0xf0,0x04,0x68,0x6c,0xe0,0x02,0x20,0xa2,0x0b,0xee,0x4b,0x0c,0x20,0xfd,0x0b,0xa0,0x00,0xb1,0x32,0x8d,0x46,0x0c,0xe6,0x32,0xd0,0x02,0xe6,0x33,
0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x6c,0xe2,0x02,0x60,0x85,0x36,0x20,0xe9,0x0c,0x08,0x20,0x47,0x0d,0xa4,0x39,0x20,0x4c,0x0d,0x90,0xf6,0xc4,0x3a,0xb0,0xf5,
0x20,0x4c,0x0d,0x90,0x46,0xa4,0x38,0x4c,0x8b,0x0c,0x28,0xd0,0x08,0xa5,0x36,0x45,0x3c,0xd0,0x39,0xf0,0x0c,0xa0,0x00,0xa5,0x3c,0x91,0x32,0xe6,0x32,0xd0,0x02,0xe6,
0x33,0xa4,0x38,0xc8,0xc8,0x08,0xa9,0x01,0x85,0x3c,0x20,0x47,0x0d,0x90,0x1c,0xc4,0x39,0x26,0x3c,0xa4,0x38,0x90,0xf3,0xa5,0x31,0x45,0x3c,0x85,0x31,0xa5,0x32,0xc5,
0x34,0xa5,0x33,0xe5,0x35,0x90,0xc3,0xa9,0x00,0xc5,0x31,0x68,0xa9,0x40,0x8d,0x0e,0xd4,0x8d,0x0e,0xd2,0x60,0x85,0x36,0x20,0xe9,0x0c,0x08,0xa9,0xb0,0x85,0x38,0xa9,
0xd6,0x85,0x39,0x20,0x47,0x0d,0x90,0xe3,0xa0,0x00,0x20,0x47,0x0d,0x90,0xdc,0xa0,0xc8,0x20,0x4c,0x0d,0x90,0xd5,0xc0,0xd7,0xb0,0xf5,0x20,0x4c,0x0d,0x90,0xcc,0xa0,
0xb0,0x4c,0x8b,0x0c,0xa0,0x00,0x84,0x30,0x84,0x31,0x8c,0x0e,0xd4,0x8c,0x00,0xd4,0x8c,0x0e,0xd2,0x18,0x60,0x20,0x47,0x0d,0x90,0xfb,0xa9,0x02,0x85,0x37,0xa0,0x00,
0x84,0x40,0xa2,0x03,0x20,0x47,0x0d,0x90,0xec,0xca,0xd0,0xf8,0x98,0x4a,0x48,0x49,0xff,0x85,0x38,0x68,0x4a,0x48,0x49,0xff,0x85,0x39,0x68,0x4a,0x49,0xff,0x85,0x3a,
0xa0,0x00,0x20,0x4c,0x0d,0x90,0xce,0xa4,0x38,0x20,0x47,0x0d,0x90,0xc7,0xc4,0x39,0x90,0xc3,0xe6,0x40,0xd0,0xf1,0xc6,0x37,0x10,0xc4,0xa0,0x00,0x20,0x4c,0x0d,0x90,
0xb4,0x60,0x20,0x4c,0x0d,0x90,0x1d,0xad,0x0a,0xd2,0x29,0xe4,0x05,0x30,0x4a,0x25,0x37,0x8d,0x1a,0xd0,0xc8,0xf0,0x0d,0xad,0x0f,0xd2,0x29,0x10,0xc5,0x30,0xf0,0xf4,
0x85,0x30,0x38,0x60,0x18,0x60,0xa9,0x01,0x8d,0x4b,0x0c,0x8d,0x4c,0x0c,0x20,0xa2,0x0b,0xa9,0x9b,0x8d,0x10,0x07,0xa2,0x0c,0xbd,0x04,0x07,0x9d,0xff,0x1f,0xca,0xd0,
0xf7,0xa2,0x00,0xa0,0x20,0x20,0x42,0xc6,0xa9,0x00,0x85,0x14,0xa5,0x14,0xc9,0x4b,0xd0,0xfa,0x60,0xa9,0x07,0x85,0x0c,0xa9,0x0b,0x85,0x0d,0xa9,0x00,0x8d,0x44,0x02,
0xa9,0x01,0x85,0x09,0xa2,0xb9,0xa0,0x0d,0x20,0x42,0xc6,0xa9,0x01,0x8d,0xfc,0x02,0x20,0xfc,0xfd,0x60,0x4e,0x41,0x4e,0x4f,0x42,0x54,0x41,0x50,0x45,0x9b};

    int nanobtape_ur_data[] = {0x20,0xd8,0x09,0x20,0xa5,0x09,0x20,0x7f,0x09,0x20,0xa8,0x07,0xee,0x60,0x08,0x20,0x09,0x08,0x20,0x97,0x09,0x4c,0x5b,0x07,0xa9,0x65,0x8d,0xe2,0x02,0xa9,0x08,0x8d,0xe3,
0x02,0x20,0x24,0x08,0xad,0x5c,0x08,0x85,0x36,0xad,0x5d,0x08,0x85,0x37,0xad,0x5b,0x08,0xa0,0x00,0x91,0x36,0xad,0x5c,0x08,0xcd,0x5e,0x08,0xd0,0x0e,0xad,0x5d,0x08,
0xcd,0x5f,0x08,0xd0,0x06,0x20,0x62,0x08,0x4c,0x5b,0x07,0xee,0x5c,0x08,0xd0,0x03,0xee,0x5d,0x08,0x4c,0x26,0x07,0x20,0x24,0x08,0xad,0x5b,0x08,0x8d,0x5c,0x08,0x20,
0x24,0x08,0xad,0x5b,0x08,0x8d,0x5d,0x08,0xc9,0xff,0xd0,0x0a,0xad,0x5c,0x08,0xc9,0xff,0xd0,0x03,0x4c,0x5b,0x07,0x20,0x24,0x08,0xad,0x5b,0x08,0x8d,0x5e,0x08,0x20,
0x24,0x08,0xad,0x5b,0x08,0x8d,0x5f,0x08,0xad,0x61,0x08,0xc9,0x01,0xd0,0x11,0xad,0x5c,0x08,0x8d,0xe0,0x02,0xad,0x5d,0x08,0x8d,0xe1,0x02,0xa9,0x00,0x8d,0x61,0x08,
0x4c,0x1c,0x07,0xa9,0x34,0x8d,0x02,0xd3,0x8d,0x03,0xd3,0x20,0xf8,0x07,0x20,0xfb,0x08,0x20,0x0c,0x09,0x20,0xc6,0x08,0xa5,0x38,0xc9,0xb4,0x90,0x09,0xad,0x60,0x08,
0x20,0x66,0x08,0x4c,0xd1,0x07,0xad,0x60,0x08,0x20,0xcc,0x08,0xa9,0xfd,0x8d,0x02,0xd3,0x8d,0x03,0xd3,0x90,0x01,0x60,0xa2,0x03,0xa5,0x3c,0xcd,0x60,0x08,0xf0,0x06,
0xa2,0x01,0x90,0x02,0xa2,0x02,0x20,0x97,0x09,0x8a,0x20,0xfc,0xfd,0x20,0x7f,0x09,0x4c,0xa8,0x07,0xa9,0x00,0x85,0x32,0xa9,0xf8,0x85,0x33,0xa9,0x00,0x85,0x34,0xa9,
0xfc,0x85,0x35,0x60,0xa9,0x10,0x85,0x32,0xa9,0xf8,0x85,0x33,0x18,0xa9,0x00,0x6d,0x01,0xf8,0xaa,0xad,0x02,0xf8,0x29,0x07,0x69,0xf8,0x85,0x35,0x86,0x34,0x60,0x20,
0x7f,0x09,0xa5,0x32,0xc5,0x34,0xd0,0x1d,0xa5,0x33,0xc5,0x35,0xd0,0x17,0xad,0x02,0xf8,0x29,0x80,0xf0,0x07,0x20,0x97,0x09,0x68,0x6c,0xe0,0x02,0x20,0xa8,0x07,0xee,
0x60,0x08,0x20,0x09,0x08,0xa0,0x00,0xb1,0x32,0x8d,0x5b,0x08,0xe6,0x32,0xd0,0x02,0xe6,0x33,0x20,0x97,0x09,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x6c,0xe2,0x02,
0x60,0x85,0x36,0x20,0xfb,0x08,0x08,0x20,0x59,0x09,0xa4,0x39,0x20,0x5e,0x09,0x90,0xf6,0xc4,0x3a,0xb0,0xf5,0x20,0x5e,0x09,0x90,0x46,0xa4,0x38,0x4c,0xa0,0x08,0x28,
0xd0,0x08,0xa5,0x36,0x45,0x3c,0xd0,0x39,0xf0,0x0c,0xa0,0x00,0xa5,0x3c,0x91,0x32,0xe6,0x32,0xd0,0x02,0xe6,0x33,0xa4,0x38,0xc8,0xc8,0x08,0xa9,0x01,0x85,0x3c,0x20,
0x59,0x09,0x90,0x1c,0xc4,0x39,0x26,0x3c,0xa4,0x38,0x90,0xf3,0xa5,0x31,0x45,0x3c,0x85,0x31,0xa5,0x32,0xc5,0x34,0xa5,0x33,0xe5,0x35,0x90,0xc3,0xa9,0x00,0xc5,0x31,
0x68,0xa9,0x40,0x8d,0x0e,0xd2,0x60,0x85,0x36,0x20,0xfb,0x08,0x08,0xa9,0xb0,0x85,0x38,0xa9,0xd6,0x85,0x39,0x20,0x59,0x09,0x90,0xe6,0xa0,0x00,0x20,0x59,0x09,0x90,
0xdf,0xa0,0xc8,0x20,0x5e,0x09,0x90,0xd8,0xc0,0xd7,0xb0,0xf5,0x20,0x5e,0x09,0x90,0xcf,0xa0,0xb0,0x4c,0xa0,0x08,0xa0,0x00,0x84,0x30,0x84,0x31,0x8c,0x0e,0xd4,0x8c,
0x00,0xd4,0x8c,0x0e,0xd2,0x18,0x60,0x20,0x59,0x09,0x90,0xfb,0xa9,0x02,0x85,0x37,0xa0,0x00,0x84,0x40,0xa2,0x03,0x20,0x59,0x09,0x90,0xec,0xca,0xd0,0xf8,0x98,0x4a,
0x48,0x49,0xff,0x85,0x38,0x68,0x4a,0x48,0x49,0xff,0x85,0x39,0x68,0x4a,0x49,0xff,0x85,0x3a,0xa0,0x00,0x20,0x5e,0x09,0x90,0xce,0xa4,0x38,0x20,0x59,0x09,0x90,0xc7,
0xc4,0x39,0x90,0xc3,0xe6,0x40,0xd0,0xf1,0xc6,0x37,0x10,0xc4,0xa0,0x00,0x20,0x5e,0x09,0x90,0xb4,0x60,0x20,0x5e,0x09,0x90,0x1d,0xad,0x0a,0xd2,0x29,0xe4,0x05,0x30,
0x4a,0x25,0x37,0x8d,0x1a,0xd0,0xc8,0xf0,0x0d,0xad,0x0f,0xd2,0x29,0x10,0xc5,0x30,0xf0,0xf4,0x85,0x30,0x38,0x60,0x18,0x60,0x00,0x00,0x78,0xad,0x0e,0xd4,0x8d,0x7d,
0x09,0xa9,0x00,0x8d,0x0e,0xd4,0xad,0x01,0xd3,0x8d,0x7e,0x09,0x29,0xfe,0x8d,0x01,0xd3,0x60,0xad,0x7e,0x09,0x8d,0x01,0xd3,0xad,0x7d,0x09,0x8d,0x0e,0xd4,0x58,0x60,
0xa9,0x01,0x8d,0x60,0x08,0x8d,0x61,0x08,0x20,0x7f,0x09,0x20,0xa8,0x07,0xa9,0x9b,0x8d,0x10,0xf8,0xa2,0x0c,0xbd,0x04,0xf8,0x9d,0xff,0x1f,0xca,0xd0,0xf7,0x20,0x97,
0x09,0xa2,0x00,0xa0,0x20,0x20,0x42,0xc6,0xa9,0x00,0x85,0x14,0xa5,0x14,0xc9,0x4b,0xd0,0xfa,0x60,0xa9,0x07,0x85,0x0c,0xa9,0x07,0x85,0x0d,0xa9,0x00,0x8d,0x44,0x02,
0xa9,0x01,0x85,0x09,0xa2,0xf9,0xa0,0x09,0x20,0x42,0xc6,0xa9,0x01,0x8d,0xfc,0x02,0x20,0xfc,0xfd,0x60,0x4e,0x41,0x4e,0x4f,0x42,0x54,0x41,0x50,0x45,0x5b,0x55,0x52,
0x5d,0x9b};

    int nanobtape_u2_data[] = {0x20,0xd8,0x09,0x20,0xa5,0x09,0x20,0x7f,0x09,0x20,0xa8,0x07,0xee,0x60,0x08,0x20,0x09,0x08,0x20,0x97,0x09,0x4c,0x5b,0x07,0xa9,0x65,0x8d,0xe2,0x02,0xa9,0x08,0x8d,0xe3,
0x02,0x20,0x24,0x08,0xad,0x5c,0x08,0x85,0x36,0xad,0x5d,0x08,0x85,0x37,0xad,0x5b,0x08,0xa0,0x00,0x91,0x36,0xad,0x5c,0x08,0xcd,0x5e,0x08,0xd0,0x0e,0xad,0x5d,0x08,
0xcd,0x5f,0x08,0xd0,0x06,0x20,0x62,0x08,0x4c,0x5b,0x07,0xee,0x5c,0x08,0xd0,0x03,0xee,0x5d,0x08,0x4c,0x26,0x07,0x20,0x24,0x08,0xad,0x5b,0x08,0x8d,0x5c,0x08,0x20,
0x24,0x08,0xad,0x5b,0x08,0x8d,0x5d,0x08,0xc9,0xff,0xd0,0x0a,0xad,0x5c,0x08,0xc9,0xff,0xd0,0x03,0x4c,0x5b,0x07,0x20,0x24,0x08,0xad,0x5b,0x08,0x8d,0x5e,0x08,0x20,
0x24,0x08,0xad,0x5b,0x08,0x8d,0x5f,0x08,0xad,0x61,0x08,0xc9,0x01,0xd0,0x11,0xad,0x5c,0x08,0x8d,0xe0,0x02,0xad,0x5d,0x08,0x8d,0xe1,0x02,0xa9,0x00,0x8d,0x61,0x08,
0x4c,0x1c,0x07,0xa9,0x34,0x8d,0x02,0xd3,0x8d,0x03,0xd3,0x20,0xf8,0x07,0x20,0xfb,0x08,0x20,0x0c,0x09,0x20,0xc6,0x08,0xa5,0x38,0xc9,0xb4,0x90,0x09,0xad,0x60,0x08,
0x20,0x66,0x08,0x4c,0xd1,0x07,0xad,0x60,0x08,0x20,0xcc,0x08,0xa9,0xfd,0x8d,0x02,0xd3,0x8d,0x03,0xd3,0x90,0x01,0x60,0xa2,0x03,0xa5,0x3c,0xcd,0x60,0x08,0xf0,0x06,
0xa2,0x01,0x90,0x02,0xa2,0x02,0x20,0x97,0x09,0x8a,0x20,0xfc,0xfd,0x20,0x7f,0x09,0x4c,0xa8,0x07,0xa9,0x00,0x85,0x32,0xa9,0xc0,0x85,0x33,0xa9,0x00,0x85,0x34,0xa9,
0xc4,0x85,0x35,0x60,0xa9,0x10,0x85,0x32,0xa9,0xc0,0x85,0x33,0x18,0xa9,0x00,0x6d,0x01,0xc0,0xaa,0xad,0x02,0xc0,0x29,0x07,0x69,0xc0,0x85,0x35,0x86,0x34,0x60,0x20,
0x7f,0x09,0xa5,0x32,0xc5,0x34,0xd0,0x1d,0xa5,0x33,0xc5,0x35,0xd0,0x17,0xad,0x02,0xc0,0x29,0x80,0xf0,0x07,0x20,0x97,0x09,0x68,0x6c,0xe0,0x02,0x20,0xa8,0x07,0xee,
0x60,0x08,0x20,0x09,0x08,0xa0,0x00,0xb1,0x32,0x8d,0x5b,0x08,0xe6,0x32,0xd0,0x02,0xe6,0x33,0x20,0x97,0x09,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x6c,0xe2,0x02,
0x60,0x85,0x36,0x20,0xfb,0x08,0x08,0x20,0x59,0x09,0xa4,0x39,0x20,0x5e,0x09,0x90,0xf6,0xc4,0x3a,0xb0,0xf5,0x20,0x5e,0x09,0x90,0x46,0xa4,0x38,0x4c,0xa0,0x08,0x28,
0xd0,0x08,0xa5,0x36,0x45,0x3c,0xd0,0x39,0xf0,0x0c,0xa0,0x00,0xa5,0x3c,0x91,0x32,0xe6,0x32,0xd0,0x02,0xe6,0x33,0xa4,0x38,0xc8,0xc8,0x08,0xa9,0x01,0x85,0x3c,0x20,
0x59,0x09,0x90,0x1c,0xc4,0x39,0x26,0x3c,0xa4,0x38,0x90,0xf3,0xa5,0x31,0x45,0x3c,0x85,0x31,0xa5,0x32,0xc5,0x34,0xa5,0x33,0xe5,0x35,0x90,0xc3,0xa9,0x00,0xc5,0x31,
0x68,0xa9,0x40,0x8d,0x0e,0xd2,0x60,0x85,0x36,0x20,0xfb,0x08,0x08,0xa9,0xb0,0x85,0x38,0xa9,0xd6,0x85,0x39,0x20,0x59,0x09,0x90,0xe6,0xa0,0x00,0x20,0x59,0x09,0x90,
0xdf,0xa0,0xc8,0x20,0x5e,0x09,0x90,0xd8,0xc0,0xd7,0xb0,0xf5,0x20,0x5e,0x09,0x90,0xcf,0xa0,0xb0,0x4c,0xa0,0x08,0xa0,0x00,0x84,0x30,0x84,0x31,0x8c,0x0e,0xd4,0x8c,
0x00,0xd4,0x8c,0x0e,0xd2,0x18,0x60,0x20,0x59,0x09,0x90,0xfb,0xa9,0x02,0x85,0x37,0xa0,0x00,0x84,0x40,0xa2,0x03,0x20,0x59,0x09,0x90,0xec,0xca,0xd0,0xf8,0x98,0x4a,
0x48,0x49,0xff,0x85,0x38,0x68,0x4a,0x48,0x49,0xff,0x85,0x39,0x68,0x4a,0x49,0xff,0x85,0x3a,0xa0,0x00,0x20,0x5e,0x09,0x90,0xce,0xa4,0x38,0x20,0x59,0x09,0x90,0xc7,
0xc4,0x39,0x90,0xc3,0xe6,0x40,0xd0,0xf1,0xc6,0x37,0x10,0xc4,0xa0,0x00,0x20,0x5e,0x09,0x90,0xb4,0x60,0x20,0x5e,0x09,0x90,0x1d,0xad,0x0a,0xd2,0x29,0xe4,0x05,0x30,
0x4a,0x25,0x37,0x8d,0x1a,0xd0,0xc8,0xf0,0x0d,0xad,0x0f,0xd2,0x29,0x10,0xc5,0x30,0xf0,0xf4,0x85,0x30,0x38,0x60,0x18,0x60,0x00,0x00,0x78,0xad,0x0e,0xd4,0x8d,0x7d,
0x09,0xa9,0x00,0x8d,0x0e,0xd4,0xad,0x01,0xd3,0x8d,0x7e,0x09,0x29,0xfe,0x8d,0x01,0xd3,0x60,0xad,0x7e,0x09,0x8d,0x01,0xd3,0xad,0x7d,0x09,0x8d,0x0e,0xd4,0x58,0x60,
0xa9,0x01,0x8d,0x60,0x08,0x8d,0x61,0x08,0x20,0x7f,0x09,0x20,0xa8,0x07,0xa9,0x9b,0x8d,0x10,0xc0,0xa2,0x0c,0xbd,0x04,0xc0,0x9d,0xff,0x1f,0xca,0xd0,0xf7,0x20,0x97,
0x09,0xa2,0x00,0xa0,0x20,0x20,0x42,0xc6,0xa9,0x00,0x85,0x14,0xa5,0x14,0xc9,0x4b,0xd0,0xfa,0x60,0xa9,0x07,0x85,0x0c,0xa9,0x07,0x85,0x0d,0xa9,0x00,0x8d,0x44,0x02,
0xa9,0x01,0x85,0x09,0xa2,0xf9,0xa0,0x09,0x20,0x42,0xc6,0xa9,0x01,0x8d,0xfc,0x02,0x20,0xfc,0xfd,0x60,0x4e,0x41,0x4e,0x4f,0x42,0x54,0x41,0x50,0x45,0x5b,0x55,0x52,
0x5d,0x9b};

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

        /*trXX chunk*/
        if (chunk instanceof TurboChunk) {
            int bdr = ((TurboChunk)(chunk)).getBaudRate();

            /*Upkeep baud rate range*/
            if (bdr<2270) bdr=2270;
            if (bdr>9600) bdr=9600;

            /*Choose closest known pulses*/
            PulseCrate speed = Utils.getNearestBaudRate(bdr, Turgen.pulseCache.getPulsesForPlugin(this));

            /*Generate setup instruction*/
            Utils.addSetupInstruction(is, speed, chunk.getType(),SignalGenerator.FLAG_POLARITY_10,SignalGenerator.FLAG_ORDER_HL);

            return;
        }

        /*Only data chunk accepted*/
        if (!(chunk instanceof DataChunk)) return;

        DataChunk dataChunk = (DataChunk)chunk;
        

        
        

        /*Zavadeci ton a data bloku*/
        is.add(SignalGenerator.INSTR_PILOTTONE);
        is.add(dataChunk.getAux());

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

        /*Data bloku*/
        is.add(SignalGenerator.INSTR_DATA);
        is.add(dataChunk.getLength());

        int[] dta = dataChunk.getData();

        for(int i=0;i<dataChunk.getLength();i++) {
            is.add(dta[i]);
        }

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

    public BinaryConvertor[] getBinaryConvertors() {
        
        BinaryConvertor bcs[] = new BinaryConvertor[4];
        bcs[0]=new BTapeBinaryConvertor(this,"B-TAPE + NANOBTAPE",2820, 3434, 1792, 1792+1023 ,BL_NANOBTAPE);
        bcs[1]=new BTapeBinaryConvertor(this,"B-TAPE + NANOBTAPE[UR]",1796, 2468, 49152, 49152+1023,BL_NANOBTAPE_UR);
        bcs[2]=new BTapeBinaryConvertor(this,"B-TAPE + NANOBTAPE[U2]",1796, 2468, 63488, 63488+1023,BL_NANOBTAPE_U2);
        bcs[3]=new BTapeBinaryConvertor(this,"B-TAPE",0, 0, 0, 0, BL_NONE);
        return bcs;
    }

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

    public boolean isUsingAlternateFileChooser() {
        return false;
    }

}
