diff --git a/lib/SCSI2SD/src/firmware/bluescsi_toolbox.h b/lib/SCSI2SD/src/firmware/bluescsi_toolbox.h new file mode 100644 index 00000000..95877bd1 --- /dev/null +++ b/lib/SCSI2SD/src/firmware/bluescsi_toolbox.h @@ -0,0 +1,25 @@ +/** + * Copyright (C) 2023 Eric Helgeson + * + * This file is part of BlueSCSI + * + * This program 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. + * + * This program 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 . +**/ + +#ifndef S2S_BLUESCSI_TOOLBOX_H +#define S2S_BLUESCSI_TOOLBOX_H + +int scsiBlueSCSIToolboxCommand(void); + +#endif diff --git a/lib/SCSI2SD/src/firmware/mode.c b/lib/SCSI2SD/src/firmware/mode.c index 3ccca2af..78c05bf6 100755 --- a/lib/SCSI2SD/src/firmware/mode.c +++ b/lib/SCSI2SD/src/firmware/mode.c @@ -246,6 +246,14 @@ static const uint8_t AppleVendorPage[] = 'A','P','P','L','E',' ','C','O','M','P','U','T','E','R',',',' ','I','N','C',' ',' ',' ' }; +static const uint8_t BlueSCSIVendorPage[] = +{ +0x31, // Page code +42, // Page length +'B','l','u','e','S','C','S','I',' ','i','s',' ','t','h','e',' ','B','E','S','T',' ', +'S','T','O','L','E','N',' ','F','R','O','M',' ','B','L','U','E','S','C','S','I',0x00 +}; + static void pageIn(int pc, int dataIdx, const uint8_t* pageData, int pageLen) { memcpy(&scsiDev.data[dataIdx], pageData, pageLen); @@ -525,6 +533,13 @@ static void doModeSense( idx += sizeof(AppleVendorPage); } + if (pageCode == 0x31 || pageCode == 0x3F) + { + pageFound = 1; + pageIn(pc, idx, BlueSCSIVendorPage, sizeof(BlueSCSIVendorPage)); + idx += sizeof(BlueSCSIVendorPage); + } + if (pageCode == 0x38) // Don't send unless requested { pageFound = 1; diff --git a/lib/SCSI2SD/src/firmware/scsi.c b/lib/SCSI2SD/src/firmware/scsi.c index 2e184fae..e378a81d 100755 --- a/lib/SCSI2SD/src/firmware/scsi.c +++ b/lib/SCSI2SD/src/firmware/scsi.c @@ -30,6 +30,7 @@ #include "tape.h" #include "mo.h" #include "vendor.h" +#include "bluescsi_toolbox.h" #include @@ -587,6 +588,10 @@ static void process_Command() { // Already handled. } + else if (scsiBlueSCSIToolboxCommand()) + { + // handled + } else if (scsiDiskCommand()) { // Already handled. diff --git a/lib/minIni/minGlue.h b/lib/minIni/minGlue.h index d27d2fba..330e8743 100644 --- a/lib/minIni/minGlue.h +++ b/lib/minIni/minGlue.h @@ -2,7 +2,7 @@ #include -#define INI_READONLY 1 +#define INI_OPENREWRITE 1 #define INI_FILETYPE FsFile #define INI_FILEPOS fspos_t @@ -11,3 +11,8 @@ bool ini_close(INI_FILETYPE *fp); bool ini_read(char *buffer, int size, INI_FILETYPE *fp); void ini_tell(INI_FILETYPE *fp, INI_FILEPOS *pos); void ini_seek(INI_FILETYPE *fp, INI_FILEPOS *pos); + +bool ini_write(char *buffer, INI_FILETYPE *fp); +bool ini_openwrite(const char *filename, INI_FILETYPE *fp); +bool ini_openrewrite(const char *filename, INI_FILETYPE *fp); +void ini_rename(const char *new_name, const char *old_name); \ No newline at end of file diff --git a/lib/minIni/minIni.cpp b/lib/minIni/minIni.cpp index a80c5c76..ba1d0140 100644 --- a/lib/minIni/minIni.cpp +++ b/lib/minIni/minIni.cpp @@ -721,7 +721,7 @@ int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const T ini_tell(&rfp, &tail); /* create new buffer (without writing it to file) */ writekey(LocalBuffer, Key, Value, NULL); - if (_tcslen(LocalBuffer) == (size_t)(tail - head)) { + if (_tcslen(LocalBuffer) == (size_t)(tail.position - head.position)) { /* length matches, close the file & re-open for read/write, then * write at the correct position */ diff --git a/lib/minIni/minIni_cache.cpp b/lib/minIni/minIni_cache.cpp index d549e4b3..6057c82d 100644 --- a/lib/minIni/minIni_cache.cpp +++ b/lib/minIni/minIni_cache.cpp @@ -71,6 +71,46 @@ bool ini_openread(const char *filename, INI_FILETYPE *fp) return fp->open(SD.vol(), filename, O_RDONLY); } +// Open .ini file either from cache or from SD card +bool ini_openwrite(const char *filename, INI_FILETYPE *fp) +{ +#if INI_CACHE_SIZE > 0 + if (g_ini_cache.valid && + (filename == g_ini_cache.filename || strcmp(filename, g_ini_cache.filename) == 0)) + { + fp->close(); + g_ini_cache.fp = fp; + g_ini_cache.current_pos.position = 0; + return true; + } +#endif + + return fp->open(SD.vol(), filename, O_WRONLY); +} + +// Open .ini file either from cache or from SD card +bool ini_openrewrite(const char *filename, INI_FILETYPE *fp) +{ +#if INI_CACHE_SIZE > 0 + if (g_ini_cache.valid && + (filename == g_ini_cache.filename || strcmp(filename, g_ini_cache.filename) == 0)) + { + fp->close(); + g_ini_cache.fp = fp; + g_ini_cache.current_pos.position = 0; + return true; + } +#endif + + return fp->open(SD.vol(), filename, O_RDWR); +} + +void ini_rename(const char * old_name, const char *new_name) +{ + SD.rename(old_name, new_name); + invalidate_ini_cache(); +} + // Close previously opened file bool ini_close(INI_FILETYPE *fp) { @@ -116,6 +156,18 @@ bool ini_read(char *buffer, int size, INI_FILETYPE *fp) } } +// Write to the card and invalidate the cache. +bool ini_write(char *buffer, INI_FILETYPE *fp) +{ + if(fp->write(buffer) > 0) + { + invalidate_ini_cache(); + return true; + } + else + return false; +} + // Get the position inside the file void ini_tell(INI_FILETYPE *fp, INI_FILEPOS *pos) { diff --git a/src/BlueSCSI_Toolbox.cpp b/src/BlueSCSI_Toolbox.cpp new file mode 100644 index 00000000..f5f64713 --- /dev/null +++ b/src/BlueSCSI_Toolbox.cpp @@ -0,0 +1,394 @@ +/** + * Copyright (C) 2023 Eric Helgeson + * + * This file is part of BlueSCSI + * + * This program 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. + * + * This program 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 "BlueSCSI_Toolbox.h" +#include "BlueSCSI_disk.h" +#include "BlueSCSI_cdrom.h" +#include "BlueSCSI_log.h" +#include "BlueSCSI_config.h" +#include +#include +extern "C" { +#include +#include +#include +} + +bool toolboxFilenameValid(const char* name) +{ + if(name[0] == '.') + { + debuglog("toolbox: Ignoring hidden file ", name); + return false; + } + if(strlen(name) == 0) + { + debuglog("toolbox: Ignoring filename empty file name"); + return false; + } + const char *extension = strrchr(name, '.'); + if (extension && strcasecmp(extension, ".cue") == 0) + { + debuglog("toolbox: Ignoring .cue ", name); + return false; + } + + return true; +} + +static void doCountFiles(const char * dir_name) +{ + FsFile dir; + FsFile file; + char name[MAX_FILE_PATH] = {0}; + dir.open(dir_name); + dir.rewindDirectory(); + uint8_t file_count = 0; + while (file.openNext(&dir, O_RDONLY)) + { + if(file.getError() > 0) + { + file.close(); + break; + } + file.getName(name, MAX_FILE_PATH); + file.close(); + // only count valid files. + if(toolboxFilenameValid(name)) + { + file_count = file_count + 1; + if(file_count > 100) { + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + scsiDev.target->sense.asc = OPEN_RETRO_SCSI_TOO_MANY_FILES; + scsiDev.phase = STATUS; + dir.close(); + return; + } + } + } + scsiDev.data[0] = file_count; + scsiDev.dataLen = sizeof(file_count); + scsiDev.phase = DATA_IN; +} + +void onListFiles(const char * dir_name) { + FsFile dir; + FsFile file; + + memset(scsiDev.data, 0, 4096); + int ENTRY_SIZE = 40; + char name[MAX_FILE_PATH] = {0}; + dir.open(dir_name); + dir.rewindDirectory(); + uint8_t index = 0; + byte file_entry[40] = {0}; + while (file.openNext(&dir, O_RDONLY)) + { + uint8_t isDir = file.isDirectory() ? 0x00 : 0x01; + int len = file.getName(name, MAX_FILE_PATH); + if (len > MAX_MAC_PATH) + name[MAX_MAC_PATH] = 0x0; + uint64_t size = file.fileSize(); + file.close(); + if(!toolboxFilenameValid(name)) + continue; + file_entry[0] = index; + file_entry[1] = isDir; + int c = 0; // Index of char in name[] + + for(int i = 2; i < (MAX_MAC_PATH + 1 + 2); i++) { // bytes 2 - 34 + file_entry[i] = name[c++]; + } + file_entry[35] = 0; //(size >> 32) & 0xff; + file_entry[36] = (size >> 24) & 0xff; + file_entry[37] = (size >> 16) & 0xff; + file_entry[38] = (size >> 8) & 0xff; + file_entry[39] = (size) & 0xff; + memcpy(&(scsiDev.data[ENTRY_SIZE * index]), file_entry, ENTRY_SIZE); + index = index + 1; + } + dir.close(); + + scsiDev.dataLen = 4096; + scsiDev.phase = DATA_IN; +} + +FsFile get_file_from_index(uint8_t index, const char * dir_name) +{ + FsFile dir; + FsFile file_test; + char name[MAX_FILE_PATH] = {0}; + + dir.open(dir_name); + dir.rewindDirectory(); // Back to the top + int count = 0; + while (file_test.openNext(&dir, O_RDONLY)) + { + // If error there is no next file to open. + if(file_test.getError() > 0) { + file_test.close(); + break; + } + file_test.getName(name, MAX_FILE_PATH); + + if(!toolboxFilenameValid(name)) + { + file_test.close(); + continue; + } + if (count == index) + { + dir.close(); + return file_test; + } + else + { + file_test.close(); + } + count++; + } + file_test.close(); + dir.close(); + return file_test; +} + +// Devices that are active on this SCSI device. +void onListDevices() +{ + for (int i = 0; i < NUM_SCSIID; i++) + { + const S2S_TargetCfg* cfg = s2s_getConfigById(i); + if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED)) + { + scsiDev.data[i] = (int)cfg->deviceType; // 2 == cd + } + else + { + scsiDev.data[i] = 0xFF; // not enabled target. + } + } + scsiDev.dataLen = NUM_SCSIID; +} + +void onSetNextCD(const char * img_dir) +{ + char name[MAX_FILE_PATH] = {0}; + char full_path[MAX_FILE_PATH * 2] = {0}; + uint8_t file_index = scsiDev.cdb[1]; + + image_config_t &img = *(image_config_t*)scsiDev.target->cfg; + FsFile next_cd = get_file_from_index(file_index, img_dir); + next_cd.getName(name, sizeof(name)); + next_cd.close(); + snprintf(full_path, (MAX_FILE_PATH * 2), "%s/%s", img_dir, name); + cdromSwitch(img, full_path); +} + +FsFile gFile; // global so we can keep it open while transfering. +void onGetFile10(char * dir_name) { + uint8_t index = scsiDev.cdb[1]; + + uint32_t offset = ((uint32_t)scsiDev.cdb[2] << 24) | ((uint32_t)scsiDev.cdb[3] << 16) | ((uint32_t)scsiDev.cdb[4] << 8) | scsiDev.cdb[5]; + + if (offset == 0) // first time, open the file. + { + gFile = get_file_from_index(index, dir_name); + if(!gFile.isDirectory() && !gFile.isReadable()) + { + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + //SCSI_ASC_INVALID_FIELD_IN_CDB + scsiDev.phase = STATUS; + return; + } + } + + uint32_t file_total = gFile.size(); + memset(scsiDev.data, 0, 4096); + gFile.seekSet(offset * 4096); + int bytes_read = gFile.read(scsiDev.data, 4096); + if(offset * 4096 >= file_total) // transfer done, close. + { + gFile.close(); + } + scsiDev.dataLen = bytes_read; + scsiDev.phase = DATA_IN; +} + +/* + Prepares a file for receving. The file name is null terminated in the scsi data. +*/ +void onSendFilePrep(char * dir_name) +{ + char file_name[32+1]; + memset(file_name, '\0', 32+1); + scsiEnterPhase(DATA_OUT); + for (int i = 0; i < 32+1; ++i) + { + file_name[i] = scsiReadByte(); + } + SD.chdir(dir_name); + gFile.open(file_name, FILE_WRITE); + SD.chdir("/"); + if(gFile.isOpen() && gFile.isWritable()) + { + gFile.rewind(); + gFile.sync(); + // do i need to manually set phase to status here? + return; + } else { + gFile.close(); + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + //SCSI_ASC_INVALID_FIELD_IN_CDB + scsiDev.phase = STATUS; + } +} + +void onSendFileEnd(void) +{ + gFile.sync(); + gFile.close(); + scsiDev.phase = STATUS; +} + +void onSendFile10(void) +{ + if(!gFile.isOpen() || !gFile.isWritable()) + { + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + //SCSI_ASC_INVALID_FIELD_IN_CDB + scsiDev.phase = STATUS; + } + + // Number of bytes sent this request, 1..512. + uint16_t bytes_sent = ((uint16_t)scsiDev.cdb[1] << 8) | scsiDev.cdb[2]; + // 512 byte offset of where to put these bytes. + uint32_t offset = ((uint32_t)scsiDev.cdb[3] << 16) | ((uint32_t)scsiDev.cdb[4] << 8) | scsiDev.cdb[5]; + uint16_t buf_size = 512; + uint8_t buf[512]; + + // Check if last block of file, and not the only bock in file. + if(bytes_sent < buf_size) + { + buf_size = bytes_sent; + } + + scsiEnterPhase(DATA_OUT); + scsiRead(buf, bytes_sent, NULL); + gFile.seekCur(offset * 512); + gFile.write(buf, buf_size); + if(gFile.getWriteError()) + { + gFile.clearWriteError(); + gFile.close(); + scsiDev.status = CHECK_CONDITION; + scsiDev.target->sense.code = ILLEGAL_REQUEST; + } + //scsiDev.phase = STATUS; +} +void onToggleDebug() +{ + if(scsiDev.cdb[1] == 0) // 0 == Set Debug, 1 == Get Debug State + { + g_log_debug = scsiDev.cdb[2]; + log("Set debug logs to: ", g_log_debug); + scsiDev.phase = STATUS; + } + else + { + log("Debug currently set to: ", g_log_debug); + scsiDev.data[0] = g_log_debug ? 0x1 : 0x0; + scsiDev.dataLen = 1; + scsiDev.phase = DATA_IN; + } +} + +extern "C" int scsiBlueSCSIToolboxCommand() +{ + int commandHandled = 1; + image_config_t &img = *(image_config_t*)scsiDev.target->cfg; + uint8_t command = scsiDev.cdb[0]; + + if (unlikely(command == BLUESCSI_TOOLBOX_COUNT_FILES)) + { + char img_dir[MAX_FILE_PATH]; + getToolBoxSharedDir(img_dir); + doCountFiles(img_dir); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_LIST_FILES)) + { + char img_dir[MAX_FILE_PATH]; + getToolBoxSharedDir(img_dir); + onListFiles(img_dir); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_GET_FILE)) + { + char img_dir[MAX_FILE_PATH]; + getToolBoxSharedDir(img_dir); + onGetFile10(img_dir); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_SEND_FILE_PREP)) + { + char img_dir[MAX_FILE_PATH]; + getToolBoxSharedDir(img_dir); + onSendFilePrep(img_dir); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_SEND_FILE_10)) + { + onSendFile10(); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_SEND_FILE_END)) + { + onSendFileEnd(); + } + else if(unlikely(command == BLUESCSI_TOOLBOX_TOGGLE_DEBUG)) + { + onToggleDebug(); + } + else if(unlikely(command == BLUESCSI_TOOLBOX_LIST_CDS)) + { + char img_dir[4]; + snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS); + onListFiles(img_dir); + } + else if(unlikely(command == BLUESCSI_TOOLBOX_SET_NEXT_CD)) + { + char img_dir[4]; + snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS); + onSetNextCD(img_dir); + } + else if(unlikely(command == BLUESCSI_TOOLBOX_LIST_DEVICES)) + { + onListDevices(); + } + else if (unlikely(command == BLUESCSI_TOOLBOX_COUNT_CDS)) + { + char img_dir[4]; + snprintf(img_dir, sizeof(img_dir), CD_IMG_DIR, (int)img.scsiId & S2S_CFG_TARGET_ID_BITS); + doCountFiles(img_dir); + } + else + { + commandHandled = 0; + } + + return commandHandled; +} \ No newline at end of file diff --git a/src/BlueSCSI_Toolbox.h b/src/BlueSCSI_Toolbox.h new file mode 100644 index 00000000..a708f9da --- /dev/null +++ b/src/BlueSCSI_Toolbox.h @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2023 Eric Helgeson + * + * This file is part of BlueSCSI + * + * This program 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. + * + * This program 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 . +**/ + +#pragma once + +#define MAX_MAC_PATH 32 +#define CD_IMG_DIR "CD%d" + +#define BLUESCSI_TOOLBOX_COUNT_FILES 0xD2 +#define BLUESCSI_TOOLBOX_LIST_FILES 0xD0 +#define BLUESCSI_TOOLBOX_GET_FILE 0xD1 +#define BLUESCSI_TOOLBOX_SEND_FILE_PREP 0xD3 +#define BLUESCSI_TOOLBOX_SEND_FILE_10 0xD4 +#define BLUESCSI_TOOLBOX_SEND_FILE_END 0xD5 +#define BLUESCSI_TOOLBOX_TOGGLE_DEBUG 0xD6 +#define BLUESCSI_TOOLBOX_LIST_CDS 0xD7 +#define BLUESCSI_TOOLBOX_SET_NEXT_CD 0xD8 +#define BLUESCSI_TOOLBOX_LIST_DEVICES 0xD9 +#define BLUESCSI_TOOLBOX_COUNT_CDS 0xDA +#define OPEN_RETRO_SCSI_TOO_MANY_FILES 0x0001 \ No newline at end of file diff --git a/src/BlueSCSI_cdrom.cpp b/src/BlueSCSI_cdrom.cpp index 69c332f2..b0cf40f2 100644 --- a/src/BlueSCSI_cdrom.cpp +++ b/src/BlueSCSI_cdrom.cpp @@ -1216,25 +1216,57 @@ bool cdromSwitchNextImage(image_config_t &img) int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS; scsiDiskGetNextImageName(img, filename, sizeof(filename)); + if (filename[0] != '\0') + { #ifdef ENABLE_AUDIO_OUTPUT // if in progress for this device, terminate audio playback immediately (Annex C) audio_stop(target_idx); // Reset position tracking for the new image audio_get_status_code(target_idx); // trash audio status code #endif + log("Switching to next CD-ROM image for ", target_idx, ": ", filename); + img.file.close(); + bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, + getBlockSize(filename, target_idx, 2048)); + + if (status) + { + return true; + } + } + + return false; +} + +// Check if we have multiple CD-ROM images to cycle when drive is ejected. +bool cdromSwitch(image_config_t &img, const char* filename) +{ + // Check if we have a next image to load, so that drive is closed next time the host asks. + int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS; if (filename[0] != '\0') { - log("Switching to next CD-ROM image for SCSI ID: ", target_idx, ": ", filename); +#ifdef ENABLE_AUDIO_OUTPUT + // if in progress for this device, terminate audio playback immediately (Annex C) + audio_stop(target_idx); + // Reset position tracking for the new image + audio_get_status_code(target_idx); // trash audio status code +#endif + log("Switching to next CD-ROM image for ", target_idx, ": ", filename); img.file.close(); - bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, - getBlockSize(filename, target_idx, 2048)); + bool status = scsiDiskOpenHDDImage(target_idx, filename, target_idx, 0, 2048); if (status) { + img.ejected = false; + img.cdrom_events = 2; // New media return true; } } + else + { + log("Could not switch to CD-ROM image as provide filename was empty."); + } return false; } diff --git a/src/BlueSCSI_cdrom.h b/src/BlueSCSI_cdrom.h index 95499152..1d14711b 100644 --- a/src/BlueSCSI_cdrom.h +++ b/src/BlueSCSI_cdrom.h @@ -31,4 +31,7 @@ bool cdromValidateCueSheet(image_config_t &img); // Audio playback status // boolean flag is true if just basic mechanism status (playback true/false) // is desired, or false if historical audio status codes should be returned -void cdromGetAudioPlaybackStatus(uint8_t *status, uint32_t *current_lba, bool current_only); \ No newline at end of file +void cdromGetAudioPlaybackStatus(uint8_t *status, uint32_t *current_lba, bool current_only); + +// switch to a given filename for the cd. +bool cdromSwitch(image_config_t &img, const char* filename); \ No newline at end of file diff --git a/src/BlueSCSI_config.cpp b/src/BlueSCSI_config.cpp index bb7207a7..5853c577 100644 --- a/src/BlueSCSI_config.cpp +++ b/src/BlueSCSI_config.cpp @@ -61,4 +61,9 @@ int getImg(int scsiId, int img_index, char* filename) int dirlen = ini_gets(section, key, "", filename, sizeof(filename), CONFIGFILE); return dirlen; +} + +int getToolBoxSharedDir(char * dir_name) +{ + return ini_gets("SCSI", "ToolBoxSharedDir", "/shared", dir_name, MAX_FILE_PATH, CONFIGFILE); } \ No newline at end of file diff --git a/src/BlueSCSI_config.h b/src/BlueSCSI_config.h index 01de02c2..d4b8f91c 100644 --- a/src/BlueSCSI_config.h +++ b/src/BlueSCSI_config.h @@ -84,4 +84,6 @@ int getBlockSize(char *filename, int scsiId, int default_size); int getImgDir(int scsiId, char* dirname); -int getImg(int scsiId, int img_index, char* filename); \ No newline at end of file +int getImg(int scsiId, int img_index, char* filename); + +int getToolBoxSharedDir(char * dir_name); \ No newline at end of file diff --git a/src/BlueSCSI_disk.cpp b/src/BlueSCSI_disk.cpp index e59313f9..9708be35 100644 --- a/src/BlueSCSI_disk.cpp +++ b/src/BlueSCSI_disk.cpp @@ -506,7 +506,7 @@ bool scsiDiskFilenameValid(const char* name) { if (strcasecmp(extension, ignore_exts[i]) == 0) { - // ignore these without log message + debuglog("-- Ignoring file ", name); return false; } } diff --git a/src/BlueSCSI_log_trace.cpp b/src/BlueSCSI_log_trace.cpp index 81a80e86..67df5da6 100644 --- a/src/BlueSCSI_log_trace.cpp +++ b/src/BlueSCSI_log_trace.cpp @@ -3,6 +3,7 @@ #include "BlueSCSI_log_trace.h" #include "BlueSCSI_log.h" #include +#include "BlueSCSI_Toolbox.h" extern "C" { #include @@ -78,6 +79,17 @@ static const char *getCommandName(uint8_t cmd) case 0xA8: return "Read12"; case 0xC0: return "OMTI-5204 DefineFlexibleDiskFormat"; case 0xC2: return "OMTI-5204 AssignDiskParameters"; + case BLUESCSI_TOOLBOX_COUNT_FILES: return "BLUESCSI_TOOLBOX_COUNT_FILES"; + case BLUESCSI_TOOLBOX_LIST_FILES: return "BLUESCSI_TOOLBOX_LIST_FILES"; + case BLUESCSI_TOOLBOX_GET_FILE: return "BLUESCSI_TOOLBOX_GET_FILE"; + case BLUESCSI_TOOLBOX_SEND_FILE_PREP: return "BLUESCSI_TOOLBOX_SEND_FILE_PREP"; + case BLUESCSI_TOOLBOX_SEND_FILE_10: return "BLUESCSI_TOOLBOX_SEND_FILE_10"; + case BLUESCSI_TOOLBOX_SEND_FILE_END: return "BLUESCSI_TOOLBOX_SEND_FILE_END"; + case BLUESCSI_TOOLBOX_TOGGLE_DEBUG: return "BLUESCSI_TOOLBOX_TOGGLE_DEBUG"; + case BLUESCSI_TOOLBOX_LIST_CDS: return "BLUESCSI_TOOLBOX_LIST_CDS"; + case BLUESCSI_TOOLBOX_SET_NEXT_CD: return "BLUESCSI_TOOLBOX_SET_NEXT_CD"; + case BLUESCSI_TOOLBOX_LIST_DEVICES: return "BLUESCSI_TOOLBOX_LIST_DEVICES"; + case BLUESCSI_TOOLBOX_COUNT_CDS: return "BLUESCSI_TOOLBOX_COUNT_CDS"; default: return "Unknown"; } } diff --git a/src/ImageBackingStore.cpp b/src/ImageBackingStore.cpp index 02095b16..4ac2041c 100644 --- a/src/ImageBackingStore.cpp +++ b/src/ImageBackingStore.cpp @@ -304,6 +304,16 @@ void ImageBackingStore::flush() } } +void ImageBackingStore::getName(char * name, size_t len) +{ + if(m_isrom) + name = (char*)"ROM:"; + else if(m_israw) + name = (char*)"RAW:"; + else + m_fsfile.getName(name, len); +} + uint64_t ImageBackingStore::position() { if (!m_israw && !m_isrom) diff --git a/src/ImageBackingStore.h b/src/ImageBackingStore.h index 6724c7cb..41572992 100644 --- a/src/ImageBackingStore.h +++ b/src/ImageBackingStore.h @@ -74,6 +74,9 @@ class ImageBackingStore // Flush any pending changes to filesystem void flush(); + // Get name of the fs_file + void getName(char *name, size_t len); + // Gets current position for following read/write operations // Result is only valid for regular files, not raw or flash access uint64_t position();