Index: firmware/native/diskio_image.c
===================================================================
--- firmware/native/diskio_image.c	(revision 48)
+++ firmware/native/diskio_image.c	(nonexistent)
@@ -1,74 +0,0 @@
-#include "diskio.h"
-
-#include "stdio.h"
-
-FILE * disk_image;
-
-/*-----------------------------------------------------------------------*/
-/* Initialize Disk Drive                                                 */
-/*-----------------------------------------------------------------------*/
-
-DSTATUS disk_initialize (void)
-{
-	DSTATUS stat;
-
- 	disk_image = fopen("sd.image","rb");
-
-	stat = RES_OK;
-
-	return stat;
-}
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Read Partial Sector                                                   */
-/*-----------------------------------------------------------------------*/
-
-DRESULT disk_readp (
-	BYTE* dest,			/* Pointer to the destination object */
-	DWORD sector,		/* Sector number (LBA) */
-	WORD sofs,			/* Offset in the sector */
-	WORD count			/* Byte count (bit15:destination) */
-)
-{
-	DRESULT res;
-
-	fseek(disk_image,sector*512+sofs,SEEK_SET);
-	fread(dest,count,1,disk_image);
-
-	res = RES_OK;
-
-	return res;
-}
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Write Partial Sector                                                  */
-/*-----------------------------------------------------------------------*/
-
-DRESULT disk_writep (const BYTE* buff, DWORD sc)
-{
-	DRESULT res;
-
-
-	if (!buff) {
-		if (sc) {
-
-			// Initiate write process
-
-		} else {
-
-			// Finalize write process
-
-		}
-	} else {
-
-		// Send data to the disk
-
-	}
-
-	return res;
-}
-
Index: firmware/Makefile
===================================================================
--- firmware/Makefile	(revision 48)
+++ firmware/Makefile	(revision 49)
@@ -19,7 +19,7 @@
 MINSTARTUP_OBJ = $(patsubst $(STARTUP_DIR)/%.s,$(BUILD_DIR)/%.o,$(MINSTARTUP_SRC))
 
 MAIN_PRJ = JustStartAtari
-MAIN_SRC = main.c regs.c freeze.c atari_drive_emulator.c pokey/uart.c hexdump.c printf/printf.c fat/pff_file.c fat/pff.c common/utils.c sd_direct/diskio_mmc.c sd_direct/spi.c sd_direct/mmc.c
+MAIN_SRC = main.c regs.c freeze.c joystick.c fileutils.c fileselector.c atari_drive_emulator.c pokey/uart.c hexdump.c printf/printf.c fat/pff_file.c fat/pff.c common/utils.c sd_direct/diskio_mmc.c sd_direct/spi.c sd_direct/mmc.c
 #gcc -g -O0 -DLITTLE_ENDIAN test_drive.c atari_drive_emulator.c native/uart.c hexdump.c printf/printf.c fat/pff_file.c fat/pff.c common/utils.c native/diskio_image.c -I. -Iprintf -Ifat -Icommon
 #MAIN_SRC = stuff.c
 MAIN_OBJ = $(COMMON_OBJ) $(patsubst %.c,$(BUILD_DIR)/%.o,$(MAIN_SRC))
Index: firmware/atari_drive_emulator.c
===================================================================
--- firmware/atari_drive_emulator.c	(revision 48)
+++ firmware/atari_drive_emulator.c	(revision 49)
@@ -1,4 +1,5 @@
 #include "atari_drive_emulator.h"
+#include "fileutils.h"
 
 #include "uart.h"
 #include "pause.h"
@@ -7,6 +8,8 @@
 #include "printf.h"
 #include "integer.h"
 
+extern int debug_pos; // ARG!
+
 #define send_ACK()	USART_Transmit_Byte('A');
 #define send_NACK()	USART_Transmit_Byte('N');
 #define send_CMPL()	USART_Transmit_Byte('C');
@@ -36,8 +39,14 @@
 	u16 wSecSize;
 	u08 btParsHigh;
 	u32 dwCRC;
+	u32 dwUNUSED;
+	u08 btFlags;
 } __attribute__((packed));
 struct ATRHeader atr_header;
+int offset;
+int xex_loader;
+int xex_size;
+
 int speed;
 
 int badcommandcount;
@@ -44,9 +53,11 @@
 int commandcount;
 int opendrive;
 
+int readonly;
+
 unsigned char atari_sector_buffer[256];
 
-unsigned char get_checksum(unsigned char* buffer, u16 len);
+unsigned char get_checksum(unsigned char* buffer, int len);
 
 #define    TWOBYTESTOWORD(ptr,val)           (*((u08*)(ptr)) = val&0xff);(*(1+(u08*)(ptr)) = (val>>8)&0xff);
 
@@ -59,9 +70,6 @@
 		atari_sector_buffer[i] = 0;
 }
 
-int offset;
-int xex_loader;
-int xex_size;
 uint8_t boot_xex_loader[179] = {
 	0x72,0x02,0x5f,0x07,0xf8,0x07,0xa9,0x00,0x8d,0x04,0x03,0x8d,0x44,0x02,0xa9,0x07,
 	0x8d,0x05,0x03,0xa9,0x70,0x8d,0x0a,0x03,0xa9,0x01,0x8d,0x0b,0x03,0x85,0x09,0x60,
@@ -167,32 +175,6 @@
 	DELAY_T2_MIN;
 }
 
-int compare_ext(char const * filename, char const * ext)
-{
-	int dot = 0;
-
-	while (1)
-	{
-		if (filename[dot] == '\0')
-			break;
-		if (filename[dot] != '.')
-		{
-			++dot;
-			continue;
-		}
-		if (filename[dot+1] == ext[0])
-			if (filename[dot+2] == ext[1])
-				if (filename[dot+3] == ext[2])
-				{
-					return 1;
-					break;
-				}
-		break;
-	}
-
-	return 0;
-}
-
 // Called whenever file changed
 void set_drive_status(int driveNumber, struct SimpleFile * file)
 {
@@ -229,7 +211,7 @@
 	*/
 
 	xex_loader = 0;
-	xfd = compare_ext(file_name(file),"XFD") || compare_ext(file_name(file),"xfd");
+	xfd = compare_ext(file_name(file),"XFD");
 
 	if (xfd == 1)
 	{
@@ -239,6 +221,7 @@
 		atr_header.wMagic = 0x296;
 		atr_header.wPars = file_size(file)/16;
 		atr_header.wSecSize = 0x80;
+		atr_header.btFlags = 0;
 	}
 	else if (atr_header.wMagic == 0xFFFF) // XEX
 	{
@@ -250,6 +233,7 @@
 		xex_size = file_size(file);
 		atr_header.wPars = xex_size/16;
 		atr_header.wSecSize = XEX_SECTOR_SIZE;
+		atr_header.btFlags = 1;
 	}
 	else if (atr_header.wMagic == 0x296) // ATR
 	{
@@ -345,9 +329,10 @@
 		printf("%d",drive);
 		if (drive!=opendrive)
 		{
-			if (drive<MAX_DRIVES)
+			if (drive<MAX_DRIVES && drive>=0)
 			{
 				opendrive = drive;
+				set_drive_status(drive, drives[drive]);
 			}
 		}
 
@@ -423,8 +408,6 @@
 			printf(":done\n");
 			}
 			break;
-		case 0x50: // write
-		case 0x57: // write with verify
 		default:
 			// TODO
 			//USART_Transmit_Mode();
@@ -432,6 +415,108 @@
 			//USART_Wait_Transmit_Complete();
 			//USART_Receive_Mode();
 			break;
+		case 0x50: // write
+		case 0x57: // write with verify
+			{
+			//debug_pos = 0;
+
+			int sector = ((int)command.aux1) + (((int)command.aux2&0x7f)<<8);
+			int sectorSize = 0;
+			int location =0;
+
+			printf("WACK:");
+			USART_Transmit_Mode();
+			send_ACK();
+			USART_Wait_Transmit_Complete();
+			USART_Receive_Mode();
+	
+			location = offset;
+			if (sector>3)
+			{
+				sector-=4;
+				location += 128*3;
+				location += sector*atr_header.wSecSize;
+				sectorSize = atr_header.wSecSize;
+			}
+			else
+			{
+				location += 128*(sector-1);
+				sectorSize = 128;
+			}
+
+			// Receive the data
+			int i;
+			for (i=0;i!=sectorSize;++i)
+			{
+				unsigned char temp = USART_Receive_Byte();
+				atari_sector_buffer[i] = temp;
+				//printf("%02x",temp);
+			}
+			unsigned char checksum = USART_Receive_Byte();
+			//hexdump_pure(atari_sector_buffer,sectorSize); // Somehow with this...
+			unsigned char expchk = get_checksum(&atari_sector_buffer[0],sectorSize);
+			printf("DATA:%d:",sectorSize);
+			printf("CHK:%02x EXP:%02x", checksum, expchk);
+			//printf(" %d",atari_sector_buffer[0]); // and this... The wrong checksum is sent!!
+			printf(":done\n");
+			if (checksum==expchk)
+			{
+				USART_Transmit_Mode();
+				printf(":WACK2:");
+				send_ACK();
+				USART_Wait_Transmit_Complete();
+
+				printf("%d",location);
+				printf("\n");
+				file_seek(file,location);
+				int written = 0;
+				file_write(file,&atari_sector_buffer[0], sectorSize, &written);
+
+				int ok = 0;
+
+				if (command.command == 0x57)
+				{
+					char buffer[256];
+					int read;
+					file_read(file,buffer,sectorSize,&read);
+
+					ok = 1;
+					for (i=0;i!=sectorSize;++i)
+					{
+						if (buffer[i] != atari_sector_buffer[i]) ok = 0;
+					}
+				}
+				else
+					ok = 1;
+
+				DELAY_T5_MIN;
+				if (ok)
+				{
+					printf(":CMPL:");
+					send_CMPL();
+				}
+				else
+				{
+					printf(":NACK:");
+					send_NACK();
+				}
+
+				USART_Wait_Transmit_Complete();
+				USART_Receive_Mode();
+			}
+			else
+			{
+				printf(":NACK:");
+				send_NACK();
+
+				USART_Wait_Transmit_Complete();
+				USART_Receive_Mode();
+			}
+
+			//debug_pos = -1;
+			}
+
+			break;
 		case 0x52: // read
 			{
 			int sector = ((int)command.aux1) + (((int)command.aux2&0x7f)<<8);
@@ -594,7 +679,7 @@
 	}
 }
 	
-unsigned char get_checksum(unsigned char* buffer, u16 len)
+unsigned char get_checksum(unsigned char* buffer, int len)
 {
 	u16 i;
 	u08 sumo,sum;
@@ -604,6 +689,8 @@
 		sum+=buffer[i];
 		if(sum<sumo) sum++;
 		sumo = sum;
+
+		//printf("c:%02x:",sumo);
 	}
 	return sum;
 }
Index: firmware/build_native_file_test
===================================================================
--- firmware/build_native_file_test	(revision 48)
+++ firmware/build_native_file_test	(revision 49)
@@ -1 +1 @@
-gcc -g -O0 test_file.c fat/pff_file.c fat/pff.c common/utils.c native/diskio_image.c -I. -Ifat -Icommon
+gcc -g -O0 printf/printf.c test_file.c fileutils.c fileselector.c fat/pff_file.c fat/pff.c common/utils.c native/regs.c native/joystick.c native/diskio_mmc.c native/mmc.c native/screen.c -I. -Ifat -Icommon -Iprintf
Index: firmware/common/utils.c
===================================================================
--- firmware/common/utils.c	(revision 48)
+++ firmware/common/utils.c	(revision 49)
@@ -18,6 +18,17 @@
 	while (*dest++=*src++);
 }
 
+void stricpy(char * dest, char const * src)
+{
+	while (*src)
+	{
+		char val = *src++;
+		if (val>='A' && val<='Z') val-='A'+'a';
+
+		*dest++ = val;
+	}
+}
+
 int strlen(char const * a)
 {
 	int count;
Index: firmware/common/utils.h
===================================================================
--- firmware/common/utils.h	(revision 48)
+++ firmware/common/utils.h	(revision 49)
@@ -1,4 +1,5 @@
 int strcmp(char const * a, char const * b);
 void strcpy(char * dest, char const * src);
+void stricpy(char * dest, char const * src);
 int strlen(char const * a);
 
Index: firmware/fat/diskio.h
===================================================================
--- firmware/fat/diskio.h	(revision 48)
+++ firmware/fat/diskio.h	(revision 49)
@@ -25,7 +25,8 @@
 
 DSTATUS disk_initialize (void);
 DRESULT disk_readp (BYTE*, DWORD, WORD, WORD);
-DRESULT disk_writep (const BYTE*, DWORD);
+DRESULT disk_writep (const BYTE* buff, DWORD sofs, DWORD count);
+void disk_writeflush();
 
 #define STA_NOINIT		0x01	/* Drive not initialized */
 #define STA_NODISK		0x02	/* No medium in the drive */
Index: firmware/fat/pff.h
===================================================================
--- firmware/fat/pff.h	(revision 48)
+++ firmware/fat/pff.h	(revision 49)
@@ -32,7 +32,7 @@
 
 #define	_USE_LSEEK	1	/* 1:Enable pf_lseek() */
 
-#define	_USE_WRITE	1	/* 1:Enable pf_write() */
+#define	_USE_WRITE	0	/* 1:Enable pf_write() */
 
 #define _FS_FAT12	1	/* 1:Enable FAT12 support */
 #define _FS_FAT32	1	/* 1:Enable FAT32 support */
Index: firmware/fat/pff_file.c
===================================================================
--- firmware/fat/pff_file.c	(revision 48)
+++ firmware/fat/pff_file.c	(revision 49)
@@ -15,6 +15,8 @@
 DIR dir;
 FILINFO filinfo;
 
+int write_pending;
+
 enum SimpleFileStatus translateStatus(FRESULT res)
 {
 	return res == FR_OK ? SimpleFile_OK: SimpleFile_FAIL;
@@ -65,6 +67,8 @@
 {
 	if (openfile!=file)
 	{
+		file_write_flush();
+
 		pf_open(&file->path[0]);
 		openfile = file;
 	}
@@ -75,6 +79,7 @@
 	WORD bytesread_word;
 	FRESULT res;
 
+	file_write_flush();
 	file_check_open(file);
 
 	res = pf_read(buffer, bytes, &bytesread_word);
@@ -88,18 +93,78 @@
 	WORD byteswritten_word;
 	FRESULT res;
 
+	printf("went\n");
+
 	file_check_open(file);
-	
-	res = pf_write(buffer, bytes, &byteswritten_word);
-	*byteswritten = byteswritten_word;
 
+	int rem = bytes;
+	while (rem>0)
+	{
+		int sector = fatfs.fptr>>9;
+		int pos = fatfs.fptr&0x1ff;
+
+		int bytes_this_cycle = rem;
+		if (bytes_this_cycle>(512-pos))
+			bytes_this_cycle = 512-pos;
+
+		printf("file_write:%d/%d - %d/%d\n",sector,pos,bytes_this_cycle,bytes);
+
+		if (sector != write_pending)
+		{
+			file_write_flush();
+		}
+
+		if (write_pending <0)
+		{
+			// read the sector into our 512 byte buffer...
+			pf_lseek(sector<<9);
+			int fptr = fatfs.fptr;
+
+			char temp_buffer[1];
+			pf_read(&temp_buffer[0], 1, &byteswritten_word);
+
+			printf("Writing initial pos:%d\n",pos);
+
+			// seek to the initial pos
+			fatfs.fptr = fptr + pos;
+
+			write_pending = sector;
+		}
+
+		res = disk_writep(buffer, pos, bytes_this_cycle);
+
+		fatfs.fptr += bytes_this_cycle;
+		rem-=bytes_this_cycle;
+		buffer+=bytes_this_cycle;
+	}
+	*byteswritten = bytes;
+
+	printf("wend\n");
 	return translateStatus(res);
 }
 
+enum SimpleFileStatus file_write_flush()
+{
+	if (write_pending >= 0)
+	{
+		printf("wflush\n");
+		disk_writeflush();
+		write_pending = -1;
+	}
+	return SimpleFile_OK;
+}
+
 enum SimpleFileStatus file_seek(struct SimpleFile * file, int offsetFromStart)
 {
 	FRESULT res;
 
+	int location = offsetFromStart>>9;
+	if (write_pending >=0 && write_pending != offsetFromStart)
+	{
+		printf("flush on seek\n");
+		file_write_flush();
+	}
+
 	file_check_open(file);
 
 	pf_lseek(offsetFromStart);
@@ -122,6 +187,8 @@
 	char const * filename = file_of(path);
 	dir_of(&dirname[0], path);
 
+	file_write_flush();
+
 	printf("filename:%s dirname:%s ", filename,&dirname[0]);
 
 	struct SimpleDirEntry * entry = dir_entries(&dirname[0]);
@@ -145,6 +212,8 @@
 	strcpy(&file->path[0],dir->path);
 	file->size = dir->size;
 
+	file_write_flush();
+
 	res = pf_open(&file->path[0]);
 	openfile = file;
 
@@ -156,6 +225,8 @@
 	FRESULT fres;
 	DSTATUS res;
 
+	write_pending = -1;
+
 	printf("dir_init\n");
 
 	dir_cache = mem;
@@ -174,12 +245,17 @@
 }
 
 // Read entire dir into memory (i.e. give it a decent chunk of sdram)
-// TODO - dir cache, so we don't need to know where everywhere!
 struct SimpleDirEntry * dir_entries(char const * dirPath)
 {
-	struct SimpleDirEntry * entry = 0;
+	return dir_entries_filtered(dirPath,0);
+}
+
+struct SimpleDirEntry * dir_entries_filtered(char const * dirPath,int(* filter)(struct SimpleDirEntry *))
+{
 	int room = dir_cache_size/sizeof(struct SimpleDirEntry);
 
+	file_write_flush();
+
 	printf("opendir ");
 	if (FR_OK != pf_opendir(&dir,dirPath))
 	{
@@ -188,6 +264,14 @@
 	}
 	printf("OK ");
 
+	struct SimpleDirEntry * prev = (struct SimpleDirEntry *)dir_cache;
+	strcpy(prev->path,"..");
+	prev->filename_ptr = prev->path;
+	prev->size = 0;
+	prev->is_subdir = 1;
+	--room;
+
+	struct SimpleDirEntry * entry = 0;
 	while (FR_OK == pf_readdir(&dir,&filinfo) && filinfo.fname[0]!='\0')
 	{
 		char * ptr;
@@ -201,12 +285,9 @@
 			continue;
 		}
 
-		if (!entry)
-			entry = (struct SimpleDirEntry *) dir_cache;
-		else if (room)
+		if (room)
 		{
-			printf("inc %x %x ",entry,entry->next);
-			entry = entry->next;
+			entry = prev+1;
 			--room;
 		}
 		else
@@ -228,7 +309,17 @@
 		strcpy(ptr,filinfo.fname);
 		entry->size = filinfo.fsize;
 
-		entry->next = entry + 1;
+		entry->next = 0;
+
+		if (filter && !filter(entry))
+		{
+			continue;	
+		}
+
+		if (prev)
+			prev->next = entry;
+		prev = entry;
+
 		printf("n %d %d %x ",filinfo.fsize, entry->size, entry->next);
 	}
 
Index: firmware/fileselector.c
===================================================================
--- firmware/fileselector.c	(revision 48)
+++ firmware/fileselector.c	(revision 49)
@@ -1,136 +1,162 @@
+#include "simplefile.h"
+#include "simpledir.h"
+#include "joystick.h"
+#include "regs.h" // NO NEED!!! 
+#include "printf.h"
+#include "fileutils.h"
 
-void file_select(void (*filter) (char const *), char const * path, struct SimpleFile * file)
-{
-	// Read in the whole dir
+extern int debug_pos; // ARG!
+extern int debug_adjust; // ARG!
 
-	// Write it to screen memory
+// TODO!
+#define MAX_PATH_LENGTH (9*5 + 8+3+1 + 1) 
 
-	// Allow user to scroll around with hotkeys/joystick
+int filter(struct SimpleDirEntry * entry)
+{
+	if (dir_is_subdir(entry)) return 1;
+	char const * f = dir_filename(entry);
+	return (compare_ext(f,"ATR") || compare_ext(f,"XFD") || compare_ext(f,"XEX"));
+}
 
-	// If user selects dir, then we 
+void file_selector(struct SimpleFile * file)
+{
+	char dir[MAX_PATH_LENGTH] = "";
+	for (;;)
+	{
+		// TODO last selected dir...
+		struct SimpleDirEntry * entry = dir_entries_filtered(dir,filter);
 
-	int fileno;
-	int skip;
-	int plotted = 0;
-	wait_us(200000);
-	for(;;)
-	{
-		int i = 0;
-		int go = 0;
-		fileno = 0;
-		topofscreen();
-		for (i=0; i!=(24*40); ++i)
+		// Count how many we have
+		int entries = 0;
+		struct SimpleDirEntry * temp_entry = entry;
+		while (temp_entry)
 		{
-			*(unsigned char volatile *)(i+0x10000+40000) = 0x00;
+			++entries;
+			temp_entry = dir_next(temp_entry);
 		}
-		if (FR_OK != pf_opendir(&dir,"/"))
+
+		// Selected item
+		int pos = 0;
+
+		struct joystick_status joy;
+		joy.x_ = joy.y_ = joy.fire_ = 0;
+
+		for (;;)
 		{
-			debug("opendir failed\n");
-			mmcReadCached(0);
-			hexdump_pure(mmc_sector_buffer,512);
-			
-			while(1);
-		}
+			if (pos<0) pos = 0;
+			if (pos>=entries) pos = entries-1;
 
-		plotted = 0;
-		skip = 0;
-		if (selfileno>20)
-		{
-			skip = selfileno-20;
-			skip&=0xfffffffe;
-		}
-		if (selfileno<0)
-		{
-			selfileno = 0;
-		}
-		while (FR_OK == pf_readdir(&dir,&filinfo) && filinfo.fname[0]!='\0')
-		{
-			if (filinfo.fattrib & AM_SYS)
+			// render
 			{
-				continue;
-			}
-			if (filinfo.fattrib & AM_HID)
-			{
-				continue;
-			}
-			if (filinfo.fattrib & AM_DIR)
-			{
-				debug("DIR ");
-			}
-			if (selfileno == fileno)
-			{
-				for (i=0;i!=15;++i)
+				// find which chunk to render
+				int startpos = pos-20;
+				if (startpos<0) startpos=0;
+
+				// get the dir entries for these
+				struct SimpleDirEntry * render_entry = entry;
+				int skip = startpos;
+				while (skip-->0)
 				{
-					filename[i] = filinfo.fname[i];
-					if (0==filinfo.fname[i]) break;
-					filinfo.fname[i]+=128;
+					render_entry =  dir_next(render_entry);
 				}
-			}
-			if (--skip<0)
-			{
-				debug(filinfo.fname);
-				++plotted;
-				if (plotted&1)
+
+				// clear the screen
+				clearscreen();
+
+				// find selected entry
+				struct SimpleDirEntry * sel_entry = entry;
+				skip = pos;
+				while (skip-->0)
 				{
-					setxpos(20);
+					sel_entry =  dir_next(sel_entry);
 				}
-				else
+
+				// output the new entries
+				int line;
+				for (line=0; line<44; ++line)
 				{
-					debug("\n");
+					if (!render_entry) break;
+					
+					debug_pos = line*20;
+					if (render_entry == sel_entry)
+					{
+						debug_adjust = 128;
+					}
+					else
+					{
+						debug_adjust = 0;
+					}
+					if (dir_is_subdir(render_entry))
+					{
+						printf("DIR:");
+					}
+					printf("%s",dir_filename(render_entry));
+
+					render_entry = dir_next(render_entry);
 				}
-				if (plotted==40)
+
+				debug_pos = 40*23;
+				if (sel_entry)
 				{
-					break;
+					printf("%s %s %d %d %d",dir_is_subdir(sel_entry) ? "DIR":"", dir_filename(sel_entry), joy.x_, joy.y_, pos);
 				}
 			}
-			fileno++;
-		}
-		debug("\n");
-		setypos(21);
-		opendrive = 0;
-		openfile(filename);
-		for (;;)
-		{
-			unsigned char porta = *atari_porta;
-			if (0==(porta&0x2)) // down
+
+			// Slow it down a bit
+			wait_us(100000);
+
+			// move
+			joystick_wait(&joy,WAIT_QUIET);
+			joystick_wait(&joy,WAIT_EITHER);
+			
+			if (joy.fire_)
 			{
-				selfileno+=2;
-				break;
+				int i = pos;
+				while(i--)
+				{
+					if (!entry) break;
+					entry = dir_next(entry);
+				}
+
+				if (entry)
+				{
+					if (!dir_is_subdir(entry))
+					{
+						file_open_dir(entry, file);
+						return;
+					}
+					else
+					{
+						char const *f = dir_filename(entry);
+						if (strcmp("..",f)==0)
+						{
+							int x = strlen(dir);
+							while (x-->0)
+							{
+								if (dir[x] == '/')
+								{
+									dir[x] = '\0';
+									break;
+								}
+							}
+							//printf("\nDIR UP! %s\n",dir);
+						}
+						else
+						{
+							strcpy(dir + strlen(dir),"/");
+							strcpy(dir + strlen(dir),f);
+							//printf("\nDIR DOWN:%s -> %s\n",f,dir);
+						}
+					}
+					break;
+				}
+
+				return;
 			}
-			else if (0==(porta&0x1)) // up
-			{
-				selfileno-=2;
-				break;
-			}
-			else if (0==(porta&0x8)) // right
-			{
-				selfileno|=1;
-				break;
-			}
-			else if (0==(porta&0x4)) // left
-			{
-				selfileno&=0xfffffffe;
-				break;
-			}
-			else if (0==(*atari_trig0)) // fire
-			{
-				go = 1;
-				while(0==(*atari_trig0));
-				break;
-			}
-			topofscreen();
-			//plotnextnumber(porta);
-			*atari_colbk = *atari_random;
-			//wait_us(200);
+			
+			pos += joy.x_;
+			pos += joy.y_*2;
 		}
-		if (go == 1)
-		{
-			wait_us(200000);
-			return validfile; // TODO, another way to quit without selecting...
-		}
-		wait_us(80000);
 	}
-	return 0;
 }
 
-
Index: firmware/fileselector.h
===================================================================
--- firmware/fileselector.h	(revision 48)
+++ firmware/fileselector.h	(revision 49)
@@ -1,4 +1,4 @@
 #pragma once
 
-void file_select(void (*filter) (char const *), char const * path, struct SimpleFile * file);
+void file_selector(struct SimpleFile * file);
 
Index: firmware/fileutils.c
===================================================================
--- firmware/fileutils.c	(nonexistent)
+++ firmware/fileutils.c	(revision 49)
@@ -0,0 +1,30 @@
+int compare_ext(char const * filenamein, char const * extin)
+{
+	int dot = 0;
+	char filename[64];
+	char ext[64];
+	stricpy(filename,filenamein);
+	stricpy(ext,extin);
+
+	while (1)
+	{
+		if (filename[dot] == '\0')
+			break;
+		if (filename[dot] != '.')
+		{
+			++dot;
+			continue;
+		}
+		if (filename[dot+1] == ext[0])
+			if (filename[dot+2] == ext[1])
+				if (filename[dot+3] == ext[2])
+				{
+					return 1;
+					break;
+				}
+		break;
+	}
+
+	return 0;
+}
+
Index: firmware/fileutils.h
===================================================================
--- firmware/fileutils.h	(nonexistent)
+++ firmware/fileutils.h	(revision 49)
@@ -0,0 +1,4 @@
+#pragma once
+
+int compare_ext(char const * filename, char const * ext);
+
Index: firmware/joystick.h
===================================================================
--- firmware/joystick.h	(revision 48)
+++ firmware/joystick.h	(revision 49)
@@ -2,9 +2,9 @@
 
 struct joystick_status
 {
-	char x_;
-	char y_;
-	char fire_;
+	int x_;
+	int y_;
+	int fire_;
 };
 
 enum JoyWait {WAIT_QUIET, WAIT_FIRE, WAIT_MOVE, WAIT_EITHER};
Index: firmware/main.c
===================================================================
--- firmware/main.c	(revision 48)
+++ firmware/main.c	(revision 49)
@@ -2,9 +2,11 @@
 #include "regs.h"
 #include "pause.h"
 #include "printf.h"
+#include "joystick.h"
 
 #include "simpledir.h"
 #include "simplefile.h"
+#include "fileselector.h"
 
 #include "atari_drive_emulator.h"
 
@@ -56,10 +58,10 @@
 BIT_REG(,0x7,8,ram_select,zpu_out1)
 BIT_REG(,0x3f,11,rom_select,zpu_out1)
 
-BIT_REG_RO(,0x1,0,hotkey_softboot,zpu_in1)
-BIT_REG_RO(,0x1,1,hotkey_coldboot,zpu_in1)
-BIT_REG_RO(,0x1,2,hotkey_fileselect,zpu_in1)
-BIT_REG_RO(,0x1,3,hotkey_settings,zpu_in1)
+BIT_REG_RO(,0x1,4,hotkey_softboot,zpu_in1)
+BIT_REG_RO(,0x1,5,hotkey_coldboot,zpu_in1)
+BIT_REG_RO(,0x1,6,hotkey_fileselect,zpu_in1)
+BIT_REG_RO(,0x1,7,hotkey_settings,zpu_in1)
 
 void
 wait_us(int unsigned num)
@@ -136,14 +138,22 @@
 }
 
 int debug_pos;
+int debug_adjust;
 unsigned char volatile * baseaddr;
 
+void clearscreen()
+{
+	unsigned volatile char * screen;
+	for (screen=(unsigned volatile char *)40000+atari_regbase; screen!=(unsigned volatile char *)(atari_regbase+40000+1024); ++screen)
+		*screen = 0x00;
+}
+
 void char_out ( void* p, char c)
 {
 	unsigned char val = toatarichar(c);
-	if (debug_pos>0)
+	if (debug_pos>=0)
 	{
-		*(baseaddr+debug_pos) = val;
+		*(baseaddr+debug_pos) = val|debug_adjust;
 		++debug_pos;
 	}
 }
@@ -152,11 +162,20 @@
 // 0x410000-0x41FFFF (0xc10000 in zpu space) = directory cache - 64k
 // 0x420000-0x43FFFF (0xc20000 in zpu space) = freeze backup
 
+struct SimpleFile * files[4];
+
 int main(void)
 {
+	int i;
+	for (i=0; i!=4; ++i)
+	{
+		files[i] = (struct SimpleFile *)alloca(file_struct_size());
+	}
+
 	freeze_init((void*)0xc20000); // 128k
 
 	debug_pos = -1;
+	debug_adjust = 0;
 	baseaddr = (unsigned char volatile *)(40000 + atari_regbase);
 	set_reset_6502(1);
 	set_turbo_6502(1);
@@ -196,10 +215,102 @@
 //			printf("FILE open failed\n");
 //		}
 
+char const * get_ram()
+{
+	switch(get_ram_select())
+	{
+	case 0:
+		return "64K";
+	case 1:
+		return "128";
+	case 2:
+		return "320K(Compy)";
+	case 3:
+		return "320K(Rambo)";
+	case 4:
+		return "576K(Compy)";
+	case 5:
+		return "576K(Rambo)";
+	case 6:
+		return "1MB";
+	case 7:
+		return "4MB";
+	}
+}
+
+void settings()
+{
+	struct joystick_status joy;
+	joy.x_ = joy.y_ = joy.fire_ = 0;
+
+	int row = 0;
+
+	for (;;)
+	{
+		// Render
+		clearscreen();
+		debug_pos = 20;
+		debug_adjust = 0;
+		printf("Settings");
+		debug_pos = 80;
+		debug_adjust = row==0 ? 128 : 0;
+		printf("Turbo:%dx", get_turbo_6502());
+		debug_pos = 120;
+		debug_adjust = row==1 ? 128 : 0;
+		printf("Ram:%s", get_ram());
+		debug_pos = 160;
+		debug_adjust = row==2 ? 128 : 0;
+		printf("Rom bank:%d", get_rom_select());
+
+		// Slow it down a bit
+		wait_us(100000);
+
+		// move
+		joystick_wait(&joy,WAIT_QUIET);
+		joystick_wait(&joy,WAIT_EITHER);
+
+		if (joy.fire_) break;
+		row+=joy.y_;
+		if (row<0) row = 0;
+		if (row>2) row = 2;
+		switch (row)
+		{
+		case 0:
+			{
+				int turbo = get_turbo_6502();
+				if (joy.x_==1) turbo<<=1;
+				if (joy.x_==-1) turbo>>=1;
+				if (turbo>16) turbo = 16;
+				if (turbo<1) turbo = 1;
+				set_turbo_6502(turbo);
+			}
+			break;
+		case 1:
+			{
+				int ram_select = get_ram_select();
+				ram_select+=joy.x_;
+				if (ram_select<0) ram_select = 0;
+				if (ram_select>7) ram_select = 7;
+				set_ram_select(ram_select);
+			}
+			break;
+		case 2:
+			{
+				int rom_select = get_rom_select();
+				rom_select+=joy.x_;
+				if (rom_select<0) rom_select = 0;
+				if (rom_select>7) rom_select = 7; // TODO
+				set_rom_select(rom_select);
+			}
+			break;
+		}
+	}
+}
+
 void actions()
 {
 	// Show some activity!
-	*atari_colbk = *atari_random;
+	//*atari_colbk = *atari_random;
 	
 	// Hot keys
 	if (get_hotkey_softboot())
@@ -215,9 +326,8 @@
 		set_pause_6502(1);
 		freeze();
 		debug_pos = 0;	
-		printf("Hello world - settings");
+		settings();
 		debug_pos = -1;
-		wait_us(1000000);
 		restore();
 		set_pause_6502(0);
 	}
@@ -225,12 +335,11 @@
 	{
 		set_pause_6502(1);
 		freeze();
-		debug_pos = 0;	
-		printf("Hello world - fileselect");
+		file_selector(files[0]);
 		debug_pos = -1;
-		wait_us(1000000);
 		restore();
-		set_pause_6502(0);
+		set_drive_status(0,files[0]);
+		reboot(1);
 	}
 }
 
Index: firmware/native/diskio_mmc.c
===================================================================
--- firmware/native/diskio_mmc.c	(nonexistent)
+++ firmware/native/diskio_mmc.c	(revision 49)
@@ -0,0 +1 @@
+link ../sd_direct/diskio_mmc.c
\ No newline at end of file

Property changes on: firmware/native/diskio_mmc.c
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Index: firmware/native/joystick.c
===================================================================
--- firmware/native/joystick.c	(nonexistent)
+++ firmware/native/joystick.c	(revision 49)
@@ -0,0 +1,116 @@
+#include "joystick.h"
+#include <poll.h>
+#include <termios.h>
+#include <unistd.h>
+
+extern char native_porta;
+extern char native_trig;
+
+struct termios oldt, newt;
+void term_init()
+{
+	tcgetattr(STDIN_FILENO, &oldt);
+	newt = oldt;
+	newt.c_lflag &= ~( ICANON | ECHO );
+	tcsetattr( STDIN_FILENO, TCSANOW, &newt);
+}
+
+void term_close()
+{
+	tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
+}
+
+void read_keys()
+{
+	struct pollfd fds[1];
+	fds[0].fd = STDIN_FILENO;
+	fds[0].events = POLLIN;
+	native_porta = 0xff;
+	native_trig = 0xff;
+	while (poll(&fds[0], 1, 0))
+	{
+		char buffer[0];
+		read(0,&buffer[0],1);
+
+	/*	if (buffer[0] == 0x41) fprintf(stderr, "UP\n");
+		if (buffer[0] == 0x42) fprintf(stderr, "DOWN\n");
+		if (buffer[0] == 0x44) fprintf(stderr, "LEFT\n");
+		if (buffer[0] == 0x43) fprintf(stderr, "RIGHT\n");
+		if (buffer[0] == 0x20) fprintf(stderr, "FIRE\n");*/
+
+		// RLDU
+		if (buffer[0] == 0x41) native_porta=0xff&~(1<<0);
+		if (buffer[0] == 0x42) native_porta=0xff&~(1<<1);
+		if (buffer[0] == 0x44) native_porta=0xff&~(1<<2);
+		if (buffer[0] == 0x43) native_porta=0xff&~(1<<3);
+		if (buffer[0] == 0x20) native_trig=0xff&~1;
+
+		fds[0].fd = STDIN_FILENO;
+		fds[0].events = POLLIN;
+	}
+}
+
+#include "regs.h"
+
+void joystick_poll(struct joystick_status * status)
+{
+	static int first = 1;
+	if (first)
+	{
+		first = 0;
+		term_init();
+	}
+
+	read_keys();
+
+	status->x_ = 0;
+	status->y_ = 0;
+	status->fire_ = 0;
+
+	unsigned char porta = *atari_porta;
+	if (0==(porta&0x2)) // down
+	{
+		status->y_ =1;
+	}
+	else if (0==(porta&0x1)) // up
+	{
+		status->y_ =-1;
+	}
+	if (0==(porta&0x8)) // right
+	{
+		status->x_ = 1;
+	}
+	else if (0==(porta&0x4)) // left
+	{
+		status->x_ = -1;
+	}
+	if (0==(1&*atari_trig0)) // fire
+	{
+		status->fire_ = 1;
+	}
+}
+
+void joystick_wait(struct joystick_status * status, enum JoyWait waitFor)
+{
+	while (1)
+	{
+		joystick_poll(status);
+		switch (waitFor)
+		{
+		case WAIT_QUIET:
+			if (status->x_ == 0 && status->y_ == 0 && status->fire_ == 0) return;
+			break;
+		case WAIT_FIRE:
+			if (status->fire_ == 1) return;
+			break;
+		case WAIT_EITHER:
+			if (status->fire_ == 1) return;
+			// fall through
+		case WAIT_MOVE:
+			if (status->x_ != 0 || status->y_ != 0) return;
+			break;
+		}
+	}
+}
+
+
Index: firmware/native/mmc.c
===================================================================
--- firmware/native/mmc.c	(nonexistent)
+++ firmware/native/mmc.c	(revision 49)
@@ -0,0 +1,48 @@
+#include "mmc.h"
+
+#include <stdio.h>
+
+FILE * disk_image;
+char mmc_sector_buffer[512];
+
+void set_spi_clock_freq()
+{
+}
+
+//! Initialize AVR<->MMC hardware interface.
+/// Prepares hardware for MMC access.
+void mmcInit(void)
+{
+	disk_image = fopen("sd.image","r+");
+
+	fprintf(stderr,"mmcInit:%x\n",disk_image);
+}
+
+//! Initialize the card and prepare it for use.
+/// Returns zero if successful.
+u08 mmcReset(void){ return 0;}
+
+//! Read 512-byte sector from card to buffer
+/// Returns zero if successful.
+u08 mmcRead(u32 sector)
+{
+	fprintf(stderr,"mmcRead:%x\n",sector);
+
+	fseek(disk_image, sector*512, SEEK_SET);
+	fread(&mmc_sector_buffer,512,1,disk_image);
+
+	return 0;
+}
+
+//! Write 512-byte sector from buffer to card
+/// Returns zero if successful.
+u08 mmcWrite(u32 sector)
+{
+	fprintf(stderr,"mmcWrite:%x\n",sector);
+
+	fseek(disk_image, sector*512, SEEK_SET);
+	fwrite(&mmc_sector_buffer,512,1,disk_image);
+
+	return 0;
+}
+
Index: firmware/native/mmc.h
===================================================================
--- firmware/native/mmc.h	(nonexistent)
+++ firmware/native/mmc.h	(revision 49)
@@ -0,0 +1 @@
+link ../sd_direct/mmc.h
\ No newline at end of file

Property changes on: firmware/native/mmc.h
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Index: firmware/native/regs.c
===================================================================
--- firmware/native/regs.c	(revision 48)
+++ firmware/native/regs.c	(revision 49)
@@ -3,6 +3,6 @@
 char native_porta;
 char native_trig;
 
-unsigned char volatile * atari_porta = &native_porta;
-unsigned char volatile * atari_trig0 = &native_trig;
+unsigned char volatile * atari_porta = (unsigned char volatile *)&native_porta;
+unsigned char volatile * atari_trig0 = (unsigned char volatile *)&native_trig;
 
Index: firmware/native/spi.h
===================================================================
Index: firmware/sd_direct/diskio_mmc.c
===================================================================
--- firmware/sd_direct/diskio_mmc.c	(revision 48)
+++ firmware/sd_direct/diskio_mmc.c	(revision 49)
@@ -96,7 +96,7 @@
 	for(;count>0;++sofs,--count)
 	{
 		unsigned char x = mmc_sector_buffer[sofs];
-		//printf("char:%02x loc:%d", x,sofs);
+		//printf("char:%c loc:%d ", x,sofs);
 		*dest++ = x;
 	}
 
@@ -111,26 +111,36 @@
 /* Write Partial Sector                                                  */
 /*-----------------------------------------------------------------------*/
 
-DRESULT disk_writep (const BYTE* buff, DWORD sc)
+DRESULT disk_writep (const BYTE* buff, DWORD sofs, DWORD count)
 {
 	DRESULT res;
 
+	int i=sofs;
+	int end=sofs+count;
+	int pos = 0;
+	for (;i!=end;++i,++pos)
+	{
+		mmc_sector_buffer[i] = buff[pos];
+		//printf("char:%c loc:%d,", buff[pos],i);
+	}
 
-	if (!buff) {
-		if (sc) {
+	res = RES_OK;
 
-			// Initiate write process
+	return res;
+}
 
-		} else {
+void disk_writeflush()
+{
+	// Finalize write process
+	int retry=16; //zkusi to maximalne 16x
+	int ret;
+	printf(":WSECT:%d",n_actual_mmc_sector);
+	do
+	{
+		ret = mmcWrite(n_actual_mmc_sector); //vraci 0 kdyz ok
+		retry--;
+	} while (ret && retry);
+	printf(":WD:");
+}
 
-			// Finalize write process
 
-		}
-	} else {
-
-		// Send data to the disk
-
-	}
-
-	return res;
-}
Index: firmware/simpledir.h
===================================================================
--- firmware/simpledir.h	(revision 48)
+++ firmware/simpledir.h	(revision 49)
@@ -12,6 +12,7 @@
 
 // Reads entire dir into memory (i.e. give it a decent chunk of sdram)
 enum SimpleFileStatus dir_init(void * mem, int space);
+struct SimpleDirEntry * dir_entries_filtered(char const * dirPath, int (*filter)(struct SimpleDirEntry *));
 struct SimpleDirEntry * dir_entries(char const * dirPath);
 
 char const * dir_filename(struct SimpleDirEntry *);
Index: firmware/simplefile.h
===================================================================
--- firmware/simplefile.h	(revision 48)
+++ firmware/simplefile.h	(revision 49)
@@ -10,7 +10,9 @@
 
 char const * file_name(struct SimpleFile * file);
 enum SimpleFileStatus file_read(struct SimpleFile * file, void * buffer, int bytes, int * bytesread);
-enum SimpleFileStatus file_write(struct SimpleFile * file, void * buffer, int bytes, int * byteswritten);
 enum SimpleFileStatus file_seek(struct SimpleFile * file, int offsetFromStart);
 int file_size(struct SimpleFile * file);
 
+enum SimpleFileStatus file_write(struct SimpleFile * file, void * buffer, int bytes, int * byteswritten);
+enum SimpleFileStatus file_write_flush();
+
Index: firmware/test_file.c
===================================================================
--- firmware/test_file.c	(revision 48)
+++ firmware/test_file.c	(revision 49)
@@ -1,5 +1,6 @@
 #include "simpledir.h"
 #include "simplefile.h"
+#include "fileselector.h"
 
 //#include "fat/pff_file.h"
 // XXX - BEST NOT to include this?
@@ -7,8 +8,22 @@
 #include "stdio.h"
 #include "stdlib.h"
 
+int debug_pos = 0;
+int debug_adjust = 0;
+void wait_us(int us)
+{
+	usleep(us);
+}
+
+void char_out ( void* p, char c)
+{
+	putc(c, stderr);
+}
+
 int main(void)
 {
+	init_printf(NULL, char_out);
+
 	char * mem = (char *)malloc(8192);
 	if (SimpleFile_OK != dir_init(mem, 8192))
 	{
@@ -57,6 +72,7 @@
 //enum SimpleFileStatus file_open_name(char const * path, struct SimpleFile * file);
 //enum SimpleFileStatus file_open_dir(struct SimpleDirEntry * filename, struct SimpleFile * file);
 	entry = dir_entries("/UAE4ALL");
+	entry = dir_next(entry);
 	fprintf(stderr, " Name:%s", dir_filename(entry));
 	struct SimpleFile * file = alloca(file_struct_size());
 	file_open_dir(entry,file);
@@ -66,12 +82,12 @@
 //enum SimpleFileStatus file_write(struct SimpleFile * file, void * buffer, int bytes, int * byteswritten);
 //enum SimpleFileStatus file_seek(struct SimpleFile * file, int offsetFromStart);
 //int file_size(struct SimpleFile * file);
-	fprintf(stderr, " Size:%d", file_size(file));
+	fprintf(stderr, " Size:%d\n---\n", file_size(file));
 
 	int read = 0;
-	char buffer[1024];
-	file_seek(file,100);
-	file_read(file,&buffer[0],1024,&read);
+	char buffer[2048];
+	file_seek(file,10);
+	file_read(file,&buffer[0],2048,&read);
 	int i;
 	for (i=0; i!=read; ++i)
 	{
@@ -79,6 +95,36 @@
 		fprintf(stderr,"%c", buffer[i]);
 	}
 
+	fprintf(stderr,"\n\n");
+
+	int written;
+	file_seek(file,10);
+	file_write(file,"Mark",4,&written); // in order to write 'mark' as position 10...
+	//file_write_flush(); // Done automatically on next read, or can be forced with this...
+
+	file_seek(file,512);
+/*	for (i=0;i!=130;++i)
+	{
+		char towrite[9];
+		sprintf(&towrite[0],"Mark:%03d",i);
+		fprintf(stderr,"Writing \"%s\"\n",towrite);
+		file_write(file,towrite,8,&written);
+	}*/
+	file_write(file,"Blah",4,&written);
+
+	// So... for write can only seek to nearest 512...
+
+	fprintf(stderr,"\n\n");
+	file_seek(file,10);
+	file_read(file,&buffer[0],2048,&read);
+	for (i=0; i!=read; ++i)
+	{
+		//fprintf(stderr,"%02x", buffer[i]);
+		fprintf(stderr,"%c", buffer[i]);
+	}
+
+	//file_selector(file);
+
 	return 0;
 }
 
Index: firmware/test_freeze.c
===================================================================
--- firmware/test_freeze.c	(nonexistent)
+++ firmware/test_freeze.c	(revision 49)
@@ -0,0 +1,64 @@
+#include "regs.h"
+
+#include "stdlib.h"
+#include "stdio.h"
+
+#undef atari_regbase
+static char * atari_regbase = (char *)malloc(65536);
+#undef atari_regmirror
+static char * atari_regmirror = (char *)malloc(65536);
+#include "freeze.h"
+#include "freeze.c"
+#include "regs.c"
+
+int main(void)
+{
+	char * buffer = (char *)malloc(1024*128);
+	freeze_init(buffer);
+
+	for (int i=0; i!=64*1024; ++i)
+	{
+		*((unsigned char *)(atari_regbase+i)) = i%256;
+	}
+	
+	for (int i=0;i!=0x10000;++i)
+	{
+		*((atari_regmirror+i)) = i%256-2;
+	}
+	freeze();
+	/*for (int i=0; i!=64*1024; ++i)
+	{
+		fprintf(stderr,"i:%x val:%x\n",i,*((unsigned char *)(buffer+i)));
+		if (i%256!=*((unsigned char *)(buffer+i)))
+		{
+			fprintf(stderr,"!!FAIL!%d %d %d", i, i%256, *(unsigned char *)(atari_regbase+i));
+			return -1;
+		}
+	}*/
+
+	for (int i=0;i!=0xd000; ++i)
+	{
+		*((atari_regbase+i)) = 0;
+	}
+	for (int i=0xd800;i!=0x10000; ++i)
+	{
+		*((atari_regbase+i)) = 0;
+	}
+	restore();
+
+	for (int i=0; i!=64*1024; ++i)
+	{
+		unsigned char exp = i%256;
+		if (i>=0xd000 && i<0xd800) exp-=2;
+		if (i>=0xd020 && i<0xd200) exp+=2;
+		if (i>=0xd220 && i<0xd400) exp+=2;
+		if (i>=0xd410 && i<0xd800) exp+=2;
+		if (exp!=*((unsigned char *)(atari_regbase+i)))
+		{
+			fprintf(stderr,"FAIL!addr:%x exp:%d got:%d", i, exp, *(unsigned char *)(atari_regbase+i));
+			return -1;
+		}
+	}
+	return 0;
+}
+
