64dd from sd card working

This commit is contained in:
Polprzewodnikowy 2022-09-15 19:42:46 +02:00
parent 60592dca3a
commit f701df4fbb
13 changed files with 220 additions and 50 deletions

View File

@ -34,7 +34,7 @@
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define FF_USE_FASTSEEK 1 #define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */ /* This option switches fast seek function. (0:Disable or 1:Enable) */
@ -224,7 +224,7 @@
/ System Configurations / System Configurations
/---------------------------------------------------------------------------*/ /---------------------------------------------------------------------------*/
#define FF_FS_TINY 0 #define FF_FS_TINY 1
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. / At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector / Instead of private sector buffer eliminated from the file object, common sector

View File

@ -19,6 +19,7 @@ typedef enum {
SC64_CMD_SD_SECTOR_SET = 'I', SC64_CMD_SD_SECTOR_SET = 'I',
SC64_CMD_SD_WRITE = 'S', SC64_CMD_SD_WRITE = 'S',
SC64_CMD_SD_READ = 's', SC64_CMD_SD_READ = 's',
SC64_CMD_DD_SD_DISK_INFO = 'D',
} cmd_id_t; } cmd_id_t;
typedef enum { typedef enum {
@ -199,3 +200,11 @@ bool sc64_sd_read_sectors (uint32_t *address, uint32_t sector, uint32_t count) {
} }
return sc64_execute_cmd(SC64_CMD_SD_READ, read_args, NULL); return sc64_execute_cmd(SC64_CMD_SD_READ, read_args, NULL);
} }
bool sc64_dd_set_sd_disk_info (uint32_t *address, uint32_t count) {
uint32_t args[2] = { (uint32_t) (address), count };
if (sc64_execute_cmd(SC64_CMD_DD_SD_DISK_INFO, args, NULL)) {
return true;
}
return false;
}

View File

@ -29,6 +29,8 @@ typedef enum {
CFG_ID_DD_DISK_STATE, CFG_ID_DD_DISK_STATE,
CFG_ID_BUTTON_STATE, CFG_ID_BUTTON_STATE,
CFG_ID_BUTTON_MODE, CFG_ID_BUTTON_MODE,
CFG_ID_ROM_EXTENDED_ENABLE,
CFG_ID_DD_SD_MODE,
} cfg_id_t; } cfg_id_t;
typedef enum { typedef enum {
@ -109,6 +111,7 @@ bool sc64_sd_card_get_status (void);
bool sc64_sd_card_get_info (uint32_t *address); bool sc64_sd_card_get_info (uint32_t *address);
bool sc64_sd_write_sectors (uint32_t *address, uint32_t sector, uint32_t count); bool sc64_sd_write_sectors (uint32_t *address, uint32_t sector, uint32_t count);
bool sc64_sd_read_sectors (uint32_t *address, uint32_t sector, uint32_t count); bool sc64_sd_read_sectors (uint32_t *address, uint32_t sector, uint32_t count);
bool sc64_dd_set_sd_disk_info (uint32_t *address, uint32_t count);
#endif #endif

View File

@ -13,6 +13,8 @@ bool test_check (void) {
} }
void test_execute (void) { void test_execute (void) {
uint8_t card_info[32] __attribute__((aligned(8)));
display_init(NULL); display_init(NULL);
display_printf("SC64 Test suite\n\n"); display_printf("SC64 Test suite\n\n");
@ -27,18 +29,25 @@ void test_execute (void) {
while (1); while (1);
} }
uint8_t card_info[32] __attribute__((aligned(8)));
pi_dma_read((io32_t *) (SC64_BUFFERS->BUFFER), card_info, sizeof(card_info)); pi_dma_read((io32_t *) (SC64_BUFFERS->BUFFER), card_info, sizeof(card_info));
display_printf("CSD: 0x"); display_printf("SD Card registers:\n CSD: 0x");
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
display_printf("%02X", card_info[i]); display_printf("%02X", card_info[i]);
} }
display_printf("\nCID: 0x"); display_printf("\n CID: 0x");
for (int i = 16; i < 32; i++) { for (int i = 16; i < 32; i++) {
display_printf("%02X", card_info[i]); display_printf("%02X", card_info[i]);
} }
display_printf("\n ");
for (int i = 16; i < 32; i++) {
display_printf("%c ", card_info[i] >= ' ' ? card_info[i] : 0xFF);
}
if (sc64_sd_card_deinit()) {
display_printf("SD card deinit error!\n");
while (1);
}
while (1); while (1);
} }

View File

@ -1,5 +1,6 @@
#include <stdint.h> #include <stdint.h>
#include "button.h" #include "button.h"
#include "dd.h"
#include "fpga.h" #include "fpga.h"
#include "usb.h" #include "usb.h"
@ -66,7 +67,7 @@ void button_process (void) {
break; break;
case BUTTON_MODE_DD_DISK_SWAP: case BUTTON_MODE_DD_DISK_SWAP:
// TODO: implement 64DD disk swapping dd_handle_button();
p.trigger = false; p.trigger = false;
break; break;

View File

@ -25,6 +25,7 @@ typedef enum {
CFG_ID_BUTTON_STATE, CFG_ID_BUTTON_STATE,
CFG_ID_BUTTON_MODE, CFG_ID_BUTTON_MODE,
CFG_ID_ROM_EXTENDED_ENABLE, CFG_ID_ROM_EXTENDED_ENABLE,
CFG_ID_DD_SD_MODE,
} cfg_id_t; } cfg_id_t;
typedef enum { typedef enum {
@ -106,6 +107,12 @@ static bool cfg_translate_address (uint32_t *address, uint32_t length, bool with
return false; return false;
} }
} }
if (*address >= 0x1FFE2000 && *address < 0x1FFE2800) {
if ((*address + length) <= 0x1FFE2800) {
*address = *address - 0x1FFE2000 + 0x05002000;
return false;
}
}
return true; return true;
} }
@ -220,6 +227,9 @@ bool cfg_query (uint32_t *args) {
case CFG_ID_ROM_EXTENDED_ENABLE: case CFG_ID_ROM_EXTENDED_ENABLE:
args[1] = (scr & CFG_SCR_ROM_EXTENDED_ENABLED); args[1] = (scr & CFG_SCR_ROM_EXTENDED_ENABLED);
break; break;
case CFG_ID_DD_SD_MODE:
args[1] = dd_get_sd_mode();
break;
default: default:
return true; return true;
} }
@ -285,6 +295,9 @@ bool cfg_update (uint32_t *args) {
case CFG_ID_ROM_EXTENDED_ENABLE: case CFG_ID_ROM_EXTENDED_ENABLE:
cfg_change_scr_bits(CFG_SCR_ROM_EXTENDED_ENABLED, args[1]); cfg_change_scr_bits(CFG_SCR_ROM_EXTENDED_ENABLED, args[1]);
break; break;
case CFG_ID_DD_SD_MODE:
dd_set_sd_mode(args[1]);
break;
default: default:
return true; return true;
} }
@ -457,6 +470,14 @@ void cfg_process (void) {
return; return;
} }
break; break;
case 'D':
if (cfg_translate_address(&args[0], args[1], false)) {
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
return;
}
dd_set_sd_disk_info(args[0], args[1]);
break;
default: default:
cfg_set_error(CFG_ERROR_UNKNOWN_CMD); cfg_set_error(CFG_ERROR_UNKNOWN_CMD);

View File

@ -3,13 +3,17 @@
#include "fpga.h" #include "fpga.h"
#include "hw.h" #include "hw.h"
#include "rtc.h" #include "rtc.h"
#include "sd.h"
#include "usb.h" #include "usb.h"
#define DD_SECTOR_MAX_SIZE (232) #define DD_SECTOR_MAX_SIZE (232)
#define DD_BLOCK_DATA_SECTORS_NUM (85) #define DD_BLOCK_DATA_SECTORS_NUM (85)
#define DD_BLOCK_BUFFER_ADDRESS (0x03BC0000UL - (DD_SECTOR_MAX_SIZE * DD_BLOCK_DATA_SECTORS_NUM)) #define DD_BLOCK_BUFFER_SIZE (ALIGN(DD_SECTOR_MAX_SIZE * DD_BLOCK_DATA_SECTORS_NUM, SD_SECTOR_SIZE) + SD_SECTOR_SIZE)
#define DD_BLOCK_BUFFER_ADDRESS (0x03BC0000UL - DD_BLOCK_BUFFER_SIZE)
#define DD_SECTOR_BUFFER_ADDRESS (0x05002800UL) #define DD_SECTOR_BUFFER_ADDRESS (0x05002800UL)
#define DD_SD_SECTOR_TABLE_SIZE (DD_BLOCK_BUFFER_SIZE / SD_SECTOR_SIZE)
#define DD_SD_MAX_DISKS (4)
#define DD_DRIVE_ID_RETAIL (0x0003) #define DD_DRIVE_ID_RETAIL (0x0003)
#define DD_DRIVE_ID_DEVELOPMENT (0x0004) #define DD_DRIVE_ID_DEVELOPMENT (0x0004)
@ -47,8 +51,7 @@ enum state {
STATE_NEXT_BLOCK, STATE_NEXT_BLOCK,
}; };
typedef union {
typedef union sector_info {
uint32_t full; uint32_t full;
struct { struct {
uint8_t sector_num; uint8_t sector_num;
@ -58,6 +61,11 @@ typedef union sector_info {
}; };
} sector_info_t; } sector_info_t;
typedef struct {
uint32_t thb_table_address;
uint32_t sector_table_address;
} sd_disk_info_t;
struct process { struct process {
enum state state; enum state state;
rtc_time_t time; rtc_time_t time;
@ -73,7 +81,12 @@ struct process {
sector_info_t sector_info; sector_info_t sector_info;
bool block_ready; bool block_ready;
bool block_valid; bool block_valid;
uint32_t block_offset;
dd_drive_type_t drive_type; dd_drive_type_t drive_type;
bool sd_mode;
uint8_t sd_current_disk;
sd_disk_info_t sd_disk_info[DD_SD_MAX_DISKS];
uint32_t sd_sector_table[DD_SD_SECTOR_TABLE_SIZE];
}; };
@ -87,28 +100,88 @@ static uint16_t dd_track_head_block (void) {
return (track | head | block); return (track | head | block);
} }
static uint32_t dd_fill_sd_sector_table (uint32_t index) {
uint32_t tmp;
sd_disk_info_t info = p.sd_disk_info[p.sd_current_disk];
uint32_t thb_entry_address = (info.thb_table_address + (index * sizeof(uint32_t)));
fpga_mem_read(thb_entry_address, sizeof(uint32_t), (uint8_t *) (&tmp));
uint32_t start_offset = SWAP32(tmp);
if (start_offset == 0xFFFFFFFF) {
return 0;
}
p.block_offset = (start_offset % SD_SECTOR_SIZE);
uint32_t block_length = ((p.sector_info.sector_size + 1) * DD_BLOCK_DATA_SECTORS_NUM);
uint32_t end_offset = ((start_offset + block_length) - 1); // CHECK THIS
uint32_t starting_sector = (start_offset / SD_SECTOR_SIZE);
uint32_t sectors = (1 + ((end_offset / SD_SECTOR_SIZE) - starting_sector));
for (int i = 0; i < sectors; i++) {
uint32_t sector_entry_address = info.sector_table_address + ((starting_sector + i) * sizeof(uint32_t));
fpga_mem_read(sector_entry_address, sizeof(uint32_t), (uint8_t *) (&tmp));
p.sd_sector_table[i] = SWAP32(tmp);
}
return sectors;
}
static bool dd_block_read_request (void) { static bool dd_block_read_request (void) {
usb_tx_info_t packet_info; uint16_t index = dd_track_head_block();
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST); uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS;
packet_info.data_length = 12;
packet_info.data[0] = 1; if (p.sd_mode) {
packet_info.data[1] = DD_BLOCK_BUFFER_ADDRESS; dd_set_block_ready(false);
packet_info.data[2] = dd_track_head_block(); uint32_t sectors = dd_fill_sd_sector_table(index);
p.block_ready = false; if (sectors > 0) {
return usb_enqueue_packet(&packet_info); for (int i = 0; i < sectors; i++) {
if (sd_read_sectors(buffer_address, p.sd_sector_table[i], 1)) {
return true;
}
buffer_address += SD_SECTOR_SIZE;
}
dd_set_block_ready(true);
}
return true;
} else {
usb_tx_info_t packet_info;
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST);
packet_info.data_length = 12;
packet_info.data[0] = 1;
packet_info.data[1] = buffer_address;
packet_info.data[2] = index;
p.block_ready = false;
p.block_offset = 0;
return usb_enqueue_packet(&packet_info);
}
} }
static bool dd_block_write_request (void) { static bool dd_block_write_request (void) {
usb_tx_info_t packet_info; uint32_t index = dd_track_head_block();
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST); uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS;
packet_info.data_length = 12;
packet_info.data[0] = 2; if (p.sd_mode) {
packet_info.data[1] = DD_BLOCK_BUFFER_ADDRESS; dd_set_block_ready(false);
packet_info.data[2] = dd_track_head_block(); uint32_t sectors = dd_fill_sd_sector_table(index);
packet_info.dma_length = (p.sector_info.sector_size + 1) * DD_BLOCK_DATA_SECTORS_NUM; if (sectors > 0) {
packet_info.dma_address = DD_BLOCK_BUFFER_ADDRESS; for (int i = 0; i < sectors; i++) {
p.block_ready = false; if (sd_write_sectors(buffer_address, p.sd_sector_table[i], 1)) {
return usb_enqueue_packet(&packet_info); return true;
}
buffer_address += SD_SECTOR_SIZE;
}
dd_set_block_ready(true);
}
return true;
} else {
usb_tx_info_t packet_info;
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST);
packet_info.data_length = 12;
packet_info.data[0] = 2;
packet_info.data[1] = buffer_address;
packet_info.data[2] = index;
packet_info.dma_length = (p.sector_info.sector_size + 1) * DD_BLOCK_DATA_SECTORS_NUM;
packet_info.dma_address = buffer_address;
p.block_ready = false;
p.block_offset = 0;
return usb_enqueue_packet(&packet_info);
}
} }
static void dd_set_cmd_response_ready (void) { static void dd_set_cmd_response_ready (void) {
@ -168,6 +241,29 @@ void dd_set_disk_state (dd_disk_state_t state) {
fpga_reg_set(REG_DD_SCR, scr); fpga_reg_set(REG_DD_SCR, scr);
} }
bool dd_get_sd_mode (void) {
return p.sd_mode;
}
void dd_set_sd_mode (bool value) {
p.sd_mode = value;
}
void dd_set_sd_disk_info (uint32_t address, uint32_t length) {
uint32_t tmp[2];
p.sd_current_disk = 0;
for (int i = 0; i < 4; i++) {
fpga_mem_read(address, sizeof(tmp), (uint8_t *) (tmp));
p.sd_disk_info[i].thb_table_address = SWAP32(tmp[0]);
p.sd_disk_info[i].sector_table_address = SWAP32(tmp[1]);
address += sizeof(tmp);
}
}
void dd_handle_button (void) {
// TODO: disk swap
}
void dd_init (void) { void dd_init (void) {
fpga_reg_set(REG_DD_SCR, 0); fpga_reg_set(REG_DD_SCR, 0);
fpga_reg_set(REG_DD_HEAD_TRACK, 0); fpga_reg_set(REG_DD_HEAD_TRACK, 0);
@ -178,6 +274,8 @@ void dd_init (void) {
p.disk_spinning = false; p.disk_spinning = false;
p.bm_running = false; p.bm_running = false;
p.drive_type = DD_DRIVE_TYPE_RETAIL; p.drive_type = DD_DRIVE_TYPE_RETAIL;
p.sd_mode = false;
p.sd_current_disk = 0;
} }
void dd_process (void) { void dd_process (void) {
@ -365,7 +463,7 @@ void dd_process (void) {
case STATE_SECTOR_READ: case STATE_SECTOR_READ:
fpga_mem_copy( fpga_mem_copy(
DD_BLOCK_BUFFER_ADDRESS + (p.current_sector * (p.sector_info.sector_size + 1)), DD_BLOCK_BUFFER_ADDRESS + p.block_offset + (p.current_sector * (p.sector_info.sector_size + 1)),
DD_SECTOR_BUFFER_ADDRESS, DD_SECTOR_BUFFER_ADDRESS,
p.sector_info.sector_size + 1 p.sector_info.sector_size + 1
); );
@ -377,7 +475,7 @@ void dd_process (void) {
case STATE_SECTOR_WRITE: case STATE_SECTOR_WRITE:
fpga_mem_copy( fpga_mem_copy(
DD_SECTOR_BUFFER_ADDRESS, DD_SECTOR_BUFFER_ADDRESS,
DD_BLOCK_BUFFER_ADDRESS + (p.current_sector * (p.sector_info.sector_size + 1)), DD_BLOCK_BUFFER_ADDRESS + p.block_offset + (p.current_sector * (p.sector_info.sector_size + 1)),
p.sector_info.sector_size + 1 p.sector_info.sector_size + 1
); );
p.current_sector += 1; p.current_sector += 1;

View File

@ -17,11 +17,15 @@ typedef enum {
} dd_disk_state_t; } dd_disk_state_t;
void dd_set_block_ready (bool valid);
dd_drive_type_t dd_get_drive_type (void); dd_drive_type_t dd_get_drive_type (void);
void dd_set_drive_type (dd_drive_type_t type); void dd_set_drive_type (dd_drive_type_t type);
dd_disk_state_t dd_get_disk_state (void); dd_disk_state_t dd_get_disk_state (void);
void dd_set_disk_state (dd_disk_state_t state); void dd_set_disk_state (dd_disk_state_t state);
void dd_set_block_ready (bool valid); bool dd_get_sd_mode (void);
void dd_set_sd_mode (bool value);
void dd_set_sd_disk_info (uint32_t address, uint32_t length);
void dd_handle_button (void);
void dd_init (void); void dd_init (void);
void dd_process (void); void dd_process (void);

View File

@ -55,6 +55,7 @@ typedef enum {
} fpga_reg_t; } fpga_reg_t;
#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1))
#define SWAP16(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8)) #define SWAP16(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8))
#define SWAP32(x) (((x) & 0xFF) << 24 | ((x) & 0xFF00) << 8 | ((x) & 0xFF0000) >> 8 | ((x) & 0xFF000000) >> 24) #define SWAP32(x) (((x) & 0xFF) << 24 | ((x) & 0xFF00) << 8 | ((x) & 0xFF0000) >> 8 | ((x) & 0xFF000000) >> 24)

View File

@ -6,7 +6,7 @@
#include "sd.h" #include "sd.h"
#define SD_BUFFER_ADDRESS (0x05000000UL) #define SD_INIT_BUFFER_ADDRESS (0x05002800UL)
#define CMD6_ARG_CHECK_HS (0x00FFFFF1UL) #define CMD6_ARG_CHECK_HS (0x00FFFFF1UL)
#define CMD6_ARG_SWITCH_HS (0x80FFFFF1UL) #define CMD6_ARG_SWITCH_HS (0x80FFFFF1UL)
@ -28,7 +28,10 @@
#define R7_SUPPLY_VOLTAGE_27_36_V (1 << 8) #define R7_SUPPLY_VOLTAGE_27_36_V (1 << 8)
#define R7_CHECK_PATTERN (0xAA << 0) #define R7_CHECK_PATTERN (0xAA << 0)
#define SD_BLOCK_SIZE (512) #define SWITCH_FUNCTION_CURRENT_LIMIT (SD_INIT_BUFFER_ADDRESS + 0)
#define SWITCH_FUNCTION_GROUP_1 (SD_INIT_BUFFER_ADDRESS + 12)
#define SWITCH_FUNCTION_GROUP_1_HS (1 << 1)
#define DAT_BLOCK_MAX_COUNT (256) #define DAT_BLOCK_MAX_COUNT (256)
@ -166,7 +169,7 @@ static bool sd_acmd (uint8_t acmd, uint32_t arg, rsp_type_t rsp_type, void *rsp)
} }
static void sd_dat_prepare (uint32_t address, uint32_t count, dat_mode_t mode) { static void sd_dat_prepare (uint32_t address, uint32_t count, dat_mode_t mode) {
uint32_t length = (count * SD_BLOCK_SIZE); uint32_t length = (count * SD_SECTOR_SIZE);
uint32_t sd_dat = (((count - 1) << SD_DAT_BLOCKS_BIT) | SD_DAT_FIFO_FLUSH); uint32_t sd_dat = (((count - 1) << SD_DAT_BLOCKS_BIT) | SD_DAT_FIFO_FLUSH);
uint32_t sd_dma_scr = DMA_SCR_START; uint32_t sd_dma_scr = DMA_SCR_START;
@ -209,7 +212,7 @@ static bool sd_dat_wait (uint16_t timeout) {
bool sd_card_init (void) { bool sd_card_init (void) {
uint32_t arg; uint32_t arg;
uint32_t rsp; uint32_t rsp;
uint16_t sd_function; uint16_t tmp;
if (p.card_initialized) { if (p.card_initialized) {
return false; return false;
@ -289,7 +292,7 @@ bool sd_card_init (void) {
return true; return true;
} }
sd_dat_prepare(SD_BUFFER_ADDRESS, 1, DAT_READ); sd_dat_prepare(SD_INIT_BUFFER_ADDRESS, 1, DAT_READ);
if (sd_cmd(6, CMD6_ARG_CHECK_HS, RSP_R1, NULL)) { if (sd_cmd(6, CMD6_ARG_CHECK_HS, RSP_R1, NULL)) {
sd_dat_abort(); sd_dat_abort();
sd_card_deinit(); sd_card_deinit();
@ -300,9 +303,14 @@ bool sd_card_init (void) {
sd_card_deinit(); sd_card_deinit();
return true; return true;
} }
fpga_mem_read(SD_BUFFER_ADDRESS + 12, 2, (uint8_t *) (&sd_function)); fpga_mem_read(SWITCH_FUNCTION_CURRENT_LIMIT, 2, (uint8_t *) (&tmp));
if (SWAP16(sd_function) & (1 << 1)) { if (SWAP16(tmp) == 0) {
sd_dat_prepare(SD_BUFFER_ADDRESS, 1, DAT_READ); sd_card_deinit();
return true;
}
fpga_mem_read(SWITCH_FUNCTION_GROUP_1, 2, (uint8_t *) (&tmp));
if (SWAP16(tmp) & SWITCH_FUNCTION_GROUP_1_HS) {
sd_dat_prepare(SD_INIT_BUFFER_ADDRESS, 1, DAT_READ);
if (sd_cmd(6, CMD6_ARG_SWITCH_HS, RSP_R1, NULL)) { if (sd_cmd(6, CMD6_ARG_SWITCH_HS, RSP_R1, NULL)) {
sd_dat_abort(); sd_dat_abort();
sd_card_deinit(); sd_card_deinit();
@ -313,8 +321,8 @@ bool sd_card_init (void) {
sd_card_deinit(); sd_card_deinit();
return true; return true;
} }
fpga_mem_read(SD_BUFFER_ADDRESS + 12, 2, (uint8_t *) (&sd_function)); fpga_mem_read(SWITCH_FUNCTION_GROUP_1, 2, (uint8_t *) (&tmp));
if (SWAP16(sd_function) & (1 << 1)) { if (SWAP16(tmp) & SWITCH_FUNCTION_GROUP_1_HS) {
sd_set_clock(CLOCK_50MHZ); sd_set_clock(CLOCK_50MHZ);
} }
} }
@ -352,7 +360,7 @@ bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
} }
if (!p.card_type_block) { if (!p.card_type_block) {
sector *= SD_BLOCK_SIZE; sector *= SD_SECTOR_SIZE;
} }
while (count > 0) { while (count > 0) {
@ -365,14 +373,14 @@ bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
return true; return true;
} }
sd_dat_prepare(address, blocks, DAT_WRITE); sd_dat_prepare(address, blocks, DAT_WRITE);
bool error = sd_dat_wait(1000); if (sd_dat_wait(1000)) {
sd_cmd(12, 0, RSP_R1b, NULL);
if (error) {
sd_dat_abort(); sd_dat_abort();
sd_cmd(12, 0, RSP_R1b, NULL);
return true; return true;
} }
address += (blocks * SD_BLOCK_SIZE); sd_cmd(12, 0, RSP_R1b, NULL);
sector += (blocks * (p.card_type_block ? 1 : SD_BLOCK_SIZE)); address += (blocks * SD_SECTOR_SIZE);
sector += (blocks * (p.card_type_block ? 1 : SD_SECTOR_SIZE));
count -= blocks; count -= blocks;
} }
@ -385,7 +393,7 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
} }
if (!p.card_type_block) { if (!p.card_type_block) {
sector *= SD_BLOCK_SIZE; sector *= SD_SECTOR_SIZE;
} }
while (count > 0) { while (count > 0) {
@ -406,8 +414,8 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
} }
return true; return true;
} }
address += (blocks * SD_BLOCK_SIZE); address += (blocks * SD_SECTOR_SIZE);
sector += (blocks * (p.card_type_block ? 1 : SD_BLOCK_SIZE)); sector += (blocks * (p.card_type_block ? 1 : SD_SECTOR_SIZE));
count -= blocks; count -= blocks;
} }

View File

@ -5,6 +5,9 @@
#include <stdbool.h> #include <stdbool.h>
#define SD_SECTOR_SIZE (512)
bool sd_card_init (void); bool sd_card_init (void);
void sd_card_deinit (void); void sd_card_deinit (void);
bool sd_card_get_status (void); bool sd_card_get_status (void);

View File

@ -185,6 +185,9 @@ class DD64Image:
self.__file.close() self.__file.close()
self.__drive_type = None self.__drive_type = None
def get_block_info_table(self) -> list[tuple[int, int]]:
return self.__block_info_table
def get_drive_type(self) -> str: def get_drive_type(self) -> str:
return self.__drive_type return self.__drive_type
@ -222,6 +225,12 @@ if __name__ == '__main__':
print(dd.read_block(track, head, block)[:4]) print(dd.read_block(track, head, block)[:4])
except BadBlockError: except BadBlockError:
print(f'Bad ID block [track: {track}, head: {head}, block: {block}]') print(f'Bad ID block [track: {track}, head: {head}, block: {block}]')
if (len(sys.argv) >= 3):
with open(sys.argv[2], 'wb+') as f:
block_info_table = dd.get_block_info_table()
for block in block_info_table:
offset = 0xFFFFFFFF if block == None else block[0]
f.write(offset.to_bytes(4, byteorder='big'))
dd.unload() dd.unload()
else: else:
print(f'[{sys.argv[0]}]: Expected disk image path as first argument') print(f'[{sys.argv[0]}]: Expected disk image path as first argument')

View File

@ -238,6 +238,7 @@ class SC64:
BUTTON_STATE = 12 BUTTON_STATE = 12
BUTTON_MODE = 13 BUTTON_MODE = 13
ROM_EXTENDED_ENABLE = 14 ROM_EXTENDED_ENABLE = 14
DD_SD_MODE = 15
class __UpdateError(IntEnum): class __UpdateError(IntEnum):
OK = 0 OK = 0
@ -364,6 +365,7 @@ class SC64:
self.__set_config(self.__CfgId.DD_DISK_STATE, self.__DDDiskState.EJECTED) self.__set_config(self.__CfgId.DD_DISK_STATE, self.__DDDiskState.EJECTED)
self.__set_config(self.__CfgId.BUTTON_MODE, self.__ButtonMode.NONE) self.__set_config(self.__CfgId.BUTTON_MODE, self.__ButtonMode.NONE)
self.__set_config(self.__CfgId.ROM_EXTENDED_ENABLE, False) self.__set_config(self.__CfgId.ROM_EXTENDED_ENABLE, False)
self.__set_config(self.__CfgId.DD_SD_MODE, False)
self.set_cic_parameters() self.set_cic_parameters()
def get_state(self): def get_state(self):
@ -383,6 +385,7 @@ class SC64:
'button_state': bool(self.__get_config(self.__CfgId.BUTTON_STATE)), 'button_state': bool(self.__get_config(self.__CfgId.BUTTON_STATE)),
'button_mode': self.__ButtonMode(self.__get_config(self.__CfgId.BUTTON_MODE)), 'button_mode': self.__ButtonMode(self.__get_config(self.__CfgId.BUTTON_MODE)),
'rom_extended_enable': bool(self.__get_config(self.__CfgId.ROM_EXTENDED_ENABLE)), 'rom_extended_enable': bool(self.__get_config(self.__CfgId.ROM_EXTENDED_ENABLE)),
'dd_sd_mode': bool(self.__get_config(self.__CfgId.DD_SD_MODE)),
} }
def download_memory(self) -> bytes: def download_memory(self) -> bytes:
@ -564,6 +567,7 @@ class SC64:
break break
if (dd): if (dd):
self.__set_config(self.__CfgId.DD_MODE, self.__DDMode.FULL) self.__set_config(self.__CfgId.DD_MODE, self.__DDMode.FULL)
self.__set_config(self.__CfgId.DD_SD_MODE, False)
self.__set_config(self.__CfgId.DD_DRIVE_TYPE, { self.__set_config(self.__CfgId.DD_DRIVE_TYPE, {
'retail': self.__DDDriveType.RETAIL, 'retail': self.__DDDriveType.RETAIL,
'development': self.__DDDriveType.DEVELOPMENT 'development': self.__DDDriveType.DEVELOPMENT