diff --git a/minichlink/Makefile b/minichlink/Makefile
index 0bd37d30107a55504282a51cafd0406d905875f9..e90cca96cf0b361db14d32b2c54619de2e217ac6 100644
--- a/minichlink/Makefile
+++ b/minichlink/Makefile
@@ -1,9 +1,6 @@
 TOOLS:=minichlink minichlink.so
 
-all : $(TOOLS)
-
 CFLAGS:=-O0 -g3 -Wall
-
 C_S:=minichlink.c pgm-wch-linke.c pgm-esp32s2-ch32xx.c nhc-link042.c minichgdb.c
 
 # General Note: To use with GDB, gdb-multiarch
@@ -11,7 +8,9 @@ C_S:=minichlink.c pgm-wch-linke.c pgm-esp32s2-ch32xx.c nhc-link042.c minichgdb.c
 # target remote :2345
 
 ifeq ($(OS),Windows_NT)
-	LDFLAGS:=-lpthread -lusb-1.0 -lsetupapi
+	LDFLAGS:=-L. -lpthread -lusb-1.0 -lsetupapi -lws2_32
+	CFLAGS:=-Os -s -Wall
+	TOOLS:=minichlink.exe minichlink.dll
 else
 	OS_NAME := $(shell uname -s | tr A-Z a-z)
 	ifeq ($(OS_NAME),linux)
@@ -26,9 +25,11 @@ else
 	endif
 endif
 
+all : $(TOOLS)
+
 # will need mingw-w64-x86-64-dev gcc-mingw-w64-x86-64
 minichlink.exe : $(C_S)
-	x86_64-w64-mingw32-gcc -o $@ $^ -Os -s -lsetupapi ./libusb-1.0.dll
+	x86_64-w64-mingw32-gcc -o $@ $^ $(LDFLAGS) $(CFLAGS)
 
 minichlink : $(C_S)
 	gcc -o $@ $^ $(LDFLAGS) $(CFLAGS) $(INCS)
@@ -36,6 +37,9 @@ minichlink : $(C_S)
 minichlink.so : $(C_S)
 	gcc -o $@ $^ $(LDFLAGS) $(CFLAGS) $(INCS) -shared -fPIC
 
+minichlink.dll : $(C_S)
+	x86_64-w64-mingw32-gcc -o $@ $^ $(LDFLAGS) $(CFLAGS) $(INCS) -shared
+
 install_udev_rules :
 	cp 99-WCH-LinkE.rules /etc/udev/rules.d/
 	service udev restart
diff --git a/minichlink/microgdbstub.h b/minichlink/microgdbstub.h
index bf04bc17c830ca15929d2aa123c1e0e89ff6c938..b94c8c59a0425b9176a6cb0f6841c0ef44802526 100644
--- a/minichlink/microgdbstub.h
+++ b/minichlink/microgdbstub.h
@@ -55,8 +55,29 @@ void MicroGDBStubHandleClientData( void * dev, const uint8_t * rxdata, int len )
 #include <stdio.h>
 #include <stdlib.h>
 
-uint16_t htons(uint16_t hostshort);
-uint32_t htonl(uint32_t hostlong);
+#ifdef MICROGDBSTUB_SOCKETS
+#if defined( WIN32 ) || defined( _WIN32 )
+#include <winsock2.h>
+#if !defined( POLLIN ) 
+typedef struct pollfd { SOCKET fd; SHORT  events; SHORT  revents; };
+#define POLLIN 0x0001
+#define POLLERR 0x008
+#define POLLHUP 0x010
+int WSAAPI WSAPoll(struct pollfd * fdArray, ULONG       fds, INT         timeout );
+#endif
+#define poll WSAPoll
+#define socklen_t uint32_t
+#define SHUT_RDWR SD_BOTH
+#define MSG_NOSIGNAL 0
+#else
+#define closesocket close
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/in.h>
+#include <unistd.h>
+#include <poll.h>
+#endif
+#endif
 
 char gdbbuffer[65536];
 uint8_t gdbchecksum = 0;
@@ -268,7 +289,7 @@ void HandleGDBPacket( void * dev, char * data, int len )
 		{
 			uint32_t regret;
 			if( RVReadCPURegister( dev, i, &regret ) ) goto err;
-			sprintf( cts + i * 8, "%08x", htonl( regret ) );
+			sprintf( cts + i * 8, "%08x", (uint32_t)htonl( regret ) );
 		}
 		SendReplyFull( cts );
 		break;
@@ -284,7 +305,7 @@ void HandleGDBPacket( void * dev, char * data, int len )
 			char cts[9];
 			uint32_t regret;
 			if( RVReadCPURegister( dev, regno, &regret ) ) goto err;
-			sprintf( cts, "%08x", htonl( regret ) );
+			sprintf( cts, "%08x", (uint32_t)htonl( regret ) );
 			SendReplyFull( cts );
 		}
 		break;
@@ -387,23 +408,8 @@ void MicroGDBStubHandleClientData( void * dev, const uint8_t * rxdata, int len )
 
 #ifdef MICROGDBSTUB_SOCKETS
 
-
-#ifdef WIN32
-#include <winsock2.h>
-#define socklen_t uint32_t
-#define SHUT_RDWR SD_BOTH
-#define MSG_NOSIGNAL 0
-#else
-#define closesocket close
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <linux/in.h>
-#endif
-
 #include <fcntl.h>
-#include <unistd.h>
 #include <sys/time.h>
-#include <poll.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -436,7 +442,7 @@ static int GDBListen( void * dev )
 	}
 
 	//Disable SO_LINGER (Well, enable it but turn it way down)
-#ifdef WIN32
+#if defined( WIN32 ) || defined( _WIN32 )
 	struct linger lx;
 	lx.l_onoff = 1;
 	lx.l_linger = 0;
@@ -520,7 +526,7 @@ int MicroGDBPollServer( void * dev )
 			struct   sockaddr_in tin;
 			socklen_t addrlen  = sizeof(tin);
 			memset( &tin, 0, addrlen );
-			int tsocket = accept( serverSocket, (struct sockaddr *)&tin, &addrlen );
+			int tsocket = accept( serverSocket, (struct sockaddr *)&tin, (int*)&addrlen );
 			closesocket( serverSocket );
 			serverSocket = tsocket;
 			listenMode = 2;
@@ -532,7 +538,7 @@ int MicroGDBPollServer( void * dev )
 		{
 			// Got data from a peer.
 			uint8_t buffer[16384];
-			ssize_t rx = recv( serverSocket, buffer, sizeof( buffer ), MSG_NOSIGNAL );
+			ssize_t rx = recv( serverSocket, (char*)buffer, sizeof( buffer ), MSG_NOSIGNAL );
 			if( rx == 0 )
 			{
 				MicroGDBStubHandleDisconnect( dev );
@@ -597,7 +603,7 @@ void MicroGDBStubSendReply( const void * data, int len, int docs )
 
 int MicroGDBStubStartup( void * dev )
 {
-#ifdef WIN32
+#if defined( WIN32 ) || defined( _WIN32 )
 {
     WORD wVersionRequested;
     WSADATA wsaData;
diff --git a/minichlink/minichlink.c b/minichlink/minichlink.c
index 03cabbeaf0f66d1ff5cb9c529d4892599518e737..158f375ab0304b7eb73007139fdcd2fd39bf8d23 100644
--- a/minichlink/minichlink.c
+++ b/minichlink/minichlink.c
@@ -256,9 +256,9 @@ keep_going:
 					goto unimplemented;
 				}
 
-				uint32_t datareg = SimpleReadNumberInt( argv[iarg-1], DMDATA0 );
+				uint32_t datareg = SimpleReadNumberInt( argv[iarg], DMDATA0 );
 
-				if( MCF.WriteReg32 && MCF.FlushLLCommands )
+				if( MCF.ReadReg32 && MCF.FlushLLCommands )
 				{
 					uint32_t value;
 					int ret = MCF.ReadReg32( dev, datareg, &value );
@@ -846,7 +846,6 @@ static int DefaultWriteWord( void * dev, uint32_t address_to_write, uint32_t dat
 		}
 		iss->lastwriteflags = is_flash;
 
-
 		iss->statetag = STTAG( "WRSQ" );
 		iss->currentstateval = address_to_write;
 
@@ -979,6 +978,7 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob
 			if( is_flash )
 			{
 				MCF.ReadBinaryBlob( dev, base, 64, tempblock );
+
 				MCF.Erase( dev, base, 64, 0 );
 				MCF.WriteWord( dev, 0x40022010, CR_PAGE_PG ); // THIS IS REQUIRED, (intptr_t)&FLASH->CTLR = 0x40022010
 				MCF.WriteWord( dev, 0x40022010, CR_BUF_RST | CR_PAGE_PG );  // (intptr_t)&FLASH->CTLR = 0x40022010
@@ -1044,7 +1044,7 @@ int DefaultWriteBinaryBlob( void * dev, uint32_t address_to_write, uint32_t blob
 	}
 
 	MCF.FlushLLCommands( dev );
-	MCF.DelayUS( dev, 100 ); // Why do we need this?
+	if(MCF.DelayUS) MCF.DelayUS( dev, 100 ); // Why do we need this?
 	return 0;
 timedout:
 	fprintf( stderr, "Timed out\n" );
@@ -1053,6 +1053,7 @@ timedout:
 
 static int DefaultReadWord( void * dev, uint32_t address_to_read, uint32_t * data )
 {
+	int r = 0;
 	struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal);
 
 	int autoincrement = 1;
@@ -1100,13 +1101,13 @@ static int DefaultReadWord( void * dev, uint32_t address_to_read, uint32_t * dat
 		iss->statetag = STTAG( "RDSQ" );
 		iss->currentstateval = address_to_read;
 
-		MCF.WaitForDoneOp( dev );
+		r |= MCF.WaitForDoneOp( dev );
 	}
 
 	if( iss->autoincrement )
 		iss->currentstateval += 4;
 
-	int r = MCF.ReadReg32( dev, DMDATA0, data );
+	r |= MCF.ReadReg32( dev, DMDATA0, data );
 	return r;
 }
 
@@ -1168,12 +1169,11 @@ int DefaultErase( void * dev, uint32_t address, uint32_t length, int type )
 		{
 			// Step 4:  set PAGE_ER of FLASH_CTLR(0x40022010)
 			MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_PAGE_ER ); // Actually FTER
-
 			// Step 5: Write the first address of the fast erase page to the FLASH_ADDR register.
 			MCF.WriteWord( dev, (intptr_t)&FLASH->ADDR, chunk_to_erase  );
 
 			// Step 6: Set the STAT bit of FLASH_CTLR register to '1' to initiate a fast page erase (64 bytes) action.
-			MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_STRT_Set|CR_PAGE_ER );
+			MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, CR_STRT_Set | CR_PAGE_ER );
 			if( MCF.WaitForFlash && MCF.WaitForFlash( dev ) ) return -99;
 			chunk_to_erase+=64;
 		}
@@ -1709,10 +1709,7 @@ int SetupAutomaticHighLevelFunctions( void * dev )
 	if( !MCF.VoidHighLevelState )
 		MCF.VoidHighLevelState = DefaultVoidHighLevelState;
 
-	struct InternalState * iss = malloc( sizeof( struct InternalState ) );
-	iss->statetag = 0;
-	iss->currentstateval = 0;
-	iss->autoincrement = 0;
+	struct InternalState * iss = calloc( 1, sizeof( struct InternalState ) );
 
 	((struct ProgrammerStructBase*)dev)->internal = iss;
 	return 0;
diff --git a/minichlink/minichlink.exe b/minichlink/minichlink.exe
index 0aeca0fe443026a4d437c1502dbc8cf3eee4444d..5def6b948b17d3beef6e513ac9d7a75364cbd4cd 100644
Binary files a/minichlink/minichlink.exe and b/minichlink/minichlink.exe differ
diff --git a/minichlink/pgm-wch-linke.c b/minichlink/pgm-wch-linke.c
index c1439121f82082ca13a45f294fb5b49c71ae8caa..73d8e64f8249661077fd2e25c48adc62aca5b7f2 100644
--- a/minichlink/pgm-wch-linke.c
+++ b/minichlink/pgm-wch-linke.c
@@ -19,42 +19,6 @@ struct LinkEProgrammerStruct
 #define WCHTIMEOUT 5000
 #define WCHCHECK(x) if( (status = x) ) { fprintf( stderr, "Bad USB Operation on " __FILE__ ":%d (%d)\n", __LINE__, status ); exit( status ); }
 
-const uint8_t * bootloader = (const uint8_t*)
-"\x21\x11\x22\xca\x26\xc8\x93\x77\x15\x00\x99\xcf\xb7\x06\x67\x45" \
-"\xb7\x27\x02\x40\x93\x86\x36\x12\x37\x97\xef\xcd\xd4\xc3\x13\x07" \
-"\xb7\x9a\xd8\xc3\xd4\xd3\xd8\xd3\x93\x77\x25\x00\x9d\xc7\xb7\x27" \
-"\x02\x40\x98\x4b\xad\x66\x37\x33\x00\x40\x13\x67\x47\x00\x98\xcb" \
-"\x98\x4b\x93\x86\xa6\xaa\x13\x67\x07\x04\x98\xcb\xd8\x47\x05\x8b" \
-"\x63\x16\x07\x10\x98\x4b\x6d\x9b\x98\xcb\x93\x77\x45\x00\xa9\xcb" \
-"\x93\x07\xf6\x03\x99\x83\x2e\xc0\x2d\x63\x81\x76\x3e\xc4\xb7\x32" \
-"\x00\x40\xb7\x27\x02\x40\x13\x03\xa3\xaa\xfd\x16\x98\x4b\xb7\x03" \
-"\x02\x00\x33\x67\x77\x00\x98\xcb\x02\x47\xd8\xcb\x98\x4b\x13\x67" \
-"\x07\x04\x98\xcb\xd8\x47\x05\x8b\x69\xe7\x98\x4b\x75\x8f\x98\xcb" \
-"\x02\x47\x13\x07\x07\x04\x3a\xc0\x22\x47\x7d\x17\x3a\xc4\x79\xf7" \
-"\x93\x77\x85\x00\xf1\xcf\x93\x07\xf6\x03\x2e\xc0\x99\x83\x37\x27" \
-"\x02\x40\x3e\xc4\x1c\x4b\xc1\x66\x2d\x63\xd5\x8f\x1c\xcb\x37\x07" \
-"\x00\x20\x13\x07\x07\x20\xb7\x27\x02\x40\xb7\x03\x08\x00\xb7\x32" \
-"\x00\x40\x13\x03\xa3\xaa\x94\x4b\xb3\xe6\x76\x00\x94\xcb\xd4\x47" \
-"\x85\x8a\xf5\xfe\x82\x46\xba\x84\x37\x04\x04\x00\x36\xc2\xc1\x46" \
-"\x36\xc6\x92\x46\x84\x40\x11\x07\x84\xc2\x94\x4b\xc1\x8e\x94\xcb" \
-"\xd4\x47\x85\x8a\xb1\xea\x92\x46\xba\x84\x91\x06\x36\xc2\xb2\x46" \
-"\xfd\x16\x36\xc6\xf9\xfe\x82\x46\xd4\xcb\x94\x4b\x93\xe6\x06\x04" \
-"\x94\xcb\xd4\x47\x85\x8a\x85\xee\xd4\x47\xc1\x8a\x85\xce\xd8\x47" \
-"\xb7\x06\xf3\xff\xfd\x16\x13\x67\x07\x01\xd8\xc7\x98\x4b\x21\x45" \
-"\x75\x8f\x98\xcb\x52\x44\xc2\x44\x61\x01\x02\x90\x23\x20\xd3\x00" \
-"\xf5\xb5\x23\xa0\x62\x00\x3d\xb7\x23\xa0\x62\x00\x55\xb7\x23\xa0" \
-"\x62\x00\xc1\xb7\x82\x46\x93\x86\x06\x04\x36\xc0\xa2\x46\xfd\x16" \
-"\x36\xc4\xb5\xf2\x98\x4b\xb7\x06\xf3\xff\xfd\x16\x75\x8f\x98\xcb" \
-"\x41\x89\x05\xcd\x2e\xc0\x0d\x06\x02\xc4\x09\x82\xb7\x07\x00\x20" \
-"\x32\xc6\x93\x87\x07\x20\x98\x43\x13\x86\x47\x00\xa2\x47\x82\x46" \
-"\x8a\x07\xb6\x97\x9c\x43\x63\x1c\xf7\x00\xa2\x47\x85\x07\x3e\xc4" \
-"\xa2\x46\x32\x47\xb2\x87\xe3\xe0\xe6\xfe\x01\x45\x61\xb7\x41\x45" \
-"\x51\xb7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
-"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
-"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
-
-int bootloader_len = 512;
-
 void wch_link_command( libusb_device_handle * devh, const void * command_v, int commandlen, int * transferred, uint8_t * reply, int replymax )
 {
 	uint8_t * command = (uint8_t*)command_v;
@@ -65,7 +29,6 @@ void wch_link_command( libusb_device_handle * devh, const void * command_v, int
 	if( !transferred ) transferred = &transferred_local;
 	status = libusb_bulk_transfer( devh, 0x01, command, commandlen, transferred, WCHTIMEOUT );
 	if( status ) goto sendfail;
-
 	got_to_recv = 1;
 	if( !reply )
 	{
@@ -142,6 +105,45 @@ static inline libusb_device_handle * wch_link_base_setup( int inhibit_startup )
 	return devh;
 }
 
+// DMI_OP decyphered From https://github.com/karlp/openocd-hacks/blob/27af153d4a373f29ad93dab28a01baffb7894363/src/jtag/drivers/wlink.c
+// Thanks, CW2 for pointing this out.  See DMI_OP for more info.
+int LEWriteReg32( void * dev, uint8_t reg_7_bit, uint32_t command )
+{
+	libusb_device_handle * devh = ((struct LinkEProgrammerStruct*)dev)->devh;
+
+	const uint8_t iOP = 2; // op 2 = write
+	uint8_t req[] = {
+		0x81, 0x08, 0x06, reg_7_bit,
+			(command >> 24) & 0xff,
+			(command >> 16) & 0xff,
+			(command >> 8) & 0xff,
+			(command >> 0) & 0xff,
+			iOP };
+
+	wch_link_command( devh, req, sizeof(req), 0, 0, 0 );
+	return 0;
+}
+
+int LEReadReg32( void * dev, uint8_t reg_7_bit, uint32_t * commandresp )
+{
+	libusb_device_handle * devh = ((struct LinkEProgrammerStruct*)dev)->devh;
+	const uint8_t iOP = 1; // op 1 = read
+	uint32_t transferred;
+	uint8_t rbuff[128] = { 0 };
+	uint8_t req[] = {
+		0x81, 0x08, 0x06, reg_7_bit,
+			0, 0, 0, 0,
+			iOP };
+	wch_link_command( devh, req, sizeof( req ), (int*)&transferred, rbuff, sizeof( rbuff ) );
+	*commandresp = ( rbuff[4]<<24 ) | (rbuff[5]<<16) | (rbuff[6]<<8) | (rbuff[7]<<0);
+	return 0;
+}
+
+int LEFlushLLCommands( void * dev )
+{
+	return 0;
+}
+
 static int LESetupInterface( void * d )
 {
 	libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh;
@@ -167,13 +169,22 @@ static int LESetupInterface( void * d )
 	fprintf( stderr, "Part UUID    : %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", rbuff[4], rbuff[5], rbuff[6], rbuff[7], rbuff[8], rbuff[9], rbuff[10], rbuff[11] );
 	fprintf( stderr, "PFlags       : %02x-%02x-%02x-%02x\n", rbuff[12], rbuff[13], rbuff[14], rbuff[15] );
 	fprintf( stderr, "Part Type (B): %02x-%02x-%02x-%02x\n", rbuff[16], rbuff[17], rbuff[18], rbuff[19] );
+	
+	int r = MCF.WaitForDoneOp( d );
+	if( r )
+	{
+		fprintf( stderr, "Error: WaitForDoneOp(...) failed\n" );
+	}
+
+	//Default behavior for other programmers is to be/stay in halt mode as much as possible.
+	MCF.HaltMode( d, 2 );
 	return 0;
 }
 
 static int LEControl3v3( void * d, int bOn )
 {
 	libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh;
-printf( "3v3: %d\n", bOn );
+
 	if( bOn )
 		wch_link_command( (libusb_device_handle *)dev, "\x81\x0d\x01\x09", 4, 0, 0, 0 );
 	else
@@ -184,7 +195,6 @@ printf( "3v3: %d\n", bOn );
 static int LEControl5v( void * d, int bOn )
 {
 	libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh;
-printf( "  5: %d\n", bOn );
 
 	if( bOn )
 		wch_link_command( (libusb_device_handle *)dev, "\x81\x0d\x01\x0b", 4, 0, 0, 0 );
@@ -202,7 +212,106 @@ static int LEUnbrick( void * d )
 	return 0;
 }
 
-static int LEHaltMode( void * d, int mode )
+
+static int LEConfigureNRSTAsGPIO( void * d, int one_if_yes_gpio )
+{
+	libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh;
+
+	if( one_if_yes_gpio )
+	{
+		wch_link_multicommands( (libusb_device_handle *)dev, 2, 11, "\x81\x06\x08\x02\xff\xff\xff\xff\xff\xff\xff", 4, "\x81\x0b\x01\x01" );
+	}
+	else
+	{
+		wch_link_multicommands( (libusb_device_handle *)dev, 2, 11, "\x81\x06\x08\x02\xf7\xff\xff\xff\xff\xff\xff", 4, "\x81\x0b\x01\x01" );
+	}
+	return 0;
+}
+
+int LEExit( void * d )
+{
+	libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh;
+
+	wch_link_command( (libusb_device_handle *)dev, "\x81\x0d\x01\xff", 4, 0, 0, 0);
+	return 0;
+}
+
+void * TryInit_WCHLinkE()
+{
+	libusb_device_handle * wch_linke_devh;
+	wch_linke_devh = wch_link_base_setup(0);
+	if( !wch_linke_devh ) return 0;
+
+
+	struct LinkEProgrammerStruct * ret = malloc( sizeof( struct LinkEProgrammerStruct ) );
+	memset( ret, 0, sizeof( *ret ) );
+	ret->devh = wch_linke_devh;
+	ret->lasthaltmode = 0;
+
+	MCF.ReadReg32 = LEReadReg32;
+	MCF.WriteReg32 = LEWriteReg32;
+	MCF.FlushLLCommands = LEFlushLLCommands;
+
+	MCF.SetupInterface = LESetupInterface;
+	MCF.Control3v3 = LEControl3v3;
+	MCF.Control5v = LEControl5v;
+	MCF.Unbrick = LEUnbrick;
+	MCF.ConfigureNRSTAsGPIO = LEConfigureNRSTAsGPIO;
+	//MCF.WriteBinaryBlob = LEWriteBinaryBlob;
+	//MCF.ReadBinaryBlob = LEReadBinaryBlob;
+	MCF.Exit = LEExit;
+	return ret;
+};
+
+
+
+
+
+
+
+
+// Graveyard.
+
+#if 0
+
+
+const uint8_t * bootloader = (const uint8_t*)
+"\x21\x11\x22\xca\x26\xc8\x93\x77\x15\x00\x99\xcf\xb7\x06\x67\x45" \
+"\xb7\x27\x02\x40\x93\x86\x36\x12\x37\x97\xef\xcd\xd4\xc3\x13\x07" \
+"\xb7\x9a\xd8\xc3\xd4\xd3\xd8\xd3\x93\x77\x25\x00\x9d\xc7\xb7\x27" \
+"\x02\x40\x98\x4b\xad\x66\x37\x33\x00\x40\x13\x67\x47\x00\x98\xcb" \
+"\x98\x4b\x93\x86\xa6\xaa\x13\x67\x07\x04\x98\xcb\xd8\x47\x05\x8b" \
+"\x63\x16\x07\x10\x98\x4b\x6d\x9b\x98\xcb\x93\x77\x45\x00\xa9\xcb" \
+"\x93\x07\xf6\x03\x99\x83\x2e\xc0\x2d\x63\x81\x76\x3e\xc4\xb7\x32" \
+"\x00\x40\xb7\x27\x02\x40\x13\x03\xa3\xaa\xfd\x16\x98\x4b\xb7\x03" \
+"\x02\x00\x33\x67\x77\x00\x98\xcb\x02\x47\xd8\xcb\x98\x4b\x13\x67" \
+"\x07\x04\x98\xcb\xd8\x47\x05\x8b\x69\xe7\x98\x4b\x75\x8f\x98\xcb" \
+"\x02\x47\x13\x07\x07\x04\x3a\xc0\x22\x47\x7d\x17\x3a\xc4\x79\xf7" \
+"\x93\x77\x85\x00\xf1\xcf\x93\x07\xf6\x03\x2e\xc0\x99\x83\x37\x27" \
+"\x02\x40\x3e\xc4\x1c\x4b\xc1\x66\x2d\x63\xd5\x8f\x1c\xcb\x37\x07" \
+"\x00\x20\x13\x07\x07\x20\xb7\x27\x02\x40\xb7\x03\x08\x00\xb7\x32" \
+"\x00\x40\x13\x03\xa3\xaa\x94\x4b\xb3\xe6\x76\x00\x94\xcb\xd4\x47" \
+"\x85\x8a\xf5\xfe\x82\x46\xba\x84\x37\x04\x04\x00\x36\xc2\xc1\x46" \
+"\x36\xc6\x92\x46\x84\x40\x11\x07\x84\xc2\x94\x4b\xc1\x8e\x94\xcb" \
+"\xd4\x47\x85\x8a\xb1\xea\x92\x46\xba\x84\x91\x06\x36\xc2\xb2\x46" \
+"\xfd\x16\x36\xc6\xf9\xfe\x82\x46\xd4\xcb\x94\x4b\x93\xe6\x06\x04" \
+"\x94\xcb\xd4\x47\x85\x8a\x85\xee\xd4\x47\xc1\x8a\x85\xce\xd8\x47" \
+"\xb7\x06\xf3\xff\xfd\x16\x13\x67\x07\x01\xd8\xc7\x98\x4b\x21\x45" \
+"\x75\x8f\x98\xcb\x52\x44\xc2\x44\x61\x01\x02\x90\x23\x20\xd3\x00" \
+"\xf5\xb5\x23\xa0\x62\x00\x3d\xb7\x23\xa0\x62\x00\x55\xb7\x23\xa0" \
+"\x62\x00\xc1\xb7\x82\x46\x93\x86\x06\x04\x36\xc0\xa2\x46\xfd\x16" \
+"\x36\xc4\xb5\xf2\x98\x4b\xb7\x06\xf3\xff\xfd\x16\x75\x8f\x98\xcb" \
+"\x41\x89\x05\xcd\x2e\xc0\x0d\x06\x02\xc4\x09\x82\xb7\x07\x00\x20" \
+"\x32\xc6\x93\x87\x07\x20\x98\x43\x13\x86\x47\x00\xa2\x47\x82\x46" \
+"\x8a\x07\xb6\x97\x9c\x43\x63\x1c\xf7\x00\xa2\x47\x85\x07\x3e\xc4" \
+"\xa2\x46\x32\x47\xb2\x87\xe3\xe0\xe6\xfe\x01\x45\x61\xb7\x41\x45" \
+"\x51\xb7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
+"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
+"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
+
+int bootloader_len = 512;
+
+static int InternalLinkEHaltMode( void * d, int mode )
 {
 	libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh;
 	if( mode == ((struct LinkEProgrammerStruct*)d)->lasthaltmode )
@@ -222,32 +331,16 @@ static int LEHaltMode( void * d, int mode )
 	}
 	else
 	{
-		return -93;
+		return -999;
 	}
 	return 0;
 }
 
-static int LEConfigureNRSTAsGPIO( void * d, int one_if_yes_gpio )
-{
-	libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh;
-
-	if( one_if_yes_gpio )
-	{
-		wch_link_multicommands( (libusb_device_handle *)dev, 2, 11, "\x81\x06\x08\x02\xff\xff\xff\xff\xff\xff\xff", 4, "\x81\x0b\x01\x01" );
-	}
-	else
-	{
-		wch_link_multicommands( (libusb_device_handle *)dev, 2, 11, "\x81\x06\x08\x02\xf7\xff\xff\xff\xff\xff\xff", 4, "\x81\x0b\x01\x01" );
-	}
-	return 0;
-}
-
-
 static int LEReadBinaryBlob( void * d, uint32_t offset, uint32_t amount, uint8_t * readbuff )
 {
 	libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh;
 
-	LEHaltMode( d, 0 );
+	InternalLinkEHaltMode( d, 0 );
 
 	int i;
 	int status;
@@ -305,7 +398,7 @@ static int LEWriteBinaryBlob( void * d, uint32_t address_to_write, uint32_t len,
 {
 	libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh;
 
-	LEHaltMode( d, 0 );
+	InternalLinkEHaltMode( d, 0 );
 
 	int i;
 	int status;
@@ -366,41 +459,4 @@ static int LEWriteBinaryBlob( void * d, uint32_t address_to_write, uint32_t len,
 	}
 	return 0;
 }
-
-int LEExit( void * d )
-{
-	libusb_device_handle * dev = ((struct LinkEProgrammerStruct*)d)->devh;
-
-	wch_link_command( (libusb_device_handle *)dev, "\x81\x0d\x01\xff", 4, 0, 0, 0);
-	return 0;
-}
-
-void * TryInit_WCHLinkE()
-{
-	libusb_device_handle * wch_linke_devh;
-	wch_linke_devh = wch_link_base_setup(0);
-	if( !wch_linke_devh ) return 0;
-
-
-	struct LinkEProgrammerStruct * ret = malloc( sizeof( struct LinkEProgrammerStruct ) );
-	memset( ret, 0, sizeof( *ret ) );
-	ret->devh = wch_linke_devh;
-	ret->lasthaltmode = 0;
-
-	MCF.WriteReg32 = 0;
-	MCF.ReadReg32 = 0;
-
-	MCF.SetupInterface = LESetupInterface;
-	MCF.Control3v3 = LEControl3v3;
-	MCF.Control5v = LEControl5v;
-	MCF.Unbrick = LEUnbrick;
-	MCF.HaltMode = LEHaltMode;
-	MCF.ConfigureNRSTAsGPIO = LEConfigureNRSTAsGPIO;
-	MCF.WriteBinaryBlob = LEWriteBinaryBlob;
-	MCF.ReadBinaryBlob = LEReadBinaryBlob;
-	MCF.Exit = LEExit;
-	return ret;
-};
-
-
-
+#endif
diff --git a/minichlink/test.bat b/minichlink/test.bat
deleted file mode 100644
index 863c041790e3ec6932dcad986e13b9d7aeeafa1f..0000000000000000000000000000000000000000
--- a/minichlink/test.bat
+++ /dev/null
@@ -1 +0,0 @@
-tcc -lsetupapi minichlink.c libusb-1.0.dll pgm-esp32s2-ch32xx.c  pgm-wch-linke.c
diff --git a/minichlink/winbuild.bat b/minichlink/winbuild.bat
new file mode 100644
index 0000000000000000000000000000000000000000..785472441f6d5d1db88cd6282afe61fc9f21a39b
--- /dev/null
+++ b/minichlink/winbuild.bat
@@ -0,0 +1 @@
+tcc minichlink.c pgm-esp32s2-ch32xx.c  pgm-wch-linke.c minichgdb.c nhc-link042.c -DWIN32 -lws2_32 -lsetupapi libusb-1.0.dll