Merge branch 'master' of ssh://shion.micecat.ath.cx/~ikari/public_html/git/sd2snes

This commit is contained in:
Maximilian Rehkopf 2009-09-25 23:02:54 +02:00
commit b9d119ada5
20 changed files with 3888 additions and 3643 deletions

Binary file not shown.

Binary file not shown.

View File

@ -100,7 +100,7 @@ FORMAT = ihex
TARGET = $(OBJDIR)/sd2snes
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c ff.c utils.c timer.c led.c diskio.c sdcard.c spi.c crc7.c snes.c fpga.c memory.c crc16.c fileops.c fpga_spi.c filetypes.c
SRC = main.c ff.c utils.c timer.c led.c diskio.c sdcard.c spi.c crc7.c snes.c fpga.c memory.c crc16.c fileops.c fpga_spi.c smc.c filetypes.c
ifeq ($(CONFIG_UART_DEBUG),y)
SRC += uart.c
@ -119,8 +119,8 @@ ASRC =
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
# Use s -mcall-prologues when you really need size...
#OPT = 2
OPT = 3 -finline-functions
OPT = s
#OPT = 3 -finline-functions
# Debugging format.
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.

View File

@ -35,7 +35,7 @@ CONFIG_UART_BAUDRATE=38400
CONFIG_UART_BUF_SHIFT=7
CONFIG_HARDWARE_NAME=sd2snes
CONFIG_SD_AUTO_RETRIES=10
#CONFIG_SD_DATACRC=y
CONFIG_SD_DATACRC=y
CONFIG_EEPROM_SIZE=512
CONFIG_EEPROM_OFFSET=512
CONFIG_MAX_PARTITIONS=2
CONFIG_MAX_PARTITIONS=1

View File

@ -2,59 +2,20 @@
* \file stdout
* Functions and types for CRC checks.
*
* Generated on Tue Sep 15 09:32:35 2009,
* Generated on Tue Jun 30 23:02:59 2009,
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
* using the configuration:
* Width = 16
* Poly = 0x8005
* XorIn = 0xffff
* XorIn = 0x0000
* ReflectIn = True
* XorOut = 0xffff
* XorOut = 0x0000
* ReflectOut = True
* Algorithm = table-driven
* Algorithm = bit-by-bit-fast
* Direct = True
*****************************************************************************/
#include "crc16.h"
#include <stdint.h>
/**
* Static table used for the table_driven implementation.
*****************************************************************************/
static const crc_t crc_table[256] = {
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
};
#include "crc16.h"
/**
* Update the crc value with new data.
*
@ -65,14 +26,26 @@ static const crc_t crc_table[256] = {
*****************************************************************************/
crc_t crc16_update(crc_t crc, const unsigned char *data, size_t data_len)
{
unsigned int tbl_idx;
unsigned int i;
uint8_t bit;
unsigned char c;
while (data_len--) {
tbl_idx = (crc ^ *data) & 0xff;
crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffff;
data++;
c = *data++;
for (i = 0x01; i & 0xff; i <<= 1) {
bit = (crc & 0x8000 ? 1 : 0);
if (c & i) {
bit ^= 1;
}
crc <<= 1;
if (bit) {
crc ^= 0x8005;
}
}
crc &= 0xffff;
}
return crc & 0xffff;
}

5972
src/ff.c

File diff suppressed because it is too large Load Diff

994
src/ff.h
View File

@ -1,547 +1,447 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.07a (C)ChaN, 2009
/----------------------------------------------------------------------------/
/ FatFs module is an open source software to implement FAT file system to
/ small embedded systems. This is a free software and is opened for education,
/ research and commercial developments under license policy of following trems.
/
/ Copyright (C) 2009, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/----------------------------------------------------------------------------*/
#include "integer.h"
/*---------------------------------------------------------------------------/
/ FatFs Configuration Options
/
/ CAUTION! Do not forget to make clean the project after any changes to
/ the configuration options.
/
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS
#define _WORD_ACCESS 0
/* The _WORD_ACCESS option defines which access method is used to the word
/ data in the FAT structure.
/
/ 0: Byte-by-byte access. Always compatible with all platforms.
/ 1: Word access. Do not choose this unless following condition is met.
/
/ When the byte order on the memory is big-endian or address miss-aligned
/ word access results incorrect behavior, the _WORD_ACCESS must be set to 0.
/ If it is not the case, the value can also be set to 1 to improve the
/ performance and code efficiency. */
#define _FS_READONLY 0
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
/ f_truncate and useless f_getfree. */
#define _FS_MINIMIZE 0
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/
/ 0: Full function.
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
/ are removed.
/ 2: f_opendir and f_readdir are removed in addition to level 1.
/ 3: f_lseek is removed in addition to level 2. */
#define _FS_TINY 0
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
/ object instead of the sector buffer in the individual file object for file
/ data transfer. This reduces memory consumption 512 bytes each file object. */
#define _USE_STRFUNC 0
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
#define _USE_MKFS 0
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
#define _USE_FORWARD 0
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
#define _DRIVES 1
/* Number of volumes (logical drives) to be used. */
#define _MAX_SS 512
/* Maximum sector size to be handled. (512/1024/2048/4096) */
/* 512 for memroy card and hard disk, 1024 for floppy disk, 2048 for MO disk */
#define _MULTI_PARTITION 0
/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical
/ drive number and can mount only first primaly partition. When it is set to 1,
/ each volume is tied to the partitions listed in Drives[]. */
#define _CODE_PAGE 850
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
/ When it is non LFN configuration, there is no difference between SBCS code
/ pages. When LFN is enabled, the code page must always be set correctly.
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 775 - Baltic
/ 850 - Multilingual Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 858 - Multilingual Latin 1 + Euro
/ 862 - Hebrew
/ 866 - Russian
/ 874 - Thai
/ 932 - Japanese Shift-JIS (DBCS)
/ 936 - Simplified Chinese GBK (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese Big5 (DBCS)
/ 1258 - Vietnam
*/
#define _USE_LFN 0
#define _MAX_LFN 255 /* Maximum LFN length to handle (max:255) */
/* The _USE_LFN option switches the LFN support.
/
/ 0: Disable LFN.
/ 1: Enable LFN with static working buffer on the bss. NOT REENTRANT.
/ 2: Enable LFN with dynamic working buffer on the caller's STACK.
/
/ The working buffer occupies (_MAX_LFN + 1) * 2 bytes. When enable LFN,
/ a Unicode - OEM code conversion function ff_convert() must be added to
/ the project. */
#define _FS_REENTRANT 0
#define _TIMEOUT 1000 /* Timeout period in unit of time ticks */
#define _SYNC_t HANDLE /* Type of sync object used on the OS. */
/* e.g. HANDLE, OS_EVENT*, ID and etc.. */
/* To make the FatFs module re-entrant, set _FS_REENTRANT to 1 and add user
/ provided synchronization handlers, ff_req_grant, ff_rel_grant,
/ ff_del_syncobj and ff_cre_syncobj function to the project. */
/* End of configuration options. Do not change followings without care. */
/*--------------------------------------------------------------------------*/
/* Definitions corresponds to multiple sector size */
#if _MAX_SS == 512
#define SS(fs) 512
#else
#if _MAX_SS == 1024 || _MAX_SS == 2048 || _MAX_SS == 4096
#define SS(fs) ((fs)->s_size)
#else
#error Sector size must be 512, 1024, 2048 or 4096.
#endif
#endif
/* File system object structure */
typedef struct _FATFS {
BYTE fs_type; /* FAT sub type */
BYTE drive; /* Physical drive number */
BYTE csize; /* Number of sectors per cluster */
BYTE n_fats; /* Number of FAT copies */
BYTE wflag; /* win[] dirty flag (1:must be written back) */
BYTE pad1;
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (0 on FAT32) */
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if _MAX_SS != 512U
WORD s_size; /* Sector size */
#endif
#if !_FS_READONLY
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
BYTE pad2;
DWORD last_clust; /* Last allocated cluster */
DWORD free_clust; /* Number of free clusters */
DWORD fsi_sector; /* fsinfo sector */
#endif
DWORD sects_fat; /* Sectors per fat */
DWORD max_clust; /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */
DWORD fatbase; /* FAT start sector */
DWORD dirbase; /* Root directory start sector (Cluster# on FAT32) */
DWORD database; /* Data start sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS];/* Disk access window for Directory/FAT */
} FATFS;
/* Directory object structure */
typedef struct _DIR {
WORD id; /* Owner file system mount ID */
WORD index; /* Current index number */
FATFS* fs; /* Pointer to the owner file system object */
DWORD sclust; /* Table start cluster (0:Static table) */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _USE_LFN
WCHAR* lfn; /* Pointer to the LFN working buffer */
WORD lfn_idx; /* Last matched LFN index (0xFFFF:No LFN) */
#endif
} DIR;
/* File object structure */
typedef struct _FIL {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */
BYTE csect; /* Sector address in the cluster */
DWORD fptr; /* File R/W pointer */
DWORD fsize; /* File size */
DWORD org_clust; /* File start cluster */
DWORD curr_clust; /* Current cluster */
DWORD dsect; /* Current data sector */
#if !_FS_READONLY
DWORD dir_sect; /* Sector containing the directory entry */
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS];/* File R/W buffer */
#endif
} FIL;
/* File status structure */
typedef struct _FILINFO {
DWORD fsize; /* File size */
WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */
BYTE fattrib; /* Attribute */
char fname[13]; /* Short file name (8.3 format) */
#if _USE_LFN
char *lfname; /* Pointer to the LFN buffer */
int lfsize; /* Size of LFN buffer [bytes] */
#endif
} FILINFO;
/* DBCS code ranges */
#if _CODE_PAGE == 932 /* CP932 (Japanese Shift-JIS) */
#define _DF1S 0x81 /* DBC 1st byte range 1 start */
#define _DF1E 0x9F /* DBC 1st byte range 1 end */
#define _DF2S 0xE0 /* DBC 1st byte range 2 start */
#define _DF2E 0xFC /* DBC 1st byte range 2 end */
#define _DS1S 0x40 /* DBC 2nd byte range 1 start */
#define _DS1E 0x7E /* DBC 2nd byte range 1 end */
#define _DS2S 0x80 /* DBC 2nd byte range 2 start */
#define _DS2E 0xFC /* DBC 2nd byte range 2 end */
#elif _CODE_PAGE == 936 /* CP936 (Simplified Chinese GBK) */
#define _DF1S 0x81
#define _DF1E 0xFE
#define _DS1S 0x40
#define _DS1E 0x7E
#define _DS2S 0x80
#define _DS2E 0xFE
#elif _CODE_PAGE == 949 /* CP949 (Korean) */
#define _DF1S 0x81
#define _DF1E 0xFE
#define _DS1S 0x41
#define _DS1E 0x5A
#define _DS2S 0x61
#define _DS2E 0x7A
#define _DS3S 0x81
#define _DS3E 0xFE
#elif _CODE_PAGE == 950 /* CP950 (Traditional Chinese Big5) */
#define _DF1S 0x81
#define _DF1E 0xFE
#define _DS1S 0x40
#define _DS1E 0x7E
#define _DS2S 0xA1
#define _DS2E 0xFE
#else /* SBCS code pages */
#define _DF1S 0
#endif
/* Character code support macros */
#define IsUpper(c) (((c)>='A')&&((c)<='Z'))
#define IsLower(c) (((c)>='a')&&((c)<='z'))
#define IsDigit(c) (((c)>='0')&&((c)<='9'))
#if _DF1S /* DBCS configuration */
#if _DF2S /* Two 1st byte areas */
#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
#else /* One 1st byte area */
#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
#endif
#if _DS3S /* Three 2nd byte areas */
#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
#else /* Two 2nd byte areas */
#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
#endif
#else /* SBCS configuration */
#define IsDBCS1(c) 0
#define IsDBCS2(c) 0
#endif /* _DF1S */
/* Definitions corresponds to multi partition */
#if _MULTI_PARTITION /* Multiple partition configuration */
typedef struct _PARTITION {
BYTE pd; /* Physical drive# */
BYTE pt; /* Partition # (0-3) */
} PARTITION;
extern
const PARTITION Drives[]; /* Logical drive# to physical location conversion table */
#define LD2PD(drv) (Drives[drv].pd) /* Get physical drive# */
#define LD2PT(drv) (Drives[drv].pt) /* Get partition# */
#else /* Single partition configuration */
#define LD2PD(drv) (drv) /* Physical drive# is equal to the logical drive# */
#define LD2PT(drv) 0 /* Always mounts the 1st partition */
#endif
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* 0 */
FR_DISK_ERR, /* 1 */
FR_INT_ERR, /* 2 */
FR_NOT_READY, /* 3 */
FR_NO_FILE, /* 4 */
FR_NO_PATH, /* 5 */
FR_INVALID_NAME, /* 6 */
FR_DENIED, /* 7 */
FR_EXIST, /* 8 */
FR_INVALID_OBJECT, /* 9 */
FR_WRITE_PROTECTED, /* 10 */
FR_INVALID_DRIVE, /* 11 */
FR_NOT_ENABLED, /* 12 */
FR_NO_FILESYSTEM, /* 13 */
FR_MKFS_ABORTED, /* 14 */
FR_TIMEOUT /* 15 */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
FRESULT f_open (FIL*, const char*, BYTE); /* Open or create a file */
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
FRESULT f_close (FIL*); /* Close an open file object */
FRESULT f_opendir (DIR*, const char*); /* Open an existing directory */
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
FRESULT f_stat (const char*, FILINFO*); /* Get file status */
FRESULT f_getfree (const char*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
FRESULT f_truncate (FIL*); /* Truncate file */
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
FRESULT f_unlink (const char*); /* Delete an existing file or directory */
FRESULT f_mkdir (const char*); /* Create a new directory */
FRESULT f_chmod (const char*, BYTE, BYTE); /* Change attriburte of the file/dir */
FRESULT f_utime (const char*, const FILINFO*); /* Change timestamp of the file/dir */
FRESULT f_rename (const char*, const char*); /* Rename/Move a file or directory */
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
FRESULT f_mkfs (BYTE, BYTE, WORD); /* Create a file system on the drive */
#if _USE_STRFUNC
int f_putc (int, FIL*); /* Put a character to the file */
int f_puts (const char*, FIL*); /* Put a string to the file */
int f_printf (FIL*, const char*, ...); /* Put a formatted string to the file */
char* f_gets (char*, int, FIL*); /* Get a string from the file */
#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
#ifndef EOF
#define EOF -1
#endif
#endif
/*--------------------------------------------------------------*/
/* User defined functions */
/* Real time clock */
#if !_FS_READONLY
DWORD get_fattime (void); /* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
/* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
#endif
/* Unicode - OEM code conversion */
#if _USE_LFN
WCHAR ff_convert (WCHAR, UINT);
#endif
/* Sync functions */
#if _FS_REENTRANT
BOOL ff_cre_syncobj(BYTE, _SYNC_t*);
BOOL ff_del_syncobj(_SYNC_t);
BOOL ff_req_grant(_SYNC_t);
void ff_rel_grant(_SYNC_t);
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access control and file status flags (FIL.flag) */
#define FA_READ 0x01
#define FA_OPEN_EXISTING 0x00
#if _FS_READONLY == 0
#define FA_WRITE 0x02
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA__WRITTEN 0x20
#define FA__DIRTY 0x40
#endif
#define FA__ERROR 0x80
/* FAT sub type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
/* File attribute bits for directory entry */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_VOL 0x08 /* Volume label */
#define AM_LFN 0x0F /* LFN entry */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#define AM_MASK 0x3F /* Mask of defined bits */
/* FatFs refers the members in the FAT structures with byte offset instead
/ of structure member because there are incompatibility of the packing option
/ between various compilers. */
#define BS_jmpBoot 0
#define BS_OEMName 3
#define BPB_BytsPerSec 11
#define BPB_SecPerClus 13
#define BPB_RsvdSecCnt 14
#define BPB_NumFATs 16
#define BPB_RootEntCnt 17
#define BPB_TotSec16 19
#define BPB_Media 21
#define BPB_FATSz16 22
#define BPB_SecPerTrk 24
#define BPB_NumHeads 26
#define BPB_HiddSec 28
#define BPB_TotSec32 32
#define BS_55AA 510
#define BS_DrvNum 36
#define BS_BootSig 38
#define BS_VolID 39
#define BS_VolLab 43
#define BS_FilSysType 54
#define BPB_FATSz32 36
#define BPB_ExtFlags 40
#define BPB_FSVer 42
#define BPB_RootClus 44
#define BPB_FSInfo 48
#define BPB_BkBootSec 50
#define BS_DrvNum32 64
#define BS_BootSig32 66
#define BS_VolID32 67
#define BS_VolLab32 71
#define BS_FilSysType32 82
#define FSI_LeadSig 0
#define FSI_StrucSig 484
#define FSI_Free_Count 488
#define FSI_Nxt_Free 492
#define MBR_Table 446
#define DIR_Name 0
#define DIR_Attr 11
#define DIR_NTres 12
#define DIR_CrtTime 14
#define DIR_CrtDate 16
#define DIR_FstClusHI 20
#define DIR_WrtTime 22
#define DIR_WrtDate 24
#define DIR_FstClusLO 26
#define DIR_FileSize 28
#define LDIR_Ord 0
#define LDIR_Attr 11
#define LDIR_Type 12
#define LDIR_Chksum 13
#define LDIR_FstClusLO 26
/*--------------------------------*/
/* Multi-byte word access macros */
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
#else /* Use byte-by-byte access to the FAT structure */
#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
#endif
#endif /* _FATFS */
/*--------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.06 (C)ChaN, 2008
/---------------------------------------------------------------------------/
/ FatFs module is an experimenal project to implement FAT file system to
/ cheap microcontrollers. This is a free software and is opened for education,
/ research and development under license policy of following trems.
/
/ Copyright (C) 2008, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is no warranty.
/ * You can use, modify and/or redistribute it for personal, non-profit or
/ * commercial use without any restriction under your responsibility.
/ * Redistributions of source code must retain the above copyright notice.
/
/---------------------------------------------------------------------------*/
#ifndef _FATFS
#define _MCU_ENDIAN 1
/* The _MCU_ENDIAN defines which access method is used to the FAT structure.
/ 1: Enable word access.
/ 2: Disable word access and use byte-by-byte access instead.
/ When the architectural byte order of the MCU is big-endian and/or address
/ miss-aligned access results incorrect behavior, the _MCU_ENDIAN must be set
/ to 2. If it is not the case, it can be set to 1 for good code efficiency. */
#define _FS_READONLY 0
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
/ f_truncate and useless f_getfree. */
#define _FS_MINIMIZE 0
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/ 0: Full function.
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename are removed.
/ 2: f_opendir and f_readdir are removed in addition to level 1.
/ 3: f_lseek is removed in addition to level 2. */
#define _USE_STRFUNC 0
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
#define _DRIVES 1
/*MAX_DRIVES*/
/* Number of physical drives to be used. This affects the size of internal
* table. (when using _USE_DRIVE_PREFIX */
#define _USE_MKFS 0
/* When _USE_MKFS is set to 1 and _FS_READONLY is set to 0, f_mkfs function is
/ enabled. */
#define _MULTI_PARTITION 0
/* When _MULTI_PARTITION is set to 0, each logical drive is bound to the same
/ physical drive number and can mount only 1st primary partition.
/
/ When it is set to 1, the low _PARTITION_MASK bits of each partition represent
/ the partition and the high (8-_PARTITION_MASK) bits represent the physical
/ drive */
#define _PARTITION_MASK 4
#define _USE_FSINFO 1
/* To enable FSInfo support on FAT32 volume, set _USE_FSINFO to 1. */
#define _USE_SJIS 0
/* When _USE_SJIS is set to 1, Shift-JIS code transparency is enabled, otherwise
/ only US-ASCII(7bit) code can be accepted as file/directory name. */
#define _USE_NTFLAG 0
/* When _USE_NTFLAG is set to 1, upper/lower case of the file name is preserved.
/ Note that the files are always accessed in case insensitive. */
#define _USE_CHDIR 0
#define _USE_CURR_DIR 1
#define _USE_LFN 1
/* Maximum number of characters to return for a LFN */
/* The buffer used for FILINFO.lfn must be at least */
/* _MAX_LFN_LENGTH+1 characters long! */
/* Note that if _USE_LFN_DBCS is set, this value */
/* represents the characters needed, not bytes */
#define _MAX_LFN_LENGTH 255
/* When _USE_LFN_DBCS is set to 1, FILINFO.lfn will contain a DBCS string, not
/ a simple ASCII string */
#define _USE_LFN_DBCS 0
/* When set to 1, All FIL objects will use the buffer. This reduces memory
/ requirements as open files will only require space for a FIL object, but
/ operate slower. When set, ff.c will behave like tff.c, but will allow
/ multiple filesystems. */
#define _USE_FS_BUF 1
/* When set to 1, All objects will use a static buffer. This reduces memory
/ requirements to the absolute minimum ~512 bytes for the buffer, but will
/ operate slower. This option can only be set if _USE_FS_BUF is set. */
#define _USE_1_BUF 1
/* If set to 1, FatFs will manage the FATFS structures after mounting. If
/ set to 0, the caller must send the correct drive FATFS structure for each
/ call. Normally, this should be set to 1, but if the caller wants to use
/ low level l_* functions or skip sending the drive number in the path string,
/ this must be turned off. */
#define _USE_DRIVE_PREFIX 1
/* If set to 1, FatFS will delay mounting the drive until first use. Normally,
/ this should be turned on. However, it cannot be used with
/ _USE_DRIVE_PREFIX = 0 */
#define _USE_DEFERRED_MOUNT 0
/* New features in 0.05a, not required yet */
#define _USE_TRUNCATE 0
#define _USE_UTIME 0
#include "integer.h"
#if _USE_LFN_DBCS != 0
#define S_LFN_OFFSET 26
#define S_LFN_INCREMENT 2
#else
#define S_LFN_OFFSET 13
#define S_LFN_INCREMENT 1
#endif
/* Definitions corresponds to multiple sector size (not tested) */
#define S_MAX_SIZ 512U /* Do not change */
#if S_MAX_SIZ > 512U
#define SS(fs) ((fs)->s_size)
#else
#define SS(fs) 512U
#endif
#if _USE_1_BUF == 1 && _USE_FS_BUF == 0
#error You can only use 1_BUF with _USE_FS_BUF at present
#define _USE_1_BUF 0
#endif
typedef struct _BUF {
DWORD sect;
BYTE dirty; /* dirty flag (1:must be written back) */
//BYTE pad1;
#if _USE_1_BUF != 0
struct _FATFS *fs;
#endif
BYTE data[S_MAX_SIZ]; /* Disk access window for Directory/FAT */
} BUF;
/* File system object structure */
typedef struct _FATFS {
//WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries */
DWORD sects_fat; /* Sectors per fat */
DWORD max_clust; /* Maximum cluster# + 1 */
DWORD fatbase; /* FAT start sector */
DWORD dirbase; /* Root directory start sector (cluster# for FAT32) */
DWORD database; /* Data start sector */
#if _USE_CHDIR != 0 || _USE_CURR_DIR != 0
DWORD curr_dir;
#endif
#if !_FS_READONLY
DWORD last_clust; /* Last allocated cluster */
DWORD free_clust; /* Number of free clusters */
#if _USE_FSINFO
DWORD fsi_sector; /* fsinfo sector */
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
//BYTE pad2;
#endif
#endif
BYTE fs_type; /* FAT sub type */
BYTE csize; /* Number of sectors per cluster */
#if S_MAX_SIZ > 512U
WORD s_size; /* Sector size */
#endif
BYTE n_fats; /* Number of FAT copies */
BYTE drive; /* Physical drive number */
#if _USE_1_BUF == 0
BUF buf;
#endif
} FATFS;
/* Directory object structure */
typedef struct _DIR {
//WORD id; /* Owner file system mount ID */
WORD index; /* Current index */
FATFS* fs; /* Pointer to the owner file system object */
DWORD sclust; /* Start cluster */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
} DIR;
/* File object structure */
typedef struct _FIL {
//WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */
BYTE csect; /* Sector address in the cluster */
FATFS* fs; /* Pointer to the owner file system object */
DWORD fptr; /* File R/W pointer */
DWORD fsize; /* File size */
DWORD org_clust; /* File start cluster */
DWORD curr_clust; /* Current cluster */
DWORD curr_sect; /* Current sector */
#if _FS_READONLY == 0
DWORD dir_sect; /* Sector containing the directory entry */
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
#endif
#if _USE_LESS_BUF == 0 && _USE_1_BUF == 0
BUF buf; /* File R/W buffer */
#endif
} FIL;
/* File status structure */
typedef struct _FILINFO {
DWORD fsize; /* Size */
WORD fdate; /* Date */
WORD ftime; /* Time */
BYTE fattrib; /* Attribute */
DWORD clust; /* Start cluster */
UCHAR fname[8+1+3+1]; /* Name (8.3 format) */
#if _USE_LFN != 0
UCHAR* lfn;
#endif
} FILINFO;
/* Definitions corresponds to multi partition */
#if _MULTI_PARTITION != 0 /* Multiple partition cfg */
#define LD2PD(drv) (drv >> (8-_PARTITION_MASK)) /* Get physical drive# */
#define LD2PT(drv) (drv & ((1<<_PARTITION_MASK)-1)) /* Get partition# */
#define _LOGICAL_DRIVES (_DRIVES * (1<<_PARTITION_MASK))
#else /* Single partition cfg */
#define LD2PD(drv) (drv) /* Physical drive# is equal to logical drive# */
#define LD2PT(drv) 0 /* Always mounts the 1st partition */
#define _LOGICAL_DRIVES _DRIVES
#endif
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* 0 */
FR_NOT_READY, /* 1 */
FR_NO_FILE, /* 2 */
FR_NO_PATH, /* 3 */
FR_INVALID_NAME, /* 4 */
FR_INVALID_DRIVE, /* 5 */
FR_DENIED, /* 6 */
FR_EXIST, /* 7 */
FR_RW_ERROR, /* 8 */
FR_WRITE_PROTECTED, /* 9 */
FR_NOT_ENABLED, /* 10 */
FR_NO_FILESYSTEM, /* 11 */
FR_INVALID_OBJECT, /* 12 */
FR_MKFS_ABORTED, /* 13 */
FR_IS_DIRECTORY, /* 13 */
FR_IS_READONLY, /* 14 */
FR_DIR_NOT_EMPTY, /* 15 */
FR_NOT_DIRECTORY /* 16 */
} FRESULT;
/*-----------------------------------------------------*/
/* FatFs module application interface */
#if _USE_DRIVE_PREFIX == 0
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
FRESULT f_open (FATFS*, FIL*, const UCHAR*, BYTE); /* Open or create a file */
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
FRESULT f_close (FIL*); /* Close an open file object */
FRESULT f_opendir (FATFS*, DIR*, const UCHAR*); /* Open an existing directory */
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
FRESULT f_stat (FATFS*, const UCHAR*, FILINFO*); /* Get file status */
FRESULT f_getfree (FATFS*, const UCHAR*, DWORD*); /* Get number of free clusters on the drive */
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
FRESULT f_unlink (FATFS*, const UCHAR*); /* Delete an existing file or directory */
FRESULT f_mkdir (FATFS*, const UCHAR*); /* Create a new directory */
FRESULT f_chmod (FATFS*, const UCHAR*, BYTE, BYTE); /* Change file/dir attriburte */
FRESULT f_rename (FATFS*, const UCHAR*, const UCHAR*); /* Rename/Move a file or directory */
FRESULT f_mkfs (BYTE, BYTE, WORD); /* Create a file system on the drive */
FRESULT f_chdir (FATFS*, const UCHAR*); /* Change current directory */
#else
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
FRESULT f_open (FIL*, const UCHAR*, BYTE); /* Open or create a file */
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
FRESULT f_close (FIL*); /* Close an open file object */
FRESULT f_opendir (DIR*, const UCHAR*); /* Open an existing directory */
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
FRESULT f_stat (const UCHAR*, FILINFO*); /* Get file status */
FRESULT f_getfree (const UCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
FRESULT f_unlink (const UCHAR*); /* Delete an existing file or directory */
FRESULT f_mkdir (const UCHAR*); /* Create a new directory */
FRESULT f_chmod (const UCHAR*, BYTE, BYTE); /* Change file/dir attriburte */
FRESULT f_rename (const UCHAR*, const UCHAR*); /* Rename/Move a file or directory */
FRESULT f_mkfs (BYTE, BYTE, WORD); /* Create a file system on the drive */
FRESULT f_chdir (const UCHAR*); /* Change current directory */
#endif
/* Low Level functions */
FRESULT l_opendir(FATFS* fs, DWORD cluster, DIR *dirobj); /* Open an existing directory by its start cluster */
FRESULT l_opencluster(FATFS *fs, FIL *fp, DWORD clust); /* Open a cluster by number as a read-only file */
FRESULT l_getfree (FATFS*, const UCHAR*, DWORD*, DWORD); /* Get number of free clusters on the drive, limited */
#if _USE_STRFUNC
#define feof(fp) ((fp)->fptr == (fp)->fsize)
#define EOF -1
int fputc (int, FIL*); /* Put a character to the file */
int fputs (const char*, FIL*); /* Put a string to the file */
int fprintf (FIL*, const char*, ...); /* Put a formatted string to the file */
char* fgets (char*, int, FIL*); /* Get a string from the file */
#endif
/* User defined function to give a current time to fatfs module */
#if CONFIG_RTC_VARIANT > 0
DWORD get_fattime (void); /* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
/* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
#else
/* Fixed time: 1982-08-31 0:00:00, same month as the introduction of the C64 */
# define get_fattime() 0x51f0000
#endif
/* File access control and file status flags (FIL.flag) */
#define FA_READ 0x01
#define FA_OPEN_EXISTING 0x00
#if _FS_READONLY == 0
#define FA_WRITE 0x02
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA__WRITTEN 0x20
#define FA__DIRTY 0x40
#endif
#define FA__ERROR 0x80
/* FAT sub type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
/* File attribute bits for directory entry */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_VOL 0x08 /* Volume label */
#define AM_LFN 0x0F /* LFN entry */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
/* Offset of FAT structure members */
#define BS_jmpBoot 0
#define BS_OEMName 3
#define BPB_BytsPerSec 11
#define BPB_SecPerClus 13
#define BPB_RsvdSecCnt 14
#define BPB_NumFATs 16
#define BPB_RootEntCnt 17
#define BPB_TotSec16 19
#define BPB_Media 21
#define BPB_FATSz16 22
#define BPB_SecPerTrk 24
#define BPB_NumHeads 26
#define BPB_HiddSec 28
#define BPB_TotSec32 32
#define BS_55AA 510
#define BS_DrvNum 36
#define BS_BootSig 38
#define BS_VolID 39
#define BS_VolLab 43
#define BS_FilSysType 54
#define BPB_FATSz32 36
#define BPB_ExtFlags 40
#define BPB_FSVer 42
#define BPB_RootClus 44
#define BPB_FSInfo 48
#define BPB_BkBootSec 50
#define BS_DrvNum32 64
#define BS_BootSig32 66
#define BS_VolID32 67
#define BS_VolLab32 71
#define BS_FilSysType32 82
#define FSI_LeadSig 0
#define FSI_StrucSig 484
#define FSI_Free_Count 488
#define FSI_Nxt_Free 492
#define MBR_Table 446
#define DIR_Name 0
#define DIR_Attr 11
#define DIR_NTres 12
#define DIR_Chksum 13
#define DIR_CrtTime 14
#define DIR_CrtDate 16
#define DIR_FstClusHI 20
#define DIR_WrtTime 22
#define DIR_WrtDate 24
#define DIR_FstClusLO 26
#define DIR_FileSize 28
/* Multi-byte word access macros */
#if _MCU_ENDIAN == 1 /* Use word access */
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
#elif _MCU_ENDIAN == 2 /* Use byte-by-byte access */
#define LD_WORD(ptr) (WORD)(((WORD)*(volatile BYTE*)((ptr)+1)<<8)|(WORD)*(volatile BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(((DWORD)*(volatile BYTE*)((ptr)+3)<<24)|((DWORD)*(volatile BYTE*)((ptr)+2)<<16)|((WORD)*(volatile BYTE*)((ptr)+1)<<8)|*(volatile BYTE*)(ptr))
#define ST_WORD(ptr,val) *(volatile BYTE*)(ptr)=(BYTE)(val); *(volatile BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
#define ST_DWORD(ptr,val) *(volatile BYTE*)(ptr)=(BYTE)(val); *(volatile BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(volatile BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(volatile BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
#else
#error Do not forget to set _MCU_ENDIAN properly!
#endif
#define _FATFS
#endif /* _FATFS */

View File

@ -6,12 +6,16 @@
#include "ff.h"
#include "fileops.h"
WCHAR ff_convert(WCHAR w, UINT dir) {
return w;
}
void file_init() {
f_mount(0, &fatfs);
}
void file_open(char* filename, BYTE flags) {
file_res = f_open(&file_handle, filename, flags);
file_res = f_open(&file_handle, (unsigned char*)filename, flags);
}
void file_close() {

View File

@ -40,15 +40,16 @@
#include "uart.h"
#include "sdcard.h"
#include "diskio.h"
#include "integer.h"
#include "ff.h"
#include "fileops.h"
#include "fpga_spi.h"
#include "spi.h"
#include "avrcompat.h"
DWORD get_fattime(void) {
/*DWORD get_fattime(void) {
return 0L;
}
}*/
void set_prog_b(uint8_t val) {
if(val) {
PORTD |= _BV(PD3);

View File

@ -17,6 +17,7 @@ typedef uint8_t BYTE;
typedef int16_t SHORT;
typedef uint16_t USHORT;
typedef uint16_t WORD;
typedef uint16_t WCHAR;
/* These types are assumed as 32-bit integer */
typedef int32_t LONG;

View File

@ -47,8 +47,7 @@
#include "fpga_spi.h"
#include "spi.h"
#include "avrcompat.h"
char stringbuf[100];
#include "filetypes.h"
/* Make sure the watchdog is disabled as soon as possible */
/* Copy this code to your bootloader if you use one and your */
@ -131,7 +130,7 @@ int main(void) {
snes_reset(1);
uart_init();
// sei(); // interrupts are bad for now, resets the poor AVR when inserting SD card
sei(); // suspected to reset the AVR when inserting an SD card
_delay_ms(100);
disk_init();
snes_init();
@ -140,7 +139,6 @@ int main(void) {
uart_putcrlf();
file_init();
FATFS fatfs;
f_mount(0,&fatfs);
set_busy_led(1);
@ -160,12 +158,29 @@ int main(void) {
uart_putc('[');
load_sram("/test.srm");
uart_putc(']');
*fs_path=0;
uint16_t curr_dir_id = scan_dir(fs_path, 0); // generate files footprint
dprintf("curr dir id = %x\n", curr_dir_id);
uint16_t saved_dir_id;
if((get_db_id(&saved_dir_id) != FR_OK) // no database?
|| saved_dir_id != curr_dir_id) { // files changed?
dprintf("saved dir id = %x\n", saved_dir_id);
_delay_ms(50);
dprintf("rebuilding database...");
_delay_ms(50);
curr_dir_id = scan_dir(fs_path, 1); // then rebuild database
sram_writeblock(&curr_dir_id, 0x600000, 2);
save_sram("/sd2snes/sd2snes.db", 0x10000, 0x600000);
dprintf("done\n");
}
set_busy_led(0);
set_avr_ena(1);
_delay_ms(100);
uart_puts_P(PSTR("SNES GO!"));
uart_puts_P(PSTR("SNES GO!\n"));
snes_reset(0);
while(1) {
snes_main_loop();
}
@ -173,14 +188,8 @@ int main(void) {
/* HERE BE LIONS */
while(1) {
SPI_SS_HIGH();
FPGA_SS_LOW();
spiTransferByte(0x00);
spiTransferByte(0x00);
spiTransferByte(0x7f);
spiTransferByte(0xc0);
FPGA_SS_HIGH();
FPGA_SS_LOW();
set_avr_addr(0x600000);
spi_fpga();
spiTransferByte(0x81); // read w/ increment... hopefully
spiTransferByte(0x00); // 1 dummy read
uart_putcrlf();
@ -202,7 +211,7 @@ while(1) {
}
// set_avr_bank(3);
}
FPGA_SS_HIGH();
spi_sd();
}
while(1);
}

View File

@ -14,32 +14,32 @@
#include "fpga_spi.h"
#include "avrcompat.h"
#include "led.h"
#include "filetypes.h"
#include "smc.h"
#include "fpga_spi.h"
char* hex = "0123456789ABCDEF";
void sram_readblock(void* buf, uint32_t addr, uint16_t size) {
uint16_t count=size;
void* tgt = buf;
uint8_t* tgt = buf;
set_avr_addr(addr);
spi_fpga();
spiTransferByte(0x81); // READ
spiTransferByte(0x00); // dummy
while(count--) {
*((uint8_t*)tgt++) = spiTransferByte(0x00);
*(tgt++) = spiTransferByte(0x00);
}
spi_sd();
}
void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
uint16_t count=size;
void* src = buf;
uint8_t* src = buf;
set_avr_addr(addr);
spi_fpga();
spiTransferByte(0x91); // WRITE
while(count--) {
spiTransferByte(*((uint8_t*)src++));
spiTransferByte(*src++);
}
spiTransferByte(0x00); // dummy
spi_sd();
@ -157,6 +157,9 @@ void save_sram(char* filename, uint32_t sram_size, uint32_t base_addr) {
}
spi_sd();
num = file_write();
if(file_res) {
uart_putc(0x30+file_res);
}
}
file_close();
}

View File

@ -5,6 +5,8 @@
#define MEMORY_H
uint32_t load_rom(char* filename);
uint32_t load_sram(char* filename);
void sram_readblock(void* buf, uint32_t addr, uint16_t size);
void sram_writeblock(void* buf, uint32_t addr, uint16_t size);
void save_sram(char* filename, uint32_t sram_size, uint32_t base_addr);
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
#endif

111
src/smc.c Normal file
View File

@ -0,0 +1,111 @@
// insert cool lengthy disclaimer here
// filetypes.c: File support
#include <avr/io.h>
#include <util/delay.h>
#include "fileops.h"
#include "config.h"
#include "uart.h"
#include "smc.h"
uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0};
uint8_t countAllASCII(uint8_t* data, int size) {
uint8_t res = 0;
do {
size--;
if(data[size] >= 0x20 && data[size] <= 0x7e) {
res++;
}
} while (size);
return res;
}
uint8_t countAllJISX0201(uint8_t* data, int size) {
uint8_t res = 0;
do {
size--;
if((data[size] >= 0x20 && data[size] <= 0x7e)
||(data[size] >= 0xa1 && data[size] <= 0xdf)) {
res++;
}
} while (size);
return res;
}
uint8_t isFixed(uint8_t* data, int size, uint8_t value) {
uint8_t res = 1;
do {
size--;
if(data[size] != value) {
res = 0;
}
} while (size);
return res;
}
uint8_t checkChksum(uint16_t cchk, uint16_t chk) {
uint32_t sum = cchk + chk;
uint8_t res = 0;
if(sum==0x0000ffff) {
res = 0x10;
}
return res;
}
void smc_id(snes_romprops_t* props) {
uint8_t score, maxscore=1, score_idx=0;
snes_header_t* header = &(props->header);
for(uint8_t num = 0; num < 6; num++) {
file_readblock(header, hdr_addr[num], sizeof(snes_header_t));
if(file_res) {
score = 0;
} else {
score = smc_headerscore(header);
}
if(score>=maxscore) {
score_idx=num;
maxscore=score;
}
}
if(score_idx & 1) {
props->offset = 0x200;
} else {
props->offset = 0;
}
// restore the chosen one
file_readblock(header, hdr_addr[score_idx], sizeof(snes_header_t));
switch(header->map & 0xef) {
case 0x20:
props->mapper_id = 1;
break;
case 0x21:
props->mapper_id = 0;
break;
case 0x25:
props->mapper_id = 2;
break;
default:
props->mapper_id = 0; // whatever
}
props->ramsize_bytes = (uint32_t)1024 << header->ramsize;
props->romsize_bytes = (uint32_t)1024 << header->romsize;
props->expramsize_bytes = (uint32_t)1024 << header->expramsize;
f_lseek(&file_handle, 0);
}
uint8_t smc_headerscore(snes_header_t* header) {
uint8_t score=0;
score += countAllASCII(header->maker, sizeof(header->maker));
score += countAllASCII(header->gamecode, sizeof(header->gamecode));
score += isFixed(header->fixed_00, sizeof(header->fixed_00), 0x00);
score += countAllJISX0201(header->name, sizeof(header->name));
score += 3*isFixed(&header->fixed_33, sizeof(header->fixed_33), 0x33);
score += checkChksum(header->cchk, header->chk);
return score;
}

46
src/smc.h Normal file
View File

@ -0,0 +1,46 @@
// insert cool lengthy disclaimer here
/*
* smc.h: data structures for SNES ROM images
*/
#ifndef SMC_H
#define SMC_H
typedef struct _snes_header {
uint8_t maker[2]; // 0xB0
uint8_t gamecode[4]; // 0xB2
uint8_t fixed_00[7]; // 0xB6
uint8_t expramsize; // 0xBD
uint8_t specver; // 0xBE
uint8_t carttype2; // 0xBF
uint8_t name[21]; // 0xC0
uint8_t map; // 0xD5
uint8_t carttype; // 0xD6
uint8_t romsize; // 0xD7
uint8_t ramsize; // 0xD8
uint8_t destcode; // 0xD9
uint8_t fixed_33; // 0xDA
uint8_t ver; // 0xDB
uint16_t cchk; // 0xDC
uint16_t chk; // 0xDE
} snes_header_t;
typedef struct _snes_romprops {
uint16_t offset; // start of actual ROM image
uint8_t mapper_id; // FPGA mapper
uint32_t expramsize_bytes; // ExpRAM size in bytes
uint32_t ramsize_bytes; // CartRAM size in bytes
uint32_t romsize_bytes; // ROM size in bytes (rounded up)
snes_header_t header; // original header from ROM image
} snes_romprops_t;
void smc_id(snes_romprops_t*);
uint8_t smc_headerscore(snes_header_t*);
/*pedef struct {
}*/
#endif

View File

@ -47,7 +47,7 @@ void snes_reset(int state) {
void snes_main_loop() {
if(initloop) {
saveram_crc_old = calc_sram_crc(saveram_base_addr, saveram_size);
save_sram("/test.srm", saveram_size, saveram_base_addr);
save_sram("/quite a long test filename.srm", saveram_size, saveram_base_addr);
initloop=0;
}
saveram_crc = calc_sram_crc(saveram_base_addr, saveram_size);
@ -56,7 +56,7 @@ void snes_main_loop() {
uart_puthexshort(saveram_crc);
uart_putcrlf();
set_busy_led(1);
save_sram("/test.srm", saveram_size, saveram_base_addr);
save_sram("/quite a long test filename.srm", saveram_size, saveram_base_addr);
set_busy_led(0);
}
saveram_crc_old = saveram_crc;

View File

@ -56,15 +56,16 @@ end
Index Mapper
000 HiROM
001 LoROM
010 ExHiROM
010 ExHiROM (48-64Mbit)
*/
/* HiROM: SRAM @ Bank 0x20-0x3f, 0xa0-0xbf
/* HiROM: SRAM @ Bank 0x30-0x3f, 0xb0-0xbf
Offset 6000-7fff */
assign IS_SAVERAM = ((MAPPER == 3'b000 || MAPPER == 3'b010) ? (!SNES_ADDR[22]
& SNES_ADDR[21]
& SNES_ADDR[21:20]
& &SNES_ADDR[14:13]
& !SNES_ADDR[15]
& SNES_CS
)
/* LoROM: SRAM @ Bank 0x70-0x7d, 0xf0-0xfd
Offset 0000-7fff TODO: 0000-ffff for

View File

@ -182,3 +182,52 @@ NET "SRAM_DATA[8]" LOC = P96;
NET "SRAM_DATA[9]" LOC = P98;
NET "SRAM_OE" LOC = P93;
NET "CLKIN" IOSTANDARD = LVCMOS33;
TIMESPEC TS_test = FROM "FFS" TO "FFS" 10 ns;
NET "SNES_ADDR<0>" MAXDELAY = 10 ns;
NET "SNES_ADDR<0>" MAXSKEW = 5 ns;
NET "SNES_ADDR<1>" MAXDELAY = 10 ns;
NET "SNES_ADDR<1>" MAXSKEW = 5 ns;
NET "SNES_ADDR<2>" MAXDELAY = 10 ns;
NET "SNES_ADDR<2>" MAXSKEW = 5 ns;
NET "SNES_ADDR<3>" MAXDELAY = 10 ns;
NET "SNES_ADDR<3>" MAXSKEW = 5 ns;
NET "SNES_ADDR<4>" MAXDELAY = 10 ns;
NET "SNES_ADDR<4>" MAXSKEW = 5 ns;
NET "SNES_ADDR<5>" MAXDELAY = 10 ns;
NET "SNES_ADDR<5>" MAXSKEW = 5 ns;
NET "SNES_ADDR<6>" MAXDELAY = 10 ns;
NET "SNES_ADDR<6>" MAXSKEW = 5 ns;
NET "SNES_ADDR<7>" MAXDELAY = 10 ns;
NET "SNES_ADDR<7>" MAXSKEW = 5 ns;
NET "SNES_ADDR<8>" MAXDELAY = 10 ns;
NET "SNES_ADDR<8>" MAXSKEW = 5 ns;
NET "SNES_ADDR<9>" MAXDELAY = 10 ns;
NET "SNES_ADDR<9>" MAXSKEW = 5 ns;
NET "SNES_ADDR<10>" MAXDELAY = 10 ns;
NET "SNES_ADDR<10>" MAXSKEW = 5 ns;
NET "SNES_ADDR<11>" MAXDELAY = 10 ns;
NET "SNES_ADDR<11>" MAXSKEW = 5 ns;
NET "SNES_ADDR<12>" MAXDELAY = 10 ns;
NET "SNES_ADDR<12>" MAXSKEW = 5 ns;
NET "SNES_ADDR<13>" MAXDELAY = 10 ns;
NET "SNES_ADDR<13>" MAXSKEW = 5 ns;
NET "SNES_ADDR<14>" MAXDELAY = 10 ns;
NET "SNES_ADDR<14>" MAXSKEW = 5 ns;
NET "SNES_ADDR<15>" MAXDELAY = 10 ns;
NET "SNES_ADDR<15>" MAXSKEW = 5 ns;
NET "SNES_ADDR<16>" MAXDELAY = 10 ns;
NET "SNES_ADDR<16>" MAXSKEW = 5 ns;
NET "SNES_ADDR<17>" MAXDELAY = 10 ns;
NET "SNES_ADDR<17>" MAXSKEW = 5 ns;
NET "SNES_ADDR<18>" MAXDELAY = 10 ns;
NET "SNES_ADDR<18>" MAXSKEW = 5 ns;
NET "SNES_ADDR<19>" MAXDELAY = 10 ns;
NET "SNES_ADDR<19>" MAXSKEW = 5 ns;
NET "SNES_ADDR<20>" MAXDELAY = 10 ns;
NET "SNES_ADDR<20>" MAXSKEW = 5 ns;
NET "SNES_ADDR<21>" MAXDELAY = 10 ns;
NET "SNES_ADDR<21>" MAXSKEW = 5 ns;
NET "SNES_ADDR<22>" MAXDELAY = 10 ns;
NET "SNES_ADDR<22>" MAXSKEW = 5 ns;
NET "SNES_ADDR<23>" MAXDELAY = 10 ns;
NET "SNES_ADDR<23>" MAXSKEW = 5 ns;

View File

@ -120,14 +120,20 @@ wire SNES_RW;
reg [1:0] SNES_READr;
reg [1:0] SNES_WRITEr;
reg [1:0] SNES_CSr;
reg [1:0] SNES_CPU_CLKr;
reg [7:0] SNES_RWr;
reg [5:0] SNES_CPU_CLKr;
reg [5:0] SNES_RWr;
reg [23:0] SNES_ADDRr;
reg [23:0] SNES_ADDR_PREVr;
reg [3:0] SNES_ADDRCHGr;
wire SNES_READs = (SNES_READr == 2'b11);
wire SNES_WRITEs = (SNES_WRITEr == 2'b11);
wire SNES_CSs = (SNES_CSr == 2'b11);
wire SNES_CPU_CLKs = SNES_CPU_CLK; // (SNES_CPU_CLKr == 2'b11);
wire SNES_RW_start = (SNES_RWr == 8'b11111110); // falling edge marks beginning of cycle
wire SNES_RW_start = (SNES_RWr == 6'b111110); // falling edge marks beginning of cycle
wire SNES_cycle_start = (SNES_CPU_CLKr == 6'b000001);
wire SNES_ADDRCHG = (SNES_ADDRr != SNES_ADDR_PREVr);
wire SNES_addr_start = (SNES_ADDRCHGr[0] == 1'b1);
assign SNES_RW = (SNES_READ & SNES_WRITE);
@ -135,11 +141,15 @@ always @(posedge CLK2) begin
SNES_READr <= {SNES_READr[0], SNES_READ};
SNES_WRITEr <= {SNES_WRITEr[0], SNES_WRITE};
SNES_CSr <= {SNES_CSr[0], SNES_CS};
SNES_CPU_CLKr <= {SNES_CPU_CLKr[0], SNES_CPU_CLK};
SNES_RWr <= {SNES_RWr[6:0], SNES_RW};
SNES_CPU_CLKr <= {SNES_CPU_CLKr[4:0], SNES_CPU_CLK};
SNES_RWr <= {SNES_RWr[4:0], SNES_RW};
end
reg ADDR_WRITE;
//reg [23:0] SNES_ADDRr;
//wire [23:0] SNES_ADDRw = SNES_ADDR;
address snes_addr(
.CLK(CLK2),
@ -157,6 +167,11 @@ address snes_addr(
.SAVERAM_MASK(SAVERAM_MASK),
.ROM_MASK(ROM_MASK)
);
wire SNES_READ_CYCLEw;
wire SNES_WRITE_CYCLEw;
wire AVR_READ_CYCLEw;
wire AVR_WRITE_CYCLEw;
data snes_data(.CLK(CLK2),
.SNES_READ(SNES_READ),
@ -179,33 +194,36 @@ data snes_data(.CLK(CLK2),
parameter MODE_SNES = 1'b0;
parameter MODE_AVR = 1'b1;
parameter STATE_0 = 10'b0000000001;
parameter STATE_1 = 10'b0000000010;
parameter STATE_2 = 10'b0000000100;
parameter STATE_3 = 10'b0000001000;
parameter STATE_4 = 10'b0000010000;
parameter STATE_5 = 10'b0000100000;
parameter STATE_6 = 10'b0001000000;
parameter STATE_7 = 10'b0010000000;
parameter STATE_8 = 10'b0100000000;
parameter STATE_9 = 10'b1000000000;
parameter STATE_0 = 13'b0000000000001;
parameter STATE_1 = 13'b0000000000010;
parameter STATE_2 = 13'b0000000000100;
parameter STATE_3 = 13'b0000000001000;
parameter STATE_4 = 13'b0000000010000;
parameter STATE_5 = 13'b0000000100000;
parameter STATE_6 = 13'b0000001000000;
parameter STATE_7 = 13'b0000010000000;
parameter STATE_8 = 13'b0000100000000;
parameter STATE_9 = 13'b0001000000000;
parameter STATE_10 = 13'b0010000000000;
parameter STATE_11 = 13'b0100000000000;
parameter STATE_IDLE = 13'b1000000000000;
reg [9:0] STATE;
reg [12:0] STATE;
reg [3:0] STATEIDX;
reg STATE_RESET, CYCLE_RESET, CYCLE_RESET_ACK;
reg [1:0] CYCLE_RESET;
reg SRAM_WE_MASK;
reg SRAM_OE_MASK;
reg [9:0] SRAM_WE_ARRAY [3:0];
reg [9:0] SRAM_OE_ARRAY [3:0];
reg [12:0] SRAM_WE_ARRAY [3:0];
reg [12:0] SRAM_OE_ARRAY [3:0];
reg [9:0] SNES_DATA_TO_MEM_ARRAY[1:0];
reg [9:0] AVR_DATA_TO_MEM_ARRAY[1:0];
reg [9:0] SRAM_DATA_TO_SNES_MEM_ARRAY[1:0];
reg [9:0] SRAM_DATA_TO_AVR_MEM_ARRAY[1:0];
reg [12:0] SNES_DATA_TO_MEM_ARRAY[1:0];
reg [12:0] AVR_DATA_TO_MEM_ARRAY[1:0];
reg [12:0] SRAM_DATA_TO_SNES_MEM_ARRAY[1:0];
reg [12:0] SRAM_DATA_TO_AVR_MEM_ARRAY[1:0];
reg [9:0] MODE_ARRAY;
reg [12:0] MODE_ARRAY;
reg SNES_READ_CYCLE;
reg SNES_WRITE_CYCLE;
@ -225,41 +243,39 @@ reg SNES_DATABUS_DIR_BUF;
assign MODE = !AVR_ENA ? MODE_AVR : MODE_ARRAY[STATEIDX];
initial begin
CYCLE_RESET = 0;
CYCLE_RESET_ACK = 0;
CYCLE_RESET = 2'b0;
STATE = STATE_9;
STATEIDX = 9;
STATE = STATE_IDLE;
STATEIDX = 12;
SRAM_WE_MASK = 1'b1;
SRAM_OE_MASK = 1'b1;
SNES_READ_CYCLE = 1'b1;
SNES_WRITE_CYCLE = 1'b1;
AVR_READ_CYCLE = 1'b1;
AVR_WRITE_CYCLE = 1'b1;
MODE_ARRAY = 13'b0000000111111;
SRAM_WE_ARRAY[2'b00] = 13'b1000000000000;
SRAM_WE_ARRAY[2'b01] = 13'b1000000111111;
SRAM_WE_ARRAY[2'b10] = 13'b1111111000000;
SRAM_WE_ARRAY[2'b11] = 13'b1111111111111;
MODE_ARRAY = 10'b0000011111;
SRAM_OE_ARRAY[2'b00] = 13'b1111111111111;
SRAM_OE_ARRAY[2'b01] = 13'b1111111000000;
SRAM_OE_ARRAY[2'b10] = 13'b0000000111111;
SRAM_OE_ARRAY[2'b11] = 13'b0000000000000;
SRAM_WE_ARRAY[2'b00] = 10'b1000010000;
SRAM_WE_ARRAY[2'b01] = 10'b1000011111;
SRAM_WE_ARRAY[2'b10] = 10'b1111110000;
SRAM_WE_ARRAY[2'b11] = 10'b1111111111;
SRAM_OE_ARRAY[2'b00] = 10'b1111111111;
SRAM_OE_ARRAY[2'b01] = 10'b1111100000;
SRAM_OE_ARRAY[2'b10] = 10'b0000011111;
SRAM_OE_ARRAY[2'b11] = 10'b0000000000;
SNES_DATA_TO_MEM_ARRAY[1'b0] = 13'b0001000000000; // SNES write
SNES_DATA_TO_MEM_ARRAY[1'b1] = 13'b0000000000000; // SNES read
SNES_DATA_TO_MEM_ARRAY[1'b0] = 10'b1000000000;
SNES_DATA_TO_MEM_ARRAY[1'b1] = 10'b0000000000;
AVR_DATA_TO_MEM_ARRAY[1'b0] = 13'b0000000010000; // AVR write
AVR_DATA_TO_MEM_ARRAY[1'b1] = 13'b0000000000000; // AVR read
AVR_DATA_TO_MEM_ARRAY[1'b0] = 10'b0000010000;
AVR_DATA_TO_MEM_ARRAY[1'b1] = 10'b0000000000;
SRAM_DATA_TO_SNES_MEM_ARRAY[1'b0] = 13'b0000000000000; // SNES write
SRAM_DATA_TO_SNES_MEM_ARRAY[1'b1] = 13'b0000100000000; // SNES read
SRAM_DATA_TO_SNES_MEM_ARRAY[1'b0] = 10'b0000000000;
SRAM_DATA_TO_SNES_MEM_ARRAY[1'b1] = 10'b0000100000;
SRAM_DATA_TO_AVR_MEM_ARRAY[1'b0] = 10'b0000000000;
SRAM_DATA_TO_AVR_MEM_ARRAY[1'b1] = 10'b0000000001;
SRAM_DATA_TO_AVR_MEM_ARRAY[1'b0] = 13'b0000000000000; // AVR write
SRAM_DATA_TO_AVR_MEM_ARRAY[1'b1] = 13'b0000000000001; // AVR read
end
// falling edge of SNES /RD or /WR marks the beginning of a new cycle
@ -268,48 +284,66 @@ end
// the minimum of 6 SNES cycles to get everything done.
// we have 24 internal cycles to work with. (CLKIN * 4)
reg [1:0] CYCLE_RESET;
always @(posedge CLK2) begin
CYCLE_RESET <= {CYCLE_RESET[0], SNES_RW_start};
CYCLE_RESET <= {CYCLE_RESET[0], SNES_cycle_start};
end
always @(posedge CLK2) begin
if (CYCLE_RESET[1]) begin
STATE <= STATE_0;
if (SNES_RW_start) begin
SNES_READ_CYCLE <= SNES_READ;
SNES_WRITE_CYCLE <= SNES_WRITE;
AVR_READ_CYCLE <= AVR_READ;
AVR_WRITE_CYCLE <= AVR_WRITE;
STATE <= STATE_0;
STATEIDX <= 11;
end else begin
case (STATE)
STATE_0:
STATE <= STATE_1;
STATE_1:
STATE <= STATE_2;
STATE_2:
STATE <= STATE_3;
STATE_3:
STATE <= STATE_4;
STATE_4:
STATE <= STATE_5;
STATE_5:
STATE <= STATE_6;
STATE_6:
STATE <= STATE_7;
STATE_7:
STATE <= STATE_8;
STATE_8:
STATE <= STATE_9;
STATE_0: begin
STATE <= STATE_1; STATEIDX <= 10;
end
STATE_1: begin
STATE <= STATE_2; STATEIDX <= 9;
end
STATE_2: begin
STATE <= STATE_3; STATEIDX <= 8;
end
STATE_3: begin
STATE <= STATE_4; STATEIDX <= 7;
end
STATE_4: begin
STATE <= STATE_5; STATEIDX <= 6;
end
STATE_5: begin
STATE <= STATE_6; STATEIDX <= 5;
end
STATE_6: begin
STATE <= STATE_7; STATEIDX <= 4;
end
STATE_7: begin
STATE <= STATE_8; STATEIDX <= 3;
end
STATE_8: begin
STATE <= STATE_9; STATEIDX <= 2;
end
STATE_9: begin
STATE <= STATE_9;
end
default:
STATE <= STATE_9;
STATE <= STATE_10; STATEIDX <= 1;
end
STATE_10: begin
STATE <= STATE_11; STATEIDX <= 0;
end
STATE_11: begin
STATE <= STATE_IDLE; STATEIDX <= 12;
end
STATE_IDLE: begin
STATE <= STATE_IDLE; STATEIDX <= 12;
end
default: begin
STATE <= STATE_IDLE; STATEIDX <= 12;
end
endcase
end
end
/*
always @(posedge CLK2) begin
case (STATE)
@ -356,7 +390,7 @@ always @(posedge CLK2) begin
STATEIDX <= 9;
endcase
end
*/
// When in AVR mode, enable SRAM_WE according to AVR programming
// else enable SRAM_WE according to state&cycle
assign SRAM_WE = !AVR_ENA ? AVR_WRITE
@ -375,8 +409,8 @@ assign SRAM_BLE = !SRAM_WE ? !SRAM_ADDR0 : 1'b0;
//assign SRAM_WE = !AVR_ENA ? AVR_WRITE : 1'b1;
//assign SNES_DATABUS_OE = (!IS_SAVERAM & SNES_CS) | (SNES_READ & SNES_WRITE);
assign SNES_DATABUS_OE = (IS_ROM & SNES_CSs) | (!IS_ROM & !IS_SAVERAM) | (SNES_READs & SNES_WRITEs);
assign SNES_DATABUS_DIR = !SNES_WRITEs ? 1'b0 : 1'b1;
assign SNES_DATABUS_OE = (IS_ROM & SNES_CS) | (!IS_ROM & !IS_SAVERAM) | (SNES_READ & SNES_WRITE);
assign SNES_DATABUS_DIR = !SNES_READ ? 1'b1 : 1'b0;
assign SNES_DATA_TO_MEM = SNES_DATA_TO_MEM_ARRAY[SNES_WRITE_CYCLE][STATEIDX];
assign AVR_DATA_TO_MEM = AVR_DATA_TO_MEM_ARRAY[AVR_WRITE_CYCLE][STATEIDX];
@ -384,6 +418,8 @@ assign AVR_DATA_TO_MEM = AVR_DATA_TO_MEM_ARRAY[AVR_WRITE_CYCLE][STATEIDX];
assign SRAM_DATA_TO_SNES_MEM = SRAM_DATA_TO_SNES_MEM_ARRAY[SNES_WRITE_CYCLE][STATEIDX];
assign SRAM_DATA_TO_AVR_MEM = SRAM_DATA_TO_AVR_MEM_ARRAY[AVR_WRITE_CYCLE][STATEIDX];
assign SNES_READ_CYCLEw = SNES_READ_CYCLE;
assign SNES_WRITE_CYCLEw = SNES_WRITE_CYCLE;
assign IRQ_DIR = 1'b0;
assign SNES_IRQ = 1'bZ;

View File

@ -69,21 +69,30 @@
<properties>
<property xil_pn:name="Auto Implementation Top" xil_pn:value="false"/>
<property xil_pn:name="Combinatorial Logic Optimization" xil_pn:value="true"/>
<property xil_pn:name="Constraints Entry" xil_pn:value="Constraints Editor"/>
<property xil_pn:name="Device" xil_pn:value="xc3s200"/>
<property xil_pn:name="Device Family" xil_pn:value="Spartan3"/>
<property xil_pn:name="Extra Effort" xil_pn:value="Normal"/>
<property xil_pn:name="Extra Effort (Highest PAR level only)" xil_pn:value="Normal"/>
<property xil_pn:name="Fitter Report Format" xil_pn:value="HTML"/>
<property xil_pn:name="Generate Asynchronous Delay Report" xil_pn:value="true"/>
<property xil_pn:name="Generate Detailed MAP Report" xil_pn:value="true"/>
<property xil_pn:name="Implementation Top" xil_pn:value="Module|main"/>
<property xil_pn:name="Implementation Top Instance Path" xil_pn:value="/main"/>
<property xil_pn:name="Map Effort Level" xil_pn:value="High"/>
<property xil_pn:name="Map Slice Logic into Unused Block RAMs" xil_pn:value="true"/>
<property xil_pn:name="Optimization Strategy (Cover Mode)" xil_pn:value="Speed"/>
<property xil_pn:name="PROP_BehavioralSimTop" xil_pn:value="Module|main_tf2"/>
<property xil_pn:name="PROP_DesignName" xil_pn:value="sd2snes"/>
<property xil_pn:name="PROP_PostParSimTop" xil_pn:value="Module|main_tf2"/>
<property xil_pn:name="Package" xil_pn:value="tq144"/>
<property xil_pn:name="Perform Timing-Driven Packing" xil_pn:value="true"/>
<property xil_pn:name="Place &amp; Route Effort Level (Overall)" xil_pn:value="High"/>
<property xil_pn:name="Placer Effort Level (Overrides Overall Level)" xil_pn:value="High"/>
<property xil_pn:name="Preferred Language" xil_pn:value="Verilog"/>
<property xil_pn:name="Project Description" xil_pn:value="sd2snes"/>
<property xil_pn:name="Register Duplication" xil_pn:value="On"/>
<property xil_pn:name="Router Effort Level (Overrides Overall Level)" xil_pn:value="High"/>
<property xil_pn:name="Selected Simulation Root Source Node Behavioral" xil_pn:value="Module|main_tf2"/>
<property xil_pn:name="Selected Simulation Root Source Node Post-Route" xil_pn:value="Module|main_tf2"/>