changeset 0:ebd5689e2985

Initial import of Multipaint sketch version 22.5.2017.
author Tero Heikkinen
date Tue, 03 Jul 2018 20:56:55 +0300
parents
children e2f754cc1665
files Interface.pde draw_inputs.pde draw_outputs.pde draw_smart.pde events.pde exporters.pde java.pde multipaint.pde prefread.pde
diffstat 9 files changed, 6482 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Interface.pde	Tue Jul 03 20:56:55 2018 +0300
@@ -0,0 +1,1351 @@
+// This collects UI stuff that's not directly related to the viewport
+// i.e. Icons, color selectors and the like, but also undo/spare
+
+//fixed raster parameters
+int g_raster_offset_x;
+int g_raster_offset_y;
+int g_raster_no;
+
+byte[] g_depressed = new byte[256];
+
+int g_fixedraster[]={
+  1,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,1,0,
+  1,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,1,0,
+  1,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,1,0,
+  1,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,1,0};
+
+int g_rasterpatterns[]={
+  
+  0,1,1,1,0,1,1,1,
+  1,1,1,1,1,1,1,1,
+  1,1,0,1,1,1,0,1,
+  1,1,1,1,1,1,1,1,
+  0,1,1,1,0,1,1,1,
+  1,1,1,1,1,1,1,1,
+  1,1,0,1,1,1,0,1,
+  1,1,1,1,1,1,1,1,
+  
+  0,1,1,1,0,1,1,1,
+  1,1,0,1,1,1,0,1,
+  0,1,1,1,0,1,1,1,
+  1,1,0,1,1,1,0,1,
+  0,1,1,1,0,1,1,1,
+  1,1,0,1,1,1,0,1,
+  0,1,1,1,0,1,1,1,
+  1,1,0,1,1,1,0,1,
+    
+  0,1,1,1,0,1,1,1,
+  1,0,1,0,1,0,1,0,
+  1,1,0,1,1,1,0,1,
+  1,0,1,0,1,0,1,0,
+  0,1,1,1,0,1,1,1,
+  1,0,1,0,1,0,1,0,
+  1,1,0,1,1,1,0,1,
+  1,0,1,0,1,0,1,0,
+  
+  1,0,1,0,1,0,1,0,
+  0,1,0,1,0,1,0,1,
+  1,0,1,0,1,0,1,0,
+  0,1,0,1,0,1,0,1,
+  1,0,1,0,1,0,1,0,
+  0,1,0,1,0,1,0,1,
+  1,0,1,0,1,0,1,0,
+  0,1,0,1,0,1,0,1,
+
+  1,0,0,0,1,0,0,0,
+  0,1,0,1,0,1,0,1,
+  0,0,1,0,0,0,1,0,
+  0,1,0,1,0,1,0,1,
+  1,0,0,0,1,0,0,0,
+  0,1,0,1,0,1,0,1,
+  0,0,1,0,0,0,1,0,
+  0,1,0,1,0,1,0,1,
+  
+  1,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,1,0,
+  1,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,1,0,
+  1,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,1,0,
+  1,0,0,0,1,0,0,0,
+  0,0,1,0,0,0,1,0,
+  
+  1,0,0,0,1,0,0,0,
+  0,0,0,0,0,0,0,0,
+  0,0,1,0,0,0,1,0,
+  0,0,0,0,0,0,0,0,
+  1,0,0,0,1,0,0,0,
+  0,0,0,0,0,0,0,0,
+  0,0,1,0,0,0,1,0,
+  0,0,0,0,0,0,0,0,
+   
+  1,1,1,1,1,1,1,1,
+  0,0,0,0,0,0,0,0,
+  1,1,1,1,1,1,1,1,
+  0,0,0,0,0,0,0,0,
+  1,1,1,1,1,1,1,1,
+  0,0,0,0,0,0,0,0,
+  1,1,1,1,1,1,1,1,
+  0,0,0,0,0,0,0,0,
+  
+  1,0,1,0,1,0,1,0,
+  0,0,0,0,0,0,0,0,
+  1,0,1,0,1,0,1,0,
+  0,0,0,0,0,0,0,0,
+  1,0,1,0,1,0,1,0,
+  0,0,0,0,0,0,0,0,
+  1,0,1,0,1,0,1,0,
+  0,0,0,0,0,0,0,0,
+
+  1,0,1,0,1,0,1,0,
+  1,0,1,0,1,0,1,0,
+  1,0,1,0,1,0,1,0,
+  1,0,1,0,1,0,1,0,
+  1,0,1,0,1,0,1,0,
+  1,0,1,0,1,0,1,0,
+  1,0,1,0,1,0,1,0,
+  1,0,1,0,1,0,1,0  
+};
+
+
+void setup_raster()
+{
+  g_raster_offset_x=0;
+  g_raster_offset_y=0;
+  g_raster_no=3;
+  set_fixed_raster(g_raster_no);
+}
+
+void fixed_raster_command(int par)
+{
+  if(par=='p'){
+    g_raster_no--;
+    if(g_raster_no<0)g_raster_no=9;
+    set_fixed_raster(g_raster_no);
+    g_data['r']=1;
+  }
+  if(par=='n'){
+    g_raster_no++;
+    if(g_raster_no>9)g_raster_no=0;
+    set_fixed_raster(g_raster_no);
+    g_data['r']=1; 
+  }
+  if(par=='x'){
+    g_raster_offset_x++;
+    if(g_raster_offset_x>3)g_raster_offset_x=0;
+  }
+  if(par=='y'){
+    g_raster_offset_y++;
+    if(g_raster_offset_y>3)g_raster_offset_y=0;
+  }  
+}
+
+int magmode()
+{
+  //return the mode "number" based on g_uizoom and 'm' and 'M'
+  //currently valid outputs are 0,10,20,1,11,21,2,12,22
+  int base=0;
+  if(g_uizoom==1)base=10;
+  if(g_uizoom==3)base=20;
+  if(g_data['M']==1&&g_data['m']==1)g_data['m']=0;
+  if(g_data['m']==1)base++;
+  if(g_data['M']==1)base=base+2;
+  return base;
+}
+
+int magx()
+{
+  //return the amount of horizontal 8x8 characters in current mode ('m' or 'M')
+  int psize,mag;
+  psize=g_magpix[magmode()];mag=psize*8;
+  return (width-(33*g_uizoom))/mag;
+}
+
+int magy()
+{
+  //return the amount of vertical 8x8 characters in current mode ('m' or 'M')  
+  int psize,mag;
+  psize=g_magpiy[magmode()];mag=psize*8;
+  return (height-(33*g_uizoom))/mag; //how many chars in a magmode
+}
+
+void ustats()
+{
+//a debug thingie in case the step undo does not work
+//println("UINDEX:"+g_uindex[g_spare]);
+//println("UTOP:"+g_utop[g_spare]);
+//println("UBOTTOM:"+g_ubottom[g_spare]);
+}
+
+void store_undo() //to_undo
+{
+  if(g_spare==0)g_undob[g_uindex[g_spare]]=g_map.clone();
+  if(g_spare==1)g_undobs[g_uindex[g_spare]]=g_map.clone();
+  g_uindex[g_spare]++;
+  if(g_uindex[g_spare]>10)g_uindex[g_spare]=0;
+  if(g_uindex[g_spare]==g_ubottom[g_spare]){
+    g_ubottom[g_spare]++;
+    if(g_ubottom[g_spare]>10)g_ubottom[g_spare]=0;
+  }  
+  g_utop[g_spare]=g_uindex[g_spare];
+  
+  refreshpalette();
+  ustats();
+}
+
+void restore_undo()
+{
+  if(g_uindex[g_spare]==g_ubottom[g_spare])return;
+  if(g_spare==0)g_undob[g_uindex[g_spare]]=g_map.clone();
+  if(g_spare==1)g_undobs[g_uindex[g_spare]]=g_map.clone();
+  g_uindex[g_spare]--;
+  if(g_uindex[g_spare]<0)g_uindex[g_spare]=10;
+  if(g_spare==0)g_map=g_undob[g_uindex[g_spare]].clone();
+  if(g_spare==1)g_map=g_undobs[g_uindex[g_spare]].clone();
+  
+  refreshpalette();
+  ustats();
+}
+
+void redo_undo()
+{
+  if(g_uindex[g_spare]==g_utop[g_spare])return;
+  g_uindex[g_spare]++;
+  if(g_uindex[g_spare]>10)g_uindex[g_spare]=0;
+  if(g_spare==0)g_map=g_undob[g_uindex[g_spare]].clone();
+  if(g_spare==1)g_map=g_undobs[g_uindex[g_spare]].clone();
+  if(g_uindex[g_spare]>10)g_uindex[g_spare]=0;
+  refreshpalette();
+  ustats();
+}
+
+void spare() //dpaint style spare page
+{
+  if(g_spare==0){// in REAL page, change to SPARE page
+       g_swappage=g_sparepage.clone();g_sparepage=g_map.clone();
+       g_map=g_swappage.clone();frame.setTitle(sfilename);
+  }
+  else
+  {// in SPARE page, change to REAL page
+       g_swappage=g_sparepage.clone();g_sparepage=g_map.clone();
+       g_map=g_swappage.clone();frame.setTitle(filename);
+  }
+  g_spare=1-g_spare;
+  g_realfront=byte(g_farge);g_realback=byte(g_backg);
+  refreshpalette();
+}
+
+void switcher(int di)
+{
+  // this achieves varieties of whole screen copying
+  // needed for brush copy and pre-drawing the shapes when a
+  // tool is active etc.
+  switch(di)
+  {
+    case 0:
+      g_rmap=g_map.clone();
+    break;
+    case 1:
+      g_map=g_rmap.clone();
+      for(int i=0;i<1024;i++){
+        if(g_remdo[i]==1){g_remdo[i]=0;g_redo[i]=0;}
+      }
+    break;
+    case 2:
+      g_brush=g_map.clone();
+    break;
+    case 3:
+       g_sparepage=g_map.clone();
+    break;
+    case 4:
+       g_map=g_sparepage.clone();
+    break;
+  }
+}
+
+void sussborder(){  
+  makecolor(259,g_r[g_map[0]],g_g[g_map[0]],g_b[g_map[0]]);
+  g_boxreconstruct=2;
+}
+
+void makecolor(int c, int rr,int gg,int bb)
+{
+  //0-255 go to g_map[] up until 1021-1023
+  //the rest is not stored
+  if(c<256){
+    g_map[256+c*3]=byte(rr);
+    g_map[256+c*3+1]=byte(gg);
+    g_map[256+c*3+2]=byte(bb);
+  }
+  g_r[c]=rr;g_g[c]=gg;g_b[c]=bb;
+  g_rgb[c]=0xff000000;
+  g_rgb[c]=g_rgb[c]+rr*0x00010000;
+  g_rgb[c]=g_rgb[c]+gg*0x00000100;
+  g_rgb[c]=g_rgb[c]+bb*0x00000001;  
+}
+
+int fylli()
+{
+  //for the animated rubberband thingy
+  g_rband++;
+  if(g_rband>g_rbang){
+    g_rband=0;g_rbang++;if(g_rbang>12)g_rbang=8;
+  }
+  if(g_rband>=3)return 0;
+  return 1;
+}
+
+void e_rect(int x1,int y1,int w,int h,int rgb)
+{
+  int ad=x1+y1*width;
+  //updatepixels has to be handled elsewhere
+  for(int yy=0;yy<h;yy++){
+    for(int xx=0;xx<w;xx++){
+      pixels[ad+xx]=rgb;
+    }
+    ad=ad+width;
+  }
+}
+
+void d_rect(int x1,int y1,int w,int h,int rgb)
+{
+  int ad=x1+y1*width;
+  //updatepixels has to be handled elsewhere
+  for(int yy=0;yy<h;yy++){
+    for(int xx=0;xx<w;xx++){
+      if(xx==0||yy==0||xx==w-1||yy==h-1)pixels[ad+xx]=rgb;
+    }
+    ad=ad+width;
+  }
+}
+
+void t_rect(int x1,int y1,int w,int h,int rgb)
+{
+  // transparent rectangle
+  // fixed tp, for grid drawing
+
+  //the updatepixels rigmarole has to be handled elsewhere
+  int r,g,b,s,fout;
+  int ad=x1+y1*width;
+  
+  if(g_gridmode==NEW){
+  for(int yy=0;yy<h;yy++){
+    for(int xx=0;xx<w;xx++){
+      s=pixels[ad+xx];fout=0;
+      if(g_rgb[0]==s)fout=g_grids[0];
+      if(g_rgb[1]==s)fout=g_grids[1];
+      if(g_rgb[2]==s)fout=g_grids[2];
+      if(g_rgb[3]==s)fout=g_grids[3];
+      if(g_rgb[4]==s)fout=g_grids[4];
+      if(g_rgb[5]==s)fout=g_grids[5];
+      if(g_rgb[6]==s)fout=g_grids[6];
+      if(g_rgb[7]==s)fout=g_grids[7];
+      if(g_rgb[8]==s)fout=g_grids[8];
+      if(g_rgb[9]==s)fout=g_grids[9];
+      if(g_rgb[10]==s)fout=g_grids[10];
+      if(g_rgb[11]==s)fout=g_grids[11];
+      if(g_rgb[12]==s)fout=g_grids[12];
+      if(g_rgb[13]==s)fout=g_grids[13];
+      if(g_rgb[14]==s)fout=g_grids[14];
+      if(g_rgb[15]==s)fout=g_grids[15];      
+      pixels[ad+xx]=fout;
+    }
+    ad=ad+width;
+  }
+  return;
+  }
+  
+  for(int yy=0;yy<h;yy++){
+    for(int xx=0;xx<w;xx++){
+      s=pixels[ad+xx];  
+      r=s&0x00ff0000;r=r>>16;
+      g=s&0x0000ff00;g=g>>8;
+      b=s&0x000000ff;
+      g=g+64;
+      r=r*2;g=g*2;b=b*2;
+      r=r/3;g=g/3;b=b/3;
+      pixels[ad+xx]=0xff000000+r*0x10000+g*0x100+b;
+    }
+    ad=ad+width;
+  }  
+}
+
+
+// parameter store/restore in case some functions need to bypass grid, attribute modes etc
+
+void storeparameters()
+{
+  for(int i=0;i<=255;i++)
+  {
+    g_data[767+i]=g_data[i];
+  }
+}
+
+void restoreparameters()
+{
+  for(int i=0;i<=255;i++)
+  {
+    g_data[i]=g_data[767+i];
+  }
+}
+
+void drawtext(int xo,int yo, String ss)
+{
+  //draw a bunch of text maybe not needed
+  for(int i=0;i<ss.length();i++){
+    drawchar(xo+i*8*2,yo,ss.charAt(i));
+  }
+}
+
+void drawicon(int xo,int yo, int t,int mm)
+{
+  //draw one icon
+  int ad,cad,xx,yy,pop,far;
+  int metal;
+  yy=t/16;xx=t-yy*16;xx=xx*2;yy=yy*2;
+  ad=1024+xx*8+yy*2048;
+    for(int y=0;y<=15;y++){            
+       for(int x=0;x<=15;x++){    
+         metal=0xffa0a0a0;
+         far=0xff000000;
+         if(t==18){
+           if(x<15&&y<15)far=int(g_rgb[g_farge]);
+         }
+         if(t==19&&g_backmode==1){
+           if(x<15&&y<15)far=int(g_rgb[g_farge]);
+         }
+         if(g_depressed[t]>0)metal=0xff606060;
+         
+         if(x==0||y==0){
+           metal=0xffe0e0e0;
+           if(g_depressed[t]>0)metal=0xff303030;
+           if(t==56||t==9)metal=0xffa0a0a0;
+         }
+         pop=1;cad=65536+(xx+x/8)+yy*256+y*32; 
+         if(int(g_icons[cad])==0)pop=0;
+         if(int(g_icons[ad+x])==pop){
+            far=metal;
+            if(mm==1)far=0xffffff80;
+         }
+         if(t==66){//raster icon
+           if(x>=1&&y>=2&&x<=13&&y<=12){
+             far=metal;if(mm==1)far=0xffffff80;
+             if(get_raster(x+1,y)==1)far=0xff000000;
+          }
+        }
+        e_rect(xo+x*g_uizoom,yo+y*g_uizoom,g_uizoom,g_uizoom,far);
+      }
+      ad=ad+256;
+    }
+}
+
+void drawchar(int xo,int yo, int t)
+{
+  //characters at the help box
+  int ad,cad,x,y,xx,yy,far;
+  far=0xff000000;
+  t=t-32;yy=t/32;
+  xx=t-yy*32;yy=yy+18;
+    for(y=0;y<=7;y++){     
+       cad=65536+xx+yy*256+y*32;ad=1024+xx*8+yy*2048+y*256;          
+       for(x=0;x<=7;x++){    
+          if(int(g_icons[ad+x])==1){
+             far=0xffb0b0b0;
+             if(g_bsize<4){
+               if(g_bsize+(g_btype*4)+96==t)far=0xffffff80;
+             }
+          }
+          else
+          {
+            far=0xff000000;
+            if(g_spare==1&&t<=95)far=0xff008000;//different background color for spare mode
+            if(g_msgctr>0&&t+32<128)far=0xff0000ff;//different background color
+          }
+          e_rect(xo+x*g_uizoom,yo+y*g_uizoom,g_uizoom,g_uizoom,far);
+        }
+    }
+}
+
+boolean moicon(int xx,int yy,int ww,int hh)
+{
+  //check mouse/icon boundary without actually drawing the icon
+  if(g_data['m']==0&&g_data['M']==0){
+    if(g_mx+g_windowx>=xx&&g_mx+g_windowx<xx+ww&&g_my+g_windowy>=yy&&g_my+g_windowy<yy+hh)return true;
+  }
+  if(g_data['m']==1||g_data['M']==1){
+    if(g_mx>=xx&&g_mx<=xx+ww&&g_my>=yy&&g_my<=yy+hh)return true;
+  }
+  return false;
+}
+
+boolean doicon_drag(int xx,int yy,int ww,int hh)
+{
+   if(g_iconx>=xx&&g_iconx<xx+ww&&g_icony>=yy&&g_icony<yy+hh){
+    g_iconx=-1;g_icony=-1;
+    g_repanel=-2;
+    return true;
+  }
+  if(g_piconx>=xx&&g_piconx<xx+ww&&g_picony>=yy&&g_picony<yy+hh){
+    g_piconx=-1;g_picony=-1;
+    g_repanel=-2;
+    return true;
+  }
+  return false;
+}
+
+boolean doicon(int xx,int yy,int ww,int hh)
+{
+  if(g_iconx>=xx&&g_iconx<xx+ww&&g_icony>=yy&&g_icony<yy+hh){
+    g_iconx=-1;g_icony=-1;
+    g_repanel=-2;    
+    return true;
+  }
+  return false;
+}
+
+void printat(int xx,int yy,String tex)
+{
+  //creating text into the help box
+  for(int tit=0;tit<tex.length();tit++){
+    if(tex.charAt(tit)!='|'){
+      if(g_data[256+xx+yy*12]!=byte(tex.charAt(tit))){
+        g_data[256+xx+yy*12]=byte(tex.charAt(tit));
+        g_chaup[xx+yy*16]=1;
+      }
+    }
+    xx++;
+    if(tex.charAt(tit)=='|'){xx=0;yy++;}
+  }
+}
+
+void clearmsg()
+{
+  for (int y=0;y<=3;y++){
+    for (int x=0;x<=11;x++){
+       g_data[256+x+y*12]=byte(32);
+       g_chaup[x+y*16]=1;
+    }
+  }
+}
+
+void message(String tex)
+{
+  if(tex.equals("*")){g_msgctr=100;return;}
+  clearmsg();
+  printat(0,0,tex);
+  g_msgctr=50;
+}
+
+
+void help(int a)
+{
+  String teks;
+  int b,byt,ad,valu;
+  if(g_msgctr>0)return;
+  teks="No Help";
+  clearmsg();
+  if(a>=1000){
+    a=a-1000;
+    b=a/X;
+    a=a-(b*X);
+    if(tool()==4&&g_phase==1){      
+        a=abs(g_rx2-g_rx)+1;b=abs(g_ry2-g_ry)+1;
+    }
+    if(tool()==6&&g_phase==1){      
+        a=abs(g_rx2-g_rx)+1;b=abs(g_ry2-g_ry)+1;
+    }
+    if(tool()==7&&g_phase==1){      
+        a=abs(g_rx2-g_rx)*2+1;b=abs(g_ry2-g_ry)*2+1;
+    }
+    if(tool()==8&&g_phase==1){      
+        a=abs(g_rx2-g_rx)+1;b=abs(g_ry2-g_ry)+1;
+        if(g_data['c']==1||g_shift){a--;b--;}//purkkaa
+    }   
+    //coordinates
+
+    if(a<X&&b<Y){
+        printat(0,0,str(a));
+        printat(4,0,str(b));
+        printat(0,1,str(a/8));
+        printat(4,1,str(b/8));
+        if(tool()==6&&g_phase==1){
+            printat(0,2,nf(dist(0,0,a-1,b-1),0,2));             
+            float av = getangel(g_rx2-g_rx,g_ry2-g_ry);
+            printat(0,3,nf((av),0,2));  
+        }
+        byt=a/8;
+        ad=1024+byt*8+b*X;
+        valu=g_map[ad+0]*128+g_map[ad+1]*64+g_map[ad+2]*32+g_map[ad+3]*16+g_map[ad+4]*8+g_map[ad+5]*4+g_map[ad+6]*2+g_map[ad+7]*1;
+    }
+    return;
+  }
+  
+  printat(7,3,"Key:"+char(a));
+  
+  switch(a){
+    case '.':
+      teks="Preset pens|.=reset";
+    break;
+    case TAB:
+      teks="Pick color";
+    break;
+    case'<':
+      teks="Swap colors|Right<>Left";
+    break;
+    case'>':
+      teks="Pick backgnd|shift=set";
+      if(g_backmode==0)teks="Pick backgnd|not here";
+    break;
+    case'1':
+      teks="Draw";
+    break;
+    case'2':
+      teks="Spray can";
+    break;
+    case'3':
+      teks="Continuous|Draw";
+    break;
+    case'4':
+      teks="Grab brush";
+    break;
+    case'5':
+      teks="Flood fill";
+    break;
+    case'8':
+      teks="Rectangle";
+    break;
+    case'7':
+      teks="Ellipse";
+    break;
+    case'6':
+      teks="Line";
+    break;
+    case'9':
+      teks="Brush tool";
+    break;    
+    case'0':
+      teks="Magnifier|m=direct";
+    break;    
+    case'a':
+      teks="Bitmap only|on/off";
+    break;
+    case'A':
+      teks="Export as|"+g_expname;
+    break;
+    case'b':
+      teks="A.I.|Behavior|on/off";
+    break;
+    case'B':
+      teks="Set border|[Export=N]";
+      if(g_data['Q']==1)teks="Set border|[Export=Y]";
+    break;
+    case'C':
+      teks="Set backgnd";
+      if(machine==PLUS4M||machine==PLUS4)teks="Set backgnd|V/RMB=back2";
+      if(int(g_map[1])==255)teks="Set backnd|-Not here";
+    break;
+    case'i':
+      teks="Increase|luminance";
+    break;
+    case'k':
+      teks="Decrease|luminance";
+    break;
+    case'r':
+      teks="Fill raster|on/off|RMB=swap";
+    break;
+    case'R':
+      teks="Raster from|brush|on/off";
+    break;
+    case'd':
+      teks="Recolor|right->left|on/off";
+    break;
+    case'p':
+      teks="Brush|recolor|on/off";
+    break;
+    case'q':
+      teks="IQ mode|on/off";
+    break;
+    case't':
+      teks="Tile mode|on/off";
+    break;
+    case'x':
+      teks="Brush|flip X|on/off";
+    break;
+    case'y':
+      teks="Brush|flip Y|on/off";
+    break;
+    case'z':
+      teks="Brush|rotate";
+    break;
+    case'h':
+      teks="Pen size "+(g_bsize+1)+"|LMB/h=less|RMB/H=bigger";
+    break;
+    case'j':
+      if(g_spare==0){ teks="Switch to|spare page|RMB=CopyTo";}
+        else
+      {teks="Switch to|front page|RMB=CopyTo";}
+    break;
+    case'f':
+      teks="Geometry|fill|on/off";
+    break;
+    case'c':
+      teks="Constrain|to grid|on/off";
+    break;
+    case'm':
+      teks="Magnify|on/off";
+    break;
+    case'g':
+      teks="Draw grid|on/off|G=size "+str(g_gridx);
+    break;    
+    case'X':
+      teks="Mirror X|on/off";
+    break;
+    case'Y':
+      teks="Mirror Y|on/off";
+    break;
+    case'l':
+      teks="Load data|bin/png";
+    break;
+    case's':
+      teks="Save as|[RMB=Save]|bin/png";
+    break;
+    case'u':
+      teks="Undo u LMB|Redo U RMB";
+    break;
+    case'U':
+      teks="Redo";
+    break;
+    case'e':
+      teks="Export PNG";
+    break;
+    case'E':
+      teks="Export as|source";
+    break;
+    case'o':
+      teks="Clear|screen";
+    break;
+    case 'O':
+      teks="Export|specific";
+    break;
+    case 'n':
+      teks="Playbrush|on/off|RMB=speed";
+    break;
+    case 'w':
+      teks="Format|Import:|no support";
+      if(g_formatname!="")teks="Import as|"+g_formatname;
+    break;
+    case 'W':
+      teks="Export:|no support";
+      if(g_formatname!="")teks="Export as|"+g_formatname;
+    break;
+  }
+  printat(0,0,teks);
+}
+
+void icontable(int xx,int yy,int tabletype,int realdraw)
+{
+  String pan="";
+  int x,y,ad;
+  g_data['9']=0;
+  if(g_btype==9)g_data['9']=1;
+  
+  // the main and sideboard icon panel order
+  if(tabletype==0)pan=";;h9::123456::78::pzxy::XYtn::lsEAwW::jc0g::uo::.b";
+  if(tabletype==1)pan="BCrRfd";
+  if(tabletype==2)pan="ik";
+  
+  x=0;y=0;
+  
+  for(int tit=0;tit<pan.length();tit++){
+    ad=pan.charAt(tit);
+    if(g_repanel<=0){
+      if(ad!=';'&&ad!=':'&&ad!='.'){
+        if(realdraw==1){
+          int icolor=g_data[ad];
+          if(ad=='j'&&g_spare==1)icolor=1;
+          drawicon(xx+x,yy+y,ad-48,icolor);
+        }
+      }
+      if(ad==';'){//draw the preset brush box
+        if(realdraw==1){
+          drawchar(xx,yy,128);
+          drawchar(xx+8*g_uizoom,yy,129);
+          drawchar(xx+16*g_uizoom,yy,130);
+          drawchar(xx+24*g_uizoom,yy,131);
+          drawchar(xx,yy+8*g_uizoom,132);
+          drawchar(xx+8*g_uizoom,yy+8*g_uizoom,133);
+          drawchar(xx+16*g_uizoom,yy+8*g_uizoom,134);
+          drawchar(xx+24*g_uizoom,yy+8*g_uizoom,135);
+        }      
+      }
+    }
+    
+    //tooltip
+    if(ad!=':'&&ad!=';'&&ad!='.'){
+      if(realdraw==0){
+        if(moicon(xx+x,yy+y,16*g_uizoom,16*g_uizoom))help(ad);
+      }
+      if (doicon(xx+x,yy+y,16*g_uizoom,16*g_uizoom)){
+        //println(g_realbutton);
+        if(ad=='C'&&g_realbutton==39)ad='V';
+        if(ad=='B'&&g_realbutton==39)ad='Q';
+        if(ad=='u'&&g_realbutton==39)ad='U';
+        if(ad=='n'&&g_realbutton==39)ad='N';     
+        if(ad=='h'&&g_realbutton==39)ad='H';
+        if(ad=='s'&&g_realbutton==39)ad='S';
+        if(ad=='j'&&g_realbutton==39)ad='J';
+        if(ad=='g'&&g_realbutton==39)ad='G';
+        if(ad=='r'&&g_realbutton==39){
+          ad=')';if(g_shift)ad='(';
+        }        
+        command(ad);g_msgctr=50;
+      } 
+    }
+    if(ad==';'){
+      for(int ii=0;ii<=3;ii++){
+        for(int jj=0;jj<=1;jj++){
+          if(doicon(xx+ii*8*g_uizoom,yy+jj*8*g_uizoom,8*g_uizoom,8*g_uizoom))command(128+ii+jj*4);
+        }
+      }
+    }
+    if(tabletype==0){
+      x=x+16*g_uizoom;
+      if(ad=='.')x=x-8*g_uizoom;
+      if(x>16*g_uizoom){
+        x=0;y=y+16*g_uizoom;
+        if(ad==':')y=y-14*g_uizoom;
+      }
+    }
+    if(tabletype==1||tabletype==2){
+      y=y+16*g_uizoom;
+      if(y>16*g_uizoom){y=0;x=x+16*g_uizoom;}
+    }
+  }
+  g_data['9']=0;
+}
+
+int nextluminance(int f,int d)
+{
+  int res=f+d;
+  if(machine==PLUS4||machine==PLUS4M){
+    if(f+d*15>120)return f;
+    if(f+d*15<1)return f;
+    if(d==1)return f+15;
+    if(d==-1)return f-15;
+    return res;
+  }
+  
+  if(g_map[13]==C64){//here the "C64" is generic across C64,C64M and potential FLI modes
+    int out[]={6,1,11,15,8,10,9,13,14,2,3,4,5,1,12,7}; // from "Ptoing"
+    if(d==1)res=out[f];
+    if(d==-1){
+      if(f==0)return 0;
+      for(int i=0;i<g_maxcolors;i++){
+          if(out[i]==f)res=i;
+      }
+    }
+  }
+  
+  if(g_map[13]==MSX){
+    int out[]={ 1, 4, 9,10, 6,12,13,14, 5, 3, 7,15, 2, 8,11,15}; // calculated Y
+    if(d==1)res=out[f];
+    if(d==-1)
+    {
+      if(f==0)return 0;
+        for(int i=0;i<g_maxcolors-1;i++){
+            if(out[i]==f)res=i;
+        }
+    }
+  }
+  return res;
+}
+
+
+
+int tool()
+{
+  //returns the current tool #, for convenience
+  //as there is no "tool" variable really 
+  for(int i='0';i<='9';i++){
+    if(g_data[i]==1)return i-'0';
+  }
+  return 0;
+}
+
+void set_tool(int s)
+{
+  //set current tool, for convenience
+  for(int i='0';i<='9';i++){
+    g_data[i]=0;
+  }
+  g_data[48+s]=byte(1);
+  g_map[12]=byte(s);
+}
+
+void selectcolor(int hand,int x)
+{
+  if(x>=g_maxcolors)x=x-g_maxcolors;
+  if(x<0)x=x+g_maxcolors;
+  if(hand==0){
+    g_farge=x;g_ofarge=x; //kludgey, the colour and the "original colour"
+    if(g_btype==9)g_data['p']=1;
+    g_realfront=byte(g_farge);
+    g_realback=byte(g_backg);
+  }
+  if(hand==1){
+    g_backg=x;
+    g_realback=byte(g_backg);
+    g_realfront=byte(g_farge);
+  }
+}
+
+void refresh()
+{
+  //refreshes all "dirty chars" and icon panels
+  for(int i=0;i<MX*MY;i++){
+    g_redo[i]=byte(0);g_remdo[i]=byte(1);
+  }
+  if(g_boxreconstruct==0)g_boxreconstruct=1;
+  //elsewhere use g_boxreconstruct=2 for complete window reconstruction
+}
+
+void refresh_all()
+{
+  refresh();g_boxreconstruct=2;
+}
+
+void palettebox(float x0,int y0,float x1)
+{
+   if(g_palsteps==0)return;
+   float expand=((x1-x0)/g_palsteps);
+   int divs=int(255/(g_palsteps-1));
+   for(int i=0;i<g_palsteps;i++){   
+       if(doicon_drag(int(x0+expand*i),y0,int(expand),7*g_uizoom)){g_r[g_farge]=int(i*divs);message("RED:"+i);makecolor(g_farge,g_r[g_farge],g_g[g_farge],g_b[g_farge]);refresh();g_boxreconstruct=2;}
+       if(doicon_drag(int(x0+expand*i),y0+10*g_uizoom,int(expand),7*g_uizoom)){g_g[g_farge]=int(i*divs);message("GREEN:"+i);makecolor(g_farge,g_r[g_farge],g_g[g_farge],g_b[g_farge]);refresh();g_boxreconstruct=2;}
+       if(doicon_drag(int(x0+expand*i),y0+20*g_uizoom,int(expand),7*g_uizoom)){g_b[g_farge]=int(i*divs);message("BLUE:"+i);makecolor(g_farge,g_r[g_farge],g_g[g_farge],g_b[g_farge]);refresh();g_boxreconstruct=2;}
+   }
+   e_rect(int(x0),y0,int(x1-x0),7*g_uizoom,g_rgb[258]);   
+   e_rect(int(x0),y0+10*g_uizoom,int(x1-x0),7*g_uizoom,g_rgb[258]);
+   e_rect(int(x0),y0+20*g_uizoom,int(x1-x0),7*g_uizoom,g_rgb[258]);
+    
+   for(int i=1;i<g_palsteps;i++){
+     e_rect(int(x0+expand*i),y0,g_uizoom,2*g_uizoom,g_rgb[257]);
+     e_rect(int(x0+expand*i),y0+10*g_uizoom,g_uizoom,2*g_uizoom,g_rgb[257]);
+     e_rect(int(x0+expand*i),y0+20*g_uizoom,g_uizoom,2*g_uizoom,g_rgb[257]);     
+   }        
+   e_rect(int(x0+expand*g_r[g_farge]/divs),y0, int(expand),7*g_uizoom,g_rgb[260]);
+   e_rect(int(x0+expand*g_g[g_farge]/divs),y0+10*g_uizoom, int(expand),7*g_uizoom,g_rgb[261]);
+   e_rect(int(x0+expand*g_b[g_farge]/divs),y0+20*g_uizoom, int(expand),7*g_uizoom,g_rgb[262]);
+}
+
+void colorselector(int xo,int yo)
+{
+  int x,y,ad,yfat;
+  int far,xonko,yhei,maxp,xloc,yloc;
+  int bfat;
+  float expand,divus;
+  xonko=16*g_uizoom;yhei=16*g_uizoom;expand=1;yfat=4*g_uizoom;bfat=1*g_uizoom;
+  if(g_maxcolors>60){yhei=4*g_uizoom;yfat=0;bfat=1;}
+  divus=255/g_palsteps;
+  x=0;y=0;far=0xff000000;
+  
+  maxp=g_maxcolors;xonko=512/g_maxcolors;
+  xonko=xonko/2;xonko=xonko*g_uizoom;
+   
+  if(g_maxcolors>32){maxp=g_maxcolors/2;xonko=1024/g_maxcolors;}
+  if(machine==PLUS4||machine==PLUS4M)xonko=15*g_uizoom;
+   
+     for(x=0;x<g_maxcolors;x++){
+       xloc=xo+x*xonko;yloc=yo+8*g_uizoom;
+         if(g_maxcolors>60){yloc=yo+yhei*7;
+           if(x>15&&x<=30){xloc=xo+(x-15)*xonko;yloc=yo+yhei*6+yfat*2;}
+           if(x>30&&x<=45){xloc=xo+(x-30)*xonko;yloc=yo+yhei*5+yfat*4;}
+           if(x>45&&x<=60){xloc=xo+(x-45)*xonko;yloc=yo+yhei*4+yfat*6;}
+           if(x>60&&x<=75){xloc=xo+(x-60)*xonko;yloc=yo+yhei*3+yfat*8;}
+           if(x>75&&x<=90){xloc=xo+(x-75)*xonko;yloc=yo+yhei*2+yfat*10;}
+           if(x>90&&x<=105){xloc=xo+(x-90)*xonko;yloc=yo+yhei*1+yfat*12;}
+           if(x>105&&x<=120){xloc=xo+(x-105)*xonko;yloc=yo+yhei*0+yfat*14;}      
+         }
+      if(doicon_drag(xloc,yloc,xonko,yhei))
+      {
+        if(mouseButton==LEFT||mouseButton==CENTER){
+          selectcolor(0,x);
+        }  
+        if(mouseButton==RIGHT){
+          selectcolor(1,x);g_button=LEFT;
+        }
+      }
+    
+      if(g_repanel<=0){
+        int index;
+        index=x;
+        if(machine==MSX&&x==0)index=g_map[1];
+        e_rect(xloc,yloc,xonko,yhei,g_rgb[index]); // the colour blocks
+        far=0xff000000;
+        if(g_farge==x)far=0xff808080;
+        e_rect(xloc,yloc-yfat,xonko,yfat,far);
+        if(doicon(xloc,yloc-yfat,xonko,yfat))selectcolor(0,x);
+        
+        far=0xff000000;     
+        if(g_backg==x&&yfat>0)far=0xff808080;
+        
+        e_rect(xloc,yloc+yhei,xonko,yfat,far); 
+        if(doicon(xloc,yloc+yhei,xonko,yfat))selectcolor(1,x);
+        if(yfat==0){
+          if(g_farge==x){
+            e_rect(xloc,yloc,xonko/4,yhei/4,far);
+            e_rect(xloc,yloc+1,xonko/8,yhei/4,far);
+          }
+          if(g_backg==x){
+            e_rect(xloc+xonko-xonko/4,yloc+yhei-2,xonko/4,yhei/4,far);
+            e_rect(xloc+xonko-xonko/8,yloc+yhei-3,xonko/8,yhei/4,far);
+          }
+        }
+        if(int(g_map[0])==x){
+          far=0xff000000;
+          if(dist(g_r[x],g_g[x],g_b[x],0,0,0)<1)far=0xffffffff;
+          e_rect(xloc,yloc,xonko,bfat,far);
+          e_rect(xloc,yloc+yhei-bfat,xonko,bfat,far);
+          e_rect(xloc,yloc,bfat,yhei,far);
+          e_rect(xloc+xonko-bfat,yloc,bfat,yhei,far);
+        }
+        if(int(g_map[1])==x){
+          far=0xff000000;
+          if(dist(g_r[x],g_g[x],g_b[x],0,0,0)<1)far=0xffffffff;       
+          e_rect(xloc+xonko/4,yloc+yhei/4,xonko/4,yhei/4,far);
+        }
+        if(machine==PLUS4||machine==PLUS4M){
+          if(int(g_map[1])!=255&&int(g_map[2])==x){
+          far=0xff000000;
+          if(dist(g_r[x],g_g[x],g_b[x],0,0,0)<1)far=0xffffffff;            
+            e_rect(xloc+xonko-(xonko/4)*2,yloc+yhei-(yhei/4)*2,xonko/4,yhei/4,far);
+          }
+        }
+    }
+  }
+}
+
+void messagebox(int ox,int oy)
+{
+  int cz=8*g_uizoom;
+  // lcd character display chardisplay textbox
+  // coordinates. has its own "dirtychar"
+  for(int xx=0;xx<=11;xx++){
+    for(int yy=0;yy<=3;yy++){
+      if(g_chaup[xx+yy*16]==1){
+        g_chaup[xx+yy*16]=0;
+        drawchar(ox+xx*cz,oy+yy*cz,g_data[256+xx+yy*12]);
+      }
+    }
+  }
+}
+
+void colorindicator(int ox,int oy)
+{
+  int bs=8*g_uizoom;
+  int h=0;
+  if(g_button==RIGHT)h=1;
+  e_rect(ox,oy,bs*2,bs*4,g_rgb[int(g_realback)]);
+  e_rect(ox+bs/2,oy+4*g_uizoom,12*g_uizoom,bs*2,g_rgb[int(g_realfront)]);  
+  if(doicon(ox,oy,bs*2,bs*3))command('<');
+  if(machine==C64M||machine==MSX||machine==AMIGA){
+    e_rect(ox,oy+bs*3,bs*2,bs,g_rgb[int(g_map[1])]);
+    d_rect(ox,oy+bs*3,bs*2,bs,g_rgb[int(257)]);
+    if(doicon(ox,oy+bs*3,bs*2,bs))
+    {
+      if(g_shift==false)selectcolor(h,int(g_map[1]));
+      if(g_shift)command('C');
+    }
+  }
+  if(machine==PLUS4M){
+    e_rect(ox,oy+bs*3,bs,bs,g_rgb[int(g_map[1])]);    
+    e_rect(ox+8*g_uizoom,oy+bs*3,bs,bs,g_rgb[int(g_map[2])]);
+    d_rect(ox,oy+bs*3,bs,bs,g_rgb[int(257)]);    
+    d_rect(ox+8*g_uizoom,oy+bs*3,bs,bs,g_rgb[int(257)]);    
+    if(doicon(ox,oy+bs*3,bs,bs))
+    {
+      if(g_shift==false)selectcolor(h,int(g_map[1]));
+      if(g_shift)command('C');
+    }
+    if(doicon(ox+8*g_uizoom,oy+bs*3,bs,bs))
+    {
+      if(g_shift==false)selectcolor(h,int(g_map[2])); 
+      if(g_shift)command('V');  
+    }
+  }
+}
+
+void update_ui()
+{
+  if(g_iconmode==1){
+    for(int i=0;i<=80000;i++){
+      g_icons[i]=g_map[i];
+    }
+  }
+  
+  if(g_repanel<=0)g_repanel++;
+  messagebox(width-12*8*g_uizoom,height-4*8*g_uizoom);   
+
+  // when tooltipping, the panels are not really
+  // drawn but used for easy coordinate reference
+      
+  if(g_repanel>0){
+    icontable(width-32*g_uizoom,0,0,0);
+    icontable(272*g_uizoom,height-32*g_uizoom,1,0);
+    if(machine==PLUS4M||machine==PLUS4){ 
+      icontable(240*g_uizoom,height-32*g_uizoom,2,0); 
+    }    
+    return;
+  }
+
+  if(g_repanel>0)return;
+   
+  icontable(width-32*g_uizoom-1,0,0,1);
+  icontable(272*g_uizoom,height-32*g_uizoom,1,1);
+  palettebox(g_uizoom*324+4,height-32*g_uizoom,width-(96*g_uizoom)-4);
+  if(machine==PLUS4M||machine==PLUS4){ 
+    icontable(240*g_uizoom,height-32*g_uizoom,2,1); 
+  }
+  colorselector(0,height-32*g_uizoom);
+  colorindicator(256*g_uizoom,height-32*g_uizoom);
+}
+
+void magport()
+{
+  int b=g_uizoom*2;
+  int xo=0;int yo=0;
+  for(int y=0;y<Y;y++){
+    for(int x=0;x<X;x++){
+      int raddr=(xo*24+x)+(yo*24+y)*width;
+      pixels[raddr]=int(g_rgb[easygetcolor(x,y)]);
+    }
+  }
+}
+
+void viewport()
+{
+  // formerly void redo()
+  // main machine screen redraw
+  // and dirty char update
+  int xx,yy,xo,yo,xwin,ywin,x,y,winsux,winsuy,rubx;
+  int ad,cad,a,b,c,mmode,fari,psize;
+  int zonx,zony,maxx,mayy,mag,raddr;
+  int left=32*g_uizoom;
+  raddr=0;winsux=0;winsuy=0;
+  if(g_backmode==0)g_map[1]=0;//some computers have overall background
+
+  mmode=magmode();
+  fari=0;
+  makecolor(259,g_r[g_map[0]],g_g[g_map[0]],g_b[g_map[0]]);//use border color
+  if(g_data['M']==1&&g_data['m']==1)g_data['m']=0;
+  if(g_data['m']==1)makecolor(259,48,48,48);//don't use border color in mag modes
+  if(g_data['M']==1)makecolor(259,48,48,48);
+
+  psize=g_magpix[mmode];mag=psize*8;
+  maxx=magx();mayy=magy();
+  
+  if(g_boxreconstruct==1){
+    g_boxreconstruct=0;
+    e_rect(0,(mayy*psize)*8,maxx*psize*8,height-((g_vedge+g_uizoom*2)+(mayy*psize*8)),g_rgb[259]);
+    e_rect((maxx*psize)*8,0,width-(maxx*psize*8+(g_hedge+g_uizoom*2)),height-(g_vedge+g_uizoom),g_rgb[259]);   
+  }
+  if(g_boxreconstruct==2){//in case of full window update
+    g_boxreconstruct=0;
+    e_rect(0,0,width-(g_hedge+g_uizoom*2),height-(g_vedge+g_uizoom*2),g_rgb[259]);
+  }
+  
+  maxx--;mayy--;
+  zonx=MX-magx();zony=MY-magy();
+   
+  if(g_ofx>zonx)g_ofx=zonx;
+  if(g_ofy>zony)g_ofy=zony;
+  if(g_ofx<0)g_ofx=0;
+  if(g_ofy<0)g_ofy=0;
+
+  if(mmode==10){g_ofx=0;g_ofy=0;maxx=MX-1;mayy=MY-1;winsux=g_windowx;winsuy=g_windowy;mag=16;}//mini  
+  if(mmode==0){g_ofx=0;g_ofy=0;maxx=MX-1;mayy=MY-1;winsux=g_windowx;winsuy=g_windowy;mag=24;}//normal
+  if(mmode==20){g_ofx=0;g_ofy=0;maxx=MX-1;mayy=MY-1;winsux=g_windowx;winsuy=g_windowy;mag=32;}//maxi
+
+  b=0;c=0;a=5;
+  
+  if(mmode==1||mmode==2||mmode==11||mmode==12||mmode==21||mmode==22){
+    winsux=0;winsuy=0;fill(32,32,32);
+  }
+  
+  for(ywin=0;ywin<=mayy;ywin++){
+    for(xwin=0;xwin<=maxx;xwin++){
+  
+      // source coords: is 0,0 if not magged
+      xx=g_ofx+xwin;yy=g_ofy+ywin;
+      // divided into character area blocks
+      // which are only updated if necessary
+      xo=xwin;yo=ywin;
+    
+      if(int(g_redo[xx+yy*MX])==0){
+    
+        for(y=0;y<=7;y++){//pixel rows inside "char"
+
+          switch(g_multic){
+            case 0:
+              cad=65536+xx+((yy*X)+y*MX);
+              a=int(g_map[cad]);b=int(g_map[(MX*MY)*8+cad]);c=int(g_map[(MX*MY)*8+cad]);
+            break;
+            case 1:
+              cad=65536+xx+(yy*MX);
+              a=int(g_map[cad]);b=int(g_map[cad+1000]);c=int(g_map[cad+2000]);
+              if(machine==PLUS4M){c=int(g_map[2]);}
+            break;
+            case 2:
+              cad=65536+xx+((yy*X)+y*MX);
+              a=int(g_map[cad]);b=int(g_map[(MX*MY)*8+cad]);c=int(g_map[(MX*MY)*8+cad]);
+            break;
+          }
+    
+          ad=1024+xx*8+yy*(X*8)+y*X;
+              
+          int po,vop;
+          
+          for(x=0;x<=7;x++){//pixel columns inside pixel row
+            vop=x/2;
+            if(g_multic==0){
+              if(int(g_map[ad+x])==1){
+                fari=a;if(fari==0)fari=g_map[1];
+              }
+              else{
+                fari=b;if(fari==0)fari=g_map[1];
+              }
+            }
+            if(g_multic==1)
+            {
+              po=int(g_map[ad+vop*2])+int(g_map[ad+vop*2+1]*2);
+              if(po==0)fari=g_map[1];//00 comes from $d021 in real c64 and background 1 in plus/4
+              if(po==1)fari=a;//10
+              if(po==2)fari=b;//01
+              if(po==3)fari=c; //g_map[2];//11 // comes from $d800 in real c64 and background 2 in plus/4             
+            }
+            if(g_multic==2){// "amiga" mode
+              fari=int(g_map[ad+x]);
+            }
+            
+            if(g_rubbermode==1){// rubberband mode
+              rubx=x;if(g_multic==1||g_hzoomer==2){rubx=x/2;rubx=rubx*2;}
+              if(fylli()==1){
+                if(xx*8+rubx==g_rx||xx*8+rubx==g_rx2)
+                {
+                  if(yy*8+y>=g_ry&&yy*8+y<=g_ry2)fari=256;              
+                  if(yy*8+y>=g_ry&&yy*8+y<=g_ry2)fari=256;                  
+                }
+                if(yy*8+y==g_ry||yy*8+y==g_ry2){
+                  if(xx*8+x>=g_rx&&xx*8+x<=g_rx2)fari=256;
+                  if(xx*8+x>=g_rx&&xx*8+x<=g_rx2)fari=256;
+                }
+              }
+            }
+            
+           color ari=g_rgb[fari];
+            switch(mmode){
+              case 0:
+                    raddr=(xo*24+x*3)+(yo*24+y*3)*width;raddr=raddr+g_windowx+g_windowy*width;              
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;
+                    raddr=raddr+width;             
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;
+                    raddr=raddr+width;
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;               
+              break;
+              case 1:
+                    raddr=(xo*64+x*8)+(yo*64+y*8)*width;              
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;pixels[raddr+6]=ari;pixels[raddr+7]=ari;              
+                    raddr=raddr+width;             
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;pixels[raddr+6]=ari;pixels[raddr+7]=ari;   
+                    raddr=raddr+width;
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;pixels[raddr+6]=ari;pixels[raddr+7]=ari;
+                    raddr=raddr+width;
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;pixels[raddr+6]=ari;pixels[raddr+7]=ari;
+                    raddr=raddr+width;             
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;pixels[raddr+6]=ari;pixels[raddr+7]=ari;   
+                    raddr=raddr+width;
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;pixels[raddr+6]=ari;pixels[raddr+7]=ari;
+                    raddr=raddr+width;
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;pixels[raddr+6]=ari;pixels[raddr+7]=ari;
+                    raddr=raddr+width;
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;pixels[raddr+6]=ari;pixels[raddr+7]=ari;        
+              break;
+              case 2:
+                    e_rect(xo*(64*g_uizoom)+x*(8*g_uizoom),yo*(64*g_uizoom)+y*(8*g_uizoom),8*g_uizoom,8*g_uizoom,g_rgb[fari]);
+              break;
+              // mini modes
+              case 10:  
+                    raddr=(xo*16+x*2)+(yo*8+y)*width*2;raddr=raddr+g_windowx+g_windowy*width;           
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;
+                    raddr=raddr+width;
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;              
+              break;
+              case 11:  
+                    raddr=(xo*48+x*6)+(yo*48+y*6)*width;         
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;          
+                    raddr=raddr+width;
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;           
+                    raddr=raddr+width;   
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;           
+                    raddr=raddr+width;   
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;         
+                    raddr=raddr+width;
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;            
+                    raddr=raddr+width;
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;pixels[raddr+4]=ari;pixels[raddr+5]=ari;         
+              break;     
+              case 12:
+                    e_rect(xo*(64*g_wzoom)+x*(8*g_wzoom),yo*(64*g_wzoom)+y*(8*g_wzoom),8*g_wzoom,8*g_wzoom,g_rgb[fari]);
+              break;
+              // maxi modes
+              case 20:
+                    raddr=(xo*(8*4)+x*4)+(yo*(8*4)+y*4)*width;raddr=raddr+g_windowx+g_windowy*width;              
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;
+                    raddr=raddr+width;             
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;
+                    raddr=raddr+width;
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;
+                    raddr=raddr+width;              
+                    pixels[raddr]=ari;pixels[raddr+1]=ari;pixels[raddr+2]=ari;pixels[raddr+3]=ari;
+              break;    
+              case 21:
+                    e_rect(xo*(32*g_wzoom)+x*(4*g_wzoom),yo*(32*g_wzoom)+y*(4*g_wzoom),4*g_wzoom,4*g_wzoom,g_rgb[fari]);        
+              break;
+              case 22:
+                    e_rect(xo*(64*g_wzoom)+x*(8*g_wzoom),yo*(64*g_wzoom)+y*(8*g_wzoom),8*g_wzoom,8*g_wzoom,g_rgb[fari]);        
+              break;
+            }
+        }//one pixel inside pixel row
+    }//one pixel row inside char
+    
+    //draw grid
+    //can in principle be non-square
+    if(int(g_data['g'])==1){
+      int lapx;
+      lapx=(xx*8)/g_gridx;lapx=lapx*g_gridx;
+      if(lapx==(xx*8)){
+        t_rect(xo*mag+winsux,yo*mag+winsuy,1,mag,g_rgb[257]);
+        if(g_gridx==4){
+          t_rect(xo*mag+winsux+4*psize,yo*mag+winsuy+1,1,mag/2-2,g_rgb[257]);
+          t_rect(xo*mag+winsux+4*psize,yo*mag+winsuy+mag-mag/2+2,1,mag/2-2,g_rgb[257]);          
+        }
+      }
+      lapx=(yy*8)/g_gridy;lapx=lapx*g_gridy;
+      if(lapx==(yy*8)){
+        t_rect(xo*mag+winsux+1,yo*mag+winsuy,mag-1,1,g_rgb[257]);
+        if(g_gridy==4){
+          t_rect(xo*mag+winsux+1,yo*mag+winsuy+4*psize,mag/2-2,1,g_rgb[257]);
+          t_rect(xo*mag+winsux+2+mag-mag/2,yo*mag+winsuy+4*psize,mag/2-2,1,g_rgb[257]);          
+        }
+      }
+    }
+    g_redo[xx+yy*MX]=byte(1);
+  } //dirty char?
+  }//x char
+ }//y char
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/draw_inputs.pde	Tue Jul 03 20:56:55 2018 +0300
@@ -0,0 +1,297 @@
+// Collect all that "reads" the virtual image in some way or other
+// plus other passive manipulations
+
+int odd(int v)
+{
+    if((v|1)==v)return 1;
+    return 0;
+}
+
+int even(int v)
+{
+    if(v>>1==v)return 1;
+    return 0;
+}
+
+float getangel(float xx,float yy)
+{
+    float ang=degrees(atan2(xx,-yy));
+    if(ang<0)return 360+ang;
+    return ang;
+}
+
+int zxcolor(int col)
+{
+  //something that allows different zx brightness colors treated logically as the same
+  //i.e. bright red and dark red the same. handy for brush transparency
+  if(g_britemode==0)return col;
+  if(col>7)return col-8;
+  return col;
+}
+
+//the "slow" call to mark "dirty block"
+void updatepoint(int xx,int yy)
+{
+  if(yy<0||xx<0||xx>=X||yy>=Y)return;
+  xx=xx/8;yy=yy/8;xx=xx+yy*MX;
+  g_redo[xx]=byte(0);//block update
+  g_remdo[xx]=byte(1);//block update
+}
+
+int getmultibrush(int x1,int y1)
+{
+  
+  //returns the multicolor color on point x1,y1 at brush
+    
+  int ad,looks,mmc; 
+  if(g_multic==2)return g_brush[1024+x1+y1*X];
+  
+  ad=1024+x1+y1*X;
+  looks=65536+(x1/8)+(y1/8)*MX;
+  mmc=g_brush[ad]+g_brush[ad+1]*2;
+  switch(mmc)
+  {
+    case 0:
+      return g_map[1];
+    case 1:
+      return g_brush[looks];
+    case 2:
+      return g_brush[looks+1000];
+    case 3:
+      if(machine==PLUS4M)return int(g_map[2]);
+      return g_brush[looks+2000];
+  }
+  return g_brush[ad]+g_brush[ad+1]*2;
+}
+
+int getmultic(int x1,int y1,int mode) //mode 0=screen 1=brush
+{
+  
+  //returns the multicolor color on point x1,y1
+    
+  int ad,looks,mmc,source1,source2;
+   
+  if(g_multic==2){
+    looks=1024+x1+y1*X;
+    if(mode==0)return g_map[looks];
+    if(mode==1)return g_brush[looks];
+  }
+  x1=x1/2;x1=x1*2;
+  ad=1024+x1+y1*X;
+  source1=0;source2=0;
+  looks=65536+(x1/8)+(y1/8)*MX;
+  if(mode==0){source1=g_map[ad];source2=g_map[ad+1];}
+  if(mode==1){source1=g_brush[ad];source2=g_brush[ad+1];}
+  mmc=source1+source2*2;
+  //source1=0
+  //source2=+1
+  //00=zeroc =0
+  //01=color1=2
+  //10=color2=1
+  //11=color3=3
+  
+  if(mode==0){
+    switch(mmc)
+    {
+      case 0:
+        return g_map[1];
+      case 1:
+        return g_map[looks];
+      case 2:
+        return g_map[looks+1000];
+      case 3:
+        if(machine==PLUS4M)return int(g_map[2]);
+        return g_map[looks+2000];
+    }
+  }
+  if(mode==1){
+    switch(mmc)
+    {
+      case 0:
+        return g_map[1];
+      case 1:
+        return g_brush[looks];
+      case 2:
+        return g_brush[looks+1000];
+      case 3:
+        if(machine==PLUS4M)return int(g_map[2]);
+        return g_brush[looks+2000];
+    }
+  }  
+  return source1+source2;
+}
+
+int getattra(int xx,int yy,int mode) //mode foreground backround
+{
+  //returns the internal foreground / background color on point xx,yy
+  int xv,yv,val;
+  if(g_multic==2){
+    if(mode==0)return getmultic(xx,yy,0);
+    return g_backg;
+  }
+  if(g_multic==1){
+   if(mode==0)return getmultic(xx,yy,0);
+   return g_map[1];// was 0?
+  }
+  xx=xx/8;
+  yv=yy/8;
+  int ad=65536+xx+yy*MX; 
+  if(mode==0){
+    val=g_map[ad];
+    if(g_britemode==1&&val==8)return 0;
+    return val;
+  }
+//  if(mode==1)
+  val=g_map[ad+(MX*MY)*8];
+  if(g_britemode==1&&val==8)return 0;
+  return val;
+}
+
+int getabsa(int xx,int yy,int mode)//mode 0=screen 1=brush
+{
+  // returns the visible colour on point xx,yy
+  int sad,ssap,ad,val;
+  int chek;
+  val=0;sad=1024+xx+yy*X;
+  xx=xx/8;
+  ad=65536+xx+yy*MX;
+  chek=int(g_map[sad]);
+  if(chek==100||chek==200)return chek;
+  
+  if(mode==0){
+    ssap=int(g_map[sad]);
+  }else{
+    ssap=int(g_brush[sad]);
+  }
+  
+  if(ssap==1){
+    if(mode==0){val=g_map[ad];}else{val=g_brush[ad];}
+    if(g_britemode==1&&val==8)return 0;
+    return val;
+  }
+  if(ssap==0){         
+    if(mode==0){val=g_map[ad+(MX*MY)*8];}else{val=g_brush[ad+(MX*MY)*8];;}
+    if(g_britemode==1&&val==8)return 0;
+    return val;
+  }
+  return g_map[sad];
+}
+
+//the most accessible way to get a color index from a point
+int easygetcolor(int xx,int yy)
+{
+  if(yy<0||xx<0||xx>=X||yy>=Y)return 0;
+  if(g_multic>0)return getmultic(xx,yy,0);
+  if(g_multic==0)return getabsa(xx,yy,0);
+  return 0;
+}
+
+void infersize()
+{
+  int xx,yy,cp,molox,okay;
+  int bx,by;
+  storeparameters();
+  xx=0;molox=1;okay=0;
+  if(g_multic==1||g_hzoomer==2)molox=2;
+  cp=easygetcolor(0,0);
+  for(xx=0;xx<X;xx=xx+molox){
+    if(easygetcolor(xx,0)==cp&&okay==0){g_animx=xx;}
+    else{
+      okay=1;
+    }
+  }
+  okay=0;
+  for(yy=0;yy<Y;yy++){
+    if(easygetcolor(0,yy)==cp&&okay==0){g_animy=yy;}
+    else{
+      okay=1;
+    }
+  }
+
+  g_animx=g_animx+molox;
+  g_animy=g_animy+1;
+  if(g_animx>63||g_animy>63||g_animx<=2||g_animy<=2){
+    message("BAD SIZE|See manual");restoreparameters();g_data['n']=0;
+    return;
+  }
+  int boldsourcex=g_bsourcex;
+  int boldsourcey=g_bsourcey;
+  int boldsourcex2=g_bsourcex2;
+  int boldsourcey2=g_bsourcey2;
+  
+  g_bsourcex=g_animx;
+  g_bsourcey=0;
+  g_bsourcex2=g_animx+g_animx-molox;
+  g_bsourcey2=g_animy-1;
+  g_animframes=0;
+  g_animno=1;
+  int raamit=-1;
+  for(yy=0;yy<=Y;yy=yy+g_animy){
+    for(xx=0;xx<=X;xx=xx+g_animx){
+      okay=1;
+      for(bx=0;bx<g_animx;bx=bx+molox){
+        for(by=0;by<g_animy;by++){
+          if(easygetcolor(xx+bx,yy+by)!=cp)okay=0;
+        }
+      }
+      if(okay==1&&g_animframes<=1)g_animframes=raamit;
+      if(xx+g_animx<X||xx+g_animx==X)raamit++;
+    }
+  }
+  if(g_animframes<=0){
+    message("BAD BOOKEND|See manual");restoreparameters();g_data['n']=0;
+    g_bsourcex=boldsourcex;g_bsourcey=boldsourcey;
+    g_bsourcex2=boldsourcex2;g_bsourcey2=boldsourcey2;
+    return;
+  }
+  message("Play Brush|"+g_animx+" x "+g_animy+"|"+g_animframes+" frames");
+}
+
+void animbrush_do()
+{
+  int bx,by;
+  int horisize;
+  int molox=1;
+  if(g_multic==1)molox=2;
+  horisize=X/g_animx;
+  g_animno=g_animno+1;
+  if(g_animno>g_animframes)g_animno=1;
+  by=g_animno/horisize;
+  bx=g_animno-(by*horisize);
+  g_bsourcex=bx*g_animx;
+  g_bsourcey=by*g_animy;
+  g_bsourcex2=g_bsourcex+g_animx-molox;
+  g_bsourcey2=g_bsourcey+g_animy-1;
+}
+
+void set_fixed_raster(int set)
+{
+  for(int i=0;i<64;i++){
+    g_fixedraster[i]=g_rasterpatterns[set*64+i];
+  }
+}
+
+int get_raster(int xx,int yy)
+{
+  int molox=1;
+  if(g_multic==1||g_hzoomer==2)molox=2;
+  xx=xx+g_raster_offset_x*molox;
+  yy=yy+g_raster_offset_y;
+  if(g_multic==1||g_hzoomer==2){
+    xx=xx/2;
+  }
+  int mx=xx/8;
+  int my=yy/8;
+  mx=mx*8;my=my*8;xx=xx-mx;yy=yy-my;
+  return g_fixedraster[xx+yy*8];
+}
+
+void refreshpalette()
+{
+ //relevant for alterable palettes, such as amiga or cpc
+ if(g_palsteps==0)return;
+  for(int i=0;i<g_maxcolors;i++){
+    makecolor(i,int(g_map[256+i*3]),int(g_map[256+i*3+1]),int(g_map[256+i*3+2]));
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/draw_outputs.pde	Tue Jul 03 20:56:55 2018 +0300
@@ -0,0 +1,966 @@
+// Collect all that "writes" the virtual image in some way or other
+// plus other active manipulations
+
+void createpoint(int x,int y,int mo)
+{
+  if(mo==LEFT)makepoint(x,y);
+  if(mo==RIGHT)clearpoint(x,y);
+}
+
+void doborx(int xf,int yf,int xt,int yt)
+{
+  //rectangle for brush drawing
+  for(int ii=xf;ii<=xt;ii++){
+    for(int jj=yf;jj<=yt;jj++){
+      createpoint(ii,jj,g_button);
+    }
+  }
+}
+
+void docircx(int xf,int yf,int hh,int vv)
+{
+  //circle for brush drawing
+  float prop,fh,fv;
+  fh=hh;fv=vv;
+  if(vv>0){prop=fh/fv;}else{prop=1;}
+  hh++;
+  for(int ii=-hh;ii<=hh;ii++){
+    for(int jj=-vv;jj<=vv;jj++){
+      if(dist(xf+ii,yf+jj*prop,xf,yf)<=hh-1){
+        createpoint(xf+ii,yf+jj,g_button);
+      }
+    }
+  }
+}
+
+void craft(int x,int y, int c)
+{
+  //foundational brush control
+  //whether hard coded, circular or bitmap brush
+  int calc,mb;
+  int a1,b1,s1,x0,y0,midx,midy,molox,passes,ofx,ofy;
+  ofx=x;ofy=y;mb=g_button;
+  if(g_btype==1){
+    if(g_bsize<4){
+      //some hardcoded brushes
+          switch(g_bsize)
+          {
+          case 0:
+            doborx(ofx,ofy,ofx+1,ofy+1);
+          break;
+          case 1:
+            if(g_data['c']==1||g_shift==true){
+              ofx=ofx+1;ofy=ofy+1;
+            }
+            doborx(ofx-1,ofy-1,ofx+1,ofy+1);
+          break;
+          case 2:
+            if(g_data['c']==1||g_shift==true){
+              ofx=ofx+2;ofy=ofy+2;
+            }
+            doborx(ofx-2,ofy-2,ofx+1,ofy+1);
+          break;
+          case 3:
+          if(g_data['c']==1||g_shift==true){
+              ofx=ofx+3;ofy=ofy+3;
+            }
+            doborx(ofx-3,ofy-3,ofx+4,ofy+4);
+          break;
+          }
+    }
+    else
+    {  //larger size brushes
+      calc=g_bsize-3;
+      calc=calc*calc;calc=calc+4;
+      doborx(x-calc,y-calc,x+calc,y+calc);
+    }
+  return;
+  }
+
+  if(g_btype==9){ //bitmap brush
+    passes=2;
+    molox=1;
+    int tempox,tempoy,tempx,tempy,moloy;
+    moloy=1;
+    tempox=g_bsourcex;tempoy=g_bsourcey;
+    tempx=g_bsourcex2;tempy=g_bsourcey2;
+    if(g_data['t']==1){
+        if(tempx>g_bsourcex+16)tempx=g_bsourcex+16;
+        if(tempy>g_bsourcey+16)tempy=g_bsourcey+16;
+    }
+    midx=(g_bsourcex2-g_bsourcex)/2;
+    midy=(g_bsourcey2-g_bsourcey)/2;
+    if(g_data['c']==1||g_shift==true){
+      if(g_data['q']==1){
+        midy=midy/g_gridx;midy=midy*g_gridx;
+        midx=midx/g_gridx;midx=midx*g_gridx;
+      }
+    }
+    int orient;
+    orient=g_data['x']*100+g_data['y']*10+g_data['q'];
+    if(g_multic==1||g_hzoomer==2){x=x/2;x=x*2;molox=2;passes=1;}
+
+    for(int pp=1;pp<=passes;pp++){
+      for(int yy=tempoy;yy<=tempy;yy=yy+moloy){
+        for(int xx=tempox;xx<=tempx;xx=xx+molox){
+          s1=int(g_brush[1024+xx+yy*X]);
+          if(g_multic==0)s1=getabsa(xx,yy,1);
+          if(g_multic>0)s1=getmultibrush(xx,yy);
+          if(s1!=g_backg){ 
+            x0=x+xx-g_bsourcex;
+            y0=y+yy-g_bsourcey;
+    
+            if(g_data['q']==1){
+              x0=x-(yy-g_bsourcey2);
+              y0=y+(xx-g_bsourcex);
+              x0=x0+midx;x0=x0-midy;
+              y0=y0+midy;y0=y0-midx;
+            }  
+    
+            if(g_data['x']==1){
+              x0=x0-(x+midx);
+              x0=-x0;
+              x0=x0+(x+midx);  
+            }
+
+            if(g_data['y']==1){
+              y0=y0-(y+midy);
+              y0=-y0;
+              y0=y0+(y+midy);
+            }
+          
+           if(g_data['c']==1||g_shift){
+              if(orient==10)y0=y0+1;
+              if(orient==11)y0=y0+g_gridy-molox;
+              if(orient==100)x0=x0+1;
+              if(orient==101)x0=x0+g_gridx-1;
+              if(orient==110){x0=x0+1;y0=y0+1;}
+              if(orient==111){x0=x0+g_gridx-1;y0=y0+g_gridy-molox;}
+           }
+            
+           if(mb==LEFT){  
+             if(g_multic>0){
+                g_farge=s1;
+                if(g_data['p']==1)g_farge=g_ofarge;
+                if(g_multic==1||g_hzoomer==2){
+                  if(g_data['q']==0)makepoint(x0,y0);
+                  if(g_data['q']==1){
+                    makepoint(x0-x+x0,y+(y0-y));
+                    makepoint(x0-x+x0,y+(y0-y)+1);
+                  }
+                }else{    
+               makepoint(x0,y0);
+               }              
+              }else
+              {
+                g_farge=s1;
+                if(zxcolor(g_farge)!=zxcolor(g_backg)){
+                  if(g_data['p']==1)g_farge=g_ofarge;
+                  makepoint(x0,y0);
+                }
+              }
+            }
+  
+            if(mb==RIGHT){
+
+              if(g_multic>0){
+                if(g_multic==1||g_hzoomer==2){
+                  if(g_data['q']==0)clearpoint(x0,y0);
+                  if(g_data['q']==1){
+                    clearpoint(x0-x+x0,y+(y0-y));
+                    clearpoint(x0-x+x0,y+(y0-y)+1);
+                  }
+                }else{              
+               clearpoint(x0,y0);}
+              }else
+              {
+               clearpoint(x0,y0);
+              }
+             }
+            }
+           }
+          }
+         }
+    g_farge=g_ofarge;
+    return;
+  }
+
+  if(g_bsize<4){
+    switch(g_bsize)
+    {
+    case 0:
+      createpoint(x,y,g_button);
+    break;
+    case 1:
+      createpoint(x,y+1,g_button);createpoint(x,y-1,g_button);
+      createpoint(x,y,g_button);
+      createpoint(x-1,y,g_button);createpoint(x+1,y,g_button);
+    break;
+    case 2:        
+      doborx(x-1,y-2,x+1,y+2);doborx(x-2,y-1,x+2,y+1);       
+    break;
+    case 3:
+      doborx(x-3,y-1,x+3,y+1);
+      doborx(x-1,y-3,x+1,y+3);
+      doborx(x-2,y-2,x+2,y+2);
+    break;
+    }
+  }else
+  {
+    calc=g_bsize-3;
+    calc=calc*calc;calc=calc+4;
+    docircx(x,y,calc,calc);
+  }
+}
+
+void doline(int xfrom,int yfrom,int xto,int yto,int prevent)
+{
+  //bresenham almost exactly from Wikipedia
+  int swap,molox,pex,pey;
+  boolean steep;
+  molox=1;
+  //multicolor 160 pixel reso
+  if(g_multic==1||g_hzoomer==2){xfrom=xfrom/2;xfrom=xfrom*2;xto=xto/2;xto=xto*2;}
+
+  craft(xfrom,yfrom,0);
+  pex=xfrom;pey=yfrom;
+  
+  if(prevent==0)craft(xto,yto,0);  
+  
+  if(g_multic==1||g_hzoomer==2){xfrom=xfrom/2;xto=xto/2;molox=2;}
+  
+  int x0=xfrom;
+  int y0=yfrom;
+  int x1=xto;
+  int y1=yto;
+  
+  steep=abs(y1 - y0) > abs(x1 - x0);
+
+  if(steep){
+    swap=x0;x0=y0;y0=swap;
+    swap=x1;x1=y1;y1=swap;
+  }  
+
+  float deltax = abs(x1 - x0);
+  float deltay = abs(y1 - y0);
+  float error = deltax/2;
+  int ystep;
+   
+  if(deltax==0)return;
+  
+  int y = y0;
+  int inc;
+   
+  if(x0<x1){inc=1;}else{inc=-1;}
+  if(y0<y1){ystep=1;}else{ystep=-1;}
+  int x;
+  x=x0;
+  while(x!=x1){
+    if(steep){
+      if(y*molox!=pex||x!=pey){
+        craft(y*molox,x,0);
+        pex=y*molox;pey=x;
+      }
+    }
+    else
+    {
+      if(x*molox!=pex||y!=pey){
+        craft(x*molox,y,0);
+        pex=x*molox;pey=y;
+      }
+    }
+     
+    error=error-deltay;
+    if(error<0){
+      y=y+ystep;
+      error=error+deltax;  
+    }
+    x=x+inc;
+  }
+}
+
+void docircle_new(int x1,int y1,int x2,int y2)
+{
+  int hh,vv;
+  float prop;
+  int xf,yf;
+  float fh,fv;
+  if(x2<x1)x2=x1-(x2-x1);
+  if(y2<y1)y2=y1-(y2-y1);
+  xf=x1;yf=y1;
+  hh=x2-x1;vv=y2-y1;
+  fh=hh;fv=vv;
+  if(vv>0){
+    prop=fh/fv;}else{prop=1;}
+    hh++;
+    for(int ii=-hh;ii<=hh;ii++){
+      for(int jj=-vv;jj<=vv;jj++){
+        if(dist(xf+ii,yf+jj*prop,xf,yf)<=hh-1){
+          createpoint(xf+ii,yf+jj,g_button);
+        }
+      }
+    }
+}
+  
+void docircle(int x1,int y1,int x2,int y2)
+{
+  float dds,a,t,sx,sy,gear1,gear2,x0,y0;
+  int kimea,prex,prey;
+  dds=dist(x1,y1,x2,y2);
+  gear1=int(dds);
+  if(gear1<=12)gear1=12;
+  if(gear1>120)gear1=120;
+  gear2=int(gear1*2);
+
+  if(x2<x1)x2=x1-(x2-x1);
+  if(y2<y1)y2=y1-(y2-y1);
+  
+  if(g_data['t']==1&&x2>x1+15)x2=x1+16;
+  if(g_data['t']==1&&y2>y1+15)y2=y1+16; 
+  
+  prex=0;prey=0;
+  kimea=y1-(y2-y1);
+  
+  if(g_data['f']==1&&g_btype!=9){
+    if(g_multic==1&&g_data['d']==0){
+      g_farge=g_map[1];
+      docircx(x1,y1,abs(x2-int(x1)),abs(y2-int(y1)));
+      g_farge=g_ofarge;     
+    }
+    docircx(x1,y1,abs(x2-int(x1)),abs(y2-int(y1)));
+  }
+     
+  for(t=0;t<=(gear2);t++){
+   a=t/(gear1)*PI;
+   sx=(x2-x1)*sin(a);sy=(y1-y2)*cos(a);
+   if(t>0)doline(prex,prey,x1+int(sx),y1+int(sy),1);  
+   prex=(x1+int(sx));prey=(y1+int(sy)); 
+  }
+}
+
+void rectangle(int x1,int y1,int x2,int y2)
+{
+  int x0,y0,molox;
+  int yt,xt;
+  int xf,yf;
+  xf=x1/8;xf=xf*8;xt=x2/8;xt=xt*8;
+  yf=y1/8;yf=yf*8;yt=y2/8;yt=yt*8;yt=yt+7;xt=xt+6;
+  molox=1;
+  if(g_multic==1||g_hzoomer==2)molox=2;
+  if(x2<x1){x0=x2;x2=x1;x1=x0;}
+  if(y2<y1){y0=y2;y2=y1;y1=y0;}
+  
+  if(g_data['t']==1&&x2>x1+15)x2=x1+16;
+  if(g_data['t']==1&&y2>y1+15)y2=y1+16;  
+  
+  if(g_btype!=9){
+    if(g_data['c']==1||g_shift){
+      if(x2>x1)x2--;
+      if(y2>y1)y2--;
+    }
+  }
+
+  if(g_data['f']==1&&g_btype!=9){
+    if(g_multic==1&&g_data['d']==0){
+       g_farge=g_map[1];
+       for(int y=y1;y<=y2;y++){
+        for(int x=x1;x<=x2;x=x+molox){
+          if(x>=xf&&y>=yf&&x<=xt&&y<=yt){
+           makepoint(x,y);
+          }
+        }
+      }
+    }
+    g_farge=g_ofarge;
+    if(g_button==RIGHT)g_farge=g_backg;
+    for(int y=y1;y<=y2;y++){
+      for(int x=x1;x<=x2;x=x+molox){
+        makepoint(x,y);
+      }
+    }
+  }
+  if(g_data['f']==0||g_btype==9){
+    if(g_data['c']==1&&g_btype==1){
+      if(x2>x1){
+        if(g_bsize==0)x2--;
+        if(g_bsize==1)x2=x2-2;
+        if(g_bsize==2)x2=x2-3;
+        if(g_bsize==3)x2++;
+      }
+      if(y2>y1){
+        if(g_bsize==0)y2--;
+        if(g_bsize==1)y2=y2-2;
+        if(g_bsize==2)y2=y2-3;
+        if(g_bsize==3)y2++;
+      }      
+    }
+    doline(x1,y1,x2,y1,0);
+    doline(x1,y1,x1,y2,0);
+    doline(x1,y2,x2,y2,0);
+    doline(x2,y2,x2,y1,0);
+  }
+  g_farge=g_ofarge;
+}
+
+void makepoint(int xx,int yy)
+{
+  //central pixelmaking function
+  //has become very messy but what are you gonna do
+    int uses[]=new int[8];
+    int fars[]=new int[8];
+    int mirrix=0;
+    int mirriy=0;
+    int tiler=0;
+    int ignore=0;
+    int fari;
+      
+  //for the X/Y mirrors & tiler, the function calls itself with x+10000 or y+10000
+  //resolved here
+    if(xx>=20000){
+      xx=xx-20000;mirrix=0;mirriy=0;tiler=1;
+    }
+    if(xx>=10000){xx=xx-10000;mirrix=1;mirriy=1;}
+    if(yy>=10000){yy=yy-10000;mirriy=1;mirrix=1;}
+    if(xx<0)return;
+    if(yy<0)return;
+    if(xx>=X)return;
+    if(yy>=Y)return;
+    
+    // adaptive color unless with floodfill (which has its own system)
+    if(int(g_map[12])!=5){
+      if(g_multic==2)skaveri(xx,yy,g_farge,0);
+      
+      if(g_multic!=2){
+      if(g_data['b']==0){ 
+         if(g_multic==1){
+           mkaveri(xx,yy,g_farge,0);
+         }else{ 
+           kaveri(xx,yy,g_farge,0);
+         }
+       }
+       else
+       {
+         //old iq
+         kaveri_iq(xx,yy,g_farge,0);
+       }
+      }
+    }
+    
+    if(g_multic==1||g_hzoomer==2){
+      xx=xx/2;xx=xx*2;
+    }
+
+    if(g_data['r']==1){//simple raster
+      if(get_raster(xx,yy)==0)ignore=1;
+    }
+  
+  if(g_data['R']==1){//user defined raster
+    if(g_bsourcex2>g_bsourcex&&g_bsourcey2>g_bsourcey){
+
+    int x0=xx/((g_bsourcex2+1)-g_bsourcex);
+    int y0=yy/((g_bsourcey2+1)-g_bsourcey);
+    int x1=xx-x0*((g_bsourcex2+1)-g_bsourcex);
+    int y1=yy-y0*((g_bsourcey2+1)-g_bsourcey);
+    int xr=g_bsourcex+x1;
+    int yr=g_bsourcey+y1;
+    if(g_multic==1||g_hzoomer==2){
+       x0=xx/((g_bsourcex2+2)-g_bsourcex);
+       y0=yy/((g_bsourcey2+1)-g_bsourcey);
+       x1=xx-x0*((g_bsourcex2+2)-g_bsourcex);x1=x1/2;x1=x1*2;
+       y1=yy-y0*((g_bsourcey2+1)-g_bsourcey);
+       xr=g_bsourcex+x1;xr=xr/2;xr=xr*2;
+       yr=g_bsourcey+y1;    
+       if(getmultic(xr,yr,1)==g_backg)ignore=1;
+    }else{
+       if(getabsa(xr,yr,1)==g_backg)ignore=1;
+    }
+//    if(g_brush[1024+xr+yr*X]==0){ignore=1;}
+    }
+  }
+  
+ int xc,yc;
+ 
+ if(ignore==0&&g_data['d']==1&&g_attrimode<=1){
+   int aba,baba,ii,jj,miny,maxy,ojox,ojoy;
+    aba=getattra(xx,yy,0);
+    baba=getattra(xx,yy,1);
+    if(g_multic==0){
+       ojox=xx/8;ojoy=yy/8;
+       ojox=ojox*8;ojoy=ojoy*8;
+       miny=(yy-ojoy);maxy=miny;
+       if(g_attrimode==1){miny=0;maxy=7;}
+       if(baba==g_backg)simplepaint(xx,yy,1,g_farge);
+       if(aba==g_backg)simplepaint(xx,yy,0,g_farge);
+       ignore=1;
+       if(g_farge==baba&&g_farge==aba){
+          for(jj=miny;jj<=maxy;jj++){
+             for(ii=0;ii<8;ii++){
+               g_map[1024+ojox+ojoy*X+ii+jj*X]=0;
+             }
+           }
+         }
+    }
+    else
+    {
+      if(aba==g_backg){
+        ignore=0;}else{ignore=1;}
+    }
+    xc=xx/8;
+    yc=yy/8;
+    g_redo[xc+yc*MX]=byte(0);//block update
+    g_remdo[xc+yc*MX]=byte(1);//block update
+ }
+ 
+ if(ignore==0){
+   xc=xx/8;yc=yy/8;
+   g_redo[xc+yc*MX]=byte(0);//block update
+   g_remdo[xc+yc*MX]=byte(1);//block update    
+
+   switch (g_multic)
+   {
+   case 0://1-bit + attribute i.e. spectrum
+     fari=g_farge;
+     if(machine==MSX&&fari==int(g_map[1]))fari=0;
+     if(g_britemode==1&&fari==8)fari=0;
+
+     if(getattra(xx,yy,1)==0&&fari==g_map[1]){
+       g_map[1024+xx+yy*X]=byte(0); 
+     }else
+     {
+     if(getattra(xx,yy,1)==fari){
+        g_map[1024+xx+yy*X]=byte(0);
+     }else
+     {
+       int ojox=xx/8;
+       int ojoy=yy/8;
+       int mac,macpre,maxos;
+       int maxoy,miny,maxy;
+       ojox=ojox*8;ojoy=ojoy*8;mac=0;macpre=0;
+       miny=0;maxy=7;maxos=64;
+       if(g_attrimode==0){miny=(yy-ojoy);maxy=miny;maxos=8;}//MSX
+       for(int j=miny;j<=maxy;j++){
+         for(int i=0;i<8;i++){
+           if(g_map[1024+ojox+ojoy*X+j*X]==1)macpre++;
+         }
+       }
+       g_map[1024+xx+yy*X]=byte(1);
+       for(int j=miny;j<=maxy;j++){
+         for(int i=0;i<8;i++){
+           if(g_map[1024+ojox+ojoy*X+i+j*X]==1)mac++;
+         }
+       }
+       if(mac==maxos){
+         for(int j=miny;j<=maxy;j++){
+           int vad=1024+ojox+(ojoy+j)*X;
+           for(int i=0;i<8;i++){
+             g_map[vad]=0;vad++;
+           }
+         }
+         simplepaint(xx,yy,1,fari);   
+       }else{
+         simplepaint(xx,yy,0,fari);
+       }
+     }
+     }
+ break;
+ case 1: //c64 style zoomed multicolour
+    
+      //foreg
+      int looks,skippo;
+      byte bit1,bit2,valu1,valu2;
+      int metax,metay,mex,mey,metamax;
+      fari=g_farge;
+      int zeroc=int(g_map[1]);int zeroc2=int(g_map[2]);
+      boolean cut=false;
+      if(fari==zeroc){ //shortcut
+           g_map[1024+xx+yy*X]=byte(0);g_map[1024+xx+yy*X+1]=byte(0);
+           cut=true;
+      }
+      if(machine==PLUS4M&&fari==zeroc2){ //shortcut
+           g_map[1024+xx+yy*X]=byte(1);g_map[1024+xx+yy*X+1]=byte(1);
+           cut=true;
+      }
+      if(cut){
+           // X Y mirrors      
+           if(g_data['t']==1){
+             if(tiler==0){
+               int ex=X/g_gridx;
+               int ey=Y/g_gridy;
+               for(int tilx=-ex;tilx<=ex;tilx++){
+                 for(int tily=-ey;tily<=ey;tily++){
+                     makepoint(20000+xx+(X/ex)*tilx,yy+(Y/ey)*tily);
+                 }
+               }
+             }
+             return;
+           }           
+           if(g_data['X']==1&&mirrix==0)makepoint(10000+(X-1)-xx,yy);
+           if(g_data['Y']==1&&mirriy==0)makepoint(xx,10000+(Y-1)-yy);
+           if(g_data['X']==1&&g_data['Y']==1){if(mirrix==0){makepoint(10000+(X-1)-xx,10000+(Y-1)-yy);}}
+           return;
+      }     
+      
+      uses[0]=0;uses[1]=0;uses[2]=0;uses[3]=0;
+      fars[0]=zeroc;fars[1]=zeroc;fars[2]=zeroc;fars[3]=zeroc;
+      mex=xx/8;mey=yy/8;looks=65536+mex+mey*MX;
+      mex=mex*8;mey=mey*8;
+      int saps=1024+mex+mey*X;
+       
+      for(metay=0;metay<=7;metay++){
+       for(metax=0;metax<=3;metax++){
+         int pars=g_map[saps]+g_map[saps+1]*2;
+         uses[pars]=1;
+         if(pars==0)fars[0]=zeroc;
+         if(pars==1)fars[1]=int(g_map[looks]);
+         if(pars==2)fars[2]=int(g_map[looks+1000]);
+         if(pars==3){
+           if(machine==C64M)fars[3]=int(g_map[looks+2000]);
+           if(machine==PLUS4M)fars[3]=zeroc2;
+         }   
+         saps=saps+2;    
+       }
+       saps=saps-8+X;
+      }
+
+      bit1=0;bit2=0;skippo=0;
+      
+      // mega-escape, if it's not possible to draw at all don't bother
+      if(uses[0]==1&&uses[1]==1&&uses[2]==1&&uses[3]==1){
+        if(fari!=fars[0]&&fari!=fars[1]&&fari!=fars[2]&&fari!=fars[3])skippo=100;
+      }
+ 
+      if(skippo==0){
+        int okay=0;
+        metamax=3;
+        if(machine==PLUS4M)metamax=2;
+        
+        // if the color is already in the 4x8 area?
+        
+        for(metay=0;metay<=metamax;metay++){
+          if(uses[metay]==1){
+              if(fars[metay]==fari){
+                if(metay==1){bit1=1;bit2=0;g_map[looks]=byte(fari);}
+                if(metay==2){bit1=0;bit2=1;g_map[looks+1000]=byte(fari);}
+                if(metay==3){
+                  bit1=1;bit2=1;
+                  if(machine==C64M)g_map[looks+2000]=byte(fari);
+                  if(machine==PLUS4M)g_map[looks+2000]=byte(zeroc2);
+                }
+                g_map[1024+xx+yy*X]=bit1;
+                g_map[1024+xx+yy*X+1]=bit2;
+                okay=1;       
+            }
+          }
+        }
+    
+        //if the color is not in the 4x8 area
+        
+        if(okay==0){
+          for(metay=1;metay<=metamax;metay++){
+            if(uses[metay]==0){
+               uses[metay]=1;
+               if(metay==1){bit1=1;bit2=0;g_map[looks]=byte(fari);uses[2]=1;}
+               if(metay==2){bit1=0;bit2=1;g_map[looks+1000]=byte(fari);uses[3]=1;}
+               if(metay==3){bit1=1;bit2=1;
+                 if(machine==C64M)g_map[looks+2000]=byte(fari);
+                 if(machine==PLUS4M)g_map[looks+2000]=byte(zeroc2);
+               }   
+               g_map[1024+xx+yy*X]=bit1;
+               g_map[1024+xx+yy*X+1]=bit2;    
+            }
+          }  
+        }
+    
+    }//skippo0
+    
+ break;
+ 
+ case 2: // VGA style i.e. Amiga, CPC
+   fari=g_farge;
+      
+   if(g_data['d']==1){
+       if(g_map[1024+xx+yy*X]==byte(g_backg)){
+         g_map[1024+xx+yy*X]=byte(g_farge);
+         if(g_hzoomer==2)g_map[1024+xx+yy*X+1]=byte(g_farge);
+       }
+     }
+     else
+     {
+       g_map[1024+xx+yy*X]=byte(g_farge);
+       if(g_hzoomer==2)g_map[1024+xx+yy*X+1]=byte(g_farge);
+     }
+   break;
+ }
+ }
+ 
+ // end ignore
+ 
+ // X Y mirrors & tiler
+ 
+ if(g_data['t']==1){
+   if(tiler==0){
+     int ex=X/g_gridx;
+     int ey=Y/g_gridy;
+     for(int tilx=-(ex);tilx<=ex;tilx++){
+       for(int tily=-(ey);tily<=ey;tily++){
+           makepoint(20000+xx+(X/ex)*tilx,yy+(Y/ey)*tily);
+         }
+       }
+   }
+   return;
+ }
+ if(g_data['X']==1&&mirrix==0)makepoint(10000+(X-1)-xx,yy);
+ if(g_data['Y']==1&&mirriy==0)makepoint(xx,10000+(Y-1)-yy); 
+ if(g_data['X']==1&&g_data['Y']==1){if(mirrix==0){makepoint(10000+(X-1)-xx,10000+(Y-1)-yy);}}
+}
+
+void clearpoint(int xx,int yy)
+{
+  if(g_multic==2){
+    g_farge=g_backg;makepoint(xx,yy);g_farge=g_ofarge;return;
+  }
+  if(g_multic==1){
+    xx=xx/2;xx=xx*2;
+  }
+  g_farge=g_backg;makepoint(xx,yy);g_farge=g_ofarge;return;
+}
+
+
+void absolute_clearpoint(int xx,int yy)
+{
+  int mirrix=0;
+  int mirriy=0;
+  int ignore=0;
+  if(xx>=10000){xx=xx-10000;mirrix=1;mirriy=1;}
+  if(yy>=10000){yy=yy-10000;mirriy=1;mirrix=1;}
+  if(xx<0)return;
+  if(yy<0)return;
+  if(xx>=X)return;
+  if(yy>=Y)return;
+  
+  if(g_multic==2&&g_hzoomer!=2){
+    g_farge=g_backg;makepoint(xx,yy);g_farge=g_ofarge;return;
+  }
+  if(g_multic==1||g_hzoomer==2){
+    xx=xx/2;xx=xx*2;
+  }
+  if(g_data['b']==1)return;
+  if(g_data['r']==1){//raster
+    if(get_raster(xx,yy)==0)ignore=1;
+  }
+  
+  if(g_data['R']==1){ //user defined raster
+    if(g_bsourcex2>g_bsourcex&&g_bsourcey2>g_bsourcey){
+      int x0=xx/((g_bsourcex2+1)-g_bsourcex);
+      int y0=yy/((g_bsourcey2+1)-g_bsourcey);
+      int x1=xx-x0*((g_bsourcex2+1)-g_bsourcex);
+      int y1=yy-y0*((g_bsourcey2+1)-g_bsourcey);
+      int xr=g_bsourcex+x1;
+      int yr=g_bsourcey+y1;
+      if(g_brush[1024+xr+yr*X]==0)ignore=1;
+    }
+  }
+  
+  if(ignore==0){
+    g_map[1024+xx+yy*X]=byte(0);
+    if(g_multic==1||g_hzoomer==2)g_map[1024+xx+yy*X+1]=byte(0);
+    int xc=xx/8;
+    int yc=yy/8;
+    g_redo[xc+yc*MX]=byte(0);//block update
+    g_remdo[xc+yc*MX]=byte(1);//block update
+  }
+  if(g_data['X']==1&&mirrix==0)clearpoint(10000+(X-1)-xx,yy);
+  if(g_data['Y']==1&&mirriy==0)clearpoint(xx,10000+(Y-1)-yy);
+  if(g_data['X']==1&&g_data['Y']==1){
+    if(mirrix==0)clearpoint(10000+(X-1)-xx,10000+(Y-1)-yy);
+  }
+}
+
+void simplepaint(int xx,int yy,int mode,int attr)
+{
+  int ad,swad,j,miny,maxy,ojyx;
+  xx=xx/8;
+  ojyx=yy/8;ojyx=ojyx*8;
+  ad=0;swad=0;
+  miny=yy-ojyx;maxy=miny;
+  if(g_attrimode==1){
+    miny=0;maxy=7;
+  }
+  for(j=miny;j<=maxy;j++){
+     if(mode==0){ad=65536+xx+(ojyx+j)*MX;swad=65536+xx+(ojyx+j)*MX+(MX*MY)*8;}
+     if(mode==1){ad=65536+xx+(ojyx+j)*MX+(MX*MY)*8;swad=65536+xx+(ojyx+j)*MX;}
+     if(g_britemode==1){
+       if(attr==8)attr=0;
+       if(attr>0){
+         if(attr>=8&&g_map[swad]<=7)g_map[swad]=byte(g_map[swad]+8);
+         if(attr<=7&&g_map[swad]>=8)g_map[swad]=byte(g_map[swad]-8);
+       }
+     }
+     g_map[ad]=byte(attr);
+  }
+}
+
+void do_tool(int x,int y,int mb)
+{
+  int tt,ox,oy,psizex,psizey;
+  tt=tool();
+  psizex=g_magpix[magmode()];
+  psizey=g_magpiy[magmode()];
+  
+  //handles different tool behavior
+  
+  if(g_data['m']==0&&g_data['M']==0){
+    if(g_uizoom==1){x=x/2;y=y/2;}
+    if(g_uizoom==2){x=x/3;y=y/3;}
+    if(g_uizoom==3){x=x/4;y=y/4;}
+  }
+  
+  if(g_data['m']==1||g_data['M']==1){
+      x=x/psizex;y=y/psizey;
+      x=x+g_ofx*8;
+      y=y+g_ofy*8;
+  }
+
+  ox=x;oy=y;g_storedcoordx=x;g_storedcoordy=y;
+ 
+  int midx=0;
+  int midy=0;
+  //brush handle mid point
+  //some tools are exempted
+  if(g_btype==9&&tool()!=4&&tool()!=0&&mb!=255){
+      midx=(g_bsourcex2-g_bsourcex)/2;
+      midy=(g_bsourcey2-g_bsourcey)/2;
+      x=x-midx;y=y-midy;
+  } 
+  if(g_data['c']==1||g_shift){
+      x=x/g_gridx;x=x*g_gridx;
+      y=y/g_gridy;y=y*g_gridy;
+  }
+  
+  if(g_multic==1||g_hzoomer==2){x=x/2;x=x*2;ox=ox/2;ox=ox*2;}
+
+  if(mb==254){//block picker
+      switcher(2);g_data['n']=0;g_data['x']=0;g_data['y']=0;g_data['q']=0;g_data['z']=0;
+      x=ox/g_gridx;x=x*g_gridx;y=oy/g_gridy;y=y*g_gridy;
+      g_bsourcex=x;g_bsourcey=y;
+      g_bsourcex2=x+g_gridx-1;g_bsourcey2=y+g_gridy-1;
+      //set_tool(1);
+      g_btype=9;
+      return;
+  }
+  
+  if(mb==255){ // color picker
+    if(g_multic==2){
+        if(g_hzoomer==2){ox=ox/2;ox=ox*2;}
+        selectcolor(0,getmultic(ox,oy,0));return;
+    }
+    selectcolor(0,getabsa(ox,oy,0));
+    if(g_multic==1||g_hzoomer==2){
+      ox=ox/2;ox=ox*2;
+      selectcolor(0,getattra(ox,oy,0));
+    }
+    g_ofarge=g_farge;
+    if(g_btype==9)g_data['p']=1;
+    g_realfront=byte(g_farge);
+    return;
+  }
+  
+  if(x>=0&&y>=0&&x<X&&y<Y&&g_mx<width-g_hedge&&g_my<height-g_vedge)help(1000+x+y*X);
+  if(g_phase>0)help(1000+x+y*X);
+  
+  if(tt==1)craft(x,y,0); //pixeller
+  
+  if(tt==2){ //spraycan
+    //if(random(100)<50){fixed_raster_command('x');}
+    //if(random(100)<50){fixed_raster_command('y');}    
+    for(int i=0;i<=12;i++){
+      int rx=x-10+int(random((10)*2));
+      int ry=y-10+int(random((10)*2));
+      if(mb==LEFT){
+        if(dist(x,y,rx,ry)<10)craft(rx,ry,0);
+      }
+      else
+      {
+        if(dist(x,y,rx,ry)<10)craft(rx,ry,0);
+      }     
+    }
+  }
+  
+  if(tt==3){//cont line
+    if(g_phase==0){
+      g_prex=x;g_prey=y;craft(x,y,0);
+    }
+    doline(x,y,g_prex,g_prey,0);
+    g_prex=x;g_prey=y;
+  }  
+   
+  if(tt==5){//floodfill
+    if(g_klikkeri==0){
+      g_klikkeri=1;
+      storeparameters();
+      g_data['X']=0;g_data['Y']=0;
+      g_data['c']=0;g_data['t']=0;
+      if(ox>=0&&ox<X&&oy>=0&oy<Y){
+        store_undo();// exceptional!
+        if(g_multic!=0){floodfillmc(ox,oy,mb);}
+          else
+          {floodfill_iq(ox,oy,mb);}
+      }
+      restoreparameters();
+    }
+  }
+  
+  if(tt==6||tt==7||tt==8){//line,circle,rect
+    if(g_phase==0){g_rx=x;g_ry=y;g_rx2=x;g_ry2=y;g_rubbermode=0;}
+    if(g_phase==1){g_rx2=x;g_ry2=y;}
+  }
+
+  if(tt==0){ // magnifier graphic tool
+    g_data['m']=1;
+    g_rx=x-(magx()/2)*8;g_orx=x;
+    g_ry=y-(magy()/2)*8;g_ory=y;
+    g_rx2=x+(magx()/2+odd(magx()))*8;
+    g_ry2=y+(magy()/2+odd(magy()))*8;
+    g_data['m']=0;
+    g_rubbermode=1;
+    if(g_phase==1){
+       g_rubbermode=0;g_data['m']=1;set_tool(g_prevtool);g_phase=0;
+       g_ofx=x/8-magx()/2;g_ofy=y/8-magy()/2;
+       refresh();g_repanel=-2;
+    }
+  }
+  
+  if(tt==4){ //brush grabber grab brush
+    if(g_phase==0){
+       g_rx=x;g_orx=x;
+       g_ry=y;g_ory=y;
+       g_rx2=x;g_ry2=y;
+    }
+  
+    if(g_phase==1){
+      g_rx2=x;g_rx=g_orx;
+      g_ry2=y;g_ry=g_ory;
+      if(x<g_orx){g_rx2=g_orx;g_rx=x;}
+      if(y<g_ory){g_ry2=g_ory;g_ry=y;}
+      if(g_data['c']==1||g_shift){
+        g_rx2--;g_ry2--;
+        if(g_multic==1||g_hzoomer==2)g_rx2--;
+      }
+    }
+    g_rubbermode=1;
+  }
+  
+  if(tt==0||tt==4){
+    if(g_rubbermode==1){
+      for(int xx=g_rx;xx<=g_rx2+2;xx++){
+        updatepoint(xx,g_ry);
+        updatepoint(xx,g_ry2);
+      }
+      for(int yy=g_ry;yy<=g_ry2;yy++){
+        updatepoint(g_rx,yy);
+        updatepoint(g_rx2,yy);
+      }
+    }
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/draw_smart.pde	Tue Jul 03 20:56:55 2018 +0300
@@ -0,0 +1,642 @@
+//all "intelligent" stuff, the color behavior
+//and flood fills
+
+void consistency()
+{
+  int xx,yy,ad,a,b,x0,y0,x2,y2;
+  int pat,mat,fad,bad,maxxy,mulu,ymax;
+  if(g_multic==1||g_multic==2)return;
+  maxxy=MY;mat=64;mulu=8;ymax=7;
+  if(g_attrimode==0){mat=8;mulu=1;maxxy=Y;ymax=0;}
+  for(yy=0;yy<MY;yy++){
+    for(xx=0;xx<MX;xx++){
+      a=getattra(xx*8,yy*mulu,0);
+      b=getattra(xx*8,yy*mulu,1);
+      if(a==b){
+          for(y0=0;y0<=ymax;y0++){
+             for(x0=0;x0<=7;x0++){
+               ad=1024+(xx*8)+(yy*X*mulu)+x0+y0*X;
+               g_map[ad]=byte(0);
+           }
+        }
+      }
+      pat=0;
+       for(y0=0;y0<=ymax;y0++){
+         for(x0=0;x0<=7;x0++){
+           ad=1024+(xx*8)+(yy*X*mulu)+x0+y0*X;
+           pat=pat+int(g_map[ad]);
+         }
+      }
+      if(pat==mat||pat==0){
+        for(y0=0;y0<=ymax;y0++){
+          fad=65536+xx+(yy*mulu+y0)*MX;  
+          bad=fad+(MX*MY*8);  
+          if(pat==0)g_map[fad]=g_map[bad];
+          if(pat==mat)g_map[bad]=g_map[fad];
+        }      
+      }
+   }
+  }
+}
+
+void floodfillmc(int xx,int yy,int mou)
+{
+  int x,y,molox,ax,ay,valid,okay,par,npar;
+  npar=0;par=0;molox=1;
+
+  for(x=0;x<X;x++){
+    for(y=0;y<Y;y++){
+      g_fillmap[1024+x+y*X]=0;
+    }
+  }
+  
+  if(g_multic==1||g_hzoomer==2)molox=2;
+  if(molox==2){xx=xx/2;xx=xx*2;}
+  if(mou==LEFT){par=g_farge;npar=getmultic(xx,yy,0);}
+  if(mou==RIGHT){par=g_backg;npar=getmultic(xx,yy,0);}
+
+  g_fillmap[1024+xx+yy*X]=byte(100);
+  if(molox==2)g_fillmap[1024+xx+yy*X+1]=byte(0);
+  valid=0;okay=0;
+  
+  while(okay==0){
+    
+    valid=0;
+
+    for(x=0;x<X;x=x+molox){
+      for(y=0;y<Y;y++){
+        ax=int(g_fillmap[1024+x+y*X]);
+        if(ax>=100&&ax<=199){
+        valid=1;   
+        if(y>0){
+         if(getmultic(x,y-1,0)==npar&&g_fillmap[1024+x+(y-1)*X]==0){g_fillmap[1024+x+(y-1)*X]=byte(100);
+           if(molox==2){g_fillmap[1024+x+(y-1)*X+1]=byte(0);}
+           valid=1;} 
+        }
+        if(x>0){
+         if(getmultic(x-molox,y,0)==npar&&g_fillmap[1024+(x-molox)+(y)*X]==0){g_fillmap[1024+(x-molox)+y*X]=byte(100);
+           if(molox==2){g_fillmap[1024+(x-molox)+y*X+1]=byte(0);}
+           valid=1;} 
+        }      
+        if(x<X-2){
+         if(getmultic(x+molox,y,0)==npar&&g_fillmap[1024+(x+molox)+(y)*X]==0){g_fillmap[1024+(x+molox)+y*X]=byte(100);
+           if(molox==2){g_fillmap[1024+(x+molox)+y*X+1]=byte(0);}
+           valid=1;} 
+        }          
+        if(y<Y-1){
+         if(getmultic(x,y+1,0)==npar&&g_fillmap[1024+x+(y+1)*X]==0){g_fillmap[1024+x+(y+1)*X]=byte(100);
+           if(molox==2){g_fillmap[1024+x+(y+1)*X+1]=byte(0);}
+           valid=1;} 
+        }      
+        
+         g_fillmap[1024+x+y*X]=byte(200);
+         if(molox==2)g_fillmap[1024+x+y*X+1]=byte(0);
+       }
+    }
+  }
+  
+  if(valid==0)okay=1;
+  
+  }  
+  
+  for(x=0;x<X;x=x+molox){
+    for(y=0;y<Y;y++){
+      if(int(g_fillmap[1024+x+y*X])>=200){g_farge=par;mkaveri(x,y,par,0);makepoint(x,y);g_farge=g_ofarge;}
+   }
+  }  
+}
+
+void transchar(int xx,int yy)
+{
+  int fad,bad,ad,pt,x0,y0;
+  int aa,bb,pp,ya,yb;
+    ya=0;yb=0;
+    xx=xx/8;
+    
+    if(g_attrimode==1){yy=yy/8;yy=yy*8;ya=0;yb=7;}//zx spec etc
+    if(g_attrimode==0){ya=0;yb=0;}//msx
+    
+    for(y0=ya;y0<=yb;y0++){
+       fad=65536+xx+(yy+y0)*MX;  
+       bad=fad+(MX*MY*8);   
+       aa=int(g_map[fad]);
+       bb=int(g_map[bad]);
+       g_map[fad]=byte(bb);
+       g_map[bad]=byte(aa);
+    }
+    for(y0=ya;y0<=yb;y0++){
+      for(x0=0;x0<=7;x0++){
+         ad=1024+(xx*8)+(yy*X)+x0+y0*X;
+         pp=int(g_map[ad]);
+         pp=1-pp;
+         g_map[ad]=byte(pp);
+     }
+    }
+}
+
+void prepare_char(int xx,int yy,int farbe)
+{
+
+  //changes the char foreg/backg into "favorable" relative to used color
+  //needed in floodfill
+  
+  int fad,bad,ad,pt,x0,y0;
+  int aa,bb,pp,ya,yb;
+  ya=0;yb=0;
+  
+  pt=int(g_map[1024+xx+yy*X]);
+  if(pt==0&&g_data['r']==0&&g_data['R']==0){
+    //println("trans char "+xx+"."+yy);
+    xx=xx/8;
+    if(g_attrimode==1){yy=yy/8;yy=yy*8;ya=0;yb=7;}//zx spec etc
+    if(g_attrimode==0){ya=0;yb=0;}//msx style
+    for(y0=ya;y0<=yb;y0++){
+      fad=65536+xx+(yy+y0)*MX;  
+      bad=fad+(MX*MY*8);   
+      aa=int(g_map[fad]);
+      bb=int(g_map[bad]);
+      g_map[fad]=byte(bb);
+      g_map[bad]=byte(aa);
+    }
+    for(y0=ya;y0<=yb;y0++){
+     for(x0=0;x0<=7;x0++){
+       ad=1024+(xx*8)+(yy*X)+x0+y0*X;
+       pp=int(g_map[ad]);
+       pp=1-pp;
+       g_map[ad]=byte(pp);
+     }
+    }
+  }
+}
+
+void floodfill_iq(int xx,int yy,int mou)
+{
+  int x,y,ax,ay,valid,okay,par,npar;
+  npar=0;par=0;
+  if(mou==LEFT)par=g_farge;
+  if(mou==RIGHT)par=g_backg;
+  if(getabsa(xx,yy,0)==par)return;
+  consistency();
+  npar=getabsa(xx,yy,0);
+  prepare_char(xx,yy,npar);
+  for(x=0;x<X;x++){
+    for(y=0;y<Y;y++){
+      g_fillmap[1024+x+y*X]=0;
+    }
+  }
+  g_fillmap[1024+xx+yy*X]=byte(100);
+  valid=0;okay=0;
+  while(okay==0){
+    valid=0;
+
+    for(x=0;x<X;x++){
+      for(y=0;y<Y;y++){
+        ax=int(g_fillmap[1024+x+y*X]);
+        if(ax==100){
+          valid=1;   
+          if(y>0){
+             if(getabsa(x,y-1,0)==npar&&g_fillmap[1024+x+(y-1)*X]==0){prepare_char(x,y-1,npar);g_fillmap[1024+x+(y-1)*X]=byte(100);valid=1;} 
+          }
+          if(x>0){
+             if(getabsa(x-1,y,0)==npar&&g_fillmap[1024+(x-1)+y*X]==0){prepare_char(x-1,y,npar);g_fillmap[1024+(x-1)+y*X]=byte(100);valid=1;} 
+          }      
+          if(x<X-1){
+             if(getabsa(x+1,y,0)==npar&&g_fillmap[1024+(x+1)+y*X]==0){prepare_char(x+1,y,npar);g_fillmap[1024+(x+1)+y*X]=byte(100);valid=1;} 
+          }          
+          if(y<Y-1){
+             if(getabsa(x,y+1,0)==npar&&g_fillmap[1024+x+(y+1)*X]==0){prepare_char(x,y+1,npar);g_fillmap[1024+x+(y+1)*X]=byte(100);valid=1;} 
+          }      
+          g_fillmap[1024+x+y*X]=byte(200);
+      }
+    }
+  }
+  if(valid==0)okay=1;
+  }
+  
+  for(x=0;x<X;x++){
+    for(y=0;y<Y;y++){
+      ax=int(g_fillmap[1024+x+y*X]);
+      if(ax==200){
+         g_farge=par;
+         makepoint(x,y);
+         g_fillmap[1024+x+y*X]=0;
+      } 
+    }
+  }
+  g_farge=g_ofarge; 
+}
+
+//adaptive color helper for low-attribute modes
+//reasons the background color for each char as you draw
+//=changed
+
+void fixattr(int x,int y,int foreg,int backg)
+{
+  int bad,cad,miny,maxy;
+  
+  if(g_britemode==1){
+    if(foreg==8||backg==8||foreg==0||backg==0)return;
+  }
+  
+  miny=y/8;miny=miny*8;maxy=y-miny;miny=maxy;
+  y=y/8;y=y*8;
+  if(g_attrimode==1){miny=0;maxy=7;}
+  
+  for(int i=miny;i<=maxy;i++){
+    bad=65536+(x/8)+(y+i)*MX;
+    cad=bad+MX*(MY*8);
+    if(foreg>=0){
+      g_map[bad]=byte(foreg);
+      if(foreg>=8&&g_map[cad]<8)g_map[cad]=byte(g_map[cad]+8);
+      if(foreg<8&&g_map[cad]>=8)g_map[cad]=byte(g_map[cad]-8);    
+    }
+    if(backg>=0){
+      g_map[cad]=byte(backg);
+      if(backg>=8&&g_map[bad]<8)g_map[bad]=byte(g_map[bad]+8);
+      if(backg<8&&g_map[bad]>=8)g_map[bad]=byte(g_map[bad]-8);        
+    }
+  }
+  updatepoint(x,y);
+}
+
+//multicolor color behavior
+//different behavior depending on whether color area already has max colors,
+//or if forcecolor is pressed.
+//bit different for C64 and PLUS4M
+
+void skaveri(int x,int y,int foreg,int backg)
+{
+  int mx=x/8;
+  int my=y/8;
+  if(g_control==false)return;
+  int cc=easygetcolor(x,y);
+  mx=mx*8;my=my*8;
+  for(int xx=0;xx<=7;xx++){
+    for(int yy=0;yy<=7;yy++){
+      if(easygetcolor(mx+xx,my+yy)==cc){
+        g_map[1024+mx+xx+(my+yy)*X]=byte(foreg);
+      }
+    }
+  }
+  updatepoint(x,y);
+}
+
+void mkaveri(int x,int y,int foreg,int backg)
+{
+  int mx=x/8;
+  int my=y/8;
+  int ad,bad,cad,dad,b0,b1;
+  int f0,f1,f2,f3,free1,free2,free3;
+  int f,order,numb,suffocatelimit;
+  int targetbit0,targetbit1;
+  order=0;numb=0;targetbit0=0;targetbit1=0;suffocatelimit=7;
+  
+  f=getmultic(x,y,0);
+  if(g_data['d']==1&&f!=g_backg)return;
+  
+  cad=65536+mx+(my*MX);
+  
+  f0=int(g_map[1]); 
+  f1=int(g_map[cad]);free1=1;        
+  f2=int(g_map[cad+1000]);free2=1;
+  f3=int(g_map[cad+2000]);free3=1;
+  if(machine==PLUS4M){free3=0;suffocatelimit=3;f3=int(g_map[2]);}
+  
+  if(foreg==g_map[1]&&g_control==false)return;
+  
+  if(foreg!=f1&&foreg!=f2&&foreg!=f3||g_control==true){
+   for(int yy=0;yy<=7;yy++){
+      for(int xx=0;xx<=3;xx++){
+        ad=1024+(mx*8+xx*2)+(my*8+yy)*X;
+        if(g_map[ad]==0&&g_map[ad+1]==0){//00 = 00
+          if(f0==f)order=4;
+        }        
+        if(g_map[ad]==1&&g_map[ad+1]==0){//01 = 10
+          numb=numb|1;free1=0;
+          if(f1==f)order=1;
+        }
+        if(g_map[ad]==0&&g_map[ad+1]==1){//02 = 01
+          numb=numb|2;free2=0;
+          if(f2==f)order=2;
+        }
+        if(g_map[ad]==1&&g_map[ad+1]==1){//03 = 11
+          if(machine==C64M){numb=numb|4;free3=0;}
+          if(f3==f){order=3;targetbit0=1;targetbit1=1;}
+        }      
+      }
+    }
+   
+   boolean zoink=false;
+   if(order==4)zoink=true;
+   if(order==3&&machine==PLUS4M)zoink=true;
+   
+   if((zoink||numb!=suffocatelimit)&&g_control==true){
+     if(zoink){ 
+       //println("foreg:"+foreg+" f0:"+f0+" f1:"+f1+" f2:"+f2+" f3:"+f3+" free1:"+free1+" free2:"+free2+" free3:"+free3);
+       b0=-1;b1=-1;
+       if(foreg==f1&&free1==0){b0=1;b1=0;}
+       if(foreg==f2&&free2==0){b0=0;b1=1;}
+       if(foreg==f3&&machine==C64M&&free3==0){b0=1;b1=1;}
+       if(foreg==f3&&machine==PLUS4M){b0=1;b1=1;}
+       
+       if(free1==1){
+         free2=0;free3=0;b0=1;b1=0;g_map[cad]=byte(foreg);
+       }
+       if(free2==1){
+         free3=0;b0=0;b1=1;g_map[cad+1000]=byte(foreg);
+       }
+       if(free3==1){
+         b0=1;b1=1;g_map[cad+2000]=byte(foreg);
+       }
+       
+       for(int yy=0;yy<=7;yy++){
+          for(int xx=0;xx<=3;xx++){
+              ad=1024+(mx*8+xx*2)+(my*8+yy)*X;
+            if(g_map[ad]==targetbit0&&g_map[ad+1]==targetbit1){
+              if(b0>=0){
+                g_map[ad]=byte(b0);g_map[ad+1]=byte(b1);
+              }
+            }
+          }
+       }
+     }
+   }
+   
+   //if all color positions are filled, we'll just change the existing one
+   
+    if(numb==suffocatelimit||g_control==true){
+      if(order==1){g_map[cad]=byte(foreg);}//10==1
+      if(order==2){g_map[cad+1000]=byte(foreg);}//01==2
+      if(order==3&&machine==C64M){g_map[cad+2000]=byte(foreg);}//11==3      
+    }
+    
+    //color redundancy check
+    
+      for(int yy=0;yy<=7;yy++){
+          for(int xx=0;xx<=3;xx++){
+            ad=1024+(mx*8+xx*2)+(my*8+yy)*X;
+            
+            if(machine==C64M){
+              if(g_map[cad]==g_map[cad+2000]){
+                if(g_map[ad]==1&&g_map[ad+1]==1){
+                  g_map[ad]=1;g_map[ad+1]=0;
+                }
+              }
+              if(g_map[cad+1000]==g_map[cad+2000]){
+                if(g_map[ad]==1&&g_map[ad+1]==1){
+                  g_map[ad]=0;g_map[ad+1]=1;
+                }
+              }          
+            }                
+            
+            if(g_map[cad]==g_map[cad+1000]){
+              if(g_map[ad]==0&&g_map[ad+1]==1){
+                g_map[ad]=1;g_map[ad+1]=0;
+              }
+            }
+            if(g_map[1]==g_map[cad]){
+                if(g_map[ad]==1&&g_map[ad+1]==0){
+                g_map[ad]=0;g_map[ad+1]=0;
+                }
+            }
+            if(g_map[1]==g_map[cad+1000]){
+                if(g_map[ad]==0&&g_map[ad+1]==1){
+                  g_map[ad]=0;g_map[ad+1]=0;
+                }
+            }
+            
+            if(machine==PLUS4M){
+              if(g_map[2]==g_map[cad]){
+                  if(g_map[ad]==1&&g_map[ad+1]==0){
+                  g_map[ad]=1;g_map[ad+1]=1;
+                  }
+              }
+              if(g_map[2]==g_map[cad+1000]){
+                  if(g_map[ad]==0&&g_map[ad+1]==1){
+                    g_map[ad]=1;g_map[ad+1]=1;
+                  }
+              }
+              if(g_map[1]==g_map[2]){
+                if(g_map[ad]==1&&g_map[ad+1]==1){
+                  g_map[ad]=0;g_map[ad+1]=0;
+                }
+              }              
+            }
+            
+            if(machine==C64M){
+              if(g_map[1]==g_map[cad+2000]){
+                  if(g_map[ad]==1&&g_map[ad+1]==1){
+                    g_map[ad]=0;g_map[ad+1]=0;
+                  }
+              }               
+            }
+          }
+      }
+    }
+    updatepoint(x,y);
+}
+
+void kaveri(int x,int y,int foreg,int backg)
+{
+  int k_max;
+  int maxy,miny;
+  int ad,bad,cad;
+  int mx,my,val;
+  int farge0,farge1;
+  if(g_multic!=0||g_hzoomer==2)return;
+  if(g_data['d']==1)return;
+  mx=x/8;my=y/8;
+ 
+  if(g_attrimode==1)
+    {k_max=64;miny=0;maxy=7;}
+  else
+    {k_max=8;miny=y/8;miny=miny*8;maxy=y-miny;miny=maxy;}
+  
+  if(g_britemode==1&&foreg==8)foreg=0;
+
+  //check the amount of colors in the area
+  //if there is only one, return & draw "normally"
+  
+  if(g_control==false){
+    
+    val=0;
+    
+    for(int yy=miny;yy<=maxy;yy++){
+      ad=1024+(mx*8)+(my*8+yy)*X;
+      for(int xx=0;xx<=7;xx++){
+        val=val+g_map[ad+xx];
+      }
+    }
+    
+    if(val>=k_max||val==0)return;
+  
+    //check the two colors the color area is made of
+    //if either of the intended color already exists inside the color area, return & draw "normally"
+    
+    bad=65536+mx+y*MX;
+    cad=bad+MX*(MY*8);
+    farge0=g_map[bad];//if(g_britemode==1&&farge0==8){farge0=0;}
+    farge1=g_map[cad];//if(g_britemode==1&&farge1==8){farge1=0;}
+    
+    if(g_britemode==1){
+      if(farge0<8){
+        if(foreg==farge0+8){
+          fixattr(x,y,foreg,-1);return;
+        }
+      }    
+      if(farge1<8){
+        if(foreg==farge1+8){
+          fixattr(x,y,-1,foreg);return;
+        }        
+      }
+      if(farge0>=8){
+        if(foreg==farge0-8){
+          fixattr(x,y,foreg,-1);return;
+        }
+      }        
+      if(farge1>=8){
+        if(foreg==farge1-8){
+          fixattr(x,y,-1,foreg);return;
+        }        
+      }
+    }
+    if(foreg==farge0)return;
+    if(foreg==farge1)return;
+
+  //new IQ: simply change the underlying color into the intended one, return & draw "normally"
+  
+  }
+  
+  int piksuf;
+  int bg,fg;
+  piksuf=getabsa(x,y,0);
+  if(g_britemode==1&&piksuf==8)piksuf=0;
+  bad=0;cad=0;
+  for(int yy=miny;yy<=maxy;yy++){
+      bad=65536+mx+(my*8)*MX+yy*MX;
+      cad=bad+MX*(MY*8);
+      fg=g_map[bad];if(g_britemode==1&&fg==8)fg=0;
+      bg=g_map[cad];if(g_britemode==1&&bg==8)bg=0;
+        if(piksuf==fg){
+          g_map[bad]=byte(foreg);
+          if(g_britemode==1){
+            if(foreg>7&&g_map[cad]<8&&g_map[cad]!=0){
+              g_map[cad]=byte(g_map[cad]+8);
+            }
+            if(foreg<8&&g_map[cad]>8&&foreg!=0){
+              g_map[cad]=byte(g_map[cad]-8);
+            }          
+          }
+        }
+        if(piksuf==bg){
+          g_map[cad]=byte(foreg);      
+          if(g_britemode==1){
+            if(foreg>7&&g_map[bad]<8&&g_map[bad]!=0){
+              g_map[bad]=byte(g_map[bad]+8);
+            }
+            if(foreg<8&&g_map[bad]>8&&foreg!=0){
+              g_map[bad]=byte(g_map[bad]-8);
+            }
+          }          
+        }
+  } 
+  
+  // if the result is same color, zero the pixel data
+  
+  if(g_map[bad]==g_map[cad]){
+    for(int yy=miny;yy<=maxy;yy++){
+       for(int xx=0;xx<=7;xx++){
+         ad=1024+(mx*8+xx)+(my*8+yy)*X;
+         g_map[ad]=byte(0);
+     }
+    }
+  }
+  updatepoint(x,y);
+}
+
+void kaveri_iq(int x,int y,int f1,int f2)
+{
+  int k_xx,k_yy,k_ad,k_bad,k_ojox,k_ojoy,k_miny,k_maxy,k_xv,k_yv;
+  int k_c1,k_c2,k_v0,k_v1,k_tipping,k_maximum;
+  byte k_p;
+  
+  if(g_multic!=0||g_hzoomer==2)return;
+  
+  int exist;
+
+  exist=getabsa(x,y,0);
+  
+  if(g_britemode==1){
+    if(exist==8){if(g_farge<8){exist=0;}}
+    if(exist==0){if(g_farge>7){exist=0;}}
+  }
+  
+  k_v0=0;k_v1=0;k_tipping=4;
+  k_xx=x/8;k_yy=y/8;k_yy=k_yy*8;k_ojox=x/8;k_ojoy=y/8;
+  k_ojox=k_ojox*8;k_ojoy=k_ojoy*8;k_miny=(y-k_ojoy);k_maxy=k_miny;k_maximum=8;
+  
+  if(g_attrimode==1){k_miny=0;k_maxy=7;k_tipping=32;k_maximum=64;}//spectrum&c64 style
+  
+  k_ad=65536+k_xx+(k_yy+k_miny)*MX;k_bad=k_ad+MX*(MY*8);
+  k_c1=g_map[k_ad];k_c2=g_map[k_bad];
+  
+  if(g_britemode==1){
+    if(k_c1==8)k_c1=0;
+    if(k_c2==8)k_c2=0;
+  }
+  
+  k_bad=1024+k_xx*8+k_yy*X;
+  
+  //do we have more 0's or 1's
+  for(k_yv=k_miny;k_yv<=k_maxy;k_yv++){
+    k_ad=k_bad+k_yv*X;
+    for(k_xv=0;k_xv<=7;k_xv++){
+        if(g_map[k_ad]==1){k_v1++;}else{k_v0++;}
+        k_ad++;
+    }
+  }
+  
+  //force color
+  
+  if(g_control){
+    
+    k_v1=k_tipping+1;
+    
+    if(k_c1==exist){k_c1=g_farge;  
+      if(k_c1==8&&g_britemode==1)k_c1=0;
+    }
+    if(k_c2==exist){k_c2=g_farge;
+      if(k_c2==8&&g_britemode==1)k_c2=0;
+    }
+    
+    if(g_britemode==1){
+      if(g_farge>=8){
+        if(k_c1<=7)k_c1=k_c1+8;
+        if(k_c2<=7)k_c2=k_c2+8;
+      }
+    if(g_farge<=7){
+        if(k_c1>=8)k_c1=k_c1-8;
+        if(k_c2>=8)k_c2=k_c2-8;
+      }
+    }
+    
+  }
+  
+  if(k_v1>k_tipping){
+      for(k_yv=k_miny;k_yv<=k_maxy;k_yv++){
+        k_ad=65536+k_xx+(k_yy+k_yv)*MX;
+        k_bad=k_ad+MX*(MY*8);g_map[k_ad]=byte(k_c2);g_map[k_bad]=byte(k_c1);
+      }
+      for(k_yv=k_miny;k_yv<=k_maxy;k_yv++){
+        k_ad=1024+k_xx*8+(k_yy+k_yv)*X;
+        for(k_xv=0;k_xv<=7;k_xv++){
+          k_p=g_map[k_ad];
+          g_map[k_ad]=byte(1-k_p);
+          if(k_c1==k_c2)g_map[k_ad]=byte(0);
+          k_ad++;
+      }
+    }    
+  }
+  updatepoint(x,y);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/events.pde	Tue Jul 03 20:56:55 2018 +0300
@@ -0,0 +1,735 @@
+//collects mouse/key events and directly related command parsing
+
+void keyPressed()
+{
+  if(key==ESC)
+  {
+    key=0;
+    return;
+  }
+  if(key==CODED){ 
+    if(keyCode==RIGHT)g_ofx++;refresh();
+    if(keyCode==LEFT)g_ofx--;refresh();
+    if(keyCode==UP)g_ofy--;refresh();
+    if(keyCode==DOWN)g_ofy++;refresh();        
+    if(keyCode==SHIFT)g_shift=true;
+    if(platform==MACOSX)
+    {
+      if(keyCode==COMMAND)g_control=true;
+    }
+    else
+    {
+      if(keyCode==CONTROL)g_control=true;
+    }  
+    return;
+  }
+  
+  //send to the indirect key handling
+  //so commands can be invoked elsewhere too
+  command(key);
+}
+
+void keyReleased()
+{
+  if(key==CODED){
+    if(keyCode==CONTROL)g_control=false;
+    if(keyCode==SHIFT)g_shift=false;
+    if(platform==MACOSX)
+    {
+      if(keyCode==COMMAND)
+      g_control=false;
+    }
+      else
+    {
+      if(keyCode==CONTROL)
+      g_control=false;
+    }  
+  }
+}
+
+void mouseDragged()
+{
+  int msx,msy;
+  g_iconx=mouseX;
+  g_icony=mouseY;
+  if(insidewindow(g_iconx,g_icony)){
+      if(g_phase==0){
+        g_piconx=g_iconx;g_picony=g_icony; g_iconx=-1;g_icony=-1;
+        g_repanel=-2;g_tooltrigger=100;
+        return;
+      }else{
+          g_iconx=-1;g_icony=-1;
+          g_piconx=-1;g_picony=-1;        
+      }
+  }else
+  {
+    if(g_data['m']==0&&g_data['M']==0){
+      msx=g_iconx-(g_windowx);
+      msy=g_icony-(g_windowy);
+      msx=g_msx-(g_windowx);msy=g_msy-(g_windowy);
+   
+    }else{
+      msx=g_iconx;msy=g_icony;
+    }
+    
+    g_iconx=-1;g_icony=-1;
+  }
+  g_iconx=-1;g_icony=-1;
+  if(mouseButton==CENTER)return;
+  if(g_tooltrigger==0)g_tooltrigger=1;
+}
+
+boolean insidewindow(int x,int y)
+{
+  if(x>width-g_hedge||y>height-g_vedge)return true;
+  return false;
+}
+
+void mousePressed()
+{
+    int msx,msy;
+    g_iconx=mouseX;g_icony=mouseY;
+    g_button=mouseButton;g_realbutton=g_button;
+ 
+    if(insidewindow(g_iconx,g_icony)){
+        if(g_phase==0){
+          g_repanel=-2;g_tooltrigger=100;g_piconx=g_iconx;g_picony=g_icony;
+        }else{
+          g_iconx=-1;g_icony=-1;
+        }
+      return;
+     }
+      else
+     {
+        g_msx=g_iconx;g_msy=g_icony;
+        if(g_data['m']==0&&g_data['M']==0){
+          msx=g_iconx-(g_windowx);
+          msy=g_icony-(g_windowy);
+          msx=g_msx-(g_windowx);msy=g_msy-(g_windowy);
+       
+        }else{
+          msx=g_iconx;msy=g_icony;
+        }
+            
+        if(g_button!=CENTER){
+          if(tool()!=5&&tool()!=4)store_undo();
+          if(tool()==4){//cut brush results in undo
+            if(g_button==RIGHT)store_undo();
+          }
+        }
+      if(g_button==CENTER){g_button=255;g_repanel=-2;
+        if(g_shift)g_button=254;
+      }
+      g_phase=0;
+      do_tool(msx,msy,g_button);
+      g_phase=1;
+   }
+}
+
+void mouseReleased()
+{
+  int swap;
+  g_tooltrigger=0;
+  g_klikkeri=0;
+  if(tool()==8){
+    if(g_phase==1){
+      g_phase=0;
+      rectangle(g_rx,g_ry,g_rx2,g_ry2);
+    }
+  }
+  if(tool()==7){//circle
+    if(g_phase==1){
+      g_phase=0;
+      docircle(g_rx,g_ry,g_rx2,g_ry2);
+    }
+  }  
+  if(tool()==6){
+    if(g_phase==1){
+      g_phase=0;
+      doline(g_rx,g_ry,g_rx2,g_ry2,0);
+    }
+  }
+  
+  if(g_data['4']==1){ 
+    if(g_phase==1){
+      g_phase=0;g_rubbermode=0;refresh();
+      g_data['4']=0;g_data['d']=0;
+      g_data['r']=0;g_data['R']=0;
+      g_data['x']=0;g_data['y']=0;
+      g_data['q']=0;g_data['p']=0;
+      g_data['t']=0;g_data['n']=0;
+      switcher(2);
+      if(g_multic==1||g_hzoomer==2){g_rx=g_rx/2;g_rx=g_rx*2;g_rx2=g_rx2/2;g_rx2=g_rx2*2;}
+      g_bsourcex=g_rx;g_bsourcey=g_ry;
+      g_bsourcex2=g_rx2;g_bsourcey2=g_ry2;
+      if(g_bsourcex<=0)g_bsourcex=0;
+      if(g_bsourcey<=0)g_bsourcey=0;
+      if(g_bsourcex>=X)g_bsourcex=X-1;
+      if(g_bsourcey>=Y)g_bsourcex=Y-1;    
+      if(g_bsourcex2<=0)g_bsourcex2=0;
+      if(g_bsourcey2<=0)g_bsourcey2=0;
+      if(g_bsourcex2>=X)g_bsourcex2=X-1;
+      if(g_bsourcey2>=Y)g_bsourcey2=Y-1;
+      
+      set_tool(1);
+      g_btype=9;
+      g_repanel=-2;
+      if(g_button==RIGHT){
+        storeparameters();
+        g_data['f']=1;g_data['X']=0;g_data['Y']=0;       
+        doborx(g_rx,g_ry,g_rx2,g_ry2);
+        restoreparameters();
+      }
+    }
+  consistency();
+  }
+  if(g_phase==1){
+     g_phase=0;g_rubbermode=0;refresh(); //needed otherwise the pen color is kept e.g. after right mousebutton
+  }
+}
+
+void macro_command(int ckey)
+{
+    //filter out load/save
+    if(ckey=='s'||ckey=='S'||ckey=='l'||ckey=='E'||ckey=='w'||ckey=='W'||ckey=='A')return;
+    command(ckey);
+}
+
+void command(int ckey)
+{
+  int swap;
+  
+  //keypresses change g_data[] values directly as 1/0 switches
+  //handling these presses "indirectly" adds complexity here
+  //but is valuable elsewhere = corresponding icons have shortcuts automatically
+  
+  if(ckey=='-')ckey='h';
+  if(ckey=='+')ckey='H';
+  
+  if(ckey==TAB){
+    if(g_shift==false){
+      if(g_britemode==1){
+        if(g_realfront==7)g_realfront=-1;
+        if(g_realfront==15)g_realfront=7;
+      }
+      selectcolor(0,g_realfront+1);g_repanel=-2;
+    }else{
+      if(g_britemode==1){
+        if(g_realfront==8)g_realfront=16;
+        if(g_realfront==0)g_realfront=8;
+      }
+      selectcolor(0,g_realfront-1);g_repanel=-2;
+    }
+  }
+      
+  //println("ckey+"+ckey);
+  if(g_control==true){
+    int UNDO=26,
+    REDO=25,
+    PASTE=22,
+    SAVE=19,
+    LOAD=15,
+    NEW=14,
+    COPY=3,
+    COPYALT=24,
+    ALL=1;
+            
+    if(platform==MACOSX){
+      UNDO=122;
+      REDO=25;
+      PASTE=22;
+      SAVE=115;
+      LOAD=111;
+      NEW=110;
+      COPY=99;
+      COPYALT=120;
+      ALL=97;        
+    }
+        
+    if(ckey==UNDO){
+      ckey='u';
+      if(g_shift)ckey='U';
+    }//undo
+    if(ckey==REDO)ckey='U';
+    if(ckey==PASTE)ckey='9';
+    if(ckey==SAVE){
+      ckey='S';
+      if(g_shift)ckey='s';
+    }//save
+    if(ckey==LOAD)ckey='l';
+    if(ckey==NEW)ckey='o';
+    if(ckey==COPY||ckey==COPYALT)ckey='4';
+    if(ckey==ALL){
+      switcher(2);
+      g_bsourcex=0;g_bsourcey=0;
+      g_bsourcex2=X-1;g_bsourcey2=Y-1;
+      ckey='9';
+      g_data['p']=0;g_data['x']=0;g_data['y']=0;g_data['q']=0;g_data['z']=0;
+      g_phase=0;g_rubbermode=0;
+      set_tool(1);
+    }
+  }
+  
+  if(ckey>=128&&ckey<=131){
+    g_bsize=ckey-128;g_btype=0;
+  }
+  
+  if(ckey>=132&&ckey<=135){
+    g_bsize=ckey-132;g_btype=1;
+  }
+  
+  if(ckey==' '||ckey=='.'){
+    if(ckey=='.'){g_bsize=0;g_btype=0;g_data['n']=0;}
+    ckey='3';
+    if(ckey==' '){}    
+  }
+    
+  if(ckey>=0&&ckey<=255){
+    //g_depressed[ckey-48]=10;
+  }
+    
+  if(ckey==','){
+      g_repanel=-2;
+      do_tool(mouseX,mouseY,255);
+      do_tool(g_mx,g_my,255);
+      return;
+  }
+  
+  if(ckey=='v'){
+    g_repanel=-2;
+   // do_tool(mouseX,mouseY,254);
+    do_tool(g_mx,g_my,254);
+    return;
+  }
+  
+  if(ckey=='['){
+      fixed_raster_command('x');
+      message("R.OFFSET "+str(g_raster_offset_x)+"."+str(g_raster_offset_y));
+      g_repanel=-2;
+      return;
+  }
+  if(ckey==']'){
+      fixed_raster_command('y');
+      message("R.OFFSET "+str(g_raster_offset_x)+"."+str(g_raster_offset_y));
+      g_repanel=-2;
+      return;
+  }  
+  if(ckey=='('){
+      fixed_raster_command('p');
+      message("RASTER "+str(g_raster_no)+"/9|[=PREV|]=NEXT");
+      g_repanel=-2;
+      return;
+  }
+  
+  if(ckey==')'){
+      fixed_raster_command('n');
+      message("RASTER "+str(g_raster_no)+"/9|[=PREV|]=NEXT");
+      g_repanel=-2;
+      return;
+  }
+  
+  if(ckey=='>'){
+    selectcolor(0,g_rgb[int(g_map[1])]);
+    message("Current=Back");    
+    g_repanel=-2;
+    return;
+  }
+  if(ckey=='<'){
+    g_repanel=-2;
+    swap=g_farge;
+    g_farge=g_backg;g_ofarge=g_farge;
+    g_backg=swap;
+    g_realfront=byte(g_farge);
+    g_realback=byte(g_backg);
+  }
+  
+  if(ckey=='0'){
+      if(g_data['m']==0&&g_data['M']==0){
+        if(tool()!=0){
+          g_prevtool=tool();
+        }
+      }else
+      {
+        ckey='m';
+      }
+   }
+      
+   if(ckey=='9'){
+     g_repanel=-2;
+     g_btype=9;
+     return;
+   }
+   if(ckey>='0'&&ckey<='8'){
+     g_repanel=-2;
+     set_tool(ckey-48);
+     g_phase=0;g_rubbermode=0;
+     g_rx=-1;g_ry=-1;g_rx2=-1;g_ry2=-1;
+     if(g_data[ckey]>1)g_data[ckey]=0;
+     if(ckey=='4'){
+       g_data['x']=0;
+       g_data['y']=0;
+       g_data['h']=0;
+       g_data['q']=0;
+       g_data['t']=0;
+       g_data['n']=0;
+     }
+  }
+  
+  if(ckey>='A'&&ckey<='Z'){
+    g_repanel=-2;
+    g_data[ckey]++;
+    if(g_data[ckey]>1)g_data[ckey]=0;
+    
+    if(ckey=='Q'){g_repanel=-2;g_msgctr=0;help('B');g_msgctr=50;}
+    if(ckey=='G'){
+      g_data['G']=0;
+      switch(g_gridx){
+        case 8:
+          g_gridx=16;g_gridy=16;
+        break;
+        case 16:
+          g_gridx=4;g_gridy=4;
+        break;
+        case 4:
+          g_gridx=8;g_gridy=8;
+        break;
+      }
+      g_repanel=-2;g_msgctr=0;help('g');g_msgctr=50;
+    }
+    
+    if(ckey=='I'){
+       // message("sprites shitted");
+        //poopsprites();
+       // poopspecialsprites();
+    }
+    
+    if(ckey=='T'){
+     //   message("chars shitted");
+      //  poopultimachars();
+//        poopsprites();
+    }
+    if(ckey=='G'){
+       if(g_data['g']==0)g_data['g']=1;
+    }
+    if(g_data['M']==0)g_boxreconstruct=2;
+    
+    if(g_data['M']==1){
+      if(ckey=='M'){
+        g_ofx=g_storedcoordx/8-magx()/2;
+        g_ofy=g_storedcoordy/8-magy()/2;
+        g_data['m']=0;message("Super|Magnify");
+        if(tool()==0){set_tool(g_prevtool);g_phase=0;g_rubbermode=0;}
+      }
+    }
+    if(g_data['B']==1){
+      g_data['B']=0;
+      if(machine!=MSX){
+        store_undo();
+        g_map[0]=byte(zxcolor(g_farge));
+        sussborder();
+        message("Set border");
+      }
+      if(machine==MSX){
+        g_data['C']=1;
+      }
+    }
+    if(g_data['C']==1){
+      g_data['C']=0;
+      if(int(g_map[1])!=255){
+        store_undo();
+        if(machine==PLUS4M&&g_farge==g_map[2]){
+            message("1st and 2nd|can't be|same");
+            refresh();
+            return;          
+        }
+        g_map[1]=byte(g_farge);
+        
+        if(machine==MSX){g_map[0]=byte(g_farge);sussborder();}
+        message("Set back|color");
+       }
+    }
+    if(g_data['V']==1){
+      g_data['V']=0;
+      if(int(g_map[1])!=255){
+        store_undo();
+        if(machine==PLUS4M&&g_farge==g_map[1]){
+          message("1st and 2nd|can't be|same");
+          refresh();
+          return;
+        }
+          g_map[2]=byte(g_farge);
+        message("Set 2nd|back color");
+       }
+    }      
+    if(g_data['W']==1){
+      g_data['W']=0; 
+      if(g_formatextension!=""){
+        gui=true;exportfmt=true;
+        message("Format|export");
+      }
+        else
+      {
+        message("None for|"+g_name);
+      }
+    }
+    if(g_data['N']==1){
+        g_data['N']=0;
+        int i=g_animspeed;
+        i++;
+        if(i>3)i=0;
+        g_animspeed=i;
+        message("Playbrush|speed="+g_animspeed);
+      }
+    refresh();
+  }
+  
+  if(ckey>='a'&&ckey<='z'){
+    g_repanel=-2;
+    g_data[ckey]++;
+    if(g_data[ckey]>1){
+      if(ckey=='m'||ckey=='M'){g_boxreconstruct=2;g_data['M']=0;g_data['m']=0;}
+      g_data[ckey]=0;
+    }
+    
+    if(g_data['t']==1){
+      if(ckey=='t')message("Tile mode");
+    }
+    
+    if(ckey=='n'){if(g_data['n']==1){
+      switcher(2);infersize();
+      if(g_data['n']==1){
+        command('1');command('9');
+        g_data['p']=0;g_data['x']=0;g_data['y']=0;
+        g_data['q']=0;g_data['t']=0;
+        }
+      }
+    }    
+    
+    if(g_data['i']==1){
+      g_data['i']=0;
+      selectcolor(0,nextluminance(g_farge,1));
+    }
+    if(g_data['k']==1){
+      g_data['k']=0;
+      selectcolor(0,nextluminance(g_farge,-1));
+    }
+    if(g_data['d']==0){
+      if(ckey=='d')consistency();
+    }
+    if(g_data['z']==1){
+      g_data['z']=0;
+      int orient;
+      orient=g_data['x']*100+g_data['y']*10+g_data['q'];
+      if(orient==0){
+        g_data['x']=0;g_data['y']=0;g_data['q']=1;
+      }
+      if(orient==1){
+        g_data['x']=1;g_data['y']=1;g_data['q']=0;
+      }  
+      if(orient==110){
+        g_data['x']=1;g_data['y']=1;g_data['q']=1;
+      } 
+      if(orient==111){
+        g_data['x']=0;g_data['y']=0;g_data['q']=0;
+      }
+      if(orient==100){
+        g_data['x']=0;g_data['y']=1;g_data['q']=1;
+      }
+      if(orient==11){
+        g_data['x']=0;g_data['y']=1;g_data['q']=0;
+      }  
+      if(orient==10){
+        g_data['x']=1;g_data['y']=0;g_data['q']=1;
+      }
+      if(orient==101){
+        g_data['x']=1;g_data['y']=0;g_data['q']=0;
+      }      
+      message("Rotate|brush");
+    }    
+
+    if(ckey=='m'){
+      if(g_data['M']==1){
+        g_data['M']=0;g_data['m']=0;ckey=0;g_boxreconstruct=2;
+      }
+      g_data['M']=0;        
+    }
+    if(g_data['m']==1){
+      if(ckey=='m'){
+       g_data['M']=0;
+       int moux,mouy;
+       moux=g_mx/g_wzoom;mouy=g_my/g_wzoom;
+       g_ofx=moux/(8)-magx()/2;
+       g_ofy=mouy/(8)-magy()/2;
+       message("Magnify");
+       if(tool()==0){set_tool(g_prevtool);g_phase=0;g_rubbermode=0;}
+      }
+    }
+    refresh();
+  }
+  
+  if(g_data['J']==1){
+    g_data['J']=0;g_data['j']=0;
+    spare();
+    store_undo();
+    switch(g_spare){
+      case 0:
+        message("Copied to|Front");
+        switcher(4);
+      break;
+      case 1:
+        message("Copied to|Spare");
+        switcher(4);        
+      break;
+    }
+    spare(); 
+  }
+  
+  if(g_data['j']==1){
+    g_data['j']=0;
+    if(g_spare==0)message("Spare Page");
+    if(g_spare==1)message("Front Page");
+    spare();
+    makecolor(259,g_r[g_map[0]],g_g[g_map[0]],g_b[g_map[0]]);
+    g_boxreconstruct=2;
+  }
+  if(g_data['E']==1){
+    g_data['E']=0;
+    message("Source|export");    
+    gui=true;exporttxt=true;
+    //machine_export(1);  
+  }
+  if(g_data['A']==1){
+    g_data['A']=0;
+    message("Executable|export");   
+    gui=true;exportemu=true;
+    //machine_export(0);  
+  }
+  if(g_data['w']==1){
+    g_data['w']=0;
+    gui=true;importfmt=true;
+  }   
+  if(g_data['O']==1){
+    g_data['O']=0;
+    store_undo();
+    for(int xx=0;xx<X*Y;xx++){
+        g_map[1024+xx]=0;
+    }    
+    for(int xx=0;xx<X;xx++){
+      for(int yy=0;yy<Y;yy++){
+        g_farge=g_backg;
+        makepoint(xx,yy);
+        g_farge=g_ofarge;      
+      }
+    }
+  }
+  
+  if(g_data['o']==1){
+    g_data['o']=0;
+    message("Clear all");
+    store_undo();
+    storeparameters();
+    g_data['r']=0;g_data['R']=0;g_data['d']=0;g_data['t']=0;
+           
+    for(int xx=0;xx<X*Y;xx++){
+        g_map[1024+xx]=0;
+    }
+ 
+    for(int xx=0;xx<X;xx++){
+      for(int yy=0;yy<Y;yy++){
+        g_farge=g_backg;
+        makepoint(xx,yy);
+        g_farge=g_ofarge;      
+      }
+    }
+    
+    restoreparameters();
+  }
+  
+  if(g_data['e']==1){
+    g_data['e']=0;
+  }
+ 
+  if(g_data['h']==1){
+    g_data['h']=0;
+    g_bsize--;if(g_bsize<0)g_bsize=0;
+    g_msgctr=-2;
+    help('h');  
+  }
+  if(g_data['H']==1){
+    g_data['H']=0;
+    g_bsize++;if(g_bsize>10)g_bsize=10;
+    g_msgctr=-2;
+    help('h');
+  }  
+  if(g_data['u']==1){
+    g_data['u']=0;
+    message("Undo");
+    restore_undo();refresh();g_boxreconstruct=2;
+  }
+  if(g_data['U']==1){
+    g_data['U']=0;
+    message("Redo");
+    redo_undo();refresh();
+  }
+  if(g_data['S']==1){
+    g_data['S']=0;
+    if(g_spare==0)elename=filename;
+    if(g_spare==1)elename=sfilename;
+    
+    if(elename.length()>3){
+    
+      if(g_iconmode==0){
+        if(g_spare==0){
+          message("Page saved");
+          store(elename);
+        }
+        if(g_spare==1){
+          message("Spare page|saved");
+          store(elename);
+        }
+      }
+    
+    }
+      else
+    {
+      message("No filename!");
+      message("*");
+      g_data['S']=0;g_data['s']=0;
+    }
+  }
+  
+  if(machine==SPECTRUM&&debugger==1){
+      if(g_data['i']==1){
+          g_data['i']=0;
+          if(g_iconmode==0){
+            message("Icons|not loaded!");
+          }
+            else
+          {
+            message("Store|icons");
+            store("icons.bin");
+          }
+      }
+      if(g_data['I']==1){
+        g_data['I']=0;
+        store_undo();
+        message("Restore|icons");
+        restore("icons.bin");
+        refresh();
+        g_iconmode=1;
+      }  
+  }
+  if(g_data['l']==1){
+    g_data['l']=0;
+    gui=true;fileselect=true;
+  }
+  if(g_data['s']==1){
+    g_data['s']=0;
+    gui=true;saveas=true;
+  }  
+  if(g_data['L']==1){
+    g_data['L']=0;
+  }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/exporters.pde	Tue Jul 03 20:56:55 2018 +0300
@@ -0,0 +1,1851 @@
+// machine definitions
+// source writer and other export/import functions
+// the machine_export() makes use of bitmapexport() and colorexport() below
+// remember hexdump -C !
+
+String g_formatname, g_formatextension;
+
+int g_headpos;
+int[] g_grids = new int[16];
+int OLD=0;
+int NEW=1;
+int g_gridmode=OLD;
+
+int bitti(int inp)
+{
+    if(inp==0)return 0;
+    return 1;
+}
+
+int qbitti(int inp)
+{
+    if(inp==10)return 1;
+    return 0;
+}
+
+void poopspecialsprites()
+{
+    int x,y,xs,xx,yy,mup,row;
+    int b7,b6,b5,b4,b3,b2,b1,b0,val;
+    mup=0;
+        for(row=0;row<=1;row++){
+        for(x=0;x<=8;x++)
+        {
+            for(y=0;y<=20;y++){
+            for(xs=0;xs<=2;xs++){
+                if(mup>0){print(",");}
+                  mup=1;
+                  xx=x*24+xs*8;
+                  if(row==1&&x==7){xx=xx+24;}
+                  if(x==8){xx=xx+24;}
+                  yy=row*48+2+y;
+                  b7=qbitti(easygetcolor(xx,yy));
+                  b6=qbitti(easygetcolor(xx+1,yy));
+                  b5=qbitti(easygetcolor(xx+2,yy));
+                  b4=qbitti(easygetcolor(xx+3,yy));
+                  b3=qbitti(easygetcolor(xx+4,yy));
+                  b2=qbitti(easygetcolor(xx+5,yy));
+                  b1=qbitti(easygetcolor(xx+6,yy));
+                  b0=qbitti(easygetcolor(xx+7,yy));
+                  val=b7*128+b6*64+b5*32+b4*16+b3*8+b2*4+b1*2+b0;
+                  print(str(val));
+            }
+            
+        }print(",0");  println("");
+        for(y=0;y<=20;y++){
+            for(xs=0;xs<=2;xs++){
+                if(mup>0){print(",");}
+                  mup=1;
+                  xx=x*24+xs*8;yy=row*48+y*2;
+                  if(x==8){xx=xx+24;}
+                    b7=bitti(easygetcolor(xx,yy));
+                    b6=bitti(easygetcolor(xx+1,yy));
+                    b5=bitti(easygetcolor(xx+2,yy));
+                    b4=bitti(easygetcolor(xx+3,yy));
+                    b3=bitti(easygetcolor(xx+4,yy));
+                    b2=bitti(easygetcolor(xx+5,yy));
+                    b1=bitti(easygetcolor(xx+6,yy));
+                    b0=bitti(easygetcolor(xx+7,yy));                 
+                  if(x==7){xx=x*24+xs*16;yy=row*48+y;
+                    b7=bitti(easygetcolor(xx,yy));
+                    b6=bitti(easygetcolor(xx+2,yy));
+                    b5=bitti(easygetcolor(xx+4,yy));
+                    b4=bitti(easygetcolor(xx+6,yy));
+                    b3=bitti(easygetcolor(xx+8,yy));
+                    b2=bitti(easygetcolor(xx+10,yy));
+                    b1=bitti(easygetcolor(xx+12,yy));
+                    b0=bitti(easygetcolor(xx+14,yy));
+                  }
+                  val=b7*128+b6*64+b5*32+b4*16+b3*8+b2*4+b1*2+b0;
+                  print(str(val));
+            }
+          
+        }print(",0");  println();
+        }
+    }
+}
+
+void poopultimachars()
+{
+    PImage poutput;
+    poutput=createImage(256*8,8,RGB);
+    int x,y,rr,gg,bb,xx,yy,bx,by;
+    int ac,box,boy;
+    int b7,b6,b5,b4,b3,b2,b1,b0,val;
+    int blok,muna;
+    color c;
+    
+    blok=0;
+    PrintWriter f=createWriter("/home/tero/code/c64/ultima/graffa.s");
+    f.println(".global _graffa");
+    f.println("_graffa:");
+    f.println();
+    //print("unsigned char graffa[]={");
+    for(y=0;y<=5;y++){
+      muna=0;
+      if(blok<=63){
+        f.print(".byte ");}
+    for(x=0;x<=19;x++)
+    {
+      if(blok<=63){
+      for(boy=0;boy<=1;boy++){
+        for(box=0;box<=1;box++){
+          
+        for(yy=0;yy<=7;yy++){
+          bx=x*16+box*8;by=(y*16+boy*8+yy);
+      
+            b7=0;b6=0;b5=0;b4=0;b3=0;b2=0;b1=0;b0=0;
+            ac=easygetcolor(bx,by);
+            if(ac==0){b7=0;b6=0;}
+            if(ac==15){b7=1;b6=0;}
+            if(ac==2){b7=0;b6=1;}
+            if(ac==7){b7=1;b6=1;}
+            ac=easygetcolor(bx+2,by);
+            if(ac==0){b5=0;b4=0;}
+            if(ac==15){b5=1;b4=0;}
+            if(ac==2){b5=0;b4=1;}
+            if(ac==7){b5=1;b4=1;}
+            ac=easygetcolor(bx+4,by);
+            if(ac==0){b3=0;b2=0;}
+            if(ac==15){b3=1;b2=0;}
+            if(ac==2){b3=0;b2=1;}
+            if(ac==7){b3=1;b2=1;}
+            ac=easygetcolor(bx+6,by);
+            if(ac==0){b1=0;b0=0;}
+            if(ac==15){b1=1;b0=0;}
+            if(ac==2){b1=0;b0=1;}
+            if(ac==7){b1=1;b0=1;}            
+            val=b7*128+b6*64+b5*32+b4*16+b3*8+b2*4+b1*2+b0;
+            f.print(str(val));muna++;
+            if(muna<640){f.print(",");}
+            
+          for(xx=0;xx<=7;xx++){
+             
+            rr=g_r[easygetcolor(x*8+xx,y*8+yy)];  
+            gg=g_g[easygetcolor(x*8+xx,y*8+yy)];  
+            bb=g_b[easygetcolor(x*8+xx,y*8+yy)];
+            c=color(rr,gg,bb);
+            poutput.set(x*8+y*(16*8)+xx,yy,c);
+          }
+        }
+        }
+      }
+      }
+      }
+      f.println();
+      blok++;
+    }
+        f.flush();
+    f.close();
+    //poutput.save("/home/tero/sketchbook/petscii/data/petscii-c64x.png");
+}
+
+void poopchars()
+{
+    PImage poutput;
+    poutput=createImage(256*8,8,RGB);
+    int x,y,rr,gg,bb,xx,yy,bx,by;
+    int ac;
+    int b7,b6,b5,b4,b3,b2,b1,b0,val;
+    color c;
+    
+    PrintWriter f=createWriter("/home/tero/code/c64/newgame/graffa.s");
+    f.println(".global _graffa");
+    f.println("_graffa:");
+    f.println();
+    //print("unsigned char graffa[]={");
+      for(y=0;y<=15;y++){
+        f.print(".byte ");
+    for(x=0;x<=15;x++)
+    {
+        for(yy=0;yy<=7;yy++){
+          bx=x*8;by=(y*8+yy);
+      
+            b7=0;b6=0;b5=0;b4=0;b3=0;b2=0;b1=0;b0=0;
+            ac=easygetcolor(bx,by);
+            if(ac==0){b7=0;b6=0;}
+            if(ac==15){b7=1;b6=0;}
+            if(ac==11){b7=0;b6=1;}
+            if(ac==5){b7=1;b6=1;}
+            ac=easygetcolor(bx+2,by);
+            if(ac==0){b5=0;b4=0;}
+            if(ac==15){b5=1;b4=0;}
+            if(ac==11){b5=0;b4=1;}
+            if(ac==5){b5=1;b4=1;}
+            ac=easygetcolor(bx+4,by);
+            if(ac==0){b3=0;b2=0;}
+            if(ac==15){b3=1;b2=0;}
+            if(ac==11){b3=0;b2=1;}
+            if(ac==5){b3=1;b2=1;}
+            ac=easygetcolor(bx+6,by);
+            if(ac==0){b1=0;b0=0;}
+            if(ac==15){b1=1;b0=0;}
+            if(ac==11){b1=0;b0=1;}
+            if(ac==5){b1=1;b0=1;}            
+            val=b7*128+b6*64+b5*32+b4*16+b3*8+b2*4+b1*2+b0;
+            f.print(str(val));
+            if(x<15||yy<7){f.print(",");}
+          for(xx=0;xx<=7;xx++){
+             
+            rr=g_r[easygetcolor(x*8+xx,y*8+yy)];  
+            gg=g_g[easygetcolor(x*8+xx,y*8+yy)];  
+            bb=g_b[easygetcolor(x*8+xx,y*8+yy)];
+            c=color(rr,gg,bb);
+            poutput.set(x*8+y*(16*8)+xx,yy,c);
+          }
+        }
+      }
+      f.println();
+    }
+        f.flush();
+    f.close();
+    poutput.save("/home/tero/sketchbook/petscii/data/petscii-c64x.png");
+}
+
+void poopsprites()
+{
+    int x,y,xs,xx,yy,mup;
+    int b7,b6,b5,b4,b3,b2,b1,b0,val;
+    mup=0;
+        for(x=0;x<=7;x++)
+        {
+            for(y=0;y<=15;y++){
+            for(xs=0;xs<=1;xs++){
+                if(mup>0){print(",");}
+                mup=1;
+            xx=x*16+xs*8;
+            yy=y;
+            b7=bitti(easygetcolor(xx,yy));
+            b6=bitti(easygetcolor(xx+1,yy));
+            b5=bitti(easygetcolor(xx+2,yy));
+            b4=bitti(easygetcolor(xx+3,yy));
+            b3=bitti(easygetcolor(xx+4,yy));
+            b2=bitti(easygetcolor(xx+5,yy));
+            b1=bitti(easygetcolor(xx+6,yy));
+            b0=bitti(easygetcolor(xx+7,yy));
+            val=b7*128+b6*64+b5*32+b4*16+b3*8+b2*4+b1*2+b0;
+            print(str(val));
+            }
+            
+        }println();
+    }
+    
+}
+
+void pushbyte(int ad,int head)
+{
+  g_map[ad]=byte((g_template[head]&128)>>7);
+  g_map[ad+1]=byte((g_template[head]&64)>>6);             
+  g_map[ad+2]=byte((g_template[head]&32)>>5);
+  g_map[ad+3]=byte((g_template[head]&16)>>4);  
+  g_map[ad+4]=byte((g_template[head]&8)>>3);
+  g_map[ad+5]=byte((g_template[head]&4)>>2);             
+  g_map[ad+6]=byte((g_template[head]&2)>>1);
+  g_map[ad+7]=byte(g_template[head]&1); 
+}
+                    
+void format_import(String fname)
+{
+    int x, y, x2, y2, y3, head, xx, yy, yp, ad, valu;
+    int p1, p2, p3;
+    head=0;
+    
+    if (machine==SPECTRUM) //SCR=SCREEN$
+    {
+        // 32*24*8 bytes of bitmap
+        // 32*24 bytes of attributes
+        import_program(fname);
+        if(g_template.length<6912){message("FALSE");return;}
+        for (y=0; y<=2; y++) {
+            for (y2=0; y2<=7; y2++) {
+                for (yy=0; yy<=7; yy++) {
+                    for (x=0; x<=31; x++) {
+                        yp=y*64+yy*8+y2;
+                        ad=1024+yp*256+x*8;
+                        pushbyte(ad,head);
+                        head++;
+                    }
+                }
+            }
+        }
+        for (y=0; y<=23; y++) {
+            for (x=0; x<=31; x++) {
+                ad=65536+x+y*(32*8);
+                valu=g_template[head];
+                int ink=valu&7;
+                int pap=valu&56;
+                pap=pap>>3;
+                int bri=valu&64;
+                bri=bri>>6;
+                ink=ink+bri*8;
+                pap=pap+bri*8;
+                if (pap==8) {
+                    pap=0;
+                }
+                for (y2=0; y2<=7; y2++) {
+                    g_map[ad+y2*32]=byte(ink);
+                    g_map[ad+y2*32+MX*MY*8]=byte(pap);
+                }
+                head++;
+            }
+        }
+    }
+
+    if (machine==C64) {
+        //0x0002->bitmap
+        //0x1f42->colormap
+        //0x232a=border (take the lower nybble)
+        import_program(fname); //art studio
+        if(g_template.length<9006){message("FALSE");return;}
+        if (g_template.length>=0x232a) {
+            g_map[0]=byte(g_template[0x232a]&15);
+        }
+        for (y=0; y<25; y++) {
+            for (x=0; x<40; x++) {
+                for (y2=0; y2<=7; y2++) {
+                    head=2+x*8+y*(40*8)+y2;
+                    ad=1024+x*8+y*(320*8)+y2*320;
+                    pushbyte(ad,head);
+                    p1=g_template[0x1f42+x+y*40]&15;
+                    p2=g_template[0x1f42+x+y*40]&240;
+                    p2=p2>>4;             
+                    g_map[65536+x+y*40*8+y2*40]=byte(p2);
+                    g_map[65536+MX*MY*8+x+y*40*8+y2*40]=byte(p1);
+                }
+            }
+        }
+    }
+    
+    if (machine==PLUS4) { // Botticelli
+        //g.hires.prg = botticelli
+        //2 - luminance 40*25
+        //1026 - colors 40*25
+        //2050 - bitmappi 40*25*8    
+        import_program(fname); 
+        
+        if(g_template.length<10050){message("FALSE");return;}
+        int l1,l2;
+        for (y=0; y<25; y++) {
+            for (x=0; x<40; x++) {
+                for (y2=0; y2<=7; y2++) {
+                    head=2050+x*8+y*(40*8)+y2;                    
+                    ad=1024+x*8+y*(320*8)+y2*320;
+                    pushbyte(ad,head);
+
+                    p1=g_template[1026+x+y*40]&15;
+                    p2=g_template[1026+x+y*40]&240;
+                    p2=p2>>4;
+                    l1=g_template[2+x+y*40]&15;
+                    l2=g_template[2+x+y*40]&240;
+                    l2=l2>>4;                    
+                    g_map[65536+x+y*40*8+y2*40]=byte(convertlumi(l1,p2));
+                    g_map[65536+MX*MY*8+x+y*40*8+y2*40]=byte(convertlumi(l2,p1));
+                }
+            }
+        }
+                 
+    }
+    
+    if (machine==PLUS4M) { // Multi Botticelli
+        //m.multi.prg = multi botticelli
+        //2- lumins 40*25
+        //1024 - bäkki1
+        //1025 - bäkki2
+        //1026 - colors 40*25
+        //2050 - bitmap 40*25*8    
+        import_program(fname);
+        
+        if(g_template.length<10050){message("FALSE");return;}
+        int l1,l2;
+        for (y=0; y<25; y++) {
+            for (x=0; x<40; x++) {
+                for (y2=0; y2<=7; y2++) {
+                    head=2050+x*8+y*(40*8)+y2;                    
+                    ad=1024+x*8+y*(320*8)+y2*320;
+                    pushbyte(ad,head);
+
+                    p1=g_template[1026+x+y*40]&15;
+                    p2=g_template[1026+x+y*40]&240;
+                    p2=p2>>4;
+                    l1=g_template[2+x+y*40]&15;
+                    l2=g_template[2+x+y*40]&240;
+                    l2=l2>>4;                    
+                    g_map[65536+x+y*40+1000]=byte(convertlumi(l1,p2));
+                    g_map[65536+x+y*40+0000]=byte(convertlumi(l2,p1));
+                }
+            }
+        }
+      p1=int(g_template[1025])&240;
+      l1=int(g_template[1025])&15;
+      p1=p1>>4;           
+      g_map[1]=byte(convertlumi(l1,p1));
+      p1=int(g_template[1024])&240;
+      l1=int(g_template[1024])&15;
+      p1=p1>>4;       
+      g_map[2]=byte(convertlumi(l1,p1));
+    }
+    
+    if (machine==C64M) {//advanced art studio      
+        //adv. art studio (=multicolor) 10018 bytes
+        //0x0002 bitmap (40*25*8)
+        //0x1f42 colors1 (40*25)
+        //0x232a border
+        //0x232b background
+        //0x233a colors2 (40*25)
+        import_program(fname); 
+        if(g_template.length<10018){message("FALSE");return;}
+        for (y=0; y<25; y++) {
+            for (x=0; x<40; x++) {
+                for (y2=0; y2<8; y2++) {
+                    head=2+x*8+y*(40*8)+y2;
+                    ad=1024+x*8+y*(320*8)+y2*320;
+                    pushbyte(ad,head);
+
+                    p1=g_template[0x1f42+x+y*40]&15;
+                    p2=g_template[0x1f42+x+y*40]&240;
+                    p2=p2>>4;
+                    p3=g_template[0x233a+x+y*40]&15;
+                    g_map[65536+x+y*40]=byte(p1);
+                    g_map[65536+x+y*40+1000]=byte(p2);
+                    g_map[65536+x+y*40+2000]=byte(p3);
+                    g_map[0]=byte(g_template[0x232a]&15);//bord
+                    g_map[1]=byte(g_template[0x232b]&15);//baku
+                }
+            }
+        }
+    }
+
+    if(machine==MSX){        // sc2
+        // 7=bitmap 32*24*8
+        // 7+(32*24*8)=colormap 32*24
+        import_program(fname);
+        if(g_template.length<14343){message("FALSE");return;}
+            for (y=0; y<24; y++) {
+              for (x=0; x<32; x++) {
+                for (y2=0; y2<=7; y2++) {
+                    head=7+x*8+y*(32*8)+y2;
+                    ad=1024+x*8+y*(256*8)+y2*256;
+                    pushbyte(ad,head);
+                    p1=g_template[(8199)+x*8+((y*8*32)+y2)]&15;
+                    p2=g_template[(8199)+x*8+((y*8*32)+y2)]&240;                 
+                    p2=p2>>4;             
+                    if(p1==0){p1=1;}
+                    if(p2==0){p2=1;}
+                    g_map[65536+x+y*32*8+y2*32]=byte(p2);
+                    g_map[65536+MX*MY*8+x+y*32*8+y2*32]=byte(p1);
+                }
+            }
+        }    
+    }
+    
+    if(machine==CPC){ // a studio?
+        import_program(fname);
+        message("Not|Working");
+    }    
+    
+    consistency();
+    refresh();
+    g_boxreconstruct=2;
+}
+
+void format_export(String fname)
+{
+    int val1, val2, val3;
+    int y, y2, yy, x, yp, xp, ad, valu, valu2, bri;
+
+    if (machine==PLUS4) {// botticelli hires
+        load_template("g.hires.prg");
+        set_head(0x02);
+        colorexport(40, 25, 65536, 5);//lumis
+        set_head(1026);
+        colorexport(40, 25, 65536, 4);//colors  
+        set_head(2050);
+        bitmapexport(40, 25);
+        export_program(fname);
+    }
+    
+    if (machine==PLUS4M) {// multi botticelli multicolor
+        load_template("m.multi.prg");
+        val2=getpluscolor(int(g_map[1]));
+        val1=getplusluminance(int(g_map[1]));
+        val3=val2*16+val1;
+        set_head(1025);
+        write_head(val3);
+        val2=getpluscolor(int(g_map[2]));
+        val1=getplusluminance(int(g_map[2]));
+        val3=val2*16+val1;
+        set_head(1024);
+        write_head(val3);
+        set_head(1026);
+        colorexport(40, 25, 65536, 6);//colors
+        set_head(2);
+        colorexport(40, 25, 65536, 7);//lumis 
+        set_head(2050);
+        bitmapexport(40, 25);
+        export_program(fname);
+    }
+    
+    if (machine==C64) {
+        load_template("hires.art");
+        set_head(2);
+        bitmapexport(40, 25);
+        set_head(0x1f42);
+        colorexport(40, 25, 65536, 0);
+        set_head(0x232a);
+        write_head(int(g_map[0]));
+        export_program(fname);
+    }
+    
+    if (machine==C64M) {
+        if(fname.indexOf(".kla")==-1){
+          load_template("multic.ocp");
+          set_head(2);
+          bitmapexport(40, 25);
+          set_head(0x1f42);
+          colorexport(40, 25, 65536, 1);
+          set_head(0x233a);
+          colorexport(40, 25, 65536+2000, 2);
+          set_head(0x232a);
+          write_head(int(g_map[0]));
+          set_head(0x232b);
+          write_head(int(g_map[1]));
+          export_program(fname);
+        }
+        
+        //koala
+        
+        if(fname.indexOf(".kla")>=0){
+          load_template("multic.kla");
+          set_head(2);
+          bitmapexport(40,25);
+          set_head(0x1f42);
+          colorexport(40,25,65536,1);
+          set_head(0x232a);
+          colorexport(40,25,65536+2000,2);
+          set_head(0x2712);
+          write_head(int(g_map[1]&15));
+          export_program(fname);
+        }
+        
+      }
+
+    if (machine==MSX) {
+        load_template("msx-screen2.sc2");
+        set_head(7); 
+        bitmapexport(32, 24);
+        set_head(7+(32*24*8)+768+1280);
+        colorexport(32, 24, 65536, 3);//there's an exception for msx-style
+        export_program(fname);
+    } 
+
+    if (machine==SPECTRUM)
+    {
+        load_template("zx-screen.scr");
+        set_head(0);
+        for (y=0; y<=2; y++) {
+            for (y2=0; y2<=7; y2++) {
+                for (yy=0; yy<=7; yy++) {
+                    for (x=0; x<=31; x++) {
+                        yp=y*64+yy*8+y2;
+                        ad=1024+yp*256+x*8;
+                        valu=g_map[ad+0]*128+g_map[ad+1]*64+g_map[ad+2]*32+g_map[ad+3]*16+g_map[ad+4]*8+g_map[ad+5]*4+g_map[ad+6]*2+g_map[ad+7]*1;  
+                        write_head(int(valu));
+                    }
+                }
+            }
+        }
+        for (y=0; y<=23; y++) {
+            for (x=0; x<=31; x++) {
+                ad=65536+x+y*256;
+                valu=int(g_map[ad]);
+                valu2=int(g_map[ad+MX*MY*8]);
+                bri=0;
+                if (valu>=8) {
+                    bri=1;
+                    valu=valu-8;
+                    valu2=valu2-8;
+                    if (valu2<=0) {
+                        valu2=0;
+                    }
+                }
+                if (bri==1) {
+                    valu=valu+64;
+                }
+                write_head(int(valu+valu2*8));
+            }
+        }
+        export_program(fname);
+    }
+}
+
+void machine_export(String fname, int sorsa)
+{
+    int yy, xx, x, y2, y, checksum;
+    int xp, yp;
+    int valu, valu2;
+    int val1, val2, val3;
+    int ad, by;
+    int bri, skyp;
+    g_sorsaa=sorsa;//aargh another global
+
+    if (sorsa==1) {
+        exwriter=createWriter(fname);
+    }
+
+    // any common text headers
+    by=0;
+    skyp=0;
+    outputter(";machine="+str(machine)+" ("+g_name+")", true);
+
+    if (machine==C64) { //C64 HIRES
+
+        load_template("c64show.prg");
+        set_head(0X0227);
+        bitmapexport(40, 25);
+        set_head(0X2167);
+        write_head(g_map[0]);//=border
+        set_head(0X2168);
+        write_head(g_map[1]);//=background mutta ei tarvita
+        set_head(0X2169);
+        outputter("; The following two first values are border and background", true);
+        colorexport(40, 25, 65536, 0);
+        export_program(fname);
+
+        //c64show.prg
+        //offsets
+        //0x0227->bitmappi (40x25 x 8 bytee)
+        //0x2167:borderi väri
+        //0x2169->värikartta (40x25 bytee, nyppelit foreg/backg)
+    }
+
+    if (machine==C64M) { //C64 MULTICOLOR
+
+        load_template("c64mshow.prg");
+        set_head(0x0239);
+        bitmapexport(40, 25);
+
+        // first color information
+        set_head(0x2179);
+        write_head(g_map[0]);
+        set_head(0x217A);
+        write_head(g_map[1]);
+        set_head(0x217B);
+        outputter("; The following two first values are border and background", true);
+        colorexport(40, 25, 65536, 1);
+
+        // second color information
+        set_head(0x2563);
+        outputter("; The following goes to $D800 onwards", true);  
+        colorexport(40, 25, 65536+2000, 2);
+        export_program(fname);
+
+        //c64 multicolor
+        //offsets
+        //0x0239->bitmappi (40x25 x 8 bytee)
+        //0x2179:borderi väri
+        //0x217A:bäkkis väri
+        //0x217B->värikartta 1 (40x25 bytee, nyppelit foreg/backg ilmeisesti)
+        //0x2563->värikartta 2 (40x25 bytee, nyppeli 3-väri nepan osoitteessa $d800-)
+    }
+
+    if (machine==PLUS4M) { //PLUS4 MULTICOLOR
+        load_template("showpfourm.prg");
+        outputter("  .global _bitmap", true);
+        outputter("  .global _color1", true);
+        outputter("  .global _color2", true);
+        outputter("  .global _border", true);
+        outputter("  .global _back1", true);
+        outputter("  .global _back2", true);
+        outputter("_bitmap:", true);
+        set_head(0x013e);
+        bitmapexport(40, 25);
+        outputter("_border:", true);
+        val1=getpluscolor(int(g_map[0]));
+        val2=getplusluminance(int(g_map[0]));
+        val3=val2*16+val1;
+        set_head(0x207e);
+        write_head(val3);
+        outputter("  .byte "+val3, true);
+        outputter("_back1:", true);
+        val1=getpluscolor(int(g_map[1]));
+        val2=getplusluminance(int(g_map[1]));
+        val3=val2*16+val1;
+        set_head(0x207f);
+        write_head(val3);
+        outputter("  .byte "+val3, true);
+        outputter("_back2:", true);
+        val1=getpluscolor(int(g_map[2]));
+        val2=getplusluminance(int(g_map[2]));
+        val3=val2*16+val1;
+        set_head(0x2080);
+        write_head(val3);
+        outputter("  .byte "+val3, true);
+        outputter("_color1:", true);
+        set_head(0x2081);
+        colorexport(40, 25, 65536, 6);
+        outputter("_color2:", true);
+        set_head(0x2469);
+        colorexport(40, 25, 65536, 7);
+        export_program(fname);
+        //plus4 multic
+        //0x013e bitmap (40 x 25 x 8)
+        //0x207e border
+        //0x207f background 1
+        //0x2080 background 2
+        //0x2081 colors (40 x 25)
+        //0x2469 luminance (40 x 25)
+    }
+
+    if (machine==PLUS4) {// Plus 4 hires
+        load_template("showpfour.prg");
+        outputter("  .global _bitmap", true);
+        outputter("  .global _color", true);
+        outputter("  .global _lumi", true);
+        outputter("  .global _border", true);
+        outputter("_bitmap:", true);
+        set_head(0x0137);
+        bitmapexport(40, 25);
+        val1=getpluscolor(int(g_map[0]));
+        val2=getplusluminance(int(g_map[0]));
+        val3=val2*16+val1;
+        set_head(0x2077);
+        write_head(val3); //border
+
+        set_head(0x2078);
+        colorexport(40, 25, 65536, 4);//colors
+        set_head(0x2460);
+        colorexport(40, 25, 65536, 5);//lumis
+        export_program(fname);
+        //plus4 hires
+        //0x0137   bitmap (40 x 25 x 8)
+        //0x2077   borderi
+        //0x2078   colors (40 x 25)
+        //0x2460   luminance (40 x 25)
+    }
+
+    if (machine==MSX) { // MSX
+        load_template("msxshow.com");
+        set_head(0x00f9);
+        outputter(char(9)+".globl _nimi1,_nimi2", true);
+        outputter(char(9)+".area _CODE", true);
+        outputter("_nimi1:", true);
+        bitmapexport(32, 24);
+        set_head(0x18f9);
+        //write_head(g_map[1]); //backg
+        //outputter("; The first following value is background", true);
+        outputter("_nimi2:", true);
+        colorexport(32, 24, 65536, 3);//there's an exception for msx-style
+        export_program(fname);
+        //msx comm
+        //0x00f9 bitmap (32x24 x 8 bytes)
+        //0x18f9 background color
+        //0x18fa colors (32*24 bytes)
+    }
+
+    if (machine==SPECTRUM) { // ZX Spectrum
+
+        //would need some cleaning up
+
+        //  outputter("  .area  _DATA",true);
+        //  outputter("  .globl _taustakuva",true);
+        //  outputter("",true);
+        //  outputter("_taustakuva:",true);
+        load_template("specshow.tap");
+        int stad;
+
+        checksum=0xc9;
+        for (y=0x1d24; y<=0x1d3d; y++) { //1d3e
+            checksum=checksum^int(g_template[y]);
+        }
+        //TAP requires fiddling with the checksum
+        //println("Checksum:"+hex(checksum,2));
+        set_head(0x0223);
+        outputter(".byte "+(str(g_map[0]))+" ;border", true);
+        write_head(int(g_map[0]));
+        checksum=checksum^int(g_map[0]);
+        for (y=0; y<=2; y++) {
+            for (y2=0; y2<=7; y2++) {
+                for (yy=0; yy<=7; yy++) {
+
+                    outputter(".byte ", false);
+                    for (x=0; x<=31; x++) {
+                        yp=y*64+yy*8+y2;
+                        xp=x;
+                        ad=1024+yp*256+x*8;
+                        valu=g_map[ad+0]*128+g_map[ad+1]*64+g_map[ad+2]*32+g_map[ad+3]*16+g_map[ad+4]*8+g_map[ad+5]*4+g_map[ad+6]*2+g_map[ad+7]*1;
+                        outputter(str(int(valu)), false);
+                        by++;
+                        write_head(int(valu));
+                        checksum=checksum^int(valu);
+                        if (x<=30) {
+                            outputter(",", false);
+                        }
+                    }
+                    outputter("", true);
+                }
+            }
+        }
+
+        outputter("; attributes", true);
+        for (y=0; y<=23; y++) {
+            outputter(".byte ", false);
+            for (x=0; x<=31; x++) {
+                ad=65536+x+y*256;
+                valu=int(g_map[ad]);
+                valu2=int(g_map[ad+MX*MY*8]);
+                bri=0;
+                if (valu>=8) {
+                    bri=1;
+                    valu=valu-8;
+                    valu2=valu2-8;
+                    if (valu2<=0) {
+                        valu2=0;
+                    }
+                }
+                if (bri==1) {
+                    valu=valu+64;
+                }
+                outputter(str(valu+valu2*8), false);
+                by++;
+                write_head(int(valu+valu2*8));
+                checksum=checksum^int(valu+valu2*8);
+                if (x<=30) {
+                    outputter(",", false);
+                }
+            }
+            outputter("", true);
+        }
+        //println("checksum:"+hex(checksum,2));
+        set_head(0x1d3e);
+        write_head(int(checksum));
+        export_program(fname);
+    }
+
+    if (machine==CPC) {
+        load_template("cpc-mode0.bin");
+
+        set_head(69);//bitmap offset
+        bitmapexport_cpc(160, 200);
+        set_head(16453);
+        outputter(";palette", true);
+        outputter(".byte ", false);
+        for (int i=0; i<g_maxcolors; i++) {//fixed # of palette entries, just trying to be generic
+            val1=int(g_g[i]/(256/g_palsteps));
+            val2=int(g_r[i]/(256/g_palsteps));
+            val3=int(g_b[i]/(256/g_palsteps));
+            write_head(val1*9+val2*3+val3);
+            outputter(str(val1*9+val2*3+val3), false);
+            if (i<g_maxcolors-1) {
+                outputter(",", false);
+            }
+        }
+        outputter("", true);
+        outputter(";border", true);
+        outputter(".byte ", false);  
+        set_head(16469);
+        valu=int(g_map[0]);
+        val1=int(g_g[valu]/(256/g_palsteps));
+        val2=int(g_r[valu]/(256/g_palsteps));
+        val3=int(g_b[valu]/(256/g_palsteps));
+        write_head(val1*9+val2*3+val3);
+        outputter(str(val1*9+val2*3+val3), false);
+        //cpc
+        //69    bitmap 16384 bytes
+        //16453 palette 16 bytes (0..26)
+        //16469 border color (0..26)
+        export_program(fname);
+    }
+
+    // any common lead-outs
+
+    if (sorsa==1) {
+        exwriter.flush();
+        exwriter.close();
+    }
+}
+
+void bitmapexport_cpc(int xwid, int yy)
+{
+    int x, y, ad, val1, val2, y2;
+    int pix0b0, pix0b1, pix0b2, pix0b3;
+    int pix1b0, pix1b1, pix1b2, pix1b3;
+    int pp;
+    pp=0;
+    outputter(";bitmap", true);
+    for (y2=0; y2<=7; y2++) {
+        for (y=0; y<25; y++) {
+            outputter("  .byte ", false); 
+            for (x=0; x<xwid/2; x++) {
+                ad=1024+(y*8)*X+(y2*X)+x*4;
+ 
+                val1=int(g_map[ad]);
+                pix0b0=0;pix0b1=0;pix0b2=0;pix0b3=0;
+                if ((val1&1)!=0) pix0b0=1;
+                if ((val1&2)!=0) pix0b1=1;
+                if ((val1&4)!=0) pix0b2=1;
+                if ((val1&8)!=0) pix0b3=1;
+
+                val1=int(g_map[ad+2]);
+
+                pix1b0=0;pix1b1=0;pix1b2=0;pix1b3=0;
+                if ((val1&1)!=0) pix1b0=1;
+                if ((val1&2)!=0) pix1b1=1;
+                if ((val1&4)!=0) pix1b2=1;
+                if ((val1&8)!=0) pix1b3=1;
+                
+                val2=pix1b3+pix0b3*2+pix1b1*4+pix0b1*8+pix1b2*16+pix0b2*32+pix1b0*64+pix0b0*128;
+                outputter(str(int(val2)), false);
+                write_head(val2);
+                pp++;
+                if (x<xwid/2-1) {
+                    outputter(",", false);
+                }
+            }
+            outputter("", true);
+        }
+        outputter("  .byte ", false); 
+        for (int j=0; j<=47; j++) {
+            write_head(0);
+            outputter(str(int(0)), false);
+            pp++;
+            if (j<47) {
+                outputter(",", false);
+            }
+        }
+        outputter("", true);
+    }
+    outputter("", true);
+}
+
+void bitmapexport(int xx, int yy)
+{
+    int xwid, ywid, x, y, y2, value, ad, linep;
+    linep=0;
+    xwid=xx*8;
+    ywid=yy*8;
+    //outputter("unsigned char img[]={",false);
+
+    for (y=0; y<yy; y++) {
+        for (x=0; x<xx; x++) {
+//            outputter("  .byte ", false);
+           outputter(char(9)+".db ",false); 
+            for (y2=0; y2<=7; y2++) {
+                ad=1024+y*(xwid*8)+(y2*xwid)+x*8;
+                value=g_map[ad+0]*128+g_map[ad+1]*64+g_map[ad+2]*32+g_map[ad+3]*16+g_map[ad+4]*8+g_map[ad+5]*4+g_map[ad+6]*2+g_map[ad+7]*1;       
+                outputter(str(int(value)), false);
+                write_head(int(value));
+                if (y2<=6) {
+                    outputter(",", false);
+                }
+            }  
+            outputter("", true);
+            linep++;
+            if (linep==xx) {
+                linep=0;
+                outputter("", true);
+            }
+        }
+    }
+    outputter("", true);
+}
+
+int convertlumi(int l,int f)
+{
+    int res=0;
+    if(f==0)return 0;
+    if(l==0)res=0+f;
+    if(l==1)res=15+f;
+    if(l==2)res=30+f;
+    if(l==3)res=45+f;
+    if(l==4)res=60+f;
+    if(l==5)res=75+f;
+    if(l==6)res=90+f;
+    if(l==7)res=105+f;
+    return res;
+}
+
+int getplusluminance(int c)
+{
+    int res=0;
+    if (c==0)res=0;
+    if (c>=1&&c<=15)res=0;
+    if (c>=16&&c<=30)res=1;
+    if (c>=31&&c<=45)res=2;
+    if (c>=46&&c<=60)res=3;
+    if (c>=61&&c<=75)res=4;
+    if (c>=76&&c<=90)res=5;
+    if (c>=91&&c<=105)res=6;
+    if (c>=106&&c<=120)res=7;
+    return res;
+}
+
+int getpluscolor(int c)
+{
+    int res=0;
+    if (c==0)res=0;
+    if (c>=1&&c<=15)res=c;
+    if (c>=16&&c<=30)res=c-15;
+    if (c>=31&&c<=45)res=c-30;
+    if (c>=46&&c<=60)res=c-45;
+    if (c>=61&&c<=75)res=c-60;
+    if (c>=76&&c<=90)res=c-75;
+    if (c>=91&&c<=105)res=c-90;
+    if (c>=106&&c<=120)res=c-105;
+    return res;
+}
+
+void colorexport(int xx, int yy, int source, int param)
+{
+    int x, y, y2, valu, valu2, kalu, muista, ad, linep, xwid, ywid, xoor, yline, myrpsi;
+    xwid=xx*8;
+    ywid=yy*8;
+    valu=0;
+    valu2=0;
+    myrpsi=0;
+    xoor=xx;
+    if (param==0||param==4||param==5) {
+        xoor=xx*8;
+    }
+    if (machine==MSX) {
+        myrpsi=7;
+    }
+    if (param<2) {
+        outputter("colora:", true);
+    }
+    if (param==2) {
+        outputter("colorb:", true);
+    }     
+    if (param<2) {
+        outputter("  .byte "+int(g_map[0])+","+int(g_map[1]), true);
+    }
+    if (param==3) {
+     //   outputter("color:", true);
+     //   outputter("  .byte ", false);
+      //  outputter(g_map[0]+" ", true);
+        xoor=xx*8;
+    }
+    if (param==4) {
+        outputter("_border:", true);
+        outputter("  .byte ", false);
+        kalu=getpluscolor(int(g_map[0]));
+        valu2=getplusluminance(int(g_map[0]));
+        valu=valu2*16+kalu;
+        outputter(valu+" ", true);
+        outputter("_color:", true);
+    }
+    if (param==5) {
+        outputter("_lumi:", true);
+    }
+    for (y=0; y<yy; y++) {
+        //outputter("  .byte ", false);
+        outputter(char(9)+".db ", false);
+        for (x=0; x<xx; x++) {
+            for (yline=0; yline<=myrpsi; yline++) {
+                ad=source+x+y*xoor+yline*xx;
+                if (param==0) {
+                    valu=int(g_map[ad]);
+                    valu2=int(g_map[ad+MX*MY*8]);
+                }
+                if (param==1) {
+                    valu2=int(g_map[ad]);
+                    valu=int(g_map[ad+1000]);
+                }   
+                if (param==2) {
+                    valu2=int(g_map[ad]);
+                    valu=0;
+                }  
+                if (param==3) {
+                    valu=int(g_map[ad]);
+                    valu2=int(g_map[ad+MX*MY*8]);
+                }
+
+                if (param==4) {//plus4 colortable
+                    kalu=int(g_map[ad]);
+                    valu=getpluscolor(kalu);
+                    kalu=int(g_map[ad+MX*MY*8]);
+                    valu2=getpluscolor(kalu);
+                }        
+                
+                if (param==5) {//plus4 lumitable
+                    kalu=int(g_map[ad]);
+                    valu2=getplusluminance(kalu);
+                    kalu=int(g_map[ad+MX*MY*8]);
+                    valu=getplusluminance(kalu);
+                }
+                
+                if (param==6) {//plus4 multic1
+                    valu2=getpluscolor(int(g_map[ad]));
+                    valu=getpluscolor(int(g_map[ad+1000]));
+                }
+                
+                if (param==7) {//plus4 multic2
+                    valu=getplusluminance(int(g_map[ad]));
+                    valu2=getplusluminance(int(g_map[ad+1000]));
+                }
+                
+                outputter(str(valu*16+valu2), false);
+                write_head(int(valu*16+valu2));                           
+                if (x<(xx-1)||yline<myrpsi) {
+                    outputter(",", false);
+                }
+            }
+        }
+        outputter("", true);
+    }
+    outputter("", true);
+}
+
+void load_template(String fname)
+{
+    g_template=loadBytes("templates/"+fname);
+}
+
+void import_program(String fname)
+{
+    g_template=loadBytes(fname);
+}
+
+void set_head(int pos)
+{
+    g_headpos=pos;
+}
+
+void write_head(int bb)
+{
+    g_template[g_headpos]=byte(bb);
+    g_headpos++;
+}
+
+void export_program(String fname)
+{
+    if (g_sorsaa==1) {
+        return;
+    }
+    saveBytes(fname, g_template);
+}
+
+void outputter(String oput, boolean eol)
+{
+    if (g_sorsaa==0)return;
+    if (eol==false)exwriter.print(oput);
+    if (eol==true)exwriter.println(oput);
+}
+
+
+void import_image(String name)
+{
+    PImage image;
+    image = loadImage(name);
+    int balx, baly, xx, yy, x2, y2, rr, gg, bb, avg, molox, i, j, target;
+    int cx, cy;
+    int aas, bbs, swap, idefix, avx, avy;
+    int[] pixut= new int[260];
+    int[] idx=new int[260];
+    int[] histog=new int[8192];
+    float ww, hh, fld, compa, fx2, fy2;
+    color c;
+    int xcolors, limitter, vertti, erkki;
+    int rh,gh,bh;
+
+    xcolors=g_maxcolors;
+    vertti=8;
+    erkki=1;
+    limitter=2;
+    if (g_britemode==1) {
+        xcolors=8;
+    }
+    if (g_attrimode==0) {
+        vertti=1;
+        erkki=8;
+    }
+    if (g_multic==1) {
+        limitter=4;
+    }//because zero color can be anywhere?
+    if (g_multic==2) {
+        limitter=16;
+    }
+    molox=1;
+    command('O');//special clear screen
+    if (g_multic==1||g_hzoomer==2) {
+        molox=2;
+    }
+    ww=image.width;
+    hh=image.height;
+    if (ww<=16||hh<=16) {
+        return;
+    }
+    balx=int(ww/X);
+    balx=balx*molox;
+    baly=int(hh/Y);
+    if (balx<1) {
+        balx=1;
+    }
+    if (baly<1) {
+        baly=1;
+    }
+
+    if(g_palsteps>0){
+      for(i=0;i<g_maxcolors;i++){
+        makecolor(i,0,0,0);
+      }
+        
+      int maxhis,palls,psteps;
+      psteps=int(g_palsteps-1);
+      maxhis=0;palls=int(255/psteps);
+        for (cy=0; cy<MY*erkki; cy++) {
+        for (cx=0; cx<MX; cx++) {
+            for (yy=cy*vertti; yy<=cy*vertti+vertti-1; yy++) {
+                for (xx=cx*8; xx<=cx*8+7; xx=xx+molox) {
+                    fx2=(ww/X)*xx;
+                    fy2=(hh/Y)*yy;
+                    x2=int(fx2);
+                    y2=int(fy2);
+                    rr=0;
+                    gg=0;
+                    bb=0;
+                    avg=0;
+
+                    for (avy=0; avy<baly; avy++) {
+                        for (avx=0; avx<balx; avx++) {
+                            c=image.get(x2+avx, y2+avy);
+                            rr=rr+int(red(c));
+                            gg=gg+int(green(c));
+                            bb=bb+int(blue(c));
+                            avg++;
+                        }
+                    }
+                    rh=rr/(avg);
+                    gh=gg/(avg);
+                    bh=bb/(avg);
+                    rh=int(rh)/palls;
+                    gh=int(gh)/palls;
+                    bh=int(bh)/palls;
+                    histog[int(rh*(g_palsteps*g_palsteps)+gh*(g_palsteps)+bh)]++;
+                    if(histog[int(rh*(g_palsteps*g_palsteps)+gh*(g_palsteps)+bh)]>maxhis){maxhis=histog[int(rh*(g_palsteps*g_palsteps)+gh*(g_palsteps)+bh)];}
+                }
+              }
+            }
+          }
+    
+      int step;
+      step=0;
+      for(j=maxhis;j>0;j--){
+        for(i=0;i<=4096;i++){
+           if(histog[i]==j){
+              rh=i/int(g_palsteps*g_palsteps);
+              gh=i-int(rh*(g_palsteps*g_palsteps));gh=gh/int(g_palsteps);
+              bh=i-int(rh*(g_palsteps*g_palsteps));bh=bh-int(gh*g_palsteps);
+              rh=rh*int(palls);
+              gh=gh*int(palls);
+              bh=bh*int(palls);
+              if(step<g_maxcolors){
+                makecolor(step,rh,gh,bh);step++;
+              }
+            }
+          }
+        }
+
+    }
+                            
+    for (cy=0; cy<MY*erkki; cy++) {
+        for (cx=0; cx<MX; cx++) {
+            for (i=0; i<xcolors; i++) {
+                pixut[i]=0;
+                idx[i]=i;
+            }  
+            for (yy=cy*vertti; yy<=cy*vertti+vertti-1; yy++) {
+                for (xx=cx*8; xx<=cx*8+7; xx=xx+molox) {
+                    fx2=(ww/X)*xx;
+                    fy2=(hh/Y)*yy;
+                    x2=int(fx2);
+                    y2=int(fy2);
+                    rr=0;
+                    gg=0;
+                    bb=0;
+                    avg=0;
+                    for (avy=0; avy<baly; avy++) {
+                        for (avx=0; avx<balx; avx++) {
+                            c=image.get(x2+avx, y2+avy);
+                            rr=rr+int(red(c));
+                            gg=gg+int(green(c));
+                            bb=bb+int(blue(c));
+                            avg++;
+                        }
+                    }
+                    rr=rr/(avg);
+                    gg=gg/(avg);
+                    bb=bb/(avg);
+                    g_farge=0;
+                    target=-1;
+                    compa=9999;
+                    for (i=0; i<xcolors; i++) {
+                        fld=dist(rr, gg, bb, g_r[i], g_g[i], g_b[i]);
+                        if (fld<compa) {
+                            compa=fld;
+                            target=i;
+                        }
+                    }
+
+                    g_farge=target;
+                    pixut[target]++;//histogramming
+                }
+            }
+
+            for (aas=0; aas<xcolors; aas++) {
+                for (bbs=0; bbs<=aas; bbs++) {
+                    if (pixut[aas]>pixut[bbs]) {
+                        swap=pixut[aas];
+                        pixut[aas]=pixut[bbs];
+                        pixut[bbs]=swap;
+                        swap=idx[aas];
+                        idx[aas]=idx[bbs];
+                        idx[bbs]=swap;
+                    }
+                }
+            }
+
+            for (idefix=0; idefix<limitter; idefix++) {
+                i=idx[idefix];
+                for (yy=cy*vertti; yy<=cy*vertti+vertti-1; yy++) {
+                    for (xx=cx*8; xx<=cx*8+7; xx=xx+molox) {
+
+                        fx2=(ww/X)*xx;
+                        fy2=(hh/Y)*yy;
+                        x2=int(fx2);
+                        y2=int(fy2);
+
+                        rr=0;
+                        gg=0;
+                        bb=0;
+                        avg=0;
+                        for (avy=0; avy<baly; avy++) {
+                            for (avx=0; avx<balx; avx++) {
+                                c=image.get(x2+avx, y2+avy);
+                                rr=rr+int(red(c));
+                                gg=gg+int(green(c));
+                                bb=bb+int(blue(c));
+                                avg++;
+                            }
+                        }
+                        rr=rr/(avg);
+                        gg=gg/(avg);
+                        bb=bb/(avg);
+                        g_farge=0;
+                        target=-1;
+                        compa=9999;
+                        for (j=0; j<limitter; j++) {
+                            fld=dist(rr, gg, bb, g_r[idx[j]], g_g[idx[j]], g_b[idx[j]]);
+                            if (fld<compa) {
+                                compa=fld;
+                                target=idx[j];
+                            }
+                        }
+                        if (i==target) {
+
+                            g_farge=target;
+                            makepoint(xx, yy);
+                        }
+                    }
+                }
+                if (idefix==0) {
+
+                    for (yy=cy*vertti; yy<=cy*vertti+vertti-1; yy++) {
+                        for (xx=cx*8; xx<=cx*8+7; xx=xx+molox) {
+                            g_farge=idx[0];
+                            makepoint(xx, yy);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+}
+
+void export_image(String name)
+{
+    //output the visible graphics as image
+    //with border
+    //processing style
+    int xx, yy, f, x2;
+    color c;
+    for (xx=0; xx<output.width; xx++) {
+        for (yy=0; yy<output.width; yy++) {
+            c=color(g_r[259], g_g[259], g_b[259]);
+            output.set(xx, yy, c);
+        }
+    }
+
+    for (xx=0; xx<X; xx++) {
+        for (yy=0; yy<Y; yy++) {
+            x2=xx; 
+            f=getabsa(x2, yy, 0);
+            if (g_multic==1||g_hzoomer==2) {
+                x2=xx/2;
+                x2=x2*2; 
+                f=getmultic(x2, yy, 0);
+            }
+            if (machine==MSX) {
+                if (f==0) {
+                    f=g_map[1];
+                }
+            }
+            c=color(g_r[f], g_g[f], g_b[f]);
+            for (int vertti=0; vertti<=g_omag; vertti++) {
+                for (int mortti=0; mortti<=g_omag; mortti++) {
+                    output.set((g_bordh*g_omag)/2+xx*g_omag+mortti, (g_bordv*g_omag)/2+yy*g_omag+vertti, c);
+                }
+            }
+        }
+    }
+    output.save(name);
+}
+
+void export_image_sans_border(String name)
+{
+    //output the visible graphics as image
+    //processing style
+    //without border
+    int xx, yy, f, x2;
+    color c;
+
+    for (xx=0; xx<outputsans.width; xx++) {
+        for (yy=0; yy<outputsans.width; yy++) {
+            c=color(g_r[259], g_g[259], g_b[259]);
+            outputsans.set(xx, yy, c);
+        }
+    }
+
+    for (xx=0; xx<X; xx++) {
+        for (yy=0; yy<Y; yy++) {
+            x2=xx;
+            f=getabsa(x2, yy, 0);
+            if (g_multic==1||g_hzoomer==2) {
+                x2=xx/2;
+                x2=x2*2;  
+                f=getmultic(x2, yy, 0);
+            }
+
+            if (machine==MSX) {
+                if (f==0) {
+                    f=g_map[1];
+                }
+            }
+            c=color(g_r[f], g_g[f], g_b[f]);
+            for (int vertti=0; vertti<=g_omag; vertti++) {
+                for (int mortti=0; mortti<=g_omag; mortti++) {
+                    outputsans.set(xx*g_omag+mortti, yy*g_omag+vertti, c);
+                }
+            }
+        }
+    }
+    outputsans.save(name);
+}
+
+void make_c64_palette()
+{
+    // Pepto's murky C64 palette: http://www.pepto.de/projects/colorvic
+    int rgb[]={#000000,#FFFFFF,#68372B,#70A4B2,#6F3D86,#588D43,#352879,#B8C76F,
+                     #6F4F25,#433900,#9A6759,#444444,#6C6C6C,#9AD284,#6C5EB5,#959595};
+    for(int i=0;i<g_maxcolors;i++){
+      rgb[i]=rgb[i]&0xffffff;
+      g_grids[i]=rgb[i]+#282828;
+      makecolor(i,rgb[i]>>16,(rgb[i]&#00FF00)>>8,rgb[i]&#0000FF);
+    }
+    g_grids[1]=#d0d0d0;g_gridmode=NEW;
+    g_map[13]=byte(C64);
+}
+
+void make_plus4_palette()
+{
+  int rgb[]={
+    #000000,#2C2C2C,#621307,#00424C,#510378,#004E00,#27188E,#303E00,#582100,#463000,#244400,#630448,#004E0C,#0E2784,#33118E,#184800,
+    #3B3B3B,#702419,#00505A,#601685,#125D00,#36289B,#3F4C00,#663100,#553F00,#345200,#711656,#005C1D,#1F3691,#42229B,#285700,
+    #424242,#772C21,#055861,#661E8C,#1B6400,#3E30A2,#475400,#6D3900,#5C4700,#3B5900,#771F5D,#046325,#273E98,#492AA1,#305E00,
+    #515151,#843B31,#17656F,#742E99,#2B7100,#4C3FAF,#556200,#7A4709,#6A5500,#4A6700,#852F6B,#177135,#364CA5,#5739AE,#3F6B00,
+    #7A7A7A,#AC665C,#468E97,#9C5AC0,#57992E,#766AD5,#7E8A13,#A2713A,#927E20,#748F14,#AC5A93,#459960,#6276CB,#8064D4,#6A9419,
+    #959595,#C58178,#62A8B1,#B675D9,#73B34C,#9185ED,#99A433,#BB8C57,#AC993E,#8FAA34,#C676AD,#62B37B,#7D91E4,#9B80ED,#85AE38,
+    #AFAFAF,#DE9B93,#7DC2CA,#CF90F2,#8DCD68,#AB9FFF,#B3BE51,#D5A673,#C6B35B,#A9C351,#DF91C7,#7DCC96,#97ABFD,#B59AFF,#9FC755,
+    #E1E1E1,#FFCFC6,#B2F4FC,#FFC4FF,#C1FE9D,#DDD2FF,#E5F088,#FFD9A8,#F7E591,#DBF588,#FFC4F9,#B1FEC9,#CBDDFF,#E7CDFF,#D2F98C
+  };
+    for(int i=0;i<g_maxcolors;i++){
+      rgb[i]=rgb[i]&0xffffff;
+      makecolor(i,rgb[i]>>16,(rgb[i]&#00FF00)>>8,rgb[i]&#0000FF);
+    }
+}
+
+void make_msx_palette()
+{
+    int rgb[]={
+    #000000,
+    #000000,
+    #3EB849,
+    #74D07D,
+    #5955E0,
+    #8076F1,
+    #B95E51,
+    #65DBEF,
+    #DB6559,
+    #FF897D,
+    #CCC35E,
+    #DED087,
+    #3AA241,
+    #B766B5,
+    #CCCCCC,
+    #FFFFFF};
+
+    for(int i=0;i<g_maxcolors;i++){
+      rgb[i]=rgb[i]&0xffffff;
+      g_grids[i]=rgb[i]+#1f1f1f;
+      makecolor(i,(rgb[i]>>16),(rgb[i]&#00FF00)>>8,rgb[i]&#0000FF);
+    }
+    g_grids[5]=#9f95Ff;
+    g_grids[7]=#84faEF;
+    g_grids[9]=#ffa99d;
+    g_grids[15]=#d8d8d8;g_gridmode=NEW;
+}
+
+void make_spectrum_palette()
+{
+  int rgb[]={#000000,#0000C0,#C00000,#C000C0,#00C000,#00C0C0,#C0C000,#C0C0C0,
+              #000000,#0000FF,#FF0000,#FF00FF,#00FF00,#00FFFF,#FFFF00,#FFFFFF};
+              
+  g_grids[9]=#0000d8;
+  g_grids[10]=#d80000;
+  g_grids[11]=#d800d8;
+  g_grids[12]=#00d800;
+  g_grids[13]=#00d8d8;
+  g_grids[14]=#d8d800;
+  g_grids[15]=#d8d8d8;
+    for(int i=0;i<g_maxcolors;i++){
+      rgb[i]=rgb[i]&0xffffff;
+      if(i<=8){g_grids[i]=rgb[i]+#282828;}
+      makecolor(i,(rgb[i]>>16),(rgb[i]&#00FF00)>>8,rgb[i]&#0000FF);
+    }
+    g_gridmode=NEW;
+}
+
+void set_machine(int m)
+{
+    machine=m;
+    g_expname="none";
+    g_map[3]=byte(machine);g_map[13]=byte(machine);
+    g_palsteps=0;g_farge=1;g_backg=0;g_britemode=0;
+    g_charlimit=0;g_hzoomer=1;g_backmode=0;
+    g_formatname="";
+    g_formatextension="";
+    g_maxcolors=16;X=320;Y=200;
+
+    if (machine==C64) {//c64 hires
+        g_expname="prg";
+        g_formatname="Art Studio";
+        g_formatextension="art";
+        g_name="c64";
+        g_attrimode=1;
+        g_map[1]=byte(255);
+        g_map[0]=6;
+        make_c64_palette();
+    }
+
+    if (machine==CPC) {  //Amstrad CPC mode 0
+        g_hzoomer=2;
+        g_palsteps=3;
+        g_name="cpc";g_expname="bin";
+        g_formatname="";g_formatextension="";
+        g_multic=2;
+        g_attrimode=0;
+        g_map[1]=byte(255);g_map[0]=1;
+
+        makecolor(0, 0, 0, 0);
+        makecolor(1, 0x0, 0x0, 0x80);
+        makecolor(2, 0x00, 0x00, 0xFF);
+        makecolor(3, 0x80, 0x00, 0x00);
+        makecolor(4, 0x80, 0x00, 0x80);
+        makecolor(5, 0x80, 0x00, 0xFF);
+        makecolor(6, 0xFF, 0x00, 0x00);
+        makecolor(7, 0xFF, 0x00, 0x80);
+        makecolor(8, 0xFF, 0x00, 0xFF);
+        makecolor(9, 0x00, 0x80, 0x00);
+        makecolor(10, 0x00, 0x80, 0x80);
+        makecolor(11, 0x00, 0x80, 0xFF);
+        makecolor(12, 0x80, 0x80, 0x00);
+        makecolor(13, 0x80, 0x80, 0x80);
+        makecolor(14, 0x80, 0x80, 0xFF);
+        makecolor(15, 0xFF, 0xFF, 0xFF);
+    }
+
+    if (machine==MSX) {    // MSX
+        g_name="msx";
+        g_expname="com";
+        g_formatname="Screen 2";
+        g_formatextension="sc2";
+        X=256;Y=192;
+        g_attrimode=0;
+        g_backmode=1;
+        g_farge=15;
+        g_backg=0; 
+
+        //TI99 variant
+        /*
+        makecolor(0,0,0,0);
+        makecolor(1,0,0,0);
+
+        makecolor(2,0x21,0xc8,0x42); //21c842 medgreen
+        makecolor(3,0x5e,0xdc,0x78);//5edc78 light green
+        makecolor(4,0x54,0x55,0xed);//5455ed dark blue
+        makecolor(5,0x7d,0x76,0xFc);//7d76fc light blue
+        
+        makecolor(6,0xd4,0x52,0x4d); //d4524d dark red
+        makecolor(7,0x42,0xeb,0xf5); //42ebf5 cyan
+        makecolor(8,0xfc,0x55,0x54); //fc5554 medium red
+        makecolor(9,0xff,0x79,0x78); //ff7978 light red
+        makecolor(10,0xd4,0xc1,0x54);// d4c154 dark yellow
+        makecolor(11,0xe6,0xce,0x80);// e6ce80 light yellow
+        makecolor(12,0x21,0xb0,0x3b);// 21b03b dark green
+        makecolor(13,0xc9,0x5b,0xba);// c95bba magenta
+        makecolor(14,0xCc,0xcc,0xCc);// gray 
+        makecolor(15,0xFF,0xFF,0xFF);
+        */
+        make_msx_palette();
+    }
+
+    if (machine==SPECTRUM) { // ZX Spectrum
+        g_name="spec";
+        g_expname="tap";
+        X=256;Y=192;
+        g_formatname="Screen$";g_formatextension="scr";
+        g_farge=7;
+        g_backg=0;
+        g_attrimode=1;
+        g_britemode=1;
+        g_map[0]=1;
+        g_map[1]=byte(255);
+        make_spectrum_palette();
+    }
+
+    if (machine==TIMEX) {    // timex sinclair
+        g_name="tmx";
+        X=256;Y=192;
+        g_farge=7;
+        g_backg=0;
+        g_attrimode=0;
+        g_britemode=1;
+        g_map[1]=byte(255);
+        make_spectrum_palette();
+    }
+
+    if (machine==JR200) {  // Panasonic JR200
+        g_name="jr200";
+        X=256;Y=192;
+        g_maxcolors=8;
+        g_farge=7;
+        g_backg=0;
+        g_attrimode=1;
+        g_map[1]=byte(255);
+        make_spectrum_palette();//cheating
+    }
+
+    if (machine==PLUS4M||machine==PLUS4) { // Commodore plus/4
+        g_backmode=1;
+        g_multic=1;    
+        g_name="plus4m";g_expname="prg";
+        g_attrimode=1;
+        g_maxcolors=121;
+        g_charlimit=2;
+        g_map[1]=0;g_map[2]=61;g_farge=61;
+        g_formatname="M.Botticelli";g_formatextension="prg";
+        if (machine==PLUS4) { // plus/4 hires
+            g_formatname="Botticelli";g_formatextension="prg";
+            g_multic=0;
+            g_backmode=0;
+            g_charlimit=0;
+            g_name="plus4";
+            g_attrimode=1;
+            g_map[1]=byte(255);
+        }
+        g_map[0]=6;
+        make_plus4_palette();
+    }
+
+    if (machine==C64M) {    //c64 multicolor
+        g_backmode=1;
+        g_charlimit=3;
+        g_multic=1;
+        g_name="c64m";g_expname="prg";
+        g_formatname="A. A. Studio";
+        g_formatextension="ocp";
+        g_attrimode=1;
+        g_map[1]=byte(0);  
+        g_map[0]=6;
+        make_c64_palette();
+    }
+
+    if (machine==AMIGA) {    //generic 16bit
+        g_backmode=1;
+        g_maxcolors=32;g_palsteps=16;
+        g_name="test";
+        g_multic=2;
+        g_attrimode=2;
+        g_map[1]=byte(0);
+        for (int z=0; z<g_maxcolors; z++) {
+            if (z<16) {
+                makecolor(z, z*17, z*17, z*17);
+            } else
+            {
+                makecolor(z, (z-16)*17, 0, 0);
+            }
+        }
+    }
+
+    if (machine==C64FLI) {    //c64 hires FLI = AFLI
+        g_expname="prg";
+        g_formatname="";g_formatextension="";
+        g_name="afli";
+        g_attrimode=0;
+        g_map[1]=byte(255);
+        g_map[0]=6;
+        make_c64_palette();
+    }
+
+    if (machine==C64FLIM) {    //C64 FLI multicolor 
+        g_hzoomer=2;
+        g_maxcolors=16;
+        g_name="fli";g_expname="";
+        g_formatname="";g_formatextension="";
+        g_multic=2;
+        g_attrimode=0;
+        g_map[1]=byte(255);
+        g_map[0]=6;
+        make_c64_palette();
+    }
+    
+    if (machine==FAKEX) {    // Fake 8-bit computer
+        g_name="fake";
+        g_expname="";
+        g_formatname="";
+        g_formatextension="";
+        X=320;Y=200;
+        g_multic=2;
+        g_attrimode=2;//g_palsteps=4;
+        g_farge=15;
+        g_backg=0; 
+        make_c64_palette();
+    }
+    
+    if (machine==PICO8) {    // Pico-8 fantasy console
+        g_name="pico8";
+        g_expname="";
+        g_formatname="";
+        g_formatextension="";
+        X=128;Y=128;
+        g_farge=15;
+        g_backg=0; 
+        g_multic=2;
+        g_attrimode=2;
+        makecolor(0, 0, 0, 0);
+        makecolor(1, 32, 51, 123);
+        makecolor(2, 126, 37, 83);
+        makecolor(3, 0, 144, 61);        
+        makecolor(4, 171, 82, 54);
+        makecolor(5, 52, 54, 53);
+        makecolor(6, 194, 195, 199);
+        makecolor(7, 255, 241, 232);      
+        makecolor(8, 255, 0, 77);
+        makecolor(9, 255, 155, 0);
+        makecolor(10, 255, 231, 39);
+        makecolor(11, 0, 226, 50);       
+        makecolor(12, 41, 173, 255);
+        makecolor(13, 132, 112, 169);
+        makecolor(14, 255, 119, 168);
+        makecolor(15, 255, 214, 197);
+    }
+        if (machine==UNIA) {    // Unia digital palette
+        g_name="unia";
+        g_expname="";
+        g_formatname="";
+        g_formatextension="";
+        X=256;Y=192;
+        g_farge=15;
+        g_backg=0; 
+        g_multic=2;
+        g_attrimode=2;
+        makecolor(0, 0, 0 , 0);
+        makecolor(1, 0xff, 0xff, 0xff);
+        makecolor(2, 0xff, 0xfd, 0x38);
+        makecolor(3, 0xff, 0xc5, 0x00);        
+        makecolor(4, 0xff, 0x00, 0x00);
+        makecolor(5, 0xff, 0x3c, 0xb4);
+        makecolor(6, 0xa0, 0x23, 0xbc);
+        makecolor(7, 0x1b, 0xa1, 0xfc);      
+        makecolor(8, 0xe1, 0xe1, 0xe1);
+        makecolor(9, 0xb9, 0x63, 0x00);
+        makecolor(10, 0xff, 0xaa, 0xbe);
+        makecolor(11, 0xd2, 0x9b, 0xd7);       
+        makecolor(12, 0xad, 0xad, 0xad);
+        makecolor(13, 0x00, 0xb7, 0xb7);
+        makecolor(14, 0x23, 0xaf, 0x32);
+        makecolor(15, 0x29, 0xf7, 0xa7);
+    }
+}
+
+void packer()
+{
+    int i, dat, amo;
+    int head;
+    amo=1;
+    i=0;
+    head=0;
+    //0=repeated element [n repetitions, element length, element]
+    //1-255=repeat byte [element]
+
+    while (i<=g_map.length-3) {
+        dat=int(g_map[i]);
+        while (int (g_map[i+1])==dat&&i<=g_map.length-3) {
+            if (int(g_map[i+1])==dat) {
+                if (amo<65535) {
+                    amo++;
+                    i++;
+                }
+                if (amo==65535) {
+                    //pask[head]=dat;pask[head+1]=255;
+                    println(dat+" x "+amo);
+                    head=head+3;
+                    amo=0;
+                }
+            }
+        }
+        println(dat+" x "+amo);
+        amo=0;
+        //  pask[head]=dat;pask[head+1]=amo;
+        head++;
+        head++;
+        head++;
+        i++;
+    }
+    println(head);
+
+    for (i=0; i<=g_map.length; i++) {
+    }
+    message("Packing|test|"+str(head));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java.pde	Tue Jul 03 20:56:55 2018 +0300
@@ -0,0 +1,126 @@
+
+// Pure Java UI elements, such as a file selector
+// Adapted from Marq's PETSCII editor
+// (this crap really makes me lose all my will to live, but it's needed now)
+
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+
+class Selector extends JPanel implements ActionListener
+{
+    int selection;
+    protected JButton b[];
+    
+    Selector(String s) // Split string into options
+    {
+        String splitz[]=splitTokens(s,",");
+        b=new JButton[splitz.length];
+        
+        setLayout(new GridLayout(splitz.length,1,1,1));
+        
+        for(int i=0;i<splitz.length;i++)
+        {
+            b[i]=new JButton(splitz[i]);
+            b[i].setActionCommand(str(i+'0'));
+            b[i].addActionListener(this);
+            b[i].setHorizontalAlignment(SwingConstants.LEFT);
+            
+            add(b[i]);
+        }
+        
+        selection=-1;
+    }
+    public void actionPerformed(ActionEvent e)
+    {
+        for(int i=0;i<b.length;i++)
+        {
+            if(str(i+'0').equals(e.getActionCommand()))
+                selection=i;
+        }
+    }
+}
+
+// Select from a list
+int selector(String title,String opt)
+{
+    JFrame frame=new JFrame(title);
+    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+    frame.setLocationRelativeTo(null);
+    
+    Selector s=new Selector(opt);
+    s.setOpaque(true);
+    frame.setContentPane(s);
+ 
+    //Display the window.
+    frame.pack();
+    frame.setVisible(true);
+    
+    frame.setLocationRelativeTo(null); // About in the middle
+    
+    while(s.selection==-1)
+    {
+        frame.toFront(); // A bit of a kludge to force the window on top
+        frame.repaint();
+        try { Thread.sleep(200); }
+        catch(Exception e){};
+    }
+    
+    frame.setVisible(false);
+    
+    System.gc(); // It'll leak anyway...
+    return(s.selection);
+}
+
+final int LOADPIX=0,
+          LOADIMG=1,
+          SAVEIMG=2,
+          SAVETXT=3,
+          SAVEEMU=4,
+          SAVEFMT=5,
+          LOADFMT=6;
+
+// File selector
+String fileselector(String dir,int mode)
+{
+    JFileChooser fc=new JFileChooser(dir);
+    
+    fc.setPreferredSize(new Dimension(480, 500));
+    fc.setDialogTitle("Select a File");
+    
+    if(mode==LOADPIX) // Show image files
+        fc.setFileFilter(new FileNameExtensionFilter("Images (*.png,*.gif,*.jpg)",
+                         "png","gif","jpg","jpeg"));
+    if(mode==LOADIMG||mode==SAVEIMG)
+        fc.setFileFilter(new FileNameExtensionFilter("Multipaint files (*.bin) or png (*.png)","bin","png","jpg"));
+    if(mode==SAVEEMU)
+        fc.setFileFilter(new FileNameExtensionFilter("Export files (*."+g_expname+") ",g_expname));
+    if(mode==SAVETXT)
+        fc.setFileFilter(new FileNameExtensionFilter("Export source (*.txt) ","c","asm","txt"));
+    if(mode==SAVEFMT||mode==LOADFMT)
+        fc.setFileFilter(new FileNameExtensionFilter(g_formatname+" (*."+g_formatextension+")",g_formatextension));
+        
+    if(mode<=LOADIMG||mode==LOADFMT)
+        fc.setApproveButtonText("Load");
+    if(mode==SAVEIMG)
+        fc.setApproveButtonText("Save");
+    if(mode==SAVETXT|mode==SAVEEMU||mode==SAVEFMT)
+        fc.setApproveButtonText("Export");        
+    int returnVal = fc.showOpenDialog(null);
+    
+    if(returnVal==JFileChooser.APPROVE_OPTION)
+    {
+        // Save cwd for next time
+        if(mode==LOADPIX)
+            refpath=fc.getCurrentDirectory().getPath();
+        else
+            path=fc.getCurrentDirectory().getPath();
+        
+        File file = fc.getSelectedFile();
+        return file.getPath();
+    }
+    else
+        return null;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multipaint.pde	Tue Jul 03 20:56:55 2018 +0300
@@ -0,0 +1,441 @@
+//Multipaint Metal Edition 22.5.2017
+//Tero Heikkinen (Dr. TerrorZ)
+//processing setup draw and file things here
+
+PrintWriter exwriter;
+final int C64=0, MSX=5, SPECTRUM=6, C64M=10, PLUS4=9, PLUS4M=19, CPC=2; // supported
+final int TIMEX=7,JR200=8,AMIGA=11; // experimental or incomplete
+final int C64FLI=20,C64FLIM=21; // experimental
+final int PICO8=88;
+final int FAKEX=32; // Commodore 64 without attribute limitations
+final int UNIA=33;
+
+//-1 & -1 for normal operation
+int machine=-1; // change this to autoselect
+int debugger=-1;
+
+final int COMMAND=157; // Marq's cmd/ctrl solution
+
+int g_active,g_tooltrigger,g_prevtool;
+int g_rband,g_rbang,g_boxreconstruct,g_sorsaa,g_charlimit;
+int g_animx,g_animy,g_animframes,g_animno,g_animtime,g_animspeed;
+int g_omag,g_bordh,g_bordv,g_keymacpos,g_framec;
+
+boolean gui=true,fileselect=false,saveas=false,refselect=false,g_control=false,g_shift=false,exporttxt=false,importfmt=false,exportemu=false,exportfmt=false;
+String path="",refpath="",filename="",elename="",sfilename="",refname="",g_expname="",g_fmtname="";
+String exporttxtname="",exportemuname="",exportfmtname;
+String g_keymacro="";
+
+int[] g_r = new int[266];int[] g_g = new int[266];int[] g_b = new int[266];
+int[] g_rgb = new int[266];
+
+byte[] g_map = new byte[88000];
+byte[] g_fillmap = new byte[88000];
+byte[] g_sparepage = new byte[88000];
+byte[] g_swappage = new byte[88000];
+byte[] g_rmap = new byte[88000];
+byte[] g_icons = new byte[88000];
+byte[] g_brush = new byte[88000];
+byte[][] g_undob = new byte[11][88000];
+byte[][] g_undobs = new byte[11][88000];
+byte[] g_template = new byte[16384];
+byte[] g_redo = new byte[1024];
+byte[] g_remdo = new byte[1024];
+int[] g_chaup = new int[64];
+byte[] g_data = new byte[1024];
+int [] g_uindex = new int[8];
+int [] g_ubottom = new int[8];
+int [] g_utop = new int[8];
+int [] g_magpix = new int[64];int [] g_magpiy = new int[64];
+
+byte g_realfront,g_realback;
+PImage output,outputsans;
+String g_name;
+
+//dimensions
+int X,Y,MX,MY;
+//generic mouse
+int g_ofx,g_ofy,g_button,g_realbutton,g_klikkeri,g_mx,g_my,g_orx,g_ory,g_msx,g_msy;
+//rubberband,mouse
+int g_phase,g_rx,g_ry,g_rx2,g_ry2,g_rubbermode;
+int g_prex,g_prey,g_storedcoordx,g_storedcoordy;
+//window positioning
+int g_windowx,g_windowy,g_maglocx,g_maglocy;
+int g_hedge,g_vedge,g_uizoom,g_wzoom;
+//icons & gui stuff
+int g_iconx,g_icony,g_piconx,g_picony,g_iconmode;
+int g_gridx,g_gridy,g_spare;
+int g_farge,g_backg,g_ofarge,g_repanel,g_msgctr;
+//machine related color properties
+int g_attrimode,g_britemode,g_multic,g_backmode,g_maxcolors,g_hzoomer;
+float g_palsteps;
+//brush, tool parameters
+int g_bsourcex,g_bsourcey,g_bsourcex2,g_bsourcey2;
+int g_bsize,g_btype;
+
+
+void setup()
+{
+//  size(1058,708);//processing3
+  int i,x,y;
+  g_uizoom=2;g_animspeed=1;
+  g_magpix[0]=3;g_magpix[1]=8;g_magpix[2]=16;
+  g_magpix[10]=2;g_magpix[11]=6;g_magpix[12]=16;
+  g_magpix[20]=4;g_magpix[21]=16;g_magpix[22]=32;
+  
+  g_magpiy[0]=3;g_magpiy[1]=8;g_magpiy[2]=16;
+  g_magpiy[10]=2;g_magpiy[11]=6;g_magpiy[12]=16;
+  g_magpiy[20]=4;g_magpiy[21]=16;g_magpiy[22]=32;
+  
+  g_omag=1;g_bordh=64;g_bordv=32;
+  readprefs("prefs.txt");
+  
+  //processing 2
+  switch (g_uizoom){
+    case 1:  g_wzoom=2;size(700,468);break;
+    case 2:  g_wzoom=3;size(1058,708);break;
+    case 3:  g_wzoom=4;size(1460,950);break;
+  }
+  /*
+  //processing 3
+  switch (g_uizoom){
+    case 1:  g_wzoom=2;surface.setSize(700,468);break;
+    case 2:  g_wzoom=3;surface.setSize(1058,708);break;
+    case 3:  g_wzoom=4;surface.setSize(1460,950);break;
+  }
+  */
+  
+  g_hedge=32*g_uizoom;g_vedge=32*g_uizoom;
+  
+  if(machine==-1||debugger==0){
+    if(gui)
+    {
+        try{ UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); }
+        catch (Exception e) {};
+        machine=selector("Select a Platform","C64 hires,C64 multicolor,ZX Spectrum,MSX1 mode 2,Plus4 hires,Plus4 multicolor,Amstrad CPC mode 0");
+    }
+    switch(machine)
+    {
+        case 0: machine=C64; break;
+        case 1: machine=C64M; break;
+        case 2: machine=SPECTRUM; break;
+        case 3: machine=MSX; break;
+        case 4: machine=PLUS4; break;
+        case 5: machine=PLUS4M; break;
+        case 6: machine=CPC; break;
+        default: ;
+    }
+  }
+
+  g_uindex[0]=0;g_utop[0]=0;g_ubottom[0]=0;g_uindex[1]=0;g_utop[1]=0;g_ubottom[1]=0;
+  g_spare=0;g_bsize=0;g_btype=0;g_phase=0;g_button=LEFT;
+  g_data['f']=1;g_data['g']=1;
+  if(fexists("icons.bin")==true)g_icons=loadBytes("icons.bin");
+  set_tool(3);
+  
+  g_gridx=8;g_gridy=8;g_multic=0;g_repanel=-2;
+  
+  //UI colors
+  makecolor(256,0xff,0,0xff);makecolor(257,180,180,180);g_rgb[257]=0xff808080;
+  makecolor(258,0,0,0);makecolor(259,48,48,48);
+  //R,G,B
+  makecolor(260,255,0,0);makecolor(261,0,255,0);makecolor(262,0,0,255);
+  
+  set_machine(machine);
+  g_windowx=width-(g_hedge)-(g_wzoom*X);g_windowx=g_windowx/2;
+  g_windowy=height-(g_vedge)-(g_wzoom*Y);g_windowy=g_windowy/2; 
+  
+  switcher(3);
+  
+  g_map[4]=byte(g_maxcolors-1);
+  g_ofarge=g_farge;MX=X/8;MY=Y/8;
+  g_realfront=byte(g_farge);g_realback=byte(g_backg);
+  
+  output= createImage (X*g_omag+g_bordh*g_omag,Y*g_omag+g_bordv*g_omag,RGB);
+  outputsans= createImage (X*g_omag,Y*g_omag,RGB);
+  
+  for(y=0;y<Y;y++){
+   for(x=0;x<X;x++){
+     absolute_clearpoint(x,y);
+   }
+  }
+
+  switcher(2);
+  noStroke();
+  background(g_r[259],g_g[259],g_b[259]);
+  sussborder();
+  setup_raster();
+  message("Multipaint|Metal|v22.5.2017");
+  message("*");
+}
+
+void store(String name)
+{
+  String[] m1 = match(name, ".png");
+  if (m1 != null) {
+    if(g_data['Q']==0){export_image_sans_border(name);}
+    if(g_data['Q']==1){export_image(name);}
+    return;
+  }
+  
+  //save the picture page g_map[], make sure some essential parameters are correct
+  g_map[3]=byte(machine);
+  g_map[5]=byte(MX);
+  g_map[7]=byte(MY);
+  saveBytes(name,g_map);
+}
+
+boolean fexists(String fname)
+{
+  File f = new File(sketchPath(fname));
+  if (f.exists())return true;
+  return false;
+}
+
+void restore(String name)
+{
+  //load the picture page g_map[] with parameters
+  boolean im_import=false;
+  if(fexists(name)==false){
+    message("NO FILE");
+    return;
+  }
+  String[] m1 = match(name, ".png");if (m1 != null)im_import=true;
+  String[] m2 = match(name, ".PNG");if (m2 != null)im_import=true;
+  String[] m3 = match(name, ".jpg");if (m3 != null)im_import=true;
+  String[] m4 = match(name, ".JPG");if (m4 != null)im_import=true;
+
+  if(im_import){
+      int lefth=g_farge;
+      int righth=g_backg;
+      storeparameters();g_data['d']=0;g_data['t']=0;g_data['b']=1;//old IQ
+      import_image(name);
+      restoreparameters();refreshpalette();refresh();
+      g_boxreconstruct=2;
+      message("Image|loaded");
+      selectcolor(0,lefth);selectcolor(1,righth);
+      return;
+  }
+  g_map=loadBytes(name);
+  if(g_map[3]!=machine){message("Wrong|machine!");restore_undo();return;}
+  refreshpalette();consistency();
+  g_farge=int(g_realfront);g_ofarge=g_farge;g_backg=int(g_realback);
+  sussborder();
+  message("Page|loaded");
+}
+
+void draw()
+{
+  int msx,msy;
+
+  if(!focused){
+    g_control=false;
+    g_shift=false; 
+    delay(200);
+  }
+  
+  if(g_data['n']==1){
+      g_animtime++;
+      if(g_animtime>8-g_animspeed*2){
+        animbrush_do();
+        g_animtime=0;  
+    }
+  }
+  /*
+  boolean depis=false;
+  for(int i=0;i<=255;i++){
+    if(g_depressed[i]>0){
+      g_depressed[i]--;
+      if(g_depressed[i]==0)depis=true;
+    }
+  }
+  if(depis)g_repanel=-2;
+  */
+  if(moicon(16*16*g_uizoom,height-32*g_uizoom,16*g_uizoom,24*g_uizoom))help('<');
+  if(moicon(16*16*g_uizoom,height-8*g_uizoom,16*g_uizoom,8*g_uizoom))help('>');
+  if(moicon(0,height-32*g_uizoom,15*16*g_uizoom,32*g_uizoom))help(TAB);
+  if(moicon(width-32*g_uizoom,0,32*g_uizoom,16*g_uizoom))help('.');
+  
+  if(g_data['m']==0&&g_data['M']==0){
+    msx=mouseX-g_windowx;
+    msy=mouseY-g_windowy;
+    msx=g_msx-g_windowx;msy=g_msy-g_windowy;
+  }
+  else
+  {
+    msx=mouseX;msy=mouseY;
+    //msx=g_msx;msy=g_msy;
+  }
+ g_mx=msx;g_my=msy;
+ 
+ //actual tool drawing
+  if(g_tooltrigger==1){ // comes from mousepressed, or mousedragged
+        if(g_mx<=width-g_hedge&&g_my<=height-g_vedge)do_tool(msx,msy,g_button);
+  }    
+    g_msx=mouseX;g_msy=mouseY;   
+    switcher(0);
+
+    for(int i=0;i<1024;i++){
+      g_remdo[i]=0;
+    }
+    int lipo=g_button;
+    //tool drawing for shows
+    if(tool()!=5){
+       if(g_phase==0)g_button=LEFT;
+       do_tool(msx,msy,LEFT);
+    }
+    if(tool()==6)doline(g_rx,g_ry,g_rx2,g_ry2,0);
+    if(tool()==7)docircle(g_rx,g_ry,g_rx2,g_ry2);
+    if(tool()==8)rectangle(g_rx,g_ry,g_rx2,g_ry2);
+    g_button=lipo; 
+    loadPixels();
+      viewport();
+      //magport();
+      switcher(1);
+      update_ui();
+    updatePixels();
+    if(g_msgctr>0)g_msgctr--;
+    
+      // UI file operations
+    if(gui)
+    {
+        if(fileselect) // Fileselect "event" for Load
+        {
+            String s=fileselector(path,LOADIMG);
+            if(s!=null)
+            {
+               store_undo();
+               if(g_spare==0){
+                  filename=s;
+                  frame.setTitle(filename);    
+                  restore(s);
+                }
+                if(g_spare==1){
+                  restore(s);
+                  sfilename=s;
+                  frame.setTitle(sfilename);
+                }
+                refresh();
+            }
+            fileselect=false;g_shift=false;g_control=false;
+        }
+        if(saveas) // Fileselect "event" for Save as
+        {
+            String s=fileselector(path,SAVEIMG);
+            String orig="";
+            int kuva=0;
+            if(g_spare==0)orig=filename;
+            if(g_spare==1)orig=sfilename;
+            if(s!=null)
+            {
+                // Add extension if needed
+                if(s.length()<=2)s+=".bin";
+                s=s+".dummy.dummy";
+                String[]l=split(s,'.');
+                String []m1=match(l[1],"png");String []m2=match(l[1],"PNG");
+                String []m3=match(l[1],"bin");String []m4=match(l[1],"BIN");
+                if(m1!=null||m2!=null)kuva=1;
+                if(m1==null&&m2==null&&m3==null&&m4==null)l[1]="bin";
+
+                if(g_spare==0){
+                  filename=l[0]+"."+l[1];store(filename);
+                  if(kuva==1)filename=orig;
+                  frame.setTitle(filename);
+                }
+                if(g_spare==1){
+                  sfilename=l[0]+"."+l[1];store(sfilename);
+                  if(kuva==1)sfilename=orig;
+                  frame.setTitle(sfilename);
+                }
+                
+                message("SAVED");
+                if(kuva==1)message("EXPORTED|PNG");
+            }
+            saveas=false;g_shift=false;g_control=false;
+        }
+        if(exporttxt)
+        {
+           String s=fileselector(path,SAVETXT);
+            if(s!=null)
+            {
+                // Add extension if needed
+                if(s.length()<=2)s+=".txt";
+                s=s+".dummy.dummy";
+                String[]l=split(s,'.');
+                l[1]="txt";
+                if(g_spare==0){exportemuname=l[0]+"."+l[1];machine_export(exportemuname,1);}
+                if(g_spare==1){exportemuname=l[0]+"."+l[1];machine_export(exportemuname,1);}
+            }
+            exporttxt=false;g_shift=false;g_control=false;
+        }
+        if(exportemu)
+        {
+           String s=fileselector(path,SAVEEMU);
+            if(s!=null)
+            {
+                // Add extension if needed
+                if(s.length()<=2)s+="."+g_expname;
+                s=s+".dummy.dummy";
+                String[]l=split(s,'.');
+                l[1]=g_expname;
+                if(g_spare==0){
+                  exportemuname=l[0]+"."+l[1];machine_export(exportemuname,0);
+                  //println(exportemuname);
+                }
+                if(g_spare==1){
+                  exportemuname=l[0]+"."+l[1];machine_export(exportemuname,0);
+                }
+               
+                //message("EXPORTED");
+            }
+            exportemu=false;g_shift=false;g_control=false;
+        }
+        if(importfmt)
+        {
+            String s=fileselector(path,LOADFMT);
+            if(s!=null)
+            {
+               store_undo();
+               format_import(s);
+               refresh();
+            }
+            importfmt=false;g_shift=false;g_control=false;
+        }
+        if(exportfmt)
+        {
+           String s=fileselector(path,SAVEFMT);
+            if(s!=null)
+            {
+                boolean koalakludge=false;
+                // Add extension if needed
+                if(s.indexOf(".kla")>-1&&machine==C64M)koalakludge=true;
+                if(s.length()<=2)s+="."+g_fmtname;
+                s=s+".dummy.dummy";
+                String[]l=split(s,'.');       
+                l[1]=g_formatextension;
+                
+                if(koalakludge)l[1]="kla";
+                
+                if(g_spare==0){
+                  exportfmtname=l[0]+"."+l[1];format_export(exportfmtname);
+                  //println(exportemuname);
+                }
+                if(g_spare==1){
+                  exportfmtname=l[0]+"."+l[1];format_export(exportfmtname);
+                }
+               
+                //message("EXPORTED");
+            }
+            exportfmt=false;g_shift=false;g_control=false;
+        }
+
+    }
+    
+    //if(g_framec==1){saveFrame("frames/out-######.png");}
+    g_framec++;if(g_framec>1)g_framec=0;
+    if(g_keymacro.length()>g_keymacpos){
+        macro_command(g_keymacro.charAt(g_keymacpos));
+        g_keymacpos++;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prefread.pde	Tue Jul 03 20:56:55 2018 +0300
@@ -0,0 +1,73 @@
+//Read preferences from file
+//Adapted from Marq's PETSCII editor
+
+final String machinenames[]={
+          "C64",
+          "C64M",
+          "SPECTRUM",
+          "MSX",
+          "PLUS4",
+          "PLUS4M",
+          "CPC"
+          };
+//a bit sad
+final int g_machineidx[]={C64,C64M,SPECTRUM,MSX,PLUS4,PLUS4M,CPC};
+
+void readprefs(String namn)
+    {
+        String row[]=loadStrings(namn);
+        
+        if(row==null)
+            return;
+            
+        for(int i=0;i<row.length;i++) // Parse each line
+        {
+            if(row[i].length()>1)
+            {
+                String s[]=split(row[i],"=");
+                
+                if(s[0].equals("ZOOM"))
+                {
+                    g_uizoom=int(s[1]);
+                    if(g_uizoom<1)g_uizoom=2;
+                    if(g_uizoom>3)g_uizoom=2;
+                }
+                    
+                if(s[0].equals("MACHINE") && s.length>1)
+                {
+                    for(int j=0;j<machinenames.length;j++)
+                        if(s[1].equals(machinenames[j]))
+                            machine=g_machineidx[j];
+                }
+                
+                if(s[0].equals("PATH") && s.length>1)
+                {
+                    path=s[1];
+                }
+                
+                if(s[0].equals("KEYMACRO") && s.length>1 && s.length<80)
+                {
+                    g_keymacro=s[1];
+                }      
+                
+                if(s[0].equals("PNGSCALE"))
+                {
+                    g_omag=int(s[1]);
+                    if(g_omag<1||g_omag>10)g_omag=1;
+                }
+                
+                if(s[0].equals("PNGHBORDER"))
+                {
+                    g_bordh=int(s[1]);
+                    if(g_bordh<1||g_bordh>256)g_bordh=64;
+                }
+                
+                if(s[0].equals("PNGVBORDER"))
+                {
+                    g_bordv=int(s[1]);
+                    if(g_bordv<1||g_bordv>256)g_bordv=32;
+                }
+                
+            }
+        }
+    }