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"
|
Also available in: Unified diff
First cut of write support