Browse Source

Work in progress:
Some size reductions
Partially tested support for Arduino Mega
Untested support for Sanguino
Initial code in place for Luminet **completely untested**

cathedrow 15 years ago
parent
commit
90cb186e87

+ 47 - 13
optiboot/boards.txt

@@ -122,16 +122,50 @@ proo.build.f_cpu=8000000L
 proo.build.core=arduino
 
 ##############################################################
-#
-#lumineto.name=[Optiboot] Luminet (in development)
-#lumineto.upload.protocol=stk500
-#lumineto.upload.maximum_size=7424
-#lumineto.upload.speed=9600
-#lumineto.bootloader.low_fuses=0x62
-#lumineto.bootloader.high_fuses=0xdf
-#lumineto.bootloader.extended_fuses=0xfe
-#lumineto.bootloader.path=optiboot
-#lumineto.bootloader.file=optiboot_luminet.hex
-#lumineto.build.mcu=attiny84
-#lumineto.build.f_cpu=1000000L
-#lumineto.build.core=arduino
+
+megao.name=[Optiboot] Arduino Mega (work in progress)
+megao.upload.protocol=stk500
+megao.upload.maximum_size=130048
+megao.upload.speed=115200
+megao.bootloader.low_fuses=0xff
+megao.bootloader.high_fuses=0xde
+megao.bootloader.extended_fuses=0xf5
+megao.bootloader.path=optiboot
+megao.bootloader.file=optiboot_atmega1280.hex
+megao.bootloader.unlock_bits=0x3F
+megao.bootloader.lock_bits=0x0F
+megao.build.mcu=atmega1280
+megao.build.f_cpu=16000000L
+megao.build.core=arduino
+
+##############################################################
+
+sanguinoo.name=[Optiboot] Sanguino (work in progress)
+sanguinoo.upload.protocol=stk500
+sanguinoo.upload.maximum_size=63488
+sanguinoo.upload.speed=115200
+sanguinoo.bootloader.low_fuses=0xff
+sanguinoo.bootloader.high_fuses=0xdc
+sanguinoo.bootloader.extended_fuses=0xfd
+sanguinoo.bootloader.path=optiboot
+sanguinoo.bootloader.file=optiboot_sanguino.hex
+sanguinoo.bootloader.unlock_bits=0x3F
+sanguinoo.bootloader.lock_bits=0x0F
+sanguinoo.build.mcu=atmega644p
+sanguinoo.build.f_cpu=16000000L
+sanguinoo.build.core=sanguino
+
+##############################################################
+
+lumineto.name=[Optiboot] Luminet (work in progress)
+lumineto.upload.protocol=stk500
+lumineto.upload.maximum_size=7424
+lumineto.upload.speed=9600
+lumineto.bootloader.low_fuses=0x62
+lumineto.bootloader.high_fuses=0xdf
+lumineto.bootloader.extended_fuses=0xfe
+lumineto.bootloader.path=optiboot
+lumineto.bootloader.file=optiboot_luminet.hex
+lumineto.build.mcu=attiny84
+lumineto.build.f_cpu=1000000L
+lumineto.build.core=luminet

+ 37 - 10
optiboot/bootloaders/optiboot/Makefile

@@ -73,7 +73,6 @@ pro20: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
 pro20: AVR_FREQ = 20000000L
 pro20: $(PROGRAM)_pro_20mhz.hex
 pro20: $(PROGRAM)_pro_20mhz.lst
-
 pro20_isp: pro20
 pro20_isp: TARGET = pro_20mhz
 pro20_isp: HFUSE = DD # 2.7V brownout
@@ -91,7 +90,6 @@ pro16: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
 pro16: AVR_FREQ = 16000000L
 pro16: $(PROGRAM)_pro_16MHz.hex
 pro16: $(PROGRAM)_pro_16MHz.lst
-
 pro16_isp: pro16
 pro16_isp: TARGET = pro_16MHz
 pro16_isp: HFUSE = DD # 2.7V brownout
@@ -100,13 +98,11 @@ pro16_isp: EFUSE = 02 # 512 byte boot
 pro16_isp: isp
 
 # Diecimila and NG use identical bootloaders
-#
 diecimila: TARGET = diecimila
 diecimila: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
 diecimila: AVR_FREQ = 16000000L 
 diecimila: $(PROGRAM)_diecimila.hex
 diecimila: $(PROGRAM)_diecimila.lst
-
 diecimila_isp: diecimila
 diecimila_isp: TARGET = diecimila
 diecimila_isp: HFUSE = DD # 2.7V brownout
@@ -121,7 +117,6 @@ atmega328: AVR_FREQ = 16000000L
 atmega328: LDSECTION  = --section-start=.text=0x7e00
 atmega328: $(PROGRAM)_atmega328.hex
 atmega328: $(PROGRAM)_atmega328.lst
-
 atmega328_isp: atmega328
 atmega328_isp: TARGET = atmega328
 atmega328_isp: MCU_TARGET = atmega328p
@@ -130,6 +125,38 @@ atmega328_isp: LFUSE = FF # Low power xtal (16MHz) 16KCK/14CK+65ms
 atmega328_isp: EFUSE = 05 # 2.7V brownout
 atmega328_isp: isp
 
+# Sanguino has a minimum boot size of 1024 bytes, so enable extra functions
+sanguino: TARGET = atmega644p
+sanguino: MCU_TARGET = atmega644p
+sanguino: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT'
+sanguino: AVR_FREQ = 16000000L
+sanguino: LDSECTION  = --section-start=.text=0xfc00
+sanguino: $(PROGRAM)_atmega644p.hex
+sanguino: $(PROGRAM)_atmega644p.lst
+sanguino_isp: sanguino
+sanguino_isp: TARGET = atmega644p
+sanguino_isp: MCU_TARGET = atmega644p
+sanguino_isp: HFUSE = DE # 1024 byte boot
+sanguino_isp: LFUSE = FF # Low power xtal (16MHz) 16KCK/14CK+65ms
+sanguino_isp: EFUSE = 05 # 2.7V brownout
+sanguino_isp: isp
+
+# Mega has a minimum boot size of 1024 bytes, so enable extra functions
+mega: TARGET = atmega1280
+mega: MCU_TARGET = atmega1280
+mega: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=230400' '-DSOFT_UART' '-DBIGBOOT'
+mega: AVR_FREQ = 16000000L
+mega: LDSECTION  = --section-start=.text=0x1fc00
+mega: $(PROGRAM)_atmega1280.hex
+mega: $(PROGRAM)_atmega1280.lst
+mega_isp: mega
+mega_isp: TARGET = atmega1280
+mega_isp: MCU_TARGET = atmega1280
+mega_isp: HFUSE = DE # 1024 byte boot
+mega_isp: LFUSE = FF # Low power xtal (16MHz) 16KCK/14CK+65ms
+mega_isp: EFUSE = 05 # 2.7V brownout
+mega_isp: isp
+
 # 8MHz clocked platforms
 #
 # These are capable of 115200 baud
@@ -140,7 +167,6 @@ lilypad: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=115200'
 lilypad: AVR_FREQ = 8000000L
 lilypad: $(PROGRAM)_lilypad.hex
 lilypad: $(PROGRAM)_lilypad.lst
-
 lilypad_isp: lilypad
 lilypad_isp: TARGET = lilypad
 lilypad_isp: HFUSE = DD # 2.7V brownout
@@ -153,7 +179,6 @@ lilypad_resonator: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=
 lilypad_resonator: AVR_FREQ = 8000000L
 lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex
 lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst
-
 lilypad_resonator_isp: lilypad_resonator
 lilypad_resonator_isp: TARGET = lilypad_resonator
 lilypad_resonator_isp: HFUSE = DD # 2.7V brownout
@@ -166,7 +191,6 @@ pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=115200'
 pro8: AVR_FREQ = 8000000L
 pro8: $(PROGRAM)_pro_8MHz.hex
 pro8: $(PROGRAM)_pro_8MHz.lst
-
 pro8_isp: pro8
 pro8_isp: TARGET = pro_8MHz
 pro8_isp: HFUSE = DD # 2.7V brownout
@@ -181,7 +205,6 @@ atmega328_pro8: AVR_FREQ = 8000000L
 atmega328_pro8: LDSECTION  = --section-start=.text=0x7e00
 atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex
 atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst
-
 atmega328_pro8_isp: atmega328_pro8
 atmega328_pro8_isp: TARGET = atmega328_pro_8MHz
 atmega328_pro8_isp: MCU_TARGET = atmega328p
@@ -203,7 +226,6 @@ luminet: AVR_FREQ = 1000000L
 luminet: LDSECTION  = --section-start=.text=0x1d00
 luminet: $(PROGRAM)_luminet.hex
 luminet: $(PROGRAM)_luminet.lst
-
 luminet_isp: luminet
 luminet_isp: TARGET = luminet
 luminet_isp: MCU_TARGET = attiny84
@@ -212,6 +234,11 @@ luminet_isp: LFUSE = 62 # 1MHz internal oscillator, slowly rising power
 luminet_isp: EFUSE = FE # Self-programming enable
 luminet_isp: isp
 
+#
+# Generic build instructions
+#
+#
+
 isp: $(TARGET)
 	$(ISPFUSES)
 	$(ISPFLASH)

+ 2 - 0
optiboot/bootloaders/optiboot/makeall

@@ -9,5 +9,7 @@ make diecimila
 make ng
 make atmega328
 make atmega328_pro8
+make sanguino
+make mega
 make luminet
 

+ 116 - 104
optiboot/bootloaders/optiboot/optiboot.c

@@ -1,6 +1,8 @@
 /**********************************************************/
 /* Optiboot bootloader for Arduino                        */
 /*                                                        */
+/* http://optiboot.googlecode.com                         */
+/*                                                        */
 /* Heavily optimised bootloader that is faster and        */
 /* smaller than the Arduino standard bootloader           */
 /*                                                        */
@@ -10,6 +12,8 @@
 /*   Higher baud rate speeds up programming               */
 /*   Written almost entirely in C                         */
 /*   Customisable timeout with accurate timeconstant      */
+/*   Optional virtual UART. No hardware UART required.    */
+/*   Optional virtual boot partition for devices without. */
 /*                                                        */
 /* What you lose:                                         */
 /*   Implements a skeleton STK500 protocol which is       */
@@ -18,12 +22,19 @@
 /*   High baud rate breaks compatibility with standard    */
 /*     Arduino flash settings                             */
 /*                                                        */
-/* Currently supports:                                    */
-/*   ATmega168 based devices (Diecimila etc)              */
+/* Fully supported:                                       */
+/*   ATmega168 based devices  (Diecimila etc)             */
 /*   ATmega328P based devices (Duemilanove etc)           */
 /*                                                        */
+/* Alpha test                                             */
+/*   ATmega1280 based devices (Arduino Mega)              */
+/*                                                        */
+/* Work in progress:                                      */
+/*   ATmega644P based devices (Sanguino)                  */
+/*   ATtiny84 based devices (Luminet)                     */
+/*                                                        */
 /* Does not support:                                      */
-/*   ATmega1280 based devices (eg. Mega)                  */
+/*   USB based devices (eg. Teensy)                       */
 /*                                                        */
 /* Assumptions:                                           */
 /*   The code makes several assumptions that reduce the   */
@@ -64,102 +75,77 @@
 /*                                                        */
 /**********************************************************/
 
+
+/**********************************************************/
+/*                                                        */
+/* Optional defines:                                      */
+/*                                                        */
+/**********************************************************/
+/*                                                        */
+/* BIG_BOOT:                                              */
+/* Build a 1k bootloader, not 512 bytes. This turns on    */
+/* extra functionality.                                   */
+/*                                                        */
+/* BAUD_RATE:                                             */
+/* Set bootloader baud rate.                              */
+/*                                                        */
+/* LUDICROUS_SPEED:                                       */
+/* 230400 baud :-)                                        */
+/*                                                        */
+/* SOFT_UART:                                             */
+/* Use AVR305 soft-UART instead of hardware UART.         */
+/*                                                        */
+/* LED_START_FLASHES:                                     */
+/* Number of LED flashes on bootup.                       */
+/*                                                        */
+/* LED_DATA_FLASH:                                        */
+/* Flash LED when transferring data. For boards without   */
+/* TX or RX LEDs, or for people who like blinky lights.   */
+/*                                                        */
+/* SUPPORT_EEPROM:                                        */
+/* Support reading and writing from EEPROM. This is not   */
+/* used by Arduino, so off by default.                    */
+/*                                                        */
+/* TIMEOUT_MS:                                            */
+/* Bootloader timeout period, in milliseconds.            */
+/* 500,1000,2000,4000,8000 supported.                     */
+/*                                                        */
+/**********************************************************/
+
 #include <inttypes.h>
 #include <avr/io.h>
 #include <avr/pgmspace.h>
-#include <avr/boot.h>
 
-//#define LED_DATA_FLASH
+// <avr/boot.h> uses sts instructions, but this version uses out instructions
+// This saves cycles and program memory.
+#include "boot.h"
 
-#ifndef LED_START_FLASHES
-#define LED_START_FLASHES 0
-#endif
+// We don't use <avr/wdt.h> as those routines have interrupt overhead we don't need.
 
-/* Build-time variables */
-/* BAUD_RATE       Programming baud rate */
-/* LED_NO_FLASHES  Number of LED flashes on boot */
-/* FLASH_TIME_MS   Duration of each LED flash */
-/* BOOT_TIMEOUT_MS Serial port wait time before exiting bootloader */
+#include "pin_defs.h"
+#include "stk500.h"
 
-/* set the UART baud rate */
-#ifndef BAUD_RATE
-#define BAUD_RATE   19200
+#ifndef LED_START_FLASHES
+#define LED_START_FLASHES 0
 #endif
 
-#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
-/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */ 
-#define LED_DDR     DDRB
-#define LED_PORT    PORTB
-#define LED_PIN     PINB
-#define LED         PINB5
-
-/* Ports for soft UART */
-#ifdef SOFT_UART
-#define UART_PORT   PORTD
-#define UART_PIN    PIND
-#define UART_DDR    DDRD
-#define UART_TX_BIT 1
-#define UART_RX_BIT 0
-#endif
+#ifdef LUDICROUS_SPEED
+#define BAUD_RATE 230400L
 #endif
 
-#if defined(__AVR_ATtiny84__)
-/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */ 
-#define LED_DDR     DDRA
-#define LED_PORT    PORTA
-#define LED_PIN     PINA
-#define LED         PINA4
-
-/* Ports for soft UART - left port only for now*/
-#ifdef SOFT_UART
-#define UART_PORT   PORTA
-#define UART_PIN    PINA
-#define UART_DDR    DDRA
-#define UART_TX_BIT 2
-#define UART_RX_BIT 3
+/* set the UART baud rate defaults */
+#ifndef BAUD_RATE
+#if F_CPU >= 8000000L
+#define BAUD_RATE   115200L // Highest rate Avrdude win32 will support
+#elsif F_CPU >= 1000000L
+#define BAUD_RATE   9600L   // 19200 also supported, but with significant error
+#elsif F_CPU >= 128000L
+#define BAUD_RATE   4800L   // Good for 128kHz internal RC
+#else
+#define BAUD_RATE 1200L     // Good even at 32768Hz
 #endif
 #endif
 
-/* STK500 constants list, from AVRDUDE */
-#define STK_OK              0x10
-#define STK_FAILED          0x11  // Not used
-#define STK_UNKNOWN         0x12  // Not used
-#define STK_NODEVICE        0x13  // Not used
-#define STK_INSYNC          0x14  // ' '
-#define STK_NOSYNC          0x15  // Not used
-#define ADC_CHANNEL_ERROR   0x16  // Not used
-#define ADC_MEASURE_OK      0x17  // Not used
-#define PWM_CHANNEL_ERROR   0x18  // Not used
-#define PWM_ADJUST_OK       0x19  // Not used
-#define CRC_EOP             0x20  // 'SPACE'
-#define STK_GET_SYNC        0x30  // '0'
-#define STK_GET_SIGN_ON     0x31  // '1'
-#define STK_SET_PARAMETER   0x40  // '@'
-#define STK_GET_PARAMETER   0x41  // 'A'
-#define STK_SET_DEVICE      0x42  // 'B'
-#define STK_SET_DEVICE_EXT  0x45  // 'E'
-#define STK_ENTER_PROGMODE  0x50  // 'P'
-#define STK_LEAVE_PROGMODE  0x51  // 'Q'
-#define STK_CHIP_ERASE      0x52  // 'R'
-#define STK_CHECK_AUTOINC   0x53  // 'S'
-#define STK_LOAD_ADDRESS    0x55  // 'U'
-#define STK_UNIVERSAL       0x56  // 'V'
-#define STK_PROG_FLASH      0x60  // '`'
-#define STK_PROG_DATA       0x61  // 'a'
-#define STK_PROG_FUSE       0x62  // 'b'
-#define STK_PROG_LOCK       0x63  // 'c'
-#define STK_PROG_PAGE       0x64  // 'd'
-#define STK_PROG_FUSE_EXT   0x65  // 'e'
-#define STK_READ_FLASH      0x70  // 'p'
-#define STK_READ_DATA       0x71  // 'q'
-#define STK_READ_FUSE       0x72  // 'r'
-#define STK_READ_LOCK       0x73  // 's'
-#define STK_READ_PAGE       0x74  // 't'
-#define STK_READ_SIGN       0x75  // 'u'
-#define STK_READ_OSCCAL     0x76  // 'v'
-#define STK_READ_FUSE_EXT   0x77  // 'w'
-#define STK_READ_OSCCAL_EXT 0x78  // 'x'
-
 /* Watchdog settings */
 #define WATCHDOG_OFF    (0)
 #define WATCHDOG_16MS   (_BV(WDE))
@@ -191,16 +177,23 @@ void uartDelay() __attribute__ ((naked));
 #endif
 void appStart() __attribute__ ((naked));
 
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || (__AVR_ATmega644P__) || defined(__AVR_ATtiny84__)
+#define RAMSTART (0x100)
+#elif defined(__AVR_ATmega1280__)
+#define RAMSTART (0x200)
+#endif
+
 /* C zero initialises all global variables. However, that requires */
 /* These definitions are NOT zero initialised, but that doesn't matter */
 /* This allows us to drop the zero init code, saving us memory */
-#define buff    ((uint8_t*)(0x100))
-#define address (*(uint16_t*)(0x200))
-#define length  (*(uint8_t*)(0x202))
+#define buff    ((uint8_t*)(RAMSTART))
+#define address (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2))
+#define length  (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+2))
 #ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
   // After the zero init loop, this is the first code to run.
@@ -269,9 +262,15 @@ int main(void) {
     }
     else if(ch == STK_LOAD_ADDRESS) {
       // LOAD ADDRESS
-      address = getch();
-      address = (address & 0xff) | (getch() << 8);
-      address += address; // Convert from word address to byte address
+      uint16_t newAddress;
+      newAddress = getch();
+      newAddress = (newAddress & 0xff) | (getch() << 8);
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+      address = newAddress;
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
@@ -288,8 +287,8 @@ int main(void) {
       getLen();
 
       // Immediately start page erase - this will 4.5ms
-      boot_page_erase((uint16_t)(void*)address);
-
+      __boot_page_erase_short((uint16_t)(void*)address);
+      
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
@@ -310,10 +309,10 @@ int main(void) {
         // Move RESET vector to WDT vector
         uint16_t vect = buff[0] | (buff[1]<<8);
         rstVect = vect;
-        wdtVect = buff[10] | (buff[11]<<8);
+        wdtVect = buff[8] | (buff[9]<<8);
         vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
-        buff[10] = vect & 0xff;
-        buff[11] = vect >> 8;
+        buff[8] = vect & 0xff;
+        buff[9] = vect >> 8;
 
         // Add jump to bootloader at RESET vector
         buff[0] = 0x7f;
@@ -329,12 +328,12 @@ int main(void) {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
+      __boot_page_write_short((uint16_t)(void*)address);
       boot_spm_busy_wait();
 
 #if defined(RWWSRE)
@@ -353,15 +352,27 @@ int main(void) {
         // Undo vector patch in bottom page so verify passes
         if (address == 0)       ch=rstVect & 0xff;
         else if (address == 1)  ch=rstVect >> 8;
-        else if (address == 10)  ch=wdtVect & 0xff;
-        else if (address == 11) ch=wdtVect >> 8;
+        else if (address == 8)  ch=wdtVect & 0xff;
+        else if (address == 9) ch=wdtVect >> 8;
         else ch = pgm_read_byte_near(address);
         address++;
         putch(ch);
       } while (--length);
+#else
+#ifdef __AVR_ATmega1280__
+//      do putch(pgm_read_byte_near(address++));
+//      while (--length);
+      do {
+        uint8_t result;
+        __asm__ ("elpm %0,Z\n":"=r"(result):"z"(address));
+        putch(result);
+        address++;
+      }
+      while (--length);
 #else
       do putch(pgm_read_byte_near(address++));
       while (--length);
+#endif
 #endif
     }
 
@@ -462,7 +473,8 @@ uint8_t getch(void) {
 }
 
 #ifdef SOFT_UART
-//#define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
+// AVR350 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
+// Adding 3 to numerator simulates nearest rounding for more accurate baud rates
 #define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
 #if UART_B_VALUE > 255
 #error Baud rate too slow for soft UART
@@ -524,7 +536,7 @@ void appStart() {
   __asm__ __volatile__ (
 #ifdef VIRTUAL_BOOT_PARTITION
     // Jump to WDT vector
-    "ldi r30,5\n"
+    "ldi r30,4\n"
     "clr r31\n"
 #else
     // Jump to RST vector

+ 26 - 27
optiboot/bootloaders/optiboot/optiboot_atmega328.hex

@@ -1,33 +1,32 @@
 :107E000085E08093810082E08093C00088E18093C8
 :107E1000C10086E08093C20080E18093C40084B7F3
-:107E200014BE81FFD0D08DE0C8D0259A86E020E333
+:107E200014BE81FFC8D08DE0C0D0259A86E020E343
 :107E30003CEF91E0309385002093840096BBB09B8B
 :107E4000FECF1D9AA8958150A9F7DD24D394A5E013
-:107E5000EA2EF1E1FF2EA4D0813421F481E0BED0DE
-:107E600083E024C0823411F484E103C0853419F422
-:107E700085E0B4D08AC08535A1F492D0082F10E0F7
-:107E800010930102009300028BD090E0982F882776
-:107E9000802B912B880F991F9093010280930002F1
-:107EA00073C0863529F484E099D080E071D06DC02C
-:107EB000843609F043C07CD0E0910002F0910102C9
-:107EC00083E080935700E895C0E0D1E069D08993C2
-:107ED000809102028150809302028823B9F778D002
-:107EE00007B600FCFDCF4091000250910102A0E0D6
-:107EF000B1E02C9130E011968C91119790E0982F81
-:107F00008827822B932B1296FA010C01D0925700EE
-:107F1000E89511244E5F5F4FF1E0A038BF0749F7A5
-:107F2000E0910002F0910102E0925700E89507B657
-:107F300000FCFDCFF0925700E89527C08437B9F4D4
-:107F400037D046D0E0910002F09101023196F093D3
-:107F50000102E09300023197E4918E2F19D08091B5
-:107F60000202815080930202882361F70EC0853798
-:107F700039F42ED08EE10CD085E90AD08FE096CF6F
-:107F8000813511F488E019D023D080E101D063CF8E
-:107F9000982F8091C00085FFFCCF9093C600089574
-:107FA000A8958091C00087FFFCCF8091C6000895FE
-:107FB000F7DFF6DF80930202F3CFE0E6F0E098E12E
-:107FC00090838083089580E0F8DFEE27FF270994EF
-:107FD000E7DF803209F0F7DF84E1DACF1F93182F53
-:0C7FE000DFDF1150E9F7F4DF1F91089576
+:107E5000FA2EF1E1EF2E9CD0813421F481E0B6D0EE
+:107E600083E020C0823411F484E103C0853419F426
+:107E700085E0ACD082C0853581F48AD0082F10E02F
+:107E800087D090E0982F8827802B912B880F991FFF
+:107E900090930102809300026FC0863529F484E03C
+:107EA00095D080E06DD069C0843609F03FC078D0AD
+:107EB000E0910002F091010283E087BFE895C0E005
+:107EC000D1E066D0899380910202815080930202B2
+:107ED0008823B9F775D007B600FCFDCF40910002AA
+:107EE00050910102A0E0B1E02C9130E011968C910C
+:107EF000119790E0982F8827822B932B1296FA01E6
+:107F00000C01D7BEE89511244E5F5F4FF1E0A03819
+:107F1000BF0751F7E0910002F0910102F7BEE8952A
+:107F200007B600FCFDCFE7BEE89527C08437B9F45B
+:107F300037D046D0E0910002F09101023196F093E3
+:107F40000102E09300023197E4918E2F19D08091C5
+:107F50000202815080930202882361F70EC08537A8
+:107F600039F42ED08EE10CD085E90AD08FE09ACF7B
+:107F7000813511F488E019D023D080E101D06BCF96
+:107F8000982F8091C00085FFFCCF9093C600089584
+:107F9000A8958091C00087FFFCCF8091C60008950E
+:107FA000F7DFF6DF80930202F3CFE0E6F0E098E13E
+:107FB00090838083089580E0F8DFEE27FF270994FF
+:107FC000E7DF803209F0F7DF84E1DACF1F93182F63
+:0C7FD000DFDF1150E9F7F4DF1F91089586
 :0400000300007E007B
 :00000001FF

+ 206 - 201
optiboot/bootloaders/optiboot/optiboot_atmega328.lst

@@ -3,34 +3,34 @@ optiboot_atmega328.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001ec  00007e00  00007e00  00000054  2**1
+  0 .text         000001dc  00007e00  00007e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  00000240  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000230  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 0000006a  00000000  00000000  00000268  2**0
+  2 .debug_pubnames 0000006a  00000000  00000000  00000258  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   00000269  00000000  00000000  000002d2  2**0
+  3 .debug_info   00000283  00000000  00000000  000002c2  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000196  00000000  00000000  0000053b  2**0
+  4 .debug_abbrev 000001ae  00000000  00000000  00000545  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003d3  00000000  00000000  000006d1  2**0
+  5 .debug_line   000003db  00000000  00000000  000006f3  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000aa4  2**2
+  6 .debug_frame  00000090  00000000  00000000  00000ad0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    00000135  00000000  00000000  00000b34  2**0
+  7 .debug_str    00000140  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d1  00000000  00000000  00000c69  2**0
+  8 .debug_loc    000001d1  00000000  00000000  00000ca0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000e3a  2**0
+  9 .debug_ranges 00000068  00000000  00000000  00000e71  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
 
 00007e00 <main>:
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
     7e00:	85 e0       	ldi	r24, 0x05	; 5
@@ -61,12 +61,12 @@ int main(void) {
     7e20:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
     7e22:	81 ff       	sbrs	r24, 1
-    7e24:	d0 d0       	rcall	.+416    	; 0x7fc6 <appStart>
+    7e24:	c8 d0       	rcall	.+400    	; 0x7fb6 <appStart>
 
   // Set up watchdog to trigger after 500ms
   watchdogConfig(WATCHDOG_500MS);
     7e26:	8d e0       	ldi	r24, 0x0D	; 13
-    7e28:	c8 d0       	rcall	.+400    	; 0x7fba <watchdogConfig>
+    7e28:	c0 d0       	rcall	.+384    	; 0x7faa <watchdogConfig>
 
   /* Set LED pin as output */
   LED_DDR |= _BV(LED);
@@ -120,28 +120,28 @@ void watchdogReset() {
       getNch(1);
     7e4a:	dd 24       	eor	r13, r13
     7e4c:	d3 94       	inc	r13
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
+      __boot_page_write_short((uint16_t)(void*)address);
     7e4e:	a5 e0       	ldi	r26, 0x05	; 5
-    7e50:	ea 2e       	mov	r14, r26
+    7e50:	fa 2e       	mov	r15, r26
       boot_spm_busy_wait();
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
     7e52:	f1 e1       	ldi	r31, 0x11	; 17
-    7e54:	ff 2e       	mov	r15, r31
+    7e54:	ef 2e       	mov	r14, r31
 #endif
 
   /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    7e56:	a4 d0       	rcall	.+328    	; 0x7fa0 <getch>
+    7e56:	9c d0       	rcall	.+312    	; 0x7f90 <getch>
 
     if(ch == STK_GET_PARAMETER) {
     7e58:	81 34       	cpi	r24, 0x41	; 65
@@ -149,10 +149,10 @@ void watchdogReset() {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
     7e5c:	81 e0       	ldi	r24, 0x01	; 1
-    7e5e:	be d0       	rcall	.+380    	; 0x7fdc <verifySpace+0xc>
+    7e5e:	b6 d0       	rcall	.+364    	; 0x7fcc <verifySpace+0xc>
       putch(0x03);
     7e60:	83 e0       	ldi	r24, 0x03	; 3
-    7e62:	24 c0       	rjmp	.+72     	; 0x7eac <main+0xac>
+    7e62:	20 c0       	rjmp	.+64     	; 0x7ea4 <main+0xa4>
     }
     else if(ch == STK_SET_DEVICE) {
     7e64:	82 34       	cpi	r24, 0x42	; 66
@@ -168,353 +168,358 @@ void watchdogReset() {
       // SET DEVICE EXT is ignored
       getNch(5);
     7e70:	85 e0       	ldi	r24, 0x05	; 5
-    7e72:	b4 d0       	rcall	.+360    	; 0x7fdc <verifySpace+0xc>
-    7e74:	8a c0       	rjmp	.+276    	; 0x7f8a <main+0x18a>
+    7e72:	ac d0       	rcall	.+344    	; 0x7fcc <verifySpace+0xc>
+    7e74:	82 c0       	rjmp	.+260    	; 0x7f7a <main+0x17a>
     }
     else if(ch == STK_LOAD_ADDRESS) {
     7e76:	85 35       	cpi	r24, 0x55	; 85
-    7e78:	a1 f4       	brne	.+40     	; 0x7ea2 <main+0xa2>
+    7e78:	81 f4       	brne	.+32     	; 0x7e9a <main+0x9a>
       // LOAD ADDRESS
-      address = getch();
-    7e7a:	92 d0       	rcall	.+292    	; 0x7fa0 <getch>
+      uint16_t newAddress;
+      newAddress = getch();
+    7e7a:	8a d0       	rcall	.+276    	; 0x7f90 <getch>
+      newAddress = (newAddress & 0xff) | (getch() << 8);
     7e7c:	08 2f       	mov	r16, r24
     7e7e:	10 e0       	ldi	r17, 0x00	; 0
-    7e80:	10 93 01 02 	sts	0x0201, r17
-    7e84:	00 93 00 02 	sts	0x0200, r16
-      address = (address & 0xff) | (getch() << 8);
-    7e88:	8b d0       	rcall	.+278    	; 0x7fa0 <getch>
-    7e8a:	90 e0       	ldi	r25, 0x00	; 0
-    7e8c:	98 2f       	mov	r25, r24
-    7e8e:	88 27       	eor	r24, r24
-    7e90:	80 2b       	or	r24, r16
-    7e92:	91 2b       	or	r25, r17
-      address += address; // Convert from word address to byte address
-    7e94:	88 0f       	add	r24, r24
-    7e96:	99 1f       	adc	r25, r25
-    7e98:	90 93 01 02 	sts	0x0201, r25
-    7e9c:	80 93 00 02 	sts	0x0200, r24
-    7ea0:	73 c0       	rjmp	.+230    	; 0x7f88 <main+0x188>
+    7e80:	87 d0       	rcall	.+270    	; 0x7f90 <getch>
+    7e82:	90 e0       	ldi	r25, 0x00	; 0
+    7e84:	98 2f       	mov	r25, r24
+    7e86:	88 27       	eor	r24, r24
+    7e88:	80 2b       	or	r24, r16
+    7e8a:	91 2b       	or	r25, r17
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+    7e8c:	88 0f       	add	r24, r24
+    7e8e:	99 1f       	adc	r25, r25
+      address = newAddress;
+    7e90:	90 93 01 02 	sts	0x0201, r25
+    7e94:	80 93 00 02 	sts	0x0200, r24
+    7e98:	6f c0       	rjmp	.+222    	; 0x7f78 <main+0x178>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    7ea2:	86 35       	cpi	r24, 0x56	; 86
-    7ea4:	29 f4       	brne	.+10     	; 0x7eb0 <main+0xb0>
+    7e9a:	86 35       	cpi	r24, 0x56	; 86
+    7e9c:	29 f4       	brne	.+10     	; 0x7ea8 <main+0xa8>
       // UNIVERSAL command is ignored
       getNch(4);
-    7ea6:	84 e0       	ldi	r24, 0x04	; 4
-    7ea8:	99 d0       	rcall	.+306    	; 0x7fdc <verifySpace+0xc>
+    7e9e:	84 e0       	ldi	r24, 0x04	; 4
+    7ea0:	95 d0       	rcall	.+298    	; 0x7fcc <verifySpace+0xc>
       putch(0x00);
-    7eaa:	80 e0       	ldi	r24, 0x00	; 0
-    7eac:	71 d0       	rcall	.+226    	; 0x7f90 <putch>
-    7eae:	6d c0       	rjmp	.+218    	; 0x7f8a <main+0x18a>
+    7ea2:	80 e0       	ldi	r24, 0x00	; 0
+    7ea4:	6d d0       	rcall	.+218    	; 0x7f80 <putch>
+    7ea6:	69 c0       	rjmp	.+210    	; 0x7f7a <main+0x17a>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    7eb0:	84 36       	cpi	r24, 0x64	; 100
-    7eb2:	09 f0       	breq	.+2      	; 0x7eb6 <main+0xb6>
-    7eb4:	43 c0       	rjmp	.+134    	; 0x7f3c <main+0x13c>
+    7ea8:	84 36       	cpi	r24, 0x64	; 100
+    7eaa:	09 f0       	breq	.+2      	; 0x7eae <main+0xae>
+    7eac:	3f c0       	rjmp	.+126    	; 0x7f2c <main+0x12c>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
 
       getLen();
-    7eb6:	7c d0       	rcall	.+248    	; 0x7fb0 <getLen>
+    7eae:	78 d0       	rcall	.+240    	; 0x7fa0 <getLen>
 
       // Immediately start page erase - this will 4.5ms
-      boot_page_erase((uint16_t)(void*)address);
-    7eb8:	e0 91 00 02 	lds	r30, 0x0200
-    7ebc:	f0 91 01 02 	lds	r31, 0x0201
-    7ec0:	83 e0       	ldi	r24, 0x03	; 3
-    7ec2:	80 93 57 00 	sts	0x0057, r24
-    7ec6:	e8 95       	spm
-    7ec8:	c0 e0       	ldi	r28, 0x00	; 0
-    7eca:	d1 e0       	ldi	r29, 0x01	; 1
-
+      __boot_page_erase_short((uint16_t)(void*)address);
+    7eb0:	e0 91 00 02 	lds	r30, 0x0200
+    7eb4:	f0 91 01 02 	lds	r31, 0x0201
+    7eb8:	83 e0       	ldi	r24, 0x03	; 3
+    7eba:	87 bf       	out	0x37, r24	; 55
+    7ebc:	e8 95       	spm
+    7ebe:	c0 e0       	ldi	r28, 0x00	; 0
+    7ec0:	d1 e0       	ldi	r29, 0x01	; 1
+      
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    7ecc:	69 d0       	rcall	.+210    	; 0x7fa0 <getch>
-    7ece:	89 93       	st	Y+, r24
+    7ec2:	66 d0       	rcall	.+204    	; 0x7f90 <getch>
+    7ec4:	89 93       	st	Y+, r24
       while (--length);
-    7ed0:	80 91 02 02 	lds	r24, 0x0202
-    7ed4:	81 50       	subi	r24, 0x01	; 1
-    7ed6:	80 93 02 02 	sts	0x0202, r24
-    7eda:	88 23       	and	r24, r24
-    7edc:	b9 f7       	brne	.-18     	; 0x7ecc <main+0xcc>
+    7ec6:	80 91 02 02 	lds	r24, 0x0202
+    7eca:	81 50       	subi	r24, 0x01	; 1
+    7ecc:	80 93 02 02 	sts	0x0202, r24
+    7ed0:	88 23       	and	r24, r24
+    7ed2:	b9 f7       	brne	.-18     	; 0x7ec2 <main+0xc2>
 
       // Read command terminator, start reply
       verifySpace();
-    7ede:	78 d0       	rcall	.+240    	; 0x7fd0 <verifySpace>
+    7ed4:	75 d0       	rcall	.+234    	; 0x7fc0 <verifySpace>
       
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    7ee0:	07 b6       	in	r0, 0x37	; 55
-    7ee2:	00 fc       	sbrc	r0, 0
-    7ee4:	fd cf       	rjmp	.-6      	; 0x7ee0 <main+0xe0>
+    7ed6:	07 b6       	in	r0, 0x37	; 55
+    7ed8:	00 fc       	sbrc	r0, 0
+    7eda:	fd cf       	rjmp	.-6      	; 0x7ed6 <main+0xd6>
       }
 #endif
 
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    7ee6:	40 91 00 02 	lds	r20, 0x0200
-    7eea:	50 91 01 02 	lds	r21, 0x0201
-    7eee:	a0 e0       	ldi	r26, 0x00	; 0
-    7ef0:	b1 e0       	ldi	r27, 0x01	; 1
+    7edc:	40 91 00 02 	lds	r20, 0x0200
+    7ee0:	50 91 01 02 	lds	r21, 0x0201
+    7ee4:	a0 e0       	ldi	r26, 0x00	; 0
+    7ee6:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    7ef2:	2c 91       	ld	r18, X
-    7ef4:	30 e0       	ldi	r19, 0x00	; 0
+    7ee8:	2c 91       	ld	r18, X
+    7eea:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    7ef6:	11 96       	adiw	r26, 0x01	; 1
-    7ef8:	8c 91       	ld	r24, X
-    7efa:	11 97       	sbiw	r26, 0x01	; 1
-    7efc:	90 e0       	ldi	r25, 0x00	; 0
-    7efe:	98 2f       	mov	r25, r24
-    7f00:	88 27       	eor	r24, r24
-    7f02:	82 2b       	or	r24, r18
-    7f04:	93 2b       	or	r25, r19
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+    7eec:	11 96       	adiw	r26, 0x01	; 1
+    7eee:	8c 91       	ld	r24, X
+    7ef0:	11 97       	sbiw	r26, 0x01	; 1
+    7ef2:	90 e0       	ldi	r25, 0x00	; 0
+    7ef4:	98 2f       	mov	r25, r24
+    7ef6:	88 27       	eor	r24, r24
+    7ef8:	82 2b       	or	r24, r18
+    7efa:	93 2b       	or	r25, r19
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
-    7f06:	12 96       	adiw	r26, 0x02	; 2
+    7efc:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
-    7f08:	fa 01       	movw	r30, r20
-    7f0a:	0c 01       	movw	r0, r24
-    7f0c:	d0 92 57 00 	sts	0x0057, r13
-    7f10:	e8 95       	spm
-    7f12:	11 24       	eor	r1, r1
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+    7efe:	fa 01       	movw	r30, r20
+    7f00:	0c 01       	movw	r0, r24
+    7f02:	d7 be       	out	0x37, r13	; 55
+    7f04:	e8 95       	spm
+    7f06:	11 24       	eor	r1, r1
         addrPtr += 2;
-    7f14:	4e 5f       	subi	r20, 0xFE	; 254
-    7f16:	5f 4f       	sbci	r21, 0xFF	; 255
+    7f08:	4e 5f       	subi	r20, 0xFE	; 254
+    7f0a:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    7f18:	f1 e0       	ldi	r31, 0x01	; 1
-    7f1a:	a0 38       	cpi	r26, 0x80	; 128
-    7f1c:	bf 07       	cpc	r27, r31
-    7f1e:	49 f7       	brne	.-46     	; 0x7ef2 <main+0xf2>
+    7f0c:	f1 e0       	ldi	r31, 0x01	; 1
+    7f0e:	a0 38       	cpi	r26, 0x80	; 128
+    7f10:	bf 07       	cpc	r27, r31
+    7f12:	51 f7       	brne	.-44     	; 0x7ee8 <main+0xe8>
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
-    7f20:	e0 91 00 02 	lds	r30, 0x0200
-    7f24:	f0 91 01 02 	lds	r31, 0x0201
-    7f28:	e0 92 57 00 	sts	0x0057, r14
-    7f2c:	e8 95       	spm
+      __boot_page_write_short((uint16_t)(void*)address);
+    7f14:	e0 91 00 02 	lds	r30, 0x0200
+    7f18:	f0 91 01 02 	lds	r31, 0x0201
+    7f1c:	f7 be       	out	0x37, r15	; 55
+    7f1e:	e8 95       	spm
       boot_spm_busy_wait();
-    7f2e:	07 b6       	in	r0, 0x37	; 55
-    7f30:	00 fc       	sbrc	r0, 0
-    7f32:	fd cf       	rjmp	.-6      	; 0x7f2e <main+0x12e>
+    7f20:	07 b6       	in	r0, 0x37	; 55
+    7f22:	00 fc       	sbrc	r0, 0
+    7f24:	fd cf       	rjmp	.-6      	; 0x7f20 <main+0x120>
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
-    7f34:	f0 92 57 00 	sts	0x0057, r15
-    7f38:	e8 95       	spm
-    7f3a:	27 c0       	rjmp	.+78     	; 0x7f8a <main+0x18a>
+    7f26:	e7 be       	out	0x37, r14	; 55
+    7f28:	e8 95       	spm
+    7f2a:	27 c0       	rjmp	.+78     	; 0x7f7a <main+0x17a>
 #endif
 
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    7f3c:	84 37       	cpi	r24, 0x74	; 116
-    7f3e:	b9 f4       	brne	.+46     	; 0x7f6e <main+0x16e>
+    7f2c:	84 37       	cpi	r24, 0x74	; 116
+    7f2e:	b9 f4       	brne	.+46     	; 0x7f5e <main+0x15e>
       // READ PAGE - we only read flash
       getLen();
-    7f40:	37 d0       	rcall	.+110    	; 0x7fb0 <getLen>
+    7f30:	37 d0       	rcall	.+110    	; 0x7fa0 <getLen>
       verifySpace();
-    7f42:	46 d0       	rcall	.+140    	; 0x7fd0 <verifySpace>
-        else ch = pgm_read_byte_near(address);
+    7f32:	46 d0       	rcall	.+140    	; 0x7fc0 <verifySpace>
+        putch(result);
         address++;
-        putch(ch);
-      } while (--length);
+      }
+      while (--length);
 #else
       do putch(pgm_read_byte_near(address++));
-    7f44:	e0 91 00 02 	lds	r30, 0x0200
-    7f48:	f0 91 01 02 	lds	r31, 0x0201
-    7f4c:	31 96       	adiw	r30, 0x01	; 1
-    7f4e:	f0 93 01 02 	sts	0x0201, r31
-    7f52:	e0 93 00 02 	sts	0x0200, r30
-    7f56:	31 97       	sbiw	r30, 0x01	; 1
-    7f58:	e4 91       	lpm	r30, Z+
-    7f5a:	8e 2f       	mov	r24, r30
-    7f5c:	19 d0       	rcall	.+50     	; 0x7f90 <putch>
+    7f34:	e0 91 00 02 	lds	r30, 0x0200
+    7f38:	f0 91 01 02 	lds	r31, 0x0201
+    7f3c:	31 96       	adiw	r30, 0x01	; 1
+    7f3e:	f0 93 01 02 	sts	0x0201, r31
+    7f42:	e0 93 00 02 	sts	0x0200, r30
+    7f46:	31 97       	sbiw	r30, 0x01	; 1
+    7f48:	e4 91       	lpm	r30, Z+
+    7f4a:	8e 2f       	mov	r24, r30
+    7f4c:	19 d0       	rcall	.+50     	; 0x7f80 <putch>
       while (--length);
-    7f5e:	80 91 02 02 	lds	r24, 0x0202
-    7f62:	81 50       	subi	r24, 0x01	; 1
-    7f64:	80 93 02 02 	sts	0x0202, r24
-    7f68:	88 23       	and	r24, r24
-    7f6a:	61 f7       	brne	.-40     	; 0x7f44 <main+0x144>
-    7f6c:	0e c0       	rjmp	.+28     	; 0x7f8a <main+0x18a>
+    7f4e:	80 91 02 02 	lds	r24, 0x0202
+    7f52:	81 50       	subi	r24, 0x01	; 1
+    7f54:	80 93 02 02 	sts	0x0202, r24
+    7f58:	88 23       	and	r24, r24
+    7f5a:	61 f7       	brne	.-40     	; 0x7f34 <main+0x134>
+    7f5c:	0e c0       	rjmp	.+28     	; 0x7f7a <main+0x17a>
+#endif
 #endif
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    7f6e:	85 37       	cpi	r24, 0x75	; 117
-    7f70:	39 f4       	brne	.+14     	; 0x7f80 <main+0x180>
+    7f5e:	85 37       	cpi	r24, 0x75	; 117
+    7f60:	39 f4       	brne	.+14     	; 0x7f70 <main+0x170>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    7f72:	2e d0       	rcall	.+92     	; 0x7fd0 <verifySpace>
+    7f62:	2e d0       	rcall	.+92     	; 0x7fc0 <verifySpace>
       putch(SIGNATURE_0);
-    7f74:	8e e1       	ldi	r24, 0x1E	; 30
-    7f76:	0c d0       	rcall	.+24     	; 0x7f90 <putch>
+    7f64:	8e e1       	ldi	r24, 0x1E	; 30
+    7f66:	0c d0       	rcall	.+24     	; 0x7f80 <putch>
       putch(SIGNATURE_1);
-    7f78:	85 e9       	ldi	r24, 0x95	; 149
-    7f7a:	0a d0       	rcall	.+20     	; 0x7f90 <putch>
+    7f68:	85 e9       	ldi	r24, 0x95	; 149
+    7f6a:	0a d0       	rcall	.+20     	; 0x7f80 <putch>
       putch(SIGNATURE_2);
-    7f7c:	8f e0       	ldi	r24, 0x0F	; 15
-    7f7e:	96 cf       	rjmp	.-212    	; 0x7eac <main+0xac>
+    7f6c:	8f e0       	ldi	r24, 0x0F	; 15
+    7f6e:	9a cf       	rjmp	.-204    	; 0x7ea4 <main+0xa4>
     }
     else if (ch == 'Q') {
-    7f80:	81 35       	cpi	r24, 0x51	; 81
-    7f82:	11 f4       	brne	.+4      	; 0x7f88 <main+0x188>
+    7f70:	81 35       	cpi	r24, 0x51	; 81
+    7f72:	11 f4       	brne	.+4      	; 0x7f78 <main+0x178>
       // Adaboot no-wait mod
       watchdogConfig(WATCHDOG_16MS);
-    7f84:	88 e0       	ldi	r24, 0x08	; 8
-    7f86:	19 d0       	rcall	.+50     	; 0x7fba <watchdogConfig>
+    7f74:	88 e0       	ldi	r24, 0x08	; 8
+    7f76:	19 d0       	rcall	.+50     	; 0x7faa <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    7f88:	23 d0       	rcall	.+70     	; 0x7fd0 <verifySpace>
+    7f78:	23 d0       	rcall	.+70     	; 0x7fc0 <verifySpace>
     }
     putch(STK_OK);
-    7f8a:	80 e1       	ldi	r24, 0x10	; 16
-    7f8c:	01 d0       	rcall	.+2      	; 0x7f90 <putch>
-    7f8e:	63 cf       	rjmp	.-314    	; 0x7e56 <main+0x56>
+    7f7a:	80 e1       	ldi	r24, 0x10	; 16
+    7f7c:	01 d0       	rcall	.+2      	; 0x7f80 <putch>
+    7f7e:	6b cf       	rjmp	.-298    	; 0x7e56 <main+0x56>
 
-00007f90 <putch>:
+00007f80 <putch>:
   }
 }
 
 void putch(char ch) {
-    7f90:	98 2f       	mov	r25, r24
+    7f80:	98 2f       	mov	r25, r24
 #ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    7f92:	80 91 c0 00 	lds	r24, 0x00C0
-    7f96:	85 ff       	sbrs	r24, 5
-    7f98:	fc cf       	rjmp	.-8      	; 0x7f92 <putch+0x2>
+    7f82:	80 91 c0 00 	lds	r24, 0x00C0
+    7f86:	85 ff       	sbrs	r24, 5
+    7f88:	fc cf       	rjmp	.-8      	; 0x7f82 <putch+0x2>
   UDR0 = ch;
-    7f9a:	90 93 c6 00 	sts	0x00C6, r25
+    7f8a:	90 93 c6 00 	sts	0x00C6, r25
       [uartBit] "I" (UART_TX_BIT)
     :
       "r25"
   );
 #endif
 }
-    7f9e:	08 95       	ret
+    7f8e:	08 95       	ret
 
-00007fa0 <getch>:
+00007f90 <getch>:
   return getch();
 }
 
 // Watchdog functions. These are only safe with interrupts turned off.
 void watchdogReset() {
   __asm__ __volatile__ (
-    7fa0:	a8 95       	wdr
+    7f90:	a8 95       	wdr
       [uartBit] "I" (UART_RX_BIT)
     :
       "r25"
 );
 #else
   while(!(UCSR0A & _BV(RXC0)));
-    7fa2:	80 91 c0 00 	lds	r24, 0x00C0
-    7fa6:	87 ff       	sbrs	r24, 7
-    7fa8:	fc cf       	rjmp	.-8      	; 0x7fa2 <getch+0x2>
+    7f92:	80 91 c0 00 	lds	r24, 0x00C0
+    7f96:	87 ff       	sbrs	r24, 7
+    7f98:	fc cf       	rjmp	.-8      	; 0x7f92 <getch+0x2>
   ch = UDR0;
-    7faa:	80 91 c6 00 	lds	r24, 0x00C6
+    7f9a:	80 91 c6 00 	lds	r24, 0x00C6
 #ifdef LED_DATA_FLASH
   LED_PIN |= _BV(LED);
 #endif
 
   return ch;
 }
-    7fae:	08 95       	ret
+    7f9e:	08 95       	ret
 
-00007fb0 <getLen>:
+00007fa0 <getLen>:
   } while (--count);
 }
 #endif
 
 uint8_t getLen() {
   getch();
-    7fb0:	f7 df       	rcall	.-18     	; 0x7fa0 <getch>
+    7fa0:	f7 df       	rcall	.-18     	; 0x7f90 <getch>
   length = getch();
-    7fb2:	f6 df       	rcall	.-20     	; 0x7fa0 <getch>
-    7fb4:	80 93 02 02 	sts	0x0202, r24
+    7fa2:	f6 df       	rcall	.-20     	; 0x7f90 <getch>
+    7fa4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    7fb8:	f3 cf       	rjmp	.-26     	; 0x7fa0 <getch>
+    7fa8:	f3 cf       	rjmp	.-26     	; 0x7f90 <getch>
 
-00007fba <watchdogConfig>:
+00007faa <watchdogConfig>:
     "wdr\n"
   );
 }
 
 void watchdogConfig(uint8_t x) {
   WDTCSR = _BV(WDCE) | _BV(WDE);
-    7fba:	e0 e6       	ldi	r30, 0x60	; 96
-    7fbc:	f0 e0       	ldi	r31, 0x00	; 0
-    7fbe:	98 e1       	ldi	r25, 0x18	; 24
-    7fc0:	90 83       	st	Z, r25
+    7faa:	e0 e6       	ldi	r30, 0x60	; 96
+    7fac:	f0 e0       	ldi	r31, 0x00	; 0
+    7fae:	98 e1       	ldi	r25, 0x18	; 24
+    7fb0:	90 83       	st	Z, r25
   WDTCSR = x;
-    7fc2:	80 83       	st	Z, r24
+    7fb2:	80 83       	st	Z, r24
 }
-    7fc4:	08 95       	ret
+    7fb4:	08 95       	ret
 
-00007fc6 <appStart>:
+00007fb6 <appStart>:
 
 void appStart() {
   watchdogConfig(WATCHDOG_OFF);
-    7fc6:	80 e0       	ldi	r24, 0x00	; 0
-    7fc8:	f8 df       	rcall	.-16     	; 0x7fba <watchdogConfig>
+    7fb6:	80 e0       	ldi	r24, 0x00	; 0
+    7fb8:	f8 df       	rcall	.-16     	; 0x7faa <watchdogConfig>
   __asm__ __volatile__ (
-    7fca:	ee 27       	eor	r30, r30
-    7fcc:	ff 27       	eor	r31, r31
-    7fce:	09 94       	ijmp
+    7fba:	ee 27       	eor	r30, r30
+    7fbc:	ff 27       	eor	r31, r31
+    7fbe:	09 94       	ijmp
 
-00007fd0 <verifySpace>:
+00007fc0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    7fd0:	e7 df       	rcall	.-50     	; 0x7fa0 <getch>
-    7fd2:	80 32       	cpi	r24, 0x20	; 32
-    7fd4:	09 f0       	breq	.+2      	; 0x7fd8 <verifySpace+0x8>
-    7fd6:	f7 df       	rcall	.-18     	; 0x7fc6 <appStart>
+    7fc0:	e7 df       	rcall	.-50     	; 0x7f90 <getch>
+    7fc2:	80 32       	cpi	r24, 0x20	; 32
+    7fc4:	09 f0       	breq	.+2      	; 0x7fc8 <verifySpace+0x8>
+    7fc6:	f7 df       	rcall	.-18     	; 0x7fb6 <appStart>
   putch(STK_INSYNC);
-    7fd8:	84 e1       	ldi	r24, 0x14	; 20
+    7fc8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    7fda:	da cf       	rjmp	.-76     	; 0x7f90 <putch>
+    7fca:	da cf       	rjmp	.-76     	; 0x7f80 <putch>
     ::[count] "M" (UART_B_VALUE)
   );
 }
 #endif
 
 void getNch(uint8_t count) {
-    7fdc:	1f 93       	push	r17
-    7fde:	18 2f       	mov	r17, r24
+    7fcc:	1f 93       	push	r17
+    7fce:	18 2f       	mov	r17, r24
 
-00007fe0 <getNch>:
+00007fd0 <getNch>:
   do getch(); while (--count);
-    7fe0:	df df       	rcall	.-66     	; 0x7fa0 <getch>
-    7fe2:	11 50       	subi	r17, 0x01	; 1
-    7fe4:	e9 f7       	brne	.-6      	; 0x7fe0 <getNch>
+    7fd0:	df df       	rcall	.-66     	; 0x7f90 <getch>
+    7fd2:	11 50       	subi	r17, 0x01	; 1
+    7fd4:	e9 f7       	brne	.-6      	; 0x7fd0 <getNch>
   verifySpace();
-    7fe6:	f4 df       	rcall	.-24     	; 0x7fd0 <verifySpace>
+    7fd6:	f4 df       	rcall	.-24     	; 0x7fc0 <verifySpace>
 }
-    7fe8:	1f 91       	pop	r17
-    7fea:	08 95       	ret
+    7fd8:	1f 91       	pop	r17
+    7fda:	08 95       	ret

+ 26 - 27
optiboot/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex

@@ -1,33 +1,32 @@
 :107E000085E08093810082E08093C00088E18093C8
 :107E1000C10086E08093C20088E08093C40084B7EC
-:107E200014BE81FFD0D08DE0C8D0259A86E028E12D
+:107E200014BE81FFC8D08DE0C0D0259A86E028E13D
 :107E30003EEF91E0309385002093840096BBB09B89
 :107E4000FECF1D9AA8958150A9F7DD24D394A5E013
-:107E5000EA2EF1E1FF2EA4D0813421F481E0BED0DE
-:107E600083E024C0823411F484E103C0853419F422
-:107E700085E0B4D08AC08535A1F492D0082F10E0F7
-:107E800010930102009300028BD090E0982F882776
-:107E9000802B912B880F991F9093010280930002F1
-:107EA00073C0863529F484E099D080E071D06DC02C
-:107EB000843609F043C07CD0E0910002F0910102C9
-:107EC00083E080935700E895C0E0D1E069D08993C2
-:107ED000809102028150809302028823B9F778D002
-:107EE00007B600FCFDCF4091000250910102A0E0D6
-:107EF000B1E02C9130E011968C91119790E0982F81
-:107F00008827822B932B1296FA010C01D0925700EE
-:107F1000E89511244E5F5F4FF1E0A038BF0749F7A5
-:107F2000E0910002F0910102E0925700E89507B657
-:107F300000FCFDCFF0925700E89527C08437B9F4D4
-:107F400037D046D0E0910002F09101023196F093D3
-:107F50000102E09300023197E4918E2F19D08091B5
-:107F60000202815080930202882361F70EC0853798
-:107F700039F42ED08EE10CD085E90AD08FE096CF6F
-:107F8000813511F488E019D023D080E101D063CF8E
-:107F9000982F8091C00085FFFCCF9093C600089574
-:107FA000A8958091C00087FFFCCF8091C6000895FE
-:107FB000F7DFF6DF80930202F3CFE0E6F0E098E12E
-:107FC00090838083089580E0F8DFEE27FF270994EF
-:107FD000E7DF803209F0F7DF84E1DACF1F93182F53
-:0C7FE000DFDF1150E9F7F4DF1F91089576
+:107E5000FA2EF1E1EF2E9CD0813421F481E0B6D0EE
+:107E600083E020C0823411F484E103C0853419F426
+:107E700085E0ACD082C0853581F48AD0082F10E02F
+:107E800087D090E0982F8827802B912B880F991FFF
+:107E900090930102809300026FC0863529F484E03C
+:107EA00095D080E06DD069C0843609F03FC078D0AD
+:107EB000E0910002F091010283E087BFE895C0E005
+:107EC000D1E066D0899380910202815080930202B2
+:107ED0008823B9F775D007B600FCFDCF40910002AA
+:107EE00050910102A0E0B1E02C9130E011968C910C
+:107EF000119790E0982F8827822B932B1296FA01E6
+:107F00000C01D7BEE89511244E5F5F4FF1E0A03819
+:107F1000BF0751F7E0910002F0910102F7BEE8952A
+:107F200007B600FCFDCFE7BEE89527C08437B9F45B
+:107F300037D046D0E0910002F09101023196F093E3
+:107F40000102E09300023197E4918E2F19D08091C5
+:107F50000202815080930202882361F70EC08537A8
+:107F600039F42ED08EE10CD085E90AD08FE09ACF7B
+:107F7000813511F488E019D023D080E101D06BCF96
+:107F8000982F8091C00085FFFCCF9093C600089584
+:107F9000A8958091C00087FFFCCF8091C60008950E
+:107FA000F7DFF6DF80930202F3CFE0E6F0E098E13E
+:107FB00090838083089580E0F8DFEE27FF270994FF
+:107FC000E7DF803209F0F7DF84E1DACF1F93182F63
+:0C7FD000DFDF1150E9F7F4DF1F91089586
 :0400000300007E007B
 :00000001FF

+ 206 - 201
optiboot/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst

@@ -3,34 +3,34 @@ optiboot_atmega328_pro_8MHz.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001ec  00007e00  00007e00  00000054  2**1
+  0 .text         000001dc  00007e00  00007e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  00000240  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000230  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 0000006a  00000000  00000000  00000268  2**0
+  2 .debug_pubnames 0000006a  00000000  00000000  00000258  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   00000269  00000000  00000000  000002d2  2**0
+  3 .debug_info   00000283  00000000  00000000  000002c2  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000196  00000000  00000000  0000053b  2**0
+  4 .debug_abbrev 000001ae  00000000  00000000  00000545  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003d3  00000000  00000000  000006d1  2**0
+  5 .debug_line   000003db  00000000  00000000  000006f3  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000aa4  2**2
+  6 .debug_frame  00000090  00000000  00000000  00000ad0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    00000135  00000000  00000000  00000b34  2**0
+  7 .debug_str    00000140  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d1  00000000  00000000  00000c69  2**0
+  8 .debug_loc    000001d1  00000000  00000000  00000ca0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000e3a  2**0
+  9 .debug_ranges 00000068  00000000  00000000  00000e71  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
 
 00007e00 <main>:
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
     7e00:	85 e0       	ldi	r24, 0x05	; 5
@@ -61,12 +61,12 @@ int main(void) {
     7e20:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
     7e22:	81 ff       	sbrs	r24, 1
-    7e24:	d0 d0       	rcall	.+416    	; 0x7fc6 <appStart>
+    7e24:	c8 d0       	rcall	.+400    	; 0x7fb6 <appStart>
 
   // Set up watchdog to trigger after 500ms
   watchdogConfig(WATCHDOG_500MS);
     7e26:	8d e0       	ldi	r24, 0x0D	; 13
-    7e28:	c8 d0       	rcall	.+400    	; 0x7fba <watchdogConfig>
+    7e28:	c0 d0       	rcall	.+384    	; 0x7faa <watchdogConfig>
 
   /* Set LED pin as output */
   LED_DDR |= _BV(LED);
@@ -120,28 +120,28 @@ void watchdogReset() {
       getNch(1);
     7e4a:	dd 24       	eor	r13, r13
     7e4c:	d3 94       	inc	r13
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
+      __boot_page_write_short((uint16_t)(void*)address);
     7e4e:	a5 e0       	ldi	r26, 0x05	; 5
-    7e50:	ea 2e       	mov	r14, r26
+    7e50:	fa 2e       	mov	r15, r26
       boot_spm_busy_wait();
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
     7e52:	f1 e1       	ldi	r31, 0x11	; 17
-    7e54:	ff 2e       	mov	r15, r31
+    7e54:	ef 2e       	mov	r14, r31
 #endif
 
   /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    7e56:	a4 d0       	rcall	.+328    	; 0x7fa0 <getch>
+    7e56:	9c d0       	rcall	.+312    	; 0x7f90 <getch>
 
     if(ch == STK_GET_PARAMETER) {
     7e58:	81 34       	cpi	r24, 0x41	; 65
@@ -149,10 +149,10 @@ void watchdogReset() {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
     7e5c:	81 e0       	ldi	r24, 0x01	; 1
-    7e5e:	be d0       	rcall	.+380    	; 0x7fdc <verifySpace+0xc>
+    7e5e:	b6 d0       	rcall	.+364    	; 0x7fcc <verifySpace+0xc>
       putch(0x03);
     7e60:	83 e0       	ldi	r24, 0x03	; 3
-    7e62:	24 c0       	rjmp	.+72     	; 0x7eac <main+0xac>
+    7e62:	20 c0       	rjmp	.+64     	; 0x7ea4 <main+0xa4>
     }
     else if(ch == STK_SET_DEVICE) {
     7e64:	82 34       	cpi	r24, 0x42	; 66
@@ -168,353 +168,358 @@ void watchdogReset() {
       // SET DEVICE EXT is ignored
       getNch(5);
     7e70:	85 e0       	ldi	r24, 0x05	; 5
-    7e72:	b4 d0       	rcall	.+360    	; 0x7fdc <verifySpace+0xc>
-    7e74:	8a c0       	rjmp	.+276    	; 0x7f8a <main+0x18a>
+    7e72:	ac d0       	rcall	.+344    	; 0x7fcc <verifySpace+0xc>
+    7e74:	82 c0       	rjmp	.+260    	; 0x7f7a <main+0x17a>
     }
     else if(ch == STK_LOAD_ADDRESS) {
     7e76:	85 35       	cpi	r24, 0x55	; 85
-    7e78:	a1 f4       	brne	.+40     	; 0x7ea2 <main+0xa2>
+    7e78:	81 f4       	brne	.+32     	; 0x7e9a <main+0x9a>
       // LOAD ADDRESS
-      address = getch();
-    7e7a:	92 d0       	rcall	.+292    	; 0x7fa0 <getch>
+      uint16_t newAddress;
+      newAddress = getch();
+    7e7a:	8a d0       	rcall	.+276    	; 0x7f90 <getch>
+      newAddress = (newAddress & 0xff) | (getch() << 8);
     7e7c:	08 2f       	mov	r16, r24
     7e7e:	10 e0       	ldi	r17, 0x00	; 0
-    7e80:	10 93 01 02 	sts	0x0201, r17
-    7e84:	00 93 00 02 	sts	0x0200, r16
-      address = (address & 0xff) | (getch() << 8);
-    7e88:	8b d0       	rcall	.+278    	; 0x7fa0 <getch>
-    7e8a:	90 e0       	ldi	r25, 0x00	; 0
-    7e8c:	98 2f       	mov	r25, r24
-    7e8e:	88 27       	eor	r24, r24
-    7e90:	80 2b       	or	r24, r16
-    7e92:	91 2b       	or	r25, r17
-      address += address; // Convert from word address to byte address
-    7e94:	88 0f       	add	r24, r24
-    7e96:	99 1f       	adc	r25, r25
-    7e98:	90 93 01 02 	sts	0x0201, r25
-    7e9c:	80 93 00 02 	sts	0x0200, r24
-    7ea0:	73 c0       	rjmp	.+230    	; 0x7f88 <main+0x188>
+    7e80:	87 d0       	rcall	.+270    	; 0x7f90 <getch>
+    7e82:	90 e0       	ldi	r25, 0x00	; 0
+    7e84:	98 2f       	mov	r25, r24
+    7e86:	88 27       	eor	r24, r24
+    7e88:	80 2b       	or	r24, r16
+    7e8a:	91 2b       	or	r25, r17
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+    7e8c:	88 0f       	add	r24, r24
+    7e8e:	99 1f       	adc	r25, r25
+      address = newAddress;
+    7e90:	90 93 01 02 	sts	0x0201, r25
+    7e94:	80 93 00 02 	sts	0x0200, r24
+    7e98:	6f c0       	rjmp	.+222    	; 0x7f78 <main+0x178>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    7ea2:	86 35       	cpi	r24, 0x56	; 86
-    7ea4:	29 f4       	brne	.+10     	; 0x7eb0 <main+0xb0>
+    7e9a:	86 35       	cpi	r24, 0x56	; 86
+    7e9c:	29 f4       	brne	.+10     	; 0x7ea8 <main+0xa8>
       // UNIVERSAL command is ignored
       getNch(4);
-    7ea6:	84 e0       	ldi	r24, 0x04	; 4
-    7ea8:	99 d0       	rcall	.+306    	; 0x7fdc <verifySpace+0xc>
+    7e9e:	84 e0       	ldi	r24, 0x04	; 4
+    7ea0:	95 d0       	rcall	.+298    	; 0x7fcc <verifySpace+0xc>
       putch(0x00);
-    7eaa:	80 e0       	ldi	r24, 0x00	; 0
-    7eac:	71 d0       	rcall	.+226    	; 0x7f90 <putch>
-    7eae:	6d c0       	rjmp	.+218    	; 0x7f8a <main+0x18a>
+    7ea2:	80 e0       	ldi	r24, 0x00	; 0
+    7ea4:	6d d0       	rcall	.+218    	; 0x7f80 <putch>
+    7ea6:	69 c0       	rjmp	.+210    	; 0x7f7a <main+0x17a>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    7eb0:	84 36       	cpi	r24, 0x64	; 100
-    7eb2:	09 f0       	breq	.+2      	; 0x7eb6 <main+0xb6>
-    7eb4:	43 c0       	rjmp	.+134    	; 0x7f3c <main+0x13c>
+    7ea8:	84 36       	cpi	r24, 0x64	; 100
+    7eaa:	09 f0       	breq	.+2      	; 0x7eae <main+0xae>
+    7eac:	3f c0       	rjmp	.+126    	; 0x7f2c <main+0x12c>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
 
       getLen();
-    7eb6:	7c d0       	rcall	.+248    	; 0x7fb0 <getLen>
+    7eae:	78 d0       	rcall	.+240    	; 0x7fa0 <getLen>
 
       // Immediately start page erase - this will 4.5ms
-      boot_page_erase((uint16_t)(void*)address);
-    7eb8:	e0 91 00 02 	lds	r30, 0x0200
-    7ebc:	f0 91 01 02 	lds	r31, 0x0201
-    7ec0:	83 e0       	ldi	r24, 0x03	; 3
-    7ec2:	80 93 57 00 	sts	0x0057, r24
-    7ec6:	e8 95       	spm
-    7ec8:	c0 e0       	ldi	r28, 0x00	; 0
-    7eca:	d1 e0       	ldi	r29, 0x01	; 1
-
+      __boot_page_erase_short((uint16_t)(void*)address);
+    7eb0:	e0 91 00 02 	lds	r30, 0x0200
+    7eb4:	f0 91 01 02 	lds	r31, 0x0201
+    7eb8:	83 e0       	ldi	r24, 0x03	; 3
+    7eba:	87 bf       	out	0x37, r24	; 55
+    7ebc:	e8 95       	spm
+    7ebe:	c0 e0       	ldi	r28, 0x00	; 0
+    7ec0:	d1 e0       	ldi	r29, 0x01	; 1
+      
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    7ecc:	69 d0       	rcall	.+210    	; 0x7fa0 <getch>
-    7ece:	89 93       	st	Y+, r24
+    7ec2:	66 d0       	rcall	.+204    	; 0x7f90 <getch>
+    7ec4:	89 93       	st	Y+, r24
       while (--length);
-    7ed0:	80 91 02 02 	lds	r24, 0x0202
-    7ed4:	81 50       	subi	r24, 0x01	; 1
-    7ed6:	80 93 02 02 	sts	0x0202, r24
-    7eda:	88 23       	and	r24, r24
-    7edc:	b9 f7       	brne	.-18     	; 0x7ecc <main+0xcc>
+    7ec6:	80 91 02 02 	lds	r24, 0x0202
+    7eca:	81 50       	subi	r24, 0x01	; 1
+    7ecc:	80 93 02 02 	sts	0x0202, r24
+    7ed0:	88 23       	and	r24, r24
+    7ed2:	b9 f7       	brne	.-18     	; 0x7ec2 <main+0xc2>
 
       // Read command terminator, start reply
       verifySpace();
-    7ede:	78 d0       	rcall	.+240    	; 0x7fd0 <verifySpace>
+    7ed4:	75 d0       	rcall	.+234    	; 0x7fc0 <verifySpace>
       
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    7ee0:	07 b6       	in	r0, 0x37	; 55
-    7ee2:	00 fc       	sbrc	r0, 0
-    7ee4:	fd cf       	rjmp	.-6      	; 0x7ee0 <main+0xe0>
+    7ed6:	07 b6       	in	r0, 0x37	; 55
+    7ed8:	00 fc       	sbrc	r0, 0
+    7eda:	fd cf       	rjmp	.-6      	; 0x7ed6 <main+0xd6>
       }
 #endif
 
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    7ee6:	40 91 00 02 	lds	r20, 0x0200
-    7eea:	50 91 01 02 	lds	r21, 0x0201
-    7eee:	a0 e0       	ldi	r26, 0x00	; 0
-    7ef0:	b1 e0       	ldi	r27, 0x01	; 1
+    7edc:	40 91 00 02 	lds	r20, 0x0200
+    7ee0:	50 91 01 02 	lds	r21, 0x0201
+    7ee4:	a0 e0       	ldi	r26, 0x00	; 0
+    7ee6:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    7ef2:	2c 91       	ld	r18, X
-    7ef4:	30 e0       	ldi	r19, 0x00	; 0
+    7ee8:	2c 91       	ld	r18, X
+    7eea:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    7ef6:	11 96       	adiw	r26, 0x01	; 1
-    7ef8:	8c 91       	ld	r24, X
-    7efa:	11 97       	sbiw	r26, 0x01	; 1
-    7efc:	90 e0       	ldi	r25, 0x00	; 0
-    7efe:	98 2f       	mov	r25, r24
-    7f00:	88 27       	eor	r24, r24
-    7f02:	82 2b       	or	r24, r18
-    7f04:	93 2b       	or	r25, r19
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+    7eec:	11 96       	adiw	r26, 0x01	; 1
+    7eee:	8c 91       	ld	r24, X
+    7ef0:	11 97       	sbiw	r26, 0x01	; 1
+    7ef2:	90 e0       	ldi	r25, 0x00	; 0
+    7ef4:	98 2f       	mov	r25, r24
+    7ef6:	88 27       	eor	r24, r24
+    7ef8:	82 2b       	or	r24, r18
+    7efa:	93 2b       	or	r25, r19
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
-    7f06:	12 96       	adiw	r26, 0x02	; 2
+    7efc:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
-    7f08:	fa 01       	movw	r30, r20
-    7f0a:	0c 01       	movw	r0, r24
-    7f0c:	d0 92 57 00 	sts	0x0057, r13
-    7f10:	e8 95       	spm
-    7f12:	11 24       	eor	r1, r1
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+    7efe:	fa 01       	movw	r30, r20
+    7f00:	0c 01       	movw	r0, r24
+    7f02:	d7 be       	out	0x37, r13	; 55
+    7f04:	e8 95       	spm
+    7f06:	11 24       	eor	r1, r1
         addrPtr += 2;
-    7f14:	4e 5f       	subi	r20, 0xFE	; 254
-    7f16:	5f 4f       	sbci	r21, 0xFF	; 255
+    7f08:	4e 5f       	subi	r20, 0xFE	; 254
+    7f0a:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    7f18:	f1 e0       	ldi	r31, 0x01	; 1
-    7f1a:	a0 38       	cpi	r26, 0x80	; 128
-    7f1c:	bf 07       	cpc	r27, r31
-    7f1e:	49 f7       	brne	.-46     	; 0x7ef2 <main+0xf2>
+    7f0c:	f1 e0       	ldi	r31, 0x01	; 1
+    7f0e:	a0 38       	cpi	r26, 0x80	; 128
+    7f10:	bf 07       	cpc	r27, r31
+    7f12:	51 f7       	brne	.-44     	; 0x7ee8 <main+0xe8>
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
-    7f20:	e0 91 00 02 	lds	r30, 0x0200
-    7f24:	f0 91 01 02 	lds	r31, 0x0201
-    7f28:	e0 92 57 00 	sts	0x0057, r14
-    7f2c:	e8 95       	spm
+      __boot_page_write_short((uint16_t)(void*)address);
+    7f14:	e0 91 00 02 	lds	r30, 0x0200
+    7f18:	f0 91 01 02 	lds	r31, 0x0201
+    7f1c:	f7 be       	out	0x37, r15	; 55
+    7f1e:	e8 95       	spm
       boot_spm_busy_wait();
-    7f2e:	07 b6       	in	r0, 0x37	; 55
-    7f30:	00 fc       	sbrc	r0, 0
-    7f32:	fd cf       	rjmp	.-6      	; 0x7f2e <main+0x12e>
+    7f20:	07 b6       	in	r0, 0x37	; 55
+    7f22:	00 fc       	sbrc	r0, 0
+    7f24:	fd cf       	rjmp	.-6      	; 0x7f20 <main+0x120>
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
-    7f34:	f0 92 57 00 	sts	0x0057, r15
-    7f38:	e8 95       	spm
-    7f3a:	27 c0       	rjmp	.+78     	; 0x7f8a <main+0x18a>
+    7f26:	e7 be       	out	0x37, r14	; 55
+    7f28:	e8 95       	spm
+    7f2a:	27 c0       	rjmp	.+78     	; 0x7f7a <main+0x17a>
 #endif
 
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    7f3c:	84 37       	cpi	r24, 0x74	; 116
-    7f3e:	b9 f4       	brne	.+46     	; 0x7f6e <main+0x16e>
+    7f2c:	84 37       	cpi	r24, 0x74	; 116
+    7f2e:	b9 f4       	brne	.+46     	; 0x7f5e <main+0x15e>
       // READ PAGE - we only read flash
       getLen();
-    7f40:	37 d0       	rcall	.+110    	; 0x7fb0 <getLen>
+    7f30:	37 d0       	rcall	.+110    	; 0x7fa0 <getLen>
       verifySpace();
-    7f42:	46 d0       	rcall	.+140    	; 0x7fd0 <verifySpace>
-        else ch = pgm_read_byte_near(address);
+    7f32:	46 d0       	rcall	.+140    	; 0x7fc0 <verifySpace>
+        putch(result);
         address++;
-        putch(ch);
-      } while (--length);
+      }
+      while (--length);
 #else
       do putch(pgm_read_byte_near(address++));
-    7f44:	e0 91 00 02 	lds	r30, 0x0200
-    7f48:	f0 91 01 02 	lds	r31, 0x0201
-    7f4c:	31 96       	adiw	r30, 0x01	; 1
-    7f4e:	f0 93 01 02 	sts	0x0201, r31
-    7f52:	e0 93 00 02 	sts	0x0200, r30
-    7f56:	31 97       	sbiw	r30, 0x01	; 1
-    7f58:	e4 91       	lpm	r30, Z+
-    7f5a:	8e 2f       	mov	r24, r30
-    7f5c:	19 d0       	rcall	.+50     	; 0x7f90 <putch>
+    7f34:	e0 91 00 02 	lds	r30, 0x0200
+    7f38:	f0 91 01 02 	lds	r31, 0x0201
+    7f3c:	31 96       	adiw	r30, 0x01	; 1
+    7f3e:	f0 93 01 02 	sts	0x0201, r31
+    7f42:	e0 93 00 02 	sts	0x0200, r30
+    7f46:	31 97       	sbiw	r30, 0x01	; 1
+    7f48:	e4 91       	lpm	r30, Z+
+    7f4a:	8e 2f       	mov	r24, r30
+    7f4c:	19 d0       	rcall	.+50     	; 0x7f80 <putch>
       while (--length);
-    7f5e:	80 91 02 02 	lds	r24, 0x0202
-    7f62:	81 50       	subi	r24, 0x01	; 1
-    7f64:	80 93 02 02 	sts	0x0202, r24
-    7f68:	88 23       	and	r24, r24
-    7f6a:	61 f7       	brne	.-40     	; 0x7f44 <main+0x144>
-    7f6c:	0e c0       	rjmp	.+28     	; 0x7f8a <main+0x18a>
+    7f4e:	80 91 02 02 	lds	r24, 0x0202
+    7f52:	81 50       	subi	r24, 0x01	; 1
+    7f54:	80 93 02 02 	sts	0x0202, r24
+    7f58:	88 23       	and	r24, r24
+    7f5a:	61 f7       	brne	.-40     	; 0x7f34 <main+0x134>
+    7f5c:	0e c0       	rjmp	.+28     	; 0x7f7a <main+0x17a>
+#endif
 #endif
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    7f6e:	85 37       	cpi	r24, 0x75	; 117
-    7f70:	39 f4       	brne	.+14     	; 0x7f80 <main+0x180>
+    7f5e:	85 37       	cpi	r24, 0x75	; 117
+    7f60:	39 f4       	brne	.+14     	; 0x7f70 <main+0x170>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    7f72:	2e d0       	rcall	.+92     	; 0x7fd0 <verifySpace>
+    7f62:	2e d0       	rcall	.+92     	; 0x7fc0 <verifySpace>
       putch(SIGNATURE_0);
-    7f74:	8e e1       	ldi	r24, 0x1E	; 30
-    7f76:	0c d0       	rcall	.+24     	; 0x7f90 <putch>
+    7f64:	8e e1       	ldi	r24, 0x1E	; 30
+    7f66:	0c d0       	rcall	.+24     	; 0x7f80 <putch>
       putch(SIGNATURE_1);
-    7f78:	85 e9       	ldi	r24, 0x95	; 149
-    7f7a:	0a d0       	rcall	.+20     	; 0x7f90 <putch>
+    7f68:	85 e9       	ldi	r24, 0x95	; 149
+    7f6a:	0a d0       	rcall	.+20     	; 0x7f80 <putch>
       putch(SIGNATURE_2);
-    7f7c:	8f e0       	ldi	r24, 0x0F	; 15
-    7f7e:	96 cf       	rjmp	.-212    	; 0x7eac <main+0xac>
+    7f6c:	8f e0       	ldi	r24, 0x0F	; 15
+    7f6e:	9a cf       	rjmp	.-204    	; 0x7ea4 <main+0xa4>
     }
     else if (ch == 'Q') {
-    7f80:	81 35       	cpi	r24, 0x51	; 81
-    7f82:	11 f4       	brne	.+4      	; 0x7f88 <main+0x188>
+    7f70:	81 35       	cpi	r24, 0x51	; 81
+    7f72:	11 f4       	brne	.+4      	; 0x7f78 <main+0x178>
       // Adaboot no-wait mod
       watchdogConfig(WATCHDOG_16MS);
-    7f84:	88 e0       	ldi	r24, 0x08	; 8
-    7f86:	19 d0       	rcall	.+50     	; 0x7fba <watchdogConfig>
+    7f74:	88 e0       	ldi	r24, 0x08	; 8
+    7f76:	19 d0       	rcall	.+50     	; 0x7faa <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    7f88:	23 d0       	rcall	.+70     	; 0x7fd0 <verifySpace>
+    7f78:	23 d0       	rcall	.+70     	; 0x7fc0 <verifySpace>
     }
     putch(STK_OK);
-    7f8a:	80 e1       	ldi	r24, 0x10	; 16
-    7f8c:	01 d0       	rcall	.+2      	; 0x7f90 <putch>
-    7f8e:	63 cf       	rjmp	.-314    	; 0x7e56 <main+0x56>
+    7f7a:	80 e1       	ldi	r24, 0x10	; 16
+    7f7c:	01 d0       	rcall	.+2      	; 0x7f80 <putch>
+    7f7e:	6b cf       	rjmp	.-298    	; 0x7e56 <main+0x56>
 
-00007f90 <putch>:
+00007f80 <putch>:
   }
 }
 
 void putch(char ch) {
-    7f90:	98 2f       	mov	r25, r24
+    7f80:	98 2f       	mov	r25, r24
 #ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    7f92:	80 91 c0 00 	lds	r24, 0x00C0
-    7f96:	85 ff       	sbrs	r24, 5
-    7f98:	fc cf       	rjmp	.-8      	; 0x7f92 <putch+0x2>
+    7f82:	80 91 c0 00 	lds	r24, 0x00C0
+    7f86:	85 ff       	sbrs	r24, 5
+    7f88:	fc cf       	rjmp	.-8      	; 0x7f82 <putch+0x2>
   UDR0 = ch;
-    7f9a:	90 93 c6 00 	sts	0x00C6, r25
+    7f8a:	90 93 c6 00 	sts	0x00C6, r25
       [uartBit] "I" (UART_TX_BIT)
     :
       "r25"
   );
 #endif
 }
-    7f9e:	08 95       	ret
+    7f8e:	08 95       	ret
 
-00007fa0 <getch>:
+00007f90 <getch>:
   return getch();
 }
 
 // Watchdog functions. These are only safe with interrupts turned off.
 void watchdogReset() {
   __asm__ __volatile__ (
-    7fa0:	a8 95       	wdr
+    7f90:	a8 95       	wdr
       [uartBit] "I" (UART_RX_BIT)
     :
       "r25"
 );
 #else
   while(!(UCSR0A & _BV(RXC0)));
-    7fa2:	80 91 c0 00 	lds	r24, 0x00C0
-    7fa6:	87 ff       	sbrs	r24, 7
-    7fa8:	fc cf       	rjmp	.-8      	; 0x7fa2 <getch+0x2>
+    7f92:	80 91 c0 00 	lds	r24, 0x00C0
+    7f96:	87 ff       	sbrs	r24, 7
+    7f98:	fc cf       	rjmp	.-8      	; 0x7f92 <getch+0x2>
   ch = UDR0;
-    7faa:	80 91 c6 00 	lds	r24, 0x00C6
+    7f9a:	80 91 c6 00 	lds	r24, 0x00C6
 #ifdef LED_DATA_FLASH
   LED_PIN |= _BV(LED);
 #endif
 
   return ch;
 }
-    7fae:	08 95       	ret
+    7f9e:	08 95       	ret
 
-00007fb0 <getLen>:
+00007fa0 <getLen>:
   } while (--count);
 }
 #endif
 
 uint8_t getLen() {
   getch();
-    7fb0:	f7 df       	rcall	.-18     	; 0x7fa0 <getch>
+    7fa0:	f7 df       	rcall	.-18     	; 0x7f90 <getch>
   length = getch();
-    7fb2:	f6 df       	rcall	.-20     	; 0x7fa0 <getch>
-    7fb4:	80 93 02 02 	sts	0x0202, r24
+    7fa2:	f6 df       	rcall	.-20     	; 0x7f90 <getch>
+    7fa4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    7fb8:	f3 cf       	rjmp	.-26     	; 0x7fa0 <getch>
+    7fa8:	f3 cf       	rjmp	.-26     	; 0x7f90 <getch>
 
-00007fba <watchdogConfig>:
+00007faa <watchdogConfig>:
     "wdr\n"
   );
 }
 
 void watchdogConfig(uint8_t x) {
   WDTCSR = _BV(WDCE) | _BV(WDE);
-    7fba:	e0 e6       	ldi	r30, 0x60	; 96
-    7fbc:	f0 e0       	ldi	r31, 0x00	; 0
-    7fbe:	98 e1       	ldi	r25, 0x18	; 24
-    7fc0:	90 83       	st	Z, r25
+    7faa:	e0 e6       	ldi	r30, 0x60	; 96
+    7fac:	f0 e0       	ldi	r31, 0x00	; 0
+    7fae:	98 e1       	ldi	r25, 0x18	; 24
+    7fb0:	90 83       	st	Z, r25
   WDTCSR = x;
-    7fc2:	80 83       	st	Z, r24
+    7fb2:	80 83       	st	Z, r24
 }
-    7fc4:	08 95       	ret
+    7fb4:	08 95       	ret
 
-00007fc6 <appStart>:
+00007fb6 <appStart>:
 
 void appStart() {
   watchdogConfig(WATCHDOG_OFF);
-    7fc6:	80 e0       	ldi	r24, 0x00	; 0
-    7fc8:	f8 df       	rcall	.-16     	; 0x7fba <watchdogConfig>
+    7fb6:	80 e0       	ldi	r24, 0x00	; 0
+    7fb8:	f8 df       	rcall	.-16     	; 0x7faa <watchdogConfig>
   __asm__ __volatile__ (
-    7fca:	ee 27       	eor	r30, r30
-    7fcc:	ff 27       	eor	r31, r31
-    7fce:	09 94       	ijmp
+    7fba:	ee 27       	eor	r30, r30
+    7fbc:	ff 27       	eor	r31, r31
+    7fbe:	09 94       	ijmp
 
-00007fd0 <verifySpace>:
+00007fc0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    7fd0:	e7 df       	rcall	.-50     	; 0x7fa0 <getch>
-    7fd2:	80 32       	cpi	r24, 0x20	; 32
-    7fd4:	09 f0       	breq	.+2      	; 0x7fd8 <verifySpace+0x8>
-    7fd6:	f7 df       	rcall	.-18     	; 0x7fc6 <appStart>
+    7fc0:	e7 df       	rcall	.-50     	; 0x7f90 <getch>
+    7fc2:	80 32       	cpi	r24, 0x20	; 32
+    7fc4:	09 f0       	breq	.+2      	; 0x7fc8 <verifySpace+0x8>
+    7fc6:	f7 df       	rcall	.-18     	; 0x7fb6 <appStart>
   putch(STK_INSYNC);
-    7fd8:	84 e1       	ldi	r24, 0x14	; 20
+    7fc8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    7fda:	da cf       	rjmp	.-76     	; 0x7f90 <putch>
+    7fca:	da cf       	rjmp	.-76     	; 0x7f80 <putch>
     ::[count] "M" (UART_B_VALUE)
   );
 }
 #endif
 
 void getNch(uint8_t count) {
-    7fdc:	1f 93       	push	r17
-    7fde:	18 2f       	mov	r17, r24
+    7fcc:	1f 93       	push	r17
+    7fce:	18 2f       	mov	r17, r24
 
-00007fe0 <getNch>:
+00007fd0 <getNch>:
   do getch(); while (--count);
-    7fe0:	df df       	rcall	.-66     	; 0x7fa0 <getch>
-    7fe2:	11 50       	subi	r17, 0x01	; 1
-    7fe4:	e9 f7       	brne	.-6      	; 0x7fe0 <getNch>
+    7fd0:	df df       	rcall	.-66     	; 0x7f90 <getch>
+    7fd2:	11 50       	subi	r17, 0x01	; 1
+    7fd4:	e9 f7       	brne	.-6      	; 0x7fd0 <getNch>
   verifySpace();
-    7fe6:	f4 df       	rcall	.-24     	; 0x7fd0 <verifySpace>
+    7fd6:	f4 df       	rcall	.-24     	; 0x7fc0 <verifySpace>
 }
-    7fe8:	1f 91       	pop	r17
-    7fea:	08 95       	ret
+    7fd8:	1f 91       	pop	r17
+    7fda:	08 95       	ret

+ 26 - 27
optiboot/bootloaders/optiboot/optiboot_diecimila.hex

@@ -1,33 +1,32 @@
 :103E000085E08093810082E08093C00088E1809308
 :103E1000C10086E08093C20080E18093C40084B733
-:103E200014BE81FFD0D08DE0C8D0259A86E020E373
+:103E200014BE81FFC8D08DE0C0D0259A86E020E383
 :103E30003CEF91E0309385002093840096BBB09BCB
 :103E4000FECF1D9AA8958150A9F7DD24D394A5E053
-:103E5000EA2EF1E1FF2EA4D0813421F481E0BED01E
-:103E600083E024C0823411F484E103C0853419F462
-:103E700085E0B4D08AC08535A1F492D0082F10E037
-:103E800010930102009300028BD090E0982F8827B6
-:103E9000802B912B880F991F909301028093000231
-:103EA00073C0863529F484E099D080E071D06DC06C
-:103EB000843609F043C07CD0E0910002F091010209
-:103EC00083E080935700E895C0E0D1E069D0899302
-:103ED000809102028150809302028823B9F778D042
-:103EE00007B600FCFDCF4091000250910102A0E016
-:103EF000B1E02C9130E011968C91119790E0982FC1
-:103F00008827822B932B1296FA010C01D09257002E
-:103F1000E89511244E5F5F4FF1E0A038BF0749F7E5
-:103F2000E0910002F0910102E0925700E89507B697
-:103F300000FCFDCFF0925700E89527C08437B9F414
-:103F400037D046D0E0910002F09101023196F09313
-:103F50000102E09300023197E4918E2F19D08091F5
-:103F60000202815080930202882361F70EC08537D8
-:103F700039F42ED08EE10CD084E90AD086E096CFB9
-:103F8000813511F488E019D023D080E101D063CFCE
-:103F9000982F8091C00085FFFCCF9093C6000895B4
-:103FA000A8958091C00087FFFCCF8091C60008953E
-:103FB000F7DFF6DF80930202F3CFE0E6F0E098E16E
-:103FC00090838083089580E0F8DFEE27FF2709942F
-:103FD000E7DF803209F0F7DF84E1DACF1F93182F93
-:0C3FE000DFDF1150E9F7F4DF1F910895B6
+:103E5000FA2EF1E1EF2E9CD0813421F481E0B6D02E
+:103E600083E020C0823411F484E103C0853419F466
+:103E700085E0ACD082C0853581F48AD0082F10E06F
+:103E800087D090E0982F8827802B912B880F991F3F
+:103E900090930102809300026FC0863529F484E07C
+:103EA00095D080E06DD069C0843609F03FC078D0ED
+:103EB000E0910002F091010283E087BFE895C0E045
+:103EC000D1E066D0899380910202815080930202F2
+:103ED0008823B9F775D007B600FCFDCF40910002EA
+:103EE00050910102A0E0B1E02C9130E011968C914C
+:103EF000119790E0982F8827822B932B1296FA0126
+:103F00000C01D7BEE89511244E5F5F4FF1E0A03859
+:103F1000BF0751F7E0910002F0910102F7BEE8956A
+:103F200007B600FCFDCFE7BEE89527C08437B9F49B
+:103F300037D046D0E0910002F09101023196F09323
+:103F40000102E09300023197E4918E2F19D0809105
+:103F50000202815080930202882361F70EC08537E8
+:103F600039F42ED08EE10CD084E90AD086E09ACFC5
+:103F7000813511F488E019D023D080E101D06BCFD6
+:103F8000982F8091C00085FFFCCF9093C6000895C4
+:103F9000A8958091C00087FFFCCF8091C60008954E
+:103FA000F7DFF6DF80930202F3CFE0E6F0E098E17E
+:103FB00090838083089580E0F8DFEE27FF2709943F
+:103FC000E7DF803209F0F7DF84E1DACF1F93182FA3
+:0C3FD000DFDF1150E9F7F4DF1F910895C6
 :0400000300003E00BB
 :00000001FF

+ 206 - 201
optiboot/bootloaders/optiboot/optiboot_diecimila.lst

@@ -3,34 +3,34 @@ optiboot_diecimila.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001ec  00003e00  00003e00  00000054  2**1
+  0 .text         000001dc  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  00000240  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000230  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 0000006a  00000000  00000000  00000268  2**0
+  2 .debug_pubnames 0000006a  00000000  00000000  00000258  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   00000269  00000000  00000000  000002d2  2**0
+  3 .debug_info   00000283  00000000  00000000  000002c2  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000196  00000000  00000000  0000053b  2**0
+  4 .debug_abbrev 000001ae  00000000  00000000  00000545  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003d3  00000000  00000000  000006d1  2**0
+  5 .debug_line   000003db  00000000  00000000  000006f3  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000aa4  2**2
+  6 .debug_frame  00000090  00000000  00000000  00000ad0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    00000135  00000000  00000000  00000b34  2**0
+  7 .debug_str    00000140  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d1  00000000  00000000  00000c69  2**0
+  8 .debug_loc    000001d1  00000000  00000000  00000ca0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000e3a  2**0
+  9 .debug_ranges 00000068  00000000  00000000  00000e71  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
 
 00003e00 <main>:
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
@@ -61,12 +61,12 @@ int main(void) {
     3e20:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
     3e22:	81 ff       	sbrs	r24, 1
-    3e24:	d0 d0       	rcall	.+416    	; 0x3fc6 <appStart>
+    3e24:	c8 d0       	rcall	.+400    	; 0x3fb6 <appStart>
 
   // Set up watchdog to trigger after 500ms
   watchdogConfig(WATCHDOG_500MS);
     3e26:	8d e0       	ldi	r24, 0x0D	; 13
-    3e28:	c8 d0       	rcall	.+400    	; 0x3fba <watchdogConfig>
+    3e28:	c0 d0       	rcall	.+384    	; 0x3faa <watchdogConfig>
 
   /* Set LED pin as output */
   LED_DDR |= _BV(LED);
@@ -120,28 +120,28 @@ void watchdogReset() {
       getNch(1);
     3e4a:	dd 24       	eor	r13, r13
     3e4c:	d3 94       	inc	r13
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
+      __boot_page_write_short((uint16_t)(void*)address);
     3e4e:	a5 e0       	ldi	r26, 0x05	; 5
-    3e50:	ea 2e       	mov	r14, r26
+    3e50:	fa 2e       	mov	r15, r26
       boot_spm_busy_wait();
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
     3e52:	f1 e1       	ldi	r31, 0x11	; 17
-    3e54:	ff 2e       	mov	r15, r31
+    3e54:	ef 2e       	mov	r14, r31
 #endif
 
   /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e56:	a4 d0       	rcall	.+328    	; 0x3fa0 <getch>
+    3e56:	9c d0       	rcall	.+312    	; 0x3f90 <getch>
 
     if(ch == STK_GET_PARAMETER) {
     3e58:	81 34       	cpi	r24, 0x41	; 65
@@ -149,10 +149,10 @@ void watchdogReset() {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
     3e5c:	81 e0       	ldi	r24, 0x01	; 1
-    3e5e:	be d0       	rcall	.+380    	; 0x3fdc <verifySpace+0xc>
+    3e5e:	b6 d0       	rcall	.+364    	; 0x3fcc <verifySpace+0xc>
       putch(0x03);
     3e60:	83 e0       	ldi	r24, 0x03	; 3
-    3e62:	24 c0       	rjmp	.+72     	; 0x3eac <main+0xac>
+    3e62:	20 c0       	rjmp	.+64     	; 0x3ea4 <main+0xa4>
     }
     else if(ch == STK_SET_DEVICE) {
     3e64:	82 34       	cpi	r24, 0x42	; 66
@@ -168,353 +168,358 @@ void watchdogReset() {
       // SET DEVICE EXT is ignored
       getNch(5);
     3e70:	85 e0       	ldi	r24, 0x05	; 5
-    3e72:	b4 d0       	rcall	.+360    	; 0x3fdc <verifySpace+0xc>
-    3e74:	8a c0       	rjmp	.+276    	; 0x3f8a <main+0x18a>
+    3e72:	ac d0       	rcall	.+344    	; 0x3fcc <verifySpace+0xc>
+    3e74:	82 c0       	rjmp	.+260    	; 0x3f7a <main+0x17a>
     }
     else if(ch == STK_LOAD_ADDRESS) {
     3e76:	85 35       	cpi	r24, 0x55	; 85
-    3e78:	a1 f4       	brne	.+40     	; 0x3ea2 <main+0xa2>
+    3e78:	81 f4       	brne	.+32     	; 0x3e9a <main+0x9a>
       // LOAD ADDRESS
-      address = getch();
-    3e7a:	92 d0       	rcall	.+292    	; 0x3fa0 <getch>
+      uint16_t newAddress;
+      newAddress = getch();
+    3e7a:	8a d0       	rcall	.+276    	; 0x3f90 <getch>
+      newAddress = (newAddress & 0xff) | (getch() << 8);
     3e7c:	08 2f       	mov	r16, r24
     3e7e:	10 e0       	ldi	r17, 0x00	; 0
-    3e80:	10 93 01 02 	sts	0x0201, r17
-    3e84:	00 93 00 02 	sts	0x0200, r16
-      address = (address & 0xff) | (getch() << 8);
-    3e88:	8b d0       	rcall	.+278    	; 0x3fa0 <getch>
-    3e8a:	90 e0       	ldi	r25, 0x00	; 0
-    3e8c:	98 2f       	mov	r25, r24
-    3e8e:	88 27       	eor	r24, r24
-    3e90:	80 2b       	or	r24, r16
-    3e92:	91 2b       	or	r25, r17
-      address += address; // Convert from word address to byte address
-    3e94:	88 0f       	add	r24, r24
-    3e96:	99 1f       	adc	r25, r25
-    3e98:	90 93 01 02 	sts	0x0201, r25
-    3e9c:	80 93 00 02 	sts	0x0200, r24
-    3ea0:	73 c0       	rjmp	.+230    	; 0x3f88 <main+0x188>
+    3e80:	87 d0       	rcall	.+270    	; 0x3f90 <getch>
+    3e82:	90 e0       	ldi	r25, 0x00	; 0
+    3e84:	98 2f       	mov	r25, r24
+    3e86:	88 27       	eor	r24, r24
+    3e88:	80 2b       	or	r24, r16
+    3e8a:	91 2b       	or	r25, r17
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+    3e8c:	88 0f       	add	r24, r24
+    3e8e:	99 1f       	adc	r25, r25
+      address = newAddress;
+    3e90:	90 93 01 02 	sts	0x0201, r25
+    3e94:	80 93 00 02 	sts	0x0200, r24
+    3e98:	6f c0       	rjmp	.+222    	; 0x3f78 <main+0x178>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3ea2:	86 35       	cpi	r24, 0x56	; 86
-    3ea4:	29 f4       	brne	.+10     	; 0x3eb0 <main+0xb0>
+    3e9a:	86 35       	cpi	r24, 0x56	; 86
+    3e9c:	29 f4       	brne	.+10     	; 0x3ea8 <main+0xa8>
       // UNIVERSAL command is ignored
       getNch(4);
-    3ea6:	84 e0       	ldi	r24, 0x04	; 4
-    3ea8:	99 d0       	rcall	.+306    	; 0x3fdc <verifySpace+0xc>
+    3e9e:	84 e0       	ldi	r24, 0x04	; 4
+    3ea0:	95 d0       	rcall	.+298    	; 0x3fcc <verifySpace+0xc>
       putch(0x00);
-    3eaa:	80 e0       	ldi	r24, 0x00	; 0
-    3eac:	71 d0       	rcall	.+226    	; 0x3f90 <putch>
-    3eae:	6d c0       	rjmp	.+218    	; 0x3f8a <main+0x18a>
+    3ea2:	80 e0       	ldi	r24, 0x00	; 0
+    3ea4:	6d d0       	rcall	.+218    	; 0x3f80 <putch>
+    3ea6:	69 c0       	rjmp	.+210    	; 0x3f7a <main+0x17a>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3eb0:	84 36       	cpi	r24, 0x64	; 100
-    3eb2:	09 f0       	breq	.+2      	; 0x3eb6 <main+0xb6>
-    3eb4:	43 c0       	rjmp	.+134    	; 0x3f3c <main+0x13c>
+    3ea8:	84 36       	cpi	r24, 0x64	; 100
+    3eaa:	09 f0       	breq	.+2      	; 0x3eae <main+0xae>
+    3eac:	3f c0       	rjmp	.+126    	; 0x3f2c <main+0x12c>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
 
       getLen();
-    3eb6:	7c d0       	rcall	.+248    	; 0x3fb0 <getLen>
+    3eae:	78 d0       	rcall	.+240    	; 0x3fa0 <getLen>
 
       // Immediately start page erase - this will 4.5ms
-      boot_page_erase((uint16_t)(void*)address);
-    3eb8:	e0 91 00 02 	lds	r30, 0x0200
-    3ebc:	f0 91 01 02 	lds	r31, 0x0201
-    3ec0:	83 e0       	ldi	r24, 0x03	; 3
-    3ec2:	80 93 57 00 	sts	0x0057, r24
-    3ec6:	e8 95       	spm
-    3ec8:	c0 e0       	ldi	r28, 0x00	; 0
-    3eca:	d1 e0       	ldi	r29, 0x01	; 1
-
+      __boot_page_erase_short((uint16_t)(void*)address);
+    3eb0:	e0 91 00 02 	lds	r30, 0x0200
+    3eb4:	f0 91 01 02 	lds	r31, 0x0201
+    3eb8:	83 e0       	ldi	r24, 0x03	; 3
+    3eba:	87 bf       	out	0x37, r24	; 55
+    3ebc:	e8 95       	spm
+    3ebe:	c0 e0       	ldi	r28, 0x00	; 0
+    3ec0:	d1 e0       	ldi	r29, 0x01	; 1
+      
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3ecc:	69 d0       	rcall	.+210    	; 0x3fa0 <getch>
-    3ece:	89 93       	st	Y+, r24
+    3ec2:	66 d0       	rcall	.+204    	; 0x3f90 <getch>
+    3ec4:	89 93       	st	Y+, r24
       while (--length);
-    3ed0:	80 91 02 02 	lds	r24, 0x0202
-    3ed4:	81 50       	subi	r24, 0x01	; 1
-    3ed6:	80 93 02 02 	sts	0x0202, r24
-    3eda:	88 23       	and	r24, r24
-    3edc:	b9 f7       	brne	.-18     	; 0x3ecc <main+0xcc>
+    3ec6:	80 91 02 02 	lds	r24, 0x0202
+    3eca:	81 50       	subi	r24, 0x01	; 1
+    3ecc:	80 93 02 02 	sts	0x0202, r24
+    3ed0:	88 23       	and	r24, r24
+    3ed2:	b9 f7       	brne	.-18     	; 0x3ec2 <main+0xc2>
 
       // Read command terminator, start reply
       verifySpace();
-    3ede:	78 d0       	rcall	.+240    	; 0x3fd0 <verifySpace>
+    3ed4:	75 d0       	rcall	.+234    	; 0x3fc0 <verifySpace>
       
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3ee0:	07 b6       	in	r0, 0x37	; 55
-    3ee2:	00 fc       	sbrc	r0, 0
-    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+    3ed6:	07 b6       	in	r0, 0x37	; 55
+    3ed8:	00 fc       	sbrc	r0, 0
+    3eda:	fd cf       	rjmp	.-6      	; 0x3ed6 <main+0xd6>
       }
 #endif
 
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ee6:	40 91 00 02 	lds	r20, 0x0200
-    3eea:	50 91 01 02 	lds	r21, 0x0201
-    3eee:	a0 e0       	ldi	r26, 0x00	; 0
-    3ef0:	b1 e0       	ldi	r27, 0x01	; 1
+    3edc:	40 91 00 02 	lds	r20, 0x0200
+    3ee0:	50 91 01 02 	lds	r21, 0x0201
+    3ee4:	a0 e0       	ldi	r26, 0x00	; 0
+    3ee6:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3ef2:	2c 91       	ld	r18, X
-    3ef4:	30 e0       	ldi	r19, 0x00	; 0
+    3ee8:	2c 91       	ld	r18, X
+    3eea:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ef6:	11 96       	adiw	r26, 0x01	; 1
-    3ef8:	8c 91       	ld	r24, X
-    3efa:	11 97       	sbiw	r26, 0x01	; 1
-    3efc:	90 e0       	ldi	r25, 0x00	; 0
-    3efe:	98 2f       	mov	r25, r24
-    3f00:	88 27       	eor	r24, r24
-    3f02:	82 2b       	or	r24, r18
-    3f04:	93 2b       	or	r25, r19
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+    3eec:	11 96       	adiw	r26, 0x01	; 1
+    3eee:	8c 91       	ld	r24, X
+    3ef0:	11 97       	sbiw	r26, 0x01	; 1
+    3ef2:	90 e0       	ldi	r25, 0x00	; 0
+    3ef4:	98 2f       	mov	r25, r24
+    3ef6:	88 27       	eor	r24, r24
+    3ef8:	82 2b       	or	r24, r18
+    3efa:	93 2b       	or	r25, r19
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
-    3f06:	12 96       	adiw	r26, 0x02	; 2
+    3efc:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3f08:	fa 01       	movw	r30, r20
-    3f0a:	0c 01       	movw	r0, r24
-    3f0c:	d0 92 57 00 	sts	0x0057, r13
-    3f10:	e8 95       	spm
-    3f12:	11 24       	eor	r1, r1
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+    3efe:	fa 01       	movw	r30, r20
+    3f00:	0c 01       	movw	r0, r24
+    3f02:	d7 be       	out	0x37, r13	; 55
+    3f04:	e8 95       	spm
+    3f06:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3f14:	4e 5f       	subi	r20, 0xFE	; 254
-    3f16:	5f 4f       	sbci	r21, 0xFF	; 255
+    3f08:	4e 5f       	subi	r20, 0xFE	; 254
+    3f0a:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f18:	f1 e0       	ldi	r31, 0x01	; 1
-    3f1a:	a0 38       	cpi	r26, 0x80	; 128
-    3f1c:	bf 07       	cpc	r27, r31
-    3f1e:	49 f7       	brne	.-46     	; 0x3ef2 <main+0xf2>
+    3f0c:	f1 e0       	ldi	r31, 0x01	; 1
+    3f0e:	a0 38       	cpi	r26, 0x80	; 128
+    3f10:	bf 07       	cpc	r27, r31
+    3f12:	51 f7       	brne	.-44     	; 0x3ee8 <main+0xe8>
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
-    3f20:	e0 91 00 02 	lds	r30, 0x0200
-    3f24:	f0 91 01 02 	lds	r31, 0x0201
-    3f28:	e0 92 57 00 	sts	0x0057, r14
-    3f2c:	e8 95       	spm
+      __boot_page_write_short((uint16_t)(void*)address);
+    3f14:	e0 91 00 02 	lds	r30, 0x0200
+    3f18:	f0 91 01 02 	lds	r31, 0x0201
+    3f1c:	f7 be       	out	0x37, r15	; 55
+    3f1e:	e8 95       	spm
       boot_spm_busy_wait();
-    3f2e:	07 b6       	in	r0, 0x37	; 55
-    3f30:	00 fc       	sbrc	r0, 0
-    3f32:	fd cf       	rjmp	.-6      	; 0x3f2e <main+0x12e>
+    3f20:	07 b6       	in	r0, 0x37	; 55
+    3f22:	00 fc       	sbrc	r0, 0
+    3f24:	fd cf       	rjmp	.-6      	; 0x3f20 <main+0x120>
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
-    3f34:	f0 92 57 00 	sts	0x0057, r15
-    3f38:	e8 95       	spm
-    3f3a:	27 c0       	rjmp	.+78     	; 0x3f8a <main+0x18a>
+    3f26:	e7 be       	out	0x37, r14	; 55
+    3f28:	e8 95       	spm
+    3f2a:	27 c0       	rjmp	.+78     	; 0x3f7a <main+0x17a>
 #endif
 
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f3c:	84 37       	cpi	r24, 0x74	; 116
-    3f3e:	b9 f4       	brne	.+46     	; 0x3f6e <main+0x16e>
+    3f2c:	84 37       	cpi	r24, 0x74	; 116
+    3f2e:	b9 f4       	brne	.+46     	; 0x3f5e <main+0x15e>
       // READ PAGE - we only read flash
       getLen();
-    3f40:	37 d0       	rcall	.+110    	; 0x3fb0 <getLen>
+    3f30:	37 d0       	rcall	.+110    	; 0x3fa0 <getLen>
       verifySpace();
-    3f42:	46 d0       	rcall	.+140    	; 0x3fd0 <verifySpace>
-        else ch = pgm_read_byte_near(address);
+    3f32:	46 d0       	rcall	.+140    	; 0x3fc0 <verifySpace>
+        putch(result);
         address++;
-        putch(ch);
-      } while (--length);
+      }
+      while (--length);
 #else
       do putch(pgm_read_byte_near(address++));
-    3f44:	e0 91 00 02 	lds	r30, 0x0200
-    3f48:	f0 91 01 02 	lds	r31, 0x0201
-    3f4c:	31 96       	adiw	r30, 0x01	; 1
-    3f4e:	f0 93 01 02 	sts	0x0201, r31
-    3f52:	e0 93 00 02 	sts	0x0200, r30
-    3f56:	31 97       	sbiw	r30, 0x01	; 1
-    3f58:	e4 91       	lpm	r30, Z+
-    3f5a:	8e 2f       	mov	r24, r30
-    3f5c:	19 d0       	rcall	.+50     	; 0x3f90 <putch>
+    3f34:	e0 91 00 02 	lds	r30, 0x0200
+    3f38:	f0 91 01 02 	lds	r31, 0x0201
+    3f3c:	31 96       	adiw	r30, 0x01	; 1
+    3f3e:	f0 93 01 02 	sts	0x0201, r31
+    3f42:	e0 93 00 02 	sts	0x0200, r30
+    3f46:	31 97       	sbiw	r30, 0x01	; 1
+    3f48:	e4 91       	lpm	r30, Z+
+    3f4a:	8e 2f       	mov	r24, r30
+    3f4c:	19 d0       	rcall	.+50     	; 0x3f80 <putch>
       while (--length);
-    3f5e:	80 91 02 02 	lds	r24, 0x0202
-    3f62:	81 50       	subi	r24, 0x01	; 1
-    3f64:	80 93 02 02 	sts	0x0202, r24
-    3f68:	88 23       	and	r24, r24
-    3f6a:	61 f7       	brne	.-40     	; 0x3f44 <main+0x144>
-    3f6c:	0e c0       	rjmp	.+28     	; 0x3f8a <main+0x18a>
+    3f4e:	80 91 02 02 	lds	r24, 0x0202
+    3f52:	81 50       	subi	r24, 0x01	; 1
+    3f54:	80 93 02 02 	sts	0x0202, r24
+    3f58:	88 23       	and	r24, r24
+    3f5a:	61 f7       	brne	.-40     	; 0x3f34 <main+0x134>
+    3f5c:	0e c0       	rjmp	.+28     	; 0x3f7a <main+0x17a>
+#endif
 #endif
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f6e:	85 37       	cpi	r24, 0x75	; 117
-    3f70:	39 f4       	brne	.+14     	; 0x3f80 <main+0x180>
+    3f5e:	85 37       	cpi	r24, 0x75	; 117
+    3f60:	39 f4       	brne	.+14     	; 0x3f70 <main+0x170>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f72:	2e d0       	rcall	.+92     	; 0x3fd0 <verifySpace>
+    3f62:	2e d0       	rcall	.+92     	; 0x3fc0 <verifySpace>
       putch(SIGNATURE_0);
-    3f74:	8e e1       	ldi	r24, 0x1E	; 30
-    3f76:	0c d0       	rcall	.+24     	; 0x3f90 <putch>
+    3f64:	8e e1       	ldi	r24, 0x1E	; 30
+    3f66:	0c d0       	rcall	.+24     	; 0x3f80 <putch>
       putch(SIGNATURE_1);
-    3f78:	84 e9       	ldi	r24, 0x94	; 148
-    3f7a:	0a d0       	rcall	.+20     	; 0x3f90 <putch>
+    3f68:	84 e9       	ldi	r24, 0x94	; 148
+    3f6a:	0a d0       	rcall	.+20     	; 0x3f80 <putch>
       putch(SIGNATURE_2);
-    3f7c:	86 e0       	ldi	r24, 0x06	; 6
-    3f7e:	96 cf       	rjmp	.-212    	; 0x3eac <main+0xac>
+    3f6c:	86 e0       	ldi	r24, 0x06	; 6
+    3f6e:	9a cf       	rjmp	.-204    	; 0x3ea4 <main+0xa4>
     }
     else if (ch == 'Q') {
-    3f80:	81 35       	cpi	r24, 0x51	; 81
-    3f82:	11 f4       	brne	.+4      	; 0x3f88 <main+0x188>
+    3f70:	81 35       	cpi	r24, 0x51	; 81
+    3f72:	11 f4       	brne	.+4      	; 0x3f78 <main+0x178>
       // Adaboot no-wait mod
       watchdogConfig(WATCHDOG_16MS);
-    3f84:	88 e0       	ldi	r24, 0x08	; 8
-    3f86:	19 d0       	rcall	.+50     	; 0x3fba <watchdogConfig>
+    3f74:	88 e0       	ldi	r24, 0x08	; 8
+    3f76:	19 d0       	rcall	.+50     	; 0x3faa <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f88:	23 d0       	rcall	.+70     	; 0x3fd0 <verifySpace>
+    3f78:	23 d0       	rcall	.+70     	; 0x3fc0 <verifySpace>
     }
     putch(STK_OK);
-    3f8a:	80 e1       	ldi	r24, 0x10	; 16
-    3f8c:	01 d0       	rcall	.+2      	; 0x3f90 <putch>
-    3f8e:	63 cf       	rjmp	.-314    	; 0x3e56 <main+0x56>
+    3f7a:	80 e1       	ldi	r24, 0x10	; 16
+    3f7c:	01 d0       	rcall	.+2      	; 0x3f80 <putch>
+    3f7e:	6b cf       	rjmp	.-298    	; 0x3e56 <main+0x56>
 
-00003f90 <putch>:
+00003f80 <putch>:
   }
 }
 
 void putch(char ch) {
-    3f90:	98 2f       	mov	r25, r24
+    3f80:	98 2f       	mov	r25, r24
 #ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    3f92:	80 91 c0 00 	lds	r24, 0x00C0
-    3f96:	85 ff       	sbrs	r24, 5
-    3f98:	fc cf       	rjmp	.-8      	; 0x3f92 <putch+0x2>
+    3f82:	80 91 c0 00 	lds	r24, 0x00C0
+    3f86:	85 ff       	sbrs	r24, 5
+    3f88:	fc cf       	rjmp	.-8      	; 0x3f82 <putch+0x2>
   UDR0 = ch;
-    3f9a:	90 93 c6 00 	sts	0x00C6, r25
+    3f8a:	90 93 c6 00 	sts	0x00C6, r25
       [uartBit] "I" (UART_TX_BIT)
     :
       "r25"
   );
 #endif
 }
-    3f9e:	08 95       	ret
+    3f8e:	08 95       	ret
 
-00003fa0 <getch>:
+00003f90 <getch>:
   return getch();
 }
 
 // Watchdog functions. These are only safe with interrupts turned off.
 void watchdogReset() {
   __asm__ __volatile__ (
-    3fa0:	a8 95       	wdr
+    3f90:	a8 95       	wdr
       [uartBit] "I" (UART_RX_BIT)
     :
       "r25"
 );
 #else
   while(!(UCSR0A & _BV(RXC0)));
-    3fa2:	80 91 c0 00 	lds	r24, 0x00C0
-    3fa6:	87 ff       	sbrs	r24, 7
-    3fa8:	fc cf       	rjmp	.-8      	; 0x3fa2 <getch+0x2>
+    3f92:	80 91 c0 00 	lds	r24, 0x00C0
+    3f96:	87 ff       	sbrs	r24, 7
+    3f98:	fc cf       	rjmp	.-8      	; 0x3f92 <getch+0x2>
   ch = UDR0;
-    3faa:	80 91 c6 00 	lds	r24, 0x00C6
+    3f9a:	80 91 c6 00 	lds	r24, 0x00C6
 #ifdef LED_DATA_FLASH
   LED_PIN |= _BV(LED);
 #endif
 
   return ch;
 }
-    3fae:	08 95       	ret
+    3f9e:	08 95       	ret
 
-00003fb0 <getLen>:
+00003fa0 <getLen>:
   } while (--count);
 }
 #endif
 
 uint8_t getLen() {
   getch();
-    3fb0:	f7 df       	rcall	.-18     	; 0x3fa0 <getch>
+    3fa0:	f7 df       	rcall	.-18     	; 0x3f90 <getch>
   length = getch();
-    3fb2:	f6 df       	rcall	.-20     	; 0x3fa0 <getch>
-    3fb4:	80 93 02 02 	sts	0x0202, r24
+    3fa2:	f6 df       	rcall	.-20     	; 0x3f90 <getch>
+    3fa4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fb8:	f3 cf       	rjmp	.-26     	; 0x3fa0 <getch>
+    3fa8:	f3 cf       	rjmp	.-26     	; 0x3f90 <getch>
 
-00003fba <watchdogConfig>:
+00003faa <watchdogConfig>:
     "wdr\n"
   );
 }
 
 void watchdogConfig(uint8_t x) {
   WDTCSR = _BV(WDCE) | _BV(WDE);
-    3fba:	e0 e6       	ldi	r30, 0x60	; 96
-    3fbc:	f0 e0       	ldi	r31, 0x00	; 0
-    3fbe:	98 e1       	ldi	r25, 0x18	; 24
-    3fc0:	90 83       	st	Z, r25
+    3faa:	e0 e6       	ldi	r30, 0x60	; 96
+    3fac:	f0 e0       	ldi	r31, 0x00	; 0
+    3fae:	98 e1       	ldi	r25, 0x18	; 24
+    3fb0:	90 83       	st	Z, r25
   WDTCSR = x;
-    3fc2:	80 83       	st	Z, r24
+    3fb2:	80 83       	st	Z, r24
 }
-    3fc4:	08 95       	ret
+    3fb4:	08 95       	ret
 
-00003fc6 <appStart>:
+00003fb6 <appStart>:
 
 void appStart() {
   watchdogConfig(WATCHDOG_OFF);
-    3fc6:	80 e0       	ldi	r24, 0x00	; 0
-    3fc8:	f8 df       	rcall	.-16     	; 0x3fba <watchdogConfig>
+    3fb6:	80 e0       	ldi	r24, 0x00	; 0
+    3fb8:	f8 df       	rcall	.-16     	; 0x3faa <watchdogConfig>
   __asm__ __volatile__ (
-    3fca:	ee 27       	eor	r30, r30
-    3fcc:	ff 27       	eor	r31, r31
-    3fce:	09 94       	ijmp
+    3fba:	ee 27       	eor	r30, r30
+    3fbc:	ff 27       	eor	r31, r31
+    3fbe:	09 94       	ijmp
 
-00003fd0 <verifySpace>:
+00003fc0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fd0:	e7 df       	rcall	.-50     	; 0x3fa0 <getch>
-    3fd2:	80 32       	cpi	r24, 0x20	; 32
-    3fd4:	09 f0       	breq	.+2      	; 0x3fd8 <verifySpace+0x8>
-    3fd6:	f7 df       	rcall	.-18     	; 0x3fc6 <appStart>
+    3fc0:	e7 df       	rcall	.-50     	; 0x3f90 <getch>
+    3fc2:	80 32       	cpi	r24, 0x20	; 32
+    3fc4:	09 f0       	breq	.+2      	; 0x3fc8 <verifySpace+0x8>
+    3fc6:	f7 df       	rcall	.-18     	; 0x3fb6 <appStart>
   putch(STK_INSYNC);
-    3fd8:	84 e1       	ldi	r24, 0x14	; 20
+    3fc8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fda:	da cf       	rjmp	.-76     	; 0x3f90 <putch>
+    3fca:	da cf       	rjmp	.-76     	; 0x3f80 <putch>
     ::[count] "M" (UART_B_VALUE)
   );
 }
 #endif
 
 void getNch(uint8_t count) {
-    3fdc:	1f 93       	push	r17
-    3fde:	18 2f       	mov	r17, r24
+    3fcc:	1f 93       	push	r17
+    3fce:	18 2f       	mov	r17, r24
 
-00003fe0 <getNch>:
+00003fd0 <getNch>:
   do getch(); while (--count);
-    3fe0:	df df       	rcall	.-66     	; 0x3fa0 <getch>
-    3fe2:	11 50       	subi	r17, 0x01	; 1
-    3fe4:	e9 f7       	brne	.-6      	; 0x3fe0 <getNch>
+    3fd0:	df df       	rcall	.-66     	; 0x3f90 <getch>
+    3fd2:	11 50       	subi	r17, 0x01	; 1
+    3fd4:	e9 f7       	brne	.-6      	; 0x3fd0 <getNch>
   verifySpace();
-    3fe6:	f4 df       	rcall	.-24     	; 0x3fd0 <verifySpace>
+    3fd6:	f4 df       	rcall	.-24     	; 0x3fc0 <verifySpace>
 }
-    3fe8:	1f 91       	pop	r17
-    3fea:	08 95       	ret
+    3fd8:	1f 91       	pop	r17
+    3fda:	08 95       	ret

+ 30 - 31
optiboot/bootloaders/optiboot/optiboot_lilypad.hex

@@ -1,34 +1,33 @@
-:103E000085E08093810084B714BE81FFE4D08DE00B
-:103E1000DCD0259A519A86E028E13EEF91E030937C
+:103E000085E08093810084B714BE81FFDCD08DE013
+:103E1000D4D0259A519A86E028E13EEF91E0309384
 :103E200085002093840096BBB09BFECF1D9AA89579
-:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D
-:103E4000ABD0813421F481E0D1D083E024C082342E
-:103E500011F484E103C0853419F485E0C7D08AC029
-:103E60008535A1F499D0082F10E01093010200933A
-:103E7000000292D090E0982F8827802B912B880FFA
-:103E8000991F909301028093000273C0863529F434
-:103E900084E0ACD080E071D06DC0843609F043C0BE
-:103EA0008FD0E0910002F091010283E080935700EF
-:103EB000E895C0E0D1E070D08993809102028150F2
-:103EC000809302028823B9F78BD007B600FCFDCFA0
-:103ED0004091000250910102A0E0B1E02C9130E04D
-:103EE00011968C91119790E0982F8827822B932B15
-:103EF0001296FA010C01D0925700E89511244E5FFA
-:103F00005F4FF1E0A038BF0749F7E0910002F09160
-:103F10000102E0925700E89507B600FCFDCFF09251
-:103F20005700E89527C08437B9F44AD059D0E091BA
-:103F30000002F09101023196F0930102E093000239
-:103F40003197E4918E2F19D0809102028150809395
-:103F50000202882361F70EC0853739F441D08EE123
-:103F60000CD084E90AD086E096CF813511F488E040
-:103F70002CD036D080E101D063CF2AE030E08095AC
-:103F8000089410F4599802C0599A000015D014D022
-:103F900086952A95B1F70895A89529E030E04899CB
-:103FA000FECF0AD009D008D08894489908942A9561
-:103FB00011F08795F7CF089598E09A95F1F7089555
-:103FC000EBDFEADF80930202E7CFE0E6F0E098E182
-:103FD00090838083089580E0F8DFEE27FF2709941F
-:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2
-:0C3FF000D3DF1150E9F7F4DF1F910895B2
+:103E30008150A9F7DD24D394A5E0FA2EF1E1EF2E0D
+:103E4000A3D0813421F481E0C9D083E020C0823442
+:103E500011F484E103C0853419F485E0BFD082C039
+:103E6000853581F491D0082F10E08ED090E0982F06
+:103E70008827802B912B880F991F909301028093A4
+:103E800000026FC0863529F484E0A8D080E06DD0B0
+:103E900069C0843609F03FC08BD0E0910002F091F8
+:103EA000010283E087BFE895C0E0D1E06DD089933F
+:103EB000809102028150809302028823B9F788D052
+:103EC00007B600FCFDCF4091000250910102A0E036
+:103ED000B1E02C9130E011968C91119790E0982FE1
+:103EE0008827822B932B1296FA010C01D7BEE895F6
+:103EF00011244E5F5F4FF1E0A038BF0751F7E0910A
+:103F00000002F0910102F7BEE89507B600FCFDCF74
+:103F1000E7BEE89527C08437B9F44AD059D0E0917C
+:103F20000002F09101023196F0930102E093000249
+:103F30003197E4918E2F19D08091020281508093A5
+:103F40000202882361F70EC0853739F441D08EE133
+:103F50000CD084E90AD086E09ACF813511F488E04C
+:103F60002CD036D080E101D06BCF2AE030E08095B4
+:103F7000089410F4599802C0599A000015D014D032
+:103F800086952A95B1F70895A89529E030E04899DB
+:103F9000FECF0AD009D008D08894489908942A9571
+:103FA00011F08795F7CF089598E09A95F1F7089565
+:103FB000EBDFEADF80930202E7CFE0E6F0E098E192
+:103FC00090838083089580E0F8DFEE27FF2709942F
+:103FD000DBDF803209F0F7DF84E1C7CF1F93182FB2
+:0C3FE000D3DF1150E9F7F4DF1F910895C2
 :0400000300003E00BB
 :00000001FF

+ 231 - 226
optiboot/bootloaders/optiboot/optiboot_lilypad.lst

@@ -3,34 +3,34 @@ optiboot_lilypad.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fc  00003e00  00003e00  00000054  2**1
+  0 .text         000001ec  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000240  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000268  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   00000277  00000000  00000000  000002f0  2**0
+  3 .debug_info   00000291  00000000  00000000  000002e0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000194  00000000  00000000  00000567  2**0
+  4 .debug_abbrev 000001ac  00000000  00000000  00000571  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003bb  00000000  00000000  000006fb  2**0
+  5 .debug_line   000003c3  00000000  00000000  0000071d  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  000000a0  00000000  00000000  00000ab8  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ae0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000013f  00000000  00000000  00000b58  2**0
+  7 .debug_str    0000014a  00000000  00000000  00000b80  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001a0  00000000  00000000  00000c97  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000cca  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000070  00000000  00000000  00000e37  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e6a  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
 
 00003e00 <main>:
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
@@ -46,12 +46,12 @@ int main(void) {
     3e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
     3e0a:	81 ff       	sbrs	r24, 1
-    3e0c:	e4 d0       	rcall	.+456    	; 0x3fd6 <appStart>
+    3e0c:	dc d0       	rcall	.+440    	; 0x3fc6 <appStart>
 
   // Set up watchdog to trigger after 500ms
   watchdogConfig(WATCHDOG_500MS);
     3e0e:	8d e0       	ldi	r24, 0x0D	; 13
-    3e10:	dc d0       	rcall	.+440    	; 0x3fca <watchdogConfig>
+    3e10:	d4 d0       	rcall	.+424    	; 0x3fba <watchdogConfig>
 
   /* Set LED pin as output */
   LED_DDR |= _BV(LED);
@@ -110,28 +110,28 @@ void watchdogReset() {
       getNch(1);
     3e34:	dd 24       	eor	r13, r13
     3e36:	d3 94       	inc	r13
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
+      __boot_page_write_short((uint16_t)(void*)address);
     3e38:	a5 e0       	ldi	r26, 0x05	; 5
-    3e3a:	ea 2e       	mov	r14, r26
+    3e3a:	fa 2e       	mov	r15, r26
       boot_spm_busy_wait();
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
     3e3c:	f1 e1       	ldi	r31, 0x11	; 17
-    3e3e:	ff 2e       	mov	r15, r31
+    3e3e:	ef 2e       	mov	r14, r31
 #endif
 
   /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e40:	ab d0       	rcall	.+342    	; 0x3f98 <getch>
+    3e40:	a3 d0       	rcall	.+326    	; 0x3f88 <getch>
 
     if(ch == STK_GET_PARAMETER) {
     3e42:	81 34       	cpi	r24, 0x41	; 65
@@ -139,10 +139,10 @@ void watchdogReset() {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
     3e46:	81 e0       	ldi	r24, 0x01	; 1
-    3e48:	d1 d0       	rcall	.+418    	; 0x3fec <verifySpace+0xc>
+    3e48:	c9 d0       	rcall	.+402    	; 0x3fdc <verifySpace+0xc>
       putch(0x03);
     3e4a:	83 e0       	ldi	r24, 0x03	; 3
-    3e4c:	24 c0       	rjmp	.+72     	; 0x3e96 <main+0x96>
+    3e4c:	20 c0       	rjmp	.+64     	; 0x3e8e <main+0x8e>
     }
     else if(ch == STK_SET_DEVICE) {
     3e4e:	82 34       	cpi	r24, 0x42	; 66
@@ -158,376 +158,381 @@ void watchdogReset() {
       // SET DEVICE EXT is ignored
       getNch(5);
     3e5a:	85 e0       	ldi	r24, 0x05	; 5
-    3e5c:	c7 d0       	rcall	.+398    	; 0x3fec <verifySpace+0xc>
-    3e5e:	8a c0       	rjmp	.+276    	; 0x3f74 <main+0x174>
+    3e5c:	bf d0       	rcall	.+382    	; 0x3fdc <verifySpace+0xc>
+    3e5e:	82 c0       	rjmp	.+260    	; 0x3f64 <main+0x164>
     }
     else if(ch == STK_LOAD_ADDRESS) {
     3e60:	85 35       	cpi	r24, 0x55	; 85
-    3e62:	a1 f4       	brne	.+40     	; 0x3e8c <main+0x8c>
+    3e62:	81 f4       	brne	.+32     	; 0x3e84 <main+0x84>
       // LOAD ADDRESS
-      address = getch();
-    3e64:	99 d0       	rcall	.+306    	; 0x3f98 <getch>
+      uint16_t newAddress;
+      newAddress = getch();
+    3e64:	91 d0       	rcall	.+290    	; 0x3f88 <getch>
+      newAddress = (newAddress & 0xff) | (getch() << 8);
     3e66:	08 2f       	mov	r16, r24
     3e68:	10 e0       	ldi	r17, 0x00	; 0
-    3e6a:	10 93 01 02 	sts	0x0201, r17
-    3e6e:	00 93 00 02 	sts	0x0200, r16
-      address = (address & 0xff) | (getch() << 8);
-    3e72:	92 d0       	rcall	.+292    	; 0x3f98 <getch>
-    3e74:	90 e0       	ldi	r25, 0x00	; 0
-    3e76:	98 2f       	mov	r25, r24
-    3e78:	88 27       	eor	r24, r24
-    3e7a:	80 2b       	or	r24, r16
-    3e7c:	91 2b       	or	r25, r17
-      address += address; // Convert from word address to byte address
-    3e7e:	88 0f       	add	r24, r24
-    3e80:	99 1f       	adc	r25, r25
-    3e82:	90 93 01 02 	sts	0x0201, r25
-    3e86:	80 93 00 02 	sts	0x0200, r24
-    3e8a:	73 c0       	rjmp	.+230    	; 0x3f72 <main+0x172>
+    3e6a:	8e d0       	rcall	.+284    	; 0x3f88 <getch>
+    3e6c:	90 e0       	ldi	r25, 0x00	; 0
+    3e6e:	98 2f       	mov	r25, r24
+    3e70:	88 27       	eor	r24, r24
+    3e72:	80 2b       	or	r24, r16
+    3e74:	91 2b       	or	r25, r17
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+    3e76:	88 0f       	add	r24, r24
+    3e78:	99 1f       	adc	r25, r25
+      address = newAddress;
+    3e7a:	90 93 01 02 	sts	0x0201, r25
+    3e7e:	80 93 00 02 	sts	0x0200, r24
+    3e82:	6f c0       	rjmp	.+222    	; 0x3f62 <main+0x162>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3e8c:	86 35       	cpi	r24, 0x56	; 86
-    3e8e:	29 f4       	brne	.+10     	; 0x3e9a <main+0x9a>
+    3e84:	86 35       	cpi	r24, 0x56	; 86
+    3e86:	29 f4       	brne	.+10     	; 0x3e92 <main+0x92>
       // UNIVERSAL command is ignored
       getNch(4);
-    3e90:	84 e0       	ldi	r24, 0x04	; 4
-    3e92:	ac d0       	rcall	.+344    	; 0x3fec <verifySpace+0xc>
+    3e88:	84 e0       	ldi	r24, 0x04	; 4
+    3e8a:	a8 d0       	rcall	.+336    	; 0x3fdc <verifySpace+0xc>
       putch(0x00);
-    3e94:	80 e0       	ldi	r24, 0x00	; 0
-    3e96:	71 d0       	rcall	.+226    	; 0x3f7a <putch>
-    3e98:	6d c0       	rjmp	.+218    	; 0x3f74 <main+0x174>
+    3e8c:	80 e0       	ldi	r24, 0x00	; 0
+    3e8e:	6d d0       	rcall	.+218    	; 0x3f6a <putch>
+    3e90:	69 c0       	rjmp	.+210    	; 0x3f64 <main+0x164>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3e9a:	84 36       	cpi	r24, 0x64	; 100
-    3e9c:	09 f0       	breq	.+2      	; 0x3ea0 <main+0xa0>
-    3e9e:	43 c0       	rjmp	.+134    	; 0x3f26 <main+0x126>
+    3e92:	84 36       	cpi	r24, 0x64	; 100
+    3e94:	09 f0       	breq	.+2      	; 0x3e98 <main+0x98>
+    3e96:	3f c0       	rjmp	.+126    	; 0x3f16 <main+0x116>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
 
       getLen();
-    3ea0:	8f d0       	rcall	.+286    	; 0x3fc0 <getLen>
+    3e98:	8b d0       	rcall	.+278    	; 0x3fb0 <getLen>
 
       // Immediately start page erase - this will 4.5ms
-      boot_page_erase((uint16_t)(void*)address);
-    3ea2:	e0 91 00 02 	lds	r30, 0x0200
-    3ea6:	f0 91 01 02 	lds	r31, 0x0201
-    3eaa:	83 e0       	ldi	r24, 0x03	; 3
-    3eac:	80 93 57 00 	sts	0x0057, r24
-    3eb0:	e8 95       	spm
-    3eb2:	c0 e0       	ldi	r28, 0x00	; 0
-    3eb4:	d1 e0       	ldi	r29, 0x01	; 1
-
+      __boot_page_erase_short((uint16_t)(void*)address);
+    3e9a:	e0 91 00 02 	lds	r30, 0x0200
+    3e9e:	f0 91 01 02 	lds	r31, 0x0201
+    3ea2:	83 e0       	ldi	r24, 0x03	; 3
+    3ea4:	87 bf       	out	0x37, r24	; 55
+    3ea6:	e8 95       	spm
+    3ea8:	c0 e0       	ldi	r28, 0x00	; 0
+    3eaa:	d1 e0       	ldi	r29, 0x01	; 1
+      
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3eb6:	70 d0       	rcall	.+224    	; 0x3f98 <getch>
-    3eb8:	89 93       	st	Y+, r24
+    3eac:	6d d0       	rcall	.+218    	; 0x3f88 <getch>
+    3eae:	89 93       	st	Y+, r24
       while (--length);
-    3eba:	80 91 02 02 	lds	r24, 0x0202
-    3ebe:	81 50       	subi	r24, 0x01	; 1
-    3ec0:	80 93 02 02 	sts	0x0202, r24
-    3ec4:	88 23       	and	r24, r24
-    3ec6:	b9 f7       	brne	.-18     	; 0x3eb6 <main+0xb6>
+    3eb0:	80 91 02 02 	lds	r24, 0x0202
+    3eb4:	81 50       	subi	r24, 0x01	; 1
+    3eb6:	80 93 02 02 	sts	0x0202, r24
+    3eba:	88 23       	and	r24, r24
+    3ebc:	b9 f7       	brne	.-18     	; 0x3eac <main+0xac>
 
       // Read command terminator, start reply
       verifySpace();
-    3ec8:	8b d0       	rcall	.+278    	; 0x3fe0 <verifySpace>
+    3ebe:	88 d0       	rcall	.+272    	; 0x3fd0 <verifySpace>
       
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3eca:	07 b6       	in	r0, 0x37	; 55
-    3ecc:	00 fc       	sbrc	r0, 0
-    3ece:	fd cf       	rjmp	.-6      	; 0x3eca <main+0xca>
+    3ec0:	07 b6       	in	r0, 0x37	; 55
+    3ec2:	00 fc       	sbrc	r0, 0
+    3ec4:	fd cf       	rjmp	.-6      	; 0x3ec0 <main+0xc0>
       }
 #endif
 
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ed0:	40 91 00 02 	lds	r20, 0x0200
-    3ed4:	50 91 01 02 	lds	r21, 0x0201
-    3ed8:	a0 e0       	ldi	r26, 0x00	; 0
-    3eda:	b1 e0       	ldi	r27, 0x01	; 1
+    3ec6:	40 91 00 02 	lds	r20, 0x0200
+    3eca:	50 91 01 02 	lds	r21, 0x0201
+    3ece:	a0 e0       	ldi	r26, 0x00	; 0
+    3ed0:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3edc:	2c 91       	ld	r18, X
-    3ede:	30 e0       	ldi	r19, 0x00	; 0
+    3ed2:	2c 91       	ld	r18, X
+    3ed4:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ee0:	11 96       	adiw	r26, 0x01	; 1
-    3ee2:	8c 91       	ld	r24, X
-    3ee4:	11 97       	sbiw	r26, 0x01	; 1
-    3ee6:	90 e0       	ldi	r25, 0x00	; 0
-    3ee8:	98 2f       	mov	r25, r24
-    3eea:	88 27       	eor	r24, r24
-    3eec:	82 2b       	or	r24, r18
-    3eee:	93 2b       	or	r25, r19
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+    3ed6:	11 96       	adiw	r26, 0x01	; 1
+    3ed8:	8c 91       	ld	r24, X
+    3eda:	11 97       	sbiw	r26, 0x01	; 1
+    3edc:	90 e0       	ldi	r25, 0x00	; 0
+    3ede:	98 2f       	mov	r25, r24
+    3ee0:	88 27       	eor	r24, r24
+    3ee2:	82 2b       	or	r24, r18
+    3ee4:	93 2b       	or	r25, r19
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
-    3ef0:	12 96       	adiw	r26, 0x02	; 2
+    3ee6:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3ef2:	fa 01       	movw	r30, r20
-    3ef4:	0c 01       	movw	r0, r24
-    3ef6:	d0 92 57 00 	sts	0x0057, r13
-    3efa:	e8 95       	spm
-    3efc:	11 24       	eor	r1, r1
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+    3ee8:	fa 01       	movw	r30, r20
+    3eea:	0c 01       	movw	r0, r24
+    3eec:	d7 be       	out	0x37, r13	; 55
+    3eee:	e8 95       	spm
+    3ef0:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3efe:	4e 5f       	subi	r20, 0xFE	; 254
-    3f00:	5f 4f       	sbci	r21, 0xFF	; 255
+    3ef2:	4e 5f       	subi	r20, 0xFE	; 254
+    3ef4:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f02:	f1 e0       	ldi	r31, 0x01	; 1
-    3f04:	a0 38       	cpi	r26, 0x80	; 128
-    3f06:	bf 07       	cpc	r27, r31
-    3f08:	49 f7       	brne	.-46     	; 0x3edc <main+0xdc>
+    3ef6:	f1 e0       	ldi	r31, 0x01	; 1
+    3ef8:	a0 38       	cpi	r26, 0x80	; 128
+    3efa:	bf 07       	cpc	r27, r31
+    3efc:	51 f7       	brne	.-44     	; 0x3ed2 <main+0xd2>
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
-    3f0a:	e0 91 00 02 	lds	r30, 0x0200
-    3f0e:	f0 91 01 02 	lds	r31, 0x0201
-    3f12:	e0 92 57 00 	sts	0x0057, r14
-    3f16:	e8 95       	spm
+      __boot_page_write_short((uint16_t)(void*)address);
+    3efe:	e0 91 00 02 	lds	r30, 0x0200
+    3f02:	f0 91 01 02 	lds	r31, 0x0201
+    3f06:	f7 be       	out	0x37, r15	; 55
+    3f08:	e8 95       	spm
       boot_spm_busy_wait();
-    3f18:	07 b6       	in	r0, 0x37	; 55
-    3f1a:	00 fc       	sbrc	r0, 0
-    3f1c:	fd cf       	rjmp	.-6      	; 0x3f18 <main+0x118>
+    3f0a:	07 b6       	in	r0, 0x37	; 55
+    3f0c:	00 fc       	sbrc	r0, 0
+    3f0e:	fd cf       	rjmp	.-6      	; 0x3f0a <main+0x10a>
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
-    3f1e:	f0 92 57 00 	sts	0x0057, r15
-    3f22:	e8 95       	spm
-    3f24:	27 c0       	rjmp	.+78     	; 0x3f74 <main+0x174>
+    3f10:	e7 be       	out	0x37, r14	; 55
+    3f12:	e8 95       	spm
+    3f14:	27 c0       	rjmp	.+78     	; 0x3f64 <main+0x164>
 #endif
 
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f26:	84 37       	cpi	r24, 0x74	; 116
-    3f28:	b9 f4       	brne	.+46     	; 0x3f58 <main+0x158>
+    3f16:	84 37       	cpi	r24, 0x74	; 116
+    3f18:	b9 f4       	brne	.+46     	; 0x3f48 <main+0x148>
       // READ PAGE - we only read flash
       getLen();
-    3f2a:	4a d0       	rcall	.+148    	; 0x3fc0 <getLen>
+    3f1a:	4a d0       	rcall	.+148    	; 0x3fb0 <getLen>
       verifySpace();
-    3f2c:	59 d0       	rcall	.+178    	; 0x3fe0 <verifySpace>
-        else ch = pgm_read_byte_near(address);
+    3f1c:	59 d0       	rcall	.+178    	; 0x3fd0 <verifySpace>
+        putch(result);
         address++;
-        putch(ch);
-      } while (--length);
+      }
+      while (--length);
 #else
       do putch(pgm_read_byte_near(address++));
-    3f2e:	e0 91 00 02 	lds	r30, 0x0200
-    3f32:	f0 91 01 02 	lds	r31, 0x0201
-    3f36:	31 96       	adiw	r30, 0x01	; 1
-    3f38:	f0 93 01 02 	sts	0x0201, r31
-    3f3c:	e0 93 00 02 	sts	0x0200, r30
-    3f40:	31 97       	sbiw	r30, 0x01	; 1
-    3f42:	e4 91       	lpm	r30, Z+
-    3f44:	8e 2f       	mov	r24, r30
-    3f46:	19 d0       	rcall	.+50     	; 0x3f7a <putch>
+    3f1e:	e0 91 00 02 	lds	r30, 0x0200
+    3f22:	f0 91 01 02 	lds	r31, 0x0201
+    3f26:	31 96       	adiw	r30, 0x01	; 1
+    3f28:	f0 93 01 02 	sts	0x0201, r31
+    3f2c:	e0 93 00 02 	sts	0x0200, r30
+    3f30:	31 97       	sbiw	r30, 0x01	; 1
+    3f32:	e4 91       	lpm	r30, Z+
+    3f34:	8e 2f       	mov	r24, r30
+    3f36:	19 d0       	rcall	.+50     	; 0x3f6a <putch>
       while (--length);
-    3f48:	80 91 02 02 	lds	r24, 0x0202
-    3f4c:	81 50       	subi	r24, 0x01	; 1
-    3f4e:	80 93 02 02 	sts	0x0202, r24
-    3f52:	88 23       	and	r24, r24
-    3f54:	61 f7       	brne	.-40     	; 0x3f2e <main+0x12e>
-    3f56:	0e c0       	rjmp	.+28     	; 0x3f74 <main+0x174>
+    3f38:	80 91 02 02 	lds	r24, 0x0202
+    3f3c:	81 50       	subi	r24, 0x01	; 1
+    3f3e:	80 93 02 02 	sts	0x0202, r24
+    3f42:	88 23       	and	r24, r24
+    3f44:	61 f7       	brne	.-40     	; 0x3f1e <main+0x11e>
+    3f46:	0e c0       	rjmp	.+28     	; 0x3f64 <main+0x164>
+#endif
 #endif
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f58:	85 37       	cpi	r24, 0x75	; 117
-    3f5a:	39 f4       	brne	.+14     	; 0x3f6a <main+0x16a>
+    3f48:	85 37       	cpi	r24, 0x75	; 117
+    3f4a:	39 f4       	brne	.+14     	; 0x3f5a <main+0x15a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f5c:	41 d0       	rcall	.+130    	; 0x3fe0 <verifySpace>
+    3f4c:	41 d0       	rcall	.+130    	; 0x3fd0 <verifySpace>
       putch(SIGNATURE_0);
-    3f5e:	8e e1       	ldi	r24, 0x1E	; 30
-    3f60:	0c d0       	rcall	.+24     	; 0x3f7a <putch>
+    3f4e:	8e e1       	ldi	r24, 0x1E	; 30
+    3f50:	0c d0       	rcall	.+24     	; 0x3f6a <putch>
       putch(SIGNATURE_1);
-    3f62:	84 e9       	ldi	r24, 0x94	; 148
-    3f64:	0a d0       	rcall	.+20     	; 0x3f7a <putch>
+    3f52:	84 e9       	ldi	r24, 0x94	; 148
+    3f54:	0a d0       	rcall	.+20     	; 0x3f6a <putch>
       putch(SIGNATURE_2);
-    3f66:	86 e0       	ldi	r24, 0x06	; 6
-    3f68:	96 cf       	rjmp	.-212    	; 0x3e96 <main+0x96>
+    3f56:	86 e0       	ldi	r24, 0x06	; 6
+    3f58:	9a cf       	rjmp	.-204    	; 0x3e8e <main+0x8e>
     }
     else if (ch == 'Q') {
-    3f6a:	81 35       	cpi	r24, 0x51	; 81
-    3f6c:	11 f4       	brne	.+4      	; 0x3f72 <main+0x172>
+    3f5a:	81 35       	cpi	r24, 0x51	; 81
+    3f5c:	11 f4       	brne	.+4      	; 0x3f62 <main+0x162>
       // Adaboot no-wait mod
       watchdogConfig(WATCHDOG_16MS);
-    3f6e:	88 e0       	ldi	r24, 0x08	; 8
-    3f70:	2c d0       	rcall	.+88     	; 0x3fca <watchdogConfig>
+    3f5e:	88 e0       	ldi	r24, 0x08	; 8
+    3f60:	2c d0       	rcall	.+88     	; 0x3fba <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f72:	36 d0       	rcall	.+108    	; 0x3fe0 <verifySpace>
+    3f62:	36 d0       	rcall	.+108    	; 0x3fd0 <verifySpace>
     }
     putch(STK_OK);
-    3f74:	80 e1       	ldi	r24, 0x10	; 16
-    3f76:	01 d0       	rcall	.+2      	; 0x3f7a <putch>
-    3f78:	63 cf       	rjmp	.-314    	; 0x3e40 <main+0x40>
+    3f64:	80 e1       	ldi	r24, 0x10	; 16
+    3f66:	01 d0       	rcall	.+2      	; 0x3f6a <putch>
+    3f68:	6b cf       	rjmp	.-298    	; 0x3e40 <main+0x40>
 
-00003f7a <putch>:
+00003f6a <putch>:
 void putch(char ch) {
 #ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
   UDR0 = ch;
 #else
   __asm__ __volatile__ (
-    3f7a:	2a e0       	ldi	r18, 0x0A	; 10
-    3f7c:	30 e0       	ldi	r19, 0x00	; 0
-    3f7e:	80 95       	com	r24
-    3f80:	08 94       	sec
-    3f82:	10 f4       	brcc	.+4      	; 0x3f88 <putch+0xe>
-    3f84:	59 98       	cbi	0x0b, 1	; 11
-    3f86:	02 c0       	rjmp	.+4      	; 0x3f8c <putch+0x12>
-    3f88:	59 9a       	sbi	0x0b, 1	; 11
-    3f8a:	00 00       	nop
-    3f8c:	15 d0       	rcall	.+42     	; 0x3fb8 <uartDelay>
-    3f8e:	14 d0       	rcall	.+40     	; 0x3fb8 <uartDelay>
-    3f90:	86 95       	lsr	r24
-    3f92:	2a 95       	dec	r18
-    3f94:	b1 f7       	brne	.-20     	; 0x3f82 <putch+0x8>
+    3f6a:	2a e0       	ldi	r18, 0x0A	; 10
+    3f6c:	30 e0       	ldi	r19, 0x00	; 0
+    3f6e:	80 95       	com	r24
+    3f70:	08 94       	sec
+    3f72:	10 f4       	brcc	.+4      	; 0x3f78 <putch+0xe>
+    3f74:	59 98       	cbi	0x0b, 1	; 11
+    3f76:	02 c0       	rjmp	.+4      	; 0x3f7c <putch+0x12>
+    3f78:	59 9a       	sbi	0x0b, 1	; 11
+    3f7a:	00 00       	nop
+    3f7c:	15 d0       	rcall	.+42     	; 0x3fa8 <uartDelay>
+    3f7e:	14 d0       	rcall	.+40     	; 0x3fa8 <uartDelay>
+    3f80:	86 95       	lsr	r24
+    3f82:	2a 95       	dec	r18
+    3f84:	b1 f7       	brne	.-20     	; 0x3f72 <putch+0x8>
       [uartBit] "I" (UART_TX_BIT)
     :
       "r25"
   );
 #endif
 }
-    3f96:	08 95       	ret
+    3f86:	08 95       	ret
 
-00003f98 <getch>:
+00003f88 <getch>:
   return getch();
 }
 
 // Watchdog functions. These are only safe with interrupts turned off.
 void watchdogReset() {
   __asm__ __volatile__ (
-    3f98:	a8 95       	wdr
+    3f88:	a8 95       	wdr
 #ifdef LED_DATA_FLASH
   LED_PIN |= _BV(LED);
 #endif
 
   return ch;
 }
-    3f9a:	29 e0       	ldi	r18, 0x09	; 9
-    3f9c:	30 e0       	ldi	r19, 0x00	; 0
-    3f9e:	48 99       	sbic	0x09, 0	; 9
-    3fa0:	fe cf       	rjmp	.-4      	; 0x3f9e <getch+0x6>
-    3fa2:	0a d0       	rcall	.+20     	; 0x3fb8 <uartDelay>
-    3fa4:	09 d0       	rcall	.+18     	; 0x3fb8 <uartDelay>
-    3fa6:	08 d0       	rcall	.+16     	; 0x3fb8 <uartDelay>
-    3fa8:	88 94       	clc
-    3faa:	48 99       	sbic	0x09, 0	; 9
-    3fac:	08 94       	sec
-    3fae:	2a 95       	dec	r18
-    3fb0:	11 f0       	breq	.+4      	; 0x3fb6 <getch+0x1e>
-    3fb2:	87 95       	ror	r24
-    3fb4:	f7 cf       	rjmp	.-18     	; 0x3fa4 <getch+0xc>
-    3fb6:	08 95       	ret
-
-00003fb8 <uartDelay>:
+    3f8a:	29 e0       	ldi	r18, 0x09	; 9
+    3f8c:	30 e0       	ldi	r19, 0x00	; 0
+    3f8e:	48 99       	sbic	0x09, 0	; 9
+    3f90:	fe cf       	rjmp	.-4      	; 0x3f8e <getch+0x6>
+    3f92:	0a d0       	rcall	.+20     	; 0x3fa8 <uartDelay>
+    3f94:	09 d0       	rcall	.+18     	; 0x3fa8 <uartDelay>
+    3f96:	08 d0       	rcall	.+16     	; 0x3fa8 <uartDelay>
+    3f98:	88 94       	clc
+    3f9a:	48 99       	sbic	0x09, 0	; 9
+    3f9c:	08 94       	sec
+    3f9e:	2a 95       	dec	r18
+    3fa0:	11 f0       	breq	.+4      	; 0x3fa6 <getch+0x1e>
+    3fa2:	87 95       	ror	r24
+    3fa4:	f7 cf       	rjmp	.-18     	; 0x3f94 <getch+0xc>
+    3fa6:	08 95       	ret
+
+00003fa8 <uartDelay>:
 #if UART_B_VALUE > 255
 #error Baud rate too slow for soft UART
 #endif
 
 void uartDelay() {
   __asm__ __volatile__ (
-    3fb8:	98 e0       	ldi	r25, 0x08	; 8
-    3fba:	9a 95       	dec	r25
-    3fbc:	f1 f7       	brne	.-4      	; 0x3fba <uartDelay+0x2>
-    3fbe:	08 95       	ret
+    3fa8:	98 e0       	ldi	r25, 0x08	; 8
+    3faa:	9a 95       	dec	r25
+    3fac:	f1 f7       	brne	.-4      	; 0x3faa <uartDelay+0x2>
+    3fae:	08 95       	ret
 
-00003fc0 <getLen>:
+00003fb0 <getLen>:
   } while (--count);
 }
 #endif
 
 uint8_t getLen() {
   getch();
-    3fc0:	eb df       	rcall	.-42     	; 0x3f98 <getch>
+    3fb0:	eb df       	rcall	.-42     	; 0x3f88 <getch>
   length = getch();
-    3fc2:	ea df       	rcall	.-44     	; 0x3f98 <getch>
-    3fc4:	80 93 02 02 	sts	0x0202, r24
+    3fb2:	ea df       	rcall	.-44     	; 0x3f88 <getch>
+    3fb4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fc8:	e7 cf       	rjmp	.-50     	; 0x3f98 <getch>
+    3fb8:	e7 cf       	rjmp	.-50     	; 0x3f88 <getch>
 
-00003fca <watchdogConfig>:
+00003fba <watchdogConfig>:
     "wdr\n"
   );
 }
 
 void watchdogConfig(uint8_t x) {
   WDTCSR = _BV(WDCE) | _BV(WDE);
-    3fca:	e0 e6       	ldi	r30, 0x60	; 96
-    3fcc:	f0 e0       	ldi	r31, 0x00	; 0
-    3fce:	98 e1       	ldi	r25, 0x18	; 24
-    3fd0:	90 83       	st	Z, r25
+    3fba:	e0 e6       	ldi	r30, 0x60	; 96
+    3fbc:	f0 e0       	ldi	r31, 0x00	; 0
+    3fbe:	98 e1       	ldi	r25, 0x18	; 24
+    3fc0:	90 83       	st	Z, r25
   WDTCSR = x;
-    3fd2:	80 83       	st	Z, r24
+    3fc2:	80 83       	st	Z, r24
 }
-    3fd4:	08 95       	ret
+    3fc4:	08 95       	ret
 
-00003fd6 <appStart>:
+00003fc6 <appStart>:
 
 void appStart() {
   watchdogConfig(WATCHDOG_OFF);
-    3fd6:	80 e0       	ldi	r24, 0x00	; 0
-    3fd8:	f8 df       	rcall	.-16     	; 0x3fca <watchdogConfig>
+    3fc6:	80 e0       	ldi	r24, 0x00	; 0
+    3fc8:	f8 df       	rcall	.-16     	; 0x3fba <watchdogConfig>
   __asm__ __volatile__ (
-    3fda:	ee 27       	eor	r30, r30
-    3fdc:	ff 27       	eor	r31, r31
-    3fde:	09 94       	ijmp
+    3fca:	ee 27       	eor	r30, r30
+    3fcc:	ff 27       	eor	r31, r31
+    3fce:	09 94       	ijmp
 
-00003fe0 <verifySpace>:
+00003fd0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fe0:	db df       	rcall	.-74     	; 0x3f98 <getch>
-    3fe2:	80 32       	cpi	r24, 0x20	; 32
-    3fe4:	09 f0       	breq	.+2      	; 0x3fe8 <verifySpace+0x8>
-    3fe6:	f7 df       	rcall	.-18     	; 0x3fd6 <appStart>
+    3fd0:	db df       	rcall	.-74     	; 0x3f88 <getch>
+    3fd2:	80 32       	cpi	r24, 0x20	; 32
+    3fd4:	09 f0       	breq	.+2      	; 0x3fd8 <verifySpace+0x8>
+    3fd6:	f7 df       	rcall	.-18     	; 0x3fc6 <appStart>
   putch(STK_INSYNC);
-    3fe8:	84 e1       	ldi	r24, 0x14	; 20
+    3fd8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fea:	c7 cf       	rjmp	.-114    	; 0x3f7a <putch>
+    3fda:	c7 cf       	rjmp	.-114    	; 0x3f6a <putch>
     ::[count] "M" (UART_B_VALUE)
   );
 }
 #endif
 
 void getNch(uint8_t count) {
-    3fec:	1f 93       	push	r17
-    3fee:	18 2f       	mov	r17, r24
+    3fdc:	1f 93       	push	r17
+    3fde:	18 2f       	mov	r17, r24
 
-00003ff0 <getNch>:
+00003fe0 <getNch>:
   do getch(); while (--count);
-    3ff0:	d3 df       	rcall	.-90     	; 0x3f98 <getch>
-    3ff2:	11 50       	subi	r17, 0x01	; 1
-    3ff4:	e9 f7       	brne	.-6      	; 0x3ff0 <getNch>
+    3fe0:	d3 df       	rcall	.-90     	; 0x3f88 <getch>
+    3fe2:	11 50       	subi	r17, 0x01	; 1
+    3fe4:	e9 f7       	brne	.-6      	; 0x3fe0 <getNch>
   verifySpace();
-    3ff6:	f4 df       	rcall	.-24     	; 0x3fe0 <verifySpace>
+    3fe6:	f4 df       	rcall	.-24     	; 0x3fd0 <verifySpace>
 }
-    3ff8:	1f 91       	pop	r17
-    3ffa:	08 95       	ret
+    3fe8:	1f 91       	pop	r17
+    3fea:	08 95       	ret

+ 30 - 31
optiboot/bootloaders/optiboot/optiboot_lilypad_resonator.hex

@@ -1,34 +1,33 @@
-:103E000085E08093810084B714BE81FFE4D08DE00B
-:103E1000DCD0259A519A86E028E13EEF91E030937C
+:103E000085E08093810084B714BE81FFDCD08DE013
+:103E1000D4D0259A519A86E028E13EEF91E0309384
 :103E200085002093840096BBB09BFECF1D9AA89579
-:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D
-:103E4000ABD0813421F481E0D1D083E024C082342E
-:103E500011F484E103C0853419F485E0C7D08AC029
-:103E60008535A1F499D0082F10E01093010200933A
-:103E7000000292D090E0982F8827802B912B880FFA
-:103E8000991F909301028093000273C0863529F434
-:103E900084E0ACD080E071D06DC0843609F043C0BE
-:103EA0008FD0E0910002F091010283E080935700EF
-:103EB000E895C0E0D1E070D08993809102028150F2
-:103EC000809302028823B9F78BD007B600FCFDCFA0
-:103ED0004091000250910102A0E0B1E02C9130E04D
-:103EE00011968C91119790E0982F8827822B932B15
-:103EF0001296FA010C01D0925700E89511244E5FFA
-:103F00005F4FF1E0A038BF0749F7E0910002F09160
-:103F10000102E0925700E89507B600FCFDCFF09251
-:103F20005700E89527C08437B9F44AD059D0E091BA
-:103F30000002F09101023196F0930102E093000239
-:103F40003197E4918E2F19D0809102028150809395
-:103F50000202882361F70EC0853739F441D08EE123
-:103F60000CD084E90AD086E096CF813511F488E040
-:103F70002CD036D080E101D063CF2AE030E08095AC
-:103F8000089410F4599802C0599A000015D014D022
-:103F900086952A95B1F70895A89529E030E04899CB
-:103FA000FECF0AD009D008D08894489908942A9561
-:103FB00011F08795F7CF089598E09A95F1F7089555
-:103FC000EBDFEADF80930202E7CFE0E6F0E098E182
-:103FD00090838083089580E0F8DFEE27FF2709941F
-:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2
-:0C3FF000D3DF1150E9F7F4DF1F910895B2
+:103E30008150A9F7DD24D394A5E0FA2EF1E1EF2E0D
+:103E4000A3D0813421F481E0C9D083E020C0823442
+:103E500011F484E103C0853419F485E0BFD082C039
+:103E6000853581F491D0082F10E08ED090E0982F06
+:103E70008827802B912B880F991F909301028093A4
+:103E800000026FC0863529F484E0A8D080E06DD0B0
+:103E900069C0843609F03FC08BD0E0910002F091F8
+:103EA000010283E087BFE895C0E0D1E06DD089933F
+:103EB000809102028150809302028823B9F788D052
+:103EC00007B600FCFDCF4091000250910102A0E036
+:103ED000B1E02C9130E011968C91119790E0982FE1
+:103EE0008827822B932B1296FA010C01D7BEE895F6
+:103EF00011244E5F5F4FF1E0A038BF0751F7E0910A
+:103F00000002F0910102F7BEE89507B600FCFDCF74
+:103F1000E7BEE89527C08437B9F44AD059D0E0917C
+:103F20000002F09101023196F0930102E093000249
+:103F30003197E4918E2F19D08091020281508093A5
+:103F40000202882361F70EC0853739F441D08EE133
+:103F50000CD084E90AD086E09ACF813511F488E04C
+:103F60002CD036D080E101D06BCF2AE030E08095B4
+:103F7000089410F4599802C0599A000015D014D032
+:103F800086952A95B1F70895A89529E030E04899DB
+:103F9000FECF0AD009D008D08894489908942A9571
+:103FA00011F08795F7CF089598E09A95F1F7089565
+:103FB000EBDFEADF80930202E7CFE0E6F0E098E192
+:103FC00090838083089580E0F8DFEE27FF2709942F
+:103FD000DBDF803209F0F7DF84E1C7CF1F93182FB2
+:0C3FE000D3DF1150E9F7F4DF1F910895C2
 :0400000300003E00BB
 :00000001FF

+ 231 - 226
optiboot/bootloaders/optiboot/optiboot_lilypad_resonator.lst

@@ -3,34 +3,34 @@ optiboot_lilypad_resonator.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fc  00003e00  00003e00  00000054  2**1
+  0 .text         000001ec  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000240  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000268  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   00000277  00000000  00000000  000002f0  2**0
+  3 .debug_info   00000291  00000000  00000000  000002e0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000194  00000000  00000000  00000567  2**0
+  4 .debug_abbrev 000001ac  00000000  00000000  00000571  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003bb  00000000  00000000  000006fb  2**0
+  5 .debug_line   000003c3  00000000  00000000  0000071d  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  000000a0  00000000  00000000  00000ab8  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ae0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000013f  00000000  00000000  00000b58  2**0
+  7 .debug_str    0000014a  00000000  00000000  00000b80  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001a0  00000000  00000000  00000c97  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000cca  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000070  00000000  00000000  00000e37  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e6a  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
 
 00003e00 <main>:
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
@@ -46,12 +46,12 @@ int main(void) {
     3e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
     3e0a:	81 ff       	sbrs	r24, 1
-    3e0c:	e4 d0       	rcall	.+456    	; 0x3fd6 <appStart>
+    3e0c:	dc d0       	rcall	.+440    	; 0x3fc6 <appStart>
 
   // Set up watchdog to trigger after 500ms
   watchdogConfig(WATCHDOG_500MS);
     3e0e:	8d e0       	ldi	r24, 0x0D	; 13
-    3e10:	dc d0       	rcall	.+440    	; 0x3fca <watchdogConfig>
+    3e10:	d4 d0       	rcall	.+424    	; 0x3fba <watchdogConfig>
 
   /* Set LED pin as output */
   LED_DDR |= _BV(LED);
@@ -110,28 +110,28 @@ void watchdogReset() {
       getNch(1);
     3e34:	dd 24       	eor	r13, r13
     3e36:	d3 94       	inc	r13
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
+      __boot_page_write_short((uint16_t)(void*)address);
     3e38:	a5 e0       	ldi	r26, 0x05	; 5
-    3e3a:	ea 2e       	mov	r14, r26
+    3e3a:	fa 2e       	mov	r15, r26
       boot_spm_busy_wait();
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
     3e3c:	f1 e1       	ldi	r31, 0x11	; 17
-    3e3e:	ff 2e       	mov	r15, r31
+    3e3e:	ef 2e       	mov	r14, r31
 #endif
 
   /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e40:	ab d0       	rcall	.+342    	; 0x3f98 <getch>
+    3e40:	a3 d0       	rcall	.+326    	; 0x3f88 <getch>
 
     if(ch == STK_GET_PARAMETER) {
     3e42:	81 34       	cpi	r24, 0x41	; 65
@@ -139,10 +139,10 @@ void watchdogReset() {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
     3e46:	81 e0       	ldi	r24, 0x01	; 1
-    3e48:	d1 d0       	rcall	.+418    	; 0x3fec <verifySpace+0xc>
+    3e48:	c9 d0       	rcall	.+402    	; 0x3fdc <verifySpace+0xc>
       putch(0x03);
     3e4a:	83 e0       	ldi	r24, 0x03	; 3
-    3e4c:	24 c0       	rjmp	.+72     	; 0x3e96 <main+0x96>
+    3e4c:	20 c0       	rjmp	.+64     	; 0x3e8e <main+0x8e>
     }
     else if(ch == STK_SET_DEVICE) {
     3e4e:	82 34       	cpi	r24, 0x42	; 66
@@ -158,376 +158,381 @@ void watchdogReset() {
       // SET DEVICE EXT is ignored
       getNch(5);
     3e5a:	85 e0       	ldi	r24, 0x05	; 5
-    3e5c:	c7 d0       	rcall	.+398    	; 0x3fec <verifySpace+0xc>
-    3e5e:	8a c0       	rjmp	.+276    	; 0x3f74 <main+0x174>
+    3e5c:	bf d0       	rcall	.+382    	; 0x3fdc <verifySpace+0xc>
+    3e5e:	82 c0       	rjmp	.+260    	; 0x3f64 <main+0x164>
     }
     else if(ch == STK_LOAD_ADDRESS) {
     3e60:	85 35       	cpi	r24, 0x55	; 85
-    3e62:	a1 f4       	brne	.+40     	; 0x3e8c <main+0x8c>
+    3e62:	81 f4       	brne	.+32     	; 0x3e84 <main+0x84>
       // LOAD ADDRESS
-      address = getch();
-    3e64:	99 d0       	rcall	.+306    	; 0x3f98 <getch>
+      uint16_t newAddress;
+      newAddress = getch();
+    3e64:	91 d0       	rcall	.+290    	; 0x3f88 <getch>
+      newAddress = (newAddress & 0xff) | (getch() << 8);
     3e66:	08 2f       	mov	r16, r24
     3e68:	10 e0       	ldi	r17, 0x00	; 0
-    3e6a:	10 93 01 02 	sts	0x0201, r17
-    3e6e:	00 93 00 02 	sts	0x0200, r16
-      address = (address & 0xff) | (getch() << 8);
-    3e72:	92 d0       	rcall	.+292    	; 0x3f98 <getch>
-    3e74:	90 e0       	ldi	r25, 0x00	; 0
-    3e76:	98 2f       	mov	r25, r24
-    3e78:	88 27       	eor	r24, r24
-    3e7a:	80 2b       	or	r24, r16
-    3e7c:	91 2b       	or	r25, r17
-      address += address; // Convert from word address to byte address
-    3e7e:	88 0f       	add	r24, r24
-    3e80:	99 1f       	adc	r25, r25
-    3e82:	90 93 01 02 	sts	0x0201, r25
-    3e86:	80 93 00 02 	sts	0x0200, r24
-    3e8a:	73 c0       	rjmp	.+230    	; 0x3f72 <main+0x172>
+    3e6a:	8e d0       	rcall	.+284    	; 0x3f88 <getch>
+    3e6c:	90 e0       	ldi	r25, 0x00	; 0
+    3e6e:	98 2f       	mov	r25, r24
+    3e70:	88 27       	eor	r24, r24
+    3e72:	80 2b       	or	r24, r16
+    3e74:	91 2b       	or	r25, r17
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+    3e76:	88 0f       	add	r24, r24
+    3e78:	99 1f       	adc	r25, r25
+      address = newAddress;
+    3e7a:	90 93 01 02 	sts	0x0201, r25
+    3e7e:	80 93 00 02 	sts	0x0200, r24
+    3e82:	6f c0       	rjmp	.+222    	; 0x3f62 <main+0x162>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3e8c:	86 35       	cpi	r24, 0x56	; 86
-    3e8e:	29 f4       	brne	.+10     	; 0x3e9a <main+0x9a>
+    3e84:	86 35       	cpi	r24, 0x56	; 86
+    3e86:	29 f4       	brne	.+10     	; 0x3e92 <main+0x92>
       // UNIVERSAL command is ignored
       getNch(4);
-    3e90:	84 e0       	ldi	r24, 0x04	; 4
-    3e92:	ac d0       	rcall	.+344    	; 0x3fec <verifySpace+0xc>
+    3e88:	84 e0       	ldi	r24, 0x04	; 4
+    3e8a:	a8 d0       	rcall	.+336    	; 0x3fdc <verifySpace+0xc>
       putch(0x00);
-    3e94:	80 e0       	ldi	r24, 0x00	; 0
-    3e96:	71 d0       	rcall	.+226    	; 0x3f7a <putch>
-    3e98:	6d c0       	rjmp	.+218    	; 0x3f74 <main+0x174>
+    3e8c:	80 e0       	ldi	r24, 0x00	; 0
+    3e8e:	6d d0       	rcall	.+218    	; 0x3f6a <putch>
+    3e90:	69 c0       	rjmp	.+210    	; 0x3f64 <main+0x164>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3e9a:	84 36       	cpi	r24, 0x64	; 100
-    3e9c:	09 f0       	breq	.+2      	; 0x3ea0 <main+0xa0>
-    3e9e:	43 c0       	rjmp	.+134    	; 0x3f26 <main+0x126>
+    3e92:	84 36       	cpi	r24, 0x64	; 100
+    3e94:	09 f0       	breq	.+2      	; 0x3e98 <main+0x98>
+    3e96:	3f c0       	rjmp	.+126    	; 0x3f16 <main+0x116>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
 
       getLen();
-    3ea0:	8f d0       	rcall	.+286    	; 0x3fc0 <getLen>
+    3e98:	8b d0       	rcall	.+278    	; 0x3fb0 <getLen>
 
       // Immediately start page erase - this will 4.5ms
-      boot_page_erase((uint16_t)(void*)address);
-    3ea2:	e0 91 00 02 	lds	r30, 0x0200
-    3ea6:	f0 91 01 02 	lds	r31, 0x0201
-    3eaa:	83 e0       	ldi	r24, 0x03	; 3
-    3eac:	80 93 57 00 	sts	0x0057, r24
-    3eb0:	e8 95       	spm
-    3eb2:	c0 e0       	ldi	r28, 0x00	; 0
-    3eb4:	d1 e0       	ldi	r29, 0x01	; 1
-
+      __boot_page_erase_short((uint16_t)(void*)address);
+    3e9a:	e0 91 00 02 	lds	r30, 0x0200
+    3e9e:	f0 91 01 02 	lds	r31, 0x0201
+    3ea2:	83 e0       	ldi	r24, 0x03	; 3
+    3ea4:	87 bf       	out	0x37, r24	; 55
+    3ea6:	e8 95       	spm
+    3ea8:	c0 e0       	ldi	r28, 0x00	; 0
+    3eaa:	d1 e0       	ldi	r29, 0x01	; 1
+      
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3eb6:	70 d0       	rcall	.+224    	; 0x3f98 <getch>
-    3eb8:	89 93       	st	Y+, r24
+    3eac:	6d d0       	rcall	.+218    	; 0x3f88 <getch>
+    3eae:	89 93       	st	Y+, r24
       while (--length);
-    3eba:	80 91 02 02 	lds	r24, 0x0202
-    3ebe:	81 50       	subi	r24, 0x01	; 1
-    3ec0:	80 93 02 02 	sts	0x0202, r24
-    3ec4:	88 23       	and	r24, r24
-    3ec6:	b9 f7       	brne	.-18     	; 0x3eb6 <main+0xb6>
+    3eb0:	80 91 02 02 	lds	r24, 0x0202
+    3eb4:	81 50       	subi	r24, 0x01	; 1
+    3eb6:	80 93 02 02 	sts	0x0202, r24
+    3eba:	88 23       	and	r24, r24
+    3ebc:	b9 f7       	brne	.-18     	; 0x3eac <main+0xac>
 
       // Read command terminator, start reply
       verifySpace();
-    3ec8:	8b d0       	rcall	.+278    	; 0x3fe0 <verifySpace>
+    3ebe:	88 d0       	rcall	.+272    	; 0x3fd0 <verifySpace>
       
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3eca:	07 b6       	in	r0, 0x37	; 55
-    3ecc:	00 fc       	sbrc	r0, 0
-    3ece:	fd cf       	rjmp	.-6      	; 0x3eca <main+0xca>
+    3ec0:	07 b6       	in	r0, 0x37	; 55
+    3ec2:	00 fc       	sbrc	r0, 0
+    3ec4:	fd cf       	rjmp	.-6      	; 0x3ec0 <main+0xc0>
       }
 #endif
 
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ed0:	40 91 00 02 	lds	r20, 0x0200
-    3ed4:	50 91 01 02 	lds	r21, 0x0201
-    3ed8:	a0 e0       	ldi	r26, 0x00	; 0
-    3eda:	b1 e0       	ldi	r27, 0x01	; 1
+    3ec6:	40 91 00 02 	lds	r20, 0x0200
+    3eca:	50 91 01 02 	lds	r21, 0x0201
+    3ece:	a0 e0       	ldi	r26, 0x00	; 0
+    3ed0:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3edc:	2c 91       	ld	r18, X
-    3ede:	30 e0       	ldi	r19, 0x00	; 0
+    3ed2:	2c 91       	ld	r18, X
+    3ed4:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ee0:	11 96       	adiw	r26, 0x01	; 1
-    3ee2:	8c 91       	ld	r24, X
-    3ee4:	11 97       	sbiw	r26, 0x01	; 1
-    3ee6:	90 e0       	ldi	r25, 0x00	; 0
-    3ee8:	98 2f       	mov	r25, r24
-    3eea:	88 27       	eor	r24, r24
-    3eec:	82 2b       	or	r24, r18
-    3eee:	93 2b       	or	r25, r19
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+    3ed6:	11 96       	adiw	r26, 0x01	; 1
+    3ed8:	8c 91       	ld	r24, X
+    3eda:	11 97       	sbiw	r26, 0x01	; 1
+    3edc:	90 e0       	ldi	r25, 0x00	; 0
+    3ede:	98 2f       	mov	r25, r24
+    3ee0:	88 27       	eor	r24, r24
+    3ee2:	82 2b       	or	r24, r18
+    3ee4:	93 2b       	or	r25, r19
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
-    3ef0:	12 96       	adiw	r26, 0x02	; 2
+    3ee6:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3ef2:	fa 01       	movw	r30, r20
-    3ef4:	0c 01       	movw	r0, r24
-    3ef6:	d0 92 57 00 	sts	0x0057, r13
-    3efa:	e8 95       	spm
-    3efc:	11 24       	eor	r1, r1
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+    3ee8:	fa 01       	movw	r30, r20
+    3eea:	0c 01       	movw	r0, r24
+    3eec:	d7 be       	out	0x37, r13	; 55
+    3eee:	e8 95       	spm
+    3ef0:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3efe:	4e 5f       	subi	r20, 0xFE	; 254
-    3f00:	5f 4f       	sbci	r21, 0xFF	; 255
+    3ef2:	4e 5f       	subi	r20, 0xFE	; 254
+    3ef4:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f02:	f1 e0       	ldi	r31, 0x01	; 1
-    3f04:	a0 38       	cpi	r26, 0x80	; 128
-    3f06:	bf 07       	cpc	r27, r31
-    3f08:	49 f7       	brne	.-46     	; 0x3edc <main+0xdc>
+    3ef6:	f1 e0       	ldi	r31, 0x01	; 1
+    3ef8:	a0 38       	cpi	r26, 0x80	; 128
+    3efa:	bf 07       	cpc	r27, r31
+    3efc:	51 f7       	brne	.-44     	; 0x3ed2 <main+0xd2>
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
-    3f0a:	e0 91 00 02 	lds	r30, 0x0200
-    3f0e:	f0 91 01 02 	lds	r31, 0x0201
-    3f12:	e0 92 57 00 	sts	0x0057, r14
-    3f16:	e8 95       	spm
+      __boot_page_write_short((uint16_t)(void*)address);
+    3efe:	e0 91 00 02 	lds	r30, 0x0200
+    3f02:	f0 91 01 02 	lds	r31, 0x0201
+    3f06:	f7 be       	out	0x37, r15	; 55
+    3f08:	e8 95       	spm
       boot_spm_busy_wait();
-    3f18:	07 b6       	in	r0, 0x37	; 55
-    3f1a:	00 fc       	sbrc	r0, 0
-    3f1c:	fd cf       	rjmp	.-6      	; 0x3f18 <main+0x118>
+    3f0a:	07 b6       	in	r0, 0x37	; 55
+    3f0c:	00 fc       	sbrc	r0, 0
+    3f0e:	fd cf       	rjmp	.-6      	; 0x3f0a <main+0x10a>
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
-    3f1e:	f0 92 57 00 	sts	0x0057, r15
-    3f22:	e8 95       	spm
-    3f24:	27 c0       	rjmp	.+78     	; 0x3f74 <main+0x174>
+    3f10:	e7 be       	out	0x37, r14	; 55
+    3f12:	e8 95       	spm
+    3f14:	27 c0       	rjmp	.+78     	; 0x3f64 <main+0x164>
 #endif
 
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f26:	84 37       	cpi	r24, 0x74	; 116
-    3f28:	b9 f4       	brne	.+46     	; 0x3f58 <main+0x158>
+    3f16:	84 37       	cpi	r24, 0x74	; 116
+    3f18:	b9 f4       	brne	.+46     	; 0x3f48 <main+0x148>
       // READ PAGE - we only read flash
       getLen();
-    3f2a:	4a d0       	rcall	.+148    	; 0x3fc0 <getLen>
+    3f1a:	4a d0       	rcall	.+148    	; 0x3fb0 <getLen>
       verifySpace();
-    3f2c:	59 d0       	rcall	.+178    	; 0x3fe0 <verifySpace>
-        else ch = pgm_read_byte_near(address);
+    3f1c:	59 d0       	rcall	.+178    	; 0x3fd0 <verifySpace>
+        putch(result);
         address++;
-        putch(ch);
-      } while (--length);
+      }
+      while (--length);
 #else
       do putch(pgm_read_byte_near(address++));
-    3f2e:	e0 91 00 02 	lds	r30, 0x0200
-    3f32:	f0 91 01 02 	lds	r31, 0x0201
-    3f36:	31 96       	adiw	r30, 0x01	; 1
-    3f38:	f0 93 01 02 	sts	0x0201, r31
-    3f3c:	e0 93 00 02 	sts	0x0200, r30
-    3f40:	31 97       	sbiw	r30, 0x01	; 1
-    3f42:	e4 91       	lpm	r30, Z+
-    3f44:	8e 2f       	mov	r24, r30
-    3f46:	19 d0       	rcall	.+50     	; 0x3f7a <putch>
+    3f1e:	e0 91 00 02 	lds	r30, 0x0200
+    3f22:	f0 91 01 02 	lds	r31, 0x0201
+    3f26:	31 96       	adiw	r30, 0x01	; 1
+    3f28:	f0 93 01 02 	sts	0x0201, r31
+    3f2c:	e0 93 00 02 	sts	0x0200, r30
+    3f30:	31 97       	sbiw	r30, 0x01	; 1
+    3f32:	e4 91       	lpm	r30, Z+
+    3f34:	8e 2f       	mov	r24, r30
+    3f36:	19 d0       	rcall	.+50     	; 0x3f6a <putch>
       while (--length);
-    3f48:	80 91 02 02 	lds	r24, 0x0202
-    3f4c:	81 50       	subi	r24, 0x01	; 1
-    3f4e:	80 93 02 02 	sts	0x0202, r24
-    3f52:	88 23       	and	r24, r24
-    3f54:	61 f7       	brne	.-40     	; 0x3f2e <main+0x12e>
-    3f56:	0e c0       	rjmp	.+28     	; 0x3f74 <main+0x174>
+    3f38:	80 91 02 02 	lds	r24, 0x0202
+    3f3c:	81 50       	subi	r24, 0x01	; 1
+    3f3e:	80 93 02 02 	sts	0x0202, r24
+    3f42:	88 23       	and	r24, r24
+    3f44:	61 f7       	brne	.-40     	; 0x3f1e <main+0x11e>
+    3f46:	0e c0       	rjmp	.+28     	; 0x3f64 <main+0x164>
+#endif
 #endif
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f58:	85 37       	cpi	r24, 0x75	; 117
-    3f5a:	39 f4       	brne	.+14     	; 0x3f6a <main+0x16a>
+    3f48:	85 37       	cpi	r24, 0x75	; 117
+    3f4a:	39 f4       	brne	.+14     	; 0x3f5a <main+0x15a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f5c:	41 d0       	rcall	.+130    	; 0x3fe0 <verifySpace>
+    3f4c:	41 d0       	rcall	.+130    	; 0x3fd0 <verifySpace>
       putch(SIGNATURE_0);
-    3f5e:	8e e1       	ldi	r24, 0x1E	; 30
-    3f60:	0c d0       	rcall	.+24     	; 0x3f7a <putch>
+    3f4e:	8e e1       	ldi	r24, 0x1E	; 30
+    3f50:	0c d0       	rcall	.+24     	; 0x3f6a <putch>
       putch(SIGNATURE_1);
-    3f62:	84 e9       	ldi	r24, 0x94	; 148
-    3f64:	0a d0       	rcall	.+20     	; 0x3f7a <putch>
+    3f52:	84 e9       	ldi	r24, 0x94	; 148
+    3f54:	0a d0       	rcall	.+20     	; 0x3f6a <putch>
       putch(SIGNATURE_2);
-    3f66:	86 e0       	ldi	r24, 0x06	; 6
-    3f68:	96 cf       	rjmp	.-212    	; 0x3e96 <main+0x96>
+    3f56:	86 e0       	ldi	r24, 0x06	; 6
+    3f58:	9a cf       	rjmp	.-204    	; 0x3e8e <main+0x8e>
     }
     else if (ch == 'Q') {
-    3f6a:	81 35       	cpi	r24, 0x51	; 81
-    3f6c:	11 f4       	brne	.+4      	; 0x3f72 <main+0x172>
+    3f5a:	81 35       	cpi	r24, 0x51	; 81
+    3f5c:	11 f4       	brne	.+4      	; 0x3f62 <main+0x162>
       // Adaboot no-wait mod
       watchdogConfig(WATCHDOG_16MS);
-    3f6e:	88 e0       	ldi	r24, 0x08	; 8
-    3f70:	2c d0       	rcall	.+88     	; 0x3fca <watchdogConfig>
+    3f5e:	88 e0       	ldi	r24, 0x08	; 8
+    3f60:	2c d0       	rcall	.+88     	; 0x3fba <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f72:	36 d0       	rcall	.+108    	; 0x3fe0 <verifySpace>
+    3f62:	36 d0       	rcall	.+108    	; 0x3fd0 <verifySpace>
     }
     putch(STK_OK);
-    3f74:	80 e1       	ldi	r24, 0x10	; 16
-    3f76:	01 d0       	rcall	.+2      	; 0x3f7a <putch>
-    3f78:	63 cf       	rjmp	.-314    	; 0x3e40 <main+0x40>
+    3f64:	80 e1       	ldi	r24, 0x10	; 16
+    3f66:	01 d0       	rcall	.+2      	; 0x3f6a <putch>
+    3f68:	6b cf       	rjmp	.-298    	; 0x3e40 <main+0x40>
 
-00003f7a <putch>:
+00003f6a <putch>:
 void putch(char ch) {
 #ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
   UDR0 = ch;
 #else
   __asm__ __volatile__ (
-    3f7a:	2a e0       	ldi	r18, 0x0A	; 10
-    3f7c:	30 e0       	ldi	r19, 0x00	; 0
-    3f7e:	80 95       	com	r24
-    3f80:	08 94       	sec
-    3f82:	10 f4       	brcc	.+4      	; 0x3f88 <putch+0xe>
-    3f84:	59 98       	cbi	0x0b, 1	; 11
-    3f86:	02 c0       	rjmp	.+4      	; 0x3f8c <putch+0x12>
-    3f88:	59 9a       	sbi	0x0b, 1	; 11
-    3f8a:	00 00       	nop
-    3f8c:	15 d0       	rcall	.+42     	; 0x3fb8 <uartDelay>
-    3f8e:	14 d0       	rcall	.+40     	; 0x3fb8 <uartDelay>
-    3f90:	86 95       	lsr	r24
-    3f92:	2a 95       	dec	r18
-    3f94:	b1 f7       	brne	.-20     	; 0x3f82 <putch+0x8>
+    3f6a:	2a e0       	ldi	r18, 0x0A	; 10
+    3f6c:	30 e0       	ldi	r19, 0x00	; 0
+    3f6e:	80 95       	com	r24
+    3f70:	08 94       	sec
+    3f72:	10 f4       	brcc	.+4      	; 0x3f78 <putch+0xe>
+    3f74:	59 98       	cbi	0x0b, 1	; 11
+    3f76:	02 c0       	rjmp	.+4      	; 0x3f7c <putch+0x12>
+    3f78:	59 9a       	sbi	0x0b, 1	; 11
+    3f7a:	00 00       	nop
+    3f7c:	15 d0       	rcall	.+42     	; 0x3fa8 <uartDelay>
+    3f7e:	14 d0       	rcall	.+40     	; 0x3fa8 <uartDelay>
+    3f80:	86 95       	lsr	r24
+    3f82:	2a 95       	dec	r18
+    3f84:	b1 f7       	brne	.-20     	; 0x3f72 <putch+0x8>
       [uartBit] "I" (UART_TX_BIT)
     :
       "r25"
   );
 #endif
 }
-    3f96:	08 95       	ret
+    3f86:	08 95       	ret
 
-00003f98 <getch>:
+00003f88 <getch>:
   return getch();
 }
 
 // Watchdog functions. These are only safe with interrupts turned off.
 void watchdogReset() {
   __asm__ __volatile__ (
-    3f98:	a8 95       	wdr
+    3f88:	a8 95       	wdr
 #ifdef LED_DATA_FLASH
   LED_PIN |= _BV(LED);
 #endif
 
   return ch;
 }
-    3f9a:	29 e0       	ldi	r18, 0x09	; 9
-    3f9c:	30 e0       	ldi	r19, 0x00	; 0
-    3f9e:	48 99       	sbic	0x09, 0	; 9
-    3fa0:	fe cf       	rjmp	.-4      	; 0x3f9e <getch+0x6>
-    3fa2:	0a d0       	rcall	.+20     	; 0x3fb8 <uartDelay>
-    3fa4:	09 d0       	rcall	.+18     	; 0x3fb8 <uartDelay>
-    3fa6:	08 d0       	rcall	.+16     	; 0x3fb8 <uartDelay>
-    3fa8:	88 94       	clc
-    3faa:	48 99       	sbic	0x09, 0	; 9
-    3fac:	08 94       	sec
-    3fae:	2a 95       	dec	r18
-    3fb0:	11 f0       	breq	.+4      	; 0x3fb6 <getch+0x1e>
-    3fb2:	87 95       	ror	r24
-    3fb4:	f7 cf       	rjmp	.-18     	; 0x3fa4 <getch+0xc>
-    3fb6:	08 95       	ret
-
-00003fb8 <uartDelay>:
+    3f8a:	29 e0       	ldi	r18, 0x09	; 9
+    3f8c:	30 e0       	ldi	r19, 0x00	; 0
+    3f8e:	48 99       	sbic	0x09, 0	; 9
+    3f90:	fe cf       	rjmp	.-4      	; 0x3f8e <getch+0x6>
+    3f92:	0a d0       	rcall	.+20     	; 0x3fa8 <uartDelay>
+    3f94:	09 d0       	rcall	.+18     	; 0x3fa8 <uartDelay>
+    3f96:	08 d0       	rcall	.+16     	; 0x3fa8 <uartDelay>
+    3f98:	88 94       	clc
+    3f9a:	48 99       	sbic	0x09, 0	; 9
+    3f9c:	08 94       	sec
+    3f9e:	2a 95       	dec	r18
+    3fa0:	11 f0       	breq	.+4      	; 0x3fa6 <getch+0x1e>
+    3fa2:	87 95       	ror	r24
+    3fa4:	f7 cf       	rjmp	.-18     	; 0x3f94 <getch+0xc>
+    3fa6:	08 95       	ret
+
+00003fa8 <uartDelay>:
 #if UART_B_VALUE > 255
 #error Baud rate too slow for soft UART
 #endif
 
 void uartDelay() {
   __asm__ __volatile__ (
-    3fb8:	98 e0       	ldi	r25, 0x08	; 8
-    3fba:	9a 95       	dec	r25
-    3fbc:	f1 f7       	brne	.-4      	; 0x3fba <uartDelay+0x2>
-    3fbe:	08 95       	ret
+    3fa8:	98 e0       	ldi	r25, 0x08	; 8
+    3faa:	9a 95       	dec	r25
+    3fac:	f1 f7       	brne	.-4      	; 0x3faa <uartDelay+0x2>
+    3fae:	08 95       	ret
 
-00003fc0 <getLen>:
+00003fb0 <getLen>:
   } while (--count);
 }
 #endif
 
 uint8_t getLen() {
   getch();
-    3fc0:	eb df       	rcall	.-42     	; 0x3f98 <getch>
+    3fb0:	eb df       	rcall	.-42     	; 0x3f88 <getch>
   length = getch();
-    3fc2:	ea df       	rcall	.-44     	; 0x3f98 <getch>
-    3fc4:	80 93 02 02 	sts	0x0202, r24
+    3fb2:	ea df       	rcall	.-44     	; 0x3f88 <getch>
+    3fb4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fc8:	e7 cf       	rjmp	.-50     	; 0x3f98 <getch>
+    3fb8:	e7 cf       	rjmp	.-50     	; 0x3f88 <getch>
 
-00003fca <watchdogConfig>:
+00003fba <watchdogConfig>:
     "wdr\n"
   );
 }
 
 void watchdogConfig(uint8_t x) {
   WDTCSR = _BV(WDCE) | _BV(WDE);
-    3fca:	e0 e6       	ldi	r30, 0x60	; 96
-    3fcc:	f0 e0       	ldi	r31, 0x00	; 0
-    3fce:	98 e1       	ldi	r25, 0x18	; 24
-    3fd0:	90 83       	st	Z, r25
+    3fba:	e0 e6       	ldi	r30, 0x60	; 96
+    3fbc:	f0 e0       	ldi	r31, 0x00	; 0
+    3fbe:	98 e1       	ldi	r25, 0x18	; 24
+    3fc0:	90 83       	st	Z, r25
   WDTCSR = x;
-    3fd2:	80 83       	st	Z, r24
+    3fc2:	80 83       	st	Z, r24
 }
-    3fd4:	08 95       	ret
+    3fc4:	08 95       	ret
 
-00003fd6 <appStart>:
+00003fc6 <appStart>:
 
 void appStart() {
   watchdogConfig(WATCHDOG_OFF);
-    3fd6:	80 e0       	ldi	r24, 0x00	; 0
-    3fd8:	f8 df       	rcall	.-16     	; 0x3fca <watchdogConfig>
+    3fc6:	80 e0       	ldi	r24, 0x00	; 0
+    3fc8:	f8 df       	rcall	.-16     	; 0x3fba <watchdogConfig>
   __asm__ __volatile__ (
-    3fda:	ee 27       	eor	r30, r30
-    3fdc:	ff 27       	eor	r31, r31
-    3fde:	09 94       	ijmp
+    3fca:	ee 27       	eor	r30, r30
+    3fcc:	ff 27       	eor	r31, r31
+    3fce:	09 94       	ijmp
 
-00003fe0 <verifySpace>:
+00003fd0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fe0:	db df       	rcall	.-74     	; 0x3f98 <getch>
-    3fe2:	80 32       	cpi	r24, 0x20	; 32
-    3fe4:	09 f0       	breq	.+2      	; 0x3fe8 <verifySpace+0x8>
-    3fe6:	f7 df       	rcall	.-18     	; 0x3fd6 <appStart>
+    3fd0:	db df       	rcall	.-74     	; 0x3f88 <getch>
+    3fd2:	80 32       	cpi	r24, 0x20	; 32
+    3fd4:	09 f0       	breq	.+2      	; 0x3fd8 <verifySpace+0x8>
+    3fd6:	f7 df       	rcall	.-18     	; 0x3fc6 <appStart>
   putch(STK_INSYNC);
-    3fe8:	84 e1       	ldi	r24, 0x14	; 20
+    3fd8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fea:	c7 cf       	rjmp	.-114    	; 0x3f7a <putch>
+    3fda:	c7 cf       	rjmp	.-114    	; 0x3f6a <putch>
     ::[count] "M" (UART_B_VALUE)
   );
 }
 #endif
 
 void getNch(uint8_t count) {
-    3fec:	1f 93       	push	r17
-    3fee:	18 2f       	mov	r17, r24
+    3fdc:	1f 93       	push	r17
+    3fde:	18 2f       	mov	r17, r24
 
-00003ff0 <getNch>:
+00003fe0 <getNch>:
   do getch(); while (--count);
-    3ff0:	d3 df       	rcall	.-90     	; 0x3f98 <getch>
-    3ff2:	11 50       	subi	r17, 0x01	; 1
-    3ff4:	e9 f7       	brne	.-6      	; 0x3ff0 <getNch>
+    3fe0:	d3 df       	rcall	.-90     	; 0x3f88 <getch>
+    3fe2:	11 50       	subi	r17, 0x01	; 1
+    3fe4:	e9 f7       	brne	.-6      	; 0x3fe0 <getNch>
   verifySpace();
-    3ff6:	f4 df       	rcall	.-24     	; 0x3fe0 <verifySpace>
+    3fe6:	f4 df       	rcall	.-24     	; 0x3fd0 <verifySpace>
 }
-    3ff8:	1f 91       	pop	r17
-    3ffa:	08 95       	ret
+    3fe8:	1f 91       	pop	r17
+    3fea:	08 95       	ret

+ 26 - 27
optiboot/bootloaders/optiboot/optiboot_pro_16MHz.hex

@@ -1,33 +1,32 @@
 :103E000085E08093810082E08093C00088E1809308
 :103E1000C10086E08093C20080E18093C40084B733
-:103E200014BE81FFD0D08DE0C8D0259A86E020E373
+:103E200014BE81FFC8D08DE0C0D0259A86E020E383
 :103E30003CEF91E0309385002093840096BBB09BCB
 :103E4000FECF1D9AA8958150A9F7DD24D394A5E053
-:103E5000EA2EF1E1FF2EA4D0813421F481E0BED01E
-:103E600083E024C0823411F484E103C0853419F462
-:103E700085E0B4D08AC08535A1F492D0082F10E037
-:103E800010930102009300028BD090E0982F8827B6
-:103E9000802B912B880F991F909301028093000231
-:103EA00073C0863529F484E099D080E071D06DC06C
-:103EB000843609F043C07CD0E0910002F091010209
-:103EC00083E080935700E895C0E0D1E069D0899302
-:103ED000809102028150809302028823B9F778D042
-:103EE00007B600FCFDCF4091000250910102A0E016
-:103EF000B1E02C9130E011968C91119790E0982FC1
-:103F00008827822B932B1296FA010C01D09257002E
-:103F1000E89511244E5F5F4FF1E0A038BF0749F7E5
-:103F2000E0910002F0910102E0925700E89507B697
-:103F300000FCFDCFF0925700E89527C08437B9F414
-:103F400037D046D0E0910002F09101023196F09313
-:103F50000102E09300023197E4918E2F19D08091F5
-:103F60000202815080930202882361F70EC08537D8
-:103F700039F42ED08EE10CD084E90AD086E096CFB9
-:103F8000813511F488E019D023D080E101D063CFCE
-:103F9000982F8091C00085FFFCCF9093C6000895B4
-:103FA000A8958091C00087FFFCCF8091C60008953E
-:103FB000F7DFF6DF80930202F3CFE0E6F0E098E16E
-:103FC00090838083089580E0F8DFEE27FF2709942F
-:103FD000E7DF803209F0F7DF84E1DACF1F93182F93
-:0C3FE000DFDF1150E9F7F4DF1F910895B6
+:103E5000FA2EF1E1EF2E9CD0813421F481E0B6D02E
+:103E600083E020C0823411F484E103C0853419F466
+:103E700085E0ACD082C0853581F48AD0082F10E06F
+:103E800087D090E0982F8827802B912B880F991F3F
+:103E900090930102809300026FC0863529F484E07C
+:103EA00095D080E06DD069C0843609F03FC078D0ED
+:103EB000E0910002F091010283E087BFE895C0E045
+:103EC000D1E066D0899380910202815080930202F2
+:103ED0008823B9F775D007B600FCFDCF40910002EA
+:103EE00050910102A0E0B1E02C9130E011968C914C
+:103EF000119790E0982F8827822B932B1296FA0126
+:103F00000C01D7BEE89511244E5F5F4FF1E0A03859
+:103F1000BF0751F7E0910002F0910102F7BEE8956A
+:103F200007B600FCFDCFE7BEE89527C08437B9F49B
+:103F300037D046D0E0910002F09101023196F09323
+:103F40000102E09300023197E4918E2F19D0809105
+:103F50000202815080930202882361F70EC08537E8
+:103F600039F42ED08EE10CD084E90AD086E09ACFC5
+:103F7000813511F488E019D023D080E101D06BCFD6
+:103F8000982F8091C00085FFFCCF9093C6000895C4
+:103F9000A8958091C00087FFFCCF8091C60008954E
+:103FA000F7DFF6DF80930202F3CFE0E6F0E098E17E
+:103FB00090838083089580E0F8DFEE27FF2709943F
+:103FC000E7DF803209F0F7DF84E1DACF1F93182FA3
+:0C3FD000DFDF1150E9F7F4DF1F910895C6
 :0400000300003E00BB
 :00000001FF

+ 206 - 201
optiboot/bootloaders/optiboot/optiboot_pro_16MHz.lst

@@ -3,34 +3,34 @@ optiboot_pro_16MHz.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001ec  00003e00  00003e00  00000054  2**1
+  0 .text         000001dc  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  00000240  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000230  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 0000006a  00000000  00000000  00000268  2**0
+  2 .debug_pubnames 0000006a  00000000  00000000  00000258  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   00000269  00000000  00000000  000002d2  2**0
+  3 .debug_info   00000283  00000000  00000000  000002c2  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000196  00000000  00000000  0000053b  2**0
+  4 .debug_abbrev 000001ae  00000000  00000000  00000545  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003d3  00000000  00000000  000006d1  2**0
+  5 .debug_line   000003db  00000000  00000000  000006f3  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000aa4  2**2
+  6 .debug_frame  00000090  00000000  00000000  00000ad0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    00000135  00000000  00000000  00000b34  2**0
+  7 .debug_str    00000140  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d1  00000000  00000000  00000c69  2**0
+  8 .debug_loc    000001d1  00000000  00000000  00000ca0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000e3a  2**0
+  9 .debug_ranges 00000068  00000000  00000000  00000e71  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
 
 00003e00 <main>:
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
@@ -61,12 +61,12 @@ int main(void) {
     3e20:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
     3e22:	81 ff       	sbrs	r24, 1
-    3e24:	d0 d0       	rcall	.+416    	; 0x3fc6 <appStart>
+    3e24:	c8 d0       	rcall	.+400    	; 0x3fb6 <appStart>
 
   // Set up watchdog to trigger after 500ms
   watchdogConfig(WATCHDOG_500MS);
     3e26:	8d e0       	ldi	r24, 0x0D	; 13
-    3e28:	c8 d0       	rcall	.+400    	; 0x3fba <watchdogConfig>
+    3e28:	c0 d0       	rcall	.+384    	; 0x3faa <watchdogConfig>
 
   /* Set LED pin as output */
   LED_DDR |= _BV(LED);
@@ -120,28 +120,28 @@ void watchdogReset() {
       getNch(1);
     3e4a:	dd 24       	eor	r13, r13
     3e4c:	d3 94       	inc	r13
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
+      __boot_page_write_short((uint16_t)(void*)address);
     3e4e:	a5 e0       	ldi	r26, 0x05	; 5
-    3e50:	ea 2e       	mov	r14, r26
+    3e50:	fa 2e       	mov	r15, r26
       boot_spm_busy_wait();
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
     3e52:	f1 e1       	ldi	r31, 0x11	; 17
-    3e54:	ff 2e       	mov	r15, r31
+    3e54:	ef 2e       	mov	r14, r31
 #endif
 
   /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e56:	a4 d0       	rcall	.+328    	; 0x3fa0 <getch>
+    3e56:	9c d0       	rcall	.+312    	; 0x3f90 <getch>
 
     if(ch == STK_GET_PARAMETER) {
     3e58:	81 34       	cpi	r24, 0x41	; 65
@@ -149,10 +149,10 @@ void watchdogReset() {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
     3e5c:	81 e0       	ldi	r24, 0x01	; 1
-    3e5e:	be d0       	rcall	.+380    	; 0x3fdc <verifySpace+0xc>
+    3e5e:	b6 d0       	rcall	.+364    	; 0x3fcc <verifySpace+0xc>
       putch(0x03);
     3e60:	83 e0       	ldi	r24, 0x03	; 3
-    3e62:	24 c0       	rjmp	.+72     	; 0x3eac <main+0xac>
+    3e62:	20 c0       	rjmp	.+64     	; 0x3ea4 <main+0xa4>
     }
     else if(ch == STK_SET_DEVICE) {
     3e64:	82 34       	cpi	r24, 0x42	; 66
@@ -168,353 +168,358 @@ void watchdogReset() {
       // SET DEVICE EXT is ignored
       getNch(5);
     3e70:	85 e0       	ldi	r24, 0x05	; 5
-    3e72:	b4 d0       	rcall	.+360    	; 0x3fdc <verifySpace+0xc>
-    3e74:	8a c0       	rjmp	.+276    	; 0x3f8a <main+0x18a>
+    3e72:	ac d0       	rcall	.+344    	; 0x3fcc <verifySpace+0xc>
+    3e74:	82 c0       	rjmp	.+260    	; 0x3f7a <main+0x17a>
     }
     else if(ch == STK_LOAD_ADDRESS) {
     3e76:	85 35       	cpi	r24, 0x55	; 85
-    3e78:	a1 f4       	brne	.+40     	; 0x3ea2 <main+0xa2>
+    3e78:	81 f4       	brne	.+32     	; 0x3e9a <main+0x9a>
       // LOAD ADDRESS
-      address = getch();
-    3e7a:	92 d0       	rcall	.+292    	; 0x3fa0 <getch>
+      uint16_t newAddress;
+      newAddress = getch();
+    3e7a:	8a d0       	rcall	.+276    	; 0x3f90 <getch>
+      newAddress = (newAddress & 0xff) | (getch() << 8);
     3e7c:	08 2f       	mov	r16, r24
     3e7e:	10 e0       	ldi	r17, 0x00	; 0
-    3e80:	10 93 01 02 	sts	0x0201, r17
-    3e84:	00 93 00 02 	sts	0x0200, r16
-      address = (address & 0xff) | (getch() << 8);
-    3e88:	8b d0       	rcall	.+278    	; 0x3fa0 <getch>
-    3e8a:	90 e0       	ldi	r25, 0x00	; 0
-    3e8c:	98 2f       	mov	r25, r24
-    3e8e:	88 27       	eor	r24, r24
-    3e90:	80 2b       	or	r24, r16
-    3e92:	91 2b       	or	r25, r17
-      address += address; // Convert from word address to byte address
-    3e94:	88 0f       	add	r24, r24
-    3e96:	99 1f       	adc	r25, r25
-    3e98:	90 93 01 02 	sts	0x0201, r25
-    3e9c:	80 93 00 02 	sts	0x0200, r24
-    3ea0:	73 c0       	rjmp	.+230    	; 0x3f88 <main+0x188>
+    3e80:	87 d0       	rcall	.+270    	; 0x3f90 <getch>
+    3e82:	90 e0       	ldi	r25, 0x00	; 0
+    3e84:	98 2f       	mov	r25, r24
+    3e86:	88 27       	eor	r24, r24
+    3e88:	80 2b       	or	r24, r16
+    3e8a:	91 2b       	or	r25, r17
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+    3e8c:	88 0f       	add	r24, r24
+    3e8e:	99 1f       	adc	r25, r25
+      address = newAddress;
+    3e90:	90 93 01 02 	sts	0x0201, r25
+    3e94:	80 93 00 02 	sts	0x0200, r24
+    3e98:	6f c0       	rjmp	.+222    	; 0x3f78 <main+0x178>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3ea2:	86 35       	cpi	r24, 0x56	; 86
-    3ea4:	29 f4       	brne	.+10     	; 0x3eb0 <main+0xb0>
+    3e9a:	86 35       	cpi	r24, 0x56	; 86
+    3e9c:	29 f4       	brne	.+10     	; 0x3ea8 <main+0xa8>
       // UNIVERSAL command is ignored
       getNch(4);
-    3ea6:	84 e0       	ldi	r24, 0x04	; 4
-    3ea8:	99 d0       	rcall	.+306    	; 0x3fdc <verifySpace+0xc>
+    3e9e:	84 e0       	ldi	r24, 0x04	; 4
+    3ea0:	95 d0       	rcall	.+298    	; 0x3fcc <verifySpace+0xc>
       putch(0x00);
-    3eaa:	80 e0       	ldi	r24, 0x00	; 0
-    3eac:	71 d0       	rcall	.+226    	; 0x3f90 <putch>
-    3eae:	6d c0       	rjmp	.+218    	; 0x3f8a <main+0x18a>
+    3ea2:	80 e0       	ldi	r24, 0x00	; 0
+    3ea4:	6d d0       	rcall	.+218    	; 0x3f80 <putch>
+    3ea6:	69 c0       	rjmp	.+210    	; 0x3f7a <main+0x17a>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3eb0:	84 36       	cpi	r24, 0x64	; 100
-    3eb2:	09 f0       	breq	.+2      	; 0x3eb6 <main+0xb6>
-    3eb4:	43 c0       	rjmp	.+134    	; 0x3f3c <main+0x13c>
+    3ea8:	84 36       	cpi	r24, 0x64	; 100
+    3eaa:	09 f0       	breq	.+2      	; 0x3eae <main+0xae>
+    3eac:	3f c0       	rjmp	.+126    	; 0x3f2c <main+0x12c>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
 
       getLen();
-    3eb6:	7c d0       	rcall	.+248    	; 0x3fb0 <getLen>
+    3eae:	78 d0       	rcall	.+240    	; 0x3fa0 <getLen>
 
       // Immediately start page erase - this will 4.5ms
-      boot_page_erase((uint16_t)(void*)address);
-    3eb8:	e0 91 00 02 	lds	r30, 0x0200
-    3ebc:	f0 91 01 02 	lds	r31, 0x0201
-    3ec0:	83 e0       	ldi	r24, 0x03	; 3
-    3ec2:	80 93 57 00 	sts	0x0057, r24
-    3ec6:	e8 95       	spm
-    3ec8:	c0 e0       	ldi	r28, 0x00	; 0
-    3eca:	d1 e0       	ldi	r29, 0x01	; 1
-
+      __boot_page_erase_short((uint16_t)(void*)address);
+    3eb0:	e0 91 00 02 	lds	r30, 0x0200
+    3eb4:	f0 91 01 02 	lds	r31, 0x0201
+    3eb8:	83 e0       	ldi	r24, 0x03	; 3
+    3eba:	87 bf       	out	0x37, r24	; 55
+    3ebc:	e8 95       	spm
+    3ebe:	c0 e0       	ldi	r28, 0x00	; 0
+    3ec0:	d1 e0       	ldi	r29, 0x01	; 1
+      
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3ecc:	69 d0       	rcall	.+210    	; 0x3fa0 <getch>
-    3ece:	89 93       	st	Y+, r24
+    3ec2:	66 d0       	rcall	.+204    	; 0x3f90 <getch>
+    3ec4:	89 93       	st	Y+, r24
       while (--length);
-    3ed0:	80 91 02 02 	lds	r24, 0x0202
-    3ed4:	81 50       	subi	r24, 0x01	; 1
-    3ed6:	80 93 02 02 	sts	0x0202, r24
-    3eda:	88 23       	and	r24, r24
-    3edc:	b9 f7       	brne	.-18     	; 0x3ecc <main+0xcc>
+    3ec6:	80 91 02 02 	lds	r24, 0x0202
+    3eca:	81 50       	subi	r24, 0x01	; 1
+    3ecc:	80 93 02 02 	sts	0x0202, r24
+    3ed0:	88 23       	and	r24, r24
+    3ed2:	b9 f7       	brne	.-18     	; 0x3ec2 <main+0xc2>
 
       // Read command terminator, start reply
       verifySpace();
-    3ede:	78 d0       	rcall	.+240    	; 0x3fd0 <verifySpace>
+    3ed4:	75 d0       	rcall	.+234    	; 0x3fc0 <verifySpace>
       
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3ee0:	07 b6       	in	r0, 0x37	; 55
-    3ee2:	00 fc       	sbrc	r0, 0
-    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+    3ed6:	07 b6       	in	r0, 0x37	; 55
+    3ed8:	00 fc       	sbrc	r0, 0
+    3eda:	fd cf       	rjmp	.-6      	; 0x3ed6 <main+0xd6>
       }
 #endif
 
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ee6:	40 91 00 02 	lds	r20, 0x0200
-    3eea:	50 91 01 02 	lds	r21, 0x0201
-    3eee:	a0 e0       	ldi	r26, 0x00	; 0
-    3ef0:	b1 e0       	ldi	r27, 0x01	; 1
+    3edc:	40 91 00 02 	lds	r20, 0x0200
+    3ee0:	50 91 01 02 	lds	r21, 0x0201
+    3ee4:	a0 e0       	ldi	r26, 0x00	; 0
+    3ee6:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3ef2:	2c 91       	ld	r18, X
-    3ef4:	30 e0       	ldi	r19, 0x00	; 0
+    3ee8:	2c 91       	ld	r18, X
+    3eea:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ef6:	11 96       	adiw	r26, 0x01	; 1
-    3ef8:	8c 91       	ld	r24, X
-    3efa:	11 97       	sbiw	r26, 0x01	; 1
-    3efc:	90 e0       	ldi	r25, 0x00	; 0
-    3efe:	98 2f       	mov	r25, r24
-    3f00:	88 27       	eor	r24, r24
-    3f02:	82 2b       	or	r24, r18
-    3f04:	93 2b       	or	r25, r19
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+    3eec:	11 96       	adiw	r26, 0x01	; 1
+    3eee:	8c 91       	ld	r24, X
+    3ef0:	11 97       	sbiw	r26, 0x01	; 1
+    3ef2:	90 e0       	ldi	r25, 0x00	; 0
+    3ef4:	98 2f       	mov	r25, r24
+    3ef6:	88 27       	eor	r24, r24
+    3ef8:	82 2b       	or	r24, r18
+    3efa:	93 2b       	or	r25, r19
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
-    3f06:	12 96       	adiw	r26, 0x02	; 2
+    3efc:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3f08:	fa 01       	movw	r30, r20
-    3f0a:	0c 01       	movw	r0, r24
-    3f0c:	d0 92 57 00 	sts	0x0057, r13
-    3f10:	e8 95       	spm
-    3f12:	11 24       	eor	r1, r1
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+    3efe:	fa 01       	movw	r30, r20
+    3f00:	0c 01       	movw	r0, r24
+    3f02:	d7 be       	out	0x37, r13	; 55
+    3f04:	e8 95       	spm
+    3f06:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3f14:	4e 5f       	subi	r20, 0xFE	; 254
-    3f16:	5f 4f       	sbci	r21, 0xFF	; 255
+    3f08:	4e 5f       	subi	r20, 0xFE	; 254
+    3f0a:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f18:	f1 e0       	ldi	r31, 0x01	; 1
-    3f1a:	a0 38       	cpi	r26, 0x80	; 128
-    3f1c:	bf 07       	cpc	r27, r31
-    3f1e:	49 f7       	brne	.-46     	; 0x3ef2 <main+0xf2>
+    3f0c:	f1 e0       	ldi	r31, 0x01	; 1
+    3f0e:	a0 38       	cpi	r26, 0x80	; 128
+    3f10:	bf 07       	cpc	r27, r31
+    3f12:	51 f7       	brne	.-44     	; 0x3ee8 <main+0xe8>
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
-    3f20:	e0 91 00 02 	lds	r30, 0x0200
-    3f24:	f0 91 01 02 	lds	r31, 0x0201
-    3f28:	e0 92 57 00 	sts	0x0057, r14
-    3f2c:	e8 95       	spm
+      __boot_page_write_short((uint16_t)(void*)address);
+    3f14:	e0 91 00 02 	lds	r30, 0x0200
+    3f18:	f0 91 01 02 	lds	r31, 0x0201
+    3f1c:	f7 be       	out	0x37, r15	; 55
+    3f1e:	e8 95       	spm
       boot_spm_busy_wait();
-    3f2e:	07 b6       	in	r0, 0x37	; 55
-    3f30:	00 fc       	sbrc	r0, 0
-    3f32:	fd cf       	rjmp	.-6      	; 0x3f2e <main+0x12e>
+    3f20:	07 b6       	in	r0, 0x37	; 55
+    3f22:	00 fc       	sbrc	r0, 0
+    3f24:	fd cf       	rjmp	.-6      	; 0x3f20 <main+0x120>
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
-    3f34:	f0 92 57 00 	sts	0x0057, r15
-    3f38:	e8 95       	spm
-    3f3a:	27 c0       	rjmp	.+78     	; 0x3f8a <main+0x18a>
+    3f26:	e7 be       	out	0x37, r14	; 55
+    3f28:	e8 95       	spm
+    3f2a:	27 c0       	rjmp	.+78     	; 0x3f7a <main+0x17a>
 #endif
 
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f3c:	84 37       	cpi	r24, 0x74	; 116
-    3f3e:	b9 f4       	brne	.+46     	; 0x3f6e <main+0x16e>
+    3f2c:	84 37       	cpi	r24, 0x74	; 116
+    3f2e:	b9 f4       	brne	.+46     	; 0x3f5e <main+0x15e>
       // READ PAGE - we only read flash
       getLen();
-    3f40:	37 d0       	rcall	.+110    	; 0x3fb0 <getLen>
+    3f30:	37 d0       	rcall	.+110    	; 0x3fa0 <getLen>
       verifySpace();
-    3f42:	46 d0       	rcall	.+140    	; 0x3fd0 <verifySpace>
-        else ch = pgm_read_byte_near(address);
+    3f32:	46 d0       	rcall	.+140    	; 0x3fc0 <verifySpace>
+        putch(result);
         address++;
-        putch(ch);
-      } while (--length);
+      }
+      while (--length);
 #else
       do putch(pgm_read_byte_near(address++));
-    3f44:	e0 91 00 02 	lds	r30, 0x0200
-    3f48:	f0 91 01 02 	lds	r31, 0x0201
-    3f4c:	31 96       	adiw	r30, 0x01	; 1
-    3f4e:	f0 93 01 02 	sts	0x0201, r31
-    3f52:	e0 93 00 02 	sts	0x0200, r30
-    3f56:	31 97       	sbiw	r30, 0x01	; 1
-    3f58:	e4 91       	lpm	r30, Z+
-    3f5a:	8e 2f       	mov	r24, r30
-    3f5c:	19 d0       	rcall	.+50     	; 0x3f90 <putch>
+    3f34:	e0 91 00 02 	lds	r30, 0x0200
+    3f38:	f0 91 01 02 	lds	r31, 0x0201
+    3f3c:	31 96       	adiw	r30, 0x01	; 1
+    3f3e:	f0 93 01 02 	sts	0x0201, r31
+    3f42:	e0 93 00 02 	sts	0x0200, r30
+    3f46:	31 97       	sbiw	r30, 0x01	; 1
+    3f48:	e4 91       	lpm	r30, Z+
+    3f4a:	8e 2f       	mov	r24, r30
+    3f4c:	19 d0       	rcall	.+50     	; 0x3f80 <putch>
       while (--length);
-    3f5e:	80 91 02 02 	lds	r24, 0x0202
-    3f62:	81 50       	subi	r24, 0x01	; 1
-    3f64:	80 93 02 02 	sts	0x0202, r24
-    3f68:	88 23       	and	r24, r24
-    3f6a:	61 f7       	brne	.-40     	; 0x3f44 <main+0x144>
-    3f6c:	0e c0       	rjmp	.+28     	; 0x3f8a <main+0x18a>
+    3f4e:	80 91 02 02 	lds	r24, 0x0202
+    3f52:	81 50       	subi	r24, 0x01	; 1
+    3f54:	80 93 02 02 	sts	0x0202, r24
+    3f58:	88 23       	and	r24, r24
+    3f5a:	61 f7       	brne	.-40     	; 0x3f34 <main+0x134>
+    3f5c:	0e c0       	rjmp	.+28     	; 0x3f7a <main+0x17a>
+#endif
 #endif
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f6e:	85 37       	cpi	r24, 0x75	; 117
-    3f70:	39 f4       	brne	.+14     	; 0x3f80 <main+0x180>
+    3f5e:	85 37       	cpi	r24, 0x75	; 117
+    3f60:	39 f4       	brne	.+14     	; 0x3f70 <main+0x170>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f72:	2e d0       	rcall	.+92     	; 0x3fd0 <verifySpace>
+    3f62:	2e d0       	rcall	.+92     	; 0x3fc0 <verifySpace>
       putch(SIGNATURE_0);
-    3f74:	8e e1       	ldi	r24, 0x1E	; 30
-    3f76:	0c d0       	rcall	.+24     	; 0x3f90 <putch>
+    3f64:	8e e1       	ldi	r24, 0x1E	; 30
+    3f66:	0c d0       	rcall	.+24     	; 0x3f80 <putch>
       putch(SIGNATURE_1);
-    3f78:	84 e9       	ldi	r24, 0x94	; 148
-    3f7a:	0a d0       	rcall	.+20     	; 0x3f90 <putch>
+    3f68:	84 e9       	ldi	r24, 0x94	; 148
+    3f6a:	0a d0       	rcall	.+20     	; 0x3f80 <putch>
       putch(SIGNATURE_2);
-    3f7c:	86 e0       	ldi	r24, 0x06	; 6
-    3f7e:	96 cf       	rjmp	.-212    	; 0x3eac <main+0xac>
+    3f6c:	86 e0       	ldi	r24, 0x06	; 6
+    3f6e:	9a cf       	rjmp	.-204    	; 0x3ea4 <main+0xa4>
     }
     else if (ch == 'Q') {
-    3f80:	81 35       	cpi	r24, 0x51	; 81
-    3f82:	11 f4       	brne	.+4      	; 0x3f88 <main+0x188>
+    3f70:	81 35       	cpi	r24, 0x51	; 81
+    3f72:	11 f4       	brne	.+4      	; 0x3f78 <main+0x178>
       // Adaboot no-wait mod
       watchdogConfig(WATCHDOG_16MS);
-    3f84:	88 e0       	ldi	r24, 0x08	; 8
-    3f86:	19 d0       	rcall	.+50     	; 0x3fba <watchdogConfig>
+    3f74:	88 e0       	ldi	r24, 0x08	; 8
+    3f76:	19 d0       	rcall	.+50     	; 0x3faa <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f88:	23 d0       	rcall	.+70     	; 0x3fd0 <verifySpace>
+    3f78:	23 d0       	rcall	.+70     	; 0x3fc0 <verifySpace>
     }
     putch(STK_OK);
-    3f8a:	80 e1       	ldi	r24, 0x10	; 16
-    3f8c:	01 d0       	rcall	.+2      	; 0x3f90 <putch>
-    3f8e:	63 cf       	rjmp	.-314    	; 0x3e56 <main+0x56>
+    3f7a:	80 e1       	ldi	r24, 0x10	; 16
+    3f7c:	01 d0       	rcall	.+2      	; 0x3f80 <putch>
+    3f7e:	6b cf       	rjmp	.-298    	; 0x3e56 <main+0x56>
 
-00003f90 <putch>:
+00003f80 <putch>:
   }
 }
 
 void putch(char ch) {
-    3f90:	98 2f       	mov	r25, r24
+    3f80:	98 2f       	mov	r25, r24
 #ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    3f92:	80 91 c0 00 	lds	r24, 0x00C0
-    3f96:	85 ff       	sbrs	r24, 5
-    3f98:	fc cf       	rjmp	.-8      	; 0x3f92 <putch+0x2>
+    3f82:	80 91 c0 00 	lds	r24, 0x00C0
+    3f86:	85 ff       	sbrs	r24, 5
+    3f88:	fc cf       	rjmp	.-8      	; 0x3f82 <putch+0x2>
   UDR0 = ch;
-    3f9a:	90 93 c6 00 	sts	0x00C6, r25
+    3f8a:	90 93 c6 00 	sts	0x00C6, r25
       [uartBit] "I" (UART_TX_BIT)
     :
       "r25"
   );
 #endif
 }
-    3f9e:	08 95       	ret
+    3f8e:	08 95       	ret
 
-00003fa0 <getch>:
+00003f90 <getch>:
   return getch();
 }
 
 // Watchdog functions. These are only safe with interrupts turned off.
 void watchdogReset() {
   __asm__ __volatile__ (
-    3fa0:	a8 95       	wdr
+    3f90:	a8 95       	wdr
       [uartBit] "I" (UART_RX_BIT)
     :
       "r25"
 );
 #else
   while(!(UCSR0A & _BV(RXC0)));
-    3fa2:	80 91 c0 00 	lds	r24, 0x00C0
-    3fa6:	87 ff       	sbrs	r24, 7
-    3fa8:	fc cf       	rjmp	.-8      	; 0x3fa2 <getch+0x2>
+    3f92:	80 91 c0 00 	lds	r24, 0x00C0
+    3f96:	87 ff       	sbrs	r24, 7
+    3f98:	fc cf       	rjmp	.-8      	; 0x3f92 <getch+0x2>
   ch = UDR0;
-    3faa:	80 91 c6 00 	lds	r24, 0x00C6
+    3f9a:	80 91 c6 00 	lds	r24, 0x00C6
 #ifdef LED_DATA_FLASH
   LED_PIN |= _BV(LED);
 #endif
 
   return ch;
 }
-    3fae:	08 95       	ret
+    3f9e:	08 95       	ret
 
-00003fb0 <getLen>:
+00003fa0 <getLen>:
   } while (--count);
 }
 #endif
 
 uint8_t getLen() {
   getch();
-    3fb0:	f7 df       	rcall	.-18     	; 0x3fa0 <getch>
+    3fa0:	f7 df       	rcall	.-18     	; 0x3f90 <getch>
   length = getch();
-    3fb2:	f6 df       	rcall	.-20     	; 0x3fa0 <getch>
-    3fb4:	80 93 02 02 	sts	0x0202, r24
+    3fa2:	f6 df       	rcall	.-20     	; 0x3f90 <getch>
+    3fa4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fb8:	f3 cf       	rjmp	.-26     	; 0x3fa0 <getch>
+    3fa8:	f3 cf       	rjmp	.-26     	; 0x3f90 <getch>
 
-00003fba <watchdogConfig>:
+00003faa <watchdogConfig>:
     "wdr\n"
   );
 }
 
 void watchdogConfig(uint8_t x) {
   WDTCSR = _BV(WDCE) | _BV(WDE);
-    3fba:	e0 e6       	ldi	r30, 0x60	; 96
-    3fbc:	f0 e0       	ldi	r31, 0x00	; 0
-    3fbe:	98 e1       	ldi	r25, 0x18	; 24
-    3fc0:	90 83       	st	Z, r25
+    3faa:	e0 e6       	ldi	r30, 0x60	; 96
+    3fac:	f0 e0       	ldi	r31, 0x00	; 0
+    3fae:	98 e1       	ldi	r25, 0x18	; 24
+    3fb0:	90 83       	st	Z, r25
   WDTCSR = x;
-    3fc2:	80 83       	st	Z, r24
+    3fb2:	80 83       	st	Z, r24
 }
-    3fc4:	08 95       	ret
+    3fb4:	08 95       	ret
 
-00003fc6 <appStart>:
+00003fb6 <appStart>:
 
 void appStart() {
   watchdogConfig(WATCHDOG_OFF);
-    3fc6:	80 e0       	ldi	r24, 0x00	; 0
-    3fc8:	f8 df       	rcall	.-16     	; 0x3fba <watchdogConfig>
+    3fb6:	80 e0       	ldi	r24, 0x00	; 0
+    3fb8:	f8 df       	rcall	.-16     	; 0x3faa <watchdogConfig>
   __asm__ __volatile__ (
-    3fca:	ee 27       	eor	r30, r30
-    3fcc:	ff 27       	eor	r31, r31
-    3fce:	09 94       	ijmp
+    3fba:	ee 27       	eor	r30, r30
+    3fbc:	ff 27       	eor	r31, r31
+    3fbe:	09 94       	ijmp
 
-00003fd0 <verifySpace>:
+00003fc0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fd0:	e7 df       	rcall	.-50     	; 0x3fa0 <getch>
-    3fd2:	80 32       	cpi	r24, 0x20	; 32
-    3fd4:	09 f0       	breq	.+2      	; 0x3fd8 <verifySpace+0x8>
-    3fd6:	f7 df       	rcall	.-18     	; 0x3fc6 <appStart>
+    3fc0:	e7 df       	rcall	.-50     	; 0x3f90 <getch>
+    3fc2:	80 32       	cpi	r24, 0x20	; 32
+    3fc4:	09 f0       	breq	.+2      	; 0x3fc8 <verifySpace+0x8>
+    3fc6:	f7 df       	rcall	.-18     	; 0x3fb6 <appStart>
   putch(STK_INSYNC);
-    3fd8:	84 e1       	ldi	r24, 0x14	; 20
+    3fc8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fda:	da cf       	rjmp	.-76     	; 0x3f90 <putch>
+    3fca:	da cf       	rjmp	.-76     	; 0x3f80 <putch>
     ::[count] "M" (UART_B_VALUE)
   );
 }
 #endif
 
 void getNch(uint8_t count) {
-    3fdc:	1f 93       	push	r17
-    3fde:	18 2f       	mov	r17, r24
+    3fcc:	1f 93       	push	r17
+    3fce:	18 2f       	mov	r17, r24
 
-00003fe0 <getNch>:
+00003fd0 <getNch>:
   do getch(); while (--count);
-    3fe0:	df df       	rcall	.-66     	; 0x3fa0 <getch>
-    3fe2:	11 50       	subi	r17, 0x01	; 1
-    3fe4:	e9 f7       	brne	.-6      	; 0x3fe0 <getNch>
+    3fd0:	df df       	rcall	.-66     	; 0x3f90 <getch>
+    3fd2:	11 50       	subi	r17, 0x01	; 1
+    3fd4:	e9 f7       	brne	.-6      	; 0x3fd0 <getNch>
   verifySpace();
-    3fe6:	f4 df       	rcall	.-24     	; 0x3fd0 <verifySpace>
+    3fd6:	f4 df       	rcall	.-24     	; 0x3fc0 <verifySpace>
 }
-    3fe8:	1f 91       	pop	r17
-    3fea:	08 95       	ret
+    3fd8:	1f 91       	pop	r17
+    3fda:	08 95       	ret

+ 26 - 27
optiboot/bootloaders/optiboot/optiboot_pro_20mhz.hex

@@ -1,33 +1,32 @@
 :103E000085E08093810082E08093C00088E1809308
 :103E1000C10086E08093C20085E18093C40084B72E
-:103E200014BE81FFD0D08DE0C8D0259A86E02CE367
+:103E200014BE81FFC8D08DE0C0D0259A86E02CE377
 :103E30003BEF91E0309385002093840096BBB09BCC
 :103E4000FECF1D9AA8958150A9F7DD24D394A5E053
-:103E5000EA2EF1E1FF2EA4D0813421F481E0BED01E
-:103E600083E024C0823411F484E103C0853419F462
-:103E700085E0B4D08AC08535A1F492D0082F10E037
-:103E800010930102009300028BD090E0982F8827B6
-:103E9000802B912B880F991F909301028093000231
-:103EA00073C0863529F484E099D080E071D06DC06C
-:103EB000843609F043C07CD0E0910002F091010209
-:103EC00083E080935700E895C0E0D1E069D0899302
-:103ED000809102028150809302028823B9F778D042
-:103EE00007B600FCFDCF4091000250910102A0E016
-:103EF000B1E02C9130E011968C91119790E0982FC1
-:103F00008827822B932B1296FA010C01D09257002E
-:103F1000E89511244E5F5F4FF1E0A038BF0749F7E5
-:103F2000E0910002F0910102E0925700E89507B697
-:103F300000FCFDCFF0925700E89527C08437B9F414
-:103F400037D046D0E0910002F09101023196F09313
-:103F50000102E09300023197E4918E2F19D08091F5
-:103F60000202815080930202882361F70EC08537D8
-:103F700039F42ED08EE10CD084E90AD086E096CFB9
-:103F8000813511F488E019D023D080E101D063CFCE
-:103F9000982F8091C00085FFFCCF9093C6000895B4
-:103FA000A8958091C00087FFFCCF8091C60008953E
-:103FB000F7DFF6DF80930202F3CFE0E6F0E098E16E
-:103FC00090838083089580E0F8DFEE27FF2709942F
-:103FD000E7DF803209F0F7DF84E1DACF1F93182F93
-:0C3FE000DFDF1150E9F7F4DF1F910895B6
+:103E5000FA2EF1E1EF2E9CD0813421F481E0B6D02E
+:103E600083E020C0823411F484E103C0853419F466
+:103E700085E0ACD082C0853581F48AD0082F10E06F
+:103E800087D090E0982F8827802B912B880F991F3F
+:103E900090930102809300026FC0863529F484E07C
+:103EA00095D080E06DD069C0843609F03FC078D0ED
+:103EB000E0910002F091010283E087BFE895C0E045
+:103EC000D1E066D0899380910202815080930202F2
+:103ED0008823B9F775D007B600FCFDCF40910002EA
+:103EE00050910102A0E0B1E02C9130E011968C914C
+:103EF000119790E0982F8827822B932B1296FA0126
+:103F00000C01D7BEE89511244E5F5F4FF1E0A03859
+:103F1000BF0751F7E0910002F0910102F7BEE8956A
+:103F200007B600FCFDCFE7BEE89527C08437B9F49B
+:103F300037D046D0E0910002F09101023196F09323
+:103F40000102E09300023197E4918E2F19D0809105
+:103F50000202815080930202882361F70EC08537E8
+:103F600039F42ED08EE10CD084E90AD086E09ACFC5
+:103F7000813511F488E019D023D080E101D06BCFD6
+:103F8000982F8091C00085FFFCCF9093C6000895C4
+:103F9000A8958091C00087FFFCCF8091C60008954E
+:103FA000F7DFF6DF80930202F3CFE0E6F0E098E17E
+:103FB00090838083089580E0F8DFEE27FF2709943F
+:103FC000E7DF803209F0F7DF84E1DACF1F93182FA3
+:0C3FD000DFDF1150E9F7F4DF1F910895C6
 :0400000300003E00BB
 :00000001FF

+ 206 - 201
optiboot/bootloaders/optiboot/optiboot_pro_20mhz.lst

@@ -3,34 +3,34 @@ optiboot_pro_20mhz.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001ec  00003e00  00003e00  00000054  2**1
+  0 .text         000001dc  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  00000240  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000230  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 0000006a  00000000  00000000  00000268  2**0
+  2 .debug_pubnames 0000006a  00000000  00000000  00000258  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   00000269  00000000  00000000  000002d2  2**0
+  3 .debug_info   00000283  00000000  00000000  000002c2  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000196  00000000  00000000  0000053b  2**0
+  4 .debug_abbrev 000001ae  00000000  00000000  00000545  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003d3  00000000  00000000  000006d1  2**0
+  5 .debug_line   000003db  00000000  00000000  000006f3  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  00000090  00000000  00000000  00000aa4  2**2
+  6 .debug_frame  00000090  00000000  00000000  00000ad0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    00000135  00000000  00000000  00000b34  2**0
+  7 .debug_str    00000140  00000000  00000000  00000b60  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001d1  00000000  00000000  00000c69  2**0
+  8 .debug_loc    000001d1  00000000  00000000  00000ca0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000068  00000000  00000000  00000e3a  2**0
+  9 .debug_ranges 00000068  00000000  00000000  00000e71  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
 
 00003e00 <main>:
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
@@ -61,12 +61,12 @@ int main(void) {
     3e20:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
     3e22:	81 ff       	sbrs	r24, 1
-    3e24:	d0 d0       	rcall	.+416    	; 0x3fc6 <appStart>
+    3e24:	c8 d0       	rcall	.+400    	; 0x3fb6 <appStart>
 
   // Set up watchdog to trigger after 500ms
   watchdogConfig(WATCHDOG_500MS);
     3e26:	8d e0       	ldi	r24, 0x0D	; 13
-    3e28:	c8 d0       	rcall	.+400    	; 0x3fba <watchdogConfig>
+    3e28:	c0 d0       	rcall	.+384    	; 0x3faa <watchdogConfig>
 
   /* Set LED pin as output */
   LED_DDR |= _BV(LED);
@@ -120,28 +120,28 @@ void watchdogReset() {
       getNch(1);
     3e4a:	dd 24       	eor	r13, r13
     3e4c:	d3 94       	inc	r13
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
+      __boot_page_write_short((uint16_t)(void*)address);
     3e4e:	a5 e0       	ldi	r26, 0x05	; 5
-    3e50:	ea 2e       	mov	r14, r26
+    3e50:	fa 2e       	mov	r15, r26
       boot_spm_busy_wait();
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
     3e52:	f1 e1       	ldi	r31, 0x11	; 17
-    3e54:	ff 2e       	mov	r15, r31
+    3e54:	ef 2e       	mov	r14, r31
 #endif
 
   /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e56:	a4 d0       	rcall	.+328    	; 0x3fa0 <getch>
+    3e56:	9c d0       	rcall	.+312    	; 0x3f90 <getch>
 
     if(ch == STK_GET_PARAMETER) {
     3e58:	81 34       	cpi	r24, 0x41	; 65
@@ -149,10 +149,10 @@ void watchdogReset() {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
     3e5c:	81 e0       	ldi	r24, 0x01	; 1
-    3e5e:	be d0       	rcall	.+380    	; 0x3fdc <verifySpace+0xc>
+    3e5e:	b6 d0       	rcall	.+364    	; 0x3fcc <verifySpace+0xc>
       putch(0x03);
     3e60:	83 e0       	ldi	r24, 0x03	; 3
-    3e62:	24 c0       	rjmp	.+72     	; 0x3eac <main+0xac>
+    3e62:	20 c0       	rjmp	.+64     	; 0x3ea4 <main+0xa4>
     }
     else if(ch == STK_SET_DEVICE) {
     3e64:	82 34       	cpi	r24, 0x42	; 66
@@ -168,353 +168,358 @@ void watchdogReset() {
       // SET DEVICE EXT is ignored
       getNch(5);
     3e70:	85 e0       	ldi	r24, 0x05	; 5
-    3e72:	b4 d0       	rcall	.+360    	; 0x3fdc <verifySpace+0xc>
-    3e74:	8a c0       	rjmp	.+276    	; 0x3f8a <main+0x18a>
+    3e72:	ac d0       	rcall	.+344    	; 0x3fcc <verifySpace+0xc>
+    3e74:	82 c0       	rjmp	.+260    	; 0x3f7a <main+0x17a>
     }
     else if(ch == STK_LOAD_ADDRESS) {
     3e76:	85 35       	cpi	r24, 0x55	; 85
-    3e78:	a1 f4       	brne	.+40     	; 0x3ea2 <main+0xa2>
+    3e78:	81 f4       	brne	.+32     	; 0x3e9a <main+0x9a>
       // LOAD ADDRESS
-      address = getch();
-    3e7a:	92 d0       	rcall	.+292    	; 0x3fa0 <getch>
+      uint16_t newAddress;
+      newAddress = getch();
+    3e7a:	8a d0       	rcall	.+276    	; 0x3f90 <getch>
+      newAddress = (newAddress & 0xff) | (getch() << 8);
     3e7c:	08 2f       	mov	r16, r24
     3e7e:	10 e0       	ldi	r17, 0x00	; 0
-    3e80:	10 93 01 02 	sts	0x0201, r17
-    3e84:	00 93 00 02 	sts	0x0200, r16
-      address = (address & 0xff) | (getch() << 8);
-    3e88:	8b d0       	rcall	.+278    	; 0x3fa0 <getch>
-    3e8a:	90 e0       	ldi	r25, 0x00	; 0
-    3e8c:	98 2f       	mov	r25, r24
-    3e8e:	88 27       	eor	r24, r24
-    3e90:	80 2b       	or	r24, r16
-    3e92:	91 2b       	or	r25, r17
-      address += address; // Convert from word address to byte address
-    3e94:	88 0f       	add	r24, r24
-    3e96:	99 1f       	adc	r25, r25
-    3e98:	90 93 01 02 	sts	0x0201, r25
-    3e9c:	80 93 00 02 	sts	0x0200, r24
-    3ea0:	73 c0       	rjmp	.+230    	; 0x3f88 <main+0x188>
+    3e80:	87 d0       	rcall	.+270    	; 0x3f90 <getch>
+    3e82:	90 e0       	ldi	r25, 0x00	; 0
+    3e84:	98 2f       	mov	r25, r24
+    3e86:	88 27       	eor	r24, r24
+    3e88:	80 2b       	or	r24, r16
+    3e8a:	91 2b       	or	r25, r17
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+    3e8c:	88 0f       	add	r24, r24
+    3e8e:	99 1f       	adc	r25, r25
+      address = newAddress;
+    3e90:	90 93 01 02 	sts	0x0201, r25
+    3e94:	80 93 00 02 	sts	0x0200, r24
+    3e98:	6f c0       	rjmp	.+222    	; 0x3f78 <main+0x178>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3ea2:	86 35       	cpi	r24, 0x56	; 86
-    3ea4:	29 f4       	brne	.+10     	; 0x3eb0 <main+0xb0>
+    3e9a:	86 35       	cpi	r24, 0x56	; 86
+    3e9c:	29 f4       	brne	.+10     	; 0x3ea8 <main+0xa8>
       // UNIVERSAL command is ignored
       getNch(4);
-    3ea6:	84 e0       	ldi	r24, 0x04	; 4
-    3ea8:	99 d0       	rcall	.+306    	; 0x3fdc <verifySpace+0xc>
+    3e9e:	84 e0       	ldi	r24, 0x04	; 4
+    3ea0:	95 d0       	rcall	.+298    	; 0x3fcc <verifySpace+0xc>
       putch(0x00);
-    3eaa:	80 e0       	ldi	r24, 0x00	; 0
-    3eac:	71 d0       	rcall	.+226    	; 0x3f90 <putch>
-    3eae:	6d c0       	rjmp	.+218    	; 0x3f8a <main+0x18a>
+    3ea2:	80 e0       	ldi	r24, 0x00	; 0
+    3ea4:	6d d0       	rcall	.+218    	; 0x3f80 <putch>
+    3ea6:	69 c0       	rjmp	.+210    	; 0x3f7a <main+0x17a>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3eb0:	84 36       	cpi	r24, 0x64	; 100
-    3eb2:	09 f0       	breq	.+2      	; 0x3eb6 <main+0xb6>
-    3eb4:	43 c0       	rjmp	.+134    	; 0x3f3c <main+0x13c>
+    3ea8:	84 36       	cpi	r24, 0x64	; 100
+    3eaa:	09 f0       	breq	.+2      	; 0x3eae <main+0xae>
+    3eac:	3f c0       	rjmp	.+126    	; 0x3f2c <main+0x12c>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
 
       getLen();
-    3eb6:	7c d0       	rcall	.+248    	; 0x3fb0 <getLen>
+    3eae:	78 d0       	rcall	.+240    	; 0x3fa0 <getLen>
 
       // Immediately start page erase - this will 4.5ms
-      boot_page_erase((uint16_t)(void*)address);
-    3eb8:	e0 91 00 02 	lds	r30, 0x0200
-    3ebc:	f0 91 01 02 	lds	r31, 0x0201
-    3ec0:	83 e0       	ldi	r24, 0x03	; 3
-    3ec2:	80 93 57 00 	sts	0x0057, r24
-    3ec6:	e8 95       	spm
-    3ec8:	c0 e0       	ldi	r28, 0x00	; 0
-    3eca:	d1 e0       	ldi	r29, 0x01	; 1
-
+      __boot_page_erase_short((uint16_t)(void*)address);
+    3eb0:	e0 91 00 02 	lds	r30, 0x0200
+    3eb4:	f0 91 01 02 	lds	r31, 0x0201
+    3eb8:	83 e0       	ldi	r24, 0x03	; 3
+    3eba:	87 bf       	out	0x37, r24	; 55
+    3ebc:	e8 95       	spm
+    3ebe:	c0 e0       	ldi	r28, 0x00	; 0
+    3ec0:	d1 e0       	ldi	r29, 0x01	; 1
+      
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3ecc:	69 d0       	rcall	.+210    	; 0x3fa0 <getch>
-    3ece:	89 93       	st	Y+, r24
+    3ec2:	66 d0       	rcall	.+204    	; 0x3f90 <getch>
+    3ec4:	89 93       	st	Y+, r24
       while (--length);
-    3ed0:	80 91 02 02 	lds	r24, 0x0202
-    3ed4:	81 50       	subi	r24, 0x01	; 1
-    3ed6:	80 93 02 02 	sts	0x0202, r24
-    3eda:	88 23       	and	r24, r24
-    3edc:	b9 f7       	brne	.-18     	; 0x3ecc <main+0xcc>
+    3ec6:	80 91 02 02 	lds	r24, 0x0202
+    3eca:	81 50       	subi	r24, 0x01	; 1
+    3ecc:	80 93 02 02 	sts	0x0202, r24
+    3ed0:	88 23       	and	r24, r24
+    3ed2:	b9 f7       	brne	.-18     	; 0x3ec2 <main+0xc2>
 
       // Read command terminator, start reply
       verifySpace();
-    3ede:	78 d0       	rcall	.+240    	; 0x3fd0 <verifySpace>
+    3ed4:	75 d0       	rcall	.+234    	; 0x3fc0 <verifySpace>
       
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3ee0:	07 b6       	in	r0, 0x37	; 55
-    3ee2:	00 fc       	sbrc	r0, 0
-    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+    3ed6:	07 b6       	in	r0, 0x37	; 55
+    3ed8:	00 fc       	sbrc	r0, 0
+    3eda:	fd cf       	rjmp	.-6      	; 0x3ed6 <main+0xd6>
       }
 #endif
 
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ee6:	40 91 00 02 	lds	r20, 0x0200
-    3eea:	50 91 01 02 	lds	r21, 0x0201
-    3eee:	a0 e0       	ldi	r26, 0x00	; 0
-    3ef0:	b1 e0       	ldi	r27, 0x01	; 1
+    3edc:	40 91 00 02 	lds	r20, 0x0200
+    3ee0:	50 91 01 02 	lds	r21, 0x0201
+    3ee4:	a0 e0       	ldi	r26, 0x00	; 0
+    3ee6:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3ef2:	2c 91       	ld	r18, X
-    3ef4:	30 e0       	ldi	r19, 0x00	; 0
+    3ee8:	2c 91       	ld	r18, X
+    3eea:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ef6:	11 96       	adiw	r26, 0x01	; 1
-    3ef8:	8c 91       	ld	r24, X
-    3efa:	11 97       	sbiw	r26, 0x01	; 1
-    3efc:	90 e0       	ldi	r25, 0x00	; 0
-    3efe:	98 2f       	mov	r25, r24
-    3f00:	88 27       	eor	r24, r24
-    3f02:	82 2b       	or	r24, r18
-    3f04:	93 2b       	or	r25, r19
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+    3eec:	11 96       	adiw	r26, 0x01	; 1
+    3eee:	8c 91       	ld	r24, X
+    3ef0:	11 97       	sbiw	r26, 0x01	; 1
+    3ef2:	90 e0       	ldi	r25, 0x00	; 0
+    3ef4:	98 2f       	mov	r25, r24
+    3ef6:	88 27       	eor	r24, r24
+    3ef8:	82 2b       	or	r24, r18
+    3efa:	93 2b       	or	r25, r19
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
-    3f06:	12 96       	adiw	r26, 0x02	; 2
+    3efc:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3f08:	fa 01       	movw	r30, r20
-    3f0a:	0c 01       	movw	r0, r24
-    3f0c:	d0 92 57 00 	sts	0x0057, r13
-    3f10:	e8 95       	spm
-    3f12:	11 24       	eor	r1, r1
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+    3efe:	fa 01       	movw	r30, r20
+    3f00:	0c 01       	movw	r0, r24
+    3f02:	d7 be       	out	0x37, r13	; 55
+    3f04:	e8 95       	spm
+    3f06:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3f14:	4e 5f       	subi	r20, 0xFE	; 254
-    3f16:	5f 4f       	sbci	r21, 0xFF	; 255
+    3f08:	4e 5f       	subi	r20, 0xFE	; 254
+    3f0a:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f18:	f1 e0       	ldi	r31, 0x01	; 1
-    3f1a:	a0 38       	cpi	r26, 0x80	; 128
-    3f1c:	bf 07       	cpc	r27, r31
-    3f1e:	49 f7       	brne	.-46     	; 0x3ef2 <main+0xf2>
+    3f0c:	f1 e0       	ldi	r31, 0x01	; 1
+    3f0e:	a0 38       	cpi	r26, 0x80	; 128
+    3f10:	bf 07       	cpc	r27, r31
+    3f12:	51 f7       	brne	.-44     	; 0x3ee8 <main+0xe8>
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
-    3f20:	e0 91 00 02 	lds	r30, 0x0200
-    3f24:	f0 91 01 02 	lds	r31, 0x0201
-    3f28:	e0 92 57 00 	sts	0x0057, r14
-    3f2c:	e8 95       	spm
+      __boot_page_write_short((uint16_t)(void*)address);
+    3f14:	e0 91 00 02 	lds	r30, 0x0200
+    3f18:	f0 91 01 02 	lds	r31, 0x0201
+    3f1c:	f7 be       	out	0x37, r15	; 55
+    3f1e:	e8 95       	spm
       boot_spm_busy_wait();
-    3f2e:	07 b6       	in	r0, 0x37	; 55
-    3f30:	00 fc       	sbrc	r0, 0
-    3f32:	fd cf       	rjmp	.-6      	; 0x3f2e <main+0x12e>
+    3f20:	07 b6       	in	r0, 0x37	; 55
+    3f22:	00 fc       	sbrc	r0, 0
+    3f24:	fd cf       	rjmp	.-6      	; 0x3f20 <main+0x120>
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
-    3f34:	f0 92 57 00 	sts	0x0057, r15
-    3f38:	e8 95       	spm
-    3f3a:	27 c0       	rjmp	.+78     	; 0x3f8a <main+0x18a>
+    3f26:	e7 be       	out	0x37, r14	; 55
+    3f28:	e8 95       	spm
+    3f2a:	27 c0       	rjmp	.+78     	; 0x3f7a <main+0x17a>
 #endif
 
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f3c:	84 37       	cpi	r24, 0x74	; 116
-    3f3e:	b9 f4       	brne	.+46     	; 0x3f6e <main+0x16e>
+    3f2c:	84 37       	cpi	r24, 0x74	; 116
+    3f2e:	b9 f4       	brne	.+46     	; 0x3f5e <main+0x15e>
       // READ PAGE - we only read flash
       getLen();
-    3f40:	37 d0       	rcall	.+110    	; 0x3fb0 <getLen>
+    3f30:	37 d0       	rcall	.+110    	; 0x3fa0 <getLen>
       verifySpace();
-    3f42:	46 d0       	rcall	.+140    	; 0x3fd0 <verifySpace>
-        else ch = pgm_read_byte_near(address);
+    3f32:	46 d0       	rcall	.+140    	; 0x3fc0 <verifySpace>
+        putch(result);
         address++;
-        putch(ch);
-      } while (--length);
+      }
+      while (--length);
 #else
       do putch(pgm_read_byte_near(address++));
-    3f44:	e0 91 00 02 	lds	r30, 0x0200
-    3f48:	f0 91 01 02 	lds	r31, 0x0201
-    3f4c:	31 96       	adiw	r30, 0x01	; 1
-    3f4e:	f0 93 01 02 	sts	0x0201, r31
-    3f52:	e0 93 00 02 	sts	0x0200, r30
-    3f56:	31 97       	sbiw	r30, 0x01	; 1
-    3f58:	e4 91       	lpm	r30, Z+
-    3f5a:	8e 2f       	mov	r24, r30
-    3f5c:	19 d0       	rcall	.+50     	; 0x3f90 <putch>
+    3f34:	e0 91 00 02 	lds	r30, 0x0200
+    3f38:	f0 91 01 02 	lds	r31, 0x0201
+    3f3c:	31 96       	adiw	r30, 0x01	; 1
+    3f3e:	f0 93 01 02 	sts	0x0201, r31
+    3f42:	e0 93 00 02 	sts	0x0200, r30
+    3f46:	31 97       	sbiw	r30, 0x01	; 1
+    3f48:	e4 91       	lpm	r30, Z+
+    3f4a:	8e 2f       	mov	r24, r30
+    3f4c:	19 d0       	rcall	.+50     	; 0x3f80 <putch>
       while (--length);
-    3f5e:	80 91 02 02 	lds	r24, 0x0202
-    3f62:	81 50       	subi	r24, 0x01	; 1
-    3f64:	80 93 02 02 	sts	0x0202, r24
-    3f68:	88 23       	and	r24, r24
-    3f6a:	61 f7       	brne	.-40     	; 0x3f44 <main+0x144>
-    3f6c:	0e c0       	rjmp	.+28     	; 0x3f8a <main+0x18a>
+    3f4e:	80 91 02 02 	lds	r24, 0x0202
+    3f52:	81 50       	subi	r24, 0x01	; 1
+    3f54:	80 93 02 02 	sts	0x0202, r24
+    3f58:	88 23       	and	r24, r24
+    3f5a:	61 f7       	brne	.-40     	; 0x3f34 <main+0x134>
+    3f5c:	0e c0       	rjmp	.+28     	; 0x3f7a <main+0x17a>
+#endif
 #endif
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f6e:	85 37       	cpi	r24, 0x75	; 117
-    3f70:	39 f4       	brne	.+14     	; 0x3f80 <main+0x180>
+    3f5e:	85 37       	cpi	r24, 0x75	; 117
+    3f60:	39 f4       	brne	.+14     	; 0x3f70 <main+0x170>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f72:	2e d0       	rcall	.+92     	; 0x3fd0 <verifySpace>
+    3f62:	2e d0       	rcall	.+92     	; 0x3fc0 <verifySpace>
       putch(SIGNATURE_0);
-    3f74:	8e e1       	ldi	r24, 0x1E	; 30
-    3f76:	0c d0       	rcall	.+24     	; 0x3f90 <putch>
+    3f64:	8e e1       	ldi	r24, 0x1E	; 30
+    3f66:	0c d0       	rcall	.+24     	; 0x3f80 <putch>
       putch(SIGNATURE_1);
-    3f78:	84 e9       	ldi	r24, 0x94	; 148
-    3f7a:	0a d0       	rcall	.+20     	; 0x3f90 <putch>
+    3f68:	84 e9       	ldi	r24, 0x94	; 148
+    3f6a:	0a d0       	rcall	.+20     	; 0x3f80 <putch>
       putch(SIGNATURE_2);
-    3f7c:	86 e0       	ldi	r24, 0x06	; 6
-    3f7e:	96 cf       	rjmp	.-212    	; 0x3eac <main+0xac>
+    3f6c:	86 e0       	ldi	r24, 0x06	; 6
+    3f6e:	9a cf       	rjmp	.-204    	; 0x3ea4 <main+0xa4>
     }
     else if (ch == 'Q') {
-    3f80:	81 35       	cpi	r24, 0x51	; 81
-    3f82:	11 f4       	brne	.+4      	; 0x3f88 <main+0x188>
+    3f70:	81 35       	cpi	r24, 0x51	; 81
+    3f72:	11 f4       	brne	.+4      	; 0x3f78 <main+0x178>
       // Adaboot no-wait mod
       watchdogConfig(WATCHDOG_16MS);
-    3f84:	88 e0       	ldi	r24, 0x08	; 8
-    3f86:	19 d0       	rcall	.+50     	; 0x3fba <watchdogConfig>
+    3f74:	88 e0       	ldi	r24, 0x08	; 8
+    3f76:	19 d0       	rcall	.+50     	; 0x3faa <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f88:	23 d0       	rcall	.+70     	; 0x3fd0 <verifySpace>
+    3f78:	23 d0       	rcall	.+70     	; 0x3fc0 <verifySpace>
     }
     putch(STK_OK);
-    3f8a:	80 e1       	ldi	r24, 0x10	; 16
-    3f8c:	01 d0       	rcall	.+2      	; 0x3f90 <putch>
-    3f8e:	63 cf       	rjmp	.-314    	; 0x3e56 <main+0x56>
+    3f7a:	80 e1       	ldi	r24, 0x10	; 16
+    3f7c:	01 d0       	rcall	.+2      	; 0x3f80 <putch>
+    3f7e:	6b cf       	rjmp	.-298    	; 0x3e56 <main+0x56>
 
-00003f90 <putch>:
+00003f80 <putch>:
   }
 }
 
 void putch(char ch) {
-    3f90:	98 2f       	mov	r25, r24
+    3f80:	98 2f       	mov	r25, r24
 #ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
-    3f92:	80 91 c0 00 	lds	r24, 0x00C0
-    3f96:	85 ff       	sbrs	r24, 5
-    3f98:	fc cf       	rjmp	.-8      	; 0x3f92 <putch+0x2>
+    3f82:	80 91 c0 00 	lds	r24, 0x00C0
+    3f86:	85 ff       	sbrs	r24, 5
+    3f88:	fc cf       	rjmp	.-8      	; 0x3f82 <putch+0x2>
   UDR0 = ch;
-    3f9a:	90 93 c6 00 	sts	0x00C6, r25
+    3f8a:	90 93 c6 00 	sts	0x00C6, r25
       [uartBit] "I" (UART_TX_BIT)
     :
       "r25"
   );
 #endif
 }
-    3f9e:	08 95       	ret
+    3f8e:	08 95       	ret
 
-00003fa0 <getch>:
+00003f90 <getch>:
   return getch();
 }
 
 // Watchdog functions. These are only safe with interrupts turned off.
 void watchdogReset() {
   __asm__ __volatile__ (
-    3fa0:	a8 95       	wdr
+    3f90:	a8 95       	wdr
       [uartBit] "I" (UART_RX_BIT)
     :
       "r25"
 );
 #else
   while(!(UCSR0A & _BV(RXC0)));
-    3fa2:	80 91 c0 00 	lds	r24, 0x00C0
-    3fa6:	87 ff       	sbrs	r24, 7
-    3fa8:	fc cf       	rjmp	.-8      	; 0x3fa2 <getch+0x2>
+    3f92:	80 91 c0 00 	lds	r24, 0x00C0
+    3f96:	87 ff       	sbrs	r24, 7
+    3f98:	fc cf       	rjmp	.-8      	; 0x3f92 <getch+0x2>
   ch = UDR0;
-    3faa:	80 91 c6 00 	lds	r24, 0x00C6
+    3f9a:	80 91 c6 00 	lds	r24, 0x00C6
 #ifdef LED_DATA_FLASH
   LED_PIN |= _BV(LED);
 #endif
 
   return ch;
 }
-    3fae:	08 95       	ret
+    3f9e:	08 95       	ret
 
-00003fb0 <getLen>:
+00003fa0 <getLen>:
   } while (--count);
 }
 #endif
 
 uint8_t getLen() {
   getch();
-    3fb0:	f7 df       	rcall	.-18     	; 0x3fa0 <getch>
+    3fa0:	f7 df       	rcall	.-18     	; 0x3f90 <getch>
   length = getch();
-    3fb2:	f6 df       	rcall	.-20     	; 0x3fa0 <getch>
-    3fb4:	80 93 02 02 	sts	0x0202, r24
+    3fa2:	f6 df       	rcall	.-20     	; 0x3f90 <getch>
+    3fa4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fb8:	f3 cf       	rjmp	.-26     	; 0x3fa0 <getch>
+    3fa8:	f3 cf       	rjmp	.-26     	; 0x3f90 <getch>
 
-00003fba <watchdogConfig>:
+00003faa <watchdogConfig>:
     "wdr\n"
   );
 }
 
 void watchdogConfig(uint8_t x) {
   WDTCSR = _BV(WDCE) | _BV(WDE);
-    3fba:	e0 e6       	ldi	r30, 0x60	; 96
-    3fbc:	f0 e0       	ldi	r31, 0x00	; 0
-    3fbe:	98 e1       	ldi	r25, 0x18	; 24
-    3fc0:	90 83       	st	Z, r25
+    3faa:	e0 e6       	ldi	r30, 0x60	; 96
+    3fac:	f0 e0       	ldi	r31, 0x00	; 0
+    3fae:	98 e1       	ldi	r25, 0x18	; 24
+    3fb0:	90 83       	st	Z, r25
   WDTCSR = x;
-    3fc2:	80 83       	st	Z, r24
+    3fb2:	80 83       	st	Z, r24
 }
-    3fc4:	08 95       	ret
+    3fb4:	08 95       	ret
 
-00003fc6 <appStart>:
+00003fb6 <appStart>:
 
 void appStart() {
   watchdogConfig(WATCHDOG_OFF);
-    3fc6:	80 e0       	ldi	r24, 0x00	; 0
-    3fc8:	f8 df       	rcall	.-16     	; 0x3fba <watchdogConfig>
+    3fb6:	80 e0       	ldi	r24, 0x00	; 0
+    3fb8:	f8 df       	rcall	.-16     	; 0x3faa <watchdogConfig>
   __asm__ __volatile__ (
-    3fca:	ee 27       	eor	r30, r30
-    3fcc:	ff 27       	eor	r31, r31
-    3fce:	09 94       	ijmp
+    3fba:	ee 27       	eor	r30, r30
+    3fbc:	ff 27       	eor	r31, r31
+    3fbe:	09 94       	ijmp
 
-00003fd0 <verifySpace>:
+00003fc0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fd0:	e7 df       	rcall	.-50     	; 0x3fa0 <getch>
-    3fd2:	80 32       	cpi	r24, 0x20	; 32
-    3fd4:	09 f0       	breq	.+2      	; 0x3fd8 <verifySpace+0x8>
-    3fd6:	f7 df       	rcall	.-18     	; 0x3fc6 <appStart>
+    3fc0:	e7 df       	rcall	.-50     	; 0x3f90 <getch>
+    3fc2:	80 32       	cpi	r24, 0x20	; 32
+    3fc4:	09 f0       	breq	.+2      	; 0x3fc8 <verifySpace+0x8>
+    3fc6:	f7 df       	rcall	.-18     	; 0x3fb6 <appStart>
   putch(STK_INSYNC);
-    3fd8:	84 e1       	ldi	r24, 0x14	; 20
+    3fc8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fda:	da cf       	rjmp	.-76     	; 0x3f90 <putch>
+    3fca:	da cf       	rjmp	.-76     	; 0x3f80 <putch>
     ::[count] "M" (UART_B_VALUE)
   );
 }
 #endif
 
 void getNch(uint8_t count) {
-    3fdc:	1f 93       	push	r17
-    3fde:	18 2f       	mov	r17, r24
+    3fcc:	1f 93       	push	r17
+    3fce:	18 2f       	mov	r17, r24
 
-00003fe0 <getNch>:
+00003fd0 <getNch>:
   do getch(); while (--count);
-    3fe0:	df df       	rcall	.-66     	; 0x3fa0 <getch>
-    3fe2:	11 50       	subi	r17, 0x01	; 1
-    3fe4:	e9 f7       	brne	.-6      	; 0x3fe0 <getNch>
+    3fd0:	df df       	rcall	.-66     	; 0x3f90 <getch>
+    3fd2:	11 50       	subi	r17, 0x01	; 1
+    3fd4:	e9 f7       	brne	.-6      	; 0x3fd0 <getNch>
   verifySpace();
-    3fe6:	f4 df       	rcall	.-24     	; 0x3fd0 <verifySpace>
+    3fd6:	f4 df       	rcall	.-24     	; 0x3fc0 <verifySpace>
 }
-    3fe8:	1f 91       	pop	r17
-    3fea:	08 95       	ret
+    3fd8:	1f 91       	pop	r17
+    3fda:	08 95       	ret

+ 30 - 31
optiboot/bootloaders/optiboot/optiboot_pro_8MHz.hex

@@ -1,34 +1,33 @@
-:103E000085E08093810084B714BE81FFE4D08DE00B
-:103E1000DCD0259A519A86E028E13EEF91E030937C
+:103E000085E08093810084B714BE81FFDCD08DE013
+:103E1000D4D0259A519A86E028E13EEF91E0309384
 :103E200085002093840096BBB09BFECF1D9AA89579
-:103E30008150A9F7DD24D394A5E0EA2EF1E1FF2E0D
-:103E4000ABD0813421F481E0D1D083E024C082342E
-:103E500011F484E103C0853419F485E0C7D08AC029
-:103E60008535A1F499D0082F10E01093010200933A
-:103E7000000292D090E0982F8827802B912B880FFA
-:103E8000991F909301028093000273C0863529F434
-:103E900084E0ACD080E071D06DC0843609F043C0BE
-:103EA0008FD0E0910002F091010283E080935700EF
-:103EB000E895C0E0D1E070D08993809102028150F2
-:103EC000809302028823B9F78BD007B600FCFDCFA0
-:103ED0004091000250910102A0E0B1E02C9130E04D
-:103EE00011968C91119790E0982F8827822B932B15
-:103EF0001296FA010C01D0925700E89511244E5FFA
-:103F00005F4FF1E0A038BF0749F7E0910002F09160
-:103F10000102E0925700E89507B600FCFDCFF09251
-:103F20005700E89527C08437B9F44AD059D0E091BA
-:103F30000002F09101023196F0930102E093000239
-:103F40003197E4918E2F19D0809102028150809395
-:103F50000202882361F70EC0853739F441D08EE123
-:103F60000CD084E90AD086E096CF813511F488E040
-:103F70002CD036D080E101D063CF2AE030E08095AC
-:103F8000089410F4599802C0599A000015D014D022
-:103F900086952A95B1F70895A89529E030E04899CB
-:103FA000FECF0AD009D008D08894489908942A9561
-:103FB00011F08795F7CF089598E09A95F1F7089555
-:103FC000EBDFEADF80930202E7CFE0E6F0E098E182
-:103FD00090838083089580E0F8DFEE27FF2709941F
-:103FE000DBDF803209F0F7DF84E1C7CF1F93182FA2
-:0C3FF000D3DF1150E9F7F4DF1F910895B2
+:103E30008150A9F7DD24D394A5E0FA2EF1E1EF2E0D
+:103E4000A3D0813421F481E0C9D083E020C0823442
+:103E500011F484E103C0853419F485E0BFD082C039
+:103E6000853581F491D0082F10E08ED090E0982F06
+:103E70008827802B912B880F991F909301028093A4
+:103E800000026FC0863529F484E0A8D080E06DD0B0
+:103E900069C0843609F03FC08BD0E0910002F091F8
+:103EA000010283E087BFE895C0E0D1E06DD089933F
+:103EB000809102028150809302028823B9F788D052
+:103EC00007B600FCFDCF4091000250910102A0E036
+:103ED000B1E02C9130E011968C91119790E0982FE1
+:103EE0008827822B932B1296FA010C01D7BEE895F6
+:103EF00011244E5F5F4FF1E0A038BF0751F7E0910A
+:103F00000002F0910102F7BEE89507B600FCFDCF74
+:103F1000E7BEE89527C08437B9F44AD059D0E0917C
+:103F20000002F09101023196F0930102E093000249
+:103F30003197E4918E2F19D08091020281508093A5
+:103F40000202882361F70EC0853739F441D08EE133
+:103F50000CD084E90AD086E09ACF813511F488E04C
+:103F60002CD036D080E101D06BCF2AE030E08095B4
+:103F7000089410F4599802C0599A000015D014D032
+:103F800086952A95B1F70895A89529E030E04899DB
+:103F9000FECF0AD009D008D08894489908942A9571
+:103FA00011F08795F7CF089598E09A95F1F7089565
+:103FB000EBDFEADF80930202E7CFE0E6F0E098E192
+:103FC00090838083089580E0F8DFEE27FF2709942F
+:103FD000DBDF803209F0F7DF84E1C7CF1F93182FB2
+:0C3FE000D3DF1150E9F7F4DF1F910895C2
 :0400000300003E00BB
 :00000001FF

+ 231 - 226
optiboot/bootloaders/optiboot/optiboot_pro_8MHz.lst

@@ -3,34 +3,34 @@ optiboot_pro_8MHz.elf:     file format elf32-avr
 
 Sections:
 Idx Name          Size      VMA       LMA       File off  Algn
-  0 .text         000001fc  00003e00  00003e00  00000054  2**1
+  0 .text         000001ec  00003e00  00003e00  00000054  2**1
                   CONTENTS, ALLOC, LOAD, READONLY, CODE
-  1 .debug_aranges 00000028  00000000  00000000  00000250  2**0
+  1 .debug_aranges 00000028  00000000  00000000  00000240  2**0
                   CONTENTS, READONLY, DEBUGGING
-  2 .debug_pubnames 00000078  00000000  00000000  00000278  2**0
+  2 .debug_pubnames 00000078  00000000  00000000  00000268  2**0
                   CONTENTS, READONLY, DEBUGGING
-  3 .debug_info   00000277  00000000  00000000  000002f0  2**0
+  3 .debug_info   00000291  00000000  00000000  000002e0  2**0
                   CONTENTS, READONLY, DEBUGGING
-  4 .debug_abbrev 00000194  00000000  00000000  00000567  2**0
+  4 .debug_abbrev 000001ac  00000000  00000000  00000571  2**0
                   CONTENTS, READONLY, DEBUGGING
-  5 .debug_line   000003bb  00000000  00000000  000006fb  2**0
+  5 .debug_line   000003c3  00000000  00000000  0000071d  2**0
                   CONTENTS, READONLY, DEBUGGING
-  6 .debug_frame  000000a0  00000000  00000000  00000ab8  2**2
+  6 .debug_frame  000000a0  00000000  00000000  00000ae0  2**2
                   CONTENTS, READONLY, DEBUGGING
-  7 .debug_str    0000013f  00000000  00000000  00000b58  2**0
+  7 .debug_str    0000014a  00000000  00000000  00000b80  2**0
                   CONTENTS, READONLY, DEBUGGING
-  8 .debug_loc    000001a0  00000000  00000000  00000c97  2**0
+  8 .debug_loc    000001a0  00000000  00000000  00000cca  2**0
                   CONTENTS, READONLY, DEBUGGING
-  9 .debug_ranges 00000070  00000000  00000000  00000e37  2**0
+  9 .debug_ranges 00000070  00000000  00000000  00000e6a  2**0
                   CONTENTS, READONLY, DEBUGGING
 
 Disassembly of section .text:
 
 00003e00 <main>:
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
     3e00:	85 e0       	ldi	r24, 0x05	; 5
@@ -46,12 +46,12 @@ int main(void) {
     3e08:	14 be       	out	0x34, r1	; 52
   if (!(ch & _BV(EXTRF))) appStart();
     3e0a:	81 ff       	sbrs	r24, 1
-    3e0c:	e4 d0       	rcall	.+456    	; 0x3fd6 <appStart>
+    3e0c:	dc d0       	rcall	.+440    	; 0x3fc6 <appStart>
 
   // Set up watchdog to trigger after 500ms
   watchdogConfig(WATCHDOG_500MS);
     3e0e:	8d e0       	ldi	r24, 0x0D	; 13
-    3e10:	dc d0       	rcall	.+440    	; 0x3fca <watchdogConfig>
+    3e10:	d4 d0       	rcall	.+424    	; 0x3fba <watchdogConfig>
 
   /* Set LED pin as output */
   LED_DDR |= _BV(LED);
@@ -110,28 +110,28 @@ void watchdogReset() {
       getNch(1);
     3e34:	dd 24       	eor	r13, r13
     3e36:	d3 94       	inc	r13
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
         addrPtr += 2;
       } while (--ch);
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
+      __boot_page_write_short((uint16_t)(void*)address);
     3e38:	a5 e0       	ldi	r26, 0x05	; 5
-    3e3a:	ea 2e       	mov	r14, r26
+    3e3a:	fa 2e       	mov	r15, r26
       boot_spm_busy_wait();
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
     3e3c:	f1 e1       	ldi	r31, 0x11	; 17
-    3e3e:	ff 2e       	mov	r15, r31
+    3e3e:	ef 2e       	mov	r14, r31
 #endif
 
   /* Forever loop */
   for (;;) {
     /* get character from UART */
     ch = getch();
-    3e40:	ab d0       	rcall	.+342    	; 0x3f98 <getch>
+    3e40:	a3 d0       	rcall	.+326    	; 0x3f88 <getch>
 
     if(ch == STK_GET_PARAMETER) {
     3e42:	81 34       	cpi	r24, 0x41	; 65
@@ -139,10 +139,10 @@ void watchdogReset() {
       // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
       getNch(1);
     3e46:	81 e0       	ldi	r24, 0x01	; 1
-    3e48:	d1 d0       	rcall	.+418    	; 0x3fec <verifySpace+0xc>
+    3e48:	c9 d0       	rcall	.+402    	; 0x3fdc <verifySpace+0xc>
       putch(0x03);
     3e4a:	83 e0       	ldi	r24, 0x03	; 3
-    3e4c:	24 c0       	rjmp	.+72     	; 0x3e96 <main+0x96>
+    3e4c:	20 c0       	rjmp	.+64     	; 0x3e8e <main+0x8e>
     }
     else if(ch == STK_SET_DEVICE) {
     3e4e:	82 34       	cpi	r24, 0x42	; 66
@@ -158,376 +158,381 @@ void watchdogReset() {
       // SET DEVICE EXT is ignored
       getNch(5);
     3e5a:	85 e0       	ldi	r24, 0x05	; 5
-    3e5c:	c7 d0       	rcall	.+398    	; 0x3fec <verifySpace+0xc>
-    3e5e:	8a c0       	rjmp	.+276    	; 0x3f74 <main+0x174>
+    3e5c:	bf d0       	rcall	.+382    	; 0x3fdc <verifySpace+0xc>
+    3e5e:	82 c0       	rjmp	.+260    	; 0x3f64 <main+0x164>
     }
     else if(ch == STK_LOAD_ADDRESS) {
     3e60:	85 35       	cpi	r24, 0x55	; 85
-    3e62:	a1 f4       	brne	.+40     	; 0x3e8c <main+0x8c>
+    3e62:	81 f4       	brne	.+32     	; 0x3e84 <main+0x84>
       // LOAD ADDRESS
-      address = getch();
-    3e64:	99 d0       	rcall	.+306    	; 0x3f98 <getch>
+      uint16_t newAddress;
+      newAddress = getch();
+    3e64:	91 d0       	rcall	.+290    	; 0x3f88 <getch>
+      newAddress = (newAddress & 0xff) | (getch() << 8);
     3e66:	08 2f       	mov	r16, r24
     3e68:	10 e0       	ldi	r17, 0x00	; 0
-    3e6a:	10 93 01 02 	sts	0x0201, r17
-    3e6e:	00 93 00 02 	sts	0x0200, r16
-      address = (address & 0xff) | (getch() << 8);
-    3e72:	92 d0       	rcall	.+292    	; 0x3f98 <getch>
-    3e74:	90 e0       	ldi	r25, 0x00	; 0
-    3e76:	98 2f       	mov	r25, r24
-    3e78:	88 27       	eor	r24, r24
-    3e7a:	80 2b       	or	r24, r16
-    3e7c:	91 2b       	or	r25, r17
-      address += address; // Convert from word address to byte address
-    3e7e:	88 0f       	add	r24, r24
-    3e80:	99 1f       	adc	r25, r25
-    3e82:	90 93 01 02 	sts	0x0201, r25
-    3e86:	80 93 00 02 	sts	0x0200, r24
-    3e8a:	73 c0       	rjmp	.+230    	; 0x3f72 <main+0x172>
+    3e6a:	8e d0       	rcall	.+284    	; 0x3f88 <getch>
+    3e6c:	90 e0       	ldi	r25, 0x00	; 0
+    3e6e:	98 2f       	mov	r25, r24
+    3e70:	88 27       	eor	r24, r24
+    3e72:	80 2b       	or	r24, r16
+    3e74:	91 2b       	or	r25, r17
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+    3e76:	88 0f       	add	r24, r24
+    3e78:	99 1f       	adc	r25, r25
+      address = newAddress;
+    3e7a:	90 93 01 02 	sts	0x0201, r25
+    3e7e:	80 93 00 02 	sts	0x0200, r24
+    3e82:	6f c0       	rjmp	.+222    	; 0x3f62 <main+0x162>
       verifySpace();
     }
     else if(ch == STK_UNIVERSAL) {
-    3e8c:	86 35       	cpi	r24, 0x56	; 86
-    3e8e:	29 f4       	brne	.+10     	; 0x3e9a <main+0x9a>
+    3e84:	86 35       	cpi	r24, 0x56	; 86
+    3e86:	29 f4       	brne	.+10     	; 0x3e92 <main+0x92>
       // UNIVERSAL command is ignored
       getNch(4);
-    3e90:	84 e0       	ldi	r24, 0x04	; 4
-    3e92:	ac d0       	rcall	.+344    	; 0x3fec <verifySpace+0xc>
+    3e88:	84 e0       	ldi	r24, 0x04	; 4
+    3e8a:	a8 d0       	rcall	.+336    	; 0x3fdc <verifySpace+0xc>
       putch(0x00);
-    3e94:	80 e0       	ldi	r24, 0x00	; 0
-    3e96:	71 d0       	rcall	.+226    	; 0x3f7a <putch>
-    3e98:	6d c0       	rjmp	.+218    	; 0x3f74 <main+0x174>
+    3e8c:	80 e0       	ldi	r24, 0x00	; 0
+    3e8e:	6d d0       	rcall	.+218    	; 0x3f6a <putch>
+    3e90:	69 c0       	rjmp	.+210    	; 0x3f64 <main+0x164>
     }
     /* Write memory, length is big endian and is in bytes  */
     else if(ch == STK_PROG_PAGE) {
-    3e9a:	84 36       	cpi	r24, 0x64	; 100
-    3e9c:	09 f0       	breq	.+2      	; 0x3ea0 <main+0xa0>
-    3e9e:	43 c0       	rjmp	.+134    	; 0x3f26 <main+0x126>
+    3e92:	84 36       	cpi	r24, 0x64	; 100
+    3e94:	09 f0       	breq	.+2      	; 0x3e98 <main+0x98>
+    3e96:	3f c0       	rjmp	.+126    	; 0x3f16 <main+0x116>
       // PROGRAM PAGE - we support flash programming only, not EEPROM
       uint8_t *bufPtr;
       uint16_t addrPtr;
 
       getLen();
-    3ea0:	8f d0       	rcall	.+286    	; 0x3fc0 <getLen>
+    3e98:	8b d0       	rcall	.+278    	; 0x3fb0 <getLen>
 
       // Immediately start page erase - this will 4.5ms
-      boot_page_erase((uint16_t)(void*)address);
-    3ea2:	e0 91 00 02 	lds	r30, 0x0200
-    3ea6:	f0 91 01 02 	lds	r31, 0x0201
-    3eaa:	83 e0       	ldi	r24, 0x03	; 3
-    3eac:	80 93 57 00 	sts	0x0057, r24
-    3eb0:	e8 95       	spm
-    3eb2:	c0 e0       	ldi	r28, 0x00	; 0
-    3eb4:	d1 e0       	ldi	r29, 0x01	; 1
-
+      __boot_page_erase_short((uint16_t)(void*)address);
+    3e9a:	e0 91 00 02 	lds	r30, 0x0200
+    3e9e:	f0 91 01 02 	lds	r31, 0x0201
+    3ea2:	83 e0       	ldi	r24, 0x03	; 3
+    3ea4:	87 bf       	out	0x37, r24	; 55
+    3ea6:	e8 95       	spm
+    3ea8:	c0 e0       	ldi	r28, 0x00	; 0
+    3eaa:	d1 e0       	ldi	r29, 0x01	; 1
+      
       // While that is going on, read in page contents
       bufPtr = buff;
       do *bufPtr++ = getch();
-    3eb6:	70 d0       	rcall	.+224    	; 0x3f98 <getch>
-    3eb8:	89 93       	st	Y+, r24
+    3eac:	6d d0       	rcall	.+218    	; 0x3f88 <getch>
+    3eae:	89 93       	st	Y+, r24
       while (--length);
-    3eba:	80 91 02 02 	lds	r24, 0x0202
-    3ebe:	81 50       	subi	r24, 0x01	; 1
-    3ec0:	80 93 02 02 	sts	0x0202, r24
-    3ec4:	88 23       	and	r24, r24
-    3ec6:	b9 f7       	brne	.-18     	; 0x3eb6 <main+0xb6>
+    3eb0:	80 91 02 02 	lds	r24, 0x0202
+    3eb4:	81 50       	subi	r24, 0x01	; 1
+    3eb6:	80 93 02 02 	sts	0x0202, r24
+    3eba:	88 23       	and	r24, r24
+    3ebc:	b9 f7       	brne	.-18     	; 0x3eac <main+0xac>
 
       // Read command terminator, start reply
       verifySpace();
-    3ec8:	8b d0       	rcall	.+278    	; 0x3fe0 <verifySpace>
+    3ebe:	88 d0       	rcall	.+272    	; 0x3fd0 <verifySpace>
       
       // If only a partial page is to be programmed, the erase might not be complete.
       // So check that here
       boot_spm_busy_wait();
-    3eca:	07 b6       	in	r0, 0x37	; 55
-    3ecc:	00 fc       	sbrc	r0, 0
-    3ece:	fd cf       	rjmp	.-6      	; 0x3eca <main+0xca>
+    3ec0:	07 b6       	in	r0, 0x37	; 55
+    3ec2:	00 fc       	sbrc	r0, 0
+    3ec4:	fd cf       	rjmp	.-6      	; 0x3ec0 <main+0xc0>
       }
 #endif
 
       // Copy buffer into programming buffer
       bufPtr = buff;
       addrPtr = (uint16_t)(void*)address;
-    3ed0:	40 91 00 02 	lds	r20, 0x0200
-    3ed4:	50 91 01 02 	lds	r21, 0x0201
-    3ed8:	a0 e0       	ldi	r26, 0x00	; 0
-    3eda:	b1 e0       	ldi	r27, 0x01	; 1
+    3ec6:	40 91 00 02 	lds	r20, 0x0200
+    3eca:	50 91 01 02 	lds	r21, 0x0201
+    3ece:	a0 e0       	ldi	r26, 0x00	; 0
+    3ed0:	b1 e0       	ldi	r27, 0x01	; 1
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
-    3edc:	2c 91       	ld	r18, X
-    3ede:	30 e0       	ldi	r19, 0x00	; 0
+    3ed2:	2c 91       	ld	r18, X
+    3ed4:	30 e0       	ldi	r19, 0x00	; 0
         a |= (*bufPtr++) << 8;
-    3ee0:	11 96       	adiw	r26, 0x01	; 1
-    3ee2:	8c 91       	ld	r24, X
-    3ee4:	11 97       	sbiw	r26, 0x01	; 1
-    3ee6:	90 e0       	ldi	r25, 0x00	; 0
-    3ee8:	98 2f       	mov	r25, r24
-    3eea:	88 27       	eor	r24, r24
-    3eec:	82 2b       	or	r24, r18
-    3eee:	93 2b       	or	r25, r19
-#ifdef VIRTUAL_BOOT_PARTITION
-#define rstVect (*(uint16_t*)(0x204))
-#define wdtVect (*(uint16_t*)(0x206))
+    3ed6:	11 96       	adiw	r26, 0x01	; 1
+    3ed8:	8c 91       	ld	r24, X
+    3eda:	11 97       	sbiw	r26, 0x01	; 1
+    3edc:	90 e0       	ldi	r25, 0x00	; 0
+    3ede:	98 2f       	mov	r25, r24
+    3ee0:	88 27       	eor	r24, r24
+    3ee2:	82 2b       	or	r24, r18
+    3ee4:	93 2b       	or	r25, r19
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
 #endif
+
 /* main program starts here */
 int main(void) {
-    3ef0:	12 96       	adiw	r26, 0x02	; 2
+    3ee6:	12 96       	adiw	r26, 0x02	; 2
       ch = SPM_PAGESIZE / 2;
       do {
         uint16_t a;
         a = *bufPtr++;
         a |= (*bufPtr++) << 8;
-        boot_page_fill((uint16_t)(void*)addrPtr,a);
-    3ef2:	fa 01       	movw	r30, r20
-    3ef4:	0c 01       	movw	r0, r24
-    3ef6:	d0 92 57 00 	sts	0x0057, r13
-    3efa:	e8 95       	spm
-    3efc:	11 24       	eor	r1, r1
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+    3ee8:	fa 01       	movw	r30, r20
+    3eea:	0c 01       	movw	r0, r24
+    3eec:	d7 be       	out	0x37, r13	; 55
+    3eee:	e8 95       	spm
+    3ef0:	11 24       	eor	r1, r1
         addrPtr += 2;
-    3efe:	4e 5f       	subi	r20, 0xFE	; 254
-    3f00:	5f 4f       	sbci	r21, 0xFF	; 255
+    3ef2:	4e 5f       	subi	r20, 0xFE	; 254
+    3ef4:	5f 4f       	sbci	r21, 0xFF	; 255
       } while (--ch);
-    3f02:	f1 e0       	ldi	r31, 0x01	; 1
-    3f04:	a0 38       	cpi	r26, 0x80	; 128
-    3f06:	bf 07       	cpc	r27, r31
-    3f08:	49 f7       	brne	.-46     	; 0x3edc <main+0xdc>
+    3ef6:	f1 e0       	ldi	r31, 0x01	; 1
+    3ef8:	a0 38       	cpi	r26, 0x80	; 128
+    3efa:	bf 07       	cpc	r27, r31
+    3efc:	51 f7       	brne	.-44     	; 0x3ed2 <main+0xd2>
       
       // Write from programming buffer
-      boot_page_write((uint16_t)(void*)address);
-    3f0a:	e0 91 00 02 	lds	r30, 0x0200
-    3f0e:	f0 91 01 02 	lds	r31, 0x0201
-    3f12:	e0 92 57 00 	sts	0x0057, r14
-    3f16:	e8 95       	spm
+      __boot_page_write_short((uint16_t)(void*)address);
+    3efe:	e0 91 00 02 	lds	r30, 0x0200
+    3f02:	f0 91 01 02 	lds	r31, 0x0201
+    3f06:	f7 be       	out	0x37, r15	; 55
+    3f08:	e8 95       	spm
       boot_spm_busy_wait();
-    3f18:	07 b6       	in	r0, 0x37	; 55
-    3f1a:	00 fc       	sbrc	r0, 0
-    3f1c:	fd cf       	rjmp	.-6      	; 0x3f18 <main+0x118>
+    3f0a:	07 b6       	in	r0, 0x37	; 55
+    3f0c:	00 fc       	sbrc	r0, 0
+    3f0e:	fd cf       	rjmp	.-6      	; 0x3f0a <main+0x10a>
 
 #if defined(RWWSRE)
       // Reenable read access to flash
       boot_rww_enable();
-    3f1e:	f0 92 57 00 	sts	0x0057, r15
-    3f22:	e8 95       	spm
-    3f24:	27 c0       	rjmp	.+78     	; 0x3f74 <main+0x174>
+    3f10:	e7 be       	out	0x37, r14	; 55
+    3f12:	e8 95       	spm
+    3f14:	27 c0       	rjmp	.+78     	; 0x3f64 <main+0x164>
 #endif
 
     }
     /* Read memory block mode, length is big endian.  */
     else if(ch == STK_READ_PAGE) {
-    3f26:	84 37       	cpi	r24, 0x74	; 116
-    3f28:	b9 f4       	brne	.+46     	; 0x3f58 <main+0x158>
+    3f16:	84 37       	cpi	r24, 0x74	; 116
+    3f18:	b9 f4       	brne	.+46     	; 0x3f48 <main+0x148>
       // READ PAGE - we only read flash
       getLen();
-    3f2a:	4a d0       	rcall	.+148    	; 0x3fc0 <getLen>
+    3f1a:	4a d0       	rcall	.+148    	; 0x3fb0 <getLen>
       verifySpace();
-    3f2c:	59 d0       	rcall	.+178    	; 0x3fe0 <verifySpace>
-        else ch = pgm_read_byte_near(address);
+    3f1c:	59 d0       	rcall	.+178    	; 0x3fd0 <verifySpace>
+        putch(result);
         address++;
-        putch(ch);
-      } while (--length);
+      }
+      while (--length);
 #else
       do putch(pgm_read_byte_near(address++));
-    3f2e:	e0 91 00 02 	lds	r30, 0x0200
-    3f32:	f0 91 01 02 	lds	r31, 0x0201
-    3f36:	31 96       	adiw	r30, 0x01	; 1
-    3f38:	f0 93 01 02 	sts	0x0201, r31
-    3f3c:	e0 93 00 02 	sts	0x0200, r30
-    3f40:	31 97       	sbiw	r30, 0x01	; 1
-    3f42:	e4 91       	lpm	r30, Z+
-    3f44:	8e 2f       	mov	r24, r30
-    3f46:	19 d0       	rcall	.+50     	; 0x3f7a <putch>
+    3f1e:	e0 91 00 02 	lds	r30, 0x0200
+    3f22:	f0 91 01 02 	lds	r31, 0x0201
+    3f26:	31 96       	adiw	r30, 0x01	; 1
+    3f28:	f0 93 01 02 	sts	0x0201, r31
+    3f2c:	e0 93 00 02 	sts	0x0200, r30
+    3f30:	31 97       	sbiw	r30, 0x01	; 1
+    3f32:	e4 91       	lpm	r30, Z+
+    3f34:	8e 2f       	mov	r24, r30
+    3f36:	19 d0       	rcall	.+50     	; 0x3f6a <putch>
       while (--length);
-    3f48:	80 91 02 02 	lds	r24, 0x0202
-    3f4c:	81 50       	subi	r24, 0x01	; 1
-    3f4e:	80 93 02 02 	sts	0x0202, r24
-    3f52:	88 23       	and	r24, r24
-    3f54:	61 f7       	brne	.-40     	; 0x3f2e <main+0x12e>
-    3f56:	0e c0       	rjmp	.+28     	; 0x3f74 <main+0x174>
+    3f38:	80 91 02 02 	lds	r24, 0x0202
+    3f3c:	81 50       	subi	r24, 0x01	; 1
+    3f3e:	80 93 02 02 	sts	0x0202, r24
+    3f42:	88 23       	and	r24, r24
+    3f44:	61 f7       	brne	.-40     	; 0x3f1e <main+0x11e>
+    3f46:	0e c0       	rjmp	.+28     	; 0x3f64 <main+0x164>
+#endif
 #endif
     }
 
     /* Get device signature bytes  */
     else if(ch == STK_READ_SIGN) {
-    3f58:	85 37       	cpi	r24, 0x75	; 117
-    3f5a:	39 f4       	brne	.+14     	; 0x3f6a <main+0x16a>
+    3f48:	85 37       	cpi	r24, 0x75	; 117
+    3f4a:	39 f4       	brne	.+14     	; 0x3f5a <main+0x15a>
       // READ SIGN - return what Avrdude wants to hear
       verifySpace();
-    3f5c:	41 d0       	rcall	.+130    	; 0x3fe0 <verifySpace>
+    3f4c:	41 d0       	rcall	.+130    	; 0x3fd0 <verifySpace>
       putch(SIGNATURE_0);
-    3f5e:	8e e1       	ldi	r24, 0x1E	; 30
-    3f60:	0c d0       	rcall	.+24     	; 0x3f7a <putch>
+    3f4e:	8e e1       	ldi	r24, 0x1E	; 30
+    3f50:	0c d0       	rcall	.+24     	; 0x3f6a <putch>
       putch(SIGNATURE_1);
-    3f62:	84 e9       	ldi	r24, 0x94	; 148
-    3f64:	0a d0       	rcall	.+20     	; 0x3f7a <putch>
+    3f52:	84 e9       	ldi	r24, 0x94	; 148
+    3f54:	0a d0       	rcall	.+20     	; 0x3f6a <putch>
       putch(SIGNATURE_2);
-    3f66:	86 e0       	ldi	r24, 0x06	; 6
-    3f68:	96 cf       	rjmp	.-212    	; 0x3e96 <main+0x96>
+    3f56:	86 e0       	ldi	r24, 0x06	; 6
+    3f58:	9a cf       	rjmp	.-204    	; 0x3e8e <main+0x8e>
     }
     else if (ch == 'Q') {
-    3f6a:	81 35       	cpi	r24, 0x51	; 81
-    3f6c:	11 f4       	brne	.+4      	; 0x3f72 <main+0x172>
+    3f5a:	81 35       	cpi	r24, 0x51	; 81
+    3f5c:	11 f4       	brne	.+4      	; 0x3f62 <main+0x162>
       // Adaboot no-wait mod
       watchdogConfig(WATCHDOG_16MS);
-    3f6e:	88 e0       	ldi	r24, 0x08	; 8
-    3f70:	2c d0       	rcall	.+88     	; 0x3fca <watchdogConfig>
+    3f5e:	88 e0       	ldi	r24, 0x08	; 8
+    3f60:	2c d0       	rcall	.+88     	; 0x3fba <watchdogConfig>
       verifySpace();
     }
     else {
       // This covers the response to commands like STK_ENTER_PROGMODE
       verifySpace();
-    3f72:	36 d0       	rcall	.+108    	; 0x3fe0 <verifySpace>
+    3f62:	36 d0       	rcall	.+108    	; 0x3fd0 <verifySpace>
     }
     putch(STK_OK);
-    3f74:	80 e1       	ldi	r24, 0x10	; 16
-    3f76:	01 d0       	rcall	.+2      	; 0x3f7a <putch>
-    3f78:	63 cf       	rjmp	.-314    	; 0x3e40 <main+0x40>
+    3f64:	80 e1       	ldi	r24, 0x10	; 16
+    3f66:	01 d0       	rcall	.+2      	; 0x3f6a <putch>
+    3f68:	6b cf       	rjmp	.-298    	; 0x3e40 <main+0x40>
 
-00003f7a <putch>:
+00003f6a <putch>:
 void putch(char ch) {
 #ifndef SOFT_UART
   while (!(UCSR0A & _BV(UDRE0)));
   UDR0 = ch;
 #else
   __asm__ __volatile__ (
-    3f7a:	2a e0       	ldi	r18, 0x0A	; 10
-    3f7c:	30 e0       	ldi	r19, 0x00	; 0
-    3f7e:	80 95       	com	r24
-    3f80:	08 94       	sec
-    3f82:	10 f4       	brcc	.+4      	; 0x3f88 <putch+0xe>
-    3f84:	59 98       	cbi	0x0b, 1	; 11
-    3f86:	02 c0       	rjmp	.+4      	; 0x3f8c <putch+0x12>
-    3f88:	59 9a       	sbi	0x0b, 1	; 11
-    3f8a:	00 00       	nop
-    3f8c:	15 d0       	rcall	.+42     	; 0x3fb8 <uartDelay>
-    3f8e:	14 d0       	rcall	.+40     	; 0x3fb8 <uartDelay>
-    3f90:	86 95       	lsr	r24
-    3f92:	2a 95       	dec	r18
-    3f94:	b1 f7       	brne	.-20     	; 0x3f82 <putch+0x8>
+    3f6a:	2a e0       	ldi	r18, 0x0A	; 10
+    3f6c:	30 e0       	ldi	r19, 0x00	; 0
+    3f6e:	80 95       	com	r24
+    3f70:	08 94       	sec
+    3f72:	10 f4       	brcc	.+4      	; 0x3f78 <putch+0xe>
+    3f74:	59 98       	cbi	0x0b, 1	; 11
+    3f76:	02 c0       	rjmp	.+4      	; 0x3f7c <putch+0x12>
+    3f78:	59 9a       	sbi	0x0b, 1	; 11
+    3f7a:	00 00       	nop
+    3f7c:	15 d0       	rcall	.+42     	; 0x3fa8 <uartDelay>
+    3f7e:	14 d0       	rcall	.+40     	; 0x3fa8 <uartDelay>
+    3f80:	86 95       	lsr	r24
+    3f82:	2a 95       	dec	r18
+    3f84:	b1 f7       	brne	.-20     	; 0x3f72 <putch+0x8>
       [uartBit] "I" (UART_TX_BIT)
     :
       "r25"
   );
 #endif
 }
-    3f96:	08 95       	ret
+    3f86:	08 95       	ret
 
-00003f98 <getch>:
+00003f88 <getch>:
   return getch();
 }
 
 // Watchdog functions. These are only safe with interrupts turned off.
 void watchdogReset() {
   __asm__ __volatile__ (
-    3f98:	a8 95       	wdr
+    3f88:	a8 95       	wdr
 #ifdef LED_DATA_FLASH
   LED_PIN |= _BV(LED);
 #endif
 
   return ch;
 }
-    3f9a:	29 e0       	ldi	r18, 0x09	; 9
-    3f9c:	30 e0       	ldi	r19, 0x00	; 0
-    3f9e:	48 99       	sbic	0x09, 0	; 9
-    3fa0:	fe cf       	rjmp	.-4      	; 0x3f9e <getch+0x6>
-    3fa2:	0a d0       	rcall	.+20     	; 0x3fb8 <uartDelay>
-    3fa4:	09 d0       	rcall	.+18     	; 0x3fb8 <uartDelay>
-    3fa6:	08 d0       	rcall	.+16     	; 0x3fb8 <uartDelay>
-    3fa8:	88 94       	clc
-    3faa:	48 99       	sbic	0x09, 0	; 9
-    3fac:	08 94       	sec
-    3fae:	2a 95       	dec	r18
-    3fb0:	11 f0       	breq	.+4      	; 0x3fb6 <getch+0x1e>
-    3fb2:	87 95       	ror	r24
-    3fb4:	f7 cf       	rjmp	.-18     	; 0x3fa4 <getch+0xc>
-    3fb6:	08 95       	ret
-
-00003fb8 <uartDelay>:
+    3f8a:	29 e0       	ldi	r18, 0x09	; 9
+    3f8c:	30 e0       	ldi	r19, 0x00	; 0
+    3f8e:	48 99       	sbic	0x09, 0	; 9
+    3f90:	fe cf       	rjmp	.-4      	; 0x3f8e <getch+0x6>
+    3f92:	0a d0       	rcall	.+20     	; 0x3fa8 <uartDelay>
+    3f94:	09 d0       	rcall	.+18     	; 0x3fa8 <uartDelay>
+    3f96:	08 d0       	rcall	.+16     	; 0x3fa8 <uartDelay>
+    3f98:	88 94       	clc
+    3f9a:	48 99       	sbic	0x09, 0	; 9
+    3f9c:	08 94       	sec
+    3f9e:	2a 95       	dec	r18
+    3fa0:	11 f0       	breq	.+4      	; 0x3fa6 <getch+0x1e>
+    3fa2:	87 95       	ror	r24
+    3fa4:	f7 cf       	rjmp	.-18     	; 0x3f94 <getch+0xc>
+    3fa6:	08 95       	ret
+
+00003fa8 <uartDelay>:
 #if UART_B_VALUE > 255
 #error Baud rate too slow for soft UART
 #endif
 
 void uartDelay() {
   __asm__ __volatile__ (
-    3fb8:	98 e0       	ldi	r25, 0x08	; 8
-    3fba:	9a 95       	dec	r25
-    3fbc:	f1 f7       	brne	.-4      	; 0x3fba <uartDelay+0x2>
-    3fbe:	08 95       	ret
+    3fa8:	98 e0       	ldi	r25, 0x08	; 8
+    3faa:	9a 95       	dec	r25
+    3fac:	f1 f7       	brne	.-4      	; 0x3faa <uartDelay+0x2>
+    3fae:	08 95       	ret
 
-00003fc0 <getLen>:
+00003fb0 <getLen>:
   } while (--count);
 }
 #endif
 
 uint8_t getLen() {
   getch();
-    3fc0:	eb df       	rcall	.-42     	; 0x3f98 <getch>
+    3fb0:	eb df       	rcall	.-42     	; 0x3f88 <getch>
   length = getch();
-    3fc2:	ea df       	rcall	.-44     	; 0x3f98 <getch>
-    3fc4:	80 93 02 02 	sts	0x0202, r24
+    3fb2:	ea df       	rcall	.-44     	; 0x3f88 <getch>
+    3fb4:	80 93 02 02 	sts	0x0202, r24
   return getch();
 }
-    3fc8:	e7 cf       	rjmp	.-50     	; 0x3f98 <getch>
+    3fb8:	e7 cf       	rjmp	.-50     	; 0x3f88 <getch>
 
-00003fca <watchdogConfig>:
+00003fba <watchdogConfig>:
     "wdr\n"
   );
 }
 
 void watchdogConfig(uint8_t x) {
   WDTCSR = _BV(WDCE) | _BV(WDE);
-    3fca:	e0 e6       	ldi	r30, 0x60	; 96
-    3fcc:	f0 e0       	ldi	r31, 0x00	; 0
-    3fce:	98 e1       	ldi	r25, 0x18	; 24
-    3fd0:	90 83       	st	Z, r25
+    3fba:	e0 e6       	ldi	r30, 0x60	; 96
+    3fbc:	f0 e0       	ldi	r31, 0x00	; 0
+    3fbe:	98 e1       	ldi	r25, 0x18	; 24
+    3fc0:	90 83       	st	Z, r25
   WDTCSR = x;
-    3fd2:	80 83       	st	Z, r24
+    3fc2:	80 83       	st	Z, r24
 }
-    3fd4:	08 95       	ret
+    3fc4:	08 95       	ret
 
-00003fd6 <appStart>:
+00003fc6 <appStart>:
 
 void appStart() {
   watchdogConfig(WATCHDOG_OFF);
-    3fd6:	80 e0       	ldi	r24, 0x00	; 0
-    3fd8:	f8 df       	rcall	.-16     	; 0x3fca <watchdogConfig>
+    3fc6:	80 e0       	ldi	r24, 0x00	; 0
+    3fc8:	f8 df       	rcall	.-16     	; 0x3fba <watchdogConfig>
   __asm__ __volatile__ (
-    3fda:	ee 27       	eor	r30, r30
-    3fdc:	ff 27       	eor	r31, r31
-    3fde:	09 94       	ijmp
+    3fca:	ee 27       	eor	r30, r30
+    3fcc:	ff 27       	eor	r31, r31
+    3fce:	09 94       	ijmp
 
-00003fe0 <verifySpace>:
+00003fd0 <verifySpace>:
   do getch(); while (--count);
   verifySpace();
 }
 
 void verifySpace() {
   if (getch() != CRC_EOP) appStart();
-    3fe0:	db df       	rcall	.-74     	; 0x3f98 <getch>
-    3fe2:	80 32       	cpi	r24, 0x20	; 32
-    3fe4:	09 f0       	breq	.+2      	; 0x3fe8 <verifySpace+0x8>
-    3fe6:	f7 df       	rcall	.-18     	; 0x3fd6 <appStart>
+    3fd0:	db df       	rcall	.-74     	; 0x3f88 <getch>
+    3fd2:	80 32       	cpi	r24, 0x20	; 32
+    3fd4:	09 f0       	breq	.+2      	; 0x3fd8 <verifySpace+0x8>
+    3fd6:	f7 df       	rcall	.-18     	; 0x3fc6 <appStart>
   putch(STK_INSYNC);
-    3fe8:	84 e1       	ldi	r24, 0x14	; 20
+    3fd8:	84 e1       	ldi	r24, 0x14	; 20
 }
-    3fea:	c7 cf       	rjmp	.-114    	; 0x3f7a <putch>
+    3fda:	c7 cf       	rjmp	.-114    	; 0x3f6a <putch>
     ::[count] "M" (UART_B_VALUE)
   );
 }
 #endif
 
 void getNch(uint8_t count) {
-    3fec:	1f 93       	push	r17
-    3fee:	18 2f       	mov	r17, r24
+    3fdc:	1f 93       	push	r17
+    3fde:	18 2f       	mov	r17, r24
 
-00003ff0 <getNch>:
+00003fe0 <getNch>:
   do getch(); while (--count);
-    3ff0:	d3 df       	rcall	.-90     	; 0x3f98 <getch>
-    3ff2:	11 50       	subi	r17, 0x01	; 1
-    3ff4:	e9 f7       	brne	.-6      	; 0x3ff0 <getNch>
+    3fe0:	d3 df       	rcall	.-90     	; 0x3f88 <getch>
+    3fe2:	11 50       	subi	r17, 0x01	; 1
+    3fe4:	e9 f7       	brne	.-6      	; 0x3fe0 <getNch>
   verifySpace();
-    3ff6:	f4 df       	rcall	.-24     	; 0x3fe0 <verifySpace>
+    3fe6:	f4 df       	rcall	.-24     	; 0x3fd0 <verifySpace>
 }
-    3ff8:	1f 91       	pop	r17
-    3ffa:	08 95       	ret
+    3fe8:	1f 91       	pop	r17
+    3fea:	08 95       	ret