Index: AvrdudeUploader.java
===================================================================
--- AvrdudeUploader.java	(revision 557)
+++ AvrdudeUploader.java	(working copy)
@@ -43,10 +43,17 @@
     if (uploadUsing == null) {
       // fall back on global preference
       uploadUsing = Preferences.get("upload.using");
+      System.out.println("upload.using is null");
     }
     if (uploadUsing.equals("bootloader")) {
       return uploadViaBootloader(buildPath, className);
-    } else {
+    }
+    else if (uploadUsing.equals("byInfection")) //LUMINET SPECIAL
+    {
+    	System.out.println("upload.using is byInfection");
+      return (new LuminetUploader()).infectNetwork(buildPath, className);
+    }
+    else {
       Collection params = getProgrammerCommands(uploadUsing);
       params.add("-Uflash:w:" + buildPath + File.separator + className + ".hex:i");
       return avrdude(params);
@@ -60,12 +67,21 @@
     
     // avrdude wants "stk500v1" to distinguish it from stk500v2
     if (protocol.equals("stk500"))
+    {
       protocol = "stk500v1";
+    }
     commandDownloader.add("-c" + protocol);
     commandDownloader.add("-P" + (Base.isWindows() ? "\\\\.\\" : "") + Preferences.get("serial.port"));
-    commandDownloader.add(
-      "-b" + Preferences.getInteger("boards." + Preferences.get("board") + ".upload.speed"));
-    commandDownloader.add("-D"); // don't erase
+    
+    if (protocol.equals("stk500v2"))
+    {
+    }
+    else
+    {
+    	commandDownloader.add("-b" + Preferences.getInteger("boards." + Preferences.get("board") + ".upload.speed"));
+    	commandDownloader.add("-D"); // don't erase
+  	}
+  	
     commandDownloader.add("-Uflash:w:" + buildPath + File.separator + className + ".hex:i");
 
     if (Preferences.get("boards." + Preferences.get("board") + ".upload.disable_flushing") == null ||
@@ -93,12 +109,15 @@
     // XXX: add support for specifying the port address for parallel
     // programmers, although avrdude has a default that works in most cases.
     
-    if (Preferences.get("programmers." + programmer + ".force") != null &&
-        Preferences.getBoolean("programmers." + programmer + ".force"))
+    if (Preferences.get("programmers." + programmer + ".force") != null && Preferences.getBoolean("programmers." + programmer + ".force"))
+    {
       params.add("-F");
+    }
     
     if (Preferences.get("programmers." + programmer + ".delay") != null)
+    {
       params.add("-i" + Preferences.get("programmers." + programmer + ".delay"));
+    }
     
     return params;
   }
@@ -107,22 +126,60 @@
   throws RunnerException {
     List fuses = new ArrayList();
     fuses.add("-e"); // erase the chip
-    fuses.add("-Ulock:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.unlock_bits") + ":m");
-    if (Preferences.get("boards." + Preferences.get("board") + ".bootloader.extended_fuses") != null)
-      fuses.add("-Uefuse:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.extended_fuses") + ":m");
-    fuses.add("-Uhfuse:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.high_fuses") + ":m");
-    fuses.add("-Ulfuse:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.low_fuses") + ":m");
 
-    if (!avrdude(params, fuses))
-      return false;
-      
-    List bootloader = new ArrayList();
-    bootloader.add("-Uflash:w:" + "hardware" + File.separator + "bootloaders" + File.separator +
-            Preferences.get("boards." + Preferences.get("board") + ".bootloader.path") +
-            File.separator + Preferences.get("boards." + Preferences.get("board") + ".bootloader.file") + ":i");
-    bootloader.add("-Ulock:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.lock_bits") + ":m");
+	
 
-    return avrdude(params, bootloader);
+
+		if (Preferences.get("boards." + Preferences.get("board") + ".bootloader.unlock_bits") != null)
+		{
+			fuses.add("-Ulock:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.unlock_bits") + ":m");
+		}
+		if (Preferences.get("boards." + Preferences.get("board") + ".bootloader.extended_fuses") != null)
+		{
+			fuses.add("-Uefuse:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.extended_fuses") + ":m");
+		}
+		if (Preferences.get("boards." + Preferences.get("board") + ".bootloader.high_fuses") != null)
+		{
+			fuses.add("-Uhfuse:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.high_fuses") + ":m");
+		}
+		if (Preferences.get("boards." + Preferences.get("board") + ".bootloader.low_fuses") != null)
+		{
+			fuses.add("-Ulfuse:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.low_fuses") + ":m");
+		}
+		if (!avrdude(params, fuses))
+		{
+			System.out.println("programming fuses failed.");
+			return false; 
+		}
+		else
+		{
+			System.out.println("programming fuses ok.");
+		}
+
+		List bootloader = new ArrayList();
+		bootloader.add("-Uflash:w:" + "hardware" + File.separator + "bootloaders" + File.separator +
+				Preferences.get("boards." + Preferences.get("board") + ".bootloader.path") +
+				File.separator + Preferences.get("boards." + Preferences.get("board") + ".bootloader.file") + ":i");
+
+	  if(Preferences.get("boards." + Preferences.get("board") + ".bootloader.unlock_bits") != null)
+	  {
+			bootloader.add("-Ulock:w:" + Preferences.get("boards." + Preferences.get("board") + ".bootloader.lock_bits") + ":m");
+		}
+	
+	
+		if (!avrdude(params, bootloader))
+		{
+			System.out.println("programming bootloader failed.");
+			return false; 
+		}
+		else
+		{
+			System.out.println("programming bootloader ok.");
+		}
+		
+		return true;
+
+    
   }
   
   public boolean avrdude(Collection p1, Collection p2) throws RunnerException {
@@ -159,8 +216,27 @@
     }
     // XXX: quick hack to chop the "atmega" off of "atmega8" and "atmega168",
     // then shove an "m" at the beginning.  won't work for attiny's, etc.
-    commandDownloader.add("-pm" + 
-      Preferences.get("boards." + Preferences.get("board") + ".build.mcu").substring(6));
+    //commandDownloader.add("-pm" + 
+    //  Preferences.get("boards." + Preferences.get("board") + ".build.mcu").substring(6));
+	
+	String mcuName = Preferences.get("boards." + Preferences.get("board") + ".build.mcu");
+	if(mcuName.startsWith("atmega"))
+	{
+		commandDownloader.add("-pm" + mcuName.substring(6) );
+	}
+	else if(mcuName.startsWith("attiny"))
+	{
+		commandDownloader.add("-pt" + mcuName.substring(6) );
+	}
+	else
+	{
+		//unknown part
+		commandDownloader.add("-pm" + mcuName.substring(6) );
+	}
+	
+	
+    
+	
     commandDownloader.addAll(params);
 
     return executeUploadCommand(commandDownloader);
Index: Compiler.java
===================================================================
--- Compiler.java	(revision 557)
+++ Compiler.java	(working copy)
@@ -107,7 +107,7 @@
     List baseCommandLinker = new ArrayList(Arrays.asList(new String[] {
       avrBasePath + "avr-gcc",
       "-Os",
-      "-Wl,--gc-sections",
+      "-Wl,--gc-sections,--cref",
       "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
       "-o",
       buildPath + File.separator + sketch.name + ".elf"
@@ -140,13 +140,22 @@
     // library for the target platform)
     List sourceNames = new ArrayList();
     List sourceNamesCPP = new ArrayList();
+    List sourceNamesASM = new ArrayList();
     List objectNames = new ArrayList();
     List objectNamesCPP = new ArrayList();
+    List objectNamesASM = new ArrayList();
     List targetObjectNames = new ArrayList();
     List sketchObjectNames = new ArrayList();
     for (int i = 0; i < sketch.codeCount; i++) {
       if (sketch.code[i].preprocName != null) {
-        if (sketch.code[i].preprocName.endsWith(".c")) {
+        
+        if (sketch.code[i].preprocName.endsWith(".S")) {
+          sourceNamesASM.add(buildPath + File.separator + sketch.code[i].preprocName);
+          objectNamesASM.add(buildPath + File.separator + sketch.code[i].preprocName + ".o");
+          sketchObjectNames.add(buildPath + File.separator + sketch.code[i].preprocName + ".o");
+          System.out.println("1>>>"+sketch.code[i].preprocName);
+        } 
+        else if (sketch.code[i].preprocName.endsWith(".c")) {
           sourceNames.add(buildPath + File.separator + sketch.code[i].preprocName);
           objectNames.add(buildPath + File.separator + sketch.code[i].preprocName + ".o");
           sketchObjectNames.add(buildPath + File.separator + sketch.code[i].preprocName + ".o");
@@ -155,19 +164,26 @@
           objectNamesCPP.add(buildPath + File.separator + sketch.code[i].preprocName + ".o");
           sketchObjectNames.add(buildPath + File.separator + sketch.code[i].preprocName + ".o");
         } 
+        
       }
     }
     for (Iterator iter = target.getSourceFilenames().iterator(); iter.hasNext(); ) {
       String filename = (String) iter.next();
       if (filename != null) {
         targetObjectNames.add(buildPath + File.separator + filename + ".o");
-        if (filename.endsWith(".c")) {
+        if (filename.endsWith(".S")) {
+          sourceNamesASM.add(target.getPath() + File.separator + filename);
+          objectNamesASM.add(buildPath + File.separator + filename + ".o");
+          System.out.println("2>>>"+filename);
+        } 
+        else if (filename.endsWith(".c")) {
           sourceNames.add(target.getPath() + File.separator + filename);
           objectNames.add(buildPath + File.separator + filename + ".o");
         } else if (filename.endsWith(".cpp")) {
           sourceNamesCPP.add(target.getPath() + File.separator + filename);
           objectNamesCPP.add(buildPath + File.separator + filename + ".o");
         } 
+        
       }
     }
     
@@ -188,6 +204,13 @@
 
       Process process;
       boolean compiling = true;
+      
+      for(int i = 0; i < sourceNamesASM.size(); i++) {
+        if (execAsynchronously(getCommandCompilerASM(avrBasePath, includePaths,
+          (String) sourceNamesASM.get(i), (String) objectNamesASM.get(i))) != 0)
+          return false;
+      }
+      
       for(int i = 0; i < sourceNames.size(); i++) {
         if (execAsynchronously(getCommandCompilerC(avrBasePath, includePaths,
           (String) sourceNames.get(i), (String) objectNames.get(i))) != 0)
@@ -199,6 +222,8 @@
           (String) sourceNamesCPP.get(i), (String) objectNamesCPP.get(i))) != 0)
           return false;
       }
+      
+      
 
 //      for(int i = 0; i < targetObjectNames.size(); i++) {
 //        List commandAR = new ArrayList(baseCommandAR);
@@ -531,7 +556,30 @@
     
     return baseCommandCompilerCPP;
   }
+  
+  
+  static private List getCommandCompilerASM(String avrBasePath, List includePaths,
+    String sourceName, String objectName) {
+    List baseCommandCompiler = new ArrayList(Arrays.asList(new String[] {
+      avrBasePath + "avr-gcc",
+      "-c", // compile, don't link
+      "-g", // include debugging info (so errors include line numbers)
+      "-x",
+      "assembler-with-cpp",
+      "-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
+      "-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"),
+    }));
 
+    for (int i = 0; i < includePaths.size(); i++) {
+      baseCommandCompiler.add("-I" + (String) includePaths.get(i));
+    }
+    
+    baseCommandCompiler.add(sourceName);
+    baseCommandCompiler.add("-o"+ objectName);
+    
+    return baseCommandCompiler;
+  }
+
   
   
 
Index: Editor.java
===================================================================
--- Editor.java	(revision 557)
+++ Editor.java	(working copy)
@@ -593,6 +593,15 @@
         }
       });
     menu.add(item);
+    
+    item = newJMenuItem("Burn bootloader to I/O Board", 'B');
+    item.addActionListener(new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+        	String bootprogrammer = Preferences.get("bootprogrammer");
+          handleBurnBootloader(bootprogrammer);
+        }
+      });
+    menu.add(item);
 
     /*exportAppItem = newJMenuItem("Export Application", 'E', true);
     exportAppItem.addActionListener(new ActionListener() {
@@ -803,12 +812,21 @@
     menu.addSeparator();
     
     JMenu bootloaderMenu = new JMenu("Burn Bootloader");
+    ButtonGroup bootloaderGroup = new ButtonGroup();    
     for (Iterator i = Preferences.getSubKeys("programmers"); i.hasNext(); ) {
       String programmer = (String) i.next();
       Action action = new BootloaderMenuAction(programmer);
-      item = new JMenuItem(action);
+      //item = new JMenuItem(action);
+      item = new JRadioButtonMenuItem(action);
+      
+      if (programmer.equals(Preferences.get("bootprogrammer")))
+      {
+        item.setSelected(true);
+      }
+      bootloaderGroup.add(item);
       bootloaderMenu.add(item);
     }
+    
     menu.add(bootloaderMenu);
         
     menu.addMenuListener(new MenuListener() {
@@ -882,9 +900,13 @@
     public BootloaderMenuAction(String programmer) {
       super("w/ " + Preferences.get("programmers." + programmer + ".name"));
       this.programmer = programmer;
+      
     }
     public void actionPerformed(ActionEvent actionevent) {
-      handleBurnBootloader(programmer);
+      //only select the programmer (now RadioButton)
+      //burn bootloader from File menu or using strg+b
+      Preferences.set("bootprogrammer", this.programmer);
+      //handleBurnBootloader(programmer);
     }
   }
   
Index: LuminetUploader.java
===================================================================
--- LuminetUploader.java	(revision 0)
+++ LuminetUploader.java	(revision 0)
@@ -0,0 +1,235 @@
+package processing.app;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import javax.swing.*;
+import gnu.io.*;
+
+
+public class LuminetUploader implements MessageConsumer
+{
+	int rxtimeoutms = 10000;
+	InputStream input2;
+	OutputStream output2;
+	byte[] image = new byte[20000];
+	int imagesize = 0;
+	
+	RunnerException exception;
+	
+	//converts a signed byte b to a unsigned byte... this unsigned byte has to be an int in java
+		private int byte2int(byte b)
+		{
+			int val = b & 0x80;
+			val += b & 0x7F;
+			return val;
+		}
+		
+		private int byte2int(int b)
+		{				
+			int val = b & 0x80;
+			val += b & 0x7F;
+			return val;
+		}
+
+	
+	public boolean infectNetwork(String buildPath, String className)
+	{
+		
+		String _fullFilenameHEX = buildPath+File.separator+className+".hex";
+		String _fullFilenameBIN = buildPath+File.separator+className+".bin";
+		
+		System.out.println("Converting hex file: "+ _fullFilenameHEX);
+		
+		String avrBasePath;
+    if(Base.isMacOS()) {
+    	avrBasePath = new String("hardware/tools/avr/bin/"); 
+    }
+    else if(Base.isLinux()) {
+    	avrBasePath = new String("");     	
+    }
+    else {
+    	String userdir = System.getProperty("user.dir") + File.separator;
+    	avrBasePath = new String(userdir + "hardware" + File.separator+ "tools" +File.separator+ "avr" +File.separator+ "bin" +File.separator); 
+    }
+
+		List commandObjcopy = new ArrayList(Arrays.asList(new String[] {
+      avrBasePath + "avr-objcopy",
+      "-I",
+      "ihex",
+      "-O",
+      "binary",
+      _fullFilenameHEX,
+      _fullFilenameBIN
+    }));
+
+		try
+		{
+      if (execAsynchronously(commandObjcopy) != 0)
+      {
+      	System.err.println("Cannot create .bin file");
+        return false;
+      }
+    }
+    catch(Exception ex)
+    {
+    	System.err.println("Error: Exception while creating .bin file");
+    	return false;
+    }
+		
+		System.out.println("infecting network, please wait...");
+		String _comPort = Preferences.get("serial.port");
+		try
+		{
+			upload(_fullFilenameBIN, _comPort, 9600, 64, System.out);               
+		}
+		catch(Exception ex)
+		{
+			System.err.println("error while uploading");
+			return false;
+		}
+    System.out.println("done.");
+		return true;
+  }
+  
+  private void upload(String filename, String comport, int baud, int pageSize, OutputStream out) throws Exception 
+  { 
+				// load the payload file into memory		
+				
+				//read .bin file into memory
+        InputStream Jin = new BufferedInputStream(new FileInputStream(filename));
+        imagesize = (int) new File(filename).length();
+        image = new byte[(int)(imagesize)];
+        Jin.read(image);
+        Jin.close();
+				
+				
+				System.out.println(".bin file read into memory: "+imagesize+" byes.");
+
+				CommPortIdentifier portId2 = CommPortIdentifier.getPortIdentifier(comport);
+
+        SerialPort port2 = (SerialPort) portId2.open("serial madness2", 4001);
+        port2.setSerialPortParams(baud, SerialPort.DATABITS_8,SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
+        port2.setDTR(false);
+        
+        port2.disableReceiveThreshold();
+        port2.disableReceiveTimeout();
+        //port2.enableReceiveTimeout(rxtimeoutms);
+        
+        input2 = port2.getInputStream();
+        output2 = port2.getOutputStream();
+        
+         output2.write(0xA0);//START
+
+	       try {
+	               Thread.sleep(100);
+	       } catch (InterruptedException e) {
+	       }
+
+				System.out.println("START sent.");
+
+      
+
+               // write the hex file
+        int addr = 0;
+				int c = 0;
+				int currentByte = 0;
+				
+				
+
+        while (addr < imagesize) 
+				{
+					currentByte = byte2int(image[addr]);
+					addr = addr+1;
+					
+					output2.write(0xB0);//DATA HEADER
+					//println("currentByte: "+currentByte,out); 
+					try {
+	               Thread.sleep(10);
+	       } catch (InterruptedException e) {
+	       }
+			    output2.write(currentByte);//DATA payload byte
+                       
+             while(input2.available() == 0)
+             {
+             }
+					   c = byte2int(input2.read());
+					   
+					   //println("received: "+c,out);
+						while (c != currentByte)
+						{
+							try {
+	               Thread.sleep(10);
+	       } catch (InterruptedException e) {
+	       }
+							output2.write(0xB1);//RETRANSMIT HEADER
+							System.out.println("RETRANSMIT: "+currentByte);
+							try {
+	               Thread.sleep(10);
+	       } catch (InterruptedException e) {
+	       }
+			        output2.write(currentByte);//RETRANSMIT payload byte
+		  
+              while(input2.available() == 0)
+	             {
+	             }
+              c = byte2int(input2.read());
+						}
+						System.out.print(".");
+
+                      
+               }
+
+               output2.write(0xC0);//STOP
+    					System.out.println("STOP sent.");           
+               port2.setDTR(true);
+               port2.close();
+  }
+  
+   public int execAsynchronously(List commandList) throws RunnerException, IOException 
+   {
+   	
+    String[] command = new String[commandList.size()];
+    commandList.toArray(command);
+    int result = 0;
+    
+    if (Preferences.getBoolean("build.verbose")) {
+      for(int j = 0; j < command.length; j++) {
+        System.out.print(command[j] + " ");
+      }
+      System.out.println();
+    }
+
+    Process process = Runtime.getRuntime().exec(command);
+    
+    new MessageSiphon(process.getInputStream(), this);
+    new MessageSiphon(process.getErrorStream(), this);
+
+    // wait for the process to finish.  if interrupted
+    // before waitFor returns, continue waiting
+    boolean compiling = true;
+    while (compiling) {
+      try {
+        result = process.waitFor();
+        //System.out.println("result is " + result);
+        compiling = false;
+      } catch (InterruptedException ignored) { }
+    }
+    
+    if (exception != null)  {
+      exception.hideStackTrace = true;
+      throw exception;
+    }
+    
+    return result;
+  }
+  
+  
+  public void message(String s) 
+  {
+  	System.out.println("message: "+s);
+  }
+
+  
+  
+}
\ No newline at end of file
Index: Target.java
===================================================================
--- Target.java	(revision 557)
+++ Target.java	(working copy)
@@ -52,7 +52,7 @@
                             base);
     
     for (int i = 0; i < files.length; i++) {
-      if (files[i].endsWith(".c") || files[i].endsWith(".cpp"))
+      if (files[i].endsWith(".S") || files[i].endsWith(".c") || files[i].endsWith(".cpp"))
         sources.add(files[i]);
       if (files[i].endsWith(".o"))
         objects.add(files[i]);
