Revision 49
Added by markw over 11 years ago
| firmware/native/diskio_image.c | ||
|---|---|---|
| 
     #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;
 
   | 
||
| 
     }
 
   | 
||
| 
     | 
||
| firmware/Makefile | ||
|---|---|---|
| 
     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))
 
   | 
||
| firmware/atari_drive_emulator.c | ||
|---|---|---|
| 
     #include "atari_drive_emulator.h"
 
   | 
||
| 
     #include "fileutils.h"
 
   | 
||
| 
     | 
||
| 
     #include "uart.h"
 
   | 
||
| 
     #include "pause.h"
 
   | 
||
| ... | ... | |
| 
     #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');
 
   | 
||
| ... | ... | |
| 
     	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;
 
   | 
||
| 
     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);
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     		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,
 
   | 
||
| ... | ... | |
| 
     	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)
 
   | 
||
| 
     {
 
   | 
||
| ... | ... | |
| 
     	*/
 
   | 
||
| 
     | 
||
| 
     	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)
 
   | 
||
| 
     	{
 
   | 
||
| ... | ... | |
| 
     		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
 
   | 
||
| 
     	{
 
   | 
||
| ... | ... | |
| 
     		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
 
   | 
||
| 
     	{
 
   | 
||
| ... | ... | |
| 
     		printf("%d",drive);
 
   | 
||
| 
     		if (drive!=opendrive)
 
   | 
||
| 
     		{
 
   | 
||
| 
     			if (drive<MAX_DRIVES)
 
   | 
||
| 
     			if (drive<MAX_DRIVES && drive>=0)
 
   | 
||
| 
     			{
 
   | 
||
| 
     				opendrive = drive;
 
   | 
||
| 
     				set_drive_status(drive, drives[drive]);
 
   | 
||
| 
     			}
 
   | 
||
| 
     		}
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     			printf(":done\n");
 
   | 
||
| 
     			}
 
   | 
||
| 
     			break;
 
   | 
||
| 
     		case 0x50: // write
 
   | 
||
| 
     		case 0x57: // write with verify
 
   | 
||
| 
     		default:
 
   | 
||
| 
     			// TODO
 
   | 
||
| 
     			//USART_Transmit_Mode();
 
   | 
||
| ... | ... | |
| 
     			//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);
 
   | 
||
| ... | ... | |
| 
     	}
 
   | 
||
| 
     }
 
   | 
||
| 
     | 
||
| 
     unsigned char get_checksum(unsigned char* buffer, u16 len)
 
   | 
||
| 
     unsigned char get_checksum(unsigned char* buffer, int len)
 
   | 
||
| 
     {
 
   | 
||
| 
     	u16 i;
 
   | 
||
| 
     	u08 sumo,sum;
 
   | 
||
| ... | ... | |
| 
     		sum+=buffer[i];
 
   | 
||
| 
     		if(sum<sumo) sum++;
 
   | 
||
| 
     		sumo = sum;
 
   | 
||
| 
     | 
||
| 
     		//printf("c:%02x:",sumo);
 
   | 
||
| 
     	}
 
   | 
||
| 
     	return sum;
 
   | 
||
| 
     }
 
   | 
||
| firmware/build_native_file_test | ||
|---|---|---|
| 
     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
 
   | 
||
| firmware/common/utils.c | ||
|---|---|---|
| 
     	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;
 
   | 
||
| firmware/common/utils.h | ||
|---|---|---|
| 
     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);
 
   | 
||
| 
     | 
||
| firmware/fat/diskio.h | ||
|---|---|---|
| 
     | 
||
| 
     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 */
 
   | 
||
| firmware/fat/pff.h | ||
|---|---|---|
| 
     | 
||
| 
     #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 */
 
   | 
||
| firmware/fat/pff_file.c | ||
|---|---|---|
| 
     DIR dir;
 
   | 
||
| 
     FILINFO filinfo;
 
   | 
||
| 
     | 
||
| 
     int write_pending;
 
   | 
||
| 
     | 
||
| 
     enum SimpleFileStatus translateStatus(FRESULT res)
 
   | 
||
| 
     {
 
   | 
||
| 
     	return res == FR_OK ? SimpleFile_OK: SimpleFile_FAIL;
 
   | 
||
| ... | ... | |
| 
     {
 
   | 
||
| 
     	if (openfile!=file)
 
   | 
||
| 
     	{
 
   | 
||
| 
     		file_write_flush();
 
   | 
||
| 
     | 
||
| 
     		pf_open(&file->path[0]);
 
   | 
||
| 
     		openfile = file;
 
   | 
||
| 
     	}
 
   | 
||
| ... | ... | |
| 
     	WORD bytesread_word;
 
   | 
||
| 
     	FRESULT res;
 
   | 
||
| 
     | 
||
| 
     	file_write_flush();
 
   | 
||
| 
     	file_check_open(file);
 
   | 
||
| 
     | 
||
| 
     	res = pf_read(buffer, bytes, &bytesread_word);
 
   | 
||
| ... | ... | |
| 
     	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);
 
   | 
||
| ... | ... | |
| 
     	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]);
 
   | 
||
| ... | ... | |
| 
     	strcpy(&file->path[0],dir->path);
 
   | 
||
| 
     	file->size = dir->size;
 
   | 
||
| 
     | 
||
| 
     	file_write_flush();
 
   | 
||
| 
     | 
||
| 
     	res = pf_open(&file->path[0]);
 
   | 
||
| 
     	openfile = file;
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     	FRESULT fres;
 
   | 
||
| 
     	DSTATUS res;
 
   | 
||
| 
     | 
||
| 
     	write_pending = -1;
 
   | 
||
| 
     | 
||
| 
     	printf("dir_init\n");
 
   | 
||
| 
     | 
||
| 
     	dir_cache = mem;
 
   | 
||
| ... | ... | |
| 
     }
 
   | 
||
| 
     | 
||
| 
     // 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))
 
   | 
||
| 
     	{
 
   | 
||
| ... | ... | |
| 
     	}
 
   | 
||
| 
     	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;
 
   | 
||
| ... | ... | |
| 
     			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
 
   | 
||
| ... | ... | |
| 
     		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);
 
   | 
||
| 
     	}
 
   | 
||
| 
     | 
||
| firmware/fileselector.c | ||
|---|---|---|
| 
     #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;
 
   | 
||
| 
     }
 
   | 
||
| 
     | 
||
| 
     | 
||
| firmware/fileselector.h | ||
|---|---|---|
| 
     #pragma once
 
   | 
||
| 
     | 
||
| 
     void file_select(void (*filter) (char const *), char const * path, struct SimpleFile * file);
 
   | 
||
| 
     void file_selector(struct SimpleFile * file);
 
   | 
||
| 
     | 
||
| firmware/fileutils.c | ||
|---|---|---|
| 
     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;
 
   | 
||
| 
     }
 
   | 
||
| 
     | 
||
| firmware/fileutils.h | ||
|---|---|---|
| 
     #pragma once
 
   | 
||
| 
     | 
||
| 
     int compare_ext(char const * filename, char const * ext);
 
   | 
||
| 
     | 
||
| firmware/joystick.h | ||
|---|---|---|
| 
     | 
||
| 
     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};
 
   | 
||
| firmware/main.c | ||
|---|---|---|
| 
     #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"
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     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)
 
   | 
||
| ... | ... | |
| 
     }
 
   | 
||
| 
     | 
||
| 
     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;
 
   | 
||
| 
     	}
 
   | 
||
| 
     }
 
   | 
||
| ... | ... | |
| 
     // 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);
 
   | 
||
| ... | ... | |
| 
     //			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())
 
   | 
||
| ... | ... | |
| 
     		set_pause_6502(1);
 
   | 
||
| 
     		freeze();
 
   | 
||
| 
     		debug_pos = 0;	
 
   | 
||
| 
     		printf("Hello world - settings");
 
   | 
||
| 
     		settings();
 
   | 
||
| 
     		debug_pos = -1;
 
   | 
||
| 
     		wait_us(1000000);
 
   | 
||
| 
     		restore();
 
   | 
||
| 
     		set_pause_6502(0);
 
   | 
||
| 
     	}
 
   | 
||
| ... | ... | |
| 
     	{
 
   | 
||
| 
     		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);
 
   | 
||
| 
     	}
 
   | 
||
| 
     }
 
   | 
||
| 
     | 
||
| firmware/native/diskio_mmc.c | ||
|---|---|---|
| 
     link ../sd_direct/diskio_mmc.c
 
   | 
||
| firmware/native/joystick.c | ||
|---|---|---|
| 
     #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;
 
   | 
||
| 
     		}
 
   | 
||
| 
     	}
 
   | 
||
| 
     }
 
   | 
||
| 
     | 
||
| 
     | 
||
| firmware/native/mmc.c | ||
|---|---|---|
| 
     #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;
 
   | 
||
| 
     }
 
   | 
||
| 
     | 
||
| firmware/native/mmc.h | ||
|---|---|---|
| 
     link ../sd_direct/mmc.h
 
   | 
||
| firmware/native/regs.c | ||
|---|---|---|
| 
     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;
 
   | 
||
| 
     | 
||
| firmware/sd_direct/diskio_mmc.c | ||
|---|---|---|
| 
     	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;
 
   | 
||
| 
     	}
 
   | 
||
| 
     | 
||
| ... | ... | |
| 
     /* 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;
 
   | 
||
| 
     }
 
   | 
||
| firmware/simpledir.h | ||
|---|---|---|
| 
     | 
||
| 
     // 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 *);
 
   | 
||
| firmware/simplefile.h | ||
|---|---|---|
| 
     | 
||
| 
     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();
 
   | 
||
| 
     | 
||
| firmware/test_file.c | ||
|---|---|---|
| 
     #include "simpledir.h"
 
   | 
||
First cut of write support