diff --git a/LUFA/Drivers/USB/Class/Host/StillImage.c b/LUFA/Drivers/USB/Class/Host/StillImage.c
index 67d5cdee28b4e8e957a7098d566aaf05565f216a..615094dbfd5fb814201721607b317e1cce2738cd 100644
--- a/LUFA/Drivers/USB/Class/Host/StillImage.c
+++ b/LUFA/Drivers/USB/Class/Host/StillImage.c
@@ -233,8 +233,6 @@ static uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SII
 		  Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK);
 		
 		Pipe_ClearIN();
-		
-		PIMAHeader->Code &= 0x0000000F;
 	}
 	
 	Pipe_Freeze();
diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt
index 791a170603e699b30a1b226226385550145a5111..a8502f35749ec76e1db0d9ee2c7e3caad017e5ef 100644
--- a/LUFA/ManPages/ChangeLog.txt
+++ b/LUFA/ManPages/ChangeLog.txt
@@ -61,6 +61,7 @@
   *  - Fixed the definition of the Endpoint_BytesInEndpoint() macro for the U4 series AVR parts
   *  - Fixed MIDI host Class driver MIDI_Host_SendEventPacket() routine not properly checking for Pipe ready before writing
   *  - Fixed use of deprecated struct initializers, removed library unused parameter warnings when compiled with -Wextra enabled
+  *  - Fixed Still Image Host Class driver truncating the PIMA response code (thanks to Daniel)
   *
   *  \section Sec_ChangeLog091122 Version 091122
   *
diff --git a/Projects/AVRISP/Lib/NVMTarget.c b/Projects/AVRISP/Lib/NVMTarget.c
index d84ae6b8580d8a36230c37cbb0079ae1437c1342..b6922d5e5e42ad9c37a841060e9da3c834d8ae6c 100644
--- a/Projects/AVRISP/Lib/NVMTarget.c
+++ b/Projects/AVRISP/Lib/NVMTarget.c
@@ -161,41 +161,35 @@ bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t Re
 	NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
 	PDITarget_SendByte(NVM_CMD_READNVM);
 
-	/* Send the address of the first location to read from - this also primes the internal address
-	 * counters so that we can use the REPEAT command later to save on overhead for multiple bytes */
-	PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
+	/* Load the PDI pointer register with the start address we want to read from */
+	PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES);
 	NVMTarget_SendAddress(ReadAddress);
-	*ReadBuffer = PDITarget_ReceiveByte();
 
-	/* Check to see if we are reading more than a single byte */
-	if (ReadSize > 1)
-	{
-		/* Send the REPEAT command with the specified number of bytes remaining to read */
-		PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_2BYTES);
-		PDITarget_SendByte(ReadSize &  0xFF);
-		PDITarget_SendByte(ReadSize >> 8);
+	/* Send the REPEAT command with the specified number of bytes to read */
+	PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_2BYTES);
+	PDITarget_SendByte(ReadSize &  0xFF);
+	PDITarget_SendByte(ReadSize >> 8);
 		
-		/* Send a LD command with indirect access and postincrement to read out the remaining bytes */
-		PDITarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
-		for (uint16_t i = 0; i < ReadSize; i++)
-		  *(ReadBuffer++) = PDITarget_ReceiveByte();
-	}
+	/* Send a LD command with indirect access and postincrement to read out the bytes */
+	PDITarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
+	for (uint16_t i = 0; i < ReadSize; i++)
+	  *(ReadBuffer++) = PDITarget_ReceiveByte();
 	
 	return true;
 }
 
 /** Writes byte addressed memory to the target's memory spaces.
  *
- *  \param[in]  WriteCommand      Command to send to the device to write each memory page
- *  \param[in]  WriteAddress      Start address to write to within the target's address space
- *  \param[in]  WriteBuffer       Buffer to source data from
- *  \param[in]  WriteSize         Number of bytes to write
+ *  \param[in]  WriteCommand  Command to send to the device to write each memory byte
+ *  \param[in]  WriteAddress  Start address to write to within the target's address space
+ *  \param[in]  WriteBuffer   Buffer to source data from
+ *  \param[in]  WriteSize     Number of bytes to write
  *
  *  \return Boolean true if the command sequence complete sucessfully
  */
 bool NVMTarget_WriteByteMemory(uint8_t WriteCommand, uint32_t WriteAddress, uint8_t* WriteBuffer, uint16_t WriteSize)
 {
-	for (uint8_t i = 0; i < WriteSize; i++)
+	for (uint16_t i = 0; i < WriteSize; i++)
 	{
 		/* Wait until the NVM controller is no longer busy */
 		if (!(NVMTarget_WaitWhileNVMControllerBusy()))
@@ -215,6 +209,92 @@ bool NVMTarget_WriteByteMemory(uint8_t WriteCommand, uint32_t WriteAddress, uint
 	return true;
 }
 
+/** Writes page addressed memory to the target's memory spaces.
+ *
+ *  \param[in]  WriteBuffCommand  Command to send to the device to write a byte to the memory page buffer
+ *  \param[in]  EraseBuffCommand  Command to send to the device to erase the memory page buffer
+ *  \param[in]  WritePageCommand  Command to send to the device to write the page buffer to the destination memory
+ *  \param[in]  PageMode          Bitfield indicating what operations need to be executed on the specified page
+ *  \param[in]  WriteAddress      Start address to write the page data to within the target's address space
+ *  \param[in]  WriteBuffer       Buffer to source data from
+ *  \param[in]  WriteSize         Number of bytes to write
+ *
+ *  \return Boolean true if the command sequence complete sucessfully
+ */
+bool NVMTarget_WritePageMemory(uint8_t WriteBuffCommand, uint8_t EraseBuffCommand, uint8_t WritePageCommand,
+                               uint8_t PageMode, uint32_t WriteAddress, uint8_t* WriteBuffer, uint16_t WriteSize)
+{
+	if (PageMode & XPRG_PAGEMODE_ERASE)
+	{
+		/* Wait until the NVM controller is no longer busy */
+		if (!(NVMTarget_WaitWhileNVMControllerBusy()))
+		  return false;
+
+		/* Send the memory buffer erase command to the target */
+		PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
+		NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
+		PDITarget_SendByte(EraseBuffCommand);
+
+		/* Set CMDEX bit in NVM CTRLA register to start the buffer erase */
+		PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
+		NVMTarget_SendNVMRegAddress(NVM_REG_CTRLA);
+		PDITarget_SendByte(1 << 0);
+	}
+
+	if (WriteSize)
+	{
+		/* Wait until the NVM controller is no longer busy */
+		if (!(NVMTarget_WaitWhileNVMControllerBusy()))
+		  return false;
+
+		/* Send the memory buffer write command to the target */
+		PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
+		NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
+		PDITarget_SendByte(WriteBuffCommand);
+
+		/* Load the PDI pointer register with the start address we want to write to */
+		PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES);
+		NVMTarget_SendAddress(WriteAddress);
+
+		/* Send the REPEAT command with the specified number of bytes to write */
+		PDITarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_2BYTES);
+		PDITarget_SendByte(WriteSize &  0xFF);
+		PDITarget_SendByte(WriteSize >> 8);
+			
+		/* Send a ST command with indirect access and postincrement to write the bytes */
+		PDITarget_SendByte(PDI_CMD_ST | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
+		for (uint16_t i = 0; i < WriteSize; i++)
+		  PDITarget_SendByte(*(WriteBuffer++));
+
+		// TEMP
+		PDITarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
+		NVMTarget_SendNVMRegAddress(NVM_REG_STATUS);
+		GPIOR0 = PDITarget_ReceiveByte();
+		if (!(GPIOR0 & (1 << 0)))
+		  JTAG_DEBUG_POINT();
+		// END TEMP
+	}
+	
+	if (PageMode & XPRG_PAGEMODE_WRITE)
+	{
+		/* Wait until the NVM controller is no longer busy */
+		if (!(NVMTarget_WaitWhileNVMControllerBusy()))
+		  return false;
+
+		/* Send the memory write command to the target */
+		PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
+		NVMTarget_SendNVMRegAddress(NVM_REG_CMD);
+		PDITarget_SendByte(WritePageCommand);
+		
+		/* Send the address of the first page location to write the memory page */
+		PDITarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
+		NVMTarget_SendAddress(WriteAddress);
+		PDITarget_SendByte(0x00);
+	}
+
+	return true;
+}
+
 /** Erases a specific memory space of the target.
  *
  *  \param[in] EraseCommand  NVM erase command to send to the device
diff --git a/Projects/AVRISP/Lib/NVMTarget.h b/Projects/AVRISP/Lib/NVMTarget.h
index dea9ff3decd644c9819045f1574b598eb0119cb7..3608fcb350b951a9aaa19f4a48287eef7d53cb62 100644
--- a/Projects/AVRISP/Lib/NVMTarget.h
+++ b/Projects/AVRISP/Lib/NVMTarget.h
@@ -74,8 +74,8 @@
 		#define NVM_CMD_NOOP                   0x00
 		#define NVM_CMD_CHIPERASE              0x40
 		#define NVM_CMD_READNVM                0x43
-		#define NVM_CMD_LOADFLASHBUFF          0x23
-		#define NVM_CMD_ERASEFLASHBUFF         0x26
+		#define NVM_CMD_LOADFLASHPAGEBUFF      0x23
+		#define NVM_CMD_ERASEFLASHPAGEBUFF     0x26
 		#define NVM_CMD_ERASEFLASHPAGE         0x2B
 		#define NVM_CMD_FLASHPAGEWRITE         0x2E
 		#define NVM_CMD_ERASEWRITEFLASH        0x2F
@@ -113,6 +113,8 @@
 		bool NVMTarget_ReadMemory(uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize);
 		bool NVMTarget_WriteByteMemory(uint8_t WriteCommand, uint32_t WriteAddress, uint8_t* WriteBuffer,
 		                               uint16_t WriteSize);
+		bool NVMTarget_WritePageMemory(uint8_t WriteBuffCommand, uint8_t EraseBuffCommand, uint8_t WritePageCommand,
+		                               uint8_t PageMode, uint32_t WriteAddress, uint8_t* WriteBuffer, uint16_t WriteSize);
 		bool NVMTarget_EraseMemory(uint8_t EraseCommand, uint32_t Address);
 
 #endif
diff --git a/Projects/AVRISP/Lib/PDIProtocol.c b/Projects/AVRISP/Lib/PDIProtocol.c
index 36aa3b4c5c9740912cf6c0699da20801f79fc5dc..aa03fc494803260961af99d5e2676ab7fd477f9d 100644
--- a/Projects/AVRISP/Lib/PDIProtocol.c
+++ b/Projects/AVRISP/Lib/PDIProtocol.c
@@ -201,7 +201,7 @@ static void PDIProtocol_WriteMemory(void)
 		uint8_t  PageMode;
 		uint32_t Address;
 		uint16_t Length;
-		uint8_t  ProgData[512];
+		uint8_t  ProgData[256];
 	} WriteMemory_XPROG_Params;
 	
 	Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) -
@@ -215,24 +215,37 @@ static void PDIProtocol_WriteMemory(void)
 
 
 	uint8_t WriteCommand     = NVM_CMD_NOOP;
-	uint8_t WritePageCommand = NVM_CMD_NOOP;
+	uint8_t WriteBuffCommand = NVM_CMD_NOOP;
+	uint8_t EraseBuffCommand = NVM_CMD_NOOP;
 	bool    PagedMemory      = false;
 	
 	if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_APPL)
 	{
-		PagedMemory = true;
+		WriteCommand     = NVM_CMD_ERASEWRITEFLASH;
+		WriteBuffCommand = NVM_CMD_LOADFLASHPAGEBUFF;
+		EraseBuffCommand = NVM_CMD_ERASEFLASHPAGEBUFF;
+		PagedMemory      = true;
 	}
 	else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_BOOT)
 	{
-		PagedMemory = true;
+		WriteCommand     = NVM_CMD_ERASEWRITEFLASH;
+		WriteBuffCommand = NVM_CMD_LOADFLASHPAGEBUFF;
+		EraseBuffCommand = NVM_CMD_ERASEFLASHPAGEBUFF;
+		PagedMemory      = true;
 	}
 	else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_EEPROM)
 	{
-		PagedMemory = true;
+		WriteCommand     = NVM_CMD_ERASEWRITEEEPROMPAGE;
+		WriteBuffCommand = NVM_CMD_LOADEEPROMPAGEBUFF;
+		EraseBuffCommand = NVM_CMD_ERASEEEPROMPAGEBUFF;
+		PagedMemory      = true;
 	}
 	else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_USERSIG)
 	{
-		PagedMemory = true;
+		WriteCommand     = NVM_CMD_WRITEUSERSIG;
+		WriteBuffCommand = NVM_CMD_LOADFLASHPAGEBUFF;
+		EraseBuffCommand = NVM_CMD_ERASEFLASHPAGEBUFF;
+		PagedMemory      = true;
 	}
 	else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_FUSE)
 	{
@@ -245,7 +258,12 @@ static void PDIProtocol_WriteMemory(void)
 	
 	if (PagedMemory)
 	{
-
+		if (!(NVMTarget_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand, 
+		                                WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address,
+		                                WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length)))
+		{
+			ReturnStatus = XPRG_ERR_TIMEOUT;
+		}
 	}
 	else
 	{
diff --git a/Projects/AVRISP/Lib/PDIProtocol.h b/Projects/AVRISP/Lib/PDIProtocol.h
index 490e14bf5395d0b81dab8a0ea9b840315275a9d5..127f0866ea663464e95a21895477d0ffd3e328b2 100644
--- a/Projects/AVRISP/Lib/PDIProtocol.h
+++ b/Projects/AVRISP/Lib/PDIProtocol.h
@@ -97,6 +97,9 @@
 		
 		#define XPRG_PROTOCOL_PDI                   0x00
 		#define XPRG_PROTOCOL_JTAG                  0x01
+		
+		#define XPRG_PAGEMODE_WRITE                 (1 << 0)
+		#define XPRG_PAGEMODE_ERASE                 (1 << 1)
 	
 	/* External Variables: */
 		extern uint32_t XPROG_Param_NVMBase;