summary refs log tree commit diff
path: root/src/pico1541.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pico1541.c')
-rw-r--r--src/pico1541.c203
1 files changed, 197 insertions, 6 deletions
diff --git a/src/pico1541.c b/src/pico1541.c
index fec76a3..e46c4b9 100644
--- a/src/pico1541.c
+++ b/src/pico1541.c
@@ -1,8 +1,17 @@
+#include <stdint.h>
+
 #include <hardware/clocks.h>
+#include <hardware/flash.h>
 #include <hardware/gpio.h>
 #include <hardware/timer.h>
 #include <pico/multicore.h>
 
+#include <bsp/board_api.h>
+#include <tusb.h>
+
+#include "ff/ff.h"
+#include "ff/diskio.h"
+
 #include "6502.h"
 #include "6522.h"
 #include "drive.h"
@@ -15,10 +24,14 @@ const uint32_t GPIO_LED = 25;
 
 const uint8_t DEVICE = 8;
 
+#define FS_BYTES 1572864
+static uint8_t __in_flash("fs") __attribute__((aligned(4096))) FS[FS_BYTES];
+
+static FATFS FAT_FS;
+
 static uint8_t ram[2048];
-extern uint8_t _binary__Users_max_Documents_c64_roms_dos1541_start[16384];
-// extern uint8_t _binary__Users_max_Downloads_blackbird_1_2_Blackbird_1_2_d64_start[174848];
-extern uint8_t _binary__Users_max_Downloads_MementoMori_GP_MementoMori_GP_Disk1_d64_start[174848];
+static uint8_t dos1541[16384];
+static uint8_t disk[174848];
 
 uint32_t ts;
 cpu_t cpu;
@@ -83,14 +96,14 @@ void via_pb_write(via_t *via, uint8_t cycle) {
 		drive.spinning = ((via->ddrb & via->orb) & 4) > 0;
 
 		gpio_put(GPIO_LED, (via->orb & 0b00001000) > 0 && (via->ddrb & 0b00001000) > 0);
-	}
+	} 
 }
 
 uint8_t bus_read(uint16_t addr, uint8_t cycle) {
 	if (addr < 2048) {
 		return ram[addr];
 	} else if (addr >= 0xc000) {
-		return _binary__Users_max_Documents_c64_roms_dos1541_start[addr - 0xc000];
+		return dos1541[addr - 0xc000];
 	} else if (addr >= 0x1800 && addr < 0x1810) {
 		uint8_t v = 0;
 		via_read(&via1, addr - 0x1800, &v, cycle);
@@ -136,9 +149,131 @@ void atn_irq_callback(uint pin, uint32_t flags) {
 	}
 }
 
+static bool ejected = false;
+
+void tud_msc_inquiry_cb(uint8_t lun, uint8_t vid[8], uint8_t pid[16], uint8_t rev[4]) {
+	const char v[] = "TinyUSB";
+	const char p[] = "pico1541";
+	const char r[] = "1.0";
+
+	memcpy(vid, v, strlen(v));
+	memcpy(pid, p, strlen(p));
+	memcpy(rev, r, strlen(r));
+}
+
+bool tud_msc_test_unit_ready_cb(uint8_t lun) {
+	if (ejected) {
+		tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
+		return false;
+	}
+	return true;
+}
+
+void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) {
+	*block_count = FS_BYTES / 512;
+	*block_size = 512;
+}
+
+bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) {
+	if (load_eject && !start) {
+		ejected = true;
+	}
+	return true;
+}
+
+int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) {
+	if (lba >= FS_BYTES / 512) {
+		return -1;
+	}
+
+	uint8_t *addr = FS + 512 * lba + offset;
+	memcpy(buffer, addr, bufsize);
+
+	return (int32_t)bufsize;
+}
+
+// FIXME This is pretty naive....
+int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) {
+	if (lba >= FS_BYTES / 512) {
+		return -1;
+	}
+
+	uint32_t flash_sect = ((lba * 512 + offset) / 4096) * 4096;
+	uint32_t sect_ofs = lba * 512 + offset - flash_sect;
+	for (uint32_t i = 0; i < bufsize; i += 4096) {
+		uint8_t flash_buf[4096];
+		memcpy(flash_buf, FS + flash_sect + i, 4096);
+
+		if (i == 0) {
+			if (bufsize < 4096 - sect_ofs) {
+				memcpy(flash_buf + sect_ofs, buffer, bufsize);
+			} else {
+				memcpy(flash_buf + sect_ofs, buffer, 4096 - sect_ofs);
+			}
+		} else if (bufsize - i < 4096) {
+			memcpy(flash_buf, buffer + i - sect_ofs, bufsize - i);
+		} else {
+			memcpy(flash_buf, buffer + i - sect_ofs, 4096);
+		}
+
+		flash_range_erase((uint32_t)FS + flash_sect - 0x10000000, 4096);
+		flash_range_program((uint32_t)FS + flash_sect - 0x10000000, flash_buf, 4096);	
+	}
+
+	return (int32_t)bufsize;
+}
+
+bool tud_msc_is_writable_cb(uint8_t lun) {
+	return true;
+}
+
+int32_t tud_msc_scsi_cb(uint8_t lun, const uint8_t *scsi_cmd, void *buffer, uint16_t bufsize) {
+	tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
+	return -1;
+}
+
+DSTATUS disk_status(BYTE pdrv) {
+	return 0;
+}
+
+DSTATUS disk_initialize(BYTE pdrv) {
+	return 0;
+}
+
+DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
+	memcpy(buff, FS + 512 * sector, 512 * count);
+	return RES_OK;
+}
+
+DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count) {
+	// FIXME implement
+	return RES_ERROR;
+}
+
+DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {
+	switch (cmd) {
+		case CTRL_SYNC:
+			return RES_OK;
+		case GET_SECTOR_COUNT:
+			*(LBA_t *)buff = (FS_BYTES / 512);
+			return RES_OK;
+		case GET_SECTOR_SIZE:
+			*(WORD *)buff = 512;
+			return RES_OK;
+		case GET_BLOCK_SIZE:
+			*(DWORD *)buff = 4096;
+			return RES_OK;
+		case CTRL_TRIM:
+			return RES_OK;
+	}
+
+	return RES_PARERR;
+}
+
 void drive_thread() {
 	drive_init(&drive);
-	drive.image = _binary__Users_max_Downloads_MementoMori_GP_MementoMori_GP_Disk1_d64_start;
+	drive.image = disk;
+	
 	multicore_fifo_push_blocking(1);
 
 	while (multicore_fifo_pop_blocking_inline()) {
@@ -147,6 +282,62 @@ void drive_thread() {
 }
 
 int main() {
+	board_init();
+	tud_init(BOARD_TUD_RHPORT);
+	if (board_init_after_tusb) {
+		board_init_after_tusb();
+	}
+
+	while (!ejected) {
+		tud_task();
+	}
+	tud_disconnect();
+
+	f_mount(&FAT_FS, "0:", 0);
+	
+	FIL file;
+	FRESULT res;
+	uint32_t btr;
+	uint32_t br;
+
+	res = f_open(&file, "0:dos1541.bin", FA_READ);
+	if (res) {
+		return 0;
+	}
+	btr = 16384;
+	br = 0;
+	while (btr > 0) {
+		UINT brr;
+		if (btr < 4096) {
+			f_read(&file, dos1541 + br, btr, &brr);
+		} else {
+			f_read(&file, dos1541 + br, 4096, &brr);
+		}
+		br += brr;
+		btr -= brr;
+	}
+	f_close(&file);
+
+	res = f_open(&file, "0:image.d64", FA_READ);
+	if (res) {
+		return 0;
+	}
+	btr = 174848;
+	br = 0;
+	while (btr > 0) {
+		UINT brr;
+		if (btr < 4096) {
+			f_read(&file, disk + br, btr, &brr);
+		} else {
+			f_read(&file, disk + br, 4096, &brr);
+		}
+		br += brr;
+		btr -= brr;
+	}
+	f_close(&file);
+
+	f_unmount("0:");
+	
 	set_sys_clock_khz(250000, true);
 	multicore_launch_core1(drive_thread);