From d03ef8416aed66f6dfc24519f3d66ebdf772cae5 Mon Sep 17 00:00:00 2001 From: Till Harbaum Date: Tue, 17 Nov 2015 21:53:21 +0100 Subject: [PATCH 1/2] Blockfile index acceleration --- idxfile.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ idxfile.h | 42 ++++++++++++++++++++++++++++++++++++++++++ menu.c | 7 +++++-- user_io.c | 36 +++++++++++++++++++++++------------- 4 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 idxfile.c create mode 100644 idxfile.h diff --git a/idxfile.c b/idxfile.c new file mode 100644 index 0000000..3fa2d6a --- /dev/null +++ b/idxfile.c @@ -0,0 +1,50 @@ +#include +#include "idxfile.h" + +void IDXIndex(IDXFile *pIDXF) { + // builds index to speed up hard file seek + fileTYPE *file = &pIDXF->file; + unsigned long *index = pIDXF->index; + unsigned long i; + unsigned long j; + unsigned long time = GetTimer(0); + + pIDXF->index_size = 16; // indexing size + j = 1 << pIDXF->index_size; + i = pIDXF->file.size >> 10; // divided by index table size (1024) + while (j < i) // find greater or equal power of two + { + j <<= 1; + pIDXF->index_size++; + } + + for (i = 0; i < file->size; i += j) + { + FileSeek(file, i >> 9, SEEK_SET); // FileSeek seeks in 512-byte sectors + *index++ = file->cluster; + } + + time = GetTimer(0) - time; + iprintf("File indexed in %lu ms, index size = %d\n", time >> 16, pIDXF->index_size); +} + +unsigned char IDXOpen(IDXFile *file, const char *name) { + unsigned char retval = FileOpen(&(file->file), name); + + if(retval) IDXIndex(file); + + return retval; +} + +unsigned char IDXSeek(IDXFile *pIDXF, unsigned long lba) +{ + if ((pIDXF->file.sector ^ lba) & cluster_mask) + { // different clusters + if ((pIDXF->file.sector > lba) || ((pIDXF->file.sector ^ lba) & (cluster_mask << (fat32 ? 7 : 8)))) // 7: 128 FAT32 links per sector, 8: 256 FAT16 links per sector + { // requested cluster lies before current pointer position or in different FAT sector + pIDXF->file.cluster = pIDXF->index[lba >> (pIDXF->index_size - 9)];// minus 9 because lba is in 512-byte sectors + pIDXF->file.sector = lba & (-1 << (pIDXF->index_size - 9)); + } + } + return FileSeek(&pIDXF->file, lba, SEEK_SET); +} diff --git a/idxfile.h b/idxfile.h new file mode 100644 index 0000000..0c0b3ec --- /dev/null +++ b/idxfile.h @@ -0,0 +1,42 @@ +#ifndef IDXFILE_H +#define IDXFILE_H + +/* Indexed file for fast random access on big files for e.g. hdd images + Copyright (c) 2015 by Till Harbaum + + Contributed to the Minimig project, which is free software; + you can redistribute it and/or modify it under the terms of + the GNU General Public License as published by the Free Software Foundation; + either version 3 of the License, or (at your option) any later version. + + Minimig is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "fat.h" + +typedef struct +{ + fileTYPE file; + unsigned long index[1024]; + unsigned long index_size; +} IDXFile; + +inline unsigned char IDXRead(IDXFile *file, unsigned char *pBuffer) { + return FileRead(&(file->file), pBuffer); +} + +inline unsigned char IDXWrite(IDXFile *file, unsigned char *pBuffer) { + return FileWrite(&(file->file), pBuffer); +} + +unsigned char IDXOpen(IDXFile *file, const char *name); +unsigned char IDXSeek(IDXFile *file, unsigned long lba); +void IDXIndex(IDXFile *pIDXF); + +#endif diff --git a/menu.c b/menu.c index bf11d53..3938421 100644 --- a/menu.c +++ b/menu.c @@ -114,7 +114,7 @@ const char* atari_chipset[]={"ST","STE","MegaSTE","STEroids"}; unsigned char config_autofire = 0; // file selection menu variables -char *fs_pFileExt = NULL; +char fs_pFileExt[4] = "xxx"; unsigned char fs_Options; unsigned char fs_MenuSelect; unsigned char fs_MenuCancel; @@ -123,6 +123,8 @@ void SelectFile(char* pFileExt, unsigned char Options, unsigned char MenuSelect, { // this function displays file selection menu + iprintf("%s - %s\n", pFileExt, fs_pFileExt); + if (strncmp(pFileExt, fs_pFileExt, 3) != 0) // check desired file extension { // if different from the current one go to the root directory and init entry buffer ChangeDirectory(DIRECTORY_ROOT); @@ -151,7 +153,8 @@ void SelectFile(char* pFileExt, unsigned char Options, unsigned char MenuSelect, } iprintf("pFileExt = %3s\n", pFileExt); - fs_pFileExt = pFileExt; + strcpy(fs_pFileExt, pFileExt); + // fs_pFileExt = pFileExt; fs_Options = Options; fs_MenuSelect = MenuSelect; fs_MenuCancel = MenuCancel; diff --git a/user_io.c b/user_io.c index 37c21ac..31fe1ad 100644 --- a/user_io.c +++ b/user_io.c @@ -12,7 +12,7 @@ #include "debug.h" #include "keycodes.h" #include "ikbd.h" -#include "fat.h" +#include "idxfile.h" #include "spi.h" #include "mist_cfg.h" #include "mmc.h" @@ -25,7 +25,7 @@ unsigned char key_remap_table[MAX_REMAP][2]; #define BREAK 0x8000 -fileTYPE sd_image; +IDXFile sd_image; extern fileTYPE file; extern char s[40]; @@ -130,7 +130,7 @@ static void PollAdc() { void user_io_init() { // no sd card image selected, SD card accesses will go directly // to the card - sd_image.size = 0; + sd_image.file.size = 0; // mark remap table as unused memset(key_remap_table, 0, sizeof(key_remap_table)); @@ -493,8 +493,12 @@ static void user_io_set_index(unsigned char index) { void user_io_file_mount(fileTYPE *file) { iprintf("selected %.12s with %d bytes\n", file->name, file->size); - memcpy(&sd_image, file, sizeof(fileTYPE)); + memcpy(&sd_image.file, file, sizeof(fileTYPE)); + + // build index for fast random access + IDXIndex(&sd_image); + // notify core of possible sd image change spi_uio_cmd8(UIO_SET_SDSTAT, 0); } @@ -938,11 +942,15 @@ void user_io_poll() { // ... and write it to disk DISKLED_ON; - if(sd_image.size) { - FileSeek(&sd_image, lba, SEEK_SET); - FileWrite(&sd_image, wr_buf); +#if 1 + if(sd_image.file.size) { + IDXSeek(&sd_image, lba); + IDXWrite(&sd_image, wr_buf); } else MMC_Write(lba, wr_buf); +#else + hexdump(wr_buf, 512, 0); +#endif DISKLED_OFF; } @@ -957,9 +965,9 @@ void user_io_poll() { // (C64 floppy does that ...) if(buffer_lba != lba) { DISKLED_ON; - if(sd_image.size) { - FileSeek(&sd_image, lba, SEEK_SET); - FileRead(&sd_image, buffer); + if(sd_image.file.size) { + IDXSeek(&sd_image, lba); + IDXRead(&sd_image, buffer); } else { // sector read // read sector from sd card if it is not already present in @@ -971,6 +979,8 @@ void user_io_poll() { } if(buffer_lba == lba) { + // hexdump(buffer, 32, 0); + // data is now stored in buffer. send it to fpga spi_uio_cmd_cont(UIO_SECTOR_RD); spi_block_write(buffer); @@ -983,9 +993,9 @@ void user_io_poll() { // just load the next sector now, so it may be prefetched // for the next request already DISKLED_ON; - if(sd_image.size) { - FileSeek(&sd_image, lba+1, SEEK_SET); - FileRead(&sd_image, buffer); + if(sd_image.file.size) { + IDXSeek(&sd_image, lba+1); + IDXRead(&sd_image, buffer); } else { // sector read // read sector from sd card if it is not already present in From 42d7a76848452c436a852ebd7e2d04212e59a001 Mon Sep 17 00:00:00 2001 From: Till Harbaum Date: Tue, 17 Nov 2015 21:55:44 +0100 Subject: [PATCH 2/2] Blockfile index acceleration --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e8e2ffa..5b85672 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ DUMP = $(BASE)-objdump TODAY = `date +"%m/%d/%y"` PRJ = firmware -SRC = Cstartup_SAM7.c fat.c fdd.c firmware.c fpga.c hardware.c spi.c hdd.c main.c menu.c mmc.c osd.c syscalls.c user_io.c boot.c rafile.c config.c tos.c ikbd.c xmodem.c ini_parser.c mist_cfg.c archie.c +SRC = Cstartup_SAM7.c fat.c fdd.c firmware.c fpga.c hardware.c spi.c hdd.c main.c menu.c mmc.c osd.c syscalls.c user_io.c boot.c rafile.c idxfile.c config.c tos.c ikbd.c xmodem.c ini_parser.c mist_cfg.c archie.c SRC += usb/max3421e.c usb/usb.c usb/hub.c usb/hid.c usb/hidparser.c usb/timer.c usb/asix.c usb/pl2303.c usb/usbrtc.c # SRC += usb/storage.c SRC += cdc_enumerate.c cdc_control.c