32 #include <sys/types.h>
42 # define KEEP_BUSY(n) keep_busy=n
47 #define SD_ST_SDHC 0x10
50 #define MIN_MOUNT_SECTOR_NO 10
52 #define SD_BUFFER_POS 0x0E00
53 #define FD_BUFFER_POS 0x0C00
56 static Uint8 sd_regs[0x30];
59 static int sdhc_mode = 1;
60 static Uint32 sdcard_size_in_blocks;
61 static int sd_fill_mode = 0;
62 static Uint8 sd_fill_value = 0;
63 static int default_d81_is_from_sd;
65 static int sd_compressed = 0;
66 static off_t sd_bdata_start;
67 static int compressed_block;
69 static int sd_is_read_only;
71 static int keep_busy = 0;
75 static Uint8 sd_fill_buffer[512];
82 static const char *default_d81_basename[2] = {
"mega65.d81",
"mega65_9.d81" };
83 static const char *default_d81_disk_label[2] = {
"XEMU EXTERNAL",
"XEMU EXTERNAL 9" };
96 #ifdef VIRTUAL_DISK_IMAGE_SUPPORT
98 #define VIRTUAL_DISK_BLOCKS_PER_CHUNK 2048
100 #define VIRTUAL_DISK_SIZE_IN_BLOCKS 8388608U
102 #define RANGE_MAP_SIZE 256
104 struct virtdisk_chunk_st {
105 struct virtdisk_chunk_st *
next;
113 struct virtdisk_chunk_st *head, *tail;
114 int blocks_per_chunk;
119 Uint8 range_map[RANGE_MAP_SIZE];
124 static struct virtdisk_st vdisk = { .head = NULL };
126 static void virtdisk_destroy (
void )
129 struct virtdisk_chunk_st *v = vdisk.head;
131 for (
unsigned int a = 0; a < RANGE_MAP_SIZE; a++)
132 for (
Uint8 m = 0x80; m; m >>= 1)
133 if ((vdisk.range_map[a] & m))
135 DEBUGPRINT(
"SDCARD: VDISK: destroying %d chunks (active data: %d blocks, %dKbytes, %d%%, ranges: %d/%d) of storage." NL,
136 vdisk.all_chunks, vdisk.all_blocks, vdisk.all_blocks >> 1,
137 100 * vdisk.all_blocks / (vdisk.all_chunks * vdisk.blocks_per_chunk),
138 ranges, RANGE_MAP_SIZE * 8
141 struct virtdisk_chunk_st *
next = v->next;
148 vdisk.all_chunks = 0;
149 vdisk.all_blocks = 0;
150 memset(vdisk.range_map, 0, RANGE_MAP_SIZE);
154 static void virtdisk_init (
int blocks_per_chunk,
Uint32 total_number_of_blocks )
157 vdisk.blocks_per_chunk = blocks_per_chunk;
158 vdisk.base_offset =
sizeof(
struct virtdisk_chunk_st) + (sizeof(
Uint32) * blocks_per_chunk);
159 vdisk.allocation_size = (blocks_per_chunk << 9) + vdisk.base_offset;
160 vdisk.range_map_divisor = (total_number_of_blocks / (RANGE_MAP_SIZE * 8)) + 1;
161 DEBUGPRINT(
"SDCARD: VDISK: %d blocks (%dKbytes) per chunk, range-divisor is %u" NL, blocks_per_chunk, blocks_per_chunk >> 1, vdisk.range_map_divisor);
169 struct virtdisk_chunk_st *v;
170 Uint32 range_index =
block / vdisk.range_map_divisor;
171 Uint8 range_mask = 1U << (range_index & 7U);
173 if (
XEMU_LIKELY(vdisk.head && (vdisk.range_map[range_index] & range_mask))) {
176 if (
block >= v->block_no_min && block <= v->block_no_max)
177 for (
unsigned int a = 0; a < v->used_blocks; a++)
178 if (v->list[a] ==
block)
179 return v->base + (a << 9);
190 if (vdisk.tail && (vdisk.tail->used_blocks < vdisk.blocks_per_chunk)) {
194 if (block < v->block_no_min)
195 v->block_no_min =
block;
196 if (
block > v->block_no_max)
197 v->block_no_max =
block;
198 vdisk.range_map[range_index] |= range_mask;
199 v->list[v->used_blocks] =
block;
200 return v->base + ((v->used_blocks++) << 9);
206 v->base = (
Uint8*)v + vdisk.base_offset;
209 vdisk.tail->next = v;
215 v->block_no_min =
block;
216 v->block_no_max =
block;
217 vdisk.range_map[range_index] |= range_mask;
226 Uint8 *vbuf = virtdisk_search_block(
block, has_block_nonzero_byte(buffer));
228 memcpy(vbuf, buffer, 512);
235 Uint8 *vbuf = virtdisk_search_block(
block, 0);
237 memcpy(buffer, vbuf, 512);
239 memset(buffer, 0, 512);
250 DEBUGPRINT(
"SDCARD: configuring F011 FDC (#%d) with have_disk=%d, can_write=%d" NL, which,
have_disk, can_write);
257 DEBUG(
"SDCARD: D81: reading sector at d81_pos=(%d,%d,%d), return value=%d" NL, side, track, sector, ret);
263 DEBUG(
"SDCARD: D81: writing sector at d81_pos=(%d,%d,%d), return value=%d" NL, side, track, sector, ret);
268 static void sdcard_shutdown (
void )
275 #ifdef VIRTUAL_DISK_IMAGE_SUPPORT
282 static int detect_compressed_image (
int fd )
284 static const char compressed_marker[] =
"XemuBlockCompressedImage000";
288 if (memcmp(
buf, compressed_marker,
sizeof compressed_marker)) {
292 if (((
buf[0x1C] << 16) | (
buf[0x1D] << 8) |
buf[0x1E]) != 3) {
293 ERROR_WINDOW(
"Invalid/unknown compressed image format");
296 sdcard_size_in_blocks = (
buf[0x1F] << 16) | (
buf[0x20] << 8) |
buf[0x21];
297 DEBUGPRINT(
"SDCARD: compressed image with %u blocks" NL, sdcard_size_in_blocks);
298 sd_bdata_start = 3 * sdcard_size_in_blocks + 0x22;
299 sd_is_read_only = O_RDONLY;
307 return sdcard_size_in_blocks;
311 static XEMU_INLINE void set_disk_buffer_cpu_view (
void )
317 static void show_card_init_done (
void )
319 DEBUGPRINT(
"SDCARD: card init done, size=%u Mbytes (%s), virtsd_mode=%s, default_D81_from_sd=%d" NL,
320 sdcard_size_in_blocks >> 11,
321 sd_is_read_only ?
"R/O" :
"R/W",
322 vdisk.mode ?
"IN-MEMORY-VIRTUAL" :
"image-file",
323 default_d81_is_from_sd
328 int sdcard_init (
const char *
fn,
const int virtsd_flag,
const int default_d81_is_from_sd_in )
330 default_d81_is_from_sd = default_d81_is_from_sd_in;
331 memset(sd_regs, 0,
sizeof sd_regs);
333 set_disk_buffer_cpu_view();
334 for (
int a = 0; a < 2; a++) {
335 mount_info[a].current_name =
xemu_strdup(
"<INIT>");
336 mount_info[a].internal = -1;
337 mount_info[a].force_external_name = NULL;
338 mount_info[a].at_sector = 0;
339 mount_info[a].at_sector_initial = 0;
340 mount_info[a].monitoring_initial = 0;
342 int just_created_image_file = 0;
343 char fnbuf[PATH_MAX + 1];
344 #ifdef VIRTUAL_DISK_IMAGE_SUPPORT
346 virtdisk_init(VIRTUAL_DISK_BLOCKS_PER_CHUNK, VIRTUAL_DISK_SIZE_IN_BLOCKS);
353 atexit(sdcard_shutdown);
357 memset(sd_fill_buffer, sd_fill_value, 512);
358 #ifdef VIRTUAL_DISK_IMAGE_SUPPORT
362 sdcard_size_in_blocks = VIRTUAL_DISK_SIZE_IN_BLOCKS;
366 show_card_init_done();
367 #ifdef SD_CONTENT_SUPPORT
368 sdcontent_handle(sdcard_size_in_blocks,
fn, SDCONTENT_FORCE_FDISK);
374 sd_is_read_only = O_RDONLY;
379 ERROR_WINDOW(
"Cannot open SD-card image %s, SD-card access won't work! ERROR: %s", fnbuf, strerror(
r));
380 DEBUG(
"SDCARD: cannot open image %s" NL,
fn);
385 "Default SDCARD image does not exist. Would you like me to create one for you?\n"
386 "Note: it will be a 4Gbytes long file, since this is the minimal size for an SDHC card,\n"
387 "what MEGA65 needs. Do not worry, it's a 'sparse' file on most modern OSes which does\n"
388 "not takes as much disk space as its displayed size suggests.\n"
389 "This is unavoidable to emulate something uses an SDHC-card."
394 ERROR_WINDOW(
"Couldn't create SD-card image file (hint: do you have enough space?)\nError message was: %s", strerror(
r));
396 just_created_image_file = 1;
403 INFO_WINDOW(
"SDCARD: image file %s could be open only in R/O mode!", fnbuf);
405 DEBUG(
"SDCARD: image file re-opened in RD/WR mode, good" NL);
407 DEBUG(
"SDCARD: cool, SD-card image %s (as %s) is open" NL,
fn, fnbuf);
410 ERROR_WINDOW(
"Cannot query the size of the SD-card image %s, SD-card access won't work! ERROR: %s",
fn, strerror(errno));
416 sd_compressed = detect_compressed_image(sdfd);
417 if (sd_compressed < 0) {
418 ERROR_WINDOW(
"Error while trying to detect compressed SD-image");
419 sdcard_size_in_blocks = 0;
422 sdcard_size_in_blocks = size_in_bytes >> 9;
423 DEBUG(
"SDCARD: detected size in Mbytes: %d" NL, (
int)(size_in_bytes >> 20));
424 if (size_in_bytes < 67108864UL) {
425 ERROR_WINDOW(
"SD-card image is too small! Min required size is 64Mbytes!");
430 if (size_in_bytes & (off_t)511) {
431 ERROR_WINDOW(
"SD-card image size is not multiple of 512 bytes!!");
436 if (size_in_bytes > 34359738368UL) {
437 ERROR_WINDOW(
"SD-card image is too large! Max allowed size is 32Gbytes!");
444 show_card_init_done();
446 if (just_created_image_file) {
447 just_created_image_file = 0;
449 if (!sdcontent_handle(sdcard_size_in_blocks, NULL, SDCONTENT_FORCE_FDISK)) {
450 INFO_WINDOW(
"Your just created SD-card image file has\nbeen auto-fdisk/format'ed by Xemu. Great :).");
451 sdcontent_write_rom_stub();
455 if (!virtsd_flag && sdfd >= 0) {
456 static const char msg[] =
" on the SD-card image.\nPlease use UI menu: Disks -> SD-card -> Update files ...\nUI can be accessed with right mouse click into the emulator window.";
457 int r = sdcontent_check_xemu_signature();
459 ERROR_WINDOW(
"Warning! Cannot read SD-card to get Xemu signature!");
461 INFO_WINDOW(
"Cannot find Xemu's signature%s", msg);
463 INFO_WINDOW(
"Xemu's singature is too old%s to upgrade", msg);
465 INFO_WINDOW(
"Xemu's signature is too new%s to DOWNgrade", msg);
485 FATAL(
"host_seek is called with invalid sdfd!");
489 offset =
block * 3 + 0x22;
490 if (lseek(sdfd, offset, SEEK_SET) != offset)
491 FATAL(
"SDCARD: SEEK: compressed image host-OS seek failure: %s", strerror(errno));
494 FATAL(
"SDCARD: SEEK: compressed image host-OK pre-read failure: %s", strerror(errno));
495 compressed_block = (
buf[0] & 0x80);
497 offset = ((off_t)((
buf[0] << 16) | (
buf[1] << 8) |
buf[2]) << 9) + sd_bdata_start;
500 offset = (off_t)
block << 9;
503 offset = (off_t)
block << 9;
505 if (lseek(sdfd, offset, SEEK_SET) != offset)
506 FATAL(
"SDCARD: SEEK: image seek host-OS failure: %s", strerror(errno));
515 static Uint8 sdcard_read_status (
void )
518 DEBUG(
"SDCARD: reading SD status $D680 result is $%02X PC=$%04X" NL, ret, cpu65.pc);
550 if (
block >= sdcard_size_in_blocks) {
551 DEBUGPRINT(
"SDCARD: SEEK: invalid block was requested to READ: block=%u (max_block=%u) @ PC=$%04X" NL,
block, sdcard_size_in_blocks, cpu65.pc);
554 #ifdef VIRTUAL_DISK_IMAGE_SUPPORT
556 virtdisk_read_block(
block, buffer);
560 if (host_seek(
block))
571 if (
block >= sdcard_size_in_blocks) {
572 DEBUGPRINT(
"SDCARD: SEEK: invalid block was requested to WRITE: block=%u (max_block=%u) @ PC=$%04X" NL,
block, sdcard_size_in_blocks, cpu65.pc);
577 #ifdef VIRTUAL_DISK_IMAGE_SUPPORT
579 virtdisk_write_block(
block, buffer);
583 if (host_seek(
block))
597 static void sdcard_block_io (
Uint32 block,
int is_write )
599 static int protect_important_blocks = 1;
600 DEBUG(
"SDCARD: %s block #%u @ PC=$%04X" NL,
601 is_write ?
"writing" :
"reading",
604 if (
XEMU_UNLIKELY(is_write && (
block == 0 ||
block == XEMU_INFO_SDCARD_BLOCK_NO) && sdfd >= 0 && protect_important_blocks)) {
605 if (protect_important_blocks == 2) {
609 sprintf(msg,
"Program tries to overwrite SD sector #%d!\nUnless you fdisk/format your card, it's not something you want.",
block);
610 switch (
QUESTION_WINDOW(
"Reject this|Reject all|Allow this|Allow all", msg)) {
614 protect_important_blocks = 2;
619 protect_important_blocks = 0;
631 Uint8 *buffer = get_buffer_memory(is_write);
633 if (ret || !sdhc_mode) {
642 off_t offset = sd_sector;
644 int ret = host__seek(offset);
649 Uint8 *wp = get_buffer_memory(is_write);
652 (is_write && compressed_block) ||
669 static void sdcard_command (
Uint8 cmd )
671 static Uint32 multi_io_block;
672 static Uint8 sd_last_ok_cmd;
673 DEBUG(
"SDCARD: writing command register $D680 with $%02X PC=$%04X" NL, cmd, cpu65.pc);
681 memset(sd_regs + 1, 0, 4);
691 sdcard_block_io(U8A_TO_U32(sd_regs + 1), 0);
694 sdcard_block_io(U8A_TO_U32(sd_regs + 1), 1);
700 if (sd_last_ok_cmd != 0x04) {
701 multi_io_block = U8A_TO_U32(sd_regs + 1);
702 sdcard_block_io(multi_io_block, 1);
704 DEBUGPRINT(
"SDCARD: bad multi-command sequence command $%02X after command $%02X" NL, cmd, sd_last_ok_cmd);
709 if (sd_last_ok_cmd == 0x04 || sd_last_ok_cmd == 0x05 || sd_last_ok_cmd == 0x57) {
711 sdcard_block_io(multi_io_block, 1);
713 DEBUGPRINT(
"SDCARD: bad multi-command sequence command $%02X after command $%02X" NL, cmd, sd_last_ok_cmd);
718 if (sd_last_ok_cmd == 0x04 || sd_last_ok_cmd == 0x05 || sd_last_ok_cmd == 0x57) {
720 sdcard_block_io(multi_io_block, 1);
722 DEBUGPRINT(
"SDCARD: bad multi-command sequence command $%02X after command $%02X" NL, cmd, sd_last_ok_cmd);
761 DEBUGPRINT(
"SDCARD: warning, unimplemented SD-card controller command $%02X" NL, cmd);
765 sd_last_ok_cmd = 0xFF;
767 sd_last_ok_cmd = cmd;
780 for (
int unit = 0; unit < 2; unit++) {
781 mount_info[unit].at_sector_initial = 0;
782 mount_info[unit].monitoring_initial = 1;
784 memset(sd_regs + 0x0C, 0, 4);
785 memset(sd_regs + 0x10, 0, 4);
786 sd_regs[0xB] &= 255 - (8 + 1);
792 for (
int unit = 0; unit < 2; unit++) {
793 mount_info[unit].monitoring_initial = 0;
795 DEBUGPRINT(
"SDCARD: D81-DEFAULT: WARNING: could not determine default on-sd D81 mount sector info during the RESET TRAP for unit #%d!" NL, unit);
800 static int do_default_d81_mount_hack (
const int unit )
802 static char *default_d81_path[2] = { NULL, NULL };
803 if (!default_d81_path[unit]) {
805 const char *hdosroot;
807 const int len = strlen(hdosroot) + strlen(default_d81_basename[unit]) + 1;
809 snprintf(default_d81_path[unit], len,
"%s%s", hdosroot, default_d81_basename[unit]);
811 DEBUGPRINT(
"SDCARD: D81-DEFAULT: trying to mount external D81 instead of internal default one as %s on unit #%d" NL, default_d81_path[unit], unit);
823 if (default_d81_is_from_sd) {
824 ERROR_WINDOW(
"This function is not available when\n\"default D81 mount from SD\" option is inactive!");
827 return do_default_d81_mount_hack(unit);
835 static int internal_mount (
const int unit )
843 if ( sd_is_read_only)
850 if ( sd_is_read_only)
859 mount_info[unit].current_name[0] =
'\0';
860 mount_info[unit].internal = -1;
869 if (!do_default_d81_mount_hack(unit))
873 DEBUGPRINT(
"SDCARD: D81: internal mount #%d from SD sector $%X (%s)" NL, unit,
at_sector, ro_flag ?
"R/O" :
"R/W");
876 sprintf(
fn,
"<SD@$%X:%s>",
at_sector, ro_flag ?
"RO" :
"RW");
878 mount_info[unit].internal = 1;
883 static int some_mount (
const int unit )
885 const char *extfn = mount_info[unit].force_external_name;
888 DEBUGPRINT(
"SDCARD: D81: external mount #%d change from \"%s\" to \"%s\"" NL, unit, mount_info[unit].
current_name, extfn);
890 DEBUGPRINT(
"SDCARD: D81: external mount #%d failed at \"%s\", closing unit." NL, unit, extfn);
892 mount_info[unit].current_name[0] =
'\0';
898 DEBUGPRINT(
"SDCARD: D81: external mount #%d but no change, \"%s\" = \"%s\"" NL, unit, mount_info[unit].
current_name, extfn);
900 mount_info[unit].internal = 0;
902 sd_regs[0xB] |= !unit ? 1 : 8;
906 if (internal_mount(unit) == 0) {
907 DEBUGPRINT(
"SDCARD: D81: internal mount #%d has no condition to mount anything." NL, unit);
909 mount_info[unit].current_name[0] =
'\0';
910 mount_info[unit].internal = -1;
920 *is_internal = mount_info[unit & 1].internal;
921 return mount_info[unit & 1].current_name;
927 DEBUGPRINT(
"SDCARD: D81: %s(%d, \"%s\", \"%s\");" NL, __func__, unit, filename, cry);
928 if (filename && *filename) {
932 mount_info[unit].force_external_name = NULL;
934 if (some_mount(unit)) {
937 mount_info[unit].current_name[0] =
'\0';
940 ERROR_WINDOW(
"%s\nCould not mount requested file as unit #%d:\n%s", cry, unit, filename);
943 mount_info[unit].force_external_name = NULL;
962 mount_info[unit].internal = 0;
967 mount_info[unit].force_external_name = NULL;
975 const Uint8 prev_data = sd_regs[reg];
980 sdcard_command(
data);
986 DEBUG(
"SDCARD: writing sector number register $%04X with $%02X PC=$%04X" NL, reg + 0xD680,
data, cpu65.pc);
989 sd_fill_value =
data;
990 if (sd_fill_value != sd_fill_buffer[0])
991 memset(sd_fill_buffer, sd_fill_value, 512);
994 set_disk_buffer_cpu_view();
1000 DEBUGPRINT(
"SDCARD: writing FDC configuration register $%04X with $%02X (old_data=$%02X) PC=$%04X" NL, reg + 0xD680,
data, prev_data, cpu65.pc);
1002 mount_info[0].at_sector_initial = U8A_TO_U32(sd_regs + 0x0C);
1004 mount_info[1].at_sector_initial = U8A_TO_U32(sd_regs + 0x10);
1005 if ((
data ^ prev_data) & 0x07)
1007 if ((
data ^ prev_data) & 0x38)
1014 if (
data != prev_data) {
1015 DEBUGPRINT(
"SDCARD: writing D81 #0 sector register $%04X with $%02X PC=$%04X" NL, reg + 0xD680,
data, cpu65.pc);
1023 if (
data != prev_data) {
1024 DEBUGPRINT(
"SDCARD: writing D81 #1 sector register $%04X with $%02X PC=$%04X" NL, reg + 0xD680,
data, cpu65.pc);
1029 DEBUGPRINT(
"SDCARD: unimplemented register: $%02X tried to be written with data $%02X" NL, reg,
data);
1040 return sdcard_read_status();
1054 (sd_regs[0x9] & 0x80);
1077 DEBUGPRINT(
"SDCARD: unimplemented register: $%02X tried to be read, defaulting to the back storage with data $%02X" NL, reg,
data);
1087 #ifdef XEMU_SNAPSHOT_SUPPORT
1091 #define SNAPSHOT_SDCARD_BLOCK_VERSION 0
1092 #define SNAPSHOT_SDCARD_BLOCK_SIZE (0x100 + sizeof(disk_buffers))
1094 int sdcard_snapshot_load_state (
const struct xemu_snapshot_definition_st *def,
struct xemu_snapshot_block_st *
block )
1096 Uint8 buffer[SNAPSHOT_SDCARD_BLOCK_SIZE];
1098 if (
block->block_version != SNAPSHOT_SDCARD_BLOCK_VERSION ||
block->sub_counter ||
block->sub_size !=
sizeof buffer)
1099 RETURN_XSNAPERR_USER(
"Bad SD-Card block syntax");
1100 a = xemusnap_read_file(buffer,
sizeof buffer);
1103 memcpy(sd_sector_registers, buffer, 4);
1104 memcpy(sd_d81_img1_start, buffer + 4, 4);
1105 fd_mounted = (int)P_AS_BE32(buffer + 8);
1106 sd_is_read_only = (int)P_AS_BE32(buffer + 16);
1115 int sdcard_snapshot_save_state (
const struct xemu_snapshot_definition_st *def )
1117 Uint8 buffer[SNAPSHOT_SDCARD_BLOCK_SIZE];
1118 int a = xemusnap_write_block_header(def->idstr, SNAPSHOT_SDCARD_BLOCK_VERSION);
1120 memset(buffer, 0xFF,
sizeof buffer);
1122 memcpy(buffer, sd_sector_registers, 4);
1123 memcpy(buffer + 4,sd_d81_img1_start, 4);
1124 U32_AS_BE(buffer + 8, fd_mounted);
1125 U32_AS_BE(buffer + 16, sd_is_read_only);
1130 return xemusnap_write_sub_block(buffer,
sizeof buffer);