Merge branch 'master' of ssh://shion.micecat.ath.cx/~ikari/public_html/git/sd2snes
This commit is contained in:
commit
b9d119ada5
Binary file not shown.
Binary file not shown.
@ -100,7 +100,7 @@ FORMAT = ihex
|
|||||||
TARGET = $(OBJDIR)/sd2snes
|
TARGET = $(OBJDIR)/sd2snes
|
||||||
|
|
||||||
# List C source files here. (C dependencies are automatically generated.)
|
# 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)
|
ifeq ($(CONFIG_UART_DEBUG),y)
|
||||||
SRC += uart.c
|
SRC += uart.c
|
||||||
@ -119,8 +119,8 @@ ASRC =
|
|||||||
# 0 = turn off optimization. s = optimize for size.
|
# 0 = turn off optimization. s = optimize for size.
|
||||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
||||||
# Use s -mcall-prologues when you really need size...
|
# Use s -mcall-prologues when you really need size...
|
||||||
#OPT = 2
|
OPT = s
|
||||||
OPT = 3 -finline-functions
|
#OPT = 3 -finline-functions
|
||||||
|
|
||||||
# Debugging format.
|
# Debugging format.
|
||||||
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
|
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
|
||||||
|
|||||||
@ -35,7 +35,7 @@ CONFIG_UART_BAUDRATE=38400
|
|||||||
CONFIG_UART_BUF_SHIFT=7
|
CONFIG_UART_BUF_SHIFT=7
|
||||||
CONFIG_HARDWARE_NAME=sd2snes
|
CONFIG_HARDWARE_NAME=sd2snes
|
||||||
CONFIG_SD_AUTO_RETRIES=10
|
CONFIG_SD_AUTO_RETRIES=10
|
||||||
#CONFIG_SD_DATACRC=y
|
CONFIG_SD_DATACRC=y
|
||||||
CONFIG_EEPROM_SIZE=512
|
CONFIG_EEPROM_SIZE=512
|
||||||
CONFIG_EEPROM_OFFSET=512
|
CONFIG_EEPROM_OFFSET=512
|
||||||
CONFIG_MAX_PARTITIONS=2
|
CONFIG_MAX_PARTITIONS=1
|
||||||
|
|||||||
71
src/crc16.c
71
src/crc16.c
@ -2,59 +2,20 @@
|
|||||||
* \file stdout
|
* \file stdout
|
||||||
* Functions and types for CRC checks.
|
* 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/
|
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
|
||||||
* using the configuration:
|
* using the configuration:
|
||||||
* Width = 16
|
* Width = 16
|
||||||
* Poly = 0x8005
|
* Poly = 0x8005
|
||||||
* XorIn = 0xffff
|
* XorIn = 0x0000
|
||||||
* ReflectIn = True
|
* ReflectIn = True
|
||||||
* XorOut = 0xffff
|
* XorOut = 0x0000
|
||||||
* ReflectOut = True
|
* ReflectOut = True
|
||||||
* Algorithm = table-driven
|
* Algorithm = bit-by-bit-fast
|
||||||
* Direct = True
|
* Direct = True
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#include "crc16.h"
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "crc16.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
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the crc value with new data.
|
* 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)
|
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--) {
|
while (data_len--) {
|
||||||
tbl_idx = (crc ^ *data) & 0xff;
|
c = *data++;
|
||||||
crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffff;
|
for (i = 0x01; i & 0xff; i <<= 1) {
|
||||||
|
bit = (crc & 0x8000 ? 1 : 0);
|
||||||
data++;
|
if (c & i) {
|
||||||
|
bit ^= 1;
|
||||||
|
}
|
||||||
|
crc <<= 1;
|
||||||
|
if (bit) {
|
||||||
|
crc ^= 0x8005;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crc &= 0xffff;
|
||||||
}
|
}
|
||||||
return crc & 0xffff;
|
return crc & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
558
src/ff.h
558
src/ff.h
@ -1,436 +1,341 @@
|
|||||||
/*---------------------------------------------------------------------------/
|
/*--------------------------------------------------------------------------/
|
||||||
/ FatFs - FAT file system module include file R0.07a (C)ChaN, 2009
|
/ FatFs - FAT file system module include file R0.06 (C)ChaN, 2008
|
||||||
/----------------------------------------------------------------------------/
|
/---------------------------------------------------------------------------/
|
||||||
/ FatFs module is an open source software to implement FAT file system to
|
/ FatFs module is an experimenal project to implement FAT file system to
|
||||||
/ small embedded systems. This is a free software and is opened for education,
|
/ cheap microcontrollers. This is a free software and is opened for education,
|
||||||
/ research and commercial developments under license policy of following trems.
|
/ research and development under license policy of following trems.
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2009, ChaN, all right reserved.
|
/ Copyright (C) 2008, ChaN, all right reserved.
|
||||||
/
|
/
|
||||||
/ * The FatFs module is a free software and there is NO WARRANTY.
|
/ * The FatFs module is a free software and there is no warranty.
|
||||||
/ * No restriction on use. You can use, modify and redistribute it for
|
/ * You can use, modify and/or redistribute it for personal, non-profit or
|
||||||
/ personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
|
/ * commercial use without any restriction under your responsibility.
|
||||||
/ * Redistributions of source code must retain the above copyright notice.
|
/ * 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
|
#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 _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
|
#define _FS_READONLY 0
|
||||||
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
|
/* 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,
|
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
|
||||||
/ f_truncate and useless f_getfree. */
|
/ f_truncate and useless f_getfree. */
|
||||||
|
|
||||||
|
|
||||||
#define _FS_MINIMIZE 0
|
#define _FS_MINIMIZE 0
|
||||||
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
|
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
|
||||||
/
|
|
||||||
/ 0: Full function.
|
/ 0: Full function.
|
||||||
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
|
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename are removed.
|
||||||
/ are removed.
|
|
||||||
/ 2: f_opendir and f_readdir are removed in addition to level 1.
|
/ 2: f_opendir and f_readdir are removed in addition to level 1.
|
||||||
/ 3: f_lseek is removed in addition to level 2. */
|
/ 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
|
#define _USE_STRFUNC 0
|
||||||
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
|
/* 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
|
#define _USE_MKFS 0
|
||||||
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
|
/* When _USE_MKFS is set to 1 and _FS_READONLY is set to 0, f_mkfs function is
|
||||||
|
/ enabled. */
|
||||||
|
|
||||||
#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
|
#define _MULTI_PARTITION 0
|
||||||
/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical
|
/* When _MULTI_PARTITION is set to 0, each logical drive is bound to the same
|
||||||
/ drive number and can mount only first primaly partition. When it is set to 1,
|
/ physical drive number and can mount only 1st primary partition.
|
||||||
/ 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.
|
/ When it is set to 1, the low _PARTITION_MASK bits of each partition represent
|
||||||
/ 1: Enable LFN with static working buffer on the bss. NOT REENTRANT.
|
/ the partition and the high (8-_PARTITION_MASK) bits represent the physical
|
||||||
/ 2: Enable LFN with dynamic working buffer on the caller's STACK.
|
/ drive */
|
||||||
/
|
|
||||||
/ 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 _PARTITION_MASK 4
|
||||||
|
|
||||||
#define _FS_REENTRANT 0
|
#define _USE_FSINFO 1
|
||||||
#define _TIMEOUT 1000 /* Timeout period in unit of time ticks */
|
/* To enable FSInfo support on FAT32 volume, set _USE_FSINFO to 1. */
|
||||||
#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. */
|
|
||||||
|
|
||||||
|
#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. */
|
||||||
|
|
||||||
/* End of configuration options. Do not change followings without care. */
|
#define _USE_CHDIR 0
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
#define _USE_CURR_DIR 1
|
||||||
|
|
||||||
|
#define _USE_LFN 1
|
||||||
|
|
||||||
/* Definitions corresponds to multiple sector size */
|
/* 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
|
||||||
|
|
||||||
#if _MAX_SS == 512
|
/* When _USE_LFN_DBCS is set to 1, FILINFO.lfn will contain a DBCS string, not
|
||||||
#define SS(fs) 512
|
/ 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
|
#else
|
||||||
#if _MAX_SS == 1024 || _MAX_SS == 2048 || _MAX_SS == 4096
|
#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)
|
#define SS(fs) ((fs)->s_size)
|
||||||
#else
|
#else
|
||||||
#error Sector size must be 512, 1024, 2048 or 4096.
|
#define SS(fs) 512U
|
||||||
#endif
|
|
||||||
#endif
|
#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 */
|
/* File system object structure */
|
||||||
|
|
||||||
typedef struct _FATFS {
|
typedef struct _FATFS {
|
||||||
BYTE fs_type; /* FAT sub type */
|
//WORD id; /* File system mount ID */
|
||||||
BYTE drive; /* Physical drive number */
|
WORD n_rootdir; /* Number of root directory entries */
|
||||||
BYTE csize; /* Number of sectors per cluster */
|
DWORD sects_fat; /* Sectors per fat */
|
||||||
BYTE n_fats; /* Number of FAT copies */
|
DWORD max_clust; /* Maximum cluster# + 1 */
|
||||||
BYTE wflag; /* win[] dirty flag (1:must be written back) */
|
DWORD fatbase; /* FAT start sector */
|
||||||
BYTE pad1;
|
DWORD dirbase; /* Root directory start sector (cluster# for FAT32) */
|
||||||
WORD id; /* File system mount ID */
|
DWORD database; /* Data start sector */
|
||||||
WORD n_rootdir; /* Number of root directory entries (0 on FAT32) */
|
#if _USE_CHDIR != 0 || _USE_CURR_DIR != 0
|
||||||
#if _FS_REENTRANT
|
DWORD curr_dir;
|
||||||
_SYNC_t sobj; /* Identifier of sync object */
|
|
||||||
#endif
|
|
||||||
#if _MAX_SS != 512U
|
|
||||||
WORD s_size; /* Sector size */
|
|
||||||
#endif
|
#endif
|
||||||
#if !_FS_READONLY
|
#if !_FS_READONLY
|
||||||
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
|
|
||||||
BYTE pad2;
|
|
||||||
DWORD last_clust; /* Last allocated cluster */
|
DWORD last_clust; /* Last allocated cluster */
|
||||||
DWORD free_clust; /* Number of free clusters */
|
DWORD free_clust; /* Number of free clusters */
|
||||||
|
#if _USE_FSINFO
|
||||||
DWORD fsi_sector; /* fsinfo sector */
|
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
|
#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;
|
} FATFS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Directory object structure */
|
/* Directory object structure */
|
||||||
|
|
||||||
typedef struct _DIR {
|
typedef struct _DIR {
|
||||||
WORD id; /* Owner file system mount ID */
|
//WORD id; /* Owner file system mount ID */
|
||||||
WORD index; /* Current index number */
|
WORD index; /* Current index */
|
||||||
FATFS* fs; /* Pointer to the owner file system object */
|
FATFS* fs; /* Pointer to the owner file system object */
|
||||||
DWORD sclust; /* Table start cluster (0:Static table) */
|
DWORD sclust; /* Start cluster */
|
||||||
DWORD clust; /* Current cluster */
|
DWORD clust; /* Current cluster */
|
||||||
DWORD sect; /* Current sector */
|
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;
|
} DIR;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* File object structure */
|
/* File object structure */
|
||||||
|
|
||||||
typedef struct _FIL {
|
typedef struct _FIL {
|
||||||
FATFS* fs; /* Pointer to the owner file system object */
|
//WORD id; /* Owner file system mount ID */
|
||||||
WORD id; /* Owner file system mount ID */
|
|
||||||
BYTE flag; /* File status flags */
|
BYTE flag; /* File status flags */
|
||||||
BYTE csect; /* Sector address in the cluster */
|
BYTE csect; /* Sector address in the cluster */
|
||||||
|
FATFS* fs; /* Pointer to the owner file system object */
|
||||||
DWORD fptr; /* File R/W pointer */
|
DWORD fptr; /* File R/W pointer */
|
||||||
DWORD fsize; /* File size */
|
DWORD fsize; /* File size */
|
||||||
DWORD org_clust; /* File start cluster */
|
DWORD org_clust; /* File start cluster */
|
||||||
DWORD curr_clust; /* Current cluster */
|
DWORD curr_clust; /* Current cluster */
|
||||||
DWORD dsect; /* Current data sector */
|
DWORD curr_sect; /* Current sector */
|
||||||
#if !_FS_READONLY
|
#if _FS_READONLY == 0
|
||||||
DWORD dir_sect; /* Sector containing the directory entry */
|
DWORD dir_sect; /* Sector containing the directory entry */
|
||||||
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
|
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
|
||||||
#endif
|
#endif
|
||||||
#if !_FS_TINY
|
#if _USE_LESS_BUF == 0 && _USE_1_BUF == 0
|
||||||
BYTE buf[_MAX_SS];/* File R/W buffer */
|
BUF buf; /* File R/W buffer */
|
||||||
#endif
|
#endif
|
||||||
} FIL;
|
} FIL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* File status structure */
|
/* File status structure */
|
||||||
|
|
||||||
typedef struct _FILINFO {
|
typedef struct _FILINFO {
|
||||||
DWORD fsize; /* File size */
|
DWORD fsize; /* Size */
|
||||||
WORD fdate; /* Last modified date */
|
WORD fdate; /* Date */
|
||||||
WORD ftime; /* Last modified time */
|
WORD ftime; /* Time */
|
||||||
BYTE fattrib; /* Attribute */
|
BYTE fattrib; /* Attribute */
|
||||||
char fname[13]; /* Short file name (8.3 format) */
|
DWORD clust; /* Start cluster */
|
||||||
#if _USE_LFN
|
UCHAR fname[8+1+3+1]; /* Name (8.3 format) */
|
||||||
char *lfname; /* Pointer to the LFN buffer */
|
#if _USE_LFN != 0
|
||||||
int lfsize; /* Size of LFN buffer [bytes] */
|
UCHAR* lfn;
|
||||||
#endif
|
#endif
|
||||||
} FILINFO;
|
} 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 */
|
/* Definitions corresponds to multi partition */
|
||||||
|
|
||||||
#if _MULTI_PARTITION /* Multiple partition configuration */
|
#if _MULTI_PARTITION != 0 /* Multiple partition cfg */
|
||||||
|
|
||||||
typedef struct _PARTITION {
|
#define LD2PD(drv) (drv >> (8-_PARTITION_MASK)) /* Get physical drive# */
|
||||||
BYTE pd; /* Physical drive# */
|
#define LD2PT(drv) (drv & ((1<<_PARTITION_MASK)-1)) /* Get partition# */
|
||||||
BYTE pt; /* Partition # (0-3) */
|
#define _LOGICAL_DRIVES (_DRIVES * (1<<_PARTITION_MASK))
|
||||||
} PARTITION;
|
|
||||||
|
|
||||||
extern
|
#else /* Single partition cfg */
|
||||||
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 logical drive# */
|
||||||
|
|
||||||
#define LD2PD(drv) (drv) /* Physical drive# is equal to the logical drive# */
|
|
||||||
#define LD2PT(drv) 0 /* Always mounts the 1st partition */
|
#define LD2PT(drv) 0 /* Always mounts the 1st partition */
|
||||||
|
#define _LOGICAL_DRIVES _DRIVES
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* File function return code (FRESULT) */
|
/* File function return code (FRESULT) */
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FR_OK = 0, /* 0 */
|
FR_OK = 0, /* 0 */
|
||||||
FR_DISK_ERR, /* 1 */
|
FR_NOT_READY, /* 1 */
|
||||||
FR_INT_ERR, /* 2 */
|
FR_NO_FILE, /* 2 */
|
||||||
FR_NOT_READY, /* 3 */
|
FR_NO_PATH, /* 3 */
|
||||||
FR_NO_FILE, /* 4 */
|
FR_INVALID_NAME, /* 4 */
|
||||||
FR_NO_PATH, /* 5 */
|
FR_INVALID_DRIVE, /* 5 */
|
||||||
FR_INVALID_NAME, /* 6 */
|
FR_DENIED, /* 6 */
|
||||||
FR_DENIED, /* 7 */
|
FR_EXIST, /* 7 */
|
||||||
FR_EXIST, /* 8 */
|
FR_RW_ERROR, /* 8 */
|
||||||
FR_INVALID_OBJECT, /* 9 */
|
FR_WRITE_PROTECTED, /* 9 */
|
||||||
FR_WRITE_PROTECTED, /* 10 */
|
FR_NOT_ENABLED, /* 10 */
|
||||||
FR_INVALID_DRIVE, /* 11 */
|
FR_NO_FILESYSTEM, /* 11 */
|
||||||
FR_NOT_ENABLED, /* 12 */
|
FR_INVALID_OBJECT, /* 12 */
|
||||||
FR_NO_FILESYSTEM, /* 13 */
|
FR_MKFS_ABORTED, /* 13 */
|
||||||
FR_MKFS_ABORTED, /* 14 */
|
FR_IS_DIRECTORY, /* 13 */
|
||||||
FR_TIMEOUT /* 15 */
|
FR_IS_READONLY, /* 14 */
|
||||||
|
FR_DIR_NOT_EMPTY, /* 15 */
|
||||||
|
FR_NOT_DIRECTORY /* 16 */
|
||||||
} FRESULT;
|
} FRESULT;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------*/
|
/*-----------------------------------------------------*/
|
||||||
/* FatFs module application interface */
|
/* FatFs module application interface */
|
||||||
|
|
||||||
|
#if _USE_DRIVE_PREFIX == 0
|
||||||
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
|
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
|
||||||
FRESULT f_open (FIL*, const char*, BYTE); /* Open or create a file */
|
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_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_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_lseek (FIL*, DWORD); /* Move file pointer of a file object */
|
||||||
FRESULT f_close (FIL*); /* Close an open file object */
|
FRESULT f_close (FIL*); /* Close an open file object */
|
||||||
FRESULT f_opendir (DIR*, const char*); /* Open an existing directory */
|
FRESULT f_opendir (FATFS*, DIR*, const UCHAR*); /* Open an existing directory */
|
||||||
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
|
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
|
||||||
FRESULT f_stat (const char*, FILINFO*); /* Get file status */
|
FRESULT f_stat (FATFS*, const UCHAR*, FILINFO*); /* Get file status */
|
||||||
FRESULT f_getfree (const char*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
|
FRESULT f_getfree (FATFS*, const UCHAR*, DWORD*); /* 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_sync (FIL*); /* Flush cached data of a writing file */
|
||||||
FRESULT f_unlink (const char*); /* Delete an existing file or directory */
|
FRESULT f_unlink (FATFS*, const UCHAR*); /* Delete an existing file or directory */
|
||||||
FRESULT f_mkdir (const char*); /* Create a new directory */
|
FRESULT f_mkdir (FATFS*, const UCHAR*); /* Create a new directory */
|
||||||
FRESULT f_chmod (const char*, BYTE, BYTE); /* Change attriburte of the file/dir */
|
FRESULT f_chmod (FATFS*, const UCHAR*, BYTE, BYTE); /* Change file/dir attriburte */
|
||||||
FRESULT f_utime (const char*, const FILINFO*); /* Change timestamp of the file/dir */
|
FRESULT f_rename (FATFS*, const UCHAR*, const UCHAR*); /* Rename/Move a file or directory */
|
||||||
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 */
|
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
|
#if _USE_STRFUNC
|
||||||
int f_putc (int, FIL*); /* Put a character to the file */
|
#define feof(fp) ((fp)->fptr == (fp)->fsize)
|
||||||
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
|
#define EOF -1
|
||||||
#endif
|
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
|
#endif
|
||||||
|
|
||||||
|
/* User defined function to give a current time to fatfs module */
|
||||||
|
|
||||||
|
#if CONFIG_RTC_VARIANT > 0
|
||||||
/*--------------------------------------------------------------*/
|
|
||||||
/* 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) */
|
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) */
|
/* 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
|
#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) */
|
/* File access control and file status flags (FIL.flag) */
|
||||||
|
|
||||||
#define FA_READ 0x01
|
#define FA_READ 0x01
|
||||||
@ -462,12 +367,10 @@ void ff_rel_grant(_SYNC_t);
|
|||||||
#define AM_LFN 0x0F /* LFN entry */
|
#define AM_LFN 0x0F /* LFN entry */
|
||||||
#define AM_DIR 0x10 /* Directory */
|
#define AM_DIR 0x10 /* Directory */
|
||||||
#define AM_ARC 0x20 /* Archive */
|
#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
|
/* Offset of FAT structure members */
|
||||||
/ between various compilers. */
|
|
||||||
|
|
||||||
#define BS_jmpBoot 0
|
#define BS_jmpBoot 0
|
||||||
#define BS_OEMName 3
|
#define BS_OEMName 3
|
||||||
@ -513,6 +416,7 @@ void ff_rel_grant(_SYNC_t);
|
|||||||
#define DIR_Name 0
|
#define DIR_Name 0
|
||||||
#define DIR_Attr 11
|
#define DIR_Attr 11
|
||||||
#define DIR_NTres 12
|
#define DIR_NTres 12
|
||||||
|
#define DIR_Chksum 13
|
||||||
#define DIR_CrtTime 14
|
#define DIR_CrtTime 14
|
||||||
#define DIR_CrtDate 16
|
#define DIR_CrtDate 16
|
||||||
#define DIR_FstClusHI 20
|
#define DIR_FstClusHI 20
|
||||||
@ -520,28 +424,24 @@ void ff_rel_grant(_SYNC_t);
|
|||||||
#define DIR_WrtDate 24
|
#define DIR_WrtDate 24
|
||||||
#define DIR_FstClusLO 26
|
#define DIR_FstClusLO 26
|
||||||
#define DIR_FileSize 28
|
#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 */
|
/* Multi-byte word access macros */
|
||||||
|
|
||||||
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
|
#if _MCU_ENDIAN == 1 /* Use word access */
|
||||||
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
||||||
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
||||||
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
||||||
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
||||||
#else /* Use byte-by-byte access to the FAT structure */
|
#elif _MCU_ENDIAN == 2 /* Use byte-by-byte access */
|
||||||
#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
|
#define LD_WORD(ptr) (WORD)(((WORD)*(volatile BYTE*)((ptr)+1)<<8)|(WORD)*(volatile 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 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) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
|
#define ST_WORD(ptr,val) *(volatile BYTE*)(ptr)=(BYTE)(val); *(volatile 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)
|
#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
|
#endif
|
||||||
|
|
||||||
|
#define _FATFS
|
||||||
#endif /* _FATFS */
|
#endif /* _FATFS */
|
||||||
|
|||||||
@ -6,12 +6,16 @@
|
|||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
#include "fileops.h"
|
#include "fileops.h"
|
||||||
|
|
||||||
|
WCHAR ff_convert(WCHAR w, UINT dir) {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
void file_init() {
|
void file_init() {
|
||||||
f_mount(0, &fatfs);
|
f_mount(0, &fatfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_open(char* filename, BYTE flags) {
|
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() {
|
void file_close() {
|
||||||
|
|||||||
@ -40,15 +40,16 @@
|
|||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "sdcard.h"
|
#include "sdcard.h"
|
||||||
#include "diskio.h"
|
#include "diskio.h"
|
||||||
|
#include "integer.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
#include "fileops.h"
|
#include "fileops.h"
|
||||||
#include "fpga_spi.h"
|
#include "fpga_spi.h"
|
||||||
#include "spi.h"
|
#include "spi.h"
|
||||||
#include "avrcompat.h"
|
#include "avrcompat.h"
|
||||||
|
|
||||||
DWORD get_fattime(void) {
|
/*DWORD get_fattime(void) {
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}*/
|
||||||
void set_prog_b(uint8_t val) {
|
void set_prog_b(uint8_t val) {
|
||||||
if(val) {
|
if(val) {
|
||||||
PORTD |= _BV(PD3);
|
PORTD |= _BV(PD3);
|
||||||
|
|||||||
@ -17,6 +17,7 @@ typedef uint8_t BYTE;
|
|||||||
typedef int16_t SHORT;
|
typedef int16_t SHORT;
|
||||||
typedef uint16_t USHORT;
|
typedef uint16_t USHORT;
|
||||||
typedef uint16_t WORD;
|
typedef uint16_t WORD;
|
||||||
|
typedef uint16_t WCHAR;
|
||||||
|
|
||||||
/* These types are assumed as 32-bit integer */
|
/* These types are assumed as 32-bit integer */
|
||||||
typedef int32_t LONG;
|
typedef int32_t LONG;
|
||||||
|
|||||||
37
src/main.c
37
src/main.c
@ -47,8 +47,7 @@
|
|||||||
#include "fpga_spi.h"
|
#include "fpga_spi.h"
|
||||||
#include "spi.h"
|
#include "spi.h"
|
||||||
#include "avrcompat.h"
|
#include "avrcompat.h"
|
||||||
|
#include "filetypes.h"
|
||||||
char stringbuf[100];
|
|
||||||
|
|
||||||
/* Make sure the watchdog is disabled as soon as possible */
|
/* Make sure the watchdog is disabled as soon as possible */
|
||||||
/* Copy this code to your bootloader if you use one and your */
|
/* Copy this code to your bootloader if you use one and your */
|
||||||
@ -131,7 +130,7 @@ int main(void) {
|
|||||||
|
|
||||||
snes_reset(1);
|
snes_reset(1);
|
||||||
uart_init();
|
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);
|
_delay_ms(100);
|
||||||
disk_init();
|
disk_init();
|
||||||
snes_init();
|
snes_init();
|
||||||
@ -140,7 +139,6 @@ int main(void) {
|
|||||||
uart_putcrlf();
|
uart_putcrlf();
|
||||||
|
|
||||||
file_init();
|
file_init();
|
||||||
|
|
||||||
FATFS fatfs;
|
FATFS fatfs;
|
||||||
f_mount(0,&fatfs);
|
f_mount(0,&fatfs);
|
||||||
set_busy_led(1);
|
set_busy_led(1);
|
||||||
@ -160,12 +158,29 @@ int main(void) {
|
|||||||
uart_putc('[');
|
uart_putc('[');
|
||||||
load_sram("/test.srm");
|
load_sram("/test.srm");
|
||||||
uart_putc(']');
|
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_busy_led(0);
|
||||||
set_avr_ena(1);
|
set_avr_ena(1);
|
||||||
_delay_ms(100);
|
_delay_ms(100);
|
||||||
uart_puts_P(PSTR("SNES GO!"));
|
uart_puts_P(PSTR("SNES GO!\n"));
|
||||||
snes_reset(0);
|
snes_reset(0);
|
||||||
|
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
snes_main_loop();
|
snes_main_loop();
|
||||||
}
|
}
|
||||||
@ -173,14 +188,8 @@ int main(void) {
|
|||||||
|
|
||||||
/* HERE BE LIONS */
|
/* HERE BE LIONS */
|
||||||
while(1) {
|
while(1) {
|
||||||
SPI_SS_HIGH();
|
set_avr_addr(0x600000);
|
||||||
FPGA_SS_LOW();
|
spi_fpga();
|
||||||
spiTransferByte(0x00);
|
|
||||||
spiTransferByte(0x00);
|
|
||||||
spiTransferByte(0x7f);
|
|
||||||
spiTransferByte(0xc0);
|
|
||||||
FPGA_SS_HIGH();
|
|
||||||
FPGA_SS_LOW();
|
|
||||||
spiTransferByte(0x81); // read w/ increment... hopefully
|
spiTransferByte(0x81); // read w/ increment... hopefully
|
||||||
spiTransferByte(0x00); // 1 dummy read
|
spiTransferByte(0x00); // 1 dummy read
|
||||||
uart_putcrlf();
|
uart_putcrlf();
|
||||||
@ -202,7 +211,7 @@ while(1) {
|
|||||||
}
|
}
|
||||||
// set_avr_bank(3);
|
// set_avr_bank(3);
|
||||||
}
|
}
|
||||||
FPGA_SS_HIGH();
|
spi_sd();
|
||||||
}
|
}
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/memory.c
13
src/memory.c
@ -14,32 +14,32 @@
|
|||||||
#include "fpga_spi.h"
|
#include "fpga_spi.h"
|
||||||
#include "avrcompat.h"
|
#include "avrcompat.h"
|
||||||
#include "led.h"
|
#include "led.h"
|
||||||
#include "filetypes.h"
|
#include "smc.h"
|
||||||
#include "fpga_spi.h"
|
#include "fpga_spi.h"
|
||||||
|
|
||||||
char* hex = "0123456789ABCDEF";
|
char* hex = "0123456789ABCDEF";
|
||||||
|
|
||||||
void sram_readblock(void* buf, uint32_t addr, uint16_t size) {
|
void sram_readblock(void* buf, uint32_t addr, uint16_t size) {
|
||||||
uint16_t count=size;
|
uint16_t count=size;
|
||||||
void* tgt = buf;
|
uint8_t* tgt = buf;
|
||||||
set_avr_addr(addr);
|
set_avr_addr(addr);
|
||||||
spi_fpga();
|
spi_fpga();
|
||||||
spiTransferByte(0x81); // READ
|
spiTransferByte(0x81); // READ
|
||||||
spiTransferByte(0x00); // dummy
|
spiTransferByte(0x00); // dummy
|
||||||
while(count--) {
|
while(count--) {
|
||||||
*((uint8_t*)tgt++) = spiTransferByte(0x00);
|
*(tgt++) = spiTransferByte(0x00);
|
||||||
}
|
}
|
||||||
spi_sd();
|
spi_sd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
|
void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
|
||||||
uint16_t count=size;
|
uint16_t count=size;
|
||||||
void* src = buf;
|
uint8_t* src = buf;
|
||||||
set_avr_addr(addr);
|
set_avr_addr(addr);
|
||||||
spi_fpga();
|
spi_fpga();
|
||||||
spiTransferByte(0x91); // WRITE
|
spiTransferByte(0x91); // WRITE
|
||||||
while(count--) {
|
while(count--) {
|
||||||
spiTransferByte(*((uint8_t*)src++));
|
spiTransferByte(*src++);
|
||||||
}
|
}
|
||||||
spiTransferByte(0x00); // dummy
|
spiTransferByte(0x00); // dummy
|
||||||
spi_sd();
|
spi_sd();
|
||||||
@ -157,6 +157,9 @@ void save_sram(char* filename, uint32_t sram_size, uint32_t base_addr) {
|
|||||||
}
|
}
|
||||||
spi_sd();
|
spi_sd();
|
||||||
num = file_write();
|
num = file_write();
|
||||||
|
if(file_res) {
|
||||||
|
uart_putc(0x30+file_res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
file_close();
|
file_close();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
#define MEMORY_H
|
#define MEMORY_H
|
||||||
uint32_t load_rom(char* filename);
|
uint32_t load_rom(char* filename);
|
||||||
uint32_t load_sram(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);
|
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);
|
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
111
src/smc.c
Normal file
111
src/smc.c
Normal 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
46
src/smc.h
Normal 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
|
||||||
@ -47,7 +47,7 @@ void snes_reset(int state) {
|
|||||||
void snes_main_loop() {
|
void snes_main_loop() {
|
||||||
if(initloop) {
|
if(initloop) {
|
||||||
saveram_crc_old = calc_sram_crc(saveram_base_addr, saveram_size);
|
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;
|
initloop=0;
|
||||||
}
|
}
|
||||||
saveram_crc = calc_sram_crc(saveram_base_addr, saveram_size);
|
saveram_crc = calc_sram_crc(saveram_base_addr, saveram_size);
|
||||||
@ -56,7 +56,7 @@ void snes_main_loop() {
|
|||||||
uart_puthexshort(saveram_crc);
|
uart_puthexshort(saveram_crc);
|
||||||
uart_putcrlf();
|
uart_putcrlf();
|
||||||
set_busy_led(1);
|
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);
|
set_busy_led(0);
|
||||||
}
|
}
|
||||||
saveram_crc_old = saveram_crc;
|
saveram_crc_old = saveram_crc;
|
||||||
|
|||||||
@ -56,15 +56,16 @@ end
|
|||||||
Index Mapper
|
Index Mapper
|
||||||
000 HiROM
|
000 HiROM
|
||||||
001 LoROM
|
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 */
|
Offset 6000-7fff */
|
||||||
assign IS_SAVERAM = ((MAPPER == 3'b000 || MAPPER == 3'b010) ? (!SNES_ADDR[22]
|
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[14:13]
|
||||||
& !SNES_ADDR[15]
|
& !SNES_ADDR[15]
|
||||||
|
& SNES_CS
|
||||||
)
|
)
|
||||||
/* LoROM: SRAM @ Bank 0x70-0x7d, 0xf0-0xfd
|
/* LoROM: SRAM @ Bank 0x70-0x7d, 0xf0-0xfd
|
||||||
Offset 0000-7fff TODO: 0000-ffff for
|
Offset 0000-7fff TODO: 0000-ffff for
|
||||||
|
|||||||
@ -182,3 +182,52 @@ NET "SRAM_DATA[8]" LOC = P96;
|
|||||||
NET "SRAM_DATA[9]" LOC = P98;
|
NET "SRAM_DATA[9]" LOC = P98;
|
||||||
NET "SRAM_OE" LOC = P93;
|
NET "SRAM_OE" LOC = P93;
|
||||||
NET "CLKIN" IOSTANDARD = LVCMOS33;
|
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;
|
||||||
|
|||||||
@ -120,14 +120,20 @@ wire SNES_RW;
|
|||||||
reg [1:0] SNES_READr;
|
reg [1:0] SNES_READr;
|
||||||
reg [1:0] SNES_WRITEr;
|
reg [1:0] SNES_WRITEr;
|
||||||
reg [1:0] SNES_CSr;
|
reg [1:0] SNES_CSr;
|
||||||
reg [1:0] SNES_CPU_CLKr;
|
reg [5:0] SNES_CPU_CLKr;
|
||||||
reg [7:0] SNES_RWr;
|
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_READs = (SNES_READr == 2'b11);
|
||||||
wire SNES_WRITEs = (SNES_WRITEr == 2'b11);
|
wire SNES_WRITEs = (SNES_WRITEr == 2'b11);
|
||||||
wire SNES_CSs = (SNES_CSr == 2'b11);
|
wire SNES_CSs = (SNES_CSr == 2'b11);
|
||||||
wire SNES_CPU_CLKs = SNES_CPU_CLK; // (SNES_CPU_CLKr == 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);
|
assign SNES_RW = (SNES_READ & SNES_WRITE);
|
||||||
|
|
||||||
@ -135,11 +141,15 @@ always @(posedge CLK2) begin
|
|||||||
SNES_READr <= {SNES_READr[0], SNES_READ};
|
SNES_READr <= {SNES_READr[0], SNES_READ};
|
||||||
SNES_WRITEr <= {SNES_WRITEr[0], SNES_WRITE};
|
SNES_WRITEr <= {SNES_WRITEr[0], SNES_WRITE};
|
||||||
SNES_CSr <= {SNES_CSr[0], SNES_CS};
|
SNES_CSr <= {SNES_CSr[0], SNES_CS};
|
||||||
SNES_CPU_CLKr <= {SNES_CPU_CLKr[0], SNES_CPU_CLK};
|
SNES_CPU_CLKr <= {SNES_CPU_CLKr[4:0], SNES_CPU_CLK};
|
||||||
SNES_RWr <= {SNES_RWr[6:0], SNES_RW};
|
SNES_RWr <= {SNES_RWr[4:0], SNES_RW};
|
||||||
end
|
end
|
||||||
|
|
||||||
reg ADDR_WRITE;
|
reg ADDR_WRITE;
|
||||||
|
|
||||||
|
//reg [23:0] SNES_ADDRr;
|
||||||
|
//wire [23:0] SNES_ADDRw = SNES_ADDR;
|
||||||
|
|
||||||
|
|
||||||
address snes_addr(
|
address snes_addr(
|
||||||
.CLK(CLK2),
|
.CLK(CLK2),
|
||||||
@ -158,6 +168,11 @@ address snes_addr(
|
|||||||
.ROM_MASK(ROM_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),
|
data snes_data(.CLK(CLK2),
|
||||||
.SNES_READ(SNES_READ),
|
.SNES_READ(SNES_READ),
|
||||||
.SNES_WRITE(SNES_WRITE),
|
.SNES_WRITE(SNES_WRITE),
|
||||||
@ -179,33 +194,36 @@ data snes_data(.CLK(CLK2),
|
|||||||
parameter MODE_SNES = 1'b0;
|
parameter MODE_SNES = 1'b0;
|
||||||
parameter MODE_AVR = 1'b1;
|
parameter MODE_AVR = 1'b1;
|
||||||
|
|
||||||
parameter STATE_0 = 10'b0000000001;
|
parameter STATE_0 = 13'b0000000000001;
|
||||||
parameter STATE_1 = 10'b0000000010;
|
parameter STATE_1 = 13'b0000000000010;
|
||||||
parameter STATE_2 = 10'b0000000100;
|
parameter STATE_2 = 13'b0000000000100;
|
||||||
parameter STATE_3 = 10'b0000001000;
|
parameter STATE_3 = 13'b0000000001000;
|
||||||
parameter STATE_4 = 10'b0000010000;
|
parameter STATE_4 = 13'b0000000010000;
|
||||||
parameter STATE_5 = 10'b0000100000;
|
parameter STATE_5 = 13'b0000000100000;
|
||||||
parameter STATE_6 = 10'b0001000000;
|
parameter STATE_6 = 13'b0000001000000;
|
||||||
parameter STATE_7 = 10'b0010000000;
|
parameter STATE_7 = 13'b0000010000000;
|
||||||
parameter STATE_8 = 10'b0100000000;
|
parameter STATE_8 = 13'b0000100000000;
|
||||||
parameter STATE_9 = 10'b1000000000;
|
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 [3:0] STATEIDX;
|
||||||
|
|
||||||
reg STATE_RESET, CYCLE_RESET, CYCLE_RESET_ACK;
|
reg [1:0] CYCLE_RESET;
|
||||||
reg SRAM_WE_MASK;
|
reg SRAM_WE_MASK;
|
||||||
reg SRAM_OE_MASK;
|
reg SRAM_OE_MASK;
|
||||||
|
|
||||||
reg [9:0] SRAM_WE_ARRAY [3:0];
|
reg [12:0] SRAM_WE_ARRAY [3:0];
|
||||||
reg [9:0] SRAM_OE_ARRAY [3:0];
|
reg [12:0] SRAM_OE_ARRAY [3:0];
|
||||||
|
|
||||||
reg [9:0] SNES_DATA_TO_MEM_ARRAY[1:0];
|
reg [12:0] SNES_DATA_TO_MEM_ARRAY[1:0];
|
||||||
reg [9:0] AVR_DATA_TO_MEM_ARRAY[1:0];
|
reg [12:0] AVR_DATA_TO_MEM_ARRAY[1:0];
|
||||||
reg [9:0] SRAM_DATA_TO_SNES_MEM_ARRAY[1:0];
|
reg [12:0] SRAM_DATA_TO_SNES_MEM_ARRAY[1:0];
|
||||||
reg [9:0] SRAM_DATA_TO_AVR_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_READ_CYCLE;
|
||||||
reg SNES_WRITE_CYCLE;
|
reg SNES_WRITE_CYCLE;
|
||||||
@ -225,41 +243,39 @@ reg SNES_DATABUS_DIR_BUF;
|
|||||||
assign MODE = !AVR_ENA ? MODE_AVR : MODE_ARRAY[STATEIDX];
|
assign MODE = !AVR_ENA ? MODE_AVR : MODE_ARRAY[STATEIDX];
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
CYCLE_RESET = 0;
|
CYCLE_RESET = 2'b0;
|
||||||
CYCLE_RESET_ACK = 0;
|
|
||||||
|
|
||||||
STATE = STATE_9;
|
STATE = STATE_IDLE;
|
||||||
STATEIDX = 9;
|
STATEIDX = 12;
|
||||||
SRAM_WE_MASK = 1'b1;
|
SRAM_WE_MASK = 1'b1;
|
||||||
SRAM_OE_MASK = 1'b1;
|
SRAM_OE_MASK = 1'b1;
|
||||||
SNES_READ_CYCLE = 1'b1;
|
SNES_READ_CYCLE = 1'b1;
|
||||||
SNES_WRITE_CYCLE = 1'b1;
|
SNES_WRITE_CYCLE = 1'b1;
|
||||||
AVR_READ_CYCLE = 1'b1;
|
AVR_READ_CYCLE = 1'b1;
|
||||||
AVR_WRITE_CYCLE = 1'b1;
|
AVR_WRITE_CYCLE = 1'b1;
|
||||||
|
MODE_ARRAY = 13'b0000000111111;
|
||||||
|
|
||||||
MODE_ARRAY = 10'b0000011111;
|
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;
|
||||||
|
|
||||||
SRAM_WE_ARRAY[2'b00] = 10'b1000010000;
|
SRAM_OE_ARRAY[2'b00] = 13'b1111111111111;
|
||||||
SRAM_WE_ARRAY[2'b01] = 10'b1000011111;
|
SRAM_OE_ARRAY[2'b01] = 13'b1111111000000;
|
||||||
SRAM_WE_ARRAY[2'b10] = 10'b1111110000;
|
SRAM_OE_ARRAY[2'b10] = 13'b0000000111111;
|
||||||
SRAM_WE_ARRAY[2'b11] = 10'b1111111111;
|
SRAM_OE_ARRAY[2'b11] = 13'b0000000000000;
|
||||||
|
|
||||||
SRAM_OE_ARRAY[2'b00] = 10'b1111111111;
|
SNES_DATA_TO_MEM_ARRAY[1'b0] = 13'b0001000000000; // SNES write
|
||||||
SRAM_OE_ARRAY[2'b01] = 10'b1111100000;
|
SNES_DATA_TO_MEM_ARRAY[1'b1] = 13'b0000000000000; // SNES read
|
||||||
SRAM_OE_ARRAY[2'b10] = 10'b0000011111;
|
|
||||||
SRAM_OE_ARRAY[2'b11] = 10'b0000000000;
|
|
||||||
|
|
||||||
SNES_DATA_TO_MEM_ARRAY[1'b0] = 10'b1000000000;
|
AVR_DATA_TO_MEM_ARRAY[1'b0] = 13'b0000000010000; // AVR write
|
||||||
SNES_DATA_TO_MEM_ARRAY[1'b1] = 10'b0000000000;
|
AVR_DATA_TO_MEM_ARRAY[1'b1] = 13'b0000000000000; // AVR read
|
||||||
|
|
||||||
AVR_DATA_TO_MEM_ARRAY[1'b0] = 10'b0000010000;
|
SRAM_DATA_TO_SNES_MEM_ARRAY[1'b0] = 13'b0000000000000; // SNES write
|
||||||
AVR_DATA_TO_MEM_ARRAY[1'b1] = 10'b0000000000;
|
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_AVR_MEM_ARRAY[1'b0] = 13'b0000000000000; // AVR write
|
||||||
SRAM_DATA_TO_SNES_MEM_ARRAY[1'b1] = 10'b0000100000;
|
SRAM_DATA_TO_AVR_MEM_ARRAY[1'b1] = 13'b0000000000001; // AVR read
|
||||||
|
|
||||||
SRAM_DATA_TO_AVR_MEM_ARRAY[1'b0] = 10'b0000000000;
|
|
||||||
SRAM_DATA_TO_AVR_MEM_ARRAY[1'b1] = 10'b0000000001;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// falling edge of SNES /RD or /WR marks the beginning of a new cycle
|
// 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.
|
// the minimum of 6 SNES cycles to get everything done.
|
||||||
// we have 24 internal cycles to work with. (CLKIN * 4)
|
// we have 24 internal cycles to work with. (CLKIN * 4)
|
||||||
|
|
||||||
reg [1:0] CYCLE_RESET;
|
|
||||||
|
|
||||||
always @(posedge CLK2) begin
|
always @(posedge CLK2) begin
|
||||||
CYCLE_RESET <= {CYCLE_RESET[0], SNES_RW_start};
|
CYCLE_RESET <= {CYCLE_RESET[0], SNES_cycle_start};
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge CLK2) begin
|
always @(posedge CLK2) begin
|
||||||
if (CYCLE_RESET[1]) begin
|
if (SNES_RW_start) begin
|
||||||
STATE <= STATE_0;
|
|
||||||
SNES_READ_CYCLE <= SNES_READ;
|
SNES_READ_CYCLE <= SNES_READ;
|
||||||
SNES_WRITE_CYCLE <= SNES_WRITE;
|
SNES_WRITE_CYCLE <= SNES_WRITE;
|
||||||
AVR_READ_CYCLE <= AVR_READ;
|
AVR_READ_CYCLE <= AVR_READ;
|
||||||
AVR_WRITE_CYCLE <= AVR_WRITE;
|
AVR_WRITE_CYCLE <= AVR_WRITE;
|
||||||
|
STATE <= STATE_0;
|
||||||
|
STATEIDX <= 11;
|
||||||
end else begin
|
end else begin
|
||||||
case (STATE)
|
case (STATE)
|
||||||
STATE_0:
|
STATE_0: begin
|
||||||
STATE <= STATE_1;
|
STATE <= STATE_1; STATEIDX <= 10;
|
||||||
STATE_1:
|
end
|
||||||
STATE <= STATE_2;
|
STATE_1: begin
|
||||||
STATE_2:
|
STATE <= STATE_2; STATEIDX <= 9;
|
||||||
STATE <= STATE_3;
|
end
|
||||||
STATE_3:
|
STATE_2: begin
|
||||||
STATE <= STATE_4;
|
STATE <= STATE_3; STATEIDX <= 8;
|
||||||
STATE_4:
|
end
|
||||||
STATE <= STATE_5;
|
STATE_3: begin
|
||||||
STATE_5:
|
STATE <= STATE_4; STATEIDX <= 7;
|
||||||
STATE <= STATE_6;
|
end
|
||||||
STATE_6:
|
STATE_4: begin
|
||||||
STATE <= STATE_7;
|
STATE <= STATE_5; STATEIDX <= 6;
|
||||||
STATE_7:
|
end
|
||||||
STATE <= STATE_8;
|
STATE_5: begin
|
||||||
STATE_8:
|
STATE <= STATE_6; STATEIDX <= 5;
|
||||||
STATE <= STATE_9;
|
end
|
||||||
STATE_9: begin
|
STATE_6: begin
|
||||||
STATE <= STATE_9;
|
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_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
|
end
|
||||||
default:
|
|
||||||
STATE <= STATE_9;
|
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
/*
|
||||||
always @(posedge CLK2) begin
|
always @(posedge CLK2) begin
|
||||||
|
|
||||||
case (STATE)
|
case (STATE)
|
||||||
@ -356,7 +390,7 @@ always @(posedge CLK2) begin
|
|||||||
STATEIDX <= 9;
|
STATEIDX <= 9;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
*/
|
||||||
// When in AVR mode, enable SRAM_WE according to AVR programming
|
// When in AVR mode, enable SRAM_WE according to AVR programming
|
||||||
// else enable SRAM_WE according to state&cycle
|
// else enable SRAM_WE according to state&cycle
|
||||||
assign SRAM_WE = !AVR_ENA ? AVR_WRITE
|
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 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_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_OE = (IS_ROM & SNES_CS) | (!IS_ROM & !IS_SAVERAM) | (SNES_READ & SNES_WRITE);
|
||||||
assign SNES_DATABUS_DIR = !SNES_WRITEs ? 1'b0 : 1'b1;
|
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 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];
|
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_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 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 IRQ_DIR = 1'b0;
|
||||||
assign SNES_IRQ = 1'bZ;
|
assign SNES_IRQ = 1'bZ;
|
||||||
|
|
||||||
|
|||||||
@ -69,21 +69,30 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<property xil_pn:name="Auto Implementation Top" xil_pn:value="false"/>
|
<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="Constraints Entry" xil_pn:value="Constraints Editor"/>
|
||||||
<property xil_pn:name="Device" xil_pn:value="xc3s200"/>
|
<property xil_pn:name="Device" xil_pn:value="xc3s200"/>
|
||||||
<property xil_pn:name="Device Family" xil_pn:value="Spartan3"/>
|
<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="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="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" xil_pn:value="Module|main"/>
|
||||||
<property xil_pn:name="Implementation Top Instance Path" xil_pn:value="/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_BehavioralSimTop" xil_pn:value="Module|main_tf2"/>
|
||||||
<property xil_pn:name="PROP_DesignName" xil_pn:value="sd2snes"/>
|
<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="PROP_PostParSimTop" xil_pn:value="Module|main_tf2"/>
|
||||||
<property xil_pn:name="Package" xil_pn:value="tq144"/>
|
<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 & Route Effort Level (Overall)" xil_pn:value="High"/>
|
<property xil_pn:name="Place & 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="Placer Effort Level (Overrides Overall Level)" xil_pn:value="High"/>
|
||||||
<property xil_pn:name="Preferred Language" xil_pn:value="Verilog"/>
|
<property xil_pn:name="Preferred Language" xil_pn:value="Verilog"/>
|
||||||
<property xil_pn:name="Project Description" xil_pn:value="sd2snes"/>
|
<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="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 Behavioral" xil_pn:value="Module|main_tf2"/>
|
||||||
<property xil_pn:name="Selected Simulation Root Source Node Post-Route" xil_pn:value="Module|main_tf2"/>
|
<property xil_pn:name="Selected Simulation Root Source Node Post-Route" xil_pn:value="Module|main_tf2"/>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user