From d65abb174247e723751139c4b2a3b460f283f37d Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sat, 9 Jan 2021 18:53:07 +0100 Subject: [PATCH 01/65] Experiments with CH376 file access: - Initialize storage device - List files in root dir - List files in DSK dir --- dotNet/Sandbox/Program.cs | 37 ++++++++++ dotNet/Usb/CH376UsbHostHardware.cs | 104 +++++++++++++++++++++++++++++ dotNet/Usb/UsbPacketResult.cs | 32 +++++++-- dotNet/Usb/UsbServiceProvider.cs | 2 +- 4 files changed, 167 insertions(+), 8 deletions(-) diff --git a/dotNet/Sandbox/Program.cs b/dotNet/Sandbox/Program.cs index 162227e..2890d6c 100644 --- a/dotNet/Sandbox/Program.cs +++ b/dotNet/Sandbox/Program.cs @@ -26,6 +26,43 @@ static void Main(string[] args) static void _Main(string[] args) { + var hw = new CH376UsbHostHardware(UsbServiceProvider.GetCH376Ports()); + hw.HardwareReset(); + var diskName = hw.InitDisk(); + if (diskName == null) + Console.WriteLine("*** No storage device detected"); + else + Console.WriteLine("Storage device detected: " + diskName); + + dynamic diskTypeAndCapacity = hw.GetDiskTypeAndCapacity(); + Console.WriteLine($"Total size: {diskTypeAndCapacity.totalSizeMb} MB"); + Console.WriteLine($"Free size: {diskTypeAndCapacity.freeSizeMb} MB"); + Console.WriteLine($"Filesystem: {diskTypeAndCapacity.filesystem}"); + Console.WriteLine(); + + hw.InitFilesystem(); + var files = hw.EnumerateFiles("/"); + if(files.Length == 0) + { + Console.WriteLine("*** No files found"); + } + else + { + Console.WriteLine("Files found:"); + foreach (var name in files) + Console.WriteLine(name); + + Console.WriteLine(); + Console.WriteLine("Files found in DSK:"); + files = hw.EnumerateFiles("DSK"); + foreach (var name in files) + Console.WriteLine(name); + } + Console.ReadKey(); + return; + + ///// + var deviceWasConnected = false; usb = new UsbHost(new CH376UsbHostHardware(UsbServiceProvider.GetCH376Ports("90.173.150.35", 1288))); diff --git a/dotNet/Usb/CH376UsbHostHardware.cs b/dotNet/Usb/CH376UsbHostHardware.cs index bd59abb..9becb12 100644 --- a/dotNet/Usb/CH376UsbHostHardware.cs +++ b/dotNet/Usb/CH376UsbHostHardware.cs @@ -1,6 +1,9 @@ using System; using System.Threading; using System.Linq; +using System.Text; +using System.Dynamic; +using System.Collections.Generic; namespace Konamiman.RookieDrive.Usb { @@ -27,6 +30,15 @@ public class CH376UsbHostHardware : IUsbHostHardware, IUsbHardwareShortcuts const byte CMD_RET_SUCCESS = 0x51; const byte CMD_RET_ABORT = 0x5F; + const byte CMD_DISK_CONNECT = 0x30; + const byte CMD_DISK_MOUNT = 0x31; + const byte CMD_DISK_CAPACITY = 0x3E; + const byte CMD_DISK_QUERY = 0x3F; + const byte CMD_SET_FILE_NAME = 0x2F; + const byte CMD_FILE_OPEN = 0x32; + const byte CMD_FILE_ENUM_GO = 0x33; + const byte CMD_FILE_CLOSE = 0x36; + private readonly ICH376Ports ch; private static readonly byte[] noData = new byte[0]; @@ -233,6 +245,10 @@ private UsbPacketResult WaitAndGetResult() if (result2 == 0x20) return UsbPacketResult.Timeout; + if(result >= 0x1D && Enum.IsDefined(typeof(UsbPacketResult), (int)result)) { + return (UsbPacketResult)result; + } + throw new Exception($"Unexpected value from GET_STATUS: 0x{result:X}"); } @@ -321,5 +337,93 @@ public UsbTransferResult ClearEndpointHalt(int deviceAddress, byte endpointNumbe var result = WaitAndGetResult(); return new UsbTransferResult(result); } + + public string InitDisk() + { + ch.WriteCommand(CMD_DISK_CONNECT); + var result = WaitAndGetResult(); + if (result != UsbPacketResult.Ok) + return null; + + BusResetAndSetHostWithSofMode(); + ch.WriteCommand(CMD_DISK_MOUNT); + result = WaitAndGetResult(); + if (result != UsbPacketResult.Ok) + return null; + + var data = new byte[36]; + ReadUsbData(data, 0); + return Encoding.ASCII.GetString(data.Skip(8).ToArray()); + } + + public object GetDiskTypeAndCapacity() + { + ch.WriteCommand(CMD_DISK_QUERY); + var result = WaitAndGetResult(); + if (result != UsbPacketResult.Ok) + return null; + + var data = new byte[9]; + ReadUsbData(data, 0); + var totalSectorsCount = BitConverter.ToInt32(data, 0); + var freeSectorsCount = BitConverter.ToInt32(data, 4); + var filesystemTypeByte = data[8]; + + dynamic r = new ExpandoObject(); + r.totalSizeMb = totalSectorsCount / 2048; + r.freeSizeMb = freeSectorsCount / 2048; + r.filesystem = + filesystemTypeByte == 1 ? "FAT12" : + filesystemTypeByte == 2 ? "FAT16" : + filesystemTypeByte == 3 ? "FAT32" : + $"Unknown ({filesystemTypeByte})"; + + return r; + } + + public void InitFilesystem() + { + ch.WriteCommand(CMD_SET_FILE_NAME); + ch.WriteData(0); + ch.WriteCommand(CMD_FILE_OPEN); + } + + public string[] EnumerateFiles(string searchPath = "/") + { + ch.WriteCommand(CMD_SET_FILE_NAME); + ch.WriteMultipleData(Encoding.ASCII.GetBytes(searchPath + "\0")); + ch.WriteCommand(CMD_FILE_OPEN); + var result = WaitAndGetResult(); + if (result != UsbPacketResult.ERR_OPEN_DIR) + return new[] { $"*** Error opening directory: {result}" }; + + ch.WriteCommand(CMD_SET_FILE_NAME); + ch.WriteMultipleData(Encoding.ASCII.GetBytes("*\0")); + ch.WriteCommand(CMD_FILE_OPEN); + + result = WaitAndGetResult(); + var data = new byte[32]; + var names = new List(); + while (result == UsbPacketResult.USB_INT_DISK_READ) + { + ReadUsbData(data); + + var name = Encoding.ASCII.GetString(data, 0, 8).Trim(); + var ext = Encoding.ASCII.GetString(data, 8, 3).Trim(); + if (ext != "") + name = $"{name}.{ext}"; + if ((data[11] & 0x10) == 0x10) + name += "/"; + + names.Add(name); + + ch.WriteCommand(CMD_FILE_ENUM_GO); + result = WaitAndGetResult(); + } + + //ch.WriteCommand(CMD_FILE_CLOSE); + //ch.WriteData(0); + return names.ToArray(); + } } } diff --git a/dotNet/Usb/UsbPacketResult.cs b/dotNet/Usb/UsbPacketResult.cs index 8cb4d4a..c18e78b 100644 --- a/dotNet/Usb/UsbPacketResult.cs +++ b/dotNet/Usb/UsbPacketResult.cs @@ -3,12 +3,30 @@ public enum UsbPacketResult { Ok, - Nak, - Stall, - Timeout, - DataError, - OtherError, - NoDeviceConnected, - NotImplemented + Nak = 1, + Stall = 2, + Timeout = 3, + DataError = 4, + OtherError = 5, + NoDeviceConnected = 6, + NotImplemented = 7, + USB_INT_SUCCESS = 0x14, + USB_INT_CONNECT = 0x15, + USB_INT_DISCONNECT = 0x16, + USB_INT_BUF_OVER = 0x17, + USB_INT_USB_READY = 0x18, + USB_INT_DISK_READ = 0x1D, + USB_INT_DISK_WRITE = 0x1E, + USB_INT_DISK_ERR = 0x1F, + ERR_OPEN_DIR = 0x41, + ERR_MISS_FILE = 0x42, + ERR_FOUND_NAME = 0x43, + ERR_DISK_DISCON = 0x82, + ERR_LARGE_SECTOR = 0x84, + ERR_TYPE_ERROR = 0x92, + ERR_BPB_ERROR = 0xA1, + ERR_DISK_FULL = 0xB1, + ERR_FDT_OVER = 0xB2, + ERR_FILE_CLOSE = 0xB4 } } diff --git a/dotNet/Usb/UsbServiceProvider.cs b/dotNet/Usb/UsbServiceProvider.cs index 2d1ef8a..d094772 100644 --- a/dotNet/Usb/UsbServiceProvider.cs +++ b/dotNet/Usb/UsbServiceProvider.cs @@ -5,7 +5,7 @@ public static class UsbServiceProvider public static ICH376Ports GetCH376Ports(string serverIp = "localhost", int serverPort = 3434) { //return new CH376PortsViaOpc(serverIp, serverPort); - return new CH376PortsViaNoobtocol("COM4"); + return new CH376PortsViaNoobtocol("COM5"); } } } From 84a03d8a63449f23c979bdb1e3fd04d3a6ca466d Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sun, 10 Jan 2021 15:56:59 +0100 Subject: [PATCH 02/65] Experiments with CH376 file access: - Open a file and read its contents --- dotNet/Sandbox/Program.cs | 4 +++ dotNet/Usb/CH376UsbHostHardware.cs | 42 ++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/dotNet/Sandbox/Program.cs b/dotNet/Sandbox/Program.cs index 2890d6c..d9ec91d 100644 --- a/dotNet/Sandbox/Program.cs +++ b/dotNet/Sandbox/Program.cs @@ -57,6 +57,10 @@ static void _Main(string[] args) files = hw.EnumerateFiles("DSK"); foreach (var name in files) Console.WriteLine(name); + + Console.WriteLine(); + Console.WriteLine("Contents of DSK/DRIVER.ASM:"); + Console.Write(hw.ReadFileContents("DRIVER.ASM")); } Console.ReadKey(); return; diff --git a/dotNet/Usb/CH376UsbHostHardware.cs b/dotNet/Usb/CH376UsbHostHardware.cs index 9becb12..74aaab4 100644 --- a/dotNet/Usb/CH376UsbHostHardware.cs +++ b/dotNet/Usb/CH376UsbHostHardware.cs @@ -38,6 +38,9 @@ public class CH376UsbHostHardware : IUsbHostHardware, IUsbHardwareShortcuts const byte CMD_FILE_OPEN = 0x32; const byte CMD_FILE_ENUM_GO = 0x33; const byte CMD_FILE_CLOSE = 0x36; + const byte CMD_BYTE_LOCATE = 0x39; + const byte CMD_BYTE_READ = 0x3A; + const byte CMD_BYTE_RD_GO = 0x3B; private readonly ICH376Ports ch; private static readonly byte[] noData = new byte[0]; @@ -421,9 +424,44 @@ public string[] EnumerateFiles(string searchPath = "/") result = WaitAndGetResult(); } - //ch.WriteCommand(CMD_FILE_CLOSE); - //ch.WriteData(0); return names.ToArray(); } + + public string ReadFileContents(string filename) + { + int count; + UsbPacketResult result; + var data = new byte[65535]; + + ch.WriteCommand(CMD_SET_FILE_NAME); + ch.WriteMultipleData(Encoding.ASCII.GetBytes(filename + "\0")); + ch.WriteCommand(CMD_FILE_OPEN); + result = WaitAndGetResult(); + if (result != UsbPacketResult.Ok) + return "*** Error opening file: " + result.ToString(); + + var sb = new StringBuilder(); + + while (true) + { + ch.WriteCommand(CMD_BYTE_READ); + ch.WriteData(0xFF); + ch.WriteData(0xFF); //Request 65535 bytes + result = WaitAndGetResult(); + if (result == UsbPacketResult.Ok) + return sb.ToString(); + else if (result != UsbPacketResult.USB_INT_DISK_READ) + return "*** Error reading file: " + result.ToString(); + + do + { + count = ReadUsbData(data); + sb.Append(Encoding.ASCII.GetString(data, 0, count)); + ch.WriteCommand(CMD_BYTE_RD_GO); + result = WaitAndGetResult(); + } + while (result == UsbPacketResult.USB_INT_DISK_READ); + } + } } } From f4234447dbbbc8ac82f5c186370a5d6b2576448b Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 12 Jan 2021 22:24:24 +0100 Subject: [PATCH 03/65] Experiments with CH376 file access: Use normal reset instead of DISK_CONNECT. --- dotNet/Sandbox/Program.cs | 7 +++++-- dotNet/Usb/CH376UsbHostHardware.cs | 18 ++++++++++++------ dotNet/Usb/UsbPacketResult.cs | 14 +++++++------- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/dotNet/Sandbox/Program.cs b/dotNet/Sandbox/Program.cs index d9ec91d..458c693 100644 --- a/dotNet/Sandbox/Program.cs +++ b/dotNet/Sandbox/Program.cs @@ -29,8 +29,11 @@ static void _Main(string[] args) var hw = new CH376UsbHostHardware(UsbServiceProvider.GetCH376Ports()); hw.HardwareReset(); var diskName = hw.InitDisk(); - if (diskName == null) - Console.WriteLine("*** No storage device detected"); + if (diskName[0] == '*') + { + Console.WriteLine(diskName); + return; + } else Console.WriteLine("Storage device detected: " + diskName); diff --git a/dotNet/Usb/CH376UsbHostHardware.cs b/dotNet/Usb/CH376UsbHostHardware.cs index 74aaab4..81ad606 100644 --- a/dotNet/Usb/CH376UsbHostHardware.cs +++ b/dotNet/Usb/CH376UsbHostHardware.cs @@ -30,6 +30,7 @@ public class CH376UsbHostHardware : IUsbHostHardware, IUsbHardwareShortcuts const byte CMD_RET_SUCCESS = 0x51; const byte CMD_RET_ABORT = 0x5F; + const byte CMD_TEST_CONNECT = 0x16; const byte CMD_DISK_CONNECT = 0x30; const byte CMD_DISK_MOUNT = 0x31; const byte CMD_DISK_CAPACITY = 0x3E; @@ -248,7 +249,7 @@ private UsbPacketResult WaitAndGetResult() if (result2 == 0x20) return UsbPacketResult.Timeout; - if(result >= 0x1D && Enum.IsDefined(typeof(UsbPacketResult), (int)result)) { + if(result >= 0x14 && Enum.IsDefined(typeof(UsbPacketResult), (int)result)) { return (UsbPacketResult)result; } @@ -343,16 +344,21 @@ public UsbTransferResult ClearEndpointHalt(int deviceAddress, byte endpointNumbe public string InitDisk() { - ch.WriteCommand(CMD_DISK_CONNECT); - var result = WaitAndGetResult(); - if (result != UsbPacketResult.Ok) - return null; + ch.WriteCommand(CMD_TEST_CONNECT); + byte status; + do + { + status = ch.ReadStatus(); + } while (status == 0); + var result = (UsbPacketResult)(status & 0x7F); // WaitAndGetResult(); + if (result == UsbPacketResult.NoDeviceConnected) + return "*** No device connected"; BusResetAndSetHostWithSofMode(); ch.WriteCommand(CMD_DISK_MOUNT); result = WaitAndGetResult(); if (result != UsbPacketResult.Ok) - return null; + return "*** No proper storage device connected"; var data = new byte[36]; ReadUsbData(data, 0); diff --git a/dotNet/Usb/UsbPacketResult.cs b/dotNet/Usb/UsbPacketResult.cs index c18e78b..e8f5d52 100644 --- a/dotNet/Usb/UsbPacketResult.cs +++ b/dotNet/Usb/UsbPacketResult.cs @@ -3,13 +3,13 @@ public enum UsbPacketResult { Ok, - Nak = 1, - Stall = 2, - Timeout = 3, - DataError = 4, - OtherError = 5, - NoDeviceConnected = 6, - NotImplemented = 7, + Nak, + Stall, + Timeout, + DataError, + OtherError, + NoDeviceConnected, + NotImplemented, USB_INT_SUCCESS = 0x14, USB_INT_CONNECT = 0x15, USB_INT_DISCONNECT = 0x16, From 8a14e3a65e35b8eb5cd9bab413877855f389cc4c Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 12 Jan 2021 22:24:46 +0100 Subject: [PATCH 04/65] First steps on the MSX side for the USB boot menu: Introduce routines (fake for now) to detect if a pendrive is inserted, show its name, and list files and directories. Show the frame of the boot menu. --- msx/bank0/kernel.asm | 4 +-- msx/bank1/boot_menu.asm | 42 ++++++++++++++++++++++++ msx/bank1/ch376.asm | 64 +++++++++++++++++++++++++++++++++++++ msx/bank1/inihrd_inienv.asm | 7 ++-- msx/bank1/verbose_reset.asm | 28 ++++++++++++++++ msx/config.asm | 3 -- msx/constants.asm | 6 ++++ msx/rookiefdd.asm | 2 ++ 8 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 msx/bank1/boot_menu.asm create mode 100644 msx/constants.asm diff --git a/msx/bank0/kernel.asm b/msx/bank0/kernel.asm index 228ad1b..646c03b 100644 --- a/msx/bank0/kernel.asm +++ b/msx/bank0/kernel.asm @@ -64,9 +64,9 @@ LDIRMV equ 00059H LDIRVM equ 0005CH CHSNS equ 0009CH CHGET equ 0009FH -CHPUT equ 000A2H +;CHPUT equ 000A2H LPTOUT equ 000A5H -BREAKX equ 000B7H +;BREAKX equ 000B7H CKCNTC equ 000BDH ERAFNK equ 000CCH TOTEXT equ 000D2H diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm new file mode 100644 index 0000000..5233aec --- /dev/null +++ b/msx/bank1/boot_menu.asm @@ -0,0 +1,42 @@ +DO_BOOT_MENU: + ld a,40 + ld (LINL40),a + call INITXT + + ld h,1 + ld l,2 + call POSIT + call _BM_DRAW_LINE + ld h,1 + ld l,23 + call POSIT + call _BM_DRAW_LINE + + ld h,1 + ld l,1 + call POSIT + ld a,"/" + call CHPUT + + ld h,1 + ld l,24 + call POSIT + ld hl,_BM_F1_HELP + call PRINT + +_BOOT_MENU_LOOP: + halt + call BREAKX + ret c + jr _BOOT_MENU_LOOP + +_BM_DRAW_LINE: + ld b,40 +_BM_DRAW_LINE_LOOP: + ld a,"-" + call CHPUT + djnz _BM_DRAW_LINE_LOOP + ret + +_BM_F1_HELP: + db "F1 = Help",0 \ No newline at end of file diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index 5995fe2..58459e9 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -96,6 +96,9 @@ CH_ST_RET_ABORT: equ 5Fh ; Output: Cy = 0 if hardware is operational, 1 if it's not HW_TEST: + or a + ret ;!!! + ld a,34h call _HW_TEST_DO scf @@ -499,6 +502,67 @@ _CH_DELAY_LOOP: ret +; ----------------------------------------------------------------------------- +; File management routines +; ----------------------------------------------------------------------------- + +; ----------------------------------------------------------------------------- +; HWF_MOUNT_DISK: Mounts a storage device if present. +; +; On success it also opens the root directory +; ----------------------------------------------------------------------------- +; Input: HL = address for the name of the device found +; Output: Cy = 0: ok +; 1: error, no device present or it's not a storage device + +HWF_MOUNT_DISK: + ex de,hl + ld hl,FAKE_DEV_NAME + ld bc,24 + ldir + xor a + ld (de),a + ret + +FAKE_DEV_NAME: + db "TheStorageThing 0.05" + +; ----------------------------------------------------------------------------- +; HWF_CHANGE_DIR: Enter a directory from the current one +; ----------------------------------------------------------------------------- +; Input: HL = Address of directory name, relative to current, +; can be ".." to go back to previous +; Output: A = 0: ok +; 1: directory not found +; 2: other error (e.g. no device found) + +HWF_CHANGE_DIR: + xor a + ret + + +; ----------------------------------------------------------------------------- +; HWF_ENUM_FILES: Enumerate files and directories in the current directory +; +; Files/directories whose first character is not a letter or a digit +; will be skipped. +; +; The name of each files/directory will be put at the specified address, +; sequentially and with no separators, as a fixed 11 bytes string in the +; same format as in the directory entry (e.g. "FILE EXT"); after the last +; entry a 0 byte will be placed. +; ----------------------------------------------------------------------------- +; Input: HL = Address of buffer to get file info into +; BC = Maximum number of files/directories to enumerate +; Output: Cy = 0: ok +; 1: error, no device present or it's not a storage device + +HWF_ENUM_FILES: + xor a + ld (hl),a + ret + + ; ----------------------------------------------------------------------------- ; Optional shortcut routines ; ----------------------------------------------------------------------------- diff --git a/msx/bank1/inihrd_inienv.asm b/msx/bank1/inihrd_inienv.asm index 50a003e..388384c 100644 --- a/msx/bank1/inihrd_inienv.asm +++ b/msx/bank1/inihrd_inienv.asm @@ -9,8 +9,6 @@ ; because we need to setup the work area during reset, but work area ; is zeroed by kernel between INIHRD and INIENV. -INITXT: equ 006Ch - ; ----------------------------------------------------------------------------- ; INIHRD @@ -48,4 +46,9 @@ INIENV_IMPL: DELAY_AFTER_PRINT: halt djnz DELAY_AFTER_PRINT + + call HWF_MOUNT_DISK + ret c + + call DO_BOOT_MENU ret diff --git a/msx/bank1/verbose_reset.asm b/msx/bank1/verbose_reset.asm index 7d46b2e..eb814a1 100644 --- a/msx/bank1/verbose_reset.asm +++ b/msx/bank1/verbose_reset.asm @@ -11,6 +11,32 @@ VERBOSE_RESET: ld hl,NOHARD_S jp c,PRINT + ld hl,0C000h + call HWF_MOUNT_DISK + jr c,_HW_RESET_NO_STOR + + ld hl,STOR_FOUND_S + call PRINT + ld hl,0C000h + ld b,0 + ;Print the device name, collapsing multiple spaces to a single one +_HW_RESET_PRINT: + ld a,(hl) + inc hl + or a + jr z,_HW_RESET_PRINT_END + cp ' ' + jr nz,_HW_RESET_PRINT_GO + cp b + jr z,_HW_RESET_PRINT +_HW_RESET_PRINT_GO: + ld b,a + call CHPUT + jr _HW_RESET_PRINT +_HW_RESET_PRINT_END: + ret + +_HW_RESET_NO_STOR: ld b,5 _HW_RESET_TRY: push bc @@ -242,3 +268,5 @@ DEVERR_S: ERR_INQUIRY_S: db "ERROR querying the device name: ",0 +STOR_FOUND_S: + db "USB storage device found:",13,10,0 diff --git a/msx/config.asm b/msx/config.asm index 904cb32..12639a6 100644 --- a/msx/config.asm +++ b/msx/config.asm @@ -69,6 +69,3 @@ USE_ASCII8_ROM_MAPPER: equ 0 ;Note that these refer to 16K banks, even in the case of using the ASCII8 mapper. ROM_BANK_0: equ 0 ROM_BANK_1: equ 1 - - - diff --git a/msx/constants.asm b/msx/constants.asm new file mode 100644 index 0000000..38c13a2 --- /dev/null +++ b/msx/constants.asm @@ -0,0 +1,6 @@ +INITXT: equ 006Ch +CHPUT: equ 00A2h +BREAKX: equ 00B7h +POSIT: equ 00C6h + +LINL40: equ 0F3AEH \ No newline at end of file diff --git a/msx/rookiefdd.asm b/msx/rookiefdd.asm index dd443be..661d019 100644 --- a/msx/rookiefdd.asm +++ b/msx/rookiefdd.asm @@ -10,6 +10,7 @@ CALL_IX: equ 7FD0h CALL_BANK: equ CALL_IX+2 + include "constants.asm" include "config.asm" include "usb_errors.asm" @@ -57,6 +58,7 @@ DEFDPB: include "bank1/work_area.asm" include "bank1/usb.asm" include "bank1/misc.asm" + include "bank1/boot_menu.asm" DEFDPB_1: include "defdpb.asm" From 924e4d1e062fbb8ef3f5e2801aa390668c75da83 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Wed, 13 Jan 2021 17:42:42 +0100 Subject: [PATCH 05/65] Implemented the help system. --- msx/bank1/boot_menu.asm | 176 +++++++++++++++++++++++++++++++++++++--- msx/constants.asm | 12 ++- 2 files changed, 175 insertions(+), 13 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 5233aec..0684d1d 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -6,11 +6,11 @@ DO_BOOT_MENU: ld h,1 ld l,2 call POSIT - call _BM_DRAW_LINE + call BM_DRAW_LINE ld h,1 ld l,23 call POSIT - call _BM_DRAW_LINE + call BM_DRAW_LINE ld h,1 ld l,1 @@ -18,19 +18,103 @@ DO_BOOT_MENU: ld a,"/" call CHPUT - ld h,1 - ld l,24 - call POSIT - ld hl,_BM_F1_HELP - call PRINT + ld hl,BM_F1_HELP + call BM_PRINT_STATUS -_BOOT_MENU_LOOP: +;--- Main loop + +BOOT_MENU_LOOP: halt call BREAKX ret c - jr _BOOT_MENU_LOOP -_BM_DRAW_LINE: + call BM_F1_IS_PRESSED + call z,BM_DO_HELP + + jr BOOT_MENU_LOOP + +;--- Help loop + +BM_DO_HELP: + call BM_CLEAR_INFO_AREA + + ld h,1 + ld l,4 + call POSIT + ld hl,BM_HELP_1 + call PRINT + + ld hl,BM_F1_NEXT + call BM_PRINT_STATUS + +_BM_HELP_LOOP1: + ;halt + call BM_F1_IS_PRESSED + jr nz,_BM_HELP_LOOP1 + + call BM_CLEAR_INFO_AREA + + ld h,1 + ld l,4 + call POSIT + ld hl,BM_HELP_2 + call PRINT + + ld hl,BM_F1_END + call BM_PRINT_STATUS + +_BM_HELP_LOOP2: + ;halt + call BM_F1_IS_PRESSED + jr nz,_BM_HELP_LOOP2 + + call BM_CLEAR_INFO_AREA + + ld hl,BM_F1_HELP + call BM_PRINT_STATUS + + ret + +;--- Clear the central information area + +BM_CLEAR_INFO_AREA: + ld h,1 + ld l,3 + call POSIT + ld b,20 +_BM_CLEAR_INFO_AREA_LOOP: + ld a,27 + call CHPUT + ld a,'K' + call CHPUT ;Delete to end of line + ld a,10 + call CHPUT + djnz _BM_CLEAR_INFO_AREA_LOOP + ret + +;--- Print something in the lower status line + +BM_PRINT_STATUS: + push hl + ld h,1 + ld l,24 + call POSIT + ld a,27 + call CHPUT + ld a,'K' + call CHPUT ;Delete to end of line + pop hl + jp PRINT + +;--- Check if F1 is pressed + +BM_F1_IS_PRESSED: + ld de,2006h + jp BM_KEY_CHECK + +;--- Draw a horizontal line of 40 hyphens + +BM_DRAW_LINE: ld b,40 _BM_DRAW_LINE_LOOP: ld a,"-" @@ -38,5 +122,73 @@ _BM_DRAW_LINE_LOOP: djnz _BM_DRAW_LINE_LOOP ret -_BM_F1_HELP: - db "F1 = Help",0 \ No newline at end of file +;--- Check if a key is pressed +;Input: D=column mask, E=row number +;Output: Z if pressed, NZ if not +BM_KEY_CHECK: + ld b,d + ld d,0 + ;ld hl,OLDKEY + ;add hl,de + ;ld a,(hl) + ;cpl + ;and b + ;ld c,a + ld hl,NEWKEY + add hl,de + ld a,(hl) + and b + ;or c + ret nz + +_BM_KEY_CHECK_WAIT_RELEASE: + halt + ld a,(hl) + and b + jr z,_BM_KEY_CHECK_WAIT_RELEASE + xor a + ret + +;--- Strings + +BM_F1_HELP: + db "F1 = Help",0 + +BM_F1_NEXT: + db "F1 = Next",0 + +BM_F1_END: + db "F1 = End",0 + +BM_HELP_1: + db "Cursors: select file or directory",13,10 + db 13,10 + db "SHIFT+Right/Left: Next/prev page",13,10 + db 13,10 + db "SHIFT+Up/Down: Up/down 10 pages",13,10 + db 13,10 + db "Enter (on file): Mount file and boot",13,10 + db 13,10 + db "Enter (on dir): Enter directory",13,10 + db 13,10 + db "SHIFT+Enter (on dir):",13,10 + db " Mount first file on dir and boot",13,10 + db 13,10 + db "BS: Back to parent directory",13,10 + db 13,10 + db "F5: Reset device and start over",13,10 + db 13,10 + db "CTRL+STOP: Exit without any mounting" + db 0 + +BM_HELP_2: + db "After boot it is possible to switch",13,10 + db "to another disk image file from the",13,10 + db "same directory (up to 36 files).",13,10 + db 13,10 + db "On disk access press the key for the",13,10 + db "file (1-0, A-Z), or press CODE/KANA",13,10 + db "and when CAPS blinks press the key." + db 0 + +_BM_VARS_BASE: equ 0E000h diff --git a/msx/constants.asm b/msx/constants.asm index 38c13a2..6ff98af 100644 --- a/msx/constants.asm +++ b/msx/constants.asm @@ -3,4 +3,14 @@ CHPUT: equ 00A2h BREAKX: equ 00B7h POSIT: equ 00C6h -LINL40: equ 0F3AEH \ No newline at end of file +LINL40: equ 0F3AEh +OLDKEY: equ 0FBDAh +NEWKEY: equ 0FBE5h + +;Keyboard matrix: +; bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 +;row 6 F3 F2 F1 CODE CAPS GRAPH CTRL SHIFT +;row 7 RET SELECT BS STOP TAB ESC F5 F4 +;row 8 Right Down Up Left DEL INS HOME SPACE +;row 9 NUM4 NUM3 NUM2 NUM1 NUM0 NUM/ NUM+ NUM* +;row 10 NUM. NUM, NUM- NUM9 NUM8 NUM7 NUM6 NUM5 From 99315bf898dc99bba48bcd8f90ee57266f3b3216 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 14 Jan 2021 17:24:49 +0100 Subject: [PATCH 06/65] Additions to the MSX USB boot menu: - HWF_ENUM_FILES implemented (generates fake filenames) - The files list is displayed in the boot menu (no paging yet) --- msx/bank1/boot_menu.asm | 96 +++++++++++++++++++++++++++++++++++++++++ msx/bank1/ch376.asm | 78 ++++++++++++++++++++++++++++++++- 2 files changed, 173 insertions(+), 1 deletion(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 0684d1d..5e03b48 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -21,6 +21,13 @@ DO_BOOT_MENU: ld hl,BM_F1_HELP call BM_PRINT_STATUS + ld hl,0C000h + ld bc,25 + call HWF_ENUM_FILES + + ld hl,0C000h + call BM_PRINT_FILENAMES_PAGE + ;--- Main loop BOOT_MENU_LOOP: @@ -70,17 +77,106 @@ _BM_HELP_LOOP2: call BM_CLEAR_INFO_AREA + ld hl,0C000h + call BM_PRINT_FILENAMES_PAGE + ld hl,BM_F1_HELP call BM_PRINT_STATUS ret + +;--- Print a screen full of filenames +; Input: HL = Pointer to first filename + +BM_PRINT_FILENAMES_PAGE: + call BM_CLEAR_INFO_AREA + + ld b,2 ;X coordinate +_BM_PRINT_FILENAMES_COLUMN: + ld c,3 ;Y coordinate + + push hl + ld h,b + ld l,c + call POSIT + pop hl + +_BM_PRINT_FILENAMES_COLUMN_LOOP: + ld a,(hl) + or a + ret z ;End of the files list reached + + push bc + call BM_PRINT_FILENAME + pop bc + inc c + ld a,c + cp 23 + jr nc,_BM_PRINT_FILENAMES_COLUMN_END + + push hl + ld h,b + ld l,c + call POSIT + pop hl + + jr _BM_PRINT_FILENAMES_COLUMN_LOOP + +_BM_PRINT_FILENAMES_COLUMN_END: + ld a,b + add 13 + ld b,a + cp 37 + jr c,_BM_PRINT_FILENAMES_COLUMN + + ret + + +;--- Print a fixed 11 chars file name in the current position +; Input: HL = Filename +; Output: HL = Past the filename + +BM_PRINT_FILENAME: + ld b,8 +_BM_PRINT_FILENAME_MAIN: + ld a,(hl) + inc hl + cp ' ' + call nz,CHPUT + djnz _BM_PRINT_FILENAME_MAIN + + ld a,(hl) + cp ' ' + ld b,3 + jr z,_BM_PRINT_FILENAME_EXT + ld a,'.' + call CHPUT +_BM_PRINT_FILENAME_EXT: + ld a,(hl) + inc hl + and 7Fh + cp ' ' + call nz,CHPUT + djnz _BM_PRINT_FILENAME_EXT + + dec hl + ld a,(hl) + inc hl + and 80h + ret z + ld a,'/' + jp CHPUT + + ;--- Clear the central information area BM_CLEAR_INFO_AREA: + push hl ld h,1 ld l,3 call POSIT + pop hl ld b,20 _BM_CLEAR_INFO_AREA_LOOP: ld a,27 diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index 58459e9..a22108a 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -558,10 +558,86 @@ HWF_CHANGE_DIR: ; 1: error, no device present or it's not a storage device HWF_ENUM_FILES: + ld de,0 + push hl + pop ix +_HWF_ENUM_FILES_LOOP: + push bc + push de + + push ix + pop de + + ld hl,FILE_S + ld bc,3 + ldir + + pop hl + push hl + call Num2Hex + + ld a,' ' + ld (de),a + inc de + + ld hl,EXT_S + ld bc,3 + ldir + + push de + pop ix + + pop de + inc de + + ld a,e + and 15 + jr nz,_HWF_ENUM_FILES_NODIR + ld (ix-4),' ' + ld (ix-3),' ' + ld (ix-2),' ' + ld (ix-1),128 +_HWF_ENUM_FILES_NODIR: + + pop bc + dec bc + ld a,b + or c + jr nz,_HWF_ENUM_FILES_LOOP + xor a - ld (hl),a + ld (ix),a ret +FILE_S: db "FIL" +EXT_S: db "EXT" + +;Input: HL = number to convert +; DE = location of ASCII string +Num2Hex: + ld a,h + call Num1 + ld a,h + call Num2 + ld a,l + call Num1 + ld a,l + jr Num2 + +Num1: + rra + rra + rra + rra +Num2: + or 0F0h + daa + add a,0A0h + adc a,040h + + ld (de),a + inc de + ret ; ----------------------------------------------------------------------------- ; Optional shortcut routines From a0b3e6fadc35ab4fbf23eccf2595a817a03e173b Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 15 Jan 2021 17:07:27 +0100 Subject: [PATCH 07/65] Paging and page navigation implemented in the USB boot menu. --- msx/bank1/boot_menu.asm | 333 +++++++++++++++++++++++++++++++++++----- msx/bank1/ch376.asm | 7 + 2 files changed, 303 insertions(+), 37 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 5e03b48..7dfd2d0 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -1,3 +1,5 @@ +BM_FILES_BASE: equ 8000h + DO_BOOT_MENU: ld a,40 ld (LINL40),a @@ -12,20 +14,58 @@ DO_BOOT_MENU: call POSIT call BM_DRAW_LINE - ld h,1 + ld h,2 ld l,1 call POSIT ld a,"/" call CHPUT - ld hl,BM_F1_HELP + ld hl,BM_SCANNING_DIR_S call BM_PRINT_STATUS - ld hl,0C000h - ld bc,25 + ld hl,BM_FILES_BASE + ld bc,1300 call HWF_ENUM_FILES - ld hl,0C000h + ld a,1 + ld (BM_CUR_PAGE),a + + ld (BM_NUM_FILES),bc + push bc + pop hl + ld b,0 +_BM_CALC_NUM_PAGES: + ld a,h + or a + jr nz,_BM_CALC_NUM_PAGES_ADD + ld a,l + or a + jr z,_BM_CALC_NUM_PAGES_END + cp 60 + jr nc,_BM_CALC_NUM_PAGES_ADD + + inc b + jr _BM_CALC_NUM_PAGES_END + +_BM_CALC_NUM_PAGES_ADD: + inc b + ld de,60 + or a + sbc hl,de + jr _BM_CALC_NUM_PAGES + +_BM_CALC_NUM_PAGES_END: + ld a,b + or a + jr nz,_BM_CALC_NUM_PAGES_END_2 + inc a +_BM_CALC_NUM_PAGES_END_2: + ld (BM_NUM_PAGES),a + +BM_ENTER_MAIN_LOOP: + call BM_CLEAR_INFO_AREA + call BM_PRINT_MAIN_STATUS + call BM_PRINT_FILENAMES_PAGE ;--- Main loop @@ -36,7 +76,11 @@ BOOT_MENU_LOOP: ret c call BM_F1_IS_PRESSED - call z,BM_DO_HELP + jp z,BM_DO_HELP + + call BM_CURSOR_IS_PRESSED + bit 7,a + jp nz,BM_UPDATE_PAGE jr BOOT_MENU_LOOP @@ -75,21 +119,97 @@ _BM_HELP_LOOP2: call BM_F1_IS_PRESSED jr nz,_BM_HELP_LOOP2 - call BM_CLEAR_INFO_AREA + jp BM_ENTER_MAIN_LOOP - ld hl,0C000h - call BM_PRINT_FILENAMES_PAGE +;--- Update current page on cursor press +; Input: A = pressed cursor key - ld hl,BM_F1_HELP - call BM_PRINT_STATUS +BM_UPDATE_PAGE: + and 7Fh + dec a + jr z,_BM_NEXT_10_PAGES + dec a + jr z,_BM_NEXT_PAGE + dec a + jr z,_BM_PREV_10_PAGES + dec a + jr z,_BM_PREV_PAGE + jp BOOT_MENU_LOOP + +_BM_NEXT_PAGE: + ld a,(BM_NUM_PAGES) + ld b,a + ld a,(BM_CUR_PAGE) + cp b + jp z,BOOT_MENU_LOOP - ret + inc a + ld (BM_CUR_PAGE),a + jp BM_ENTER_MAIN_LOOP +_BM_NEXT_10_PAGES: + ld a,(BM_NUM_PAGES) + ld b,a + ld a,(BM_CUR_PAGE) + cp b + jp nc,BOOT_MENU_LOOP + inc b + add 10 + cp b + jr c,_BM_NEXT_10_PAGES_GO + ld a,(BM_NUM_PAGES) + +_BM_NEXT_10_PAGES_GO: + ld (BM_CUR_PAGE),a + jp BM_ENTER_MAIN_LOOP + +_BM_PREV_PAGE: + ld a,(BM_CUR_PAGE) + cp 1 + jp z,BOOT_MENU_LOOP + + dec a + ld (BM_CUR_PAGE),a + jp BM_ENTER_MAIN_LOOP + +_BM_PREV_10_PAGES: + ld a,(BM_CUR_PAGE) + cp 1 + jp z,BOOT_MENU_LOOP + sub 10 + jr z,_BM_PREV_10_PAGES_1 + jp p,_BM_PREV_10_PAGES_GO +_BM_PREV_10_PAGES_1: + ld a,1 + +_BM_PREV_10_PAGES_GO: + ld (BM_CUR_PAGE),a + jp BM_ENTER_MAIN_LOOP ;--- Print a screen full of filenames -; Input: HL = Pointer to first filename +; Input: A = Page number BM_PRINT_FILENAMES_PAGE: + ld hl,(BM_NUM_FILES) + ld a,h + or l + jp nz,_BM_PRINT_FILENAMES_PAGE_GO + + ld h,3 + ld l,12 + call POSIT + ld hl,BM_NO_FILES_S + jp PRINT + +_BM_PRINT_FILENAMES_PAGE_GO: + ld a,(BM_CUR_PAGE) + ld b,a + ld hl,BM_FILES_BASE-11*60 + ld de,11*60 +_BM_PRINT_FILENAMES_CALC: + add hl,de + djnz _BM_PRINT_FILENAMES_CALC + call BM_CLEAR_INFO_AREA ld b,2 ;X coordinate @@ -192,7 +312,7 @@ _BM_CLEAR_INFO_AREA_LOOP: BM_PRINT_STATUS: push hl - ld h,1 + ld h,2 ld l,24 call POSIT ld a,27 @@ -202,12 +322,89 @@ BM_PRINT_STATUS: pop hl jp PRINT +;--- Print the main lower status line + +BM_PRINT_MAIN_STATUS: + ld hl,BM_F1_HELP + call BM_PRINT_STATUS + +BM_PRINT_PAGE_NUM: + ld h,28 + ld l,24 + call POSIT + ld hl,BM_PAGE_S + call PRINT + + ld a,(BM_CUR_PAGE) + call BM_PRINT_BYTE + ld hl,BM_SPACE_AND_BAR + call PRINT + ld a,(BM_NUM_PAGES) + jp BM_PRINT_BYTE + +BM_PRINT_BYTE: + ld ix,BM_BUF + call BYTE2ASC + ld (ix),0 + ld hl,BM_BUF + jp PRINT + ;--- Check if F1 is pressed BM_F1_IS_PRESSED: ld de,2006h jp BM_KEY_CHECK +;--- Check if a cursor key is pressed +; Output: A=0: no +; 1,2,3,4: up,right,down,left +; Bit 7 set if SHIFT is pressed too + +BM_CURSOR_IS_PRESSED: + ld hl,NEWKEY + ld de,8 + add hl,de + ld a,(hl) + + rlca + ld b,2 + jr nc,_BM_CURSOR_IS_PRESSED_END + rlca + ld b,3 + jr nc,_BM_CURSOR_IS_PRESSED_END + rlca + ld b,1 + jr nc,_BM_CURSOR_IS_PRESSED_END + rlca + ld b,4 + jr nc,_BM_CURSOR_IS_PRESSED_END + + xor a + ret + +_BM_CURSOR_IS_PRESSED_END: + dec hl + dec hl ;Row 6 + ld a,(hl) + cpl + rrca + and 80h + or b + push af + inc hl + inc hl + +_BM_CURSOR_WAIT_RELEASE: + halt + ld a,(hl) + cpl + and 11110000b + jr z,_BM_CURSOR_WAIT_RELEASE + + pop af + ret + + ;--- Draw a horizontal line of 40 hyphens BM_DRAW_LINE: @@ -224,17 +421,10 @@ _BM_DRAW_LINE_LOOP: BM_KEY_CHECK: ld b,d ld d,0 - ;ld hl,OLDKEY - ;add hl,de - ;ld a,(hl) - ;cpl - ;and b - ;ld c,a ld hl,NEWKEY add hl,de ld a,(hl) and b - ;or c ret nz _BM_KEY_CHECK_WAIT_RELEASE: @@ -245,6 +435,56 @@ _BM_KEY_CHECK_WAIT_RELEASE: xor a ret +;--- Convert a 1-byte number to an unterminated ASCII string +; Input: A = Number to convert +; IX = Destination address for the string +; Output: IX points after the string +; Modifies: AF, C + +BYTE2ASC: cp 10 + jr c,B2A_1D + cp 100 + jr c,B2A_2D + cp 200 + jr c,B2A_1XX + jr B2A_2XX + + ; One digit + +B2A_1D: add "0" + ld (ix),a + inc ix + ret + + ; Two digits + +B2A_2D: ld c,"0" +B2A_2D2: inc c + sub 10 + cp 10 + jr nc,B2A_2D2 + + ld (ix),c + inc ix + jr B2A_1D + + ; Between 100 and 199 + +B2A_1XX: ld (ix),"1" + sub 100 +B2A_XXX: inc ix + cp 10 + jr nc,B2A_2D ;If 1XY with X>0 + ld (ix),"0" ;If 10Y + inc ix + jr B2A_1D + + ;--- Between 200 and 255 + +B2A_2XX: ld (ix),"2" + sub 200 + jr B2A_XXX + ;--- Strings BM_F1_HELP: @@ -256,35 +496,54 @@ BM_F1_NEXT: BM_F1_END: db "F1 = End",0 +BM_PAGE_S: + db "Page ",0 + +BM_SPACE_AND_BAR: + db " / ",0 + +BM_NO_FILES_S: + db "No files found in current directory!",0 + +BM_SCANNING_DIR_S: + db "Scanning directory...",0 + BM_HELP_1: - db "Cursors: select file or directory",13,10 + db " Cursors: select file or directory",13,10 db 13,10 - db "SHIFT+Right/Left: Next/prev page",13,10 + db " SHIFT+Right/Left: Next/prev page",13,10 db 13,10 - db "SHIFT+Up/Down: Up/down 10 pages",13,10 + db " SHIFT+Up/Down: Up/down 10 pages",13,10 db 13,10 - db "Enter (on file): Mount file and boot",13,10 + db " Enter (on file): Mount file and boot",13,10 db 13,10 - db "Enter (on dir): Enter directory",13,10 + db " Enter (on dir): Enter directory",13,10 db 13,10 - db "SHIFT+Enter (on dir):",13,10 - db " Mount first file on dir and boot",13,10 + db " SHIFT+Enter (on dir):",13,10 + db " Mount first file on dir and boot",13,10 db 13,10 - db "BS: Back to parent directory",13,10 + db " BS: Back to parent directory",13,10 db 13,10 - db "F5: Reset device and start over",13,10 + db " F5: Reset device and start over",13,10 db 13,10 - db "CTRL+STOP: Exit without any mounting" + db " CTRL+STOP: Exit without any mounting" db 0 BM_HELP_2: - db "After boot it is possible to switch",13,10 - db "to another disk image file from the",13,10 - db "same directory (up to 36 files).",13,10 + db " After boot it is possible to switch",13,10 + db " to another disk image file from the",13,10 + db " same directory (up to 36 files).",13,10 db 13,10 - db "On disk access press the key for the",13,10 - db "file (1-0, A-Z), or press CODE/KANA",13,10 - db "and when CAPS blinks press the key." + db " On disk access press the key for the",13,10 + db " file (1-0, A-Z), or press CODE/KANA",13,10 + db " and when CAPS blinks press the key." db 0 + ;--- Variable definition + _BM_VARS_BASE: equ 0E000h + +BM_NUM_PAGES: equ _BM_VARS_BASE +BM_CUR_PAGE: equ BM_NUM_PAGES+1 +BM_NUM_FILES: equ BM_CUR_PAGE+1 +BM_BUF: equ BM_NUM_FILES+2 diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index a22108a..d0970ec 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -556,8 +556,15 @@ HWF_CHANGE_DIR: ; BC = Maximum number of files/directories to enumerate ; Output: Cy = 0: ok ; 1: error, no device present or it's not a storage device +; BC = Number of filenames found (if no error) HWF_ENUM_FILES: + push bc + call _HWF_ENUM_FILES + pop bc + ret + +_HWF_ENUM_FILES: ld de,0 push hl pop ix From cbc4f56c1288671e7d8bab4d9c30522bd3a29292 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 15 Jan 2021 17:25:13 +0100 Subject: [PATCH 08/65] Some code reorganization on the USB boot menu. --- msx/bank1/boot_menu.asm | 207 +++++++++++++++++++++------------------- msx/bank1/misc.asm | 57 ++++++++++- 2 files changed, 165 insertions(+), 99 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 7dfd2d0..808f755 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -1,6 +1,21 @@ +; Rookie Drive USB FDD BIOS +; By Konamiman, 2018 +; +; This file contains the code for the boot menu that displays +; a navigable list of disk image files (available only when a +; standard USB mass storage device is plugged in). + BM_FILES_BASE: equ 8000h + +; ----------------------------------------------------------------------------- +; Boot menu entry point +; ----------------------------------------------------------------------------- + DO_BOOT_MENU: + + ; Init screen mode, draw fixed elements + ld a,40 ld (LINL40),a call INITXT @@ -20,6 +35,8 @@ DO_BOOT_MENU: ld a,"/" call CHPUT + ; Enumerate files, initialize paging + ld hl,BM_SCANNING_DIR_S call BM_PRINT_STATUS @@ -62,15 +79,23 @@ _BM_CALC_NUM_PAGES_END: _BM_CALC_NUM_PAGES_END_2: ld (BM_NUM_PAGES),a + +; ----------------------------------------------------------------------------- +; Main key scanning loop +; ----------------------------------------------------------------------------- + + +;--- This entry point redraws the screen + BM_ENTER_MAIN_LOOP: call BM_CLEAR_INFO_AREA call BM_PRINT_MAIN_STATUS call BM_PRINT_FILENAMES_PAGE -;--- Main loop +;--- This is the actual start of the loop -BOOT_MENU_LOOP: +_BM_MAIN_LOOP: halt call BREAKX ret c @@ -82,9 +107,18 @@ BOOT_MENU_LOOP: bit 7,a jp nz,BM_UPDATE_PAGE - jr BOOT_MENU_LOOP + jr _BM_MAIN_LOOP + + +; ----------------------------------------------------------------------------- +; Key press handlers +; +; These are JP-ed in, so they must finish by JP-ing to +; either BM_ENTER_MAIN_LOOP or _BM_MAIN_LOOP. +; ----------------------------------------------------------------------------- -;--- Help loop + +;--- Help loop, entered when F1 is pressed BM_DO_HELP: call BM_CLEAR_INFO_AREA @@ -99,7 +133,7 @@ BM_DO_HELP: call BM_PRINT_STATUS _BM_HELP_LOOP1: - ;halt + halt call BM_F1_IS_PRESSED jr nz,_BM_HELP_LOOP1 @@ -115,12 +149,13 @@ _BM_HELP_LOOP1: call BM_PRINT_STATUS _BM_HELP_LOOP2: - ;halt + halt call BM_F1_IS_PRESSED jr nz,_BM_HELP_LOOP2 jp BM_ENTER_MAIN_LOOP + ;--- Update current page on cursor press ; Input: A = pressed cursor key @@ -134,14 +169,14 @@ BM_UPDATE_PAGE: jr z,_BM_PREV_10_PAGES dec a jr z,_BM_PREV_PAGE - jp BOOT_MENU_LOOP + jp _BM_MAIN_LOOP _BM_NEXT_PAGE: ld a,(BM_NUM_PAGES) ld b,a ld a,(BM_CUR_PAGE) cp b - jp z,BOOT_MENU_LOOP + jp z,_BM_MAIN_LOOP inc a ld (BM_CUR_PAGE),a @@ -152,7 +187,7 @@ _BM_NEXT_10_PAGES: ld b,a ld a,(BM_CUR_PAGE) cp b - jp nc,BOOT_MENU_LOOP + jp nc,_BM_MAIN_LOOP inc b add 10 cp b @@ -166,7 +201,7 @@ _BM_NEXT_10_PAGES_GO: _BM_PREV_PAGE: ld a,(BM_CUR_PAGE) cp 1 - jp z,BOOT_MENU_LOOP + jp z,_BM_MAIN_LOOP dec a ld (BM_CUR_PAGE),a @@ -175,7 +210,7 @@ _BM_PREV_PAGE: _BM_PREV_10_PAGES: ld a,(BM_CUR_PAGE) cp 1 - jp z,BOOT_MENU_LOOP + jp z,_BM_MAIN_LOOP sub 10 jr z,_BM_PREV_10_PAGES_1 jp p,_BM_PREV_10_PAGES_GO @@ -186,8 +221,13 @@ _BM_PREV_10_PAGES_GO: ld (BM_CUR_PAGE),a jp BM_ENTER_MAIN_LOOP -;--- Print a screen full of filenames -; Input: A = Page number + +; ----------------------------------------------------------------------------- +; Screen printing routines +; ----------------------------------------------------------------------------- + + +;--- Print the filenames for the current page BM_PRINT_FILENAMES_PAGE: ld hl,(BM_NUM_FILES) @@ -253,9 +293,10 @@ _BM_PRINT_FILENAMES_COLUMN_END: ret -;--- Print a fixed 11 chars file name in the current position -; Input: HL = Filename -; Output: HL = Past the filename +;--- Print a formatted file name in the current position +; Input: HL = Pointer to filename in directory entry format +; (11 chars, name and extensionpadded with spaces) +; Output: HL = Points past the filename BM_PRINT_FILENAME: ld b,8 @@ -308,7 +349,9 @@ _BM_CLEAR_INFO_AREA_LOOP: djnz _BM_CLEAR_INFO_AREA_LOOP ret + ;--- Print something in the lower status line +; Input: HL = Pointer to string to print BM_PRINT_STATUS: push hl @@ -322,7 +365,9 @@ BM_PRINT_STATUS: pop hl jp PRINT + ;--- Print the main lower status line +; ("F1=HELP" and current page number) BM_PRINT_MAIN_STATUS: ld hl,BM_F1_HELP @@ -349,14 +394,55 @@ BM_PRINT_BYTE: ld hl,BM_BUF jp PRINT + +;--- Draw a horizontal line of 40 hyphens in the current cursor location + +BM_DRAW_LINE: + ld b,40 +_BM_DRAW_LINE_LOOP: + ld a,"-" + call CHPUT + djnz _BM_DRAW_LINE_LOOP + ret + + +; ----------------------------------------------------------------------------- +; Keyboard scanning routines +; ----------------------------------------------------------------------------- + +;--- Check if a key is pressed +; Input: D = Keyboard matrix column mask, desired key set to 1 +; E = Keyboard matrix row number +; Output: Z if key is pressed, NZ if not + +BM_KEY_CHECK: + ld b,d + ld d,0 + ld hl,NEWKEY + add hl,de + ld a,(hl) + and b + ret nz + +_BM_KEY_CHECK_WAIT_RELEASE: + halt + ld a,(hl) + and b + jr z,_BM_KEY_CHECK_WAIT_RELEASE + xor a + ret + + ;--- Check if F1 is pressed +; Output: Z if pressed, NZ if not BM_F1_IS_PRESSED: ld de,2006h jp BM_KEY_CHECK + ;--- Check if a cursor key is pressed -; Output: A=0: no +; Output: A=0: no cursor key is pressed ; 1,2,3,4: up,right,down,left ; Bit 7 set if SHIFT is pressed too @@ -405,85 +491,9 @@ _BM_CURSOR_WAIT_RELEASE: ret -;--- Draw a horizontal line of 40 hyphens - -BM_DRAW_LINE: - ld b,40 -_BM_DRAW_LINE_LOOP: - ld a,"-" - call CHPUT - djnz _BM_DRAW_LINE_LOOP - ret - -;--- Check if a key is pressed -;Input: D=column mask, E=row number -;Output: Z if pressed, NZ if not -BM_KEY_CHECK: - ld b,d - ld d,0 - ld hl,NEWKEY - add hl,de - ld a,(hl) - and b - ret nz - -_BM_KEY_CHECK_WAIT_RELEASE: - halt - ld a,(hl) - and b - jr z,_BM_KEY_CHECK_WAIT_RELEASE - xor a - ret - -;--- Convert a 1-byte number to an unterminated ASCII string -; Input: A = Number to convert -; IX = Destination address for the string -; Output: IX points after the string -; Modifies: AF, C - -BYTE2ASC: cp 10 - jr c,B2A_1D - cp 100 - jr c,B2A_2D - cp 200 - jr c,B2A_1XX - jr B2A_2XX - - ; One digit - -B2A_1D: add "0" - ld (ix),a - inc ix - ret - - ; Two digits - -B2A_2D: ld c,"0" -B2A_2D2: inc c - sub 10 - cp 10 - jr nc,B2A_2D2 - - ld (ix),c - inc ix - jr B2A_1D - - ; Between 100 and 199 - -B2A_1XX: ld (ix),"1" - sub 100 -B2A_XXX: inc ix - cp 10 - jr nc,B2A_2D ;If 1XY with X>0 - ld (ix),"0" ;If 10Y - inc ix - jr B2A_1D - - ;--- Between 200 and 255 - -B2A_2XX: ld (ix),"2" - sub 200 - jr B2A_XXX +; ----------------------------------------------------------------------------- +; Text strings +; ----------------------------------------------------------------------------- ;--- Strings @@ -539,7 +549,10 @@ BM_HELP_2: db " and when CAPS blinks press the key." db 0 - ;--- Variable definition + +; ----------------------------------------------------------------------------- +; Variables +; ----------------------------------------------------------------------------- _BM_VARS_BASE: equ 0E000h diff --git a/msx/bank1/misc.asm b/msx/bank1/misc.asm index 5516808..326a544 100644 --- a/msx/bank1/misc.asm +++ b/msx/bank1/misc.asm @@ -178,7 +178,60 @@ DO_SNSMAT: ; ----------------------------------------------------------------------------- -; SNSMAT: Print a string describing an USB error code +; BYTE2ASC: Convert a byte to ASCII +; ----------------------------------------------------------------------------- +; Input: A = Number to convert +; IX = Destination address for the string +; Output: IX points after the string +; Modifies: AF, C ; ----------------------------------------------------------------------------- - +;--- Convert a 1-byte number to an unterminated ASCII string +; Input: A = Number to convert +; IX = Destination address for the string +; Output: IX points after the string +; Modifies: AF, C + +BYTE2ASC: cp 10 + jr c,B2A_1D + cp 100 + jr c,B2A_2D + cp 200 + jr c,B2A_1XX + jr B2A_2XX + + ; One digit + +B2A_1D: add "0" + ld (ix),a + inc ix + ret + + ; Two digits + +B2A_2D: ld c,"0" +B2A_2D2: inc c + sub 10 + cp 10 + jr nc,B2A_2D2 + + ld (ix),c + inc ix + jr B2A_1D + + ; Between 100 and 199 + +B2A_1XX: ld (ix),"1" + sub 100 +B2A_XXX: inc ix + cp 10 + jr nc,B2A_2D ;If 1XY with X>0 + ld (ix),"0" ;If 10Y + inc ix + jr B2A_1D + + ;--- Between 200 and 255 + +B2A_2XX: ld (ix),"2" + sub 200 + jr B2A_XXX From a18998fe0f60c34eea9521f638c90bce5984f5cc Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sat, 16 Jan 2021 23:15:55 +0100 Subject: [PATCH 09/65] Implemented the cursor file navigation in the USB boot menu. For now the selected file is just printed in lowercase. --- msx/bank1/boot_menu.asm | 315 ++++++++++++++++++++++++++++++++++++++-- msx/bank1/ch376.asm | 5 +- 2 files changed, 304 insertions(+), 16 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 808f755..96e0da0 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -37,18 +37,25 @@ DO_BOOT_MENU: ; Enumerate files, initialize paging + ld a,1 + ld (BM_CUR_PAGE),a + ld hl,BM_SCANNING_DIR_S call BM_PRINT_STATUS ld hl,BM_FILES_BASE - ld bc,1300 + ld bc,1290 call HWF_ENUM_FILES - - ld a,1 - ld (BM_CUR_PAGE),a - ld (BM_NUM_FILES),bc push bc + + push hl + pop de + inc de + ld (hl),0 + ld bc,59*11-1 + ldir + pop hl ld b,0 _BM_CALC_NUM_PAGES: @@ -92,6 +99,13 @@ BM_ENTER_MAIN_LOOP: call BM_PRINT_MAIN_STATUS call BM_PRINT_FILENAMES_PAGE + call BM_UPDATE_CUR_PAGE_PNT + xor a + ld (BM_CUR_ROW),a + ld (BM_CUR_COL),a + call BM_UPDATE_CUR_FILE_PNT + call BM_POSIT_CUR_FILE + call BM_PRINT_CURRENT_FILE_AS_SELECTED ;--- This is the actual start of the loop @@ -104,10 +118,12 @@ _BM_MAIN_LOOP: jp z,BM_DO_HELP call BM_CURSOR_IS_PRESSED + or a + jr z,_BM_MAIN_LOOP bit 7,a - jp nz,BM_UPDATE_PAGE - - jr _BM_MAIN_LOOP + jp z,BM_UPDATE_CUR_FILE + and 7Fh + jp BM_UPDATE_PAGE ; ----------------------------------------------------------------------------- @@ -156,11 +172,87 @@ _BM_HELP_LOOP2: jp BM_ENTER_MAIN_LOOP -;--- Update current page on cursor press +;--- Update currently pointed file on cursor press +; Input: A = pressed cursor key + +BM_UPDATE_CUR_FILE: + push af + call BM_POSIT_CUR_FILE + call BM_PRINT_CURRENT_FILE + pop af + + dec a + jr z,_BM_FILE_UP + dec a + jr z,_BM_FILE_RIGHT + dec a + jr z,_BM_FILE_DOWN + +_BM_FILE_LEFT: + ld a,(BM_CUR_COL) + dec a + cp 0FFh + jr nz,_BM_UPDATE_CUR_COL_GO + ld a,2 + jr _BM_UPDATE_CUR_COL_GO + +_BM_FILE_RIGHT: + ld a,(BM_CUR_COL) + inc a + cp 3 + jr c,_BM_UPDATE_CUR_COL_GO + xor a + jr _BM_UPDATE_CUR_COL_GO + +_BM_FILE_UP: + ld a,(BM_CUR_ROW) + dec a + cp 0FFh + jr nz,_BM_UPDATE_CUR_ROW_GO + ld a,19 + jr _BM_UPDATE_CUR_ROW_GO + +_BM_FILE_DOWN: + ld a,(BM_CUR_ROW) + inc a + cp 20 + jr c,_BM_UPDATE_CUR_ROW_GO + xor a + jr _BM_UPDATE_CUR_ROW_GO + +_BM_UPDATE_CUR_COL_GO: + ld (BM_CUR_COL),a + ld hl,BM_CUR_COL + ld (BM_BUF),hl + jr _BM_UPDATE_CUR_ROWCOL_GO + +_BM_UPDATE_CUR_ROW_GO: + ld (BM_CUR_ROW),a + ld hl,BM_CUR_ROW + ld (BM_BUF),hl + +_BM_UPDATE_CUR_ROWCOL_GO: + call BM_UPDATE_CUR_FILE_PNT + ld hl,(BM_CUR_FILE_PNT) + ld a,(hl) + or a + jr nz,_BM_UPDATE_CUR_ROWCOL_GO_2 + ;We ended up pointing past the end of the list, + ;so reset column/row to 0 + ld hl,(BM_BUF) + ld (hl),0 + call BM_UPDATE_CUR_FILE_PNT + +_BM_UPDATE_CUR_ROWCOL_GO_2: + call BM_POSIT_CUR_FILE + call BM_PRINT_CURRENT_FILE_AS_SELECTED + jp _BM_MAIN_LOOP + + +;--- Update current page on cursor+SHIFT press ; Input: A = pressed cursor key BM_UPDATE_PAGE: - and 7Fh dec a jr z,_BM_NEXT_10_PAGES dec a @@ -293,18 +385,40 @@ _BM_PRINT_FILENAMES_COLUMN_END: ret +;--- Generate a formatted file name from one in dir entry format +; Input: HL = Pointer to filename in directory entry format +; (11 chars, name and extension padded with spaces) +; DE = Destination buffer for the formatted file name +; Output: HL = Points past the filename +; C = Length of the formatted file name + +BM_GENERATE_FILENAME: + ld ix,_BM_DO_LD_DE + ld c,0 + call _BM_PRINTPUT_FILENAME + xor a + ld (de),a + ret + + ;--- Print a formatted file name in the current position ; Input: HL = Pointer to filename in directory entry format -; (11 chars, name and extensionpadded with spaces) +; (11 chars, name and extension padded with spaces) ; Output: HL = Points past the filename +; C = Length of the printed file name BM_PRINT_FILENAME: + ld ix,_BM_DO_CHPUT + + +_BM_PRINTPUT_FILENAME: ld b,8 + ld c,0 _BM_PRINT_FILENAME_MAIN: ld a,(hl) inc hl cp ' ' - call nz,CHPUT + call nz,CALL_IX djnz _BM_PRINT_FILENAME_MAIN ld a,(hl) @@ -312,13 +426,13 @@ _BM_PRINT_FILENAME_MAIN: ld b,3 jr z,_BM_PRINT_FILENAME_EXT ld a,'.' - call CHPUT + call CALL_IX _BM_PRINT_FILENAME_EXT: ld a,(hl) inc hl and 7Fh cp ' ' - call nz,CHPUT + call nz,CALL_IX djnz _BM_PRINT_FILENAME_EXT dec hl @@ -327,8 +441,18 @@ _BM_PRINT_FILENAME_EXT: and 80h ret z ld a,'/' + jp CALL_IX + +_BM_DO_CHPUT: + inc c jp CHPUT +_BM_DO_LD_DE: + ld (de),a + inc de + inc c + ret + ;--- Clear the central information area @@ -406,6 +530,67 @@ _BM_DRAW_LINE_LOOP: ret +;--- Position the cursor for the current file: +; col = (BM_CUR_COL*13)+2 +; row = BM_CUR_ROW+3 + +BM_POSIT_CUR_FILE: + ld a,(BM_CUR_COL) + ld b,a + sla a + sla a + sla a ;*8 + add b + add b + add b + add b + add b ;*13 + inc a + inc a + ld h,a + ld a,(BM_CUR_ROW) + add 3 + ld l,a + jp POSIT + + +;--- Print the current filename at the current position + +BM_PRINT_CURRENT_FILE: + ld hl,(BM_CUR_FILE_PNT) + call BM_PRINT_FILENAME + ld b,' ' +_BM_PRINT_CURRENT_FILE_PAD: + ld a,c + cp 12 + ret nc + ld a,b + call CHPUT + inc c + jr _BM_PRINT_CURRENT_FILE_PAD + + +;--- Print the current filename at the current position, as selected + +BM_PRINT_CURRENT_FILE_AS_SELECTED: + ld hl,(BM_CUR_FILE_PNT) + ld de,BM_BUF + call BM_GENERATE_FILENAME + ld hl,BM_BUF + +_BM_PRINT_SELECTED_LOOP: + ld a,(hl) + or a + jr z,_BM_PRINT_SELECTED_LOOP_END + or 32 + call CHPUT + inc hl + jr _BM_PRINT_SELECTED_LOOP +_BM_PRINT_SELECTED_LOOP_END + ld b,'!' + jr _BM_PRINT_CURRENT_FILE_PAD + + ; ----------------------------------------------------------------------------- ; Keyboard scanning routines ; ----------------------------------------------------------------------------- @@ -485,12 +670,107 @@ _BM_CURSOR_WAIT_RELEASE: ld a,(hl) cpl and 11110000b - jr z,_BM_CURSOR_WAIT_RELEASE + jr nz,_BM_CURSOR_WAIT_RELEASE pop af ret +; ----------------------------------------------------------------------------- +; Utility routines +; ----------------------------------------------------------------------------- + + +;--- Update BM_CUR_PAGE_PNT as: +; BM_FILES_BASE + ((BM_CUR_PAGE-1)*60)*11 + +BM_UPDATE_CUR_PAGE_PNT: + ld hl,(BM_CUR_PAGE) + ld h,0 + dec l + call BM_MULT_60 + call BM_MULT_11 + ld de,BM_FILES_BASE + add hl,de + ld (BM_CUR_PAGE_PNT),hl + ret + + +;--- Update BM_CUR_FILE_PNT as: +; BM_CUR_PAGE_PNT + ((BM_CUR_COL*20) + BM_CUR_ROW)*11 + +BM_UPDATE_CUR_FILE_PNT: + ld hl,(BM_CUR_COL) + ld h,0 + call BM_MULT_20 + ld de,(BM_CUR_ROW) + ld d,0 + add hl,de + call BM_MULT_11 + ld de,(BM_CUR_PAGE_PNT) + add hl,de + ld (BM_CUR_FILE_PNT),hl + ret + + +;--- Multiply HL by 11 + +BM_MULT_11: + push hl + pop de + sla l + rl h ;*2 + sla l + rl h ;*4 + sla l + rl h ;*8 + add hl,de ;*9 + add hl,de ;*10 + add hl,de ;*11 + ret + + +;--- Multiply HL by 20 + +BM_MULT_20: + push hl + pop de + sla l + rl h ;*2 + sla l + rl h ;*4 + sla l + rl h ;*8 + sla l + rl h ;*16 + add hl,de ;*17 + add hl,de ;*18 + add hl,de ;*19 + add hl,de ;*20 + ret + + +;--- Multiply HL by 60 + +BM_MULT_60: + push hl + pop de + sla l + rl h ;*2 + sla l + rl h ;*4 + sla l + rl h ;*8 + sla l + rl h ;*16 + sla l + rl h ;*32 + ld b,60-32 +_BM_MULT_60_LOOP: + add hl,de + djnz _BM_MULT_60_LOOP + ret + ; ----------------------------------------------------------------------------- ; Text strings ; ----------------------------------------------------------------------------- @@ -560,3 +840,8 @@ BM_NUM_PAGES: equ _BM_VARS_BASE BM_CUR_PAGE: equ BM_NUM_PAGES+1 BM_NUM_FILES: equ BM_CUR_PAGE+1 BM_BUF: equ BM_NUM_FILES+2 +BM_CUR_PAGE_PNT: equ BM_BUF+13 ;Pointer to 1st filename in current page +BM_CUR_FILE_PNT: equ BM_CUR_PAGE_PNT+2 ;Pointer to current filename +BM_CUR_ROW: equ BM_CUR_FILE_PNT+2 ;Current logical row, 0-19 +BM_CUR_COL: equ BM_CUR_ROW+1 ;Current logical column, 0-2 + diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index d0970ec..6a9e71c 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -556,6 +556,7 @@ HWF_CHANGE_DIR: ; BC = Maximum number of files/directories to enumerate ; Output: Cy = 0: ok ; 1: error, no device present or it's not a storage device +; HL = Pointer to the 0 byte at the end of the list ; BC = Number of filenames found (if no error) HWF_ENUM_FILES: @@ -603,7 +604,7 @@ _HWF_ENUM_FILES_LOOP: ld (ix-4),' ' ld (ix-3),' ' ld (ix-2),' ' - ld (ix-1),128 + ld (ix-1),128+32 ;Space with bit 7 set _HWF_ENUM_FILES_NODIR: pop bc @@ -614,6 +615,8 @@ _HWF_ENUM_FILES_NODIR: xor a ld (ix),a + push ix + pop hl ret FILE_S: db "FIL" From 038a7285711d632d983bf591e1014b8c00193752 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sat, 16 Jan 2021 23:35:26 +0100 Subject: [PATCH 10/65] USB boot menu: improve responsiveness of cursor keys --- msx/bank1/boot_menu.asm | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 96e0da0..73f6c17 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -14,6 +14,9 @@ BM_FILES_BASE: equ 8000h DO_BOOT_MENU: + xor a + ld (BM_CURSOR_LAST),a + ; Init screen mode, draw fixed elements ld a,40 @@ -651,28 +654,25 @@ BM_CURSOR_IS_PRESSED: jr nc,_BM_CURSOR_IS_PRESSED_END xor a + ld (BM_CURSOR_LAST),a ret _BM_CURSOR_IS_PRESSED_END: + ld a,(BM_CURSOR_LAST) + or a + ld a,0 + ret nz ;Still pressed since last time + + inc a + ld (BM_CURSOR_LAST),a + dec hl - dec hl ;Row 6 + dec hl ;Row 6 (for SHIFT) ld a,(hl) cpl rrca and 80h or b - push af - inc hl - inc hl - -_BM_CURSOR_WAIT_RELEASE: - halt - ld a,(hl) - cpl - and 11110000b - jr nz,_BM_CURSOR_WAIT_RELEASE - - pop af ret @@ -844,4 +844,4 @@ BM_CUR_PAGE_PNT: equ BM_BUF+13 ;Pointer to 1st filename in current page BM_CUR_FILE_PNT: equ BM_CUR_PAGE_PNT+2 ;Pointer to current filename BM_CUR_ROW: equ BM_CUR_FILE_PNT+2 ;Current logical row, 0-19 BM_CUR_COL: equ BM_CUR_ROW+1 ;Current logical column, 0-2 - +BM_CURSOR_LAST: equ BM_CUR_COL+1 ;Result of last call to BM_CURSOR_IS_PRESSED From 788abfc42cba08d9f4b061861d92a4c73567ecbd Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sat, 16 Jan 2021 23:56:49 +0100 Subject: [PATCH 11/65] USB boot menu: don't reset file position after help --- msx/bank1/boot_menu.asm | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 73f6c17..032fb11 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -52,9 +52,9 @@ DO_BOOT_MENU: ld (BM_NUM_FILES),bc push bc - push hl - pop de - inc de + push hl ;Fill one extra page of 0s. + pop de ;This will be used to detect non-existing + inc de ;file positions in the last page. ld (hl),0 ld bc,59*11-1 ldir @@ -89,6 +89,10 @@ _BM_CALC_NUM_PAGES_END: _BM_CALC_NUM_PAGES_END_2: ld (BM_NUM_PAGES),a + xor a + ld (BM_CUR_ROW),a + ld (BM_CUR_COL),a + ; ----------------------------------------------------------------------------- ; Main key scanning loop @@ -103,9 +107,6 @@ BM_ENTER_MAIN_LOOP: call BM_PRINT_FILENAMES_PAGE call BM_UPDATE_CUR_PAGE_PNT - xor a - ld (BM_CUR_ROW),a - ld (BM_CUR_COL),a call BM_UPDATE_CUR_FILE_PNT call BM_POSIT_CUR_FILE call BM_PRINT_CURRENT_FILE_AS_SELECTED @@ -275,7 +276,7 @@ _BM_NEXT_PAGE: inc a ld (BM_CUR_PAGE),a - jp BM_ENTER_MAIN_LOOP + jp _BM_UPDATE_PAGE_END _BM_NEXT_10_PAGES: ld a,(BM_NUM_PAGES) @@ -291,7 +292,7 @@ _BM_NEXT_10_PAGES: _BM_NEXT_10_PAGES_GO: ld (BM_CUR_PAGE),a - jp BM_ENTER_MAIN_LOOP + jp _BM_UPDATE_PAGE_END _BM_PREV_PAGE: ld a,(BM_CUR_PAGE) @@ -300,7 +301,7 @@ _BM_PREV_PAGE: dec a ld (BM_CUR_PAGE),a - jp BM_ENTER_MAIN_LOOP + jp _BM_UPDATE_PAGE_END _BM_PREV_10_PAGES: ld a,(BM_CUR_PAGE) @@ -314,8 +315,13 @@ _BM_PREV_10_PAGES_1: _BM_PREV_10_PAGES_GO: ld (BM_CUR_PAGE),a - jp BM_ENTER_MAIN_LOOP + jp _BM_UPDATE_PAGE_END +_BM_UPDATE_PAGE_END: + xor a + ld (BM_CUR_ROW),a + ld (BM_CUR_COL),a + jp BM_ENTER_MAIN_LOOP ; ----------------------------------------------------------------------------- ; Screen printing routines From ff215f895372cfc8e03f3e78542d1eb5d0f6ed84 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sun, 17 Jan 2021 17:37:02 +0100 Subject: [PATCH 12/65] USB boot menu: show selected files in inverted color --- msx/bank1/boot_menu.asm | 72 +++++++++++++++++++++++++++++++++++------ msx/constants.asm | 6 ++++ 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 032fb11..72c7891 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -399,6 +399,7 @@ _BM_PRINT_FILENAMES_COLUMN_END: ; (11 chars, name and extension padded with spaces) ; DE = Destination buffer for the formatted file name ; Output: HL = Points past the filename +; DE = Points to the termination 0 ; C = Length of the formatted file name BM_GENERATE_FILENAME: @@ -581,23 +582,74 @@ _BM_PRINT_CURRENT_FILE_PAD: ;--- Print the current filename at the current position, as selected + ;Generate the formatted file name in BM_BUF, padded with spaces + BM_PRINT_CURRENT_FILE_AS_SELECTED: ld hl,(BM_CUR_FILE_PNT) ld de,BM_BUF call BM_GENERATE_FILENAME - ld hl,BM_BUF -_BM_PRINT_SELECTED_LOOP: +_BM_GEN_CURRENT_FILE_PAD: + ld a,c + cp 12 + jr nc,_BM_GEN_CURRENT_FILE_OK + ld a,' ' + ld (de),a + inc de + inc c + jr _BM_GEN_CURRENT_FILE_PAD +_BM_GEN_CURRENT_FILE_OK: + + ;Redefine chars 128-139 as the inverted chars of the filename + + ld hl,(TXTCGP) + ld de,128*8 + add hl,de + call SETWRT + + ld a,(VDP_DW) + ld c,a ;VDP write port + + ld hl,BM_BUF ;Pointer to current char + ld b,12 ;How many chars left to invert +_BM_INVERT_CHARS_LOOP: + push hl + push bc + ld e,(hl) + ld d,0 + sla e + rl d + sla e + rl d + sla e + rl d ;DE = Current char *8 + ld hl,(CGTABL) + add hl,de ;HL = Pointer to start of char definition + + ld b,8 +_BM_INVERT_ONE_CHAR_LOOP ld a,(hl) - or a - jr z,_BM_PRINT_SELECTED_LOOP_END - or 32 - call CHPUT + cpl + out (c),a inc hl - jr _BM_PRINT_SELECTED_LOOP -_BM_PRINT_SELECTED_LOOP_END - ld b,'!' - jr _BM_PRINT_CURRENT_FILE_PAD + djnz _BM_INVERT_ONE_CHAR_LOOP + + pop bc + pop hl + inc hl + djnz _BM_INVERT_CHARS_LOOP + + ;Print the inverted filename + + call BM_POSIT_CUR_FILE + ld a,128 +_BM_PRINT_INVERTED_LOOP: + call CHPUT + inc a + cp 128+12 + jr c,_BM_PRINT_INVERTED_LOOP + + ret ; ----------------------------------------------------------------------------- diff --git a/msx/constants.asm b/msx/constants.asm index 6ff98af..db937e6 100644 --- a/msx/constants.asm +++ b/msx/constants.asm @@ -1,9 +1,15 @@ +CGTABL: equ 0004h ;Address of font definition in BIOS ROM + +VDP_DW: equ 0007h +WRTVRM: equ 004Dh +SETWRT: equ 0053h INITXT: equ 006Ch CHPUT: equ 00A2h BREAKX: equ 00B7h POSIT: equ 00C6h LINL40: equ 0F3AEh +TXTCGP: equ 0F3B7h ;Address of pattern generator table in VRAM OLDKEY: equ 0FBDAh NEWKEY: equ 0FBE5h From c1c5f8d44bfd848c44fe43a571a36ddeb4f9d52a Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sun, 17 Jan 2021 18:24:08 +0100 Subject: [PATCH 13/65] USB boot menu: implement handler for pressing the ENER key --- msx/bank0/kernel.asm | 4 +-- msx/bank1/boot_menu.asm | 58 +++++++++++++++++++++++++++++++++++++++++ msx/bank1/ch376.asm | 22 +++++++++++----- msx/constants.asm | 2 ++ 4 files changed, 78 insertions(+), 8 deletions(-) diff --git a/msx/bank0/kernel.asm b/msx/bank0/kernel.asm index 646c03b..fcde257 100644 --- a/msx/bank0/kernel.asm +++ b/msx/bank0/kernel.asm @@ -63,7 +63,7 @@ KEYINT equ 00038H LDIRMV equ 00059H LDIRVM equ 0005CH CHSNS equ 0009CH -CHGET equ 0009FH +;CHGET equ 0009FH ;CHPUT equ 000A2H LPTOUT equ 000A5H ;BREAKX equ 000B7H @@ -72,7 +72,7 @@ ERAFNK equ 000CCH TOTEXT equ 000D2H SNSMAT equ 00141H PHYDIO equ 00144H -KILBUF equ 00156H +;KILBUF equ 00156H CALBAS equ 00159H X003B equ 0003BH ; helper routine in DOS memoryspace: save and change secundairy slotregister diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 72c7891..b81db47 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -118,6 +118,9 @@ _BM_MAIN_LOOP: call BREAKX ret c + call BM_ENTER_IS_PRESSED + jp z,BM_DO_ENTER + call BM_F1_IS_PRESSED jp z,BM_DO_HELP @@ -138,6 +141,39 @@ _BM_MAIN_LOOP: ; ----------------------------------------------------------------------------- +;--- ENTER key press handler + +BM_DO_ENTER: + ld hl,(BM_CUR_FILE_PNT) + ld de,BM_BUF + call BM_GENERATE_FILENAME + ld hl,BM_BUF + + call HWF_OPEN_FILE_DIR + or a + ret z ;Continue computer boot process + + dec a + jp z,_BM_MAIN_LOOP ;TODO: handle entering directory + + dec a + ld hl,BM_FILE_NOT_FOUND_S + jr z,_BM_DO_ENTER_PRINT_ERR + + ld hl,BM_ERROR_OPENING_FILE_S +_BM_DO_ENTER_PRINT_ERR: + call BM_PRINT_STATUS + call KILBUF + call CHGET ;TODO: This displays cursor, somehow hide + call KILBUF + call BM_PRINT_MAIN_STATUS + +_BM_DO_ENTER_WAIT_RELEASE: ;In case the "any key" pressed is enter + call BM_ENTER_IS_PRESSED + jr z,_BM_DO_ENTER_WAIT_RELEASE + jp _BM_MAIN_LOOP + + ;--- Help loop, entered when F1 is pressed BM_DO_HELP: @@ -687,6 +723,22 @@ BM_F1_IS_PRESSED: jp BM_KEY_CHECK +;--- Check if ENTER is pressed +; Output: Z if pressed, NZ if not + +BM_ENTER_IS_PRESSED: + ld de,8007h + jp BM_KEY_CHECK + ret nz + +_BM_ENTER_IS_PRESSED_WAIT_RELEASE: + ld de,8007h + call BM_KEY_CHECK + jr z,_BM_ENTER_IS_PRESSED_WAIT_RELEASE + xor a + ret + + ;--- Check if a cursor key is pressed ; Output: A=0: no cursor key is pressed ; 1,2,3,4: up,right,down,left @@ -856,6 +908,12 @@ BM_NO_FILES_S: BM_SCANNING_DIR_S: db "Scanning directory...",0 +BM_FILE_NOT_FOUND_S: + db "File/dir not found! Press any key",0 + +BM_ERROR_OPENING_FILE_S: + db "Error opening file/dir! Press any key",0 + BM_HELP_1: db " Cursors: select file or directory",13,10 db 13,10 diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index 6a9e71c..bd62a49 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -527,16 +527,26 @@ HWF_MOUNT_DISK: FAKE_DEV_NAME: db "TheStorageThing 0.05" + ; ----------------------------------------------------------------------------- -; HWF_CHANGE_DIR: Enter a directory from the current one +; HWF_OPEN_FILE_DIR: Open a file or enter a directory from the current one ; ----------------------------------------------------------------------------- -; Input: HL = Address of directory name, relative to current, +; Input: HL = Address of file or directory name, relative to current, ; can be ".." to go back to previous -; Output: A = 0: ok -; 1: directory not found -; 2: other error (e.g. no device found) +; Output: A = 0: ok, file open +; 1: ok, directory entered +; 2: file or directory not found +; 3: other error (e.g. no device found) + +HWF_OPEN_FILE_DIR: + ld a,3 + ret -HWF_CHANGE_DIR: + ld a,27 + call CHPUT + ld a,'j' + call CHPUT + call PRINT xor a ret diff --git a/msx/constants.asm b/msx/constants.asm index db937e6..208518b 100644 --- a/msx/constants.asm +++ b/msx/constants.asm @@ -4,9 +4,11 @@ VDP_DW: equ 0007h WRTVRM: equ 004Dh SETWRT: equ 0053h INITXT: equ 006Ch +CHGET: equ 009Fh CHPUT: equ 00A2h BREAKX: equ 00B7h POSIT: equ 00C6h +KILBUF: equ 0156h LINL40: equ 0F3AEh TXTCGP: equ 0F3B7h ;Address of pattern generator table in VRAM From 435c12c8f9fa00c1506e3bdae941fa2b796d1786 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 19 Jan 2021 16:07:37 +0100 Subject: [PATCH 14/65] Take serial port number from "serialPortNumber" config key in NestorMSX plugin --- dotNet/NestorMsxPlugin/RookieDrivePorts.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotNet/NestorMsxPlugin/RookieDrivePorts.cs b/dotNet/NestorMsxPlugin/RookieDrivePorts.cs index d747f0c..b1dea02 100644 --- a/dotNet/NestorMsxPlugin/RookieDrivePorts.cs +++ b/dotNet/NestorMsxPlugin/RookieDrivePorts.cs @@ -49,7 +49,7 @@ public class RookieDrivePortsPlugin public RookieDrivePortsPlugin(PluginContext context, IDictionary pluginConfig) { context.Cpu.MemoryAccess += Cpu_MemoryAccess; - chPorts = UsbServiceProvider.GetCH376Ports(); + chPorts = new CH376PortsViaNoobtocol((string)pluginConfig["serialPortNumber"]); cpu = context.Cpu; slots = context.SlotsSystem; context.Cpu.BeforeInstructionFetch += Cpu_BeforeInstructionFetch; From 59d19e5380cf53c4bc06db47b68395db35e8fbfe Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 19 Jan 2021 16:11:20 +0100 Subject: [PATCH 15/65] Changes in USB boot menu: - Introduce the USE_FAKE_STORAGE_DEVICE constant - Implement HWF_MOUNT_DISK and HWF_OPEN_FILE_DIR for real hardware - Show an error if opening root directory fails --- msx/bank1/boot_menu.asm | 26 ++++++++++-- msx/bank1/ch376.asm | 90 +++++++++++++++++++++++++++++++++++++++-- msx/config.asm | 5 ++- msx/usb_errors.asm | 9 ++++- 4 files changed, 121 insertions(+), 9 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index b81db47..722b394 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -46,6 +46,15 @@ DO_BOOT_MENU: ld hl,BM_SCANNING_DIR_S call BM_PRINT_STATUS + ld hl,BM_ROOT_DIR_S + call HWF_OPEN_FILE_DIR + dec a + jr z,_BM_OPEN_ROOT_OK + ld hl,BM_ERROR_OPENING_FILE_S + call BM_PRINT_STATUS_WAIT_KEY + ret +_BM_OPEN_ROOT_OK: + ld hl,BM_FILES_BASE ld bc,1290 call HWF_ENUM_FILES @@ -162,10 +171,7 @@ BM_DO_ENTER: ld hl,BM_ERROR_OPENING_FILE_S _BM_DO_ENTER_PRINT_ERR: - call BM_PRINT_STATUS - call KILBUF - call CHGET ;TODO: This displays cursor, somehow hide - call KILBUF + call BM_PRINT_STATUS_WAIT_KEY call BM_PRINT_MAIN_STATUS _BM_DO_ENTER_WAIT_RELEASE: ;In case the "any key" pressed is enter @@ -174,6 +180,15 @@ _BM_DO_ENTER_WAIT_RELEASE: ;In case the "any key" pressed is enter jp _BM_MAIN_LOOP +;--- Print the string HL in the status area and wait for a key press + +BM_PRINT_STATUS_WAIT_KEY: + call BM_PRINT_STATUS + call KILBUF + call CHGET ;TODO: This displays cursor, somehow hide + jp KILBUF + + ;--- Help loop, entered when F1 is pressed BM_DO_HELP: @@ -902,6 +917,9 @@ BM_PAGE_S: BM_SPACE_AND_BAR: db " / ",0 +BM_ROOT_DIR_S: + db "/",0 + BM_NO_FILES_S: db "No files found in current directory!",0 diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index bd62a49..fe48843 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -65,6 +65,12 @@ CH_CMD_ABORT_NAK: equ 17h CH_CMD_GET_STATUS: equ 22h CH_CMD_RD_USB_DATA0: equ 27h CH_CMD_WR_HOST_DATA: equ 2Ch +CH_CMD_SET_FILE_NAME: equ 2Fh +CH_CMD_DISK_CONNECT: equ 30h +CH_CMD_DISK_MOUNT: equ 31h +CH_CMD_FILE_OPEN: equ 32h +CH_CMD_FILE_ENUM_GO: equ 33h +CH_CMD_FILE_CLOSE: equ 36h CH_CMD_SET_ADDRESS: equ 45h CH_CMD_GET_DESCR: equ 46h CH_CMD_SET_CONFIG: equ 49h @@ -96,8 +102,10 @@ CH_ST_RET_ABORT: equ 5Fh ; Output: Cy = 0 if hardware is operational, 1 if it's not HW_TEST: + if USE_FAKE_STORAGE_DEVICE=1 or a - ret ;!!! + ret + endif ld a,34h call _HW_TEST_DO @@ -516,6 +524,8 @@ _CH_DELAY_LOOP: ; 1: error, no device present or it's not a storage device HWF_MOUNT_DISK: + if USE_FAKE_STORAGE_DEVICE=1 + ex de,hl ld hl,FAKE_DEV_NAME ld bc,24 @@ -527,6 +537,39 @@ HWF_MOUNT_DISK: FAKE_DEV_NAME: db "TheStorageThing 0.05" + endif + + ld a,CH_CMD_DISK_CONNECT + out (CH_COMMAND_PORT),a + call CH_WAIT_INT_AND_GET_RESULT + cp USB_ERR_OK + scf + ret nz + + ld a,6 + call CH_SET_USB_MODE + + ld a,CH_CMD_DISK_MOUNT + out (CH_COMMAND_PORT),a + call CH_WAIT_INT_AND_GET_RESULT + cp USB_ERR_OK + scf + ret nz + + push hl + call CH_READ_DATA + pop hl + ld d,h + ld e,l + ld bc,8 + add hl,bc + ld bc,36-8 + ldir + xor a + ld (de),a + + ret + ; ----------------------------------------------------------------------------- ; HWF_OPEN_FILE_DIR: Open a file or enter a directory from the current one @@ -539,8 +582,7 @@ FAKE_DEV_NAME: ; 3: other error (e.g. no device found) HWF_OPEN_FILE_DIR: - ld a,3 - ret + if USE_FAKE_STORAGE_DEVICE=1 ld a,27 call CHPUT @@ -550,6 +592,31 @@ HWF_OPEN_FILE_DIR: xor a ret + endif + + ld a,CH_CMD_SET_FILE_NAME + out (CH_COMMAND_PORT),a + call CH_WRITE_STRING + + ld a,CH_CMD_FILE_OPEN + out (CH_COMMAND_PORT),a + call CH_WAIT_INT_AND_GET_RESULT + + ld b,0 + cp USB_ERR_OK + jr z,_HWF_OPEN_FILE_DIR_END + inc b + cp USB_ERR_OPEN_DIR + jr z,_HWF_OPEN_FILE_DIR_END + inc b + cp USB_ERR_MISS_FILE + jr z,_HWF_OPEN_FILE_DIR_END + inc b + +_HWF_OPEN_FILE_DIR_END: + ld a,b + ret + ; ----------------------------------------------------------------------------- ; HWF_ENUM_FILES: Enumerate files and directories in the current directory @@ -838,6 +905,13 @@ CH_WAIT_INT_AND_GET_RESULT: jr nz,CH_WAIT_INT_AND_GET_RESULT ;TODO: Perhaps add a timeout check here? call CH_GET_STATUS + cp USB_FILERR_MIN + jr c,_CH_WAIT_INT_AND_GET_RESULT_2 + cp USB_FILERR_MAX+1 + jr nc,_CH_WAIT_INT_AND_GET_RESULT_2 + ret + +_CH_WAIT_INT_AND_GET_RESULT_2: cp CH_ST_RET_SUCCESS ld b,USB_ERR_OK @@ -1056,3 +1130,13 @@ CH_WRITE_DATA: otir ret + +CH_WRITE_STRING: + ld c,CH_DATA_PORT +_CH_WRITE_STRING_LOOP: + ld a,(hl) + inc hl + out (c),a + or a + jr nz,_CH_WRITE_STRING_LOOP + ret \ No newline at end of file diff --git a/msx/config.asm b/msx/config.asm index 12639a6..a84b094 100644 --- a/msx/config.asm +++ b/msx/config.asm @@ -39,7 +39,7 @@ USE_ALTERNATIVE_PORTS: equ 0 ;Enable this if you are Konamiman and you are using NestorMSX with ;the almigthy Arduino board that Xavirompe sent you -USING_ARDUINO_BOARD: equ 0 +USING_ARDUINO_BOARD: equ 1 ;Enable to debug DSKIO calls: whenever DSKIO is called, text mode is enabled, ;the input parameters are printed, and system stops waiting for a key press @@ -49,6 +49,9 @@ DEBUG_DSKIO: equ 0 ;at boot time WAIT_KEY_ON_INIT: equ 0 +;Enable to simulate a fake storage device connected to a USB port +USE_FAKE_STORAGE_DEVICE: equ 0 + ; ----------------------------------------------------------------------------- ; ROM configuration diff --git a/msx/usb_errors.asm b/msx/usb_errors.asm index dfc4997..59028c3 100644 --- a/msx/usb_errors.asm +++ b/msx/usb_errors.asm @@ -14,4 +14,11 @@ USB_ERR_NO_DEVICE: equ 5 USB_ERR_PANIC_BUTTON_PRESSED: equ 6 USB_ERR_UNEXPECTED_STATUS_FROM_HOST: equ 7 -USB_ERR_MAX: equ 7 \ No newline at end of file +USB_ERR_MAX: equ 7 + +USB_FILERR_MIN: equ 41h + +USB_ERR_OPEN_DIR: equ 41h +USB_ERR_MISS_FILE: equ 42h + +USB_FILERR_MAX: equ 0B4h From 40394a1ad29e13c821347865b992107d49f3bb9e Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 19 Jan 2021 17:29:25 +0100 Subject: [PATCH 16/65] USB boot menu: implement file enum on real hardware. Also, open "DSK" directory and exit if not found. --- msx/bank1/boot_menu.asm | 26 +++++++----- msx/bank1/ch376.asm | 94 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 100 insertions(+), 20 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 722b394..bf3b584 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -5,7 +5,7 @@ ; a navigable list of disk image files (available only when a ; standard USB mass storage device is plugged in). -BM_FILES_BASE: equ 8000h +BM_FILES_BASE: equ 8010h ; ----------------------------------------------------------------------------- @@ -17,6 +17,18 @@ DO_BOOT_MENU: xor a ld (BM_CURSOR_LAST),a + ; Try opening DSK directory on the device + + ld hl,BM_ROOT_DIR_S + call HWF_OPEN_FILE_DIR + dec a + ret nz + + ld hl,BM_DSK_S + call HWF_OPEN_FILE_DIR + dec a + ret nz + ; Init screen mode, draw fixed elements ld a,40 @@ -46,15 +58,6 @@ DO_BOOT_MENU: ld hl,BM_SCANNING_DIR_S call BM_PRINT_STATUS - ld hl,BM_ROOT_DIR_S - call HWF_OPEN_FILE_DIR - dec a - jr z,_BM_OPEN_ROOT_OK - ld hl,BM_ERROR_OPENING_FILE_S - call BM_PRINT_STATUS_WAIT_KEY - ret -_BM_OPEN_ROOT_OK: - ld hl,BM_FILES_BASE ld bc,1290 call HWF_ENUM_FILES @@ -920,6 +923,9 @@ BM_SPACE_AND_BAR: BM_ROOT_DIR_S: db "/",0 +BM_DSK_S: + db "DSK",0 + BM_NO_FILES_S: db "No files found in current directory!",0 diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index fe48843..5f7df56 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -88,6 +88,9 @@ CH_ST_INT_SUCCESS: equ 14h CH_ST_INT_CONNECT: equ 15h CH_ST_INT_DISCONNECT: equ 16h CH_ST_INT_BUF_OVER: equ 17h +CH_ST_INT_DISK_READ: equ 1Dh +CH_ST_INT_DISK_WRITE: equ 1Eh +CH_ST_INT_DISK_ERR: equ 1Fh CH_ST_RET_SUCCESS: equ 51h CH_ST_RET_ABORT: equ 5Fh @@ -584,12 +587,12 @@ FAKE_DEV_NAME: HWF_OPEN_FILE_DIR: if USE_FAKE_STORAGE_DEVICE=1 - ld a,27 - call CHPUT - ld a,'j' - call CHPUT - call PRINT - xor a + ;ld a,27 + ;call CHPUT + ;ld a,'j' + ;call CHPUT + ;call PRINT + ld a,1 ret endif @@ -631,12 +634,12 @@ _HWF_OPEN_FILE_DIR_END: ; ----------------------------------------------------------------------------- ; Input: HL = Address of buffer to get file info into ; BC = Maximum number of files/directories to enumerate -; Output: Cy = 0: ok -; 1: error, no device present or it's not a storage device -; HL = Pointer to the 0 byte at the end of the list -; BC = Number of filenames found (if no error) +; Output: HL = Pointer to the 0 byte at the end of the list +; BC = Number of filenames found HWF_ENUM_FILES: + if USE_FAKE_STORAGE_DEVICE = 1 + push bc call _HWF_ENUM_FILES pop bc @@ -726,6 +729,75 @@ Num2: inc de ret + endif + + if USE_FAKE_STORAGE_DEVICE = 0 + + ld a,CH_CMD_SET_FILE_NAME + out (CH_COMMAND_PORT),a + ld a,'*' + out (CH_DATA_PORT),a + xor a + out (CH_DATA_PORT),a + + ld de,0 ;Number of files found + ld a,CH_CMD_FILE_OPEN + out (CH_COMMAND_PORT),a +_HWF_ENUM_FILES_LOOP: + push hl + push de + push bc + call CH_WAIT_INT_AND_GET_RESULT + pop bc + pop de + pop hl + cp USB_ERR_OK + jr nz,_HWF_ENUM_FILES_END + + push bc + push hl + push de + call CH_READ_DATA + pop de + pop hl + pop bc + + ;WIP: If not letter or digit jump to _HWF_ENUM_DIR_NEXT + + push bc + ld bc,11 + add hl,bc + pop bc + + ld a,(hl) ;File attributes byte + and 10h + jr z,_HWF_ENUM_DIR_OK + dec hl + set 7,(hl) + inc hl +_HWF_ENUM_DIR_OK: + + inc de + + dec bc + ld a,b + or c + jr z,_HWF_ENUM_FILES_END + +_HWF_ENUM_DIR_NEXT: + ld a,CH_CMD_FILE_ENUM_GO + out (CH_COMMAND_PORT),a + jp _HWF_ENUM_FILES_LOOP + +_HWF_ENUM_FILES_END: + ld (hl),0 + push de + pop bc + ret + + endif + + ; ----------------------------------------------------------------------------- ; Optional shortcut routines ; ----------------------------------------------------------------------------- @@ -918,6 +990,8 @@ _CH_WAIT_INT_AND_GET_RESULT_2: jr z,_CH_LD_A_B_RET cp CH_ST_INT_SUCCESS jr z,_CH_LD_A_B_RET + cp CH_ST_INT_DISK_READ + jr z,_CH_LD_A_B_RET cp CH_ST_INT_DISCONNECT jr z,_CH_NO_DEV_ERR cp CH_ST_INT_BUF_OVER From a6aab1348e4a5d707529c125730421b4037e31ea Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Wed, 20 Jan 2021 13:10:57 +0100 Subject: [PATCH 17/65] UDB boot menu: discard filenames not starting with letter or digit on enum --- msx/bank1/ch376.asm | 4 +++- msx/bank1/misc.asm | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index 5f7df56..be83aed 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -762,7 +762,9 @@ _HWF_ENUM_FILES_LOOP: pop hl pop bc - ;WIP: If not letter or digit jump to _HWF_ENUM_DIR_NEXT + ld a,(hl) + call IS_DIGIT_OR_LETTER + jr nc,_HWF_ENUM_DIR_NEXT push bc ld bc,11 diff --git a/msx/bank1/misc.asm b/msx/bank1/misc.asm index 326a544..3f88468 100644 --- a/msx/bank1/misc.asm +++ b/msx/bank1/misc.asm @@ -235,3 +235,25 @@ B2A_XXX: inc ix B2A_2XX: ld (ix),"2" sub 200 jr B2A_XXX + + +; ----------------------------------------------------------------------------- +; IS_DIGIT_OR_LETTER: Check if a char is a digit or a letter +; ----------------------------------------------------------------------------- +; Input: A = Char to check +; Output: Cy=1 if it's a char or a letter (A-Z), 0 otherwise +; Modifies: AF +; ----------------------------------------------------------------------------- + +IS_DIGIT_OR_LETTER: + cp '0' + ccf + ret nc + cp '9'+1 + ret c + + cp 'Z'+1 + ret nc + cp 'A' + ccf + ret From 99dad640019908206935448648ee6a19d02438b1 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 21 Jan 2021 17:22:01 +0100 Subject: [PATCH 18/65] Changes in the USB boot menu: - Added a definition and some routines for the device storage-specific work area (which is not used yet) - Implemented the F5 key to start over file enumeration --- msx/bank1/boot_menu.asm | 47 +++++++++++++++++++++ msx/bank1/usb.asm | 13 +++++- msx/bank1/verbose_reset.asm | 1 + msx/bank1/work_area.asm | 81 ++++++++++++++++++++++++++++++++++++- 4 files changed, 140 insertions(+), 2 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index bf3b584..9fcba5d 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -16,6 +16,7 @@ DO_BOOT_MENU: xor a ld (BM_CURSOR_LAST),a + ld (BM_NO_STOR_DEV),a ; Try opening DSK directory on the device @@ -130,6 +131,13 @@ _BM_MAIN_LOOP: call BREAKX ret c + call BM_F5_IS_PRESSED + jp z,BM_START_OVER + + ld a,(BM_NO_STOR_DEV) + inc a + jr z,_BM_MAIN_LOOP + call BM_ENTER_IS_PRESSED jp z,BM_DO_ENTER @@ -144,6 +152,30 @@ _BM_MAIN_LOOP: and 7Fh jp BM_UPDATE_PAGE +;--- Start over after F5 is pressed + +BM_START_OVER: + xor a + ld (BM_NUM_FILES),a + ld (BM_NUM_FILES+1),a + inc a + ld (BM_CUR_PAGE),a + ld (BM_NUM_PAGES),a + + call BM_CLEAR_INFO_AREA + ld hl,BM_RESETTING_DEVICE_S + call BM_PRINT_STATUS + + call HWF_MOUNT_DISK + jp nc,DO_BOOT_MENU + + ld a,0FFh + ld (BM_NO_STOR_DEV),a + ld hl,BM_NO_DEV_OR_NO_STOR_S + call BM_PRINT_STATUS + + jp _BM_MAIN_LOOP + ; ----------------------------------------------------------------------------- ; Key press handlers @@ -741,6 +773,14 @@ BM_F1_IS_PRESSED: jp BM_KEY_CHECK +;--- Check if F5 is pressed +; Output: Z if pressed, NZ if not + +BM_F5_IS_PRESSED: + ld de,0207h + jp BM_KEY_CHECK + + ;--- Check if ENTER is pressed ; Output: Z if pressed, NZ if not @@ -932,6 +972,12 @@ BM_NO_FILES_S: BM_SCANNING_DIR_S: db "Scanning directory...",0 +BM_RESETTING_DEVICE_S: + db "Resetting device...",0 + +BM_NO_DEV_OR_NO_STOR_S: + db "No storage device found! F5 to retry",0 + BM_FILE_NOT_FOUND_S: db "File/dir not found! Press any key",0 @@ -985,3 +1031,4 @@ BM_CUR_FILE_PNT: equ BM_CUR_PAGE_PNT+2 ;Pointer to current filename BM_CUR_ROW: equ BM_CUR_FILE_PNT+2 ;Current logical row, 0-19 BM_CUR_COL: equ BM_CUR_ROW+1 ;Current logical column, 0-2 BM_CURSOR_LAST: equ BM_CUR_COL+1 ;Result of last call to BM_CURSOR_IS_PRESSED +BM_NO_STOR_DEV: equ BM_CURSOR_LAST+1 ;FFh if F5 was pressed and no storage device was found diff --git a/msx/bank1/usb.asm b/msx/bank1/usb.asm index 30e5f0b..34fa14c 100644 --- a/msx/bank1/usb.asm +++ b/msx/bank1/usb.asm @@ -21,7 +21,8 @@ USB_PROTO_WITH_INT_EP: equ 0 ; On device connection, initialize it. ; On device disconnection, clear work area. ; ----------------------------------------------------------------------------- -; Output: Cy = 0 if a properly initialized CBI device is connected, 1 if not +; Output: Cy = 0 if a properly initialized CBI or storage device is connected +; 1 if not USB_CHECK_DEV_CHANGE: call HW_DEV_CHANGE @@ -46,6 +47,16 @@ _USB_CHECK_DEV_CHANGE_CHANGED: call USB_INIT_DEV or a ret z ;Initialization OK + dec a + jr nz,_USB_CHECK_DEV_CHANGE_NO_DEV + + ;* Device present but it's not a FDD: check if it's a storage device + + call HWF_MOUNT_DISK + jr c,_USB_CHECK_DEV_CHANGE_NO_DEV + call WK_INIT_FOR_STORAGE_DEV + or a + ret ;* No device, or device initialization failed diff --git a/msx/bank1/verbose_reset.asm b/msx/bank1/verbose_reset.asm index eb814a1..fdb25be 100644 --- a/msx/bank1/verbose_reset.asm +++ b/msx/bank1/verbose_reset.asm @@ -34,6 +34,7 @@ _HW_RESET_PRINT_GO: call CHPUT jr _HW_RESET_PRINT _HW_RESET_PRINT_END: + call WK_INIT_FOR_STORAGE_DEV ret _HW_RESET_NO_STOR: diff --git a/msx/bank1/work_area.asm b/msx/bank1/work_area.asm index b0ebc45..3ea7ab5 100644 --- a/msx/bank1/work_area.asm +++ b/msx/bank1/work_area.asm @@ -5,7 +5,7 @@ ; We use the 8 bytes available for our slot at SLTWRK. -; Work area definition: +; Work area definition when a FDD is connected: ; ; +0: Bulk OUT endpoint parameters ; +1: Bulk IN endpoint parameters @@ -30,6 +30,17 @@ ; 10 = 32 bytes ; 11 = 64 bytes ; +; Work area definition when a storage device is connected: +; +; +0: flags: +; bit 7: set to 1, indicates a storage device is connected +; (if a floppy is connected it'll be 0 since the byte holds +; the OUT endpoint number) +; bit 0: set to 1 if there's a file mounted +; +1: Current directory depth: +; 0: no directory currently open +; 1: root directory, etc +; ; If no device is connected or the connected device is not a CBI FDD, ; or if some error occurred during USB hardware or device initialization, ; the work area contents is all zero @@ -294,6 +305,74 @@ WK_GET_LAST_REL_DRIVE: ret +; ----------------------------------------------------------------------------- +; Initialize work area for a storage device + +WK_INIT_FOR_STORAGE_DEV: + call _WK_GETWRK + ld (ix),80h + ld (ix+1),0 + ret + + +; ----------------------------------------------------------------------------- +; Retrieve the storage device flags +; +; Output: A = storage device flags byte +; NZ if a storage device is connected, Z otherwise + +WK_GET_STORAGE_DEV_FLAGS: + push ix + call _WK_GETWRK + ld a,(ix) + pop ix + bit 7,a + ret + + +; ----------------------------------------------------------------------------- +; Set the storage device flags +; +; Input: A = interface number + +WK_SET_STORAGE_DEV_FLAGS: + push ix + push af + call _WK_GETWRK + pop af + ld (ix),a + pop ix + ret + + +; ----------------------------------------------------------------------------- +; Retrieve the current directory depth for the storage device +; +; Output: A = current directory depth + +WK_GET_CUR_DIR_DEPTH: + push ix + call _WK_GETWRK + ld a,(ix+1) + pop ix + ret + + +; ----------------------------------------------------------------------------- +; Set the current directory depth for the storage device +; +; Input: A = directory depth to set + +WK_SET_CUR_DIR_DEPTH: + push ix + push af + call _WK_GETWRK + pop af + ld (ix+1),a + pop ix + ret + + ; ----------------------------------------------------------------------------- ; Get the storage address for a given work area value ; From 0cfbf43654b9f7ea69dd705638327a8f14d1eba4 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sun, 24 Jan 2021 16:17:25 +0100 Subject: [PATCH 19/65] USB boot menu: partial implementation of actually mounting files. When pressing ENTER on a file name, the file is mounted and the computer properly boots from it. For now with limitations: - Read-only - Usage of XFER for transfers to page 1 not implemented yet --- msx/bank1/boot_menu.asm | 15 ++++- msx/bank1/ch376.asm | 115 +++++++++++++++++++++++++++++++++++- msx/bank1/dskio_dskchg.asm | 70 ++++++++++++++++++++++ msx/bank1/inihrd_inienv.asm | 4 ++ msx/bank1/work_area.asm | 7 +++ 5 files changed, 207 insertions(+), 4 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 9fcba5d..9bf5dfb 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -20,6 +20,7 @@ DO_BOOT_MENU: ; Try opening DSK directory on the device + if USE_FAKE_STORAGE_DEVICE = 0 ld hl,BM_ROOT_DIR_S call HWF_OPEN_FILE_DIR dec a @@ -29,6 +30,7 @@ DO_BOOT_MENU: call HWF_OPEN_FILE_DIR dec a ret nz + endif ; Init screen mode, draw fixed elements @@ -189,13 +191,19 @@ BM_START_OVER: BM_DO_ENTER: ld hl,(BM_CUR_FILE_PNT) + + push hl + pop ix + bit 7,(ix+10) + jp nz,_BM_MAIN_LOOP ;For now entering directories is not supported + ld de,BM_BUF call BM_GENERATE_FILENAME ld hl,BM_BUF call HWF_OPEN_FILE_DIR or a - ret z ;Continue computer boot process + jr z,_BM_DO_ENTER_FILE_IS_OPEN dec a jp z,_BM_MAIN_LOOP ;TODO: handle entering directory @@ -214,6 +222,11 @@ _BM_DO_ENTER_WAIT_RELEASE: ;In case the "any key" pressed is enter jr z,_BM_DO_ENTER_WAIT_RELEASE jp _BM_MAIN_LOOP +_BM_DO_ENTER_FILE_IS_OPEN: + call WK_GET_STORAGE_DEV_FLAGS + or 1 ;There's a file open + call WK_SET_STORAGE_DEV_FLAGS + ret ;Continue computer boot process ;--- Print the string HL in the status area and wait for a key press diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index be83aed..1ac5408 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -71,6 +71,9 @@ CH_CMD_DISK_MOUNT: equ 31h CH_CMD_FILE_OPEN: equ 32h CH_CMD_FILE_ENUM_GO: equ 33h CH_CMD_FILE_CLOSE: equ 36h +CH_CMD_BYTE_LOCATE: equ 39h +CH_CMD_BYTE_READ: equ 3Ah +CH_CMD_BYTE_RD_GO: equ 3Bh CH_CMD_SET_ADDRESS: equ 45h CH_CMD_GET_DESCR: equ 46h CH_CMD_SET_CONFIG: equ 49h @@ -592,7 +595,7 @@ HWF_OPEN_FILE_DIR: ;ld a,'j' ;call CHPUT ;call PRINT - ld a,1 + xor a ret endif @@ -751,7 +754,7 @@ _HWF_ENUM_FILES_LOOP: pop bc pop de pop hl - cp USB_ERR_OK + cp CH_ST_INT_DISK_READ jr nz,_HWF_ENUM_FILES_END push bc @@ -800,6 +803,112 @@ _HWF_ENUM_FILES_END: endif +; ----------------------------------------------------------------------------- +; HWF_SEEK_FILE: Move the pointer of the currently mounted file +; ----------------------------------------------------------------------------- +; Input: HL:DE = New pointer +; Output: A = 0: Ok +; 1: End of file +; 2: Other error + +HWF_SEEK_FILE: + if USE_FAKE_STORAGE_DEVICE = 1 + xor a + ret + endif + + ld a,CH_CMD_BYTE_LOCATE + out (CH_COMMAND_PORT),a + ld a,e + out (CH_DATA_PORT),a + ld a,d + out (CH_DATA_PORT),a + ld a,l + out (CH_DATA_PORT),a + ld a,h + out (CH_DATA_PORT),a + + call CH_WAIT_INT_AND_GET_RESULT + or a + ld a,2 + ret nz + + ld a,CH_CMD_RD_USB_DATA0 + out (CH_COMMAND_PORT),a + in a,(CH_DATA_PORT) + cp 4 + ld a,2 + ret nz + + ;Read the current pointer, if it's FFFFFFFFh return end of file error + ld b,4 + ld c,0FFh +_HWF_SEEK_FILE_CUR_POINTER: + in a,(CH_DATA_PORT) + and c + ld c,a + djnz _HWF_SEEK_FILE_CUR_POINTER + + ld a,c + inc a + ld a,1 + ret z + dec a + ret + + +; ----------------------------------------------------------------------------- +; HWF_READ_FILE: Read the currently mounted file +; ----------------------------------------------------------------------------- +; Input: BC = How many bytes to read +; HL = Destination address +; Output: A = 0: Ok +; 1: Error +; BC = How many bytes actually read + +HWF_READ_FILE: + if USE_FAKE_STORAGE_DEVICE=1 + ld a,1 + ld bc,2048 + ret + endif + + push hl + push hl + ld a,CH_CMD_BYTE_READ + out (CH_COMMAND_PORT),a + ld a,c + out (CH_DATA_PORT),a + ld a,b + out (CH_DATA_PORT),a + +_HWF_READ_FILE_LOOP: + call CH_WAIT_INT_AND_GET_RESULT + or a + jr z,_HWF_READ_FILE_END + cp CH_ST_INT_DISK_READ + ld a,1 + jr nz,_HWF_READ_FILE_END + + pop hl + call CH_READ_DATA + push hl + + ld a,CH_CMD_BYTE_RD_GO + out (CH_COMMAND_PORT),a + + jr _HWF_READ_FILE_LOOP + +_HWF_READ_FILE_END: + pop hl ;Address after the last byte retrieved + pop de ;Initial dest address + or a + sbc hl,de + push hl + pop bc + ret + + ; ----------------------------------------------------------------------------- ; Optional shortcut routines ; ----------------------------------------------------------------------------- @@ -993,7 +1102,7 @@ _CH_WAIT_INT_AND_GET_RESULT_2: cp CH_ST_INT_SUCCESS jr z,_CH_LD_A_B_RET cp CH_ST_INT_DISK_READ - jr z,_CH_LD_A_B_RET + ret z cp CH_ST_INT_DISCONNECT jr z,_CH_NO_DEV_ERR cp CH_ST_INT_BUF_OVER diff --git a/msx/bank1/dskio_dskchg.asm b/msx/bank1/dskio_dskchg.asm index 1c3206e..849fa21 100644 --- a/msx/bank1/dskio_dskchg.asm +++ b/msx/bank1/dskio_dskchg.asm @@ -57,6 +57,9 @@ _DSKIO_ERR_PARAM: ret _DSKIO_OK_UNIT: + call WK_GET_STORAGE_DEV_FLAGS + jp nz,_DSKIO_IMPL_STDEV + ld a,b pop bc rrc c ;Now C:7 = 0 to read, 1 to write @@ -337,6 +340,62 @@ CALL_XFER: ret + ;--- DSKIO for storage devices (mounted file) --- + +_DSKIO_IMPL_STDEV: + pop af + + jp c,_DSKIO_ERR_WPROT ;No write support for now + + push hl + push bc + + ld h,0 + ld l,d + ld d,e + ld e,0 + sla d + rl l + rl h ;HLDE = DE*512 + call HWF_SEEK_FILE + + pop bc + pop hl + ld c,b + ld b,0 + or a + jr z,_DSKIO_IMPL_STDEV_SEEKOK + dec a + ld a,8 ;Record not found + scf + ret z + ld a,12 ;Other error + ret + +_DSKIO_IMPL_STDEV_SEEKOK: + ld b,c + + ;TODO: use XFER if necessary + + sla b + ld c,0 ;BC = B*512 + call HWF_READ_FILE + srl b ;B = BC/512 + + or a + ld a,12 + scf + ret nz + + xor a + ret + +_DSKIO_ERR_WPROT: + xor a + scf + ret + + ; ----------------------------------------------------------------------------- ; DSKCHG ; ----------------------------------------------------------------------------- @@ -360,6 +419,11 @@ CALL_XFER: DSKCHG_IMPL: call CHECK_SAME_DRIVE + push af + call WK_GET_STORAGE_DEV_FLAGS + jp nz,_DSKCHG_IMPL_STDEV + pop af + cp 2 ld a,12 ccf @@ -386,6 +450,12 @@ DSKCHG_IMPL: xor a ret +_DSKCHG_IMPL_STDEV: + pop af + xor a + ld b,1 + ret + ; ----------------------------------------------------------------------------- ; GETDPB diff --git a/msx/bank1/inihrd_inienv.asm b/msx/bank1/inihrd_inienv.asm index 388384c..f847f64 100644 --- a/msx/bank1/inihrd_inienv.asm +++ b/msx/bank1/inihrd_inienv.asm @@ -50,5 +50,9 @@ DELAY_AFTER_PRINT: call HWF_MOUNT_DISK ret c + call WK_INIT_FOR_STORAGE_DEV + xor a + call WK_SET_LAST_REL_DRIVE + call DO_BOOT_MENU ret diff --git a/msx/bank1/work_area.asm b/msx/bank1/work_area.asm index 3ea7ab5..7933165 100644 --- a/msx/bank1/work_area.asm +++ b/msx/bank1/work_area.asm @@ -309,6 +309,7 @@ WK_GET_LAST_REL_DRIVE: ; Initialize work area for a storage device WK_INIT_FOR_STORAGE_DEV: + call WK_ZERO call _WK_GETWRK ld (ix),80h ld (ix+1),0 @@ -322,10 +323,16 @@ WK_INIT_FOR_STORAGE_DEV: ; NZ if a storage device is connected, Z otherwise WK_GET_STORAGE_DEV_FLAGS: + push hl + push de + push bc push ix call _WK_GETWRK ld a,(ix) pop ix + pop bc + pop de + pop hl bit 7,a ret From d13160e7ff006881ff4821e4efea1f7433edaf4f Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sun, 24 Jan 2021 17:41:17 +0100 Subject: [PATCH 20/65] Implement DSKIO via XFER for USB storage devices. --- msx/bank1/boot_menu.asm | 2 +- msx/bank1/ch376.asm | 3 ++ msx/bank1/dskio_dskchg.asm | 108 +++++++++++++++++++++++++++++++------ 3 files changed, 95 insertions(+), 18 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 9bf5dfb..db77331 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -1033,7 +1033,7 @@ BM_HELP_2: ; Variables ; ----------------------------------------------------------------------------- -_BM_VARS_BASE: equ 0E000h +_BM_VARS_BASE: equ 0C800h BM_NUM_PAGES: equ _BM_VARS_BASE BM_CUR_PAGE: equ BM_NUM_PAGES+1 diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index 1ac5408..76a65d7 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -865,6 +865,7 @@ _HWF_SEEK_FILE_CUR_POINTER: ; Output: A = 0: Ok ; 1: Error ; BC = How many bytes actually read +; HL = Address after last byte read HWF_READ_FILE: if USE_FAKE_STORAGE_DEVICE=1 @@ -902,10 +903,12 @@ _HWF_READ_FILE_LOOP: _HWF_READ_FILE_END: pop hl ;Address after the last byte retrieved pop de ;Initial dest address + push hl or a sbc hl,de push hl pop bc + pop hl ret diff --git a/msx/bank1/dskio_dskchg.asm b/msx/bank1/dskio_dskchg.asm index 849fa21..8ac5639 100644 --- a/msx/bank1/dskio_dskchg.asm +++ b/msx/bank1/dskio_dskchg.asm @@ -60,6 +60,9 @@ _DSKIO_OK_UNIT: call WK_GET_STORAGE_DEV_FLAGS jp nz,_DSKIO_IMPL_STDEV + + ;--- DSKIO for floppy disk drives --- + ld a,b pop bc rrc c ;Now C:7 = 0 to read, 1 to write @@ -121,22 +124,8 @@ _DSKIO_OK_CMD: ;* Check if we can transfer sectors directly or we need to transfer one by one. ;* We'll start with one by one transfer if page 1 is involved in the transfer. - bit 7,d - jr nz,_DSKIO_DIRECT_TRANSFER ;Transfer starts at >= 8000h - bit 6,d - jr nz,_DSKIO_ONE_BY_ONE ;Transfer starts at >= 4000h and <8000h - push de - push bc - ex de,hl - sla b - ld c,0 ;BC = Sectors * 512 - add hl,bc - dec hl ;Now HL = Last transfer address - pop bc - pop de - ld a,h - cp 40h ;If transfer starts at <4000h, it must end at <4000h for direct transfer - jr nc,_DSKIO_ONE_BY_ONE + call CHECK_XFER_IS_NEEDED + jr c,_DSKIO_ONE_BY_ONE ;>>> Direct transfer ; We transfer sectors directly from/to the source/target address, @@ -375,8 +364,14 @@ _DSKIO_IMPL_STDEV: _DSKIO_IMPL_STDEV_SEEKOK: ld b,c - ;TODO: use XFER if necessary + ex de,hl + call CHECK_XFER_IS_NEEDED + ex de,hl + jr c,_DSKIO_IMPL_STDEV_XFER + + ;* Direct transfer +_DSKIO_IMPL_STDEV_DIRECT: sla b ld c,0 ;BC = B*512 call HWF_READ_FILE @@ -390,9 +385,88 @@ _DSKIO_IMPL_STDEV_SEEKOK: xor a ret + ;* Transfer using XFER + +_DSKIO_IMPL_STDEV_XFER: + ld c,0 +_DSKIO_IMPL_STDEV_XFER_LOOP: + push bc ;B=Sectors left, C=Sectors transferred + push hl ;Dest address + + ld hl,(SECBUF) + ld bc,512 + call HWF_READ_FILE + or a + jr nz,_DSKIO_IMPL_STDEV_XFER_ERR + ld a,b + cp 2 + jr c,_DSKIO_IMPL_STDEV_XFER_ERR ;Error if less than 1 sector transferred + + pop de + push de + + ld hl,(SECBUF) + ld bc,512 + call CALL_XFER + + pop hl + pop bc + inc c + inc h + inc h ;HL=HL+512 + djnz _DSKIO_IMPL_STDEV_XFER_LOOP + + ld b,c + xor a + ret + +_DSKIO_IMPL_STDEV_XFER_ERR: + pop hl + pop bc + ld b,c + ld a,12 + scf + ret + _DSKIO_ERR_WPROT: xor a + ld b,0 + scf + ret + + + ;-- Check if transfer can be done directly or if we need to use XFER + ; (XFER will be needed if page 1 is involved in the transfer). + ; + ; Input: DE = Transfer address + ; B = How many sectors to transfer + ; Output: Cy = 0 if direct transfer is possible + ; 1 if XFER is needed + +CHECK_XFER_IS_NEEDED: + ld a,(XFER) + cp 0C9h + ret z ;Sanity check: we can't use XFER if it isn't enabled + + bit 7,d scf + ccf + ret nz ;Transfer starts at >= 8000h, so direct ok + bit 6,d + scf + ret nz ;Transfer starts at >= 4000h and <8000h, so XFER needed + push de + push bc + ex de,hl + sla b + ld c,0 ;BC = Sectors * 512 + add hl,bc + dec hl ;Now HL = Last transfer address + pop bc + pop de + ld a,h + cp 40h ;If transfer starts at <4000h, it must end at <4000h for direct transfer + ccf ret From ee511f0f16a80c0b2e27fc4d75ec18695ba9dd0b Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Mon, 25 Jan 2021 22:31:33 +0100 Subject: [PATCH 21/65] Implemented file write in the .NET sandbox. --- dotNet/Sandbox/Program.cs | 26 ++++++++++- dotNet/Usb/CH376UsbHostHardware.cs | 73 ++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/dotNet/Sandbox/Program.cs b/dotNet/Sandbox/Program.cs index 458c693..988c3ec 100644 --- a/dotNet/Sandbox/Program.cs +++ b/dotNet/Sandbox/Program.cs @@ -61,9 +61,19 @@ static void _Main(string[] args) foreach (var name in files) Console.WriteLine(name); + Console.WriteLine("Writing file... " + hw.WriteFileContents("NBASIC.TXT", longString)); Console.WriteLine(); - Console.WriteLine("Contents of DSK/DRIVER.ASM:"); - Console.Write(hw.ReadFileContents("DRIVER.ASM")); + + Console.WriteLine(); + if (!hw.ChangeDir("/DSK")) + { + Console.WriteLine("*** Can't change to dir DSK"); + } + else + { + Console.WriteLine("Contents of DSK/NBASIC.TXT:"); + Console.Write(hw.ReadFileContents("NBASIC.TXT")); + } } Console.ReadKey(); return; @@ -339,5 +349,17 @@ private static void PrintHexDump(byte[] data) Console.WriteLine(); } } + + const string longString = @"NestorBASIC 1.0 release date is july 2003, whilst the last beta, version 0.07, was released in july 1998. Yes, the NestorBASIC project has remained abandoned for exactly five years. + +The story is as follows. In 1998 a technical failure (the SCSI cable I used those days was bullshit) caused a crash in my computer, and when restarting I discovered that the FAT of the hard disk partition where my programs were stored was completely smashed. With a lot of patience and a sectors editor I could recover almost all of the source codes, but one of the lost ones was NestorBASIC. + +And you may ask: ""But you hadn't any backup copy?"" Yes, I had the NestorBASIC directory mirrored in another partition of the hard disk... but it was version 0.06, and a lot of changes were made when stepping to version 0.07. So, since NestorBASIC 0.07 was already quite complete, I decided to abandon the project. + +And time passed...until may 2003. While I was looking at Kyoko playing Bubble Rain, I began to think: ""It is really a nice game, and the best part is that it uses NestorBASIC, what a pity that I lost the source code... it is the only of my programs that are used regularly by other MSX users (more or less), if I could only recover it and improve it a little... blah blah..."" + +So I took a crazy decision: I would dissassemble NestorBASIC 0.07 and, comparing the result with the sources of version 0.06, I would rebuild the lost sources and from that point I would make version 1.0. And I really did it: one month of hard work later, NestorBASIC 1.0 was released, with a lot of failures corrected and with support for InterNestor Suite. + +I hope that it was worth the effort, and that soon MSX programmers around the world will develop a lot of games and internet applications using NestorBASIC (well, just daydreaming)."; } } diff --git a/dotNet/Usb/CH376UsbHostHardware.cs b/dotNet/Usb/CH376UsbHostHardware.cs index 81ad606..d85b539 100644 --- a/dotNet/Usb/CH376UsbHostHardware.cs +++ b/dotNet/Usb/CH376UsbHostHardware.cs @@ -42,6 +42,10 @@ public class CH376UsbHostHardware : IUsbHostHardware, IUsbHardwareShortcuts const byte CMD_BYTE_LOCATE = 0x39; const byte CMD_BYTE_READ = 0x3A; const byte CMD_BYTE_RD_GO = 0x3B; + const byte CMD_WR_REQ_DATA = 0x2D; + const byte CMD_BYTE_WRITE = 0x3C; + const byte CMD_BYTE_WRITE_GO = 0x3D; + const byte CMD_FILE_CREATE = 0x34; private readonly ICH376Ports ch; private static readonly byte[] noData = new byte[0]; @@ -469,5 +473,74 @@ public string ReadFileContents(string filename) while (result == UsbPacketResult.USB_INT_DISK_READ); } } + + public string WriteFileContents(string filename, string contents) + { + UsbPacketResult result; + + ch.WriteCommand(CMD_SET_FILE_NAME); + ch.WriteMultipleData(Encoding.ASCII.GetBytes(filename + "\0")); + ch.WriteCommand(CMD_FILE_OPEN); + result = WaitAndGetResult(); + if(result == UsbPacketResult.ERR_MISS_FILE) + { + Console.WriteLine(">>> File doesn't exist, creating"); + ch.WriteCommand(CMD_FILE_CREATE); + result = WaitAndGetResult(); + if (result != UsbPacketResult.Ok) + { + return "*** Error creating file: received " + result.ToString(); + } + } + if (result != UsbPacketResult.Ok) + return "*** Error opening file: " + result.ToString(); + + var bytesToWrite = Encoding.ASCII.GetBytes(contents); + + ch.WriteCommand(CMD_BYTE_WRITE); + ch.WriteData((byte)(bytesToWrite.Length & 0xFF)); + ch.WriteData((byte)(bytesToWrite.Length >> 8)); + result = WaitAndGetResult(); + + while(result != UsbPacketResult.Ok) + { + if(result != UsbPacketResult.USB_INT_DISK_WRITE) + { + return "*** Error writing file: received " + result.ToString(); + } + + ch.WriteCommand(CMD_WR_REQ_DATA); + var nextChunkSize = ch.ReadData(); + var chunk = bytesToWrite.Take(nextChunkSize).ToArray(); + //For some reason CH376PortsViaNoobtocol.WriteMultipleData doesn't work for 255 bytes... + for (int i = 0; i < chunk.Length; i++) ch.WriteData(chunk[i]); + //ch.WriteMultipleData(chunk); + + bytesToWrite = bytesToWrite.Skip(nextChunkSize).ToArray(); + + ch.WriteCommand(CMD_BYTE_WRITE_GO); + result = WaitAndGetResult(); + } + + ch.WriteCommand(CMD_BYTE_WRITE); + ch.WriteData(0); + ch.WriteData(0); + result = WaitAndGetResult(); + if(result != UsbPacketResult.Ok) + { + return "*** Error updating file dir entry after write: " + result.ToString(); + } + + return ">>> Write ok!"; + } + + public bool ChangeDir(string dir) + { + ch.WriteCommand(CMD_SET_FILE_NAME); + ch.WriteMultipleData(Encoding.ASCII.GetBytes(dir + "\0")); + ch.WriteCommand(CMD_FILE_OPEN); + var result = WaitAndGetResult(); + return result == UsbPacketResult.ERR_OPEN_DIR; + } } } From 45de9f6f0fe1378b9829d2fc142ad42686e9e816 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 26 Jan 2021 17:17:08 +0100 Subject: [PATCH 22/65] USB menu: show a "Mounting file and booting" message on mount --- msx/bank1/boot_menu.asm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index db77331..3a519d0 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -226,6 +226,11 @@ _BM_DO_ENTER_FILE_IS_OPEN: call WK_GET_STORAGE_DEV_FLAGS or 1 ;There's a file open call WK_SET_STORAGE_DEV_FLAGS + + call BM_CLEAR_INFO_AREA + ld hl,BM_MOUNTING_BOOTING_S + call BM_PRINT_STATUS + ret ;Continue computer boot process ;--- Print the string HL in the status area and wait for a key press @@ -997,6 +1002,9 @@ BM_FILE_NOT_FOUND_S: BM_ERROR_OPENING_FILE_S: db "Error opening file/dir! Press any key",0 +BM_MOUNTING_BOOTING_S: + db "Mounting file and booting...",0 + BM_HELP_1: db " Cursors: select file or directory",13,10 db 13,10 From 15fc246a035df9f63f43a35ebc2dbd3da694f902 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 26 Jan 2021 17:18:21 +0100 Subject: [PATCH 23/65] Implement sector write via DSKIO for mounted disk image files. --- msx/bank1/ch376.asm | 74 +++++++++++++++++++++++++++++ msx/bank1/dskio_dskchg.asm | 93 ++++++++++++++++++++++++++++++------- msx/bank1/verbose_reset.asm | 2 +- 3 files changed, 151 insertions(+), 18 deletions(-) diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index 76a65d7..cd80a66 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -65,6 +65,7 @@ CH_CMD_ABORT_NAK: equ 17h CH_CMD_GET_STATUS: equ 22h CH_CMD_RD_USB_DATA0: equ 27h CH_CMD_WR_HOST_DATA: equ 2Ch +CH_CMD_WR_REQ_DATA: equ 2Dh CH_CMD_SET_FILE_NAME: equ 2Fh CH_CMD_DISK_CONNECT: equ 30h CH_CMD_DISK_MOUNT: equ 31h @@ -74,6 +75,8 @@ CH_CMD_FILE_CLOSE: equ 36h CH_CMD_BYTE_LOCATE: equ 39h CH_CMD_BYTE_READ: equ 3Ah CH_CMD_BYTE_RD_GO: equ 3Bh +CH_CMD_BYTE_WRITE: equ 3Ch +CH_CMD_BYTE_WRITE_GO: equ 3Dh CH_CMD_SET_ADDRESS: equ 45h CH_CMD_GET_DESCR: equ 46h CH_CMD_SET_CONFIG: equ 49h @@ -912,6 +915,75 @@ _HWF_READ_FILE_END: ret +; ----------------------------------------------------------------------------- +; HWF_WRITE_FILE: Write to the currently mounted file +; ----------------------------------------------------------------------------- +; Input: BC = How many bytes to write +; HL = Source address +; Output: A = 0: Ok +; 1: Error +; BC = How many bytes actually read +; HL = Address after last byte written + +HWF_WRITE_FILE: + if USE_FAKE_STORAGE_DEVICE=1 + ld a,1 + ld bc,2048 + ret + endif + + push hl + push hl + ld a,CH_CMD_BYTE_WRITE + out (CH_COMMAND_PORT),a + ld a,c + out (CH_DATA_PORT),a + ld a,b + out (CH_DATA_PORT),a + +_HWF_WRITE_FILE_LOOP: + call CH_WAIT_INT_AND_GET_RESULT + or a + jr z,_HWF_WRITE_FILE_END + cp CH_ST_INT_DISK_WRITE + ld a,1 + jr nz,_HWF_WRITE_FILE_END + + ld a,CH_CMD_WR_REQ_DATA + out (CH_COMMAND_PORT),a + in a,(CH_DATA_PORT) + ld b,a + + pop hl + ld c,CH_DATA_PORT + otir + push hl + + ld a,CH_CMD_BYTE_WRITE_GO + out (CH_COMMAND_PORT),a + + jr _HWF_WRITE_FILE_LOOP + +_HWF_WRITE_FILE_END: + push af + ld a,CH_CMD_BYTE_WRITE + out (CH_COMMAND_PORT),a + xor a + out (CH_DATA_PORT),a + out (CH_DATA_PORT),a + pop af + + pop hl ;Address after the last byte written + pop de ;Initial src address + push hl + or a + sbc hl,de + push hl + pop bc + pop hl + ret + + ; ----------------------------------------------------------------------------- ; Optional shortcut routines ; ----------------------------------------------------------------------------- @@ -1106,6 +1178,8 @@ _CH_WAIT_INT_AND_GET_RESULT_2: jr z,_CH_LD_A_B_RET cp CH_ST_INT_DISK_READ ret z + cp CH_ST_INT_DISK_WRITE + ret z cp CH_ST_INT_DISCONNECT jr z,_CH_NO_DEV_ERR cp CH_ST_INT_BUF_OVER diff --git a/msx/bank1/dskio_dskchg.asm b/msx/bank1/dskio_dskchg.asm index 8ac5639..2931d5f 100644 --- a/msx/bank1/dskio_dskchg.asm +++ b/msx/bank1/dskio_dskchg.asm @@ -61,7 +61,7 @@ _DSKIO_OK_UNIT: jp nz,_DSKIO_IMPL_STDEV - ;--- DSKIO for floppy disk drives --- + ;=== DSKIO for floppy disk drives === ld a,b pop bc @@ -329,13 +329,9 @@ CALL_XFER: ret - ;--- DSKIO for storage devices (mounted file) --- + ;=== DSKIO for storage devices (mounted file) === _DSKIO_IMPL_STDEV: - pop af - - jp c,_DSKIO_ERR_WPROT ;No write support for now - push hl push bc @@ -354,6 +350,8 @@ _DSKIO_IMPL_STDEV: ld b,0 or a jr z,_DSKIO_IMPL_STDEV_SEEKOK + + pop hl ;Discard input AF dec a ld a,8 ;Record not found scf @@ -364,14 +362,21 @@ _DSKIO_IMPL_STDEV: _DSKIO_IMPL_STDEV_SEEKOK: ld b,c + pop af + jp c,_DSKIO_IMPL_STDEW_WRITE + + + ;=== DSKIO for storage devices - READ === + +_DSKIO_IMPL_STDEW_READ: ex de,hl call CHECK_XFER_IS_NEEDED ex de,hl - jr c,_DSKIO_IMPL_STDEV_XFER + jr c,_DSKIO_R_STDEV_XFER ;* Direct transfer -_DSKIO_IMPL_STDEV_DIRECT: +_DSKIO_R_STDEV_DIRECT: sla b ld c,0 ;BC = B*512 call HWF_READ_FILE @@ -387,9 +392,9 @@ _DSKIO_IMPL_STDEV_DIRECT: ;* Transfer using XFER -_DSKIO_IMPL_STDEV_XFER: +_DSKIO_R_STDEV_XFER: ld c,0 -_DSKIO_IMPL_STDEV_XFER_LOOP: +_DSKIO_R_STDEV_XFER_LOOP: push bc ;B=Sectors left, C=Sectors transferred push hl ;Dest address @@ -414,23 +419,77 @@ _DSKIO_IMPL_STDEV_XFER_LOOP: inc c inc h inc h ;HL=HL+512 - djnz _DSKIO_IMPL_STDEV_XFER_LOOP + djnz _DSKIO_R_STDEV_XFER_LOOP ld b,c xor a ret -_DSKIO_IMPL_STDEV_XFER_ERR: - pop hl - pop bc - ld b,c + + ;=== DSKIO for storage devices - WRITE === + +_DSKIO_IMPL_STDEW_WRITE: + ex de,hl + call CHECK_XFER_IS_NEEDED + ex de,hl + jr c,_DSKIO_W_STDEV_XFER + + ;* Direct transfer + +_DSKIO_W_STDEV_DIRECT: + sla b + ld c,0 ;BC = B*512 + call HWF_WRITE_FILE + srl b ;B = BC/512 + + or a ld a,12 scf + ret nz + + xor a ret -_DSKIO_ERR_WPROT: + ;* Transfer using XFER + +_DSKIO_W_STDEV_XFER: + ld c,0 +_DSKIO_W_STDEV_XFER_LOOP: + push bc ;B=Sectors left, C=Sectors transferred + push hl ;Src address + + ld de,(SECBUF) + ld bc,512 + call CALL_XFER + + ld hl,(SECBUF) + ld bc,512 + call HWF_WRITE_FILE + or a + jr nz,_DSKIO_IMPL_STDEV_XFER_ERR + ld a,b + cp 2 + jr c,_DSKIO_IMPL_STDEV_XFER_ERR ;Error if less than 1 sector transferred + + pop hl + pop bc + inc c + inc h + inc h ;HL=HL+512 + djnz _DSKIO_W_STDEV_XFER_LOOP + + ld b,c xor a - ld b,0 + ret + + + ;=== DSKIO for storage devices - common === + +_DSKIO_IMPL_STDEV_XFER_ERR: + pop hl + pop bc + ld b,c + ld a,12 scf ret diff --git a/msx/bank1/verbose_reset.asm b/msx/bank1/verbose_reset.asm index fdb25be..0e7b72c 100644 --- a/msx/bank1/verbose_reset.asm +++ b/msx/bank1/verbose_reset.asm @@ -270,4 +270,4 @@ ERR_INQUIRY_S: db "ERROR querying the device name: ",0 STOR_FOUND_S: - db "USB storage device found:",13,10,0 + db "USB storage device found: ",0 From 9b99fa4ad1903d2f81d19a674279bb19e985aa32 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 28 Jan 2021 17:31:59 +0100 Subject: [PATCH 24/65] Implement directory navigation in the USB boot menu. --- msx/bank1/boot_menu.asm | 394 +++++++++++++++++++++++++++++++++------- 1 file changed, 324 insertions(+), 70 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 3a519d0..4a83525 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -6,7 +6,7 @@ ; standard USB mass storage device is plugged in). BM_FILES_BASE: equ 8010h - +BM_MAX_DIR_NAME_LENGTH: equ 64 ; ----------------------------------------------------------------------------- ; Boot menu entry point @@ -18,6 +18,15 @@ DO_BOOT_MENU: ld (BM_CURSOR_LAST),a ld (BM_NO_STOR_DEV),a + ld hl,BM_DSK_S + ld de,BM_CUR_DIR + ld bc,5 + ldir + ld a,1 + ld (BM_CUR_DIR_LEVEL),a + ld a,4 + ld (BM_CUR_DIR_LENGTH),a + ; Try opening DSK directory on the device if USE_FAKE_STORAGE_DEVICE = 0 @@ -47,66 +56,8 @@ DO_BOOT_MENU: call POSIT call BM_DRAW_LINE - ld h,2 - ld l,1 - call POSIT - ld a,"/" - call CHPUT - - ; Enumerate files, initialize paging - - ld a,1 - ld (BM_CUR_PAGE),a - - ld hl,BM_SCANNING_DIR_S - call BM_PRINT_STATUS - - ld hl,BM_FILES_BASE - ld bc,1290 - call HWF_ENUM_FILES - ld (BM_NUM_FILES),bc - push bc - - push hl ;Fill one extra page of 0s. - pop de ;This will be used to detect non-existing - inc de ;file positions in the last page. - ld (hl),0 - ld bc,59*11-1 - ldir - - pop hl - ld b,0 -_BM_CALC_NUM_PAGES: - ld a,h - or a - jr nz,_BM_CALC_NUM_PAGES_ADD - ld a,l - or a - jr z,_BM_CALC_NUM_PAGES_END - cp 60 - jr nc,_BM_CALC_NUM_PAGES_ADD - - inc b - jr _BM_CALC_NUM_PAGES_END - -_BM_CALC_NUM_PAGES_ADD: - inc b - ld de,60 - or a - sbc hl,de - jr _BM_CALC_NUM_PAGES - -_BM_CALC_NUM_PAGES_END: - ld a,b - or a - jr nz,_BM_CALC_NUM_PAGES_END_2 - inc a -_BM_CALC_NUM_PAGES_END_2: - ld (BM_NUM_PAGES),a - - xor a - ld (BM_CUR_ROW),a - ld (BM_CUR_COL),a + call BM_PRINT_CUR_DIR + call BM_ENUM_FILES ; ----------------------------------------------------------------------------- @@ -124,7 +75,10 @@ BM_ENTER_MAIN_LOOP: call BM_UPDATE_CUR_PAGE_PNT call BM_UPDATE_CUR_FILE_PNT call BM_POSIT_CUR_FILE - call BM_PRINT_CURRENT_FILE_AS_SELECTED + ld hl,(BM_NUM_FILES) + ld a,h + or l + call nz,BM_PRINT_CURRENT_FILE_AS_SELECTED ;--- This is the actual start of the loop @@ -143,6 +97,9 @@ _BM_MAIN_LOOP: call BM_ENTER_IS_PRESSED jp z,BM_DO_ENTER + call BM_BS_IS_PRESSED + jp z,BM_DO_BS + call BM_F1_IS_PRESSED jp z,BM_DO_HELP @@ -165,6 +122,9 @@ BM_START_OVER: ld (BM_NUM_PAGES),a call BM_CLEAR_INFO_AREA + xor a + ld (BM_CUR_DIR+1),a + call BM_PRINT_CUR_DIR ld hl,BM_RESETTING_DEVICE_S call BM_PRINT_STATUS @@ -193,21 +153,22 @@ BM_DO_ENTER: ld hl,(BM_CUR_FILE_PNT) push hl + ld de,BM_BUF + call BM_GENERATE_FILENAME pop ix bit 7,(ix+10) - jp nz,_BM_MAIN_LOOP ;For now entering directories is not supported + jp nz,BM_DO_ENTER_DIR - ld de,BM_BUF - call BM_GENERATE_FILENAME + ;* It's a file + +BM_DO_ENTER_FILE: ld hl,BM_BUF - call HWF_OPEN_FILE_DIR or a jr z,_BM_DO_ENTER_FILE_IS_OPEN - dec a - jp z,_BM_MAIN_LOOP ;TODO: handle entering directory - +_BM_DO_ENTER_OPEN_ERR: + dec a ;It's a dir: treat as other error (should never happen) dec a ld hl,BM_FILE_NOT_FOUND_S jr z,_BM_DO_ENTER_PRINT_ERR @@ -231,8 +192,63 @@ _BM_DO_ENTER_FILE_IS_OPEN: ld hl,BM_MOUNTING_BOOTING_S call BM_PRINT_STATUS + call KILBUF ret ;Continue computer boot process + ;* It's a directory + +BM_DO_ENTER_DIR: + ld hl,BM_BUF + ld c,"/" + call BM_STRLEN_C + ld (hl),0 + inc b ;Count also the additional "/" + ld a,(BM_CUR_DIR_LENGTH) + add b + cp BM_MAX_DIR_NAME_LENGTH+1 + jp nc,_BM_MAIN_LOOP ;Max dir length surpassed: can't change dir + + ld hl,BM_BUF + call HWF_OPEN_FILE_DIR + cp 1 + jp nz,_BM_DO_ENTER_OPEN_ERR + + ld hl,BM_CUR_DIR_LEVEL + inc (hl) + + ld a,(BM_CUR_DIR_LENGTH) + ld e,a + ld d,0 + ld hl,BM_CUR_DIR + add hl,de + + ld a,(BM_CUR_DIR_LEVEL) + cp 1 + jr z,_BM_DO_ENTER_DIR_WAS_ROOT + ld (hl),"/" + inc hl +_BM_DO_ENTER_DIR_WAS_ROOT: + + ex de,hl + ld hl,BM_BUF +_BM_COPY_DIR_NAME_LOOP: + ld a,(hl) + ld (de),a + inc hl + inc de + or a + jr nz,_BM_COPY_DIR_NAME_LOOP + + ld hl,BM_CUR_DIR + call BM_STRLEN + ld a,b + ld (BM_CUR_DIR_LENGTH),a + + call BM_PRINT_CUR_DIR + call BM_ENUM_FILES + jp BM_ENTER_MAIN_LOOP + + ;--- Print the string HL in the status area and wait for a key press BM_PRINT_STATUS_WAIT_KEY: @@ -242,6 +258,90 @@ BM_PRINT_STATUS_WAIT_KEY: jp KILBUF +;--- BS key press handler +; +; The CH376 doesn't support opening ".." so we'll have to +; cd to root and then to each dir on the current path +; stopping right before the last one :facepalm: + +BM_DO_BS: + ld a,(BM_CUR_DIR_LEVEL) + or a + jp z,_BM_MAIN_LOOP ;We are in the root dir already + + call BM_CLEAR_INFO_AREA + ld hl,BM_ENTERING_DIR_S + call BM_PRINT_STATUS + + ld hl,BM_ROOT_DIR_S + call HWF_OPEN_FILE_DIR + cp 1 + jr z,_BM_DO_BS_OPEN_ROOT_OK + +_BM_DO_BS_OPEN_ERROR: + xor a + ld (BM_CUR_DIR+1),a + call BM_PRINT_CUR_DIR + ld hl,BM_ERROR_OPENING_FILE_S + call BM_PRINT_STATUS_WAIT_KEY + xor a + ld (BM_NUM_FILES),a + ld (BM_NUM_FILES+1),a + inc a + ld (BM_NUM_PAGES),a + ld (BM_CUR_PAGE),a + ld (BM_CUR_DIR_LENGTH),a + jp BM_ENTER_MAIN_LOOP +_BM_DO_BS_OPEN_ROOT_OK: + + ld a,(BM_CUR_DIR_LEVEL) + dec a + jp z,_BM_DO_BS_LV1_END + ld b,a ;How many levels to go back + ld hl,BM_CUR_DIR ;Pointer to dir at current level, -1 + +_BM_DO_BS_LOOP: + push bc + push hl + ld (hl),"/" + inc hl +_BM_DO_BS_FIND_SLASH: + ld a,(hl) + inc hl + cp "/" + jr nz,_BM_DO_BS_FIND_SLASH + + dec hl + ld (hl),0 + ex (sp),hl ;Now HL=Start of dir name-1, (SP)=Terminator + inc hl + call HWF_OPEN_FILE_DIR + pop hl + pop bc + cp 1 + jr nz,_BM_DO_BS_OPEN_ROOT_OK + + djnz _BM_DO_BS_LOOP + +_BM_DO_BS_END: + ld hl,BM_CUR_DIR_LEVEL + dec (hl) +_BM_DO_BS_END_2: + ld hl,BM_CUR_DIR + call BM_STRLEN + ld a,b + ld (BM_CUR_DIR_LENGTH),a + call BM_PRINT_CUR_DIR + call BM_ENUM_FILES + jp BM_ENTER_MAIN_LOOP + +_BM_DO_BS_LV1_END: + xor a + ld (BM_CUR_DIR+1),a + ld (BM_CUR_DIR_LEVEL),a + jr _BM_DO_BS_END_2 + + ;--- Help loop, entered when F1 is pressed BM_DO_HELP: @@ -427,6 +527,66 @@ _BM_UPDATE_PAGE_END: ld (BM_CUR_COL),a jp BM_ENTER_MAIN_LOOP + + ;--- Enumerate files and initialize paging + +BM_ENUM_FILES: + ld a,1 + ld (BM_CUR_PAGE),a + + call BM_CLEAR_INFO_AREA + ld hl,BM_SCANNING_DIR_S + call BM_PRINT_STATUS + + ld hl,BM_FILES_BASE + ld bc,1290 + call HWF_ENUM_FILES + ld (BM_NUM_FILES),bc + push bc + + push hl ;Fill one extra page of 0s. + pop de ;This will be used to detect non-existing + inc de ;file positions in the last page. + ld (hl),0 + ld bc,59*11-1 + ldir + + pop hl + ld b,0 +_BM_CALC_NUM_PAGES: + ld a,h + or a + jr nz,_BM_CALC_NUM_PAGES_ADD + ld a,l + or a + jr z,_BM_CALC_NUM_PAGES_END + cp 60 + jr nc,_BM_CALC_NUM_PAGES_ADD + + inc b + jr _BM_CALC_NUM_PAGES_END + +_BM_CALC_NUM_PAGES_ADD: + inc b + ld de,60 + or a + sbc hl,de + jr _BM_CALC_NUM_PAGES + +_BM_CALC_NUM_PAGES_END: + ld a,b + or a + jr nz,_BM_CALC_NUM_PAGES_END_2 + inc a +_BM_CALC_NUM_PAGES_END_2: + ld (BM_NUM_PAGES),a + + xor a + ld (BM_CUR_ROW),a + ld (BM_CUR_COL),a + ret + + ; ----------------------------------------------------------------------------- ; Screen printing routines ; ----------------------------------------------------------------------------- @@ -756,6 +916,53 @@ _BM_PRINT_INVERTED_LOOP: ret +;--- Print the current directory in the top row + +BM_PRINT_CUR_DIR: + ld h,2 + ld l,1 + call POSIT + + ld a,(BM_CUR_DIR_LENGTH) + cp 41 + jr c,_BM_PRINT_CUR_DIR_DIRECT + + ld hl,BM_DOTS_BAR_S + call PRINT + + call BM_GET_LAST_DIR_PNT + call PRINT + jr _BM_PRINT_CUR_DIR_END + +_BM_PRINT_CUR_DIR_DIRECT: + ld hl,BM_CUR_DIR + call PRINT + +_BM_PRINT_CUR_DIR_END: + ld a,27 + call CHPUT + ld a,'K' + jp CHPUT ;Delete to end of line + + +;--- Get pointer to the last part of the current directory name +; (assuming current dir is not root) + +BM_GET_LAST_DIR_PNT: + ld hl,BM_CUR_DIR + ld de,(BM_CUR_DIR_LENGTH) + ld d,0 + add hl,de +_BM_GET_LAST_DIR_PNT_LOOP: + dec hl + ld a,(hl) + cp "/" + jr nz,_BM_GET_LAST_DIR_PNT_LOOP + + inc hl + ret + + ; ----------------------------------------------------------------------------- ; Keyboard scanning routines ; ----------------------------------------------------------------------------- @@ -815,6 +1022,22 @@ _BM_ENTER_IS_PRESSED_WAIT_RELEASE: ret +;--- Check if BS is pressed +; Output: Z if pressed, NZ if not + +BM_BS_IS_PRESSED: + ld de,2007h + jp BM_KEY_CHECK + ret nz + +_BM_BS_IS_PRESSED_WAIT_RELEASE: + ld de,2007h + call BM_KEY_CHECK + jr z,_BM_BS_IS_PRESSED_WAIT_RELEASE + xor a + ret + + ;--- Check if a cursor key is pressed ; Output: A=0: no cursor key is pressed ; 1,2,3,4: up,right,down,left @@ -957,6 +1180,25 @@ _BM_MULT_60_LOOP: djnz _BM_MULT_60_LOOP ret + +;--- Calculate length of zero-terminated string +; Input: HL = String +; Output: B = Length +; HL points to the zero + +BM_STRLEN: + ld c,0 +BM_STRLEN_C: + ld b,0 +_BM_STRLEN_LOOP: + ld a,(hl) + cp c + ret z + inc hl + inc b + jr _BM_STRLEN_LOOP + + ; ----------------------------------------------------------------------------- ; Text strings ; ----------------------------------------------------------------------------- @@ -982,7 +1224,7 @@ BM_ROOT_DIR_S: db "/",0 BM_DSK_S: - db "DSK",0 + db "/DSK",0 BM_NO_FILES_S: db "No files found in current directory!",0 @@ -1005,6 +1247,15 @@ BM_ERROR_OPENING_FILE_S: BM_MOUNTING_BOOTING_S: db "Mounting file and booting...",0 +BM_ENTERING_DIR_S: + db "Entering directory...",0 + +BM_DOTS_BAR_S: + db "/.../",0 + +BM_DOTDOT_S: + db "..",0 + BM_HELP_1: db " Cursors: select file or directory",13,10 db 13,10 @@ -1053,3 +1304,6 @@ BM_CUR_ROW: equ BM_CUR_FILE_PNT+2 ;Current logical row, 0-19 BM_CUR_COL: equ BM_CUR_ROW+1 ;Current logical column, 0-2 BM_CURSOR_LAST: equ BM_CUR_COL+1 ;Result of last call to BM_CURSOR_IS_PRESSED BM_NO_STOR_DEV: equ BM_CURSOR_LAST+1 ;FFh if F5 was pressed and no storage device was found +BM_CUR_DIR_LEVEL: equ BM_NO_STOR_DEV+1 ;Current direcrory level, 0 is root +BM_CUR_DIR: equ BM_CUR_DIR_LEVEL+1 ;Current directory, up to BM_MAX_DIR_NAME_LENGTH-1 chars + 0 +BM_CUR_DIR_LENGTH: equ BM_CUR_DIR+BM_MAX_DIR_NAME_LENGTH+1 \ No newline at end of file From e62dcf4b81d23a0efcfe846991a6cb7eb55ee020 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 29 Jan 2021 15:56:41 +0100 Subject: [PATCH 25/65] Mount disk image files as read-only if the read-only attribute is set for the file --- msx/bank1/boot_menu.asm | 16 +++++++++++--- msx/bank1/ch376.asm | 45 ++++++++++++++++++++++++++++++++++---- msx/bank1/dskio_dskchg.asm | 6 +++++ msx/bank1/work_area.asm | 1 + 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 4a83525..4b8b6ff 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -184,8 +184,18 @@ _BM_DO_ENTER_WAIT_RELEASE: ;In case the "any key" pressed is enter jp _BM_MAIN_LOOP _BM_DO_ENTER_FILE_IS_OPEN: + call HWF_GET_FILE_ATTR + dec a + jr z,_BM_DO_ENTER_FILE_IS_OPEN_ATTR_OK ;Error, assume not read-only + ld a,b ;Attributes byte, read-only in bit 0 + rla ;Now read-only in bit 1 + and 2 + +_BM_DO_ENTER_FILE_IS_OPEN_ATTR_OK: + ld b,a call WK_GET_STORAGE_DEV_FLAGS or 1 ;There's a file open + or b ;Maybe read-only flag call WK_SET_STORAGE_DEV_FLAGS call BM_CLEAR_INFO_AREA @@ -258,7 +268,7 @@ BM_PRINT_STATUS_WAIT_KEY: jp KILBUF -;--- BS key press handler +;--- BS key press handler, go to parent directory ; ; The CH376 doesn't support opening ".." so we'll have to ; cd to root and then to each dir on the current path @@ -303,7 +313,7 @@ _BM_DO_BS_OPEN_ROOT_OK: _BM_DO_BS_LOOP: push bc push hl - ld (hl),"/" + ld (hl),"/" ;Restore the slash we had zero-ed in the last loop step inc hl _BM_DO_BS_FIND_SLASH: ld a,(hl) @@ -312,7 +322,7 @@ _BM_DO_BS_FIND_SLASH: jr nz,_BM_DO_BS_FIND_SLASH dec hl - ld (hl),0 + ld (hl),0 ;Temporarily replace ending slash with 0 for HWF_OPEN_FILE_DIR ex (sp),hl ;Now HL=Start of dir name-1, (SP)=Terminator inc hl call HWF_OPEN_FILE_DIR diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index cd80a66..f3221cf 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -72,6 +72,7 @@ CH_CMD_DISK_MOUNT: equ 31h CH_CMD_FILE_OPEN: equ 32h CH_CMD_FILE_ENUM_GO: equ 33h CH_CMD_FILE_CLOSE: equ 36h +CH_CMD_DIR_INFO_READ: equ 37h CH_CMD_BYTE_LOCATE: equ 39h CH_CMD_BYTE_READ: equ 3Ah CH_CMD_BYTE_RD_GO: equ 3Bh @@ -343,6 +344,7 @@ _CH_DATA_IN_LOOP: jr nz,_CH_DATA_IN_ERR ;DONE if error call CH_READ_DATA + ld c,b ld b,0 add ix,bc ;Update received so far count _CH_DATA_IN_NO_MORE_DATA: @@ -984,6 +986,41 @@ _HWF_WRITE_FILE_END: ret +; ----------------------------------------------------------------------------- +; HWF_GET_FILE_ATTR: Get attributes byte of currently mounted file +; ----------------------------------------------------------------------------- +; Output: A = 0: Ok +; 1: Error +; B = Attributes byte if ok + +HWF_GET_FILE_ATTR: + ld a,CH_CMD_DIR_INFO_READ + out (CH_COMMAND_PORT),a + ld a,0FFh + out (CH_DATA_PORT),a + push hl + push bc + call CH_WAIT_INT_AND_GET_RESULT + pop bc + pop hl + cp USB_ERR_OK + ld a,1 + ret nz + + ld a,CH_CMD_RD_USB_DATA0 + out (CH_COMMAND_PORT),a + ld c,CH_DATA_PORT + ld b,11+1 ;Discard bytes counter and filename + call _CH_READ_DISCARD_DATA_LOOP + in a,(c) ;Attributes byte + ld e,a + ld b,20 ;Discard the rest of the directory info + call _CH_READ_DISCARD_DATA_LOOP + xor a + ld b,e + ret + + ; ----------------------------------------------------------------------------- ; Optional shortcut routines ; ----------------------------------------------------------------------------- @@ -1340,8 +1377,8 @@ CH_ISSUE_TOKEN: ; Read data from the CH data buffer ; ; Input: HL = Destination address for the data -; Output: C = Amount of data received (0-64) -; HL = HL + C +; Output: B = Amount of data received (0-64) +; HL = HL + B CH_READ_DATA: ld a,CH_CMD_RD_USB_DATA0 @@ -1361,13 +1398,13 @@ CH_READ_DATA: ld b,d inir - ld c,d + ld b,d ret _CH_READ_DISCARD_DATA_LOOP: in a,(c) djnz _CH_READ_DISCARD_DATA_LOOP - ld c,d + ld b,d ret diff --git a/msx/bank1/dskio_dskchg.asm b/msx/bank1/dskio_dskchg.asm index 2931d5f..0425005 100644 --- a/msx/bank1/dskio_dskchg.asm +++ b/msx/bank1/dskio_dskchg.asm @@ -429,6 +429,12 @@ _DSKIO_R_STDEV_XFER_LOOP: ;=== DSKIO for storage devices - WRITE === _DSKIO_IMPL_STDEW_WRITE: + call WK_GET_STORAGE_DEV_FLAGS + and 2 ;Read only? + ld a,0 + scf + ret nz + ex de,hl call CHECK_XFER_IS_NEEDED ex de,hl diff --git a/msx/bank1/work_area.asm b/msx/bank1/work_area.asm index 7933165..338daaf 100644 --- a/msx/bank1/work_area.asm +++ b/msx/bank1/work_area.asm @@ -37,6 +37,7 @@ ; (if a floppy is connected it'll be 0 since the byte holds ; the OUT endpoint number) ; bit 0: set to 1 if there's a file mounted +; bit 1: set if mounted in read only mode ; +1: Current directory depth: ; 0: no directory currently open ; 1: root directory, etc From b581d4dd6c2c68fea54d0809863a5502bb8ae3a8 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 29 Jan 2021 16:01:43 +0100 Subject: [PATCH 26/65] USB boot menu: don't enumerate files having the 'hidden' attribute set --- msx/bank1/ch376.asm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index f3221cf..e61f579 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -780,6 +780,16 @@ _HWF_ENUM_FILES_LOOP: pop bc ld a,(hl) ;File attributes byte + bit 1,a ;"Hidden" attribute set? + jr z,_HWF_ENUM_NO_HIDDEN + + push bc + ld bc,-11 + add hl,bc + pop bc + jr _HWF_ENUM_DIR_NEXT + +_HWF_ENUM_NO_HIDDEN: and 10h jr z,_HWF_ENUM_DIR_OK dec hl From 26d78ea8c65177c64cfaa0f1d588c3aa80b1a2d7 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 2 Feb 2021 13:54:25 +0100 Subject: [PATCH 27/65] Add the CALL USBEMNU command, preserves BASIC program and screen config. Also now the max amount of file that can be enumerated depends on the amount of free memory (min in 24 for 1K free). --- msx/bank0/kernel.asm | 8 +-- msx/bank0/oemstat.asm | 28 +++++++++- msx/bank1/boot_menu.asm | 110 +++++++++++++++++++++++++++++++++++++--- msx/bank1/ch376.asm | 5 ++ msx/bank1/misc.asm | 38 ++++++++++++++ msx/constants.asm | 10 ++++ 6 files changed, 187 insertions(+), 12 deletions(-) diff --git a/msx/bank0/kernel.asm b/msx/bank0/kernel.asm index fcde257..090066c 100644 --- a/msx/bank0/kernel.asm +++ b/msx/bank0/kernel.asm @@ -68,7 +68,7 @@ CHSNS equ 0009CH LPTOUT equ 000A5H ;BREAKX equ 000B7H CKCNTC equ 000BDH -ERAFNK equ 000CCH +;ERAFNK equ 000CCH TOTEXT equ 000D2H SNSMAT equ 00141H PHYDIO equ 00144H @@ -223,8 +223,8 @@ RDPRIM equ 0F380H WRPRIM equ 0F385H CLPRIM equ 0F38CH CLPRM1 equ 0F398H -LINLEN equ 0F3B0H -CNSDFG equ 0F3DEH +;LINLEN equ 0F3B0H +;CNSDFG equ 0F3DEH LPTPOS equ 0F415H PRTFLG equ 0F416H CURLIN equ 0F41CH @@ -242,7 +242,7 @@ FRETOP equ 0F69BH AUTLIN equ 0F6ABH SAVSTK equ 0F6B1H VARTAB equ 0F6C2H -STREND equ 0F6C6H +;STREND equ 0F6C6H DAC equ 0F7F6H ARG equ 0F847H MAXFIL equ 0F85FH diff --git a/msx/bank0/oemstat.asm b/msx/bank0/oemstat.asm index bb130f9..92e8474 100644 --- a/msx/bank0/oemstat.asm +++ b/msx/bank0/oemstat.asm @@ -69,9 +69,12 @@ OEM_COMMANDS: dw OEMC_USBRESET db "USBERROR",0 dw OEMC_USBERROR - db 0 endif + db "USBMENU",0 + dw OEMC_USBMENU + db 0 + ;--- CALL USBRESET ; Resets USB hardware and prints device info, just like at boot time @@ -125,6 +128,8 @@ _OEMC_USBERROR_ASC: ld a,e call OEM_PRINTHEX ld hl,OEM_S_H_CRLF + +OEM_PRINT_AND_END: call OEM_PRINT OEM_END: @@ -142,6 +147,27 @@ OEM_S_ASCQ: db "ASCQ: ",0 OEM_S_NOERRDATA: db "No error data recorded",0 + + + ;--- CALL USBMENU + ; Open the USB menu if there's a storage device inserted + +OEMC_USBMENU: + ld ix,DO_BOOT_MENU + ld iy,ROM_BANK_1 + call CALL_BANK + dec a + ld hl,OEM_S_NO_STDEV + jp z,OEM_PRINT_AND_END + dec a + ld hl,OEM_S_NO_MEM + jp z,OEM_PRINT_AND_END + jp OEM_END + +OEM_S_NO_STDEV: + db "No USB storage device present",0 +OEM_S_NO_MEM: + db "Not enough memory",0 ; ----------------------------------------------------------------------------- diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 4b8b6ff..bdfa7d5 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -10,10 +10,56 @@ BM_MAX_DIR_NAME_LENGTH: equ 64 ; ----------------------------------------------------------------------------- ; Boot menu entry point +; +; Output: A=0 if the menu was actually opened +; 1 if no storage device was found +; 2 if not enough memory ; ----------------------------------------------------------------------------- DO_BOOT_MENU: + ;Return with error if no storage device was found + + call USB_CHECK_DEV_CHANGE + + call WK_GET_STORAGE_DEV_FLAGS + ld a,1 + ret z + + ;Return with error if we have less than 1K of free space + + ld hl,0 + add hl,sp + ld de,(STREND) + or a + sbc hl,de + ld a,h + cp 4 + ld a,2 + ret c + + ld bc,100+660 ;Work stack space + space for one page of 0s + or a + sbc hl,bc + push hl + pop bc + ld de,11 + call DIVIDE_16 + ld (BM_MAX_FILES_TO_ENUM),bc + + call BM_SCREEN_BAK + ld a,40 + ld (LINL40),a + call INITXT + call ERAFNK + + call DO_BOOT_MENU_MAIN + + call BM_SCREEN_REST + xor a + ret + +DO_BOOT_MENU_MAIN: xor a ld (BM_CURSOR_LAST),a ld (BM_NO_STOR_DEV),a @@ -43,9 +89,7 @@ DO_BOOT_MENU: ; Init screen mode, draw fixed elements - ld a,40 - ld (LINL40),a - call INITXT + call CLS ld h,1 ld l,2 @@ -87,6 +131,10 @@ _BM_MAIN_LOOP: call BREAKX ret c + ld de,0407h + call BM_KEY_CHECK + ret z + call BM_F5_IS_PRESSED jp z,BM_START_OVER @@ -129,7 +177,7 @@ BM_START_OVER: call BM_PRINT_STATUS call HWF_MOUNT_DISK - jp nc,DO_BOOT_MENU + jp nc,DO_BOOT_MENU_MAIN ld a,0FFh ld (BM_NO_STOR_DEV),a @@ -549,7 +597,7 @@ BM_ENUM_FILES: call BM_PRINT_STATUS ld hl,BM_FILES_BASE - ld bc,1290 + ld bc,(BM_MAX_FILES_TO_ENUM) ; 1290 call HWF_ENUM_FILES ld (BM_NUM_FILES),bc push bc @@ -1209,6 +1257,50 @@ _BM_STRLEN_LOOP: jr _BM_STRLEN_LOOP +;--- Backup current screen mode + +BM_SCREEN_BAK: + ld a,(SCRMOD) + ld (BM_SCRMOD_BAK),a + ld a,(LINLEN) + ld (BM_LINLEN_BAK),a + ld a,(CNSDFG) + ld (BM_FNK_BAK),a + ret + + +;--- Restore previous screen mode + +BM_SCREEN_REST: + ld a,(BM_SCRMOD_BAK) + dec a + jr z,_BM_SCREEN_REST_W32 + + ; Restore SCREEN 0 + +_BM_SCREEN_REST_W40: + ld a,(BM_LINLEN_BAK) + ld (LINL40),a + call INITXT + jr _BM_SCREEN_REST_OK + + ; Restore SCREEN 1 + +_BM_SCREEN_REST_W32: + ld a,(BM_LINLEN_BAK) + ld (LINL32),a + call INIT32 + + ; Restore function keys + +_BM_SCREEN_REST_OK: + ld a,(BM_FNK_BAK) + or a + call nz,DSPFNK + + ret + + ; ----------------------------------------------------------------------------- ; Text strings ; ----------------------------------------------------------------------------- @@ -1284,7 +1376,7 @@ BM_HELP_1: db 13,10 db " F5: Reset device and start over",13,10 db 13,10 - db " CTRL+STOP: Exit without any mounting" + db " CTRL+STOP/ESC: Exit without mounting" db 0 BM_HELP_2: @@ -1316,4 +1408,8 @@ BM_CURSOR_LAST: equ BM_CUR_COL+1 ;Result of last call to BM_CURSOR_IS_PRESSED BM_NO_STOR_DEV: equ BM_CURSOR_LAST+1 ;FFh if F5 was pressed and no storage device was found BM_CUR_DIR_LEVEL: equ BM_NO_STOR_DEV+1 ;Current direcrory level, 0 is root BM_CUR_DIR: equ BM_CUR_DIR_LEVEL+1 ;Current directory, up to BM_MAX_DIR_NAME_LENGTH-1 chars + 0 -BM_CUR_DIR_LENGTH: equ BM_CUR_DIR+BM_MAX_DIR_NAME_LENGTH+1 \ No newline at end of file +BM_CUR_DIR_LENGTH: equ BM_CUR_DIR+BM_MAX_DIR_NAME_LENGTH+1 +BM_MAX_FILES_TO_ENUM: equ BM_CUR_DIR_LENGTH+1 +BM_SCRMOD_BAK: equ BM_MAX_FILES_TO_ENUM+2 +BM_LINLEN_BAK: equ BM_SCRMOD_BAK+1 +BM_FNK_BAK: equ BM_LINLEN_BAK+1 \ No newline at end of file diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index e61f579..38ef1a0 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -54,9 +54,14 @@ CH_COMMAND_PORT: equ 21h ;--- Commands +CH_CMD_GET_IC_VER: equ 01h CH_CMD_RESET_ALL: equ 05h CH_CMD_CHECK_EXIST: equ 06h +CH_CMD_READ_VAR8: equ 0Ah CH_CMD_SET_RETRY: equ 0Bh +CH_CMD_WRITE_VAR8: equ 0Bh +CH_CMD_READ_VAR32: equ 0Ch +CH_CMD_WRITE_VAR32: equ 0Dh CH_CMD_DELAY_100US: equ 0Fh CH_CMD_SET_USB_ADDR: equ 13h CH_CMD_SET_USB_MODE: equ 15h diff --git a/msx/bank1/misc.asm b/msx/bank1/misc.asm index 3f88468..de87509 100644 --- a/msx/bank1/misc.asm +++ b/msx/bank1/misc.asm @@ -257,3 +257,41 @@ IS_DIGIT_OR_LETTER: cp 'A' ccf ret + + +; +; Divide 16-bit values (with 16-bit result) +; In: Divide BC by divider DE +; Out: BC = result, HL = rest +; +DIVIDE_16: + ld hl,0 + ld a,b + ld b,8 +Div16_Loop1: + rla + adc hl,hl + sbc hl,de + jr nc,Div16_NoAdd1 + add hl,de +Div16_NoAdd1: + djnz Div16_Loop1 + rla + cpl + ld b,a + ld a,c + ld c,b + ld b,8 +Div16_Loop2: + rla + adc hl,hl + sbc hl,de + jr nc,Div16_NoAdd2 + add hl,de +Div16_NoAdd2: + djnz Div16_Loop2 + rla + cpl + ld b,c + ld c,a + ret \ No newline at end of file diff --git a/msx/constants.asm b/msx/constants.asm index 208518b..f70438b 100644 --- a/msx/constants.asm +++ b/msx/constants.asm @@ -4,16 +4,26 @@ VDP_DW: equ 0007h WRTVRM: equ 004Dh SETWRT: equ 0053h INITXT: equ 006Ch +INIT32: equ 006Fh CHGET: equ 009Fh CHPUT: equ 00A2h BREAKX: equ 00B7h +CLS: equ 00C3h POSIT: equ 00C6h +ERAFNK: equ 00CCh +DSPFNK: equ 00CFh KILBUF: equ 0156h LINL40: equ 0F3AEh +LINL32: equ 0F3AFh +LINLEN: equ 0F3B0h +CRTCNT: equ 0F3B1h TXTCGP: equ 0F3B7h ;Address of pattern generator table in VRAM +CNSDFG: equ 0F3DEh +STREND: equ 0F6C6h ;End of memory used by BASIC OLDKEY: equ 0FBDAh NEWKEY: equ 0FBE5h +SCRMOD: equ 0FCAFh ;Keyboard matrix: ; bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 From 2bbb61adafc4865063908c52e0ca04238b39160a Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Wed, 3 Feb 2021 13:02:44 +0100 Subject: [PATCH 28/65] Move the temp variables used by boot menu to stack allocated space. --- msx/bank1/boot_menu.asm | 303 +++++++++++++++++++++++++--------------- 1 file changed, 187 insertions(+), 116 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index bdfa7d5..e0fe538 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -5,7 +5,6 @@ ; a navigable list of disk image files (available only when a ; standard USB mass storage device is plugged in). -BM_FILES_BASE: equ 8010h BM_MAX_DIR_NAME_LENGTH: equ 64 ; ----------------------------------------------------------------------------- @@ -26,7 +25,7 @@ DO_BOOT_MENU: ld a,1 ret z - ;Return with error if we have less than 1K of free space + ;Return with error if we have less than 1.5K of free space ld hl,0 add hl,sp @@ -34,18 +33,24 @@ DO_BOOT_MENU: or a sbc hl,de ld a,h - cp 4 + cp 6 ld a,2 ret c - ld bc,100+660 ;Work stack space + space for one page of 0s + ld bc,100+660+BM_VARS_LEN ;Work stack space + space for one page of 0s + space for variables or a sbc hl,bc push hl pop bc ld de,11 call DIVIDE_16 - ld (BM_MAX_FILES_TO_ENUM),bc + + ld iy,-BM_VARS_LEN + add iy,sp + ld sp,iy + + ld (iy+BM_MAX_FILES_TO_ENUM),c + ld (iy+BM_MAX_FILES_TO_ENUM+1),b call BM_SCREEN_BAK ld a,40 @@ -56,22 +61,29 @@ DO_BOOT_MENU: call DO_BOOT_MENU_MAIN call BM_SCREEN_REST + call KILBUF + + ld iy,BM_VARS_LEN + add iy,sp + ld sp,iy + xor a ret DO_BOOT_MENU_MAIN: xor a - ld (BM_CURSOR_LAST),a - ld (BM_NO_STOR_DEV),a + ld (iy+BM_CURSOR_LAST),a + ld (iy+BM_NO_STOR_DEV),a + call BM_GET_CUR_DIR_ADD + ex de,hl ld hl,BM_DSK_S - ld de,BM_CUR_DIR ld bc,5 ldir ld a,1 - ld (BM_CUR_DIR_LEVEL),a + ld (iy+BM_CUR_DIR_LEVEL),a ld a,4 - ld (BM_CUR_DIR_LENGTH),a + ld (iy+BM_CUR_DIR_LENGTH),a ; Try opening DSK directory on the device @@ -119,7 +131,8 @@ BM_ENTER_MAIN_LOOP: call BM_UPDATE_CUR_PAGE_PNT call BM_UPDATE_CUR_FILE_PNT call BM_POSIT_CUR_FILE - ld hl,(BM_NUM_FILES) + ld l,(iy+BM_NUM_FILES) + ld h,(iy+BM_NUM_FILES+1) ld a,h or l call nz,BM_PRINT_CURRENT_FILE_AS_SELECTED @@ -138,7 +151,7 @@ _BM_MAIN_LOOP: call BM_F5_IS_PRESSED jp z,BM_START_OVER - ld a,(BM_NO_STOR_DEV) + ld a,(iy+BM_NO_STOR_DEV) inc a jr z,_BM_MAIN_LOOP @@ -163,15 +176,15 @@ _BM_MAIN_LOOP: BM_START_OVER: xor a - ld (BM_NUM_FILES),a - ld (BM_NUM_FILES+1),a + ld (iy+BM_NUM_FILES),a + ld (iy+BM_NUM_FILES+1),a inc a - ld (BM_CUR_PAGE),a - ld (BM_NUM_PAGES),a + ld (iy+BM_CUR_PAGE),a + ld (iy+BM_NUM_PAGES),a call BM_CLEAR_INFO_AREA xor a - ld (BM_CUR_DIR+1),a + ld (iy+BM_CUR_DIR+1),a call BM_PRINT_CUR_DIR ld hl,BM_RESETTING_DEVICE_S call BM_PRINT_STATUS @@ -180,7 +193,7 @@ BM_START_OVER: jp nc,DO_BOOT_MENU_MAIN ld a,0FFh - ld (BM_NO_STOR_DEV),a + ld (iy+BM_NO_STOR_DEV),a ld hl,BM_NO_DEV_OR_NO_STOR_S call BM_PRINT_STATUS @@ -198,10 +211,14 @@ BM_START_OVER: ;--- ENTER key press handler BM_DO_ENTER: - ld hl,(BM_CUR_FILE_PNT) + ld l,(iy+BM_CUR_FILE_PNT) + ld h,(iy+BM_CUR_FILE_PNT+1) push hl - ld de,BM_BUF + call BM_GET_BUF_ADD + ex de,hl + pop hl + push hl call BM_GENERATE_FILENAME pop ix bit 7,(ix+10) @@ -210,7 +227,7 @@ BM_DO_ENTER: ;* It's a file BM_DO_ENTER_FILE: - ld hl,BM_BUF + call BM_GET_BUF_ADD call HWF_OPEN_FILE_DIR or a jr z,_BM_DO_ENTER_FILE_IS_OPEN @@ -256,31 +273,32 @@ _BM_DO_ENTER_FILE_IS_OPEN_ATTR_OK: ;* It's a directory BM_DO_ENTER_DIR: - ld hl,BM_BUF + call BM_GET_BUF_ADD ld c,"/" call BM_STRLEN_C ld (hl),0 inc b ;Count also the additional "/" - ld a,(BM_CUR_DIR_LENGTH) + ld a,(iy+BM_CUR_DIR_LENGTH) add b cp BM_MAX_DIR_NAME_LENGTH+1 jp nc,_BM_MAIN_LOOP ;Max dir length surpassed: can't change dir - ld hl,BM_BUF + call BM_GET_BUF_ADD call HWF_OPEN_FILE_DIR cp 1 jp nz,_BM_DO_ENTER_OPEN_ERR - ld hl,BM_CUR_DIR_LEVEL - inc (hl) + ld a,(iy+BM_CUR_DIR_LEVEL) + inc a + ld (iy+BM_CUR_DIR_LEVEL),a - ld a,(BM_CUR_DIR_LENGTH) + ld a,(iy+BM_CUR_DIR_LENGTH) ld e,a ld d,0 - ld hl,BM_CUR_DIR + call BM_GET_CUR_DIR_ADD add hl,de - ld a,(BM_CUR_DIR_LEVEL) + ld a,(iy+BM_CUR_DIR_LEVEL) cp 1 jr z,_BM_DO_ENTER_DIR_WAS_ROOT ld (hl),"/" @@ -288,7 +306,7 @@ BM_DO_ENTER_DIR: _BM_DO_ENTER_DIR_WAS_ROOT: ex de,hl - ld hl,BM_BUF + call BM_GET_BUF_ADD _BM_COPY_DIR_NAME_LOOP: ld a,(hl) ld (de),a @@ -297,10 +315,10 @@ _BM_COPY_DIR_NAME_LOOP: or a jr nz,_BM_COPY_DIR_NAME_LOOP - ld hl,BM_CUR_DIR + call BM_GET_CUR_DIR_ADD call BM_STRLEN ld a,b - ld (BM_CUR_DIR_LENGTH),a + ld (iy+BM_CUR_DIR_LENGTH),a call BM_PRINT_CUR_DIR call BM_ENUM_FILES @@ -323,7 +341,7 @@ BM_PRINT_STATUS_WAIT_KEY: ; stopping right before the last one :facepalm: BM_DO_BS: - ld a,(BM_CUR_DIR_LEVEL) + ld a,(iy+BM_CUR_DIR_LEVEL) or a jp z,_BM_MAIN_LOOP ;We are in the root dir already @@ -338,25 +356,25 @@ BM_DO_BS: _BM_DO_BS_OPEN_ERROR: xor a - ld (BM_CUR_DIR+1),a + ld (iy+BM_CUR_DIR+1),a call BM_PRINT_CUR_DIR ld hl,BM_ERROR_OPENING_FILE_S call BM_PRINT_STATUS_WAIT_KEY xor a - ld (BM_NUM_FILES),a - ld (BM_NUM_FILES+1),a + ld (iy+BM_NUM_FILES),a + ld (iy+BM_NUM_FILES+1),a inc a - ld (BM_NUM_PAGES),a - ld (BM_CUR_PAGE),a - ld (BM_CUR_DIR_LENGTH),a + ld (iy+BM_NUM_PAGES),a + ld (iy+BM_CUR_PAGE),a + ld (iy+BM_CUR_DIR_LENGTH),a jp BM_ENTER_MAIN_LOOP _BM_DO_BS_OPEN_ROOT_OK: - ld a,(BM_CUR_DIR_LEVEL) + ld a,(iy+BM_CUR_DIR_LEVEL) dec a jp z,_BM_DO_BS_LV1_END ld b,a ;How many levels to go back - ld hl,BM_CUR_DIR ;Pointer to dir at current level, -1 + call BM_GET_CUR_DIR_ADD ;Pointer to dir at current level, -1 _BM_DO_BS_LOOP: push bc @@ -382,21 +400,22 @@ _BM_DO_BS_FIND_SLASH: djnz _BM_DO_BS_LOOP _BM_DO_BS_END: - ld hl,BM_CUR_DIR_LEVEL - dec (hl) + ld a,(iy+BM_CUR_DIR_LEVEL) + dec a + ld (iy+BM_CUR_DIR_LEVEL),a _BM_DO_BS_END_2: - ld hl,BM_CUR_DIR + call BM_GET_CUR_DIR_ADD call BM_STRLEN ld a,b - ld (BM_CUR_DIR_LENGTH),a + ld (iy+BM_CUR_DIR_LENGTH),a call BM_PRINT_CUR_DIR call BM_ENUM_FILES jp BM_ENTER_MAIN_LOOP _BM_DO_BS_LV1_END: xor a - ld (BM_CUR_DIR+1),a - ld (BM_CUR_DIR_LEVEL),a + ld (iy+BM_CUR_DIR+1),a + ld (iy+BM_CUR_DIR_LEVEL),a jr _BM_DO_BS_END_2 @@ -455,7 +474,7 @@ BM_UPDATE_CUR_FILE: jr z,_BM_FILE_DOWN _BM_FILE_LEFT: - ld a,(BM_CUR_COL) + ld a,(iy+BM_CUR_COL) dec a cp 0FFh jr nz,_BM_UPDATE_CUR_COL_GO @@ -463,7 +482,7 @@ _BM_FILE_LEFT: jr _BM_UPDATE_CUR_COL_GO _BM_FILE_RIGHT: - ld a,(BM_CUR_COL) + ld a,(iy+BM_CUR_COL) inc a cp 3 jr c,_BM_UPDATE_CUR_COL_GO @@ -471,7 +490,7 @@ _BM_FILE_RIGHT: jr _BM_UPDATE_CUR_COL_GO _BM_FILE_UP: - ld a,(BM_CUR_ROW) + ld a,(iy+BM_CUR_ROW) dec a cp 0FFh jr nz,_BM_UPDATE_CUR_ROW_GO @@ -479,7 +498,7 @@ _BM_FILE_UP: jr _BM_UPDATE_CUR_ROW_GO _BM_FILE_DOWN: - ld a,(BM_CUR_ROW) + ld a,(iy+BM_CUR_ROW) inc a cp 20 jr c,_BM_UPDATE_CUR_ROW_GO @@ -487,25 +506,35 @@ _BM_FILE_DOWN: jr _BM_UPDATE_CUR_ROW_GO _BM_UPDATE_CUR_COL_GO: - ld (BM_CUR_COL),a - ld hl,BM_CUR_COL - ld (BM_BUF),hl + ld (iy+BM_CUR_COL),a + push iy + pop hl + ld bc,BM_CUR_COL + add hl,bc + ld (iy+BM_BUF),l + ld (iy+BM_BUF+1),h jr _BM_UPDATE_CUR_ROWCOL_GO _BM_UPDATE_CUR_ROW_GO: - ld (BM_CUR_ROW),a - ld hl,BM_CUR_ROW - ld (BM_BUF),hl + ld (iy+BM_CUR_ROW),a + push iy + pop hl + ld bc,BM_CUR_ROW + add hl,bc + ld (iy+BM_BUF),l + ld (iy+BM_BUF+1),h _BM_UPDATE_CUR_ROWCOL_GO: call BM_UPDATE_CUR_FILE_PNT - ld hl,(BM_CUR_FILE_PNT) + ld l,(iy+BM_CUR_FILE_PNT) + ld h,(iy+BM_CUR_FILE_PNT+1) ld a,(hl) or a jr nz,_BM_UPDATE_CUR_ROWCOL_GO_2 ;We ended up pointing past the end of the list, ;so reset column/row to 0 - ld hl,(BM_BUF) + ld l,(iy+BM_BUF) + ld h,(iy+BM_BUF+1) ld (hl),0 call BM_UPDATE_CUR_FILE_PNT @@ -530,43 +559,43 @@ BM_UPDATE_PAGE: jp _BM_MAIN_LOOP _BM_NEXT_PAGE: - ld a,(BM_NUM_PAGES) + ld a,(iy+BM_NUM_PAGES) ld b,a - ld a,(BM_CUR_PAGE) + ld a,(iy+BM_CUR_PAGE) cp b jp z,_BM_MAIN_LOOP inc a - ld (BM_CUR_PAGE),a + ld (iy+BM_CUR_PAGE),a jp _BM_UPDATE_PAGE_END _BM_NEXT_10_PAGES: - ld a,(BM_NUM_PAGES) + ld a,(iy+BM_NUM_PAGES) ld b,a - ld a,(BM_CUR_PAGE) + ld a,(iy+BM_CUR_PAGE) cp b jp nc,_BM_MAIN_LOOP inc b add 10 cp b jr c,_BM_NEXT_10_PAGES_GO - ld a,(BM_NUM_PAGES) + ld a,(iy+BM_NUM_PAGES) _BM_NEXT_10_PAGES_GO: - ld (BM_CUR_PAGE),a + ld (iy+BM_CUR_PAGE),a jp _BM_UPDATE_PAGE_END _BM_PREV_PAGE: - ld a,(BM_CUR_PAGE) + ld a,(iy+BM_CUR_PAGE) cp 1 jp z,_BM_MAIN_LOOP dec a - ld (BM_CUR_PAGE),a + ld (iy+BM_CUR_PAGE),a jp _BM_UPDATE_PAGE_END _BM_PREV_10_PAGES: - ld a,(BM_CUR_PAGE) + ld a,(iy+BM_CUR_PAGE) cp 1 jp z,_BM_MAIN_LOOP sub 10 @@ -576,13 +605,13 @@ _BM_PREV_10_PAGES_1: ld a,1 _BM_PREV_10_PAGES_GO: - ld (BM_CUR_PAGE),a + ld (iy+BM_CUR_PAGE),a jp _BM_UPDATE_PAGE_END _BM_UPDATE_PAGE_END: xor a - ld (BM_CUR_ROW),a - ld (BM_CUR_COL),a + ld (iy+BM_CUR_ROW),a + ld (iy+BM_CUR_COL),a jp BM_ENTER_MAIN_LOOP @@ -590,16 +619,18 @@ _BM_UPDATE_PAGE_END: BM_ENUM_FILES: ld a,1 - ld (BM_CUR_PAGE),a + ld (iy+BM_CUR_PAGE),a call BM_CLEAR_INFO_AREA ld hl,BM_SCANNING_DIR_S call BM_PRINT_STATUS - ld hl,BM_FILES_BASE - ld bc,(BM_MAX_FILES_TO_ENUM) ; 1290 + ld hl,(STREND) + ld c,(iy+BM_MAX_FILES_TO_ENUM) + ld b,(iy+BM_MAX_FILES_TO_ENUM+1) call HWF_ENUM_FILES - ld (BM_NUM_FILES),bc + ld (iy+BM_NUM_FILES),c + ld (iy+BM_NUM_FILES+1),b push bc push hl ;Fill one extra page of 0s. @@ -637,11 +668,11 @@ _BM_CALC_NUM_PAGES_END: jr nz,_BM_CALC_NUM_PAGES_END_2 inc a _BM_CALC_NUM_PAGES_END_2: - ld (BM_NUM_PAGES),a + ld (iy+BM_NUM_PAGES),a xor a - ld (BM_CUR_ROW),a - ld (BM_CUR_COL),a + ld (iy+BM_CUR_ROW),a + ld (iy+BM_CUR_COL),a ret @@ -653,7 +684,8 @@ _BM_CALC_NUM_PAGES_END_2: ;--- Print the filenames for the current page BM_PRINT_FILENAMES_PAGE: - ld hl,(BM_NUM_FILES) + ld l,(iy+BM_NUM_FILES) + ld h,(iy+BM_NUM_FILES+1) ld a,h or l jp nz,_BM_PRINT_FILENAMES_PAGE_GO @@ -665,10 +697,12 @@ BM_PRINT_FILENAMES_PAGE: jp PRINT _BM_PRINT_FILENAMES_PAGE_GO: - ld a,(BM_CUR_PAGE) + ld a,(iy+BM_CUR_PAGE) ld b,a - ld hl,BM_FILES_BASE-11*60 + ld hl,(STREND) ld de,11*60 + or a + sbc hl,de _BM_PRINT_FILENAMES_CALC: add hl,de djnz _BM_PRINT_FILENAMES_CALC @@ -836,18 +870,20 @@ BM_PRINT_PAGE_NUM: ld hl,BM_PAGE_S call PRINT - ld a,(BM_CUR_PAGE) + ld a,(iy+BM_CUR_PAGE) call BM_PRINT_BYTE ld hl,BM_SPACE_AND_BAR call PRINT - ld a,(BM_NUM_PAGES) + ld a,(iy+BM_NUM_PAGES) jp BM_PRINT_BYTE BM_PRINT_BYTE: - ld ix,BM_BUF + call BM_GET_BUF_ADD + push hl + pop ix call BYTE2ASC ld (ix),0 - ld hl,BM_BUF + call BM_GET_BUF_ADD jp PRINT @@ -867,7 +903,7 @@ _BM_DRAW_LINE_LOOP: ; row = BM_CUR_ROW+3 BM_POSIT_CUR_FILE: - ld a,(BM_CUR_COL) + ld a,(iy+BM_CUR_COL) ld b,a sla a sla a @@ -880,7 +916,7 @@ BM_POSIT_CUR_FILE: inc a inc a ld h,a - ld a,(BM_CUR_ROW) + ld a,(iy+BM_CUR_ROW) add 3 ld l,a jp POSIT @@ -889,7 +925,8 @@ BM_POSIT_CUR_FILE: ;--- Print the current filename at the current position BM_PRINT_CURRENT_FILE: - ld hl,(BM_CUR_FILE_PNT) + ld l,(iy+BM_CUR_FILE_PNT) + ld h,(iy+BM_CUR_FILE_PNT+1) call BM_PRINT_FILENAME ld b,' ' _BM_PRINT_CURRENT_FILE_PAD: @@ -907,8 +944,10 @@ _BM_PRINT_CURRENT_FILE_PAD: ;Generate the formatted file name in BM_BUF, padded with spaces BM_PRINT_CURRENT_FILE_AS_SELECTED: - ld hl,(BM_CUR_FILE_PNT) - ld de,BM_BUF + call BM_GET_BUF_ADD + ex de,hl + ld l,(iy+BM_CUR_FILE_PNT) + ld h,(iy+BM_CUR_FILE_PNT+1) call BM_GENERATE_FILENAME _BM_GEN_CURRENT_FILE_PAD: @@ -932,7 +971,7 @@ _BM_GEN_CURRENT_FILE_OK: ld a,(VDP_DW) ld c,a ;VDP write port - ld hl,BM_BUF ;Pointer to current char + call BM_GET_BUF_ADD ;Pointer to current char ld b,12 ;How many chars left to invert _BM_INVERT_CHARS_LOOP: push hl @@ -981,7 +1020,7 @@ BM_PRINT_CUR_DIR: ld l,1 call POSIT - ld a,(BM_CUR_DIR_LENGTH) + ld a,(iy+BM_CUR_DIR_LENGTH) cp 41 jr c,_BM_PRINT_CUR_DIR_DIRECT @@ -993,7 +1032,7 @@ BM_PRINT_CUR_DIR: jr _BM_PRINT_CUR_DIR_END _BM_PRINT_CUR_DIR_DIRECT: - ld hl,BM_CUR_DIR + call BM_GET_CUR_DIR_ADD call PRINT _BM_PRINT_CUR_DIR_END: @@ -1007,8 +1046,8 @@ _BM_PRINT_CUR_DIR_END: ; (assuming current dir is not root) BM_GET_LAST_DIR_PNT: - ld hl,BM_CUR_DIR - ld de,(BM_CUR_DIR_LENGTH) + call BM_GET_CUR_DIR_ADD + ld e,(iy+BM_CUR_DIR_LENGTH) ld d,0 add hl,de _BM_GET_LAST_DIR_PNT_LOOP: @@ -1121,17 +1160,17 @@ BM_CURSOR_IS_PRESSED: jr nc,_BM_CURSOR_IS_PRESSED_END xor a - ld (BM_CURSOR_LAST),a + ld (iy+BM_CURSOR_LAST),a ret _BM_CURSOR_IS_PRESSED_END: - ld a,(BM_CURSOR_LAST) + ld a,(iy+BM_CURSOR_LAST) or a ld a,0 ret nz ;Still pressed since last time inc a - ld (BM_CURSOR_LAST),a + ld (iy+BM_CURSOR_LAST),a dec hl dec hl ;Row 6 (for SHIFT) @@ -1149,17 +1188,18 @@ _BM_CURSOR_IS_PRESSED_END: ;--- Update BM_CUR_PAGE_PNT as: -; BM_FILES_BASE + ((BM_CUR_PAGE-1)*60)*11 +; Base for filenames (STREND) + ((BM_CUR_PAGE-1)*60)*11 BM_UPDATE_CUR_PAGE_PNT: - ld hl,(BM_CUR_PAGE) + ld l,(iy+BM_CUR_PAGE) ld h,0 dec l call BM_MULT_60 call BM_MULT_11 - ld de,BM_FILES_BASE + ld de,(STREND) add hl,de - ld (BM_CUR_PAGE_PNT),hl + ld (iy+BM_CUR_PAGE_PNT),l + ld (iy+BM_CUR_PAGE_PNT+1),h ret @@ -1167,16 +1207,18 @@ BM_UPDATE_CUR_PAGE_PNT: ; BM_CUR_PAGE_PNT + ((BM_CUR_COL*20) + BM_CUR_ROW)*11 BM_UPDATE_CUR_FILE_PNT: - ld hl,(BM_CUR_COL) + ld l,(iy+BM_CUR_COL) ld h,0 call BM_MULT_20 - ld de,(BM_CUR_ROW) + ld e,(iy+BM_CUR_ROW) ld d,0 add hl,de call BM_MULT_11 - ld de,(BM_CUR_PAGE_PNT) + ld e,(iy+BM_CUR_PAGE_PNT) + ld d,(iy+BM_CUR_PAGE_PNT+1) add hl,de - ld (BM_CUR_FILE_PNT),hl + ld (iy+BM_CUR_FILE_PNT),l + ld (iy+BM_CUR_FILE_PNT+1),h ret @@ -1261,25 +1303,25 @@ _BM_STRLEN_LOOP: BM_SCREEN_BAK: ld a,(SCRMOD) - ld (BM_SCRMOD_BAK),a + ld (iy+BM_SCRMOD_BAK),a ld a,(LINLEN) - ld (BM_LINLEN_BAK),a + ld (iy+BM_LINLEN_BAK),a ld a,(CNSDFG) - ld (BM_FNK_BAK),a + ld (iy+BM_FNK_BAK),a ret ;--- Restore previous screen mode BM_SCREEN_REST: - ld a,(BM_SCRMOD_BAK) + ld a,(iy+BM_SCRMOD_BAK) dec a jr z,_BM_SCREEN_REST_W32 ; Restore SCREEN 0 _BM_SCREEN_REST_W40: - ld a,(BM_LINLEN_BAK) + ld a,(iy+BM_LINLEN_BAK) ld (LINL40),a call INITXT jr _BM_SCREEN_REST_OK @@ -1287,20 +1329,44 @@ _BM_SCREEN_REST_W40: ; Restore SCREEN 1 _BM_SCREEN_REST_W32: - ld a,(BM_LINLEN_BAK) + ld a,(iy+BM_LINLEN_BAK) ld (LINL32),a call INIT32 ; Restore function keys _BM_SCREEN_REST_OK: - ld a,(BM_FNK_BAK) + ld a,(iy+BM_FNK_BAK) or a call nz,DSPFNK ret +;--- Get the address of BM_BUF in HL + +BM_GET_BUF_ADD: + push bc + push iy + pop hl + ld bc,BM_BUF + add hl,bc + pop bc + ret + + +;--- Get the address of BM_CUR_DIR in HL + +BM_GET_CUR_DIR_ADD: + push bc + push iy + pop hl + ld bc,BM_CUR_DIR + add hl,bc + pop bc + ret + + ; ----------------------------------------------------------------------------- ; Text strings ; ----------------------------------------------------------------------------- @@ -1396,7 +1462,9 @@ BM_HELP_2: _BM_VARS_BASE: equ 0C800h -BM_NUM_PAGES: equ _BM_VARS_BASE +BM_VARS_START: equ 0 + +BM_NUM_PAGES: equ BM_VARS_START BM_CUR_PAGE: equ BM_NUM_PAGES+1 BM_NUM_FILES: equ BM_CUR_PAGE+1 BM_BUF: equ BM_NUM_FILES+2 @@ -1412,4 +1480,7 @@ BM_CUR_DIR_LENGTH: equ BM_CUR_DIR+BM_MAX_DIR_NAME_LENGTH+1 BM_MAX_FILES_TO_ENUM: equ BM_CUR_DIR_LENGTH+1 BM_SCRMOD_BAK: equ BM_MAX_FILES_TO_ENUM+2 BM_LINLEN_BAK: equ BM_SCRMOD_BAK+1 -BM_FNK_BAK: equ BM_LINLEN_BAK+1 \ No newline at end of file +BM_FNK_BAK: equ BM_LINLEN_BAK+1 + +BM_VARS_END: equ BM_FNK_BAK+1 +BM_VARS_LEN: equ BM_VARS_END-BM_VARS_START \ No newline at end of file From 2e039e89f47929feb5a4d2c0f6e79422b0625e7d Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 4 Feb 2021 17:01:12 +0100 Subject: [PATCH 29/65] Add the dsk.asm file, with routines to read/write config files. --- msx/bank1/ch376.asm | 63 ++++++++++++++- msx/bank1/dsk.asm | 189 ++++++++++++++++++++++++++++++++++++++++++++ msx/rookiefdd.asm | 1 + 3 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 msx/bank1/dsk.asm diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index 38ef1a0..dec794b 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -76,6 +76,7 @@ CH_CMD_DISK_CONNECT: equ 30h CH_CMD_DISK_MOUNT: equ 31h CH_CMD_FILE_OPEN: equ 32h CH_CMD_FILE_ENUM_GO: equ 33h +CH_CMD_FILE_CREATE: equ 34h CH_CMD_FILE_CLOSE: equ 36h CH_CMD_DIR_INFO_READ: equ 37h CH_CMD_BYTE_LOCATE: equ 39h @@ -83,6 +84,7 @@ CH_CMD_BYTE_READ: equ 3Ah CH_CMD_BYTE_RD_GO: equ 3Bh CH_CMD_BYTE_WRITE: equ 3Ch CH_CMD_BYTE_WRITE_GO: equ 3Dh +CH_CMD_DIR_CREATE: equ 40h CH_CMD_SET_ADDRESS: equ 45h CH_CMD_GET_DESCR: equ 46h CH_CMD_SET_CONFIG: equ 49h @@ -590,8 +592,7 @@ FAKE_DEV_NAME: ; ----------------------------------------------------------------------------- ; HWF_OPEN_FILE_DIR: Open a file or enter a directory from the current one ; ----------------------------------------------------------------------------- -; Input: HL = Address of file or directory name, relative to current, -; can be ".." to go back to previous +; Input: HL = Address of file or directory name, relative to current ; Output: A = 0: ok, file open ; 1: ok, directory entered ; 2: file or directory not found @@ -634,6 +635,64 @@ _HWF_OPEN_FILE_DIR_END: ret +; ----------------------------------------------------------------------------- +; HWF_CREATE_FILE: Create a new file in current directory, overwrite if exists +; ----------------------------------------------------------------------------- +; Input: HL = Address of file or directory name, relative to current +; Output: A = 0: ok, file open +; 1: error (might be that a directory with the same name exists) + +HWF_CREATE_FILE: + ld a,CH_CMD_SET_FILE_NAME + out (CH_COMMAND_PORT),a + call CH_WRITE_STRING + + ld a,CH_CMD_FILE_CREATE + out (CH_COMMAND_PORT),a + call CH_WAIT_INT_AND_GET_RESULT + + cp USB_ERR_OK + ld a,0 + ret z + inc a + ret + + +; ----------------------------------------------------------------------------- +; HWF_CREATE_DIR: Create a new directory in current directory, open if exists +; ----------------------------------------------------------------------------- +; Input: HL = Address of file or directory name, relative to current +; Output: A = 0: ok, file open +; 1: error (might be that a file with the same name exists) + +HWF_CREATE_DIR: + ld a,CH_CMD_SET_FILE_NAME + out (CH_COMMAND_PORT),a + call CH_WRITE_STRING + + ld a,CH_CMD_DIR_CREATE + out (CH_COMMAND_PORT),a + call CH_WAIT_INT_AND_GET_RESULT + + cp USB_ERR_OK + ld a,0 + ret z + inc a + ret + + +; ----------------------------------------------------------------------------- +; HWF_CLOSE_FILE: Close open file or directory, update size in dir entry +; ----------------------------------------------------------------------------- + +HWF_CLOSE_FILE: + ld a,CH_CMD_FILE_CLOSE + out (CH_COMMAND_PORT),a + ld a,1 + out (CH_DATA_PORT),a + jp CH_WAIT_INT_AND_GET_RESULT + + ; ----------------------------------------------------------------------------- ; HWF_ENUM_FILES: Enumerate files and directories in the current directory ; diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm new file mode 100644 index 0000000..51d29da --- /dev/null +++ b/msx/bank1/dsk.asm @@ -0,0 +1,189 @@ +; Rookie Drive USB FDD BIOS +; By Konamiman, 2018 +; +; This file contains the code for high-level management +; of disk image files, including creating and accessing +; configuration files when needed. + + +; ----------------------------------------------------------------------------- +; DSK_OPEN_MAIN_DIR: Open the main directory +; ----------------------------------------------------------------------------- +; Output: A = 0: Ok +; 1: Error + +DSK_OPEN_MAIN_DIR: + push hl + push de + push bc + call _DSK_OPEN_MAIN_DIR + pop bc + pop de + pop hl + ret +_DSK_OPEN_MAIN_DIR: + ld hl,DSK_ROOT_DIR_S + call HWF_OPEN_FILE_DIR + cp 1 + ld a,1 + ret nz + + ld hl,DSK_MAIN_DIR_S + call HWF_OPEN_FILE_DIR + ld b,a + cp 3 + ld a,1 + ret z + ld a,b + dec a + ret z + + ld hl,DSK_ROOT_DIR_S + call HWF_OPEN_FILE_DIR + dec a + ret z + ld a,1 + ret + +DSK_ROOT_DIR_S: + db "/",0 + +DSK_MAIN_DIR_S: + db "MSX",0 + + +; ----------------------------------------------------------------------------- +; DSK_READ_CONFIG_FILE: Read config file in current directory +; ----------------------------------------------------------------------------- +; Input: HL = File name +; DE = Destination address +; B = Max amount of bytes to read +; Output: A = 0: Ok +; 1: File not found +; 2: Other error +; B = Amount of bytes read if no error +; DE = Pointer after last byte read + +DSK_READ_CONFIG_FILE: + push hl + push de + push bc + ld hl,DSK_CONFIG_DIR_S + call HWF_OPEN_FILE_DIR + pop bc + pop de + pop hl + ld c,a + cp 2 + ld a,1 + ret z + ld a,c + dec a + ld a,2 + ret nz + + push de + push bc + call HWF_OPEN_FILE_DIR + pop bc + pop de + ld c,a + cp 2 + ld a,1 + ret z + ld a,c + or a + ld a,2 + ret nz + + ex de,hl + ld c,b + ld b,0 + call HWF_READ_FILE + ex de,hl + ld b,0 + or a + ret nz + ld b,c + ret + +DSK_CONFIG_DIR_S: + db "_USB",0 + + +; ----------------------------------------------------------------------------- +; DSK_READ_MAIN_CONFIG_FILE: Read config file in main directory +; ----------------------------------------------------------------------------- +; Input: HL = File name +; DE = Destination address +; B = Max amount of bytes to read +; Output: A = 0: Ok +; 1: File not found +; 2: Other error +; B = Amount of bytes read if no error +; DE = Pointer after last byte read + +DSK_READ_MAIN_CONFIG_FILE: + call DSK_OPEN_MAIN_DIR + or a + ld a,1 + ret nz + + jp DSK_READ_CONFIG_FILE + + +; ----------------------------------------------------------------------------- +; DSK_WRITE_CONFIG_FILE: Write config file in current directory +; ----------------------------------------------------------------------------- +; Input: HL = File name +; DE = Source address +; B = Amount of bytes to read +; Output: A = 0: Ok +; 1: Error + +DSK_WRITE_CONFIG_FILE: + push hl + push de + push bc + ld hl,DSK_CONFIG_DIR_S + call HWF_CREATE_DIR + pop bc + pop de + pop hl + or a + ret nz + + push de + push bc + call HWF_CREATE_FILE + pop bc + pop hl + or a + ret nz + + ld c,b + ld b,0 + call HWF_WRITE_FILE + + push af + call HWF_CLOSE_FILE + pop af + ret + + +; ----------------------------------------------------------------------------- +; DSK_WRITE_MAIN_CONFIG_FILE: Write config file in main directory +; ----------------------------------------------------------------------------- +; Input: HL = File name +; DE = Source address +; B = Amount of bytes to read +; Output: A = 0: Ok +; 1: Error + +DSK_WRITE_MAIN_CONFIG_FILE: + call DSK_OPEN_MAIN_DIR + or a + ld a,1 + ret nz + + jp DSK_WRITE_CONFIG_FILE \ No newline at end of file diff --git a/msx/rookiefdd.asm b/msx/rookiefdd.asm index 661d019..cb64319 100644 --- a/msx/rookiefdd.asm +++ b/msx/rookiefdd.asm @@ -59,6 +59,7 @@ DEFDPB: include "bank1/usb.asm" include "bank1/misc.asm" include "bank1/boot_menu.asm" + include "bank1/dsk.asm" DEFDPB_1: include "defdpb.asm" From 36468b2ad409838bc9b9cdf6b366084d9d18b48a Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 5 Feb 2021 17:56:30 +0100 Subject: [PATCH 30/65] Implemented the high-level routines for changing directories. --- msx/bank1/ch376.asm | 49 +++++++++++++-- msx/bank1/dsk.asm | 142 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 183 insertions(+), 8 deletions(-) diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index dec794b..ab5390b 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -77,6 +77,7 @@ CH_CMD_DISK_MOUNT: equ 31h CH_CMD_FILE_OPEN: equ 32h CH_CMD_FILE_ENUM_GO: equ 33h CH_CMD_FILE_CREATE: equ 34h +CH_CMD_FILE_ERASE: equ 34h CH_CMD_FILE_CLOSE: equ 36h CH_CMD_DIR_INFO_READ: equ 37h CH_CMD_BYTE_LOCATE: equ 39h @@ -597,6 +598,7 @@ FAKE_DEV_NAME: ; 1: ok, directory entered ; 2: file or directory not found ; 3: other error (e.g. no device found) +; HL = Pointer to terminator of file or directory name HWF_OPEN_FILE_DIR: if USE_FAKE_STORAGE_DEVICE=1 @@ -615,9 +617,11 @@ HWF_OPEN_FILE_DIR: out (CH_COMMAND_PORT),a call CH_WRITE_STRING + push hl ld a,CH_CMD_FILE_OPEN out (CH_COMMAND_PORT),a call CH_WAIT_INT_AND_GET_RESULT + pop hl ld b,0 cp USB_ERR_OK @@ -643,6 +647,23 @@ _HWF_OPEN_FILE_DIR_END: ; 1: error (might be that a directory with the same name exists) HWF_CREATE_FILE: + if 0 + + push hl + call HWF_CLOSE_FILE + pop hl + + push hl + ld a,CH_CMD_SET_FILE_NAME + out (CH_COMMAND_PORT),a + call CH_WRITE_STRING + ld a,CH_CMD_FILE_ERASE + out (CH_COMMAND_PORT),a + call CH_WAIT_INT_AND_GET_RESULT + pop hl + + endif + ld a,CH_CMD_SET_FILE_NAME out (CH_COMMAND_PORT),a call CH_WRITE_STRING @@ -1504,12 +1525,32 @@ CH_WRITE_DATA: ret +; -------------------------------------- +; CH_WRITE_STRING +; +; Write a zero or "/" terminated string +; to the CH data buffer (if the terminator +; is "/" a zero is written) +; +; Input: HL = Source address of the string +; Output: HL = Points to the terminator + CH_WRITE_STRING: ld c,CH_DATA_PORT -_CH_WRITE_STRING_LOOP: ld a,(hl) + out (c),a ;We accept "/" only as the first char + +_CH_WRITE_STRING_LOOP: + or a + ret z inc hl + ld a,(hl) + cp "/" + jr z,_CH_WRITE_STRING_BAR out (c),a - or a - jr nz,_CH_WRITE_STRING_LOOP - ret \ No newline at end of file + jr _CH_WRITE_STRING_LOOP + +_CH_WRITE_STRING_BAR: + xor a + out (c),a + ret diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index 51d29da..8422d91 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -120,16 +120,23 @@ DSK_CONFIG_DIR_S: ; Output: A = 0: Ok ; 1: File not found ; 2: Other error -; B = Amount of bytes read if no error +; B = Amount of bytes read if no error, 0 on error ; DE = Pointer after last byte read DSK_READ_MAIN_CONFIG_FILE: call DSK_OPEN_MAIN_DIR or a ld a,1 + ld c,b + ld b,0 ret nz + ld b,c - jp DSK_READ_CONFIG_FILE + call DSK_READ_CONFIG_FILE + or a + ret z + ld b,0 + ret ; ----------------------------------------------------------------------------- @@ -137,7 +144,7 @@ DSK_READ_MAIN_CONFIG_FILE: ; ----------------------------------------------------------------------------- ; Input: HL = File name ; DE = Source address -; B = Amount of bytes to read +; B = Amount of bytes to write ; Output: A = 0: Ok ; 1: Error @@ -186,4 +193,131 @@ DSK_WRITE_MAIN_CONFIG_FILE: ld a,1 ret nz - jp DSK_WRITE_CONFIG_FILE \ No newline at end of file + jp DSK_WRITE_CONFIG_FILE + + +; ----------------------------------------------------------------------------- +; DSK_CHANGE_DIR: Change the current directory +; (doesn't update config files) +; ----------------------------------------------------------------------------- +; Input: HL = Directory path, "dir/dir2/dir3", no starting or ending "/" +; A = 0 for relative to current, 1 for absolute +; Output: A = 0: Ok +; 1: Directory not found +; 2: Other error + +DSK_CHANGE_DIR: + or a + jr z,_DSK_CHANGE_DIR_REL + + push hl + ld hl,DSK_ROOT_DIR_S + call HWF_OPEN_FILE_DIR + pop hl + cp 1 + ld a,2 + ret nz +_DSK_CHANGE_DIR_REL: + +_DSK_CHANGE_LOOP: + call HWF_OPEN_FILE_DIR + ld b,a + or a + ld a,2 + ret z + ld a,b + dec a + ret nz + + ld a,(hl) + inc hl + or a + jr nz,_DSK_CHANGE_LOOP + + xor a + ret + + +; ----------------------------------------------------------------------------- +; DSK_CHANGE_DIR_U: Change the current directoryand update config files +; +; This one is tricky. We can't update CURDIR until after we are sure that +; the directory change has been sucessful, but if we update a config file +; after setting our directory then it won't be set anymore! Also if we fail +; we should restore the previous directory. +; +; Thus we do it like this: +; +; 1. Read current content of CURDIR, save in memory +; 2. Set CURDIR contents to the directory we want to change to +; 3. Try to change to the directory, if successful, we're all set +; 4. On error changing the directory, set CURDIR to its previous contents +; and change to it again +; ----------------------------------------------------------------------------- +; Input: HL = Directory path, "dir/dir2/dir3", no starting or ending "/" +; A = 0 for relative to current, 1 for absolute +; Output: A = 0: Ok +; 1: Directory not found +; 2: Other error + +DSK_CHANGE_DIR_U: + ld iy,-65 + add iy,sp + ld sp,iy + call _DSK_CHANGE_DIR_U + ld iy,65 + add iy,sp + ld sp,iy + ret + +_DSK_CHANGE_DIR_U: + push af + push hl + + push iy + pop de + inc de + ld hl,DSK_CURDIR_S + ld b,64 + call DSK_READ_MAIN_CONFIG_FILE + call CHPUT + ld (iy),b + + pop hl + push hl + call BM_STRLEN + pop de + push de + ld hl,DSK_CURDIR_S + call DSK_WRITE_MAIN_CONFIG_FILE + + pop hl + pop af + call DSK_CHANGE_DIR + or a + ret z + + ld c,a + ld a,(iy) + or a + ld a,c + ret z + + push iy + pop de + inc de + ld b,(iy) + ld hl,DSK_CURDIR_S + push af + push de + call DSK_WRITE_MAIN_CONFIG_FILE + pop hl + ld a,1 + call DSK_CHANGE_DIR + pop af + + ret + +DSK_CURDIR_S: + db "CURDIR",0 + From eb6901b65f35020a67aa2793640bb3ed53a8ddc6 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sun, 7 Feb 2021 17:00:25 +0100 Subject: [PATCH 31/65] Add the DSK_MOUNT routine Also now DSK_WRITE_CONFIG_FILE deletes the file if empty length is supplied. --- msx/bank1/ch376.asm | 28 ++++- msx/bank1/dsk.asm | 221 +++++++++++++++++++++++++++++++++++-- msx/bank1/dskio_dskchg.asm | 13 ++- msx/bank1/work_area.asm | 1 + 4 files changed, 250 insertions(+), 13 deletions(-) diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index ab5390b..aa50a14 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -77,7 +77,7 @@ CH_CMD_DISK_MOUNT: equ 31h CH_CMD_FILE_OPEN: equ 32h CH_CMD_FILE_ENUM_GO: equ 33h CH_CMD_FILE_CREATE: equ 34h -CH_CMD_FILE_ERASE: equ 34h +CH_CMD_FILE_ERASE: equ 35h CH_CMD_FILE_CLOSE: equ 36h CH_CMD_DIR_INFO_READ: equ 37h CH_CMD_BYTE_LOCATE: equ 39h @@ -714,6 +714,32 @@ HWF_CLOSE_FILE: jp CH_WAIT_INT_AND_GET_RESULT +; ----------------------------------------------------------------------------- +; HWF_DELETE_FILE: Delete file or directory +; ----------------------------------------------------------------------------- +; Input: HL = File or directory name +; Output: A = 0: Ok +; 1: Error + +HWF_DELETE_FILE: + ;Very important: close any open file first, or it will be deleted! + push hl + call HWF_CLOSE_FILE + pop hl + + ld a,CH_CMD_SET_FILE_NAME + out (CH_COMMAND_PORT),a + call CH_WRITE_STRING + + ld a,CH_CMD_FILE_ERASE + out (CH_COMMAND_PORT),a + call CH_WAIT_INT_AND_GET_RESULT + or a + ret z + ld a,1 + ret + + ; ----------------------------------------------------------------------------- ; HWF_ENUM_FILES: Enumerate files and directories in the current directory ; diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index 8422d91..a6f0749 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -144,7 +144,7 @@ DSK_READ_MAIN_CONFIG_FILE: ; ----------------------------------------------------------------------------- ; Input: HL = File name ; DE = Source address -; B = Amount of bytes to write +; B = Amount of bytes to write, if 0 delete the file ; Output: A = 0: Ok ; 1: Error @@ -160,6 +160,15 @@ DSK_WRITE_CONFIG_FILE: or a ret nz + ld a,b + or a + jr nz,_DSK_WRITE_CONFIG_FILE_GO + + call HWF_DELETE_FILE + xor a + ret + +_DSK_WRITE_CONFIG_FILE_GO: push de push bc call HWF_CREATE_FILE @@ -183,7 +192,7 @@ DSK_WRITE_CONFIG_FILE: ; ----------------------------------------------------------------------------- ; Input: HL = File name ; DE = Source address -; B = Amount of bytes to read +; B = Amount of bytes to write ; Output: A = 0: Ok ; 1: Error @@ -198,9 +207,10 @@ DSK_WRITE_MAIN_CONFIG_FILE: ; ----------------------------------------------------------------------------- ; DSK_CHANGE_DIR: Change the current directory -; (doesn't update config files) +; (doesn't update config files or work area) ; ----------------------------------------------------------------------------- ; Input: HL = Directory path, "dir/dir2/dir3", no starting or ending "/" +; (the root dir is represented as an empty string) ; A = 0 for relative to current, 1 for absolute ; Output: A = 0: Ok ; 1: Directory not found @@ -217,6 +227,10 @@ DSK_CHANGE_DIR: cp 1 ld a,2 ret nz + + ld a,(hl) + or a + ret z ;Empty string = root dir, so we're done _DSK_CHANGE_DIR_REL: _DSK_CHANGE_LOOP: @@ -239,7 +253,8 @@ _DSK_CHANGE_LOOP: ; ----------------------------------------------------------------------------- -; DSK_CHANGE_DIR_U: Change the current directoryand update config files +; DSK_CHANGE_DIR_U: Change the current directory +; and update config files and work area ; ; This one is tricky. We can't update CURDIR until after we are sure that ; the directory change has been sucessful, but if we update a config file @@ -274,15 +289,24 @@ _DSK_CHANGE_DIR_U: push af push hl + ;Set work area as "no file mounted" + + call WK_GET_STORAGE_DEV_FLAGS + and 0FEh + call WK_SET_STORAGE_DEV_FLAGS + + ;Get current dir from CURDIR, save in memory + push iy pop de inc de ld hl,DSK_CURDIR_S ld b,64 call DSK_READ_MAIN_CONFIG_FILE - call CHPUT ld (iy),b + ;Save new dir into CURDIR + pop hl push hl call BM_STRLEN @@ -291,17 +315,16 @@ _DSK_CHANGE_DIR_U: ld hl,DSK_CURDIR_S call DSK_WRITE_MAIN_CONFIG_FILE + ;Try the actual dir change, return if ok + pop hl pop af call DSK_CHANGE_DIR or a ret z - ld c,a - ld a,(iy) - or a - ld a,c - ret z + ;Rewrite CURDIR with its old value, + ;and change to the old directory again push iy pop de @@ -321,3 +344,181 @@ _DSK_CHANGE_DIR_U: DSK_CURDIR_S: db "CURDIR",0 + +; ----------------------------------------------------------------------------- +; DSK_MOUNT: Mount a file in the current directory +; and update config file and work area; +; in case of failure it restores the previously mounted file. +; +; This one is tricky as DSK_CHANGE_DIR_U, but even more because every time we +; want to mount a file (the requested one or the previous one) we need to ensure +; that the value of CURDIR is set as the current directory. +; ----------------------------------------------------------------------------- +; Input: HL = File path +; Output: A = 0: Ok +; 1: File not found +; 2: Other error + +DSK_MOUNT: + ld iy,-65-15 ;65 for dir name+0, 15 for file length+name+0 + add iy,sp + ld sp,iy + call _DSK_MOUNT + ld iy,65+15 + add iy,sp + ld sp,iy + ret + +_DSK_MOUNT: + push hl + + ;Set work area as "no file mounted" for now + + call WK_GET_STORAGE_DEV_FLAGS + and 0FEh + call WK_SET_STORAGE_DEV_FLAGS + + ;Get current dir from CURDIR, save in memory + + push iy + pop de + ld hl,DSK_CURDIR_S + ld b,64 + call DSK_READ_MAIN_CONFIG_FILE + xor a + ld (de),a + + ;Get current file from CURFILE, save in memory + + push iy + pop hl + ld de,65+1 + add hl,de ;HL = Buffer for file name from CURFILE + push hl + ex de,hl + ld hl,DSK_CURFILE_S + call DSK_READ_MAIN_CONFIG_FILE + pop hl + dec hl ;;HL = Buffer for length of file name + ld (hl),b + xor a + ld (de),a + + ;Set CURFILE with the new file to be mounted + + pop hl + push hl + pop de + push de + call BM_STRLEN + ld hl,DSK_CURFILE_S + call DSK_WRITE_MAIN_CONFIG_FILE + + ;Set current directory from CURDIR again + + push iy + pop hl + ld a,1 + call DSK_CHANGE_DIR + or a + pop hl ;Name of file to mount + ret nz ;Should never occur but just in case + + ;Try to actually mount the file, return if ok + + call HWF_OPEN_FILE_DIR + or a + jp z,_DSK_MOUNT_SET_WORK + + push af ;Save the error we'll return at the end + + ;Restore old contents of CURFILE + + push iy + pop hl + ld de,65 + add hl,de + ld b,(hl) + inc hl + ex de,hl + ld hl,DSK_CURFILE_S + call DSK_WRITE_MAIN_CONFIG_FILE + pop hl ;Error from mounting the requested file + or a + ld a,h + jr nz,_DSK_MOUNT_ERR_END_2 + push hl + + ;Set current directory from CURDIR again + + push iy + pop hl + ld a,1 + call DSK_CHANGE_DIR + or a + jr nz,_DSK_MOUNT_ERR_END ;Should never occur but just in case + + ;Mount file from CURFILE again if there was any + + push iy + pop hl + ld de,65+1 + add hl,de + ld a,(hl) + or a + jr z,_DSK_MOUNT_ERR_END + call HWF_OPEN_FILE_DIR + or a + call z,_DSK_MOUNT_SET_WORK + + ;Jump here on error from HWF_OPEN_FILE_DIR + +_DSK_MOUNT_ERR_END: + pop af +_DSK_MOUNT_ERR_END_2: + ld b,a + dec a + or a + ld a,2 + ret z ;Error was 1 + ld a,b + dec a + ret + + ;Set disk mounted flag in work area + +_DSK_MOUNT_SET_WORK: + push af + ld a,"!" + call CHPUT + call WK_GET_STORAGE_DEV_FLAGS + or 1+4 ;Disk present+disk has changed + call WK_SET_STORAGE_DEV_FLAGS + pop af + ret + +DSK_CURFILE_S: + db "CURFILE",0 + + +; ----------------------------------------------------------------------------- +; DSK_CHANGE_DIR_U: Change the current directory and update config files +; +; This one is tricky. We can't update CURDIR until after we are sure that +; the directory change has been sucessful, but if we update a config file +; after setting our directory then it won't be set anymore! Also if we fail +; we should restore the previous directory. +; +; Thus we do it like this: +; +; 1. Read current content of CURDIR, save in memory +; 2. Set CURDIR contents to the directory we want to change to +; 3. Try to change to the directory, if successful, we're all set +; 4. On error changing the directory, set CURDIR to its previous contents +; and change to it again +; ----------------------------------------------------------------------------- +; Input: HL = Directory path, "dir/dir2/dir3", no starting or ending "/" +; A = 0 for relative to current, 1 for absolute +; Output: A = 0: Ok +; 1: Directory not found +; 2: Other error diff --git a/msx/bank1/dskio_dskchg.asm b/msx/bank1/dskio_dskchg.asm index 0425005..5c05985 100644 --- a/msx/bank1/dskio_dskchg.asm +++ b/msx/bank1/dskio_dskchg.asm @@ -591,8 +591,17 @@ DSKCHG_IMPL: _DSKCHG_IMPL_STDEV: pop af - xor a - ld b,1 + call WK_GET_STORAGE_DEV_FLAGS + ld b,a + and 0BFh + call WK_SET_STORAGE_DEV_FLAGS + + ld a,b + and 4 + ld a,0 + ld b,1 ;Unchanged + ret z + ld b,0FFh ;Changed ret diff --git a/msx/bank1/work_area.asm b/msx/bank1/work_area.asm index 338daaf..f9b95c5 100644 --- a/msx/bank1/work_area.asm +++ b/msx/bank1/work_area.asm @@ -38,6 +38,7 @@ ; the OUT endpoint number) ; bit 0: set to 1 if there's a file mounted ; bit 1: set if mounted in read only mode +; bit 2: set if file has changed ; +1: Current directory depth: ; 0: no directory currently open ; 1: root directory, etc From 822a1d693d298f331457756c4abad5deb7d22498 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Mon, 8 Feb 2021 21:41:13 +0100 Subject: [PATCH 32/65] Improve error handling in the USB file related routines. Change error codes returned by HWF_OPEN_FILE_DIR and have the routines in dsk.asm use similar codes, simplifying the code. --- msx/bank1/boot_menu.asm | 19 ++++--- msx/bank1/ch376.asm | 29 ++++++---- msx/bank1/dsk.asm | 117 ++++++++++++---------------------------- 3 files changed, 61 insertions(+), 104 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index e0fe538..ee86608 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -90,13 +90,12 @@ DO_BOOT_MENU_MAIN: if USE_FAKE_STORAGE_DEVICE = 0 ld hl,BM_ROOT_DIR_S call HWF_OPEN_FILE_DIR - dec a ret nz ld hl,BM_DSK_S call HWF_OPEN_FILE_DIR - dec a ret nz + ret nc endif ; Init screen mode, draw fixed elements @@ -229,16 +228,17 @@ BM_DO_ENTER: BM_DO_ENTER_FILE: call BM_GET_BUF_ADD call HWF_OPEN_FILE_DIR - or a - jr z,_BM_DO_ENTER_FILE_IS_OPEN + jr nz,_BM_DO_ENTER_OPEN_ERR + jr nc,_BM_DO_ENTER_FILE_IS_OPEN _BM_DO_ENTER_OPEN_ERR: - dec a ;It's a dir: treat as other error (should never happen) + or a ;It's a dir: treat as other error (should never happen) + ld hl,BM_ERROR_OPENING_FILE_S + jr z,_BM_DO_ENTER_PRINT_ERR dec a - ld hl,BM_FILE_NOT_FOUND_S jr z,_BM_DO_ENTER_PRINT_ERR - ld hl,BM_ERROR_OPENING_FILE_S + ld hl,BM_FILE_NOT_FOUND_S _BM_DO_ENTER_PRINT_ERR: call BM_PRINT_STATUS_WAIT_KEY call BM_PRINT_MAIN_STATUS @@ -285,8 +285,8 @@ BM_DO_ENTER_DIR: call BM_GET_BUF_ADD call HWF_OPEN_FILE_DIR - cp 1 jp nz,_BM_DO_ENTER_OPEN_ERR + jp nc,_BM_DO_ENTER_OPEN_ERR ld a,(iy+BM_CUR_DIR_LEVEL) inc a @@ -351,7 +351,6 @@ BM_DO_BS: ld hl,BM_ROOT_DIR_S call HWF_OPEN_FILE_DIR - cp 1 jr z,_BM_DO_BS_OPEN_ROOT_OK _BM_DO_BS_OPEN_ERROR: @@ -394,8 +393,8 @@ _BM_DO_BS_FIND_SLASH: call HWF_OPEN_FILE_DIR pop hl pop bc - cp 1 jr nz,_BM_DO_BS_OPEN_ROOT_OK + jr nc,_BM_DO_BS_OPEN_ROOT_OK djnz _BM_DO_BS_LOOP diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index aa50a14..2680245 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -594,10 +594,13 @@ FAKE_DEV_NAME: ; HWF_OPEN_FILE_DIR: Open a file or enter a directory from the current one ; ----------------------------------------------------------------------------- ; Input: HL = Address of file or directory name, relative to current -; Output: A = 0: ok, file open -; 1: ok, directory entered +; Output: A = 0: ok, file or directory open +; 1: generic error (e.g. no device found) ; 2: file or directory not found -; 3: other error (e.g. no device found) +; +; Cy = 0: file open (if no error) +; 1: directory open (if no error) +; Z if ok, NZ if error ; HL = Pointer to terminator of file or directory name HWF_OPEN_FILE_DIR: @@ -623,19 +626,25 @@ HWF_OPEN_FILE_DIR: call CH_WAIT_INT_AND_GET_RESULT pop hl - ld b,0 + ld b,a cp USB_ERR_OK - jr z,_HWF_OPEN_FILE_DIR_END - inc b + ld a,0 + ret z ;NC, Z + + ld a,b cp USB_ERR_OPEN_DIR - jr z,_HWF_OPEN_FILE_DIR_END - inc b + ld a,0 + scf + ret z ;C, Z + + ld a,b cp USB_ERR_MISS_FILE + ld a,2 jr z,_HWF_OPEN_FILE_DIR_END - inc b + dec a _HWF_OPEN_FILE_DIR_END: - ld a,b + or a ;Force NZ ret diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index a6f0749..107e9fc 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -10,7 +10,7 @@ ; DSK_OPEN_MAIN_DIR: Open the main directory ; ----------------------------------------------------------------------------- ; Output: A = 0: Ok -; 1: Error +; 1: Other error DSK_OPEN_MAIN_DIR: push hl @@ -24,26 +24,22 @@ DSK_OPEN_MAIN_DIR: _DSK_OPEN_MAIN_DIR: ld hl,DSK_ROOT_DIR_S call HWF_OPEN_FILE_DIR - cp 1 - ld a,1 ret nz ld hl,DSK_MAIN_DIR_S call HWF_OPEN_FILE_DIR - ld b,a - cp 3 - ld a,1 ret z - ld a,b - dec a + jr c,_DSK_OPEN_MAIN_WAS_FILE + cp 1 ret z ld hl,DSK_ROOT_DIR_S - call HWF_OPEN_FILE_DIR - dec a - ret z - ld a,1 - ret + jp HWF_OPEN_FILE_DIR + +_DSK_OPEN_MAIN_WAS_FILE: + call HWF_CLOSE_FILE + ld hl,DSK_ROOT_DIR_S + jp HWF_OPEN_FILE_DIR DSK_ROOT_DIR_S: db "/",0 @@ -59,8 +55,8 @@ DSK_MAIN_DIR_S: ; DE = Destination address ; B = Max amount of bytes to read ; Output: A = 0: Ok -; 1: File not found -; 2: Other error +; 1: Other error +; 2: File not found ; B = Amount of bytes read if no error ; DE = Pointer after last byte read @@ -73,28 +69,18 @@ DSK_READ_CONFIG_FILE: pop bc pop de pop hl - ld c,a - cp 2 - ld a,1 - ret z - ld a,c - dec a - ld a,2 ret nz + ld a,1 + ret nc push de push bc call HWF_OPEN_FILE_DIR pop bc pop de - ld c,a - cp 2 - ld a,1 - ret z - ld a,c - or a - ld a,2 ret nz + ld a,1 + ret c ex de,hl ld c,b @@ -213,8 +199,9 @@ DSK_WRITE_MAIN_CONFIG_FILE: ; (the root dir is represented as an empty string) ; A = 0 for relative to current, 1 for absolute ; Output: A = 0: Ok -; 1: Directory not found -; 2: Other error +; 1: Other error +; 2: Directory not found +; 3: It's a file, not a directory DSK_CHANGE_DIR: or a @@ -224,8 +211,6 @@ DSK_CHANGE_DIR: ld hl,DSK_ROOT_DIR_S call HWF_OPEN_FILE_DIR pop hl - cp 1 - ld a,2 ret nz ld a,(hl) @@ -235,13 +220,9 @@ _DSK_CHANGE_DIR_REL: _DSK_CHANGE_LOOP: call HWF_OPEN_FILE_DIR - ld b,a - or a - ld a,2 - ret z - ld a,b - dec a ret nz + ld a,3 + ret nc ld a,(hl) inc hl @@ -272,8 +253,9 @@ _DSK_CHANGE_LOOP: ; Input: HL = Directory path, "dir/dir2/dir3", no starting or ending "/" ; A = 0 for relative to current, 1 for absolute ; Output: A = 0: Ok -; 1: Directory not found -; 2: Other error +; 1: Other error +; 2: Directory not found +; 3: It's a file, not a directory DSK_CHANGE_DIR_U: ld iy,-65 @@ -320,7 +302,6 @@ _DSK_CHANGE_DIR_U: pop hl pop af call DSK_CHANGE_DIR - or a ret z ;Rewrite CURDIR with its old value, @@ -356,8 +337,9 @@ DSK_CURDIR_S: ; ----------------------------------------------------------------------------- ; Input: HL = File path ; Output: A = 0: Ok -; 1: File not found -; 2: Other error +; 1: Other error +; 2: File not found +; 3: It's a directory, not a file DSK_MOUNT: ld iy,-65-15 ;65 for dir name+0, 15 for file length+name+0 @@ -399,7 +381,7 @@ _DSK_MOUNT: ld hl,DSK_CURFILE_S call DSK_READ_MAIN_CONFIG_FILE pop hl - dec hl ;;HL = Buffer for length of file name + dec hl ;HL = Buffer for length of file name ld (hl),b xor a ld (de),a @@ -427,8 +409,10 @@ _DSK_MOUNT: ;Try to actually mount the file, return if ok call HWF_OPEN_FILE_DIR - or a - jp z,_DSK_MOUNT_SET_WORK + jr nz,_DSK_MOUNT_ERR + jp nc,_DSK_MOUNT_SET_WORK + ld a,3 +_DSK_MOUNT_ERR: push af ;Save the error we'll return at the end @@ -446,7 +430,7 @@ _DSK_MOUNT: pop hl ;Error from mounting the requested file or a ld a,h - jr nz,_DSK_MOUNT_ERR_END_2 + ret nz push hl ;Set current directory from CURDIR again @@ -455,7 +439,6 @@ _DSK_MOUNT: pop hl ld a,1 call DSK_CHANGE_DIR - or a jr nz,_DSK_MOUNT_ERR_END ;Should never occur but just in case ;Mount file from CURFILE again if there was any @@ -468,29 +451,18 @@ _DSK_MOUNT: or a jr z,_DSK_MOUNT_ERR_END call HWF_OPEN_FILE_DIR - or a - call z,_DSK_MOUNT_SET_WORK + call z,_DSK_MOUNT_SET_WORK ;Assume it was a file, not a dir ;Jump here on error from HWF_OPEN_FILE_DIR _DSK_MOUNT_ERR_END: pop af -_DSK_MOUNT_ERR_END_2: - ld b,a - dec a - or a - ld a,2 - ret z ;Error was 1 - ld a,b - dec a ret ;Set disk mounted flag in work area _DSK_MOUNT_SET_WORK: push af - ld a,"!" - call CHPUT call WK_GET_STORAGE_DEV_FLAGS or 1+4 ;Disk present+disk has changed call WK_SET_STORAGE_DEV_FLAGS @@ -499,26 +471,3 @@ _DSK_MOUNT_SET_WORK: DSK_CURFILE_S: db "CURFILE",0 - - -; ----------------------------------------------------------------------------- -; DSK_CHANGE_DIR_U: Change the current directory and update config files -; -; This one is tricky. We can't update CURDIR until after we are sure that -; the directory change has been sucessful, but if we update a config file -; after setting our directory then it won't be set anymore! Also if we fail -; we should restore the previous directory. -; -; Thus we do it like this: -; -; 1. Read current content of CURDIR, save in memory -; 2. Set CURDIR contents to the directory we want to change to -; 3. Try to change to the directory, if successful, we're all set -; 4. On error changing the directory, set CURDIR to its previous contents -; and change to it again -; ----------------------------------------------------------------------------- -; Input: HL = Directory path, "dir/dir2/dir3", no starting or ending "/" -; A = 0 for relative to current, 1 for absolute -; Output: A = 0: Ok -; 1: Directory not found -; 2: Other error From 73ba2f1a708ca85e07c84d6bf4f9677911ab2d44 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 11 Feb 2021 17:12:40 +0100 Subject: [PATCH 33/65] Fixes in the DSK_CHANGE_DIR_U routine. --- msx/bank1/dsk.asm | 165 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 148 insertions(+), 17 deletions(-) diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index 107e9fc..f908557 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -10,7 +10,9 @@ ; DSK_OPEN_MAIN_DIR: Open the main directory ; ----------------------------------------------------------------------------- ; Output: A = 0: Ok -; 1: Other error +; 1: Error +; Z if ok, NZ if error +; Cy = 0 if root directory was open, 1 if DSK_MAIN_DIR_S was open DSK_OPEN_MAIN_DIR: push hl @@ -28,18 +30,20 @@ _DSK_OPEN_MAIN_DIR: ld hl,DSK_MAIN_DIR_S call HWF_OPEN_FILE_DIR - ret z - jr c,_DSK_OPEN_MAIN_WAS_FILE - cp 1 - ret z + jr nz,_DSK_OPEN_MAIN_REOPEN_ROOT + jr c,_DSK_OPEN_MAIN_WAS_MSX +_DSK_OPEN_MAIN_REOPEN_ROOT: ld hl,DSK_ROOT_DIR_S - jp HWF_OPEN_FILE_DIR + call HWF_OPEN_FILE_DIR +_DSK_OPEN_MAIN_END: + or a ;If error, set NZ; if ok, set Z and NC + ret -_DSK_OPEN_MAIN_WAS_FILE: - call HWF_CLOSE_FILE - ld hl,DSK_ROOT_DIR_S - jp HWF_OPEN_FILE_DIR +_DSK_OPEN_MAIN_WAS_MSX: + xor a + scf + ret DSK_ROOT_DIR_S: db "/",0 @@ -256,6 +260,7 @@ _DSK_CHANGE_LOOP: ; 1: Other error ; 2: Directory not found ; 3: It's a file, not a directory +; 4: Path is too long DSK_CHANGE_DIR_U: ld iy,-65 @@ -271,6 +276,22 @@ _DSK_CHANGE_DIR_U: push af push hl + ;If setting absolute dir we can check its length now + + or a + jr z,_DSK_CHANGE_DIR_U_LENGTH_OK + push hl + call BM_STRLEN + pop hl + ld a,b + cp BM_MAX_DIR_NAME_LENGTH+1 + jr c,_DSK_CHANGE_DIR_U_LENGTH_OK + pop hl + pop af + ld a,4 + ret +_DSK_CHANGE_DIR_U_LENGTH_OK: + ;Set work area as "no file mounted" call WK_GET_STORAGE_DEV_FLAGS @@ -287,20 +308,59 @@ _DSK_CHANGE_DIR_U: call DSK_READ_MAIN_CONFIG_FILE ld (iy),b - ;Save new dir into CURDIR + ;If setting relative dir check length now pop hl + pop af + or a + jr nz,_DSK_CHANGE_DIR_U_UPD_CURDIR push hl call BM_STRLEN - pop de - push de - ld hl,DSK_CURDIR_S - call DSK_WRITE_MAIN_CONFIG_FILE + ld a,b + add (iy) + inc a ;Account for the extra "/" to add + cp BM_MAX_DIR_NAME_LENGTH+1 + jr c,_DSK_CHANGE_DIR_U_LENGTH_OK_2 + pop hl + ld a,4 + ret +_DSK_CHANGE_DIR_U_LENGTH_OK_2: - ;Try the actual dir change, return if ok + ;Also if setting relative dir: + ;append dir to the one we have in memory + push iy pop hl - pop af + inc hl ;Skip length + ld e,(iy) + ld d,0 + add hl,de + ld (hl),'/' + inc hl + ex de,hl + + pop hl + push hl + call BM_STRLEN + pop hl + ld c,b + ld b,0 + inc bc ;Count the terminator too + ldir + + push iy + pop hl + inc hl + + ;Save new dir into CURDIR, + ;input: HL = new absolute dir + +_DSK_CHANGE_DIR_U_UPD_CURDIR: + call DSK_SET_CURDIR + + ;Try the actual dir change, return if ok + + ld a,1 call DSK_CHANGE_DIR ret z @@ -325,6 +385,18 @@ _DSK_CHANGE_DIR_U: DSK_CURDIR_S: db "CURDIR",0 + ;--- Set the value of CURDIR from HL, preserves HL + +DSK_SET_CURDIR: + push hl + call BM_STRLEN + pop de + push de + ld hl,DSK_CURDIR_S + call DSK_WRITE_MAIN_CONFIG_FILE + pop hl + ret + ; ----------------------------------------------------------------------------- ; DSK_MOUNT: Mount a file in the current directory @@ -471,3 +543,62 @@ _DSK_MOUNT_SET_WORK: DSK_CURFILE_S: db "CURFILE",0 + + +; ----------------------------------------------------------------------------- +; DSK_GET_CURDIR: Get (and enter) the current directory +; +; - If config file CURDIR exists and the directory it contains exists: return it +; - Otherwise, return the main directory +; +; Doesn't modify the contents of CURFILE. +; ----------------------------------------------------------------------------- +; Input: HL = Address of 65 byte buffer for directory name +; Output: A = 0: Ok +; 1: Error +; B = Length of name (not including terminator), 0 on error +; DE = Pointer to terminator + +DSK_GET_CURDIR: + ex de,hl + ld hl,DSK_CURDIR_S + push de + call DSK_READ_MAIN_CONFIG_FILE + or a + jr nz,_DSK_GET_CURDIR_NO_CONFIG + + pop hl + push hl + call HWF_OPEN_FILE_DIR + jr nz,_DSK_GET_CURDIR_NO_CONFIG + jr nc,_DSK_GET_CURDIR_NO_CONFIG + + inc sp + inc sp + ld (de),a + ret + +_DSK_GET_CURDIR_NO_CONFIG: + call DSK_OPEN_MAIN_DIR + ld a,1 + jr nz,_DSK_OPEN_MAIN_DIR_EMPTY + ld a,0 + jr nc,_DSK_OPEN_MAIN_DIR_EMPTY + + pop de + push de + ld hl,DSK_MAIN_DIR_S + ld bc,13 + ldir + pop hl + call BM_STRLEN + ex de,hl + xor a + ret + +_DSK_OPEN_MAIN_DIR_EMPTY: + pop de + ld b,0 + ret + + From 0a9a89473d16047618b8199a6b137135c658ef62 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 12 Feb 2021 16:39:20 +0100 Subject: [PATCH 34/65] Fixes in DSK_GET_CURDIR, and the boot menu now uses it for dir navigation. --- msx/bank1/boot_menu.asm | 154 +++++++++++++++++++++------------------- msx/bank1/dsk.asm | 10 ++- 2 files changed, 87 insertions(+), 77 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index ee86608..c6e14ae 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -9,10 +9,14 @@ BM_MAX_DIR_NAME_LENGTH: equ 64 ; ----------------------------------------------------------------------------- ; Boot menu entry point +; +; The starting point is CURDIR, or if it isn't set, the main directory. ; -; Output: A=0 if the menu was actually opened -; 1 if no storage device was found -; 2 if not enough memory +; Output: A = 0 if a file was actually mounted +; 1 if ESC or CTRL+STOP was pressed +; 2 if not enough memory to start the menu +; 3 if no storage device is present +; 4 if error getting initial directory ; ----------------------------------------------------------------------------- DO_BOOT_MENU: @@ -22,7 +26,7 @@ DO_BOOT_MENU: call USB_CHECK_DEV_CHANGE call WK_GET_STORAGE_DEV_FLAGS - ld a,1 + ld a,3 ret z ;Return with error if we have less than 1.5K of free space @@ -60,14 +64,15 @@ DO_BOOT_MENU: call DO_BOOT_MENU_MAIN + push af call BM_SCREEN_REST call KILBUF + pop af ld iy,BM_VARS_LEN add iy,sp ld sp,iy - xor a ret DO_BOOT_MENU_MAIN: @@ -75,29 +80,6 @@ DO_BOOT_MENU_MAIN: ld (iy+BM_CURSOR_LAST),a ld (iy+BM_NO_STOR_DEV),a - call BM_GET_CUR_DIR_ADD - ex de,hl - ld hl,BM_DSK_S - ld bc,5 - ldir - ld a,1 - ld (iy+BM_CUR_DIR_LEVEL),a - ld a,4 - ld (iy+BM_CUR_DIR_LENGTH),a - - ; Try opening DSK directory on the device - - if USE_FAKE_STORAGE_DEVICE = 0 - ld hl,BM_ROOT_DIR_S - call HWF_OPEN_FILE_DIR - ret nz - - ld hl,BM_DSK_S - call HWF_OPEN_FILE_DIR - ret nz - ret nc - endif - ; Init screen mode, draw fixed elements call CLS @@ -111,6 +93,43 @@ DO_BOOT_MENU_MAIN: call POSIT call BM_DRAW_LINE + ; Try opening CURDIR or the main directory on the device + + if USE_FAKE_STORAGE_DEVICE = 0 + + call BM_GET_CUR_DIR_ADD + push hl + call DSK_GET_CURDIR + pop hl + or a + jr z,_BM_MAIN_GETDIR_OK + ld hl,BM_ERROR_OPENING_FILE_S + call BM_PRINT_STATUS_WAIT_KEY + ld a,4 + ret + +_BM_MAIN_GETDIR_OK: + ld (iy+BM_CUR_DIR_LENGTH),b + + ld b,0 + ld a,(hl) + or a + jr z,_BM_CALC_DIR_LEVEL_END + inc b ;Non-empty dir: start at level 1, each "/" increases level +_BM_CALC_DIR_LEVEL: + ld a,(hl) + inc hl + or a + jr z,_BM_CALC_DIR_LEVEL_END + cp "/" + jr nz,_BM_CALC_DIR_LEVEL + inc b + jr _BM_CALC_DIR_LEVEL +_BM_CALC_DIR_LEVEL_END: + ld (iy+BM_CUR_DIR_LEVEL),b + + endif + call BM_PRINT_CUR_DIR call BM_ENUM_FILES @@ -141,10 +160,12 @@ BM_ENTER_MAIN_LOOP: _BM_MAIN_LOOP: halt call BREAKX + ld a,1 ret c - ld de,0407h + ld de,0407h ;ESC pressed? call BM_KEY_CHECK + ld a,1 ret z call BM_F5_IS_PRESSED @@ -183,7 +204,7 @@ BM_START_OVER: call BM_CLEAR_INFO_AREA xor a - ld (iy+BM_CUR_DIR+1),a + ld (iy+BM_CUR_DIR),a call BM_PRINT_CUR_DIR ld hl,BM_RESETTING_DEVICE_S call BM_PRINT_STATUS @@ -268,7 +289,8 @@ _BM_DO_ENTER_FILE_IS_OPEN_ATTR_OK: call BM_PRINT_STATUS call KILBUF - ret ;Continue computer boot process + xor a + ret ;Exit menu ;* It's a directory @@ -349,13 +371,31 @@ BM_DO_BS: ld hl,BM_ENTERING_DIR_S call BM_PRINT_STATUS - ld hl,BM_ROOT_DIR_S - call HWF_OPEN_FILE_DIR - jr z,_BM_DO_BS_OPEN_ROOT_OK + call BM_GET_CUR_DIR_ADD + push hl + ld a,(iy+BM_CUR_DIR_LEVEL) + dec a + jr z,_BM_DO_BS_FOUND_SLASH ;We are in level 1: just zero the current dir + ld c,(iy+BM_CUR_DIR_LENGTH) + ld b,0 + add hl,bc +_BM_DO_BS_FIND_SLASH_LOOP: + dec hl + ld a,(hl) + cp "/" + jr nz,_BM_DO_BS_FIND_SLASH_LOOP + +_BM_DO_BS_FOUND_SLASH: + ld (hl),0 + pop hl + ld a,1 + call DSK_CHANGE_DIR + or a + jr z,_BM_DO_BS_END _BM_DO_BS_OPEN_ERROR: xor a - ld (iy+BM_CUR_DIR+1),a + ld (iy+BM_CUR_DIR),a call BM_PRINT_CUR_DIR ld hl,BM_ERROR_OPENING_FILE_S call BM_PRINT_STATUS_WAIT_KEY @@ -367,36 +407,6 @@ _BM_DO_BS_OPEN_ERROR: ld (iy+BM_CUR_PAGE),a ld (iy+BM_CUR_DIR_LENGTH),a jp BM_ENTER_MAIN_LOOP -_BM_DO_BS_OPEN_ROOT_OK: - - ld a,(iy+BM_CUR_DIR_LEVEL) - dec a - jp z,_BM_DO_BS_LV1_END - ld b,a ;How many levels to go back - call BM_GET_CUR_DIR_ADD ;Pointer to dir at current level, -1 - -_BM_DO_BS_LOOP: - push bc - push hl - ld (hl),"/" ;Restore the slash we had zero-ed in the last loop step - inc hl -_BM_DO_BS_FIND_SLASH: - ld a,(hl) - inc hl - cp "/" - jr nz,_BM_DO_BS_FIND_SLASH - - dec hl - ld (hl),0 ;Temporarily replace ending slash with 0 for HWF_OPEN_FILE_DIR - ex (sp),hl ;Now HL=Start of dir name-1, (SP)=Terminator - inc hl - call HWF_OPEN_FILE_DIR - pop hl - pop bc - jr nz,_BM_DO_BS_OPEN_ROOT_OK - jr nc,_BM_DO_BS_OPEN_ROOT_OK - - djnz _BM_DO_BS_LOOP _BM_DO_BS_END: ld a,(iy+BM_CUR_DIR_LEVEL) @@ -411,12 +421,6 @@ _BM_DO_BS_END_2: call BM_ENUM_FILES jp BM_ENTER_MAIN_LOOP -_BM_DO_BS_LV1_END: - xor a - ld (iy+BM_CUR_DIR+1),a - ld (iy+BM_CUR_DIR_LEVEL),a - jr _BM_DO_BS_END_2 - ;--- Help loop, entered when F1 is pressed @@ -1015,12 +1019,14 @@ _BM_PRINT_INVERTED_LOOP: ;--- Print the current directory in the top row BM_PRINT_CUR_DIR: - ld h,2 + ld h,1 ld l,1 call POSIT + ld a,"/" + call CHPUT ld a,(iy+BM_CUR_DIR_LENGTH) - cp 41 + cp 40 jr c,_BM_PRINT_CUR_DIR_DIRECT ld hl,BM_DOTS_BAR_S @@ -1474,7 +1480,7 @@ BM_CUR_COL: equ BM_CUR_ROW+1 ;Current logical column, 0-2 BM_CURSOR_LAST: equ BM_CUR_COL+1 ;Result of last call to BM_CURSOR_IS_PRESSED BM_NO_STOR_DEV: equ BM_CURSOR_LAST+1 ;FFh if F5 was pressed and no storage device was found BM_CUR_DIR_LEVEL: equ BM_NO_STOR_DEV+1 ;Current direcrory level, 0 is root -BM_CUR_DIR: equ BM_CUR_DIR_LEVEL+1 ;Current directory, up to BM_MAX_DIR_NAME_LENGTH-1 chars + 0 +BM_CUR_DIR: equ BM_CUR_DIR_LEVEL+1 ;Current directory, up to BM_MAX_DIR_NAME_LENGTH chars + 0 BM_CUR_DIR_LENGTH: equ BM_CUR_DIR+BM_MAX_DIR_NAME_LENGTH+1 BM_MAX_FILES_TO_ENUM: equ BM_CUR_DIR_LENGTH+1 BM_SCRMOD_BAK: equ BM_MAX_FILES_TO_ENUM+2 diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index f908557..6841f22 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -563,19 +563,23 @@ DSK_GET_CURDIR: ex de,hl ld hl,DSK_CURDIR_S push de + ld b,64 call DSK_READ_MAIN_CONFIG_FILE or a jr nz,_DSK_GET_CURDIR_NO_CONFIG + ld (de),a pop hl push hl - call HWF_OPEN_FILE_DIR + push bc + ld a,1 + call DSK_CHANGE_DIR + pop bc + or a jr nz,_DSK_GET_CURDIR_NO_CONFIG - jr nc,_DSK_GET_CURDIR_NO_CONFIG inc sp inc sp - ld (de),a ret _DSK_GET_CURDIR_NO_CONFIG: From 4a654af91695fb182d8c092fad810c2e5298fc14 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sun, 14 Feb 2021 22:16:34 +0100 Subject: [PATCH 35/65] The boot menu now uses DSK_MOUNT to mount files. Also, DSK_MOUNT now checks if the file has the read-only flag. --- msx/bank1/boot_menu.asm | 48 ++++++++++++++++----------------------- msx/bank1/dsk.asm | 50 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 32 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index c6e14ae..eecd42e 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -247,19 +247,27 @@ BM_DO_ENTER: ;* It's a file BM_DO_ENTER_FILE: - call BM_GET_BUF_ADD - call HWF_OPEN_FILE_DIR - jr nz,_BM_DO_ENTER_OPEN_ERR - jr nc,_BM_DO_ENTER_FILE_IS_OPEN + call BM_CLEAR_INFO_AREA + ld hl,BM_MOUNTING_BOOTING_S + call BM_PRINT_STATUS -_BM_DO_ENTER_OPEN_ERR: - or a ;It's a dir: treat as other error (should never happen) + call BM_GET_CUR_DIR_ADD + call DSK_WRITE_CURDIR_FILE + or a ld hl,BM_ERROR_OPENING_FILE_S - jr z,_BM_DO_ENTER_PRINT_ERR - dec a - jr z,_BM_DO_ENTER_PRINT_ERR + jr nz,_BM_DO_ENTER_OPEN_ERR + call BM_GET_BUF_ADD + xor a + call DSK_MOUNT + or a + jr z,_BM_DO_ENTER_FILE_SUCCESS ;Exit boot menu + +_BM_DO_ENTER_OPEN_ERR: + cp 2 ld hl,BM_FILE_NOT_FOUND_S + jr z,_BM_DO_ENTER_PRINT_ERR + ld hl,BM_ERROR_OPENING_FILE_S ;Other error or it's a dir _BM_DO_ENTER_PRINT_ERR: call BM_PRINT_STATUS_WAIT_KEY call BM_PRINT_MAIN_STATUS @@ -267,27 +275,9 @@ _BM_DO_ENTER_PRINT_ERR: _BM_DO_ENTER_WAIT_RELEASE: ;In case the "any key" pressed is enter call BM_ENTER_IS_PRESSED jr z,_BM_DO_ENTER_WAIT_RELEASE - jp _BM_MAIN_LOOP - -_BM_DO_ENTER_FILE_IS_OPEN: - call HWF_GET_FILE_ATTR - dec a - jr z,_BM_DO_ENTER_FILE_IS_OPEN_ATTR_OK ;Error, assume not read-only - ld a,b ;Attributes byte, read-only in bit 0 - rla ;Now read-only in bit 1 - and 2 - -_BM_DO_ENTER_FILE_IS_OPEN_ATTR_OK: - ld b,a - call WK_GET_STORAGE_DEV_FLAGS - or 1 ;There's a file open - or b ;Maybe read-only flag - call WK_SET_STORAGE_DEV_FLAGS - - call BM_CLEAR_INFO_AREA - ld hl,BM_MOUNTING_BOOTING_S - call BM_PRINT_STATUS + jp BM_ENTER_MAIN_LOOP ; _BM_MAIN_LOOP +_BM_DO_ENTER_FILE_SUCCESS: call KILBUF xor a ret ;Exit menu diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index 6841f22..c0429c8 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -195,6 +195,21 @@ DSK_WRITE_MAIN_CONFIG_FILE: jp DSK_WRITE_CONFIG_FILE +; ----------------------------------------------------------------------------- +; DSK_WRITE_CURDIR_FILE: Write CURDIR config file in main directory +; ----------------------------------------------------------------------------- +; Input: HL = Address of content to write, zero-terminated +; Output: A = 0: Ok +; 1: Error + +DSK_WRITE_CURDIR_FILE: + push hl + call BM_STRLEN + pop de + ld hl,DSK_CURDIR_S + jp DSK_WRITE_MAIN_CONFIG_FILE + + ; ----------------------------------------------------------------------------- ; DSK_CHANGE_DIR: Change the current directory ; (doesn't update config files or work area) @@ -263,6 +278,7 @@ _DSK_CHANGE_LOOP: ; 4: Path is too long DSK_CHANGE_DIR_U: + push iy ld iy,-65 add iy,sp ld sp,iy @@ -270,6 +286,7 @@ DSK_CHANGE_DIR_U: ld iy,65 add iy,sp ld sp,iy + pop iy ret _DSK_CHANGE_DIR_U: @@ -408,22 +425,28 @@ DSK_SET_CURDIR: ; that the value of CURDIR is set as the current directory. ; ----------------------------------------------------------------------------- ; Input: HL = File path +; A = 0: Mount as read-only if read-only flag is set +; 1: Force mount as read and write +; 2: Force mount as read-only ; Output: A = 0: Ok ; 1: Other error ; 2: File not found ; 3: It's a directory, not a file DSK_MOUNT: - ld iy,-65-15 ;65 for dir name+0, 15 for file length+name+0 + push iy + ld iy,-65-15-1 ;65 for dir name+0, 15 for file length+name+0, 1 extra for read-only mode add iy,sp ld sp,iy call _DSK_MOUNT - ld iy,65+15 + ld iy,65+15+1 add iy,sp ld sp,iy + pop iy ret _DSK_MOUNT: + ld (iy+65+15),a push hl ;Set work area as "no file mounted" for now @@ -480,12 +503,14 @@ _DSK_MOUNT: ;Try to actually mount the file, return if ok + push hl call HWF_OPEN_FILE_DIR + pop hl jr nz,_DSK_MOUNT_ERR jp nc,_DSK_MOUNT_SET_WORK ld a,3 _DSK_MOUNT_ERR: - + ld (iy+65+15),0 ;Remount old file in auto-readonly mode push af ;Save the error we'll return at the end ;Restore old contents of CURFILE @@ -522,7 +547,9 @@ _DSK_MOUNT_ERR: ld a,(hl) or a jr z,_DSK_MOUNT_ERR_END + push hl call HWF_OPEN_FILE_DIR + pop hl call z,_DSK_MOUNT_SET_WORK ;Assume it was a file, not a dir ;Jump here on error from HWF_OPEN_FILE_DIR @@ -532,11 +559,28 @@ _DSK_MOUNT_ERR_END: ret ;Set disk mounted flag in work area + ;HL = File name _DSK_MOUNT_SET_WORK: push af + ld a,(iy+65+15) + cp 2 + jr z,_DSK_MOUNT_SET_WORK_DO + cp 1 + ld a,0 + jr z,_DSK_MOUNT_SET_WORK_DO + call HWF_GET_FILE_ATTR + dec a + jr z,_DSK_MOUNT_SET_WORK_DO ;Error, assume not read-only + ld a,b ;Attributes byte, read-only in bit 0 + rla ;Now read-only in bit 1 + and 2 + +_DSK_MOUNT_SET_WORK_DO: + ld b,a call WK_GET_STORAGE_DEV_FLAGS or 1+4 ;Disk present+disk has changed + or b ;Read-only flag (maybe) call WK_SET_STORAGE_DEV_FLAGS pop af ret From dcafa05c2cd0708ffacd8260433ff99735960d20 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sat, 20 Feb 2021 18:08:30 +0100 Subject: [PATCH 36/65] The boot menu now accepts a parameter that tells what to mount initially (current directory or main directory) --- msx/bank1/boot_menu.asm | 160 +++++++++++++++++++++++++++++----------- msx/bank1/dsk.asm | 6 +- 2 files changed, 120 insertions(+), 46 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index eecd42e..a5ad2c6 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -12,18 +12,27 @@ BM_MAX_DIR_NAME_LENGTH: equ 64 ; ; The starting point is CURDIR, or if it isn't set, the main directory. ; +; Input: A = What should the initial directory be: +; 0: The main directory +; 1: The current directory +; The initial directory is to be set: +; - When the menu starts +; - When F5 is pressed +; - When exiting without mounting ; Output: A = 0 if a file was actually mounted ; 1 if ESC or CTRL+STOP was pressed ; 2 if not enough memory to start the menu ; 3 if no storage device is present -; 4 if error getting initial directory +; 4 if error setting initial directory (not ehrn F5-ing) ; ----------------------------------------------------------------------------- DO_BOOT_MENU: ;Return with error if no storage device was found + push af call USB_CHECK_DEV_CHANGE + pop hl call WK_GET_STORAGE_DEV_FLAGS ld a,3 @@ -31,6 +40,7 @@ DO_BOOT_MENU: ;Return with error if we have less than 1.5K of free space + push hl ld hl,0 add hl,sp ld de,(STREND) @@ -39,6 +49,7 @@ DO_BOOT_MENU: ld a,h cp 6 ld a,2 + pop de ret c ld bc,100+660+BM_VARS_LEN ;Work stack space + space for one page of 0s + space for variables @@ -46,15 +57,19 @@ DO_BOOT_MENU: sbc hl,bc push hl pop bc + push de ld de,11 call DIVIDE_16 + pop de + push iy ld iy,-BM_VARS_LEN add iy,sp ld sp,iy ld (iy+BM_MAX_FILES_TO_ENUM),c ld (iy+BM_MAX_FILES_TO_ENUM+1),b + ld (iy+BM_INITIAL_DIR),d call BM_SCREEN_BAK ld a,40 @@ -72,6 +87,7 @@ DO_BOOT_MENU: ld iy,BM_VARS_LEN add iy,sp ld sp,iy + pop iy ret @@ -93,42 +109,12 @@ DO_BOOT_MENU_MAIN: call POSIT call BM_DRAW_LINE - ; Try opening CURDIR or the main directory on the device - - if USE_FAKE_STORAGE_DEVICE = 0 + ; Try opening the initial directory - call BM_GET_CUR_DIR_ADD - push hl - call DSK_GET_CURDIR - pop hl + call BM_OPEN_INITIAL_DIR or a - jr z,_BM_MAIN_GETDIR_OK - ld hl,BM_ERROR_OPENING_FILE_S - call BM_PRINT_STATUS_WAIT_KEY ld a,4 - ret - -_BM_MAIN_GETDIR_OK: - ld (iy+BM_CUR_DIR_LENGTH),b - - ld b,0 - ld a,(hl) - or a - jr z,_BM_CALC_DIR_LEVEL_END - inc b ;Non-empty dir: start at level 1, each "/" increases level -_BM_CALC_DIR_LEVEL: - ld a,(hl) - inc hl - or a - jr z,_BM_CALC_DIR_LEVEL_END - cp "/" - jr nz,_BM_CALC_DIR_LEVEL - inc b - jr _BM_CALC_DIR_LEVEL -_BM_CALC_DIR_LEVEL_END: - ld (iy+BM_CUR_DIR_LEVEL),b - - endif + ret nz call BM_PRINT_CUR_DIR call BM_ENUM_FILES @@ -195,30 +181,36 @@ _BM_MAIN_LOOP: ;--- Start over after F5 is pressed BM_START_OVER: - xor a - ld (iy+BM_NUM_FILES),a - ld (iy+BM_NUM_FILES+1),a - inc a - ld (iy+BM_CUR_PAGE),a - ld (iy+BM_NUM_PAGES),a - call BM_CLEAR_INFO_AREA xor a ld (iy+BM_CUR_DIR),a + call BM_ADJUST_DIR_VARS call BM_PRINT_CUR_DIR ld hl,BM_RESETTING_DEVICE_S call BM_PRINT_STATUS + ld hl,0 call HWF_MOUNT_DISK - jp nc,DO_BOOT_MENU_MAIN + jr nc,_BM_START_OVER_OK + xor a + ld (iy+BM_NUM_FILES),a + ld (iy+BM_NUM_FILES+1),a + call WK_SET_STORAGE_DEV_FLAGS + inc a + ld (iy+BM_CUR_PAGE),a + ld (iy+BM_NUM_PAGES),a ld a,0FFh ld (iy+BM_NO_STOR_DEV),a ld hl,BM_NO_DEV_OR_NO_STOR_S call BM_PRINT_STATUS - + call CHGET jp _BM_MAIN_LOOP +_BM_START_OVER_OK: + call WK_INIT_FOR_STORAGE_DEV + jp DO_BOOT_MENU_MAIN + ; ----------------------------------------------------------------------------- ; Key press handlers @@ -1362,6 +1354,84 @@ BM_GET_CUR_DIR_ADD: ret +;--- Adjust variables after BM_CUR_DIR has changed + +BM_ADJUST_DIR_VARS: + call BM_GET_CUR_DIR_ADD + push hl + call BM_STRLEN + pop hl + ld (iy+BM_CUR_DIR_LENGTH),b + + ld b,0 + ld a,(hl) + or a + jr z,_BM_CALC_DIR_LEVEL_END + inc b ;Non-empty dir: start at level 1, each "/" increases level +_BM_CALC_DIR_LEVEL: + ld a,(hl) + inc hl + or a + jr z,_BM_CALC_DIR_LEVEL_END + cp "/" + jr nz,_BM_CALC_DIR_LEVEL + inc b + jr _BM_CALC_DIR_LEVEL +_BM_CALC_DIR_LEVEL_END: + ld (iy+BM_CUR_DIR_LEVEL),b + + ret + + +;--- Try opening the initial directory +; Output: A = 0 if ok, 1 if error + +BM_OPEN_INITIAL_DIR: + if USE_FAKE_STORAGE_DEVICE = 0 + + ld a,(iy+BM_INITIAL_DIR) + or a + jr nz,_BM_OPEN_INITIAL_CURDIR + +_BM_OPEN_INITIAL_MAIN: + call DSK_OPEN_MAIN_DIR + jr nz,_BM_MAIN_GETDIR_ERR + ld hl,DSK_MAIN_DIR_S + jr c,_BM_OPEN_INITIAL_MAIN_2 + ld hl,DSK_ROOT_DIR_S +_BM_OPEN_INITIAL_MAIN_2: + push hl + call BM_GET_CUR_DIR_ADD + ex de,hl + pop hl + ld bc,BM_MAX_DIR_NAME_LENGTH+1 + ldir + jr _BM_OPEN_INITIAL_MAIN_OK + +_BM_OPEN_INITIAL_CURDIR: + call BM_GET_CUR_DIR_ADD + call DSK_GET_CURDIR + or a + jr nz,_BM_MAIN_GETDIR_ERR + +_BM_OPEN_INITIAL_MAIN_OK: + call BM_ADJUST_DIR_VARS + xor a + ret + +_BM_MAIN_GETDIR_ERR + ld hl,BM_ERROR_INITIAL_S + call BM_PRINT_STATUS_WAIT_KEY + ld a,1 + ret + + else + + xor a + ret + + endif + ; ----------------------------------------------------------------------------- ; Text strings ; ----------------------------------------------------------------------------- @@ -1407,6 +1477,9 @@ BM_FILE_NOT_FOUND_S: BM_ERROR_OPENING_FILE_S: db "Error opening file/dir! Press any key",0 +BM_ERROR_INITIAL_S: + db "Error entering initial dir! Press any key",0 + BM_MOUNTING_BOOTING_S: db "Mounting file and booting...",0 @@ -1476,6 +1549,7 @@ BM_MAX_FILES_TO_ENUM: equ BM_CUR_DIR_LENGTH+1 BM_SCRMOD_BAK: equ BM_MAX_FILES_TO_ENUM+2 BM_LINLEN_BAK: equ BM_SCRMOD_BAK+1 BM_FNK_BAK: equ BM_LINLEN_BAK+1 +BM_INITIAL_DIR: equ BM_FNK_BAK+1 BM_VARS_END: equ BM_FNK_BAK+1 BM_VARS_LEN: equ BM_VARS_END-BM_VARS_START \ No newline at end of file diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index c0429c8..a6fa6e8 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -49,7 +49,9 @@ DSK_ROOT_DIR_S: db "/",0 DSK_MAIN_DIR_S: - db "MSX",0 + db "MSX" +DSK_ZERO_S: + db 0 ; ----------------------------------------------------------------------------- @@ -648,5 +650,3 @@ _DSK_OPEN_MAIN_DIR_EMPTY: pop de ld b,0 ret - - From 413db7d6191d457de32cab5d44862c70668eed24 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sat, 20 Feb 2021 22:49:39 +0100 Subject: [PATCH 37/65] Boot menu: remount previous file if exited with ESC --- msx/bank0/oemstat.asm | 8 ++-- msx/bank1/boot_menu.asm | 11 ++++- msx/bank1/dsk.asm | 101 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 113 insertions(+), 7 deletions(-) diff --git a/msx/bank0/oemstat.asm b/msx/bank0/oemstat.asm index 92e8474..0a40fcc 100644 --- a/msx/bank0/oemstat.asm +++ b/msx/bank0/oemstat.asm @@ -156,18 +156,18 @@ OEMC_USBMENU: ld ix,DO_BOOT_MENU ld iy,ROM_BANK_1 call CALL_BANK - dec a + cp 3 ld hl,OEM_S_NO_STDEV jp z,OEM_PRINT_AND_END - dec a + cp 2 ld hl,OEM_S_NO_MEM jp z,OEM_PRINT_AND_END jp OEM_END OEM_S_NO_STDEV: - db "No USB storage device present",0 + db "No USB storage device present",7,0 OEM_S_NO_MEM: - db "Not enough memory",0 + db "Not enough memory",7,0 ; ----------------------------------------------------------------------------- diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index a5ad2c6..982331e 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -23,7 +23,7 @@ BM_MAX_DIR_NAME_LENGTH: equ 64 ; 1 if ESC or CTRL+STOP was pressed ; 2 if not enough memory to start the menu ; 3 if no storage device is present -; 4 if error setting initial directory (not ehrn F5-ing) +; 4 if error setting initial directory (not when F5-ing) ; ----------------------------------------------------------------------------- DO_BOOT_MENU: @@ -82,6 +82,15 @@ DO_BOOT_MENU: push af call BM_SCREEN_REST call KILBUF + + ld a,(iy+BM_INITIAL_DIR) + or a + jr z,_BM_NO_REMOUNT + pop af + push af + cp 1 + call z,DSK_REMOUNT +_BM_NO_REMOUNT: pop af ld iy,BM_VARS_LEN diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index a6fa6e8..9500977 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -110,8 +110,8 @@ DSK_CONFIG_DIR_S: ; DE = Destination address ; B = Max amount of bytes to read ; Output: A = 0: Ok -; 1: File not found -; 2: Other error +; 1: Other error +; 2: File not found ; B = Amount of bytes read if no error, 0 on error ; DE = Pointer after last byte read @@ -650,3 +650,100 @@ _DSK_OPEN_MAIN_DIR_EMPTY: pop de ld b,0 ret + + +; ----------------------------------------------------------------------------- +; DSK_REMOUNT: Mount again the current file (per CURDIR and CURFILE) +; ----------------------------------------------------------------------------- +; Input: HL = Address of 65 byte buffer for directory name +; Output: A = 0: Ok +; 1: Other error +; 2: No CURDIR file, or directory doesn't exist +; 3: No CURFILE file, or file doesn't exist + +DSK_REMOUNT: + push iy + ld iy,-65-13 + add iy,sp + ld sp,iy + call _DSK_REMOUNT + ld iy,65+13 + add iy,sp + ld sp,iy + pop iy + ret + +_DSK_REMOUNT: + call WK_GET_STORAGE_DEV_FLAGS ;No disk mounted for now + and 0FEh + call WK_SET_STORAGE_DEV_FLAGS + + push iy + pop de + ld hl,DSK_CURDIR_S + ld b,64 + call DSK_READ_MAIN_CONFIG_FILE + or a + ret nz + ld (de),a + + push iy + pop hl + ld bc,65 + add hl,bc + ex de,hl + ld hl,DSK_CURFILE_S + ld b,12 + call DSK_READ_MAIN_CONFIG_FILE + or a + jr z,_DSK_REMOUNT_OK + cp 1 + ret z + ld a,3 + ret +_DSK_REMOUNT_OK: + ld (de),a + + push iy + pop hl + ld a,1 + call DSK_CHANGE_DIR + cp 1 + ret z + cp 2 + ret z + cp 3 + ld a,1 + ret z ;It's a file, not a dir + + push iy + pop hl + ld bc,65 + add hl,bc + call HWF_OPEN_FILE_DIR + jr z,_DSK_REMOUNT_OK_2 + cp 1 + ret z + ld a,3 + ret + +_DSK_REMOUNT_OK_2: + ld a,1 + ret c ;It's a dir, not a file + + call HWF_GET_FILE_ATTR + dec a + jr z,_DSK_REMOUNT_OK_3 ;Error, assume not read-only + ld a,b ;Attributes byte, read-only in bit 0 + rla ;Now read-only in bit 1 + and 2 + +_DSK_REMOUNT_OK_3: + ld b,a + call WK_GET_STORAGE_DEV_FLAGS + or 1+4 ;Disk present+disk has changed + or b ;Read-only flag (maybe) + call WK_SET_STORAGE_DEV_FLAGS + + xor a + ret From ea90279ad22c923a50de1f1154aa0ef606bcfc37 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Mon, 22 Feb 2021 11:08:53 +0100 Subject: [PATCH 38/65] Boot menu: exit with SHIT+ESC to set viewed dir as current --- msx/bank1/boot_menu.asm | 51 +++++++++++++++++++++++++++++-------- msx/bank1/ch376.asm | 2 ++ msx/bank1/dskio_dskchg.asm | 12 +++++---- msx/bank1/verbose_reset.asm | 5 ++-- 4 files changed, 53 insertions(+), 17 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 982331e..4839225 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -160,8 +160,7 @@ _BM_MAIN_LOOP: ld de,0407h ;ESC pressed? call BM_KEY_CHECK - ld a,1 - ret z + jp z,BM_DO_ESC call BM_F5_IS_PRESSED jp z,BM_START_OVER @@ -229,6 +228,23 @@ _BM_START_OVER_OK: ; ----------------------------------------------------------------------------- +;--- ESC key press handler + +BM_DO_ESC: + ld de,0106h + call BM_KEY_CHECK_CORE + ld a,1 + ret nz + + ld hl,BM_CHANGING_EXITING_S + call BM_PRINT_STATUS + call BM_GET_CUR_DIR_ADD + ld a,1 + call DSK_CHANGE_DIR_U + ld a,5 + ret + + ;--- ENTER key press handler BM_DO_ENTER: @@ -1066,12 +1082,7 @@ _BM_GET_LAST_DIR_PNT_LOOP: ; Output: Z if key is pressed, NZ if not BM_KEY_CHECK: - ld b,d - ld d,0 - ld hl,NEWKEY - add hl,de - ld a,(hl) - and b + call BM_KEY_CHECK_CORE ret nz _BM_KEY_CHECK_WAIT_RELEASE: @@ -1082,6 +1093,17 @@ _BM_KEY_CHECK_WAIT_RELEASE: xor a ret + ;This version doesn't wait for key release + +BM_KEY_CHECK_CORE: + ld b,d + ld d,0 + ld hl,NEWKEY + add hl,de + ld a,(hl) + and b + ret + ;--- Check if F1 is pressed ; Output: Z if pressed, NZ if not @@ -1490,11 +1512,14 @@ BM_ERROR_INITIAL_S: db "Error entering initial dir! Press any key",0 BM_MOUNTING_BOOTING_S: - db "Mounting file and booting...",0 + db "Mounting file...",0 BM_ENTERING_DIR_S: db "Entering directory...",0 +BM_CHANGING_EXITING_S: + db "Changing current dir and exiting...",0 + BM_DOTS_BAR_S: db "/.../",0 @@ -1519,10 +1544,16 @@ BM_HELP_1: db 13,10 db " F5: Reset device and start over",13,10 db 13,10 - db " CTRL+STOP/ESC: Exit without mounting" + db 0 BM_HELP_2: + db " ESC: Exit without mounting",13,10 + db 13,10 + db " SHIFT+ESC: Set current dir and",13,10 + db " exit without mounting",13,10 + db 13,10 + db 13,10 db " After boot it is possible to switch",13,10 db " to another disk image file from the",13,10 db " same directory (up to 36 files).",13,10 diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index 2680245..aa5a233 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -629,6 +629,8 @@ HWF_OPEN_FILE_DIR: ld b,a cp USB_ERR_OK ld a,0 + scf + ccf ret z ;NC, Z ld a,b diff --git a/msx/bank1/dskio_dskchg.asm b/msx/bank1/dskio_dskchg.asm index 5c05985..252e2bb 100644 --- a/msx/bank1/dskio_dskchg.asm +++ b/msx/bank1/dskio_dskchg.asm @@ -335,6 +335,10 @@ _DSKIO_IMPL_STDEV: push hl push bc + call WK_GET_STORAGE_DEV_FLAGS + and 0FBh ;reset "Disk changed" flag + call WK_SET_STORAGE_DEV_FLAGS + ld h,0 ld l,d ld d,e @@ -591,16 +595,14 @@ DSKCHG_IMPL: _DSKCHG_IMPL_STDEV: pop af + call WK_GET_STORAGE_DEV_FLAGS - ld b,a - and 0BFh - call WK_SET_STORAGE_DEV_FLAGS - - ld a,b and 4 ld a,0 ld b,1 ;Unchanged ret z + call GETDPB_IMPL + xor a ld b,0FFh ;Changed ret diff --git a/msx/bank1/verbose_reset.asm b/msx/bank1/verbose_reset.asm index 0e7b72c..0dcdf5c 100644 --- a/msx/bank1/verbose_reset.asm +++ b/msx/bank1/verbose_reset.asm @@ -240,8 +240,9 @@ PRINT_ERROR: ; Strings ROOKIE_S: - db "Rookie Drive FDD BIOS v1.0",13,10 - db "(c) Konamiman 2018",13,10 + db "Rookie Drive NestorBIOS v2.0",13,10 + db "Prerelease version 2021.02.22",13,10 + db "(c) Konamiman 2018,2021",13,10 db 13,10 db "Initializing device...",13 db 0 From 521be0d040b474b81bab34586897361c8502234d Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Mon, 1 Mar 2021 22:54:46 +0100 Subject: [PATCH 39/65] Added the DSK_GET_DEFAULT routine and a couple auxiliary ones. --- msx/bank1/dsk.asm | 215 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index 9500977..4c0c2e2 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -747,3 +747,218 @@ _DSK_REMOUNT_OK_3: xor a ret + + +; ----------------------------------------------------------------------------- +; DSK_GET_DEFAULT: Get the name of the default file in current directory +; ----------------------------------------------------------------------------- +; Input: HL = Address of 13 byte buffer for file name +; Output: A = 0: Ok +; 1: Other error +; 2: File not found (directory is empty) + +DSK_GET_DEFAULT: + push iy + ld iy,-32 + add iy,sp + ld sp,iy + call _DSK_GET_DEFAULT + ld iy,32 + add iy,sp + ld sp,iy + pop iy + ret + +_DSK_GET_DEFAULT: + + ;* First check if a DEFAULT.DSK file exists + + push hl + call DSK_DEFAULT_EXISTS + pop hl + cp 1 + ret z + + or a + jr nz,_DSK_GET_DEFAULT_NODEF + + ; DEFAULT.DSK exists, copy to destination for now + + push hl + ex de,hl + ld hl,DSK_DEFAULT_S + ld bc,12 + ldir + pop hl + jr _DSK_GET_DEFAULT_2 + + ; DEFAULT.DSK doesn't exist, see if any suitable file exists at all + +_DSK_GET_DEFAULT_NODEF: + push hl + call DSK_GET_FIRST + pop hl + or a + ret nz + + push hl + ex de,hl + push iy + pop hl + call BM_GENERATE_FILENAME + ld (hl),0 + pop hl + + ;* Now we have either DEFAULT.DSK or the name of the first existing file + ; copied to the destination address. See if there's a suitable DEFFILE file + ; and if so extract and use its contents, if not just return. + ; No errors will be returned past this point. + +_DSK_GET_DEFAULT_2: + push hl + push iy + pop de + ld hl,DSK_DEFFILE_S + ld b,12 + call DSK_READ_CONFIG_FILE + pop hl + or a + ld a,0 + ret nz + ld (de),a + ld a,b + or a + ret z + + ; We got a file name from DEFFILE, so copy its contents + ; to the output buffer. + + ex de,hl + push iy + pop hl + ld bc,13 + ldir + + xor a + ret + +DSK_DEFFILE_S: + db "DEFFILE",0 + + +; ----------------------------------------------------------------------------- +; DSK_DEFAULT_EXISTS: Does the DEFAULT.DSK file exist in current directory? +; +; We need to do the search in a weird way because there's no way to initiate +; a file search without specifying +; ----------------------------------------------------------------------------- +; Input: IY = Address of 32 byte buffer for directory entry +; Output: A = 0: Ok +; 1: Other error +; 2: File doesn't exist + +DSK_DEFAULT_EXISTS: + ld a,CH_CMD_SET_FILE_NAME + out (CH_COMMAND_PORT),a + ld hl,DSK_DEFAST_S + call CH_WRITE_STRING + ld a,CH_CMD_FILE_OPEN + out (CH_COMMAND_PORT),a + +_DSK_DEFAULT_EXISTS_LOOP: + call CH_WAIT_INT_AND_GET_RESULT + ld b,a + cp USB_ERR_MISS_FILE + ld a,2 + ret z + ld a,b + cp CH_ST_INT_DISK_READ + ld a,1 + ret nz + + push iy + pop hl + call CH_READ_DATA + ld a,b + cp 32 + ld a,1 + ret nz + + ld a,(iy+10) + cp "K" + jr nz,_DSK_DEFAULT_EXISTS_NEXT + + ld a,(iy+11) + and 11010b ;Directory, hidden or volume? + ld a,2 + ret nz + + xor a + ret + +_DSK_DEFAULT_EXISTS_NEXT: + ld a,CH_CMD_FILE_ENUM_GO + out (CH_COMMAND_PORT),a + jr _DSK_DEFAULT_EXISTS_LOOP + +DSK_DEFAST_S: + db "DEFAULT.DS*",0 +DSK_DEFAULT_S: + db "DEFAULT.DSK",0 + + +; ----------------------------------------------------------------------------- +; DSK_GET_FIRST: Get the first available file in the current directory +; +; Hidden files and files starting with "_" don't count. +; ----------------------------------------------------------------------------- +; Input: IY = Address of 32 byte buffer for directory entry +; Output: A = 0: Ok +; 1: Other error +; 2: File doesn't exist + +DSK_GET_FIRST: + ld a,CH_CMD_SET_FILE_NAME + out (CH_COMMAND_PORT),a + ld a,'*' + out (CH_DATA_PORT),a + xor a + out (CH_DATA_PORT),a + ld a,CH_CMD_FILE_OPEN + out (CH_COMMAND_PORT),a + +_DSK_GET_FIRST_LOOP: + call CH_WAIT_INT_AND_GET_RESULT + ld b,a + cp USB_ERR_MISS_FILE + ld a,2 + ret z + ld a,b + cp CH_ST_INT_DISK_READ + ld a,1 + ret nz + + push iy + pop hl + call CH_READ_DATA + ld a,b + cp 32 + ld a,1 + ret nz + + ld a,(iy) + cp '_' + jr z,_DSK_GET_FIRST_LOOP_NEXT + + ld a,(iy+11) + and 11010b ;Directory, hidden or volume? + jr nz,_DSK_GET_FIRST_LOOP_NEXT + + xor a + ret + +_DSK_GET_FIRST_LOOP_NEXT: + ld a,CH_CMD_FILE_ENUM_GO + out (CH_COMMAND_PORT),a + jr _DSK_GET_FIRST_LOOP + From a713b15fc608b97a51ea852450dfef9097180142 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 2 Mar 2021 17:34:44 +0100 Subject: [PATCH 40/65] SHIFT+ENTER (mount default file for dir) implemented in boot menu --- msx/bank1/boot_menu.asm | 43 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 4839225..0e440d9 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -231,7 +231,7 @@ _BM_START_OVER_OK: ;--- ESC key press handler BM_DO_ESC: - ld de,0106h + ld de,0106h ;SHIFT is pressed? call BM_KEY_CHECK_CORE ld a,1 ret nz @@ -264,9 +264,10 @@ BM_DO_ENTER: ;* It's a file BM_DO_ENTER_FILE: - call BM_CLEAR_INFO_AREA ld hl,BM_MOUNTING_BOOTING_S +BM_DO_ENTER_FILE_2: call BM_PRINT_STATUS + call BM_CLEAR_INFO_AREA call BM_GET_CUR_DIR_ADD call DSK_WRITE_CURDIR_FILE @@ -287,11 +288,17 @@ _BM_DO_ENTER_OPEN_ERR: ld hl,BM_ERROR_OPENING_FILE_S ;Other error or it's a dir _BM_DO_ENTER_PRINT_ERR: call BM_PRINT_STATUS_WAIT_KEY - call BM_PRINT_MAIN_STATUS _BM_DO_ENTER_WAIT_RELEASE: ;In case the "any key" pressed is enter call BM_ENTER_IS_PRESSED jr z,_BM_DO_ENTER_WAIT_RELEASE + + ld hl,BM_SCANNING_DIR_S + call BM_PRINT_STATUS + call BM_GET_CUR_DIR_ADD + ld a,1 + call DSK_CHANGE_DIR_U + call BM_ENUM_FILES jp BM_ENTER_MAIN_LOOP ; _BM_MAIN_LOOP _BM_DO_ENTER_FILE_SUCCESS: @@ -350,9 +357,33 @@ _BM_COPY_DIR_NAME_LOOP: ld (iy+BM_CUR_DIR_LENGTH),a call BM_PRINT_CUR_DIR + + ld de,0106h ;SHIFT is pressed? + call BM_KEY_CHECK_CORE + jr z,_BM_DO_MOUNT_DEFAULT + +_BM_DO_ENTER_DIR_END: call BM_ENUM_FILES jp BM_ENTER_MAIN_LOOP + ;* It's a directory and SHIFT was pressed + +_BM_DO_MOUNT_DEFAULT: + call BM_GET_BUF_ADD + push hl + call DSK_GET_DEFAULT + pop hl + + or a + ld hl,BM_MOUNTING_DEF_S + jp z,BM_DO_ENTER_FILE_2 + cp 2 + jr z,_BM_DO_ENTER_DIR_END + + ld hl,BM_ERR_RETRIEVING_DEFAULT_S + call BM_PRINT_STATUS_WAIT_KEY + jr _BM_DO_ENTER_DIR_END + ;--- Print the string HL in the status area and wait for a key press @@ -1520,6 +1551,12 @@ BM_ENTERING_DIR_S: BM_CHANGING_EXITING_S: db "Changing current dir and exiting...",0 +BM_MOUNTING_DEF_S: + db "Mounting default file for dir...",0 + +BM_ERR_RETRIEVING_DEFAULT_S: + db "Error retrieving default file for dir!",0 + BM_DOTS_BAR_S: db "/.../",0 From 0534ab735740a1059106359fd985fed317000500 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sun, 7 Mar 2021 19:11:47 +0100 Subject: [PATCH 41/65] Implemented the functionality for BOOTDIR and BOOTMODE config files. --- msx/bank0/oemstat.asm | 493 +++++++++++++++---------------- msx/bank1/boot_menu.asm | 7 +- msx/bank1/choice_dskfmt.asm | 2 + msx/bank1/dsk.asm | 223 ++++++++++++++ msx/bank1/dskio_dskchg.asm | 46 ++- msx/bank1/inihrd_inienv.asm | 120 ++++---- msx/bank1/usb.asm | 6 + msx/bank1/verbose_reset.asm | 567 +++++++++++++++++++----------------- 8 files changed, 870 insertions(+), 594 deletions(-) diff --git a/msx/bank0/oemstat.asm b/msx/bank0/oemstat.asm index 0a40fcc..1471e94 100644 --- a/msx/bank0/oemstat.asm +++ b/msx/bank0/oemstat.asm @@ -1,247 +1,248 @@ -; Rookie Drive USB FDD BIOS -; By Konamiman, 2018 -; -; This file contains the CALL statements handler and the -; implementations of the statements themselves. - - -; ----------------------------------------------------------------------------- -; OEMSTATEMENT -; ----------------------------------------------------------------------------- -; Input: HL basicpointer -; Output: F Cx set if statement not recognized -; Cx reset if statement is recognized -; HL basicpointer, updated if recognized -; unchanged if not recognized -; Changed: AF,BC,DE,HL,IX,IY may be affected -; ----------------------------------------------------------------------------- - -OEMSTA: - push hl - ld hl,OEM_COMMANDS - -_OEMSTA_CHECK_COMMAND: - ld a,(hl) - or a - jr z,_OEMSTA_UNKNOWN - ld de,PROCNM -_OEMSTA_CHECK_COMMAND_LOOP: - ld a,(de) - cp (hl) - jr nz,_OEMSTA_SKIP_COMMAND - or a - jr z,_OEMSTA_FOUND - inc hl - inc de - jr _OEMSTA_CHECK_COMMAND_LOOP - -_OEMSTA_SKIP_COMMAND: - ld a,(hl) - inc hl - or a - jr nz,_OEMSTA_SKIP_COMMAND - inc hl ;Skip routine address - inc hl - jr _OEMSTA_CHECK_COMMAND - -_OEMSTA_FOUND: - inc hl - ld a,(hl) - inc hl - ld h,(hl) - ld l,a - jp (hl) - -_OEMSTA_UNKNOWN: - pop hl - scf - ret - -OEM_COMMANDS: - - if USE_ALTERNATIVE_PORTS=1 - db "USBRESET2",0 - dw OEMC_USBRESET - db "USBERROR2",0 - dw OEMC_USBERROR - else - db "USBRESET",0 - dw OEMC_USBRESET - db "USBERROR",0 - dw OEMC_USBERROR - endif - - db "USBMENU",0 - dw OEMC_USBMENU - db 0 - - - ;--- CALL USBRESET - ; Resets USB hardware and prints device info, just like at boot time - -OEMC_USBRESET: - ld ix,VERBOSE_RESET - ld iy,ROM_BANK_1 - call CALL_BANK - jp OEM_END - - - ;--- CALL USBERROR - ; Displays information about the USB or UFI error returned - ; by the last executed UFI command - -OEMC_USBERROR: - ld ix,WK_GET_ERROR - ld iy,ROM_BANK_1 - call CALL_BANK - or a - jr z,_OEMC_USBERROR_ASC - - push af - ld hl,OEM_S_USBERR - call OEM_PRINT - pop af - call PRINT_ERROR_DESCRIPTION - jr OEM_END - -_OEMC_USBERROR_HEX: - call OEM_PRINTHEX - jr OEM_END - -_OEMC_USBERROR_ASC: - ld a,d - or a - ld hl,OEM_S_NOERRDATA - push af - call z,OEM_PRINT - pop af - jr z,OEM_END - - ld hl,OEM_S_ASC - call OEM_PRINT - ld a,d - call OEM_PRINTHEX - ld hl,OEM_S_H_CRLF - call OEM_PRINT - ld hl,OEM_S_ASCQ - call OEM_PRINT - ld a,e - call OEM_PRINTHEX - ld hl,OEM_S_H_CRLF - -OEM_PRINT_AND_END: - call OEM_PRINT - -OEM_END: - pop hl - or a - ret - -OEM_S_USBERR: - db "USB error: ",0 -OEM_S_H_CRLF: - db "h",13,10,0 -OEM_S_ASC: - db "ASC: ",0 -OEM_S_ASCQ: - db "ASCQ: ",0 -OEM_S_NOERRDATA: - db "No error data recorded",0 - - - ;--- CALL USBMENU - ; Open the USB menu if there's a storage device inserted - -OEMC_USBMENU: - ld ix,DO_BOOT_MENU - ld iy,ROM_BANK_1 - call CALL_BANK - cp 3 - ld hl,OEM_S_NO_STDEV - jp z,OEM_PRINT_AND_END - cp 2 - ld hl,OEM_S_NO_MEM - jp z,OEM_PRINT_AND_END - jp OEM_END - -OEM_S_NO_STDEV: - db "No USB storage device present",7,0 -OEM_S_NO_MEM: - db "Not enough memory",7,0 - - -; ----------------------------------------------------------------------------- -; Print the description of an USB error code -; -; Input: A = USB error code - -PRINT_ERROR_DESCRIPTION: - cp USB_ERR_MAX+1 - jp nc,OEM_PRINTHEX - - dec a - ld c,a - sla c - ld b,0 - ld hl,USBERR_S_TABLE - add hl,bc - ld a,(hl) - inc hl - ld h,(hl) - ld l,a - jp OEM_PRINT - -USBERR_S_TABLE: - dw USBERR_S_1 - dw USBERR_S_2 - dw USBERR_S_3 - dw USBERR_S_4 - dw USBERR_S_5 - dw USBERR_S_6 - dw USBERR_S_7 - -USBERR_S_1: db "NAK",0 -USBERR_S_2: db "Stall",0 -USBERR_S_3: db "Timeout",0 -USBERR_S_4: db "Data error",0 -USBERR_S_5: db "Device was disconnected",0 -USBERR_S_6: db "Panic button pressed",0 -USBERR_S_7: db "Unexpected status received from USB host hardware",0 - - -; ----------------------------------------------------------------------------- -; Print a byte in hexadecimal format -; -; Input: A = byte to print - -OEM_PRINTHEX: - push af - call _OEM_PRINTHEX_1 - pop af - jr _OEM_PRINTHEX_2 - -_OEM_PRINTHEX_1: rra - rra - rra - rra -_OEM_PRINTHEX_2: or 0F0h - daa - add a,0A0h - adc a,40h - - call CHPUT - ret - - -; ----------------------------------------------------------------------------- -; Print a zero-terminated string -; -; Input: HL = Pointer to the string - -OEM_PRINT: - ld a,(hl) - or a - ret z - call CHPUT - inc hl +; Rookie Drive USB FDD BIOS +; By Konamiman, 2018 +; +; This file contains the CALL statements handler and the +; implementations of the statements themselves. + + +; ----------------------------------------------------------------------------- +; OEMSTATEMENT +; ----------------------------------------------------------------------------- +; Input: HL basicpointer +; Output: F Cx set if statement not recognized +; Cx reset if statement is recognized +; HL basicpointer, updated if recognized +; unchanged if not recognized +; Changed: AF,BC,DE,HL,IX,IY may be affected +; ----------------------------------------------------------------------------- + +OEMSTA: + push hl + ld hl,OEM_COMMANDS + +_OEMSTA_CHECK_COMMAND: + ld a,(hl) + or a + jr z,_OEMSTA_UNKNOWN + ld de,PROCNM +_OEMSTA_CHECK_COMMAND_LOOP: + ld a,(de) + cp (hl) + jr nz,_OEMSTA_SKIP_COMMAND + or a + jr z,_OEMSTA_FOUND + inc hl + inc de + jr _OEMSTA_CHECK_COMMAND_LOOP + +_OEMSTA_SKIP_COMMAND: + ld a,(hl) + inc hl + or a + jr nz,_OEMSTA_SKIP_COMMAND + inc hl ;Skip routine address + inc hl + jr _OEMSTA_CHECK_COMMAND + +_OEMSTA_FOUND: + inc hl + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + jp (hl) + +_OEMSTA_UNKNOWN: + pop hl + scf + ret + +OEM_COMMANDS: + + if USE_ALTERNATIVE_PORTS=1 + db "USBRESET2",0 + dw OEMC_USBRESET + db "USBERROR2",0 + dw OEMC_USBERROR + else + db "USBRESET",0 + dw OEMC_USBRESET + db "USBERROR",0 + dw OEMC_USBERROR + endif + + db "USBMENU",0 + dw OEMC_USBMENU + db 0 + + + ;--- CALL USBRESET + ; Resets USB hardware and prints device info, just like at boot time + +OEMC_USBRESET: + ld a,1 + ld ix,VERBOSE_RESET + ld iy,ROM_BANK_1 + call CALL_BANK + jp OEM_END + + + ;--- CALL USBERROR + ; Displays information about the USB or UFI error returned + ; by the last executed UFI command + +OEMC_USBERROR: + ld ix,WK_GET_ERROR + ld iy,ROM_BANK_1 + call CALL_BANK + or a + jr z,_OEMC_USBERROR_ASC + + push af + ld hl,OEM_S_USBERR + call OEM_PRINT + pop af + call PRINT_ERROR_DESCRIPTION + jr OEM_END + +_OEMC_USBERROR_HEX: + call OEM_PRINTHEX + jr OEM_END + +_OEMC_USBERROR_ASC: + ld a,d + or a + ld hl,OEM_S_NOERRDATA + push af + call z,OEM_PRINT + pop af + jr z,OEM_END + + ld hl,OEM_S_ASC + call OEM_PRINT + ld a,d + call OEM_PRINTHEX + ld hl,OEM_S_H_CRLF + call OEM_PRINT + ld hl,OEM_S_ASCQ + call OEM_PRINT + ld a,e + call OEM_PRINTHEX + ld hl,OEM_S_H_CRLF + +OEM_PRINT_AND_END: + call OEM_PRINT + +OEM_END: + pop hl + or a + ret + +OEM_S_USBERR: + db "USB error: ",0 +OEM_S_H_CRLF: + db "h",13,10,0 +OEM_S_ASC: + db "ASC: ",0 +OEM_S_ASCQ: + db "ASCQ: ",0 +OEM_S_NOERRDATA: + db "No error data recorded",0 + + + ;--- CALL USBMENU + ; Open the USB menu if there's a storage device inserted + +OEMC_USBMENU: + ld ix,DO_BOOT_MENU + ld iy,ROM_BANK_1 + call CALL_BANK + cp 3 + ld hl,OEM_S_NO_STDEV + jp z,OEM_PRINT_AND_END + cp 2 + ld hl,OEM_S_NO_MEM + jp z,OEM_PRINT_AND_END + jp OEM_END + +OEM_S_NO_STDEV: + db "No USB storage device present",7,0 +OEM_S_NO_MEM: + db "Not enough memory",7,0 + + +; ----------------------------------------------------------------------------- +; Print the description of an USB error code +; +; Input: A = USB error code + +PRINT_ERROR_DESCRIPTION: + cp USB_ERR_MAX+1 + jp nc,OEM_PRINTHEX + + dec a + ld c,a + sla c + ld b,0 + ld hl,USBERR_S_TABLE + add hl,bc + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + jp OEM_PRINT + +USBERR_S_TABLE: + dw USBERR_S_1 + dw USBERR_S_2 + dw USBERR_S_3 + dw USBERR_S_4 + dw USBERR_S_5 + dw USBERR_S_6 + dw USBERR_S_7 + +USBERR_S_1: db "NAK",0 +USBERR_S_2: db "Stall",0 +USBERR_S_3: db "Timeout",0 +USBERR_S_4: db "Data error",0 +USBERR_S_5: db "Device was disconnected",0 +USBERR_S_6: db "Panic button pressed",0 +USBERR_S_7: db "Unexpected status received from USB host hardware",0 + + +; ----------------------------------------------------------------------------- +; Print a byte in hexadecimal format +; +; Input: A = byte to print + +OEM_PRINTHEX: + push af + call _OEM_PRINTHEX_1 + pop af + jr _OEM_PRINTHEX_2 + +_OEM_PRINTHEX_1: rra + rra + rra + rra +_OEM_PRINTHEX_2: or 0F0h + daa + add a,0A0h + adc a,40h + + call CHPUT + ret + + +; ----------------------------------------------------------------------------- +; Print a zero-terminated string +; +; Input: HL = Pointer to the string + +OEM_PRINT: + ld a,(hl) + or a + ret z + call CHPUT + inc hl jr OEM_PRINT \ No newline at end of file diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 0e440d9..0518a09 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -7,6 +7,8 @@ BM_MAX_DIR_NAME_LENGTH: equ 64 +;TODO: Remove input parameter in A + ; ----------------------------------------------------------------------------- ; Boot menu entry point ; @@ -217,6 +219,8 @@ BM_START_OVER: _BM_START_OVER_OK: call WK_INIT_FOR_STORAGE_DEV + ld a,1 + call DSK_DO_BOOT_PROC jp DO_BOOT_MENU_MAIN @@ -1456,7 +1460,8 @@ BM_OPEN_INITIAL_DIR: jr nz,_BM_OPEN_INITIAL_CURDIR _BM_OPEN_INITIAL_MAIN: - call DSK_OPEN_MAIN_DIR + call DSK_CHANGE_BOOTDIR + or a jr nz,_BM_MAIN_GETDIR_ERR ld hl,DSK_MAIN_DIR_S jr c,_BM_OPEN_INITIAL_MAIN_2 diff --git a/msx/bank1/choice_dskfmt.asm b/msx/bank1/choice_dskfmt.asm index b0a73fc..c08faf4 100644 --- a/msx/bank1/choice_dskfmt.asm +++ b/msx/bank1/choice_dskfmt.asm @@ -27,6 +27,7 @@ ; ----------------------------------------------------------------------------- CHOICE_IMPL: + ;TODO: Disable for storage devices ld hl,CHOICE_S ret @@ -45,6 +46,7 @@ CHOICE_IMPL: ; ----------------------------------------------------------------------------- DSKFMT_IMPL: + ;TODO: Disable for storage devices ld c,a ld a,d call CHECK_SAME_DRIVE diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index 4c0c2e2..27a2e00 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -67,6 +67,7 @@ DSK_ZERO_S: ; DE = Pointer after last byte read DSK_READ_CONFIG_FILE: + ;TODO: Allow CR or LF as file terminator push hl push de push bc @@ -962,3 +963,225 @@ _DSK_GET_FIRST_LOOP_NEXT: out (CH_COMMAND_PORT),a jr _DSK_GET_FIRST_LOOP + +; ----------------------------------------------------------------------------- +; DSK_GET_BOOTDIR: Get the boot directory +; +; Hidden files and files starting with "_" don't count. +; ----------------------------------------------------------------------------- +; Input: HL = Address of 64 byte buffer for the directory +; Output: A = 0: Ok +; 1: Other error +; 2: File doesn't exist + +DSK_GET_BOOTDIR: + ld (hl),0 + ex de,hl + ld hl,DSK_BOOTDIR_S + ld b,64 + call DSK_READ_MAIN_CONFIG_FILE + or a + ret nz + ld (de),a + ret + +DSK_BOOTDIR_S: + db "BOOTDIR",0 + + +; ----------------------------------------------------------------------------- +; DSK_CHANGE_BOOTDIR: Change to the boot directory or the main directory +; ----------------------------------------------------------------------------- +; Output: A = 0: Ok +; 1: Error + +DSK_CHANGE_BOOTDIR: + push iy + ld iy,-64 + add iy,sp + ld sp,iy + call _DSK_CHANGE_BOOTDIR + ld iy,64 + add iy,sp + ld sp,iy + pop iy + ret + +_DSK_CHANGE_BOOTDIR: + push iy + pop hl + call DSK_GET_BOOTDIR + or a + jp nz,_DSK_CHANGE_BOOTDIR_ERR + + push iy + pop hl + ld a,1 + call DSK_CHANGE_DIR_U + or a + ret z + + ; BOOTDIR doesn't exist or can't change to the dir it points to, + ; so fallback to setting the main dir + +_DSK_CHANGE_BOOTDIR_ERR: + ld hl,DSK_MAIN_DIR_S + ld a,1 + call DSK_CHANGE_DIR_U + or a + ret z + + ld hl,DSK_ROOT_DIR_S + jp DSK_CHANGE_DIR_U + + +; ----------------------------------------------------------------------------- +; DSK_GET_BOOTMODE: Get current boot mode +; ----------------------------------------------------------------------------- +; Output: A = Boot mode (1 to 4) + +DSK_GET_BOOTMODE: + push iy + ld iy,-1 + add iy,sp + ld sp,iy + call _DSK_GET_BOOTMODE + ld iy,1 + add iy,sp + ld sp,iy + pop iy + ret + +_DSK_GET_BOOTMODE: + ld hl,DSK_BOOTMODE_S + push iy + pop de + ld b,1 + call DSK_READ_MAIN_CONFIG_FILE + or a + ld a,1 + ret nz + + ld a,b + or a + ld a,1 + ret z + + ;Return value read minus "0" if it's "1" to "4", return 1 otherwise + + ld a,(iy) + sub "0" + ld b,a + or a + ld a,1 + ret z + ld a,b + cp 5 + ret c + ld a,1 + ret + +DSK_BOOTMODE_S: + db "BOOTMODE",0 + + +; ----------------------------------------------------------------------------- +; DSK_DO_BOOT_PROC: Do the boot procedure +; ----------------------------------------------------------------------------- +; Output: A = 0: Do the computer boot procedure +; 1: Do the device change boot procedure + +DSK_DO_BOOT_PROC: + push iy + ld iy,-13 + add iy,sp + ld sp,iy + call _DSK_DO_BOOT_PROC + ld iy,13 + add iy,sp + ld sp,iy + pop iy + ret + +_DSK_DO_BOOT_PROC: + ld (iy),a + + call WK_GET_STORAGE_DEV_FLAGS ;No disk mounted for now + and 0FEh + call WK_SET_STORAGE_DEV_FLAGS + + call DSK_GET_BOOTMODE + + dec a + jr z,_DSK_DO_BOOT_1 + dec a + jr z,_DSK_DO_BOOT_2 + dec a + jr z,_DSK_DO_BOOT_3 + jr _DSK_DO_BOOT_4 + + + ;* Boot mode 1: + ; - Set boot dir + ; - If doing computer boot, show boot menu + +_DSK_DO_BOOT_1: + call DSK_CHANGE_BOOTDIR + or a + ret nz + + ld a,(iy) + or a + ret nz + + ld a,1 + jp DO_BOOT_MENU + + + ;* Boot mode 2: + ; - Set boot dir and return + +_DSK_DO_BOOT_2: + jp DSK_CHANGE_BOOTDIR + + + ;* Boot mode 3: + ; - Set boot dir + ; - Mount default file + +_DSK_DO_BOOT_3: + call DSK_CHANGE_BOOTDIR + or a + ret nz + + push iy + pop hl + inc hl + inc hl + push hl + call DSK_GET_DEFAULT + pop hl + or a + ret nz + + ;We need to set the dir again after DSK_GET_DEFAULT + ;since it will have read a config file. + push hl + call DSK_CHANGE_BOOTDIR + pop hl + or a + ret nz + + xor a + jp DSK_MOUNT + + + ; * Boot mode 4: + ; - Remount per CURDIR and CURFILE + ; - On error, fallback to mode 3 + +_DSK_DO_BOOT_4: + call DSK_REMOUNT + or a + ret z + jr _DSK_DO_BOOT_3 diff --git a/msx/bank1/dskio_dskchg.asm b/msx/bank1/dskio_dskchg.asm index 252e2bb..a7f843b 100644 --- a/msx/bank1/dskio_dskchg.asm +++ b/msx/bank1/dskio_dskchg.asm @@ -57,6 +57,16 @@ _DSKIO_ERR_PARAM: ret _DSKIO_OK_UNIT: + push hl + push de + push bc + call USB_CHECK_DEV_CHANGE + pop bc + pop de + pop hl + ld a,12 + ret c ;No device is connected + call WK_GET_STORAGE_DEV_FLAGS jp nz,_DSKIO_IMPL_STDEV @@ -72,16 +82,6 @@ _DSKIO_OK_UNIT: or a ret z ;Nothing to read - push hl - push de - push bc - call USB_CHECK_DEV_CHANGE - pop bc - pop de - pop hl - ld a,12 - ret c ;No device is connected - push hl push de push bc @@ -355,6 +355,11 @@ _DSKIO_IMPL_STDEV: or a jr z,_DSKIO_IMPL_STDEV_SEEKOK + call WK_GET_STORAGE_DEV_FLAGS + and 81h + cp 80h + jp z,_DSKIO_IMPL_POPAF_RET_ERR ;Storage device but no disk mounted + pop hl ;Discard input AF dec a ld a,8 ;Record not found @@ -503,6 +508,13 @@ _DSKIO_IMPL_STDEV_XFER_ERR: scf ret +_DSKIO_IMPL_POPAF_RET_ERR: + pop af + ld b,0 + ld a,2 + scf + ret + ;-- Check if transfer can be done directly or if we need to use XFER ; (XFER will be needed if page 1 is involved in the transfer). @@ -562,11 +574,6 @@ CHECK_XFER_IS_NEEDED: DSKCHG_IMPL: call CHECK_SAME_DRIVE - push af - call WK_GET_STORAGE_DEV_FLAGS - jp nz,_DSKCHG_IMPL_STDEV - pop af - cp 2 ld a,12 ccf @@ -578,6 +585,11 @@ DSKCHG_IMPL: ld a,12 ret c ;No device is connected + push af + call WK_GET_STORAGE_DEV_FLAGS + jp nz,_DSKCHG_IMPL_STDEV + pop af + push hl call TEST_DISK pop hl @@ -594,6 +606,10 @@ DSKCHG_IMPL: ret _DSKCHG_IMPL_STDEV: + and 81h + cp 80h + jp z,_DSKIO_IMPL_POPAF_RET_ERR ;Storage device but no disk mounted + pop af call WK_GET_STORAGE_DEV_FLAGS diff --git a/msx/bank1/inihrd_inienv.asm b/msx/bank1/inihrd_inienv.asm index f847f64..095f013 100644 --- a/msx/bank1/inihrd_inienv.asm +++ b/msx/bank1/inihrd_inienv.asm @@ -1,58 +1,62 @@ -; Rookie Drive USB FDD BIOS -; By Konamiman, 2018 -; -; This file contains the implementation of the INIHRD and INIENV -; driver routines. - - -; We do the hardware reset in INIENV and not in INIHRD -; because we need to setup the work area during reset, but work area -; is zeroed by kernel between INIHRD and INIENV. - - -; ----------------------------------------------------------------------------- -; INIHRD -; ----------------------------------------------------------------------------- -; Input: None -; Output: None -; Changed: AF,BC,DE,HL,IX,IY may be affected -; ----------------------------------------------------------------------------- - -INIHRD_IMPL: - call INITXT - ld hl,ROOKIE_S - jp PRINT - - -; ----------------------------------------------------------------------------- -; INIENV -; ----------------------------------------------------------------------------- -; Input: None -; Output: None -; Changed: AF,BC,DE,HL,IX,IY may be affected -; -; Remark: - -; ----------------------------------------------------------------------------- - -INIENV_IMPL: - - if WAIT_KEY_ON_INIT = 1 - ld hl,INIHRD_NEXT - push hl - endif - - call VERBOSE_RESET - ld b,30 -DELAY_AFTER_PRINT: - halt - djnz DELAY_AFTER_PRINT - - call HWF_MOUNT_DISK - ret c - - call WK_INIT_FOR_STORAGE_DEV - xor a - call WK_SET_LAST_REL_DRIVE - - call DO_BOOT_MENU - ret +; Rookie Drive USB FDD BIOS +; By Konamiman, 2018 +; +; This file contains the implementation of the INIHRD and INIENV +; driver routines. + + +; We do the hardware reset in INIENV and not in INIHRD +; because we need to setup the work area during reset, but work area +; is zeroed by kernel between INIHRD and INIENV. + + +; ----------------------------------------------------------------------------- +; INIHRD +; ----------------------------------------------------------------------------- +; Input: None +; Output: None +; Changed: AF,BC,DE,HL,IX,IY may be affected +; ----------------------------------------------------------------------------- + +INIHRD_IMPL: + call INITXT + ld hl,ROOKIE_S + jp PRINT + + +; ----------------------------------------------------------------------------- +; INIENV +; ----------------------------------------------------------------------------- +; Input: None +; Output: None +; Changed: AF,BC,DE,HL,IX,IY may be affected +; +; Remark: - +; ----------------------------------------------------------------------------- + +INIENV_IMPL: + + if WAIT_KEY_ON_INIT = 1 + ld hl,INIHRD_NEXT + push hl + endif + + xor a + call WK_SET_LAST_REL_DRIVE + + xor a + call VERBOSE_RESET + ld b,30 +DELAY_AFTER_PRINT: + halt + djnz DELAY_AFTER_PRINT + + ret + + + call WK_INIT_FOR_STORAGE_DEV + xor a + call WK_SET_LAST_REL_DRIVE + + call DO_BOOT_MENU + ret diff --git a/msx/bank1/usb.asm b/msx/bank1/usb.asm index 34fa14c..838e151 100644 --- a/msx/bank1/usb.asm +++ b/msx/bank1/usb.asm @@ -52,9 +52,15 @@ _USB_CHECK_DEV_CHANGE_CHANGED: ;* Device present but it's not a FDD: check if it's a storage device + call WK_GET_STORAGE_DEV_FLAGS ;No disk mounted for now + and 0FEh + call WK_SET_STORAGE_DEV_FLAGS + call HWF_MOUNT_DISK jr c,_USB_CHECK_DEV_CHANGE_NO_DEV call WK_INIT_FOR_STORAGE_DEV + ld a,1 + call DSK_DO_BOOT_PROC or a ret diff --git a/msx/bank1/verbose_reset.asm b/msx/bank1/verbose_reset.asm index 0dcdf5c..eb13919 100644 --- a/msx/bank1/verbose_reset.asm +++ b/msx/bank1/verbose_reset.asm @@ -1,274 +1,293 @@ -; Rookie Drive USB FDD BIOS -; By Konamiman, 2018 -; -; This routine resets the USB hardware, resets and initializes the device, -; and prints the device name or the appropriate error message. -; It is executed at boot time and by CALL USBRESET. - - -VERBOSE_RESET: - call HW_TEST - ld hl,NOHARD_S - jp c,PRINT - - ld hl,0C000h - call HWF_MOUNT_DISK - jr c,_HW_RESET_NO_STOR - - ld hl,STOR_FOUND_S - call PRINT - ld hl,0C000h - ld b,0 - ;Print the device name, collapsing multiple spaces to a single one -_HW_RESET_PRINT: - ld a,(hl) - inc hl - or a - jr z,_HW_RESET_PRINT_END - cp ' ' - jr nz,_HW_RESET_PRINT_GO - cp b - jr z,_HW_RESET_PRINT -_HW_RESET_PRINT_GO: - ld b,a - call CHPUT - jr _HW_RESET_PRINT -_HW_RESET_PRINT_END: - call WK_INIT_FOR_STORAGE_DEV - ret - -_HW_RESET_NO_STOR: - ld b,5 -_HW_RESET_TRY: - push bc - call HW_RESET - pop bc - jr nc,_HW_RESET_TRY_OK - djnz _HW_RESET_TRY - ld hl,RESERR_S - jp PRINT -_HW_RESET_TRY_OK: - inc a - ld hl,NODEV_S - jp z,PRINT - - ;Experiments with hubs, please ignore - if 0 - - ld a,2 - call HW_SET_ADDRESS - ld a,2 - ld b,1 - call HW_SET_CONFIG - ld hl,CMD_PORT_POWER - ld de,0 - ld a,2 - ld b,64 - call HW_CONTROL_TRANSFER - ld hl,CMD_PORT_RESET - ld de,0 - ld a,2 - ld b,64 - call HW_CONTROL_TRANSFER - jr HUBDONE - -CMD_PORT_POWER: - db 00100011b, 3, 8, 0, 1, 0, 0, 0 -CMD_PORT_RESET: - db 00100011b, 3, 4, 0, 1, 0, 0, 0 -HUBDONE: - - endif - - ld b,5 -_TRY_USB_INIT_DEV: - push bc - call USB_INIT_DEV - ld h,b - pop bc - cp 2 - jr c,_TRY_USB_INIT_DEV_OK - djnz _TRY_USB_INIT_DEV - ld a,h - ld hl,DEVERR_S - jp PRINT_ERROR -_TRY_USB_INIT_DEV_OK: - - or a - ld hl,NO_CBI_DEV_S - jp nz,PRINT - - ld hl,YES_CBI_DEV_S - call PRINT - jp PRINT_DEVICE_INFO - - if WAIT_KEY_ON_INIT = 1 -INIHRD_NEXT: - jp CHGET - endif - -PRINT: - ld a,(hl) - or a - ret z - call CHPUT - inc hl - jr PRINT - - -; ----------------------------------------------------------------------------- -; Print the device name from INQUIRY command - -PRINT_DEVICE_INFO_STACK_SPACE: equ 36 - -PRINT_DEVICE_INFO: - ld hl,-PRINT_DEVICE_INFO_STACK_SPACE - add hl,sp - ld sp,hl - - ld b,3 ;Some drives stall on first command after reset so try a few times -_TRY_INQUIRY: - push bc - push hl - pop de - ld hl,INIQUIRY_CMD - ld bc,36 - ld a,1 - or a - push de - call USB_EXECUTE_CBI_WITH_RETRY - pop hl - pop bc - or a - jr z,_INQUIRY_OK - djnz _TRY_INQUIRY - jr _PRINT_DEVICE_INFO_ERR -_INQUIRY_OK: - - ld bc,8 - add hl,bc - ld b,8 - call PRINT_SPACE_PADDED_STRING - ld a,' ' - call CHPUT - - ld bc,8 ;base + 16 - add hl,bc - ld b,16 - call PRINT_SPACE_PADDED_STRING - ld a,' ' - call CHPUT - - ld bc,16 ;base + 32 - add hl,bc - ld b,4 - call PRINT_SPACE_PADDED_STRING - - ld hl,CRLF_S - call PRINT - - jr _PRINT_DEVICE_INFO_END - -_PRINT_DEVICE_INFO_ERR: - ld hl,ERR_INQUIRY_S - call PRINT_ERROR -_PRINT_DEVICE_INFO_END: - ld hl,PRINT_DEVICE_INFO_STACK_SPACE - add hl,sp - ld sp,hl - ret - -INIQUIRY_CMD: - db 12h, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 - - - ; Print a fixed-length space-padded string, skipping the padding - ; Input: HL = String address - ; B = String length - -PRINT_SPACE_PADDED_STRING: - push hl - call _PRINT_SPACE_PADDED_STRING - pop hl - ret - -_PRINT_SPACE_PADDED_STRING: - ld e,b - ld d,0 - push hl - add hl,de ;HL points past the last char of the string -_PSPS_Z_LOOP: - dec hl - ld a,(hl) - cp ' ' - jr nz,_PSPS_DO - djnz _PSPS_Z_LOOP - pop hl - ret ;All the string is spaces, do nothing - -_PSPS_DO: - pop hl -_PSPS_P_LOOP: - ld a,(hl) - call CHPUT - inc hl - djnz _PSPS_P_LOOP - - ret - - -; ----------------------------------------------------------------------------- -; Print an error message and the description of an USB error code -; -; Input: HL = Error message -; A = Error code - -PRINT_ERROR: - push af - call PRINT - pop af - - ld ix,PRINT_ERROR_DESCRIPTION - ld iy,ROM_BANK_0 - call CALL_BANK - - ld hl,CRLF_S - jp PRINT - - -; ----------------------------------------------------------------------------- -; Strings - -ROOKIE_S: - db "Rookie Drive NestorBIOS v2.0",13,10 - db "Prerelease version 2021.02.22",13,10 - db "(c) Konamiman 2018,2021",13,10 - db 13,10 - db "Initializing device...",13 - db 0 - -NOHARD_S: - db "USB host hardware not found!" -CRLF_S: - db 13,10,0 - -NODEV_S: - db "No USB device found",27,"K",13,10,0 - -NO_CBI_DEV_S: - db "USB device found, but it's not a FDD unit",13,10,0 - -YES_CBI_DEV_S: - db "USB FDD found: ",27,"K",0 - -RESERR_S: - db "ERROR initializing USB host hardware or resetting USB device",13,10,0 - -DEVERR_S: - db "ERROR querying or initializing USB device: ",0 - -ERR_INQUIRY_S: - db "ERROR querying the device name: ",0 - -STOR_FOUND_S: - db "USB storage device found: ",0 +; Rookie Drive USB FDD BIOS +; By Konamiman, 2018 +; +; This routine resets the USB hardware, resets and initializes the device, +; and prints the device name or the appropriate error message. +; It is executed at boot time and by CALL USBRESET. +; +; Inpuy: A = 0: Called from computer boot +; 1: Called from CALL USBRESET + +VERBOSE_RESET: + push iy + ld iy,-1 + add iy,sp + ld sp,iy + call _VERBOSE_RESET + ld iy,1 + add iy,sp + ld sp,iy + pop iy + ret + +_VERBOSE_RESET: + ld (iy),a + + call HW_TEST + ld hl,NOHARD_S + jp c,PRINT + + ;TODO: Use stack instead + ld hl,0C000h + call HWF_MOUNT_DISK + jr c,_HW_RESET_NO_STOR + + ld hl,STOR_FOUND_S + call PRINT + ld hl,0C000h + ld b,0 + ;Print the device name, collapsing multiple spaces to a single one +_HW_RESET_PRINT: + ld a,(hl) + inc hl + or a + jr z,_HW_RESET_PRINT_END + cp ' ' + jr nz,_HW_RESET_PRINT_GO + cp b + jr z,_HW_RESET_PRINT +_HW_RESET_PRINT_GO: + ld b,a + call CHPUT + jr _HW_RESET_PRINT +_HW_RESET_PRINT_END: + call WK_INIT_FOR_STORAGE_DEV + ld a,(iy) + call DSK_DO_BOOT_PROC + ret + +_HW_RESET_NO_STOR: + ld b,5 +_HW_RESET_TRY: + push bc + call HW_RESET + pop bc + jr nc,_HW_RESET_TRY_OK + djnz _HW_RESET_TRY + ld hl,RESERR_S + jp PRINT +_HW_RESET_TRY_OK: + inc a + ld hl,NODEV_S + jp z,PRINT + + ;Experiments with hubs, please ignore + if 0 + + ld a,2 + call HW_SET_ADDRESS + ld a,2 + ld b,1 + call HW_SET_CONFIG + ld hl,CMD_PORT_POWER + ld de,0 + ld a,2 + ld b,64 + call HW_CONTROL_TRANSFER + ld hl,CMD_PORT_RESET + ld de,0 + ld a,2 + ld b,64 + call HW_CONTROL_TRANSFER + jr HUBDONE + +CMD_PORT_POWER: + db 00100011b, 3, 8, 0, 1, 0, 0, 0 +CMD_PORT_RESET: + db 00100011b, 3, 4, 0, 1, 0, 0, 0 +HUBDONE: + + endif + + ld b,5 +_TRY_USB_INIT_DEV: + push bc + call USB_INIT_DEV + ld h,b + pop bc + cp 2 + jr c,_TRY_USB_INIT_DEV_OK + djnz _TRY_USB_INIT_DEV + ld a,h + ld hl,DEVERR_S + jp PRINT_ERROR +_TRY_USB_INIT_DEV_OK: + + or a + ld hl,NO_CBI_DEV_S + jp nz,PRINT + + ld hl,YES_CBI_DEV_S + call PRINT + jp PRINT_DEVICE_INFO + + if WAIT_KEY_ON_INIT = 1 +INIHRD_NEXT: + jp CHGET + endif + +PRINT: + ld a,(hl) + or a + ret z + call CHPUT + inc hl + jr PRINT + + +; ----------------------------------------------------------------------------- +; Print the device name from INQUIRY command + +PRINT_DEVICE_INFO_STACK_SPACE: equ 36 + +PRINT_DEVICE_INFO: + ld hl,-PRINT_DEVICE_INFO_STACK_SPACE + add hl,sp + ld sp,hl + + ld b,3 ;Some drives stall on first command after reset so try a few times +_TRY_INQUIRY: + push bc + push hl + pop de + ld hl,INIQUIRY_CMD + ld bc,36 + ld a,1 + or a + push de + call USB_EXECUTE_CBI_WITH_RETRY + pop hl + pop bc + or a + jr z,_INQUIRY_OK + djnz _TRY_INQUIRY + jr _PRINT_DEVICE_INFO_ERR +_INQUIRY_OK: + + ld bc,8 + add hl,bc + ld b,8 + call PRINT_SPACE_PADDED_STRING + ld a,' ' + call CHPUT + + ld bc,8 ;base + 16 + add hl,bc + ld b,16 + call PRINT_SPACE_PADDED_STRING + ld a,' ' + call CHPUT + + ld bc,16 ;base + 32 + add hl,bc + ld b,4 + call PRINT_SPACE_PADDED_STRING + + ld hl,CRLF_S + call PRINT + + jr _PRINT_DEVICE_INFO_END + +_PRINT_DEVICE_INFO_ERR: + ld hl,ERR_INQUIRY_S + call PRINT_ERROR +_PRINT_DEVICE_INFO_END: + ld hl,PRINT_DEVICE_INFO_STACK_SPACE + add hl,sp + ld sp,hl + ret + +INIQUIRY_CMD: + db 12h, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 + + + ; Print a fixed-length space-padded string, skipping the padding + ; Input: HL = String address + ; B = String length + +PRINT_SPACE_PADDED_STRING: + push hl + call _PRINT_SPACE_PADDED_STRING + pop hl + ret + +_PRINT_SPACE_PADDED_STRING: + ld e,b + ld d,0 + push hl + add hl,de ;HL points past the last char of the string +_PSPS_Z_LOOP: + dec hl + ld a,(hl) + cp ' ' + jr nz,_PSPS_DO + djnz _PSPS_Z_LOOP + pop hl + ret ;All the string is spaces, do nothing + +_PSPS_DO: + pop hl +_PSPS_P_LOOP: + ld a,(hl) + call CHPUT + inc hl + djnz _PSPS_P_LOOP + + ret + + +; ----------------------------------------------------------------------------- +; Print an error message and the description of an USB error code +; +; Input: HL = Error message +; A = Error code + +PRINT_ERROR: + push af + call PRINT + pop af + + ld ix,PRINT_ERROR_DESCRIPTION + ld iy,ROM_BANK_0 + call CALL_BANK + + ld hl,CRLF_S + jp PRINT + + +; ----------------------------------------------------------------------------- +; Strings + +ROOKIE_S: + db "Rookie Drive NestorBIOS v2.0",13,10 + db "Prerelease version 2021.02.22",13,10 + db "(c) Konamiman 2018,2021",13,10 + db 13,10 + db "Initializing device...",13 + db 0 + +NOHARD_S: + db "USB host hardware not found!" +CRLF_S: + db 13,10,0 + +NODEV_S: + db "No USB device found",27,"K",13,10,0 + +NO_CBI_DEV_S: + db "USB device found, but it's not a FDD unit",13,10,0 + +YES_CBI_DEV_S: + db "USB FDD found: ",27,"K",0 + +RESERR_S: + db "ERROR initializing USB host hardware or resetting USB device",13,10,0 + +DEVERR_S: + db "ERROR querying or initializing USB device: ",0 + +ERR_INQUIRY_S: + db "ERROR querying the device name: ",0 + +STOR_FOUND_S: + db "USB storage device found: ",0 From fd41b0828b1e57a587b57d80ce2adae38dfee3a2 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 11 Mar 2021 12:54:36 +0100 Subject: [PATCH 42/65] Implemented the config submenu in the boot menu. --- msx/bank1/boot_menu.asm | 277 ++++++++++++++++++++++++++++++++++-- msx/bank1/dsk.asm | 68 +++++++++ msx/bank1/inihrd_inienv.asm | 2 + 3 files changed, 332 insertions(+), 15 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 0518a09..c38505c 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -180,6 +180,9 @@ _BM_MAIN_LOOP: call BM_F1_IS_PRESSED jp z,BM_DO_HELP + call BM_F2_IS_PRESSED + jp z,BM_DO_CONFIG + call BM_CURSOR_IS_PRESSED or a jr z,_BM_MAIN_LOOP @@ -394,8 +397,11 @@ _BM_DO_MOUNT_DEFAULT: BM_PRINT_STATUS_WAIT_KEY: call BM_PRINT_STATUS call KILBUF - call CHGET ;TODO: This displays cursor, somehow hide - jp KILBUF + call CHGET + push af + call KILBUF + pop af + ret ;--- BS key press handler, go to parent directory @@ -502,6 +508,200 @@ _BM_HELP_LOOP2: jp BM_ENTER_MAIN_LOOP +;--- Config loop, entered when F2 is pressed + +BM_DO_CONFIG: + call BM_CLEAR_INFO_AREA + ld hl,BM_ZERO_S + call BM_PRINT_STATUS + + ld h,1 + ld l,4 + call POSIT + + ;* Print the current boot directory + + ld hl,BM_CONFIG_BOOTDIR_S + call PRINT + + call BM_GET_BUF_ADD + push hl + call DSK_GET_BOOTDIR + pop hl + or a + jr z,BM_DO_CONFIG_2 + cp 1 + ld hl,BM_ERROR_S + jr z,BM_DO_CONFIG_2 + ld hl,DSK_MAIN_DIR_S +BM_DO_CONFIG_2: + call PRINT + call BM_PRINT_CRLF + + ;* Print the name of the default file in current dir + + ld hl,BM_CONFIG_DEFFILE_S + call PRINT + + call BM_RESTORE_CURDIR + + call BM_GET_BUF_ADD + push hl + call DSK_READ_DEFFILE_FILE + pop hl + or a + jr z,BM_DO_CONFIG_3 + cp 1 + ld hl,BM_ERROR_S + jr z,BM_DO_CONFIG_3 + ld hl,BM_UNSET_S +BM_DO_CONFIG_3: + push af + call PRINT + call BM_PRINT_CRLF + + ;* Print the current boot mode + + ld hl,BM_CONFIG_BOOTMODE_S + call PRINT + call DSK_GET_BOOTMODE + add "0" + call CHPUT + + call BM_RESTORE_CURDIR + + ;* Print the boot mode change options + + ld hl,BM_CONFIG_TEXT_S + call PRINT + + ;* Print "set (currently pointed file) as default" if it's indeed a file + + ;BM_TEMP usage: + ;bit 0 set if there's a pointed file that can be set as default + ;bit 1 set if there's a default file that can be unset + ld (iy+BM_TEMP),0 + + ld l,(iy+BM_NUM_FILES) + ld h,(iy+BM_NUM_FILES+1) + ld a,h + or l + jr z,BM_DO_CONFIG_4 + + ld l,(iy+BM_CUR_FILE_PNT) + ld h,(iy+BM_CUR_FILE_PNT+1) + push hl + pop ix + ld a,(ix+10) + and 80h ;Is it a directory? + jr nz,BM_DO_CONFIG_4 + + set 0,(iy+BM_TEMP) + ld hl,BM_CONFIG_SET_DEF_S + call PRINT + ld l,(iy+BM_CUR_FILE_PNT) + ld h,(iy+BM_CUR_FILE_PNT+1) + call BM_PRINT_FILENAME + + ld hl,BM_CONFIG_TEXT_2_S + call PRINT + + ;* Print "unset default file" if one is set + +BM_DO_CONFIG_4: + pop af + or a + jr nz,BM_DO_CONFIG_ASK + set 1,(iy+BM_TEMP) + ld hl,BM_CONFIG_UNSET_DEF_S + call PRINT + + ;* All info printed, ask user what to do and do it + +BM_DO_CONFIG_ASK: + ld hl,BM_CONFIG_CHOOSE_S + call BM_PRINT_STATUS_WAIT_KEY + + sub "0" + or a + jr z,BM_DO_CONFIG_RETURN + + cp 5 + jr c,BM_DO_CONFIG_BOOTMODE + + ;cp 5 + jr z,BM_DO_SET_BOOTDIR + + cp 6 + jr z,BM_DO_SET_DEFFILE + + cp 7 + jr z,BM_DO_UNSET_DEFFILE + + jr BM_DO_CONFIG_ASK ;Invalid action selected: ask again + +BM_DO_CONFIG_RETURN: + call BM_RESTORE_CURDIR + jp BM_ENTER_MAIN_LOOP + +BM_DO_CONFIG_BOOTMODE: + add "0" + call DSK_WRITE_BOOTMODE_FILE + jr BM_DO_CONFIG_AFTER_CHANGE + +BM_DO_SET_BOOTDIR: + call BM_GET_CUR_DIR_ADD + call DSK_WRITE_BOOTDIR_FILE + jr BM_DO_CONFIG_AFTER_CHANGE + +BM_DO_SET_DEFFILE: + bit 0,(iy+BM_TEMP) + jr z,BM_DO_CONFIG_ASK + + call BM_GET_BUF_ADD + push hl + ex de,hl + ld l,(iy+BM_CUR_FILE_PNT) + ld h,(iy+BM_CUR_FILE_PNT+1) + call BM_GENERATE_FILENAME + pop hl + call DSK_WRITE_DEFFILE_FILE + jr BM_DO_CONFIG_AFTER_CHANGE + +BM_DO_UNSET_DEFFILE: + bit 1,(iy+BM_TEMP) + jr z,BM_DO_CONFIG_ASK + + call BM_RESTORE_CURDIR + ld hl,BM_ZERO_S + call DSK_WRITE_DEFFILE_FILE + jr BM_DO_CONFIG_AFTER_CHANGE + + ;* After doing an action, show error if needed, then start over + +BM_DO_CONFIG_AFTER_CHANGE: + or a + jp z,BM_DO_CONFIG + ld hl,BM_CONFIG_ERROR_APPLYING_S + call BM_PRINT_STATUS_WAIT_KEY + jp BM_DO_CONFIG + + +;--- Just that... print a CRLF sequence + +BM_PRINT_CRLF: + ld hl,CRLF_S + jp PRINT + + +;--- Set again the directory in CURDIR + +BM_RESTORE_CURDIR: + call BM_GET_CUR_DIR_ADD + ld a,1 + jp DSK_CHANGE_DIR + + ;--- Update currently pointed file on cursor press ; Input: A = pressed cursor key @@ -556,8 +756,8 @@ _BM_UPDATE_CUR_COL_GO: pop hl ld bc,BM_CUR_COL add hl,bc - ld (iy+BM_BUF),l - ld (iy+BM_BUF+1),h + ld (iy+BM_TEMP),l + ld (iy+BM_TEMP+1),h jr _BM_UPDATE_CUR_ROWCOL_GO _BM_UPDATE_CUR_ROW_GO: @@ -566,8 +766,8 @@ _BM_UPDATE_CUR_ROW_GO: pop hl ld bc,BM_CUR_ROW add hl,bc - ld (iy+BM_BUF),l - ld (iy+BM_BUF+1),h + ld (iy+BM_TEMP),l + ld (iy+BM_TEMP+1),h _BM_UPDATE_CUR_ROWCOL_GO: call BM_UPDATE_CUR_FILE_PNT @@ -578,8 +778,8 @@ _BM_UPDATE_CUR_ROWCOL_GO: jr nz,_BM_UPDATE_CUR_ROWCOL_GO_2 ;We ended up pointing past the end of the list, ;so reset column/row to 0 - ld l,(iy+BM_BUF) - ld h,(iy+BM_BUF+1) + ld l,(iy+BM_TEMP) + ld h,(iy+BM_TEMP+1) ld (hl),0 call BM_UPDATE_CUR_FILE_PNT @@ -1148,6 +1348,14 @@ BM_F1_IS_PRESSED: jp BM_KEY_CHECK +;--- Check if F2 is pressed +; Output: Z if pressed, NZ if not + +BM_F2_IS_PRESSED: + ld de,4006h + jp BM_KEY_CHECK + + ;--- Check if F5 is pressed ; Output: Z if pressed, NZ if not @@ -1506,7 +1714,7 @@ _BM_MAIN_GETDIR_ERR ;--- Strings BM_F1_HELP: - db "F1 = Help",0 + db "F1 = Help, F2 = Config",0 BM_F1_NEXT: db "F1 = Next",0 @@ -1605,20 +1813,57 @@ BM_HELP_2: db " and when CAPS blinks press the key." db 0 +BM_CONFIG_BOOTDIR_S: + db "Boot dir: /",0 +BM_CONFIG_DEFFILE_S: + db "Default file in this dir: ",0 +BM_CONFIG_BOOTMODE_S: + db "Boot mode: ",0 +BM_CONFIG_TEXT_S: + db 13,10 + db 13,10 + db "Change boot mode:",13,10 + db " 1: Show menu",13,10 + db " 2: Don't show menu, don't mount",13,10 + db " 3: Mount default file in boot dir",13,10 + db " 4: Mount last mounted file",13,10 + db 13,10 + db "5: Set current dir as boot dir",13,10 + db 13,10 + db 0 +BM_CONFIG_SET_DEF_S: + db "6: Set ",0 +BM_CONFIG_TEXT_2_S: + db " as default file",13,10 + db " in this dir",13,10 + db 13,10 + db 0 +BM_CONFIG_UNSET_DEF_S: + db "7: Unset explicit default file",13,10 + db " in this dir",0 +BM_CONFIG_CHOOSE_S: + db "Choose an option, or 0 to exit: ",0 + +BM_CONFIG_ERROR_APPLYING_S: + db "Error applying change - Press key ",0 + +BM_ERROR_S: db "(error)",0 + +BM_UNSET_S: db "(not set)" + +BM_ZERO_S: db 0 + ; ----------------------------------------------------------------------------- ; Variables ; ----------------------------------------------------------------------------- -_BM_VARS_BASE: equ 0C800h - BM_VARS_START: equ 0 BM_NUM_PAGES: equ BM_VARS_START BM_CUR_PAGE: equ BM_NUM_PAGES+1 BM_NUM_FILES: equ BM_CUR_PAGE+1 -BM_BUF: equ BM_NUM_FILES+2 -BM_CUR_PAGE_PNT: equ BM_BUF+13 ;Pointer to 1st filename in current page +BM_CUR_PAGE_PNT: equ BM_NUM_FILES+2 ;Pointer to 1st filename in current page BM_CUR_FILE_PNT: equ BM_CUR_PAGE_PNT+2 ;Pointer to current filename BM_CUR_ROW: equ BM_CUR_FILE_PNT+2 ;Current logical row, 0-19 BM_CUR_COL: equ BM_CUR_ROW+1 ;Current logical column, 0-2 @@ -1631,7 +1876,9 @@ BM_MAX_FILES_TO_ENUM: equ BM_CUR_DIR_LENGTH+1 BM_SCRMOD_BAK: equ BM_MAX_FILES_TO_ENUM+2 BM_LINLEN_BAK: equ BM_SCRMOD_BAK+1 BM_FNK_BAK: equ BM_LINLEN_BAK+1 -BM_INITIAL_DIR: equ BM_FNK_BAK+1 +BM_TEMP: equ BM_FNK_BAK+1 +BM_INITIAL_DIR: equ BM_TEMP+2 +BM_BUF: equ BM_INITIAL_DIR+64 -BM_VARS_END: equ BM_FNK_BAK+1 +BM_VARS_END: equ BM_BUF+64 BM_VARS_LEN: equ BM_VARS_END-BM_VARS_START \ No newline at end of file diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index 27a2e00..d616f95 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -213,6 +213,74 @@ DSK_WRITE_CURDIR_FILE: jp DSK_WRITE_MAIN_CONFIG_FILE +; ----------------------------------------------------------------------------- +; DSK_WRITE_BOOTDIR_FILE: Write BOOTDIR config file in main directory +; ----------------------------------------------------------------------------- +; Input: HL = Address of content to write, zero-terminated +; Output: A = 0: Ok +; 1: Error + +DSK_WRITE_BOOTDIR_FILE: + push hl + call BM_STRLEN + pop de + ld hl,DSK_BOOTDIR_S + jp DSK_WRITE_MAIN_CONFIG_FILE + + +; ----------------------------------------------------------------------------- +; DSK_WRITE_BOOTMODE_FILE: Write BOOTMODE config file in main directory +; ----------------------------------------------------------------------------- +; Input: A = Value to write +; Output: A = 0: Ok +; 1: Error + +DSK_WRITE_BOOTMODE_FILE: + push af + ld hl,1 + add hl,sp + ex de,hl + ld b,1 + ld hl,DSK_BOOTMODE_S + call DSK_WRITE_MAIN_CONFIG_FILE + pop hl + ret + + +; ----------------------------------------------------------------------------- +; DSK_WRITE_DEFFILE_FILE: Write DEFFILE config file in current directory +; ----------------------------------------------------------------------------- +; Input: HL = Address of content to write, zero-terminated +; Output: A = 0: Ok +; 1: Error + +DSK_WRITE_DEFFILE_FILE: + push hl + call BM_STRLEN + pop de + ld hl,DSK_DEFFILE_S + jp DSK_WRITE_CONFIG_FILE + + +; ----------------------------------------------------------------------------- +; DSK_READ_DEFFILE_FILE: Read DEFFILE config file from current directory +; ----------------------------------------------------------------------------- +; Input: HL = Address where to read the file +; Output: A = 0: Ok +; 1: Other error +; 2: File not found + +DSK_READ_DEFFILE_FILE: + ex de,hl + ld hl,DSK_DEFFILE_S + ld b,12 + call DSK_READ_CONFIG_FILE + or a + ret nz + ld (de),a + ret + + ; ----------------------------------------------------------------------------- ; DSK_CHANGE_DIR: Change the current directory ; (doesn't update config files or work area) diff --git a/msx/bank1/inihrd_inienv.asm b/msx/bank1/inihrd_inienv.asm index 095f013..897ea0d 100644 --- a/msx/bank1/inihrd_inienv.asm +++ b/msx/bank1/inihrd_inienv.asm @@ -36,6 +36,8 @@ INIHRD_IMPL: INIENV_IMPL: + ;TODO: Key to disable mounting the file in boot modes 3 and 4 + if WAIT_KEY_ON_INIT = 1 ld hl,INIHRD_NEXT push hl From b7072c184bd6eecb1831031e5f9ad96eb419a321 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 12 Mar 2021 13:20:49 +0100 Subject: [PATCH 43/65] Adjust input parameter in DO_BOOT_MENU --- msx/bank0/oemstat.asm | 1 + msx/bank1/boot_menu.asm | 43 +++++++---------------------------------- msx/bank1/dsk.asm | 2 +- 3 files changed, 9 insertions(+), 37 deletions(-) diff --git a/msx/bank0/oemstat.asm b/msx/bank0/oemstat.asm index 1471e94..49ddf91 100644 --- a/msx/bank0/oemstat.asm +++ b/msx/bank0/oemstat.asm @@ -154,6 +154,7 @@ OEM_S_NOERRDATA: ; Open the USB menu if there's a storage device inserted OEMC_USBMENU: + ld a,1 ld ix,DO_BOOT_MENU ld iy,ROM_BANK_1 call CALL_BANK diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index c38505c..aae2b79 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -7,20 +7,14 @@ BM_MAX_DIR_NAME_LENGTH: equ 64 -;TODO: Remove input parameter in A - ; ----------------------------------------------------------------------------- ; Boot menu entry point ; ; The starting point is CURDIR, or if it isn't set, the main directory. ; -; Input: A = What should the initial directory be: -; 0: The main directory -; 1: The current directory -; The initial directory is to be set: -; - When the menu starts -; - When F5 is pressed -; - When exiting without mounting +; Input: A = Where is this called from: +; 0: Computer boot +; 1: CALL USBMENU/SUBRESET ; Output: A = 0 if a file was actually mounted ; 1 if ESC or CTRL+STOP was pressed ; 2 if not enough memory to start the menu @@ -71,7 +65,7 @@ DO_BOOT_MENU: ld (iy+BM_MAX_FILES_TO_ENUM),c ld (iy+BM_MAX_FILES_TO_ENUM+1),b - ld (iy+BM_INITIAL_DIR),d + ld (iy+BM_WHERE_CALLED_FROM),d call BM_SCREEN_BAK ld a,40 @@ -85,7 +79,7 @@ DO_BOOT_MENU: call BM_SCREEN_REST call KILBUF - ld a,(iy+BM_INITIAL_DIR) + ld a,(iy+BM_WHERE_CALLED_FROM) or a jr z,_BM_NO_REMOUNT pop af @@ -1663,33 +1657,10 @@ _BM_CALC_DIR_LEVEL_END: BM_OPEN_INITIAL_DIR: if USE_FAKE_STORAGE_DEVICE = 0 - ld a,(iy+BM_INITIAL_DIR) - or a - jr nz,_BM_OPEN_INITIAL_CURDIR - -_BM_OPEN_INITIAL_MAIN: - call DSK_CHANGE_BOOTDIR - or a - jr nz,_BM_MAIN_GETDIR_ERR - ld hl,DSK_MAIN_DIR_S - jr c,_BM_OPEN_INITIAL_MAIN_2 - ld hl,DSK_ROOT_DIR_S -_BM_OPEN_INITIAL_MAIN_2: - push hl - call BM_GET_CUR_DIR_ADD - ex de,hl - pop hl - ld bc,BM_MAX_DIR_NAME_LENGTH+1 - ldir - jr _BM_OPEN_INITIAL_MAIN_OK - -_BM_OPEN_INITIAL_CURDIR: call BM_GET_CUR_DIR_ADD call DSK_GET_CURDIR or a jr nz,_BM_MAIN_GETDIR_ERR - -_BM_OPEN_INITIAL_MAIN_OK: call BM_ADJUST_DIR_VARS xor a ret @@ -1877,8 +1848,8 @@ BM_SCRMOD_BAK: equ BM_MAX_FILES_TO_ENUM+2 BM_LINLEN_BAK: equ BM_SCRMOD_BAK+1 BM_FNK_BAK: equ BM_LINLEN_BAK+1 BM_TEMP: equ BM_FNK_BAK+1 -BM_INITIAL_DIR: equ BM_TEMP+2 -BM_BUF: equ BM_INITIAL_DIR+64 +BM_WHERE_CALLED_FROM: equ BM_TEMP+2 +BM_BUF: equ BM_WHERE_CALLED_FROM+1 BM_VARS_END: equ BM_BUF+64 BM_VARS_LEN: equ BM_VARS_END-BM_VARS_START \ No newline at end of file diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index d616f95..2541807 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -1202,7 +1202,7 @@ _DSK_DO_BOOT_1: or a ret nz - ld a,1 + xor a jp DO_BOOT_MENU From 21b224d6bd346dc3c42c53c6e8ad46bfd1f65567 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 12 Mar 2021 13:22:39 +0100 Subject: [PATCH 44/65] Force boot mode 1 when pressing TAB while booting --- msx/bank1/boot_menu.asm | 4 ++++ msx/bank1/dsk.asm | 14 ++++++++++++++ msx/bank1/inihrd_inienv.asm | 2 -- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index aae2b79..9e6eb8b 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -1775,6 +1775,10 @@ BM_HELP_2: db " exit without mounting",13,10 db 13,10 db 13,10 + db " TAB (while booting):",13,10 + db " temporarily force boot mode 1",13,10 + db 13,10 + db 13,10 db " After boot it is possible to switch",13,10 db " to another disk image file from the",13,10 db " same directory (up to 36 files).",13,10 diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index 2541807..5faeea4 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -1174,6 +1174,20 @@ DSK_DO_BOOT_PROC: _DSK_DO_BOOT_PROC: ld (iy),a + or a + jr nz,_DSK_DO_BOOT_PROC_2 + + ;When booting computer: + ;If TAB is pressed, force boot mode 1 + + ld de,7 + ld hl,NEWKEY + add hl,de + ld a,(hl) + and 8 + jr z,_DSK_DO_BOOT_1 +_DSK_DO_BOOT_PROC_2: + call WK_GET_STORAGE_DEV_FLAGS ;No disk mounted for now and 0FEh call WK_SET_STORAGE_DEV_FLAGS diff --git a/msx/bank1/inihrd_inienv.asm b/msx/bank1/inihrd_inienv.asm index 897ea0d..095f013 100644 --- a/msx/bank1/inihrd_inienv.asm +++ b/msx/bank1/inihrd_inienv.asm @@ -36,8 +36,6 @@ INIHRD_IMPL: INIENV_IMPL: - ;TODO: Key to disable mounting the file in boot modes 3 and 4 - if WAIT_KEY_ON_INIT = 1 ld hl,INIHRD_NEXT push hl From f1380a90abb81c0de0296c0285347555d10c35bb Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 12 Mar 2021 13:28:10 +0100 Subject: [PATCH 45/65] Use stack instead of fixed address in VERBOSE_RESET --- msx/bank1/verbose_reset.asm | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/msx/bank1/verbose_reset.asm b/msx/bank1/verbose_reset.asm index eb13919..7956c03 100644 --- a/msx/bank1/verbose_reset.asm +++ b/msx/bank1/verbose_reset.asm @@ -10,11 +10,11 @@ VERBOSE_RESET: push iy - ld iy,-1 + ld iy,-1-36 add iy,sp ld sp,iy call _VERBOSE_RESET - ld iy,1 + ld iy,1+36 add iy,sp ld sp,iy pop iy @@ -27,14 +27,16 @@ _VERBOSE_RESET: ld hl,NOHARD_S jp c,PRINT - ;TODO: Use stack instead - ld hl,0C000h + push iy + pop hl + inc hl + push hl call HWF_MOUNT_DISK jr c,_HW_RESET_NO_STOR ld hl,STOR_FOUND_S call PRINT - ld hl,0C000h + pop hl ld b,0 ;Print the device name, collapsing multiple spaces to a single one _HW_RESET_PRINT: From 5874ebcfc16cbe95cba1fd8327e02fbe09f2b1ef Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 12 Mar 2021 15:32:59 +0100 Subject: [PATCH 46/65] Accept CR or LF as end of file in DSK_READ_CONFIG_FILE --- msx/bank1/dsk.asm | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index 5faeea4..3d49d7b 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -56,6 +56,9 @@ DSK_ZERO_S: ; ----------------------------------------------------------------------------- ; DSK_READ_CONFIG_FILE: Read config file in current directory +; +; The file is read until B bytes have been read, the end of the file +; is reached, or a CR or LF character is found, whatever happens firts ; ----------------------------------------------------------------------------- ; Input: HL = File name ; DE = Destination address @@ -67,7 +70,6 @@ DSK_ZERO_S: ; DE = Pointer after last byte read DSK_READ_CONFIG_FILE: - ;TODO: Allow CR or LF as file terminator push hl push de push bc @@ -92,11 +94,35 @@ DSK_READ_CONFIG_FILE: ex de,hl ld c,b ld b,0 + push hl call HWF_READ_FILE ex de,hl + pop hl ld b,0 or a ret nz + + ;Search for CR or LF + + ld a,c + or a + jr z,_DSK_READ_CONFIG_FILE_END + + ld b,c + ld c,0 +_DSK_READ_CONFIG_FILE_LOOP: + ld a,(hl) + cp 13 + jr z,_DSK_READ_CONFIG_FILE_END + cp 10 + jr z,_DSK_READ_CONFIG_FILE_END + inc hl + inc c + djnz _DSK_READ_CONFIG_FILE_LOOP + +_DSK_READ_CONFIG_FILE_END: + ex de,hl + xor a ld b,c ret From 0b2f039ce3c1afcc1c70ce06a2243ca4b0fcb674 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 12 Mar 2021 15:54:18 +0100 Subject: [PATCH 47/65] Throw error when trying FORMAT with storage device present --- msx/bank1/choice_dskfmt.asm | 1129 ++++++++++++++++++----------------- 1 file changed, 568 insertions(+), 561 deletions(-) diff --git a/msx/bank1/choice_dskfmt.asm b/msx/bank1/choice_dskfmt.asm index c08faf4..4d6f278 100644 --- a/msx/bank1/choice_dskfmt.asm +++ b/msx/bank1/choice_dskfmt.asm @@ -1,561 +1,568 @@ -; Rookie Drive USB FDD BIOS -; By Konamiman, 2018 -; -; This file contains the implementation of the CHOICE and DSKFMT -; driver routines. - - -; Error codes used by DSKFMT: -; -; 0 write protect error -; 2 not ready error -; 4 data (crc) error -; 6 seek error -; 8 record not found error -; 10 write fault error -; 12 bad parameter -; 14 insufficient memory -; 16 other error - - -; ----------------------------------------------------------------------------- -; CHOICE -; ----------------------------------------------------------------------------- -; Input: None -; Output: HL pointer to choice string, 0 if no choice -; Changed: AF,BC,DE,HL,IX,IY may be affected -; ----------------------------------------------------------------------------- - -CHOICE_IMPL: - ;TODO: Disable for storage devices - ld hl,CHOICE_S - ret - - -; ----------------------------------------------------------------------------- -; DSKFMT -; ----------------------------------------------------------------------------- -; Input: A choicecode (1-9) -; D drivenumber -; HL begin of workarea -; BC length of workarea -; Output: F Cx set for error -; Cx reset for ok -; A if error, errorcode -; Changed: AF,BC,DE,HL,IX,IY may be affected -; ----------------------------------------------------------------------------- - -DSKFMT_IMPL: - ;TODO: Disable for storage devices - ld c,a - ld a,d - call CHECK_SAME_DRIVE - - push bc - call DSKCHG_IMPL ;To eat a possible "not ready" error reported by - pop bc ;the device on disk change - - dec c - - ;Now C = bit 0: 0 for full format, 1 for quick format - ; bit 1: 0 for 720K, 1 for 1440K - - rr c - jr c,_DSKFMT_QUICK - -_DSKFMT_FULL: - push bc - rr c - call PHYSICAL_FORMAT - pop bc - jr c,_DSKFMT_END_ERR - -_DSKFMT_QUICK: - rr c - call LOGICAL_FORMAT - jr c,_DSKFMT_END_ERR - ret - -_DSKFMT_BAD_PARAM: - ld a,12 - scf - ret - -_DSKFMT_END_ERR: - cp 12 - jr nz,_DSKFMT_END_ERR2 - ld a,16 -_DSKFMT_END_ERR2: - scf - ret - - -; ---------------------------------------------------------------------------- -; PHYSICAL_FORMAT -; ---------------------------------------------------------------------------- -; Input: Cy = 0 for 720K disk, 1 for 1.44M disk -; Output: Cy = 0 if ok -; Cy = 1 and A=DSKFMT error code on error - -_PHYSICAL_FORMAT_STACK_SPACE: equ 12 -_PHYSICAL_FORMAT_TRACKS_PER_SIDE_COUNT: equ 80 - -PHYSICAL_FORMAT: - if HW_IMPL_CONFIGURE_NAK_RETRY=1 - - push af - scf - call HW_CONFIGURE_NAK_RETRY - pop af - call _PHYSICAL_FORMAT - push af - or a - call HW_CONFIGURE_NAK_RETRY - pop af - ret -_PHYSICAL_FORMAT: - - endif - - ld hl,_UFI_FORMAT_UNIT_DATA_720K_SIDE_0 - jr nc,_PHYSICAL_FORMAT_2 - ld hl,_UFI_FORMAT_UNIT_DATA_1440K_SIDE_0 -_PHYSICAL_FORMAT_2: - - ld a,6 - call DO_SNSMAT - and 1 - jr nz,_PHYSICAL_FORMAT_DO_TRACK_BY_TRACK - - ;Usually devices implement single track formatting only, - ;so by default we'll format all the tracks one by one in a loop. - ;However the single all tracks format command will be used - ;if SHIFT is pressed (together with any other key) - ;when the "Strike a key when ready" command is presented. - -_PHYSICAL_FORMAT_DO_ALL_TRACKS: - ld bc,24 - add hl,bc ;Point to the _ALL_TRACKS command data - - ex de,hl - ld hl,_UFI_FORMAT_UNIT_CMD - ld bc,12 - ld a,1 - scf - call USB_EXECUTE_CBI_WITH_RETRY - - or a - ld a,12 - scf - ret nz - - ld a,d ;non-zero ASC? - or a - ret z - - jp ASC_TO_ERR - -_PHYSICAL_FORMAT_DO_TRACK_BY_TRACK: - ld ix,-_PHYSICAL_FORMAT_STACK_SPACE - add ix,sp - ld sp,ix - - push hl - push ix - pop de - ld hl,_UFI_FORMAT_UNIT_CMD - ld bc,12 - ldir - pop hl - - push hl - call _PHYSICAL_FORMAT_ONE_SIDE - pop hl - jr c,_PHYSICAL_FORMAT_END - ld bc,12 - add hl,bc ;Switch to the _SIDE_1 command - call _PHYSICAL_FORMAT_ONE_SIDE - -_PHYSICAL_FORMAT_END: - push af - pop hl - ld ix,_PHYSICAL_FORMAT_STACK_SPACE - add ix,sp - ld sp,ix - push hl - pop af - ret - - ;Format all the tracks on one side of the disk - ;Input: IX=Command, HL=Data - -_PHYSICAL_FORMAT_ONE_SIDE: - ld b,0 ;Track number - -_PHYSICAL_FORMAT_TRACK_LOOP: - ld (ix+2),b - - push ix - push hl - push bc - - ex de,hl - push ix - pop hl - ld bc,12 - ld a,1 - scf - call USB_EXECUTE_CBI_WITH_RETRY - - pop bc - pop hl - pop ix - - or a - ld a,12 - scf - ret nz - - ld a,d ;non-zero ASC? - or a - jr z,_PHYSICAL_FORMAT_NEXT_TRACK - - jp ASC_TO_ERR - -_PHYSICAL_FORMAT_NEXT_TRACK: - inc b - ld a,b - cp _PHYSICAL_FORMAT_TRACKS_PER_SIDE_COUNT - jr c,_PHYSICAL_FORMAT_TRACK_LOOP - ret - - -_UFI_FORMAT_UNIT_CMD: - db 4, 17h, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0 - -_UFI_FORMAT_UNIT_DATA_720K_SIDE_0: - db 0, 0B0h, 0, 8, 0, 0, 05h, 0A0h, 0, 0, 2, 0 -_UFI_FORMAT_UNIT_DATA_720K_SIDE_1: - db 0, 0B1h, 0, 8, 0, 0, 05h, 0A0h, 0, 0, 2, 0 -_UFI_FORMAT_UNIT_DATA_720K_ALL_TRACKS: - db 0, 0A0h, 0, 8, 0, 0, 05h, 0A0h, 0, 0, 2, 0 - -_UFI_FORMAT_UNIT_DATA_1440K_SIDE_0: - db 0, 0B0h, 0, 8, 0, 0, 0Bh, 040h, 0, 0, 2, 0 -_UFI_FORMAT_UNIT_DATA_1440K_SIDE_1: - db 0, 0B1h, 0, 8, 0, 0, 0Bh, 040h, 0, 0, 2, 0 -_UFI_FORMAT_UNIT_DATA_1440K_ALL_TRACKS: - db 0, 0A0h, 0, 8, 0, 0, 0Bh, 040h, 0, 0, 2, 0 - - -; ---------------------------------------------------------------------------- -; LOGICAL_FORMAT -; -; Initializes boot sector, FAT and root directory of the disk. -; -; MSX-DOS 1 doesn't support the standard 1.44MB format because this format -; uses 9 sectors per FAT, but DOS 1 loads the entire FAT in memory after -; having allocated just 1.5K (worth 3 sectors) for it. -; There isn't any validation so the computer just crashes. -; -; As a workaround for the above, this BIOS will apply a custom format -; of 3 sectors/FAT and 4 sectors/cluster when a 1.44MB is formatted -; in DOS 1 mode (I know, the driver shouldn't be aware of the DOS version -; under which it exists, but this is not a perfect world); in DOS2 mode -; the standard 9 sectors/FAT and 1 sector/cluster format will be applied. -; ---------------------------------------------------------------------------- -; Input: Cy = 0 for 720K disk -; 1 for 1.44M disk -; Output: Cy = 0 if ok -; Cy = 1 and A=DSKFMT error code on error - -LOGICAL_FORMAT: - ld hl,BOOT_PARAMETERS_720K - jr nc,_LOGICAL_FORMAT_DO - ld hl,BOOT_PARAMETERS_1440K_DOS1 - ld a,(DOSVER) ;We shouldn't do this but :shrug: - or a - jr z,_LOGICAL_FORMAT_DO - ld hl,BOOT_PARAMETERS_1440K - -_LOGICAL_FORMAT_DO: - - ;>>> Step 1: write boot sector - - push hl - call _LOGICAL_FORMAT_ZERO_SECBUF - ld hl,BOOT_SECTOR - ld de,(SECBUF) - ld bc,BOOT_SECTOR_END-BOOT_SECTOR - ldir - - ld hl,(SECBUF) - ld bc,BOOT_DISK_PARAMETERS-BOOT_SECTOR - add hl,bc - ex de,hl ;DE = Position of variable disk parameters in SECBUF - pop hl - push hl - ld bc,BOOT_DISK_PARAMETERS_END-BOOT_DISK_PARAMETERS - ldir - - ld de,0 - ld b,1 - call _LOGICAL_FORMAT_WR_SECTORS - pop ix - ret c - - ;>>> Step 2: write first sector of both copies of FAT - - call _LOGICAL_FORMAT_ZERO_SECBUF - - ld hl,(SECBUF) - ld a,(ix+8) ;Media ID - ld (hl),a - inc hl - ld a,0FFh - ld (hl),a - inc hl - ld (hl),a ;SECBUF contains now the initialized first FAT sector - - ld de,1 - ld b,1 - call _LOGICAL_FORMAT_WR_SECTORS ;Write first sector of first FAT - ret c - - ld e,(ix+9) ;Sectors per FAT - inc e ;DE = First sector of second FAT (skip boot sector + 1st FAT) - ld d,0 - ld b,1 - call _LOGICAL_FORMAT_WR_SECTORS - ret c - - ;>>> Step 3: clear the rest of the first FAT - - call _LOGICAL_FORMAT_ZERO_SECBUF - - ld b,(ix+9) ;Sectors per FAT - dec b ;First sector is already initialized - ld de,2 ;Skip boot sector + 1st sector of first FAT - call _LOGICAL_FORMAT_WR_SECTORS - ret c - - ;>>> Step 4: clear the rest of the second FAT and the root directory - - ld b,0 - ld c,(ix+4) ;Root directory entries - srl c - srl c - srl c - srl c ;BC = sectors for the root directory - - ld h,0 - ld l,(ix+9) ;Sectors per FAT - dec hl ;First sector is already initialized - add hl,bc - ld b,l ;B = How many sectors to clear (second FAT except 1st sector + root directory) - - ld d,0 - ld e,(ix+9) - inc e - inc e ;DE = First sector to clear (skip 1st FAT + boot sector + 1st sector of second FAT) - - jp _LOGICAL_FORMAT_WR_SECTORS - - - ;--- Write the contents of SECBUF repeatedly in a range of sectors - ; Input: DE = first sector, B = how many sectors - -_LOGICAL_FORMAT_WR_SECTORS: - push ix - push de - push bc - call WK_GET_LAST_REL_DRIVE - pop bc - pop de - ld h,a -_LOGICAL_FORMAT_WR_SECTORS_LOOP: - push bc - push de - push hl - ld a,h - ld hl,(SECBUF) - ld b,1 - scf - call DSKIO_IMPL - pop hl - pop de - pop bc - jr c,_LOGICAL_FORMAT_WR_SECTORS_LOOP_END - inc de - djnz _LOGICAL_FORMAT_WR_SECTORS_LOOP -_LOGICAL_FORMAT_WR_SECTORS_LOOP_END: - pop ix - ret - -_LOGICAL_FORMAT_ZERO_SECBUF: - ld hl,(SECBUF) - push hl - pop de - inc de - ld (hl),0 - ld bc,512-1 - ldir - ret - - -BOOT_SECTOR: - db 0EBh,0FEh,90h,"ROOKIENX" - db 00h,02h -BOOT_DISK_PARAMETERS: - db 02h,01h,00h,02h,70h,00h,0A0h,05h,0F9h,03h,00h,09h -BOOT_DISK_PARAMETERS_END: - db 00h,02h,00h,00h,00h,0D0h,0EDh - db 53h,59h,0C0h,32h,0C4h,0C0h,36h,56h,23h,36h,0C0h,31h,1Fh,0F5h,11h,9Fh - db 0C0h,0Eh,0Fh,0CDh,7Dh,0F3h,3Ch,0CAh,63h,0C0h,11h,00h,01h,0Eh,1Ah,0CDh - db 7Dh,0F3h,21h,01h,00h,22h,0ADh,0C0h,21h,00h,3Fh,11h,9Fh,0C0h,0Eh,27h - db 0CDh,7Dh,0F3h,0C3h,00h,01h,58h,0C0h,0CDh,00h,00h,79h,0E6h,0FEh,0FEh,02h - db 0C2h,6Ah,0C0h,3Ah,0C4h,0C0h,0A7h,0CAh,22h,40h,11h,79h,0C0h,0Eh,09h,0CDh - db 7Dh,0F3h,0Eh,07h,0CDh,7Dh,0F3h,18h,0B2h - db "Boot error",13,10 - db "Press any key for retry",13,10,"$",0 - db "MSXDOS SYS" -BOOT_SECTOR_END: - - -;Disk parameters that are different for each disk format: -;+0: Sectors per cluster -;+4: Root directory entries -;+6,7: Sector count -;+8: Media ID -;+9: Sectors per FAT -;+11: Sectors per track - -BOOT_PARAMETERS_720K: - db 02h,01h,00h,02h,70h,00h,0A0h,05h,0F9h,03h,00h,09h - -BOOT_PARAMETERS_1440K: - ;Media ID should be F0h here, but then DOS 2 complains with - ;"Not a DOS disk" after format finishes. Go figure. - db 01h,01h,00h,02h,0E0h,00h,40h,0Bh,0F8h,09h,00h,12h - -BOOT_PARAMETERS_1440K_DOS1: - db 04h,01h,00h,02h,0E0h,00h,40h,0Bh,0F8h,03h,00h,12h - - - if 0 - -; ----------------------------------------------------------------------------- -; Get information about the disk currently in the drive -; ----------------------------------------------------------------------------- -; Input: A = 1 to retry "disk changed" error -; Output: A = DSKIO error code (if Cy=1) -; Cy = 1 on error -; B = FFh if disk changed -; 1 if disk unchanged -; (only if A=0 at input) -; C = bit 0: 1 if disk is already formatted -; bit 1: 0 if disk is 720k, 1 if disk is 1.44M -; (only if Cy=0 and B=1) - -_GET_DISK_INFO_STACK_SPACE: equ 12 - -GET_DISK_INFO: - - if HW_IMPL_CONFIGURE_NAK_RETRY=1 - - push af - scf - call HW_CONFIGURE_NAK_RETRY - pop af - call _GET_DISK_INFO - push af - or a - call HW_CONFIGURE_NAK_RETRY - pop af - ret -_GET_DISK_INFO: - - endif - - ld ix,-_GET_DISK_INFO_STACK_SPACE - add ix,sp - ld sp,ix - - push ix - pop de - ld hl,_UFI_READ_FORMAT_CAPACITIES_CMD - ld bc,12 - or a - ld a,1 - push ix - call USB_EXECUTE_CBI_WITH_RETRY - pop ix - - or a - ld a,12 - scf - jr nz,_GET_DISK_INFO_END ;Return "other error" on USB error - - ld a,d - or a - jr z,_GET_DISK_INFO_NO_ERR - cp 28h ;"Disk changed" error - ld b,0FFh - jr z,_GET_DISK_INFO_OK - jr _GET_DISK_INFO_ASC_ERR - -_GET_DISK_INFO_NO_ERR: - - ;Useful information returned by the Read Format Capacities command: - ;+6: High byte of disk capacity in sectors: - ; 5h: 720K - ; 4h: 1.25M - ; Bh: 1.44M - ;+8: Disk format status: - ; 01b: unformatted - ; 10b: formatted - ; 11b: no disk in drive - - ld a,(ix+8) - and 11b - cp 3 - ld a,2 - scf - jr z,_GET_DISK_INFO_END ;Return "not ready" if no disk present - - ld a,(ix+8) - and 1 - xor 1 - ld c,a ;Now C = 0 for unformatted disk, 1 for formatted disk - - ld b,1 ;Disk not changed - ld a,(ix+6) - cp 05h - jr z,_GET_DISK_INFO_OK - set 1,c - cp 0Bh - jr z,_GET_DISK_INFO_OK - - ld c,10b ;If the disk is 1.25M, report it as unformatted 1.44M - jr _GET_DISK_INFO_END - -_GET_DISK_INFO_ASC_ERR: - call ASC_TO_ERR - scf - jr _GET_DISK_INFO_END -_GET_DISK_INFO_OK: - xor a -_GET_DISK_INFO_END: - push af - pop hl - ld ix,_GET_DISK_INFO_STACK_SPACE - add ix,sp - ld sp,ix - push hl - pop af - ret - -_UFI_READ_FORMAT_CAPACITIES_CMD: - db 23h, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0 - - endif +; Rookie Drive USB FDD BIOS +; By Konamiman, 2018 +; +; This file contains the implementation of the CHOICE and DSKFMT +; driver routines. + + +; Error codes used by DSKFMT: +; +; 0 write protect error +; 2 not ready error +; 4 data (crc) error +; 6 seek error +; 8 record not found error +; 10 write fault error +; 12 bad parameter +; 14 insufficient memory +; 16 other error + + +; ----------------------------------------------------------------------------- +; CHOICE +; ----------------------------------------------------------------------------- +; Input: None +; Output: HL pointer to choice string, 0 if no choice +; Changed: AF,BC,DE,HL,IX,IY may be affected +; ----------------------------------------------------------------------------- + +CHOICE_IMPL: + call WK_GET_STORAGE_DEV_FLAGS + ld hl,0 + ret nz + + ld hl,CHOICE_S + ret + + +; ----------------------------------------------------------------------------- +; DSKFMT +; ----------------------------------------------------------------------------- +; Input: A choicecode (1-9) +; D drivenumber +; HL begin of workarea +; BC length of workarea +; Output: F Cx set for error +; Cx reset for ok +; A if error, errorcode +; Changed: AF,BC,DE,HL,IX,IY may be affected +; ----------------------------------------------------------------------------- + +DSKFMT_IMPL: + ld c,a + ld a,d + call CHECK_SAME_DRIVE + + call WK_GET_STORAGE_DEV_FLAGS + ld a,16 + scf + ret nz + + push bc + call DSKCHG_IMPL ;To eat a possible "not ready" error reported by + pop bc ;the device on disk change + + dec c + + ;Now C = bit 0: 0 for full format, 1 for quick format + ; bit 1: 0 for 720K, 1 for 1440K + + rr c + jr c,_DSKFMT_QUICK + +_DSKFMT_FULL: + push bc + rr c + call PHYSICAL_FORMAT + pop bc + jr c,_DSKFMT_END_ERR + +_DSKFMT_QUICK: + rr c + call LOGICAL_FORMAT + jr c,_DSKFMT_END_ERR + ret + +_DSKFMT_BAD_PARAM: + ld a,12 + scf + ret + +_DSKFMT_END_ERR: + cp 12 + jr nz,_DSKFMT_END_ERR2 + ld a,16 +_DSKFMT_END_ERR2: + scf + ret + + +; ---------------------------------------------------------------------------- +; PHYSICAL_FORMAT +; ---------------------------------------------------------------------------- +; Input: Cy = 0 for 720K disk, 1 for 1.44M disk +; Output: Cy = 0 if ok +; Cy = 1 and A=DSKFMT error code on error + +_PHYSICAL_FORMAT_STACK_SPACE: equ 12 +_PHYSICAL_FORMAT_TRACKS_PER_SIDE_COUNT: equ 80 + +PHYSICAL_FORMAT: + if HW_IMPL_CONFIGURE_NAK_RETRY=1 + + push af + scf + call HW_CONFIGURE_NAK_RETRY + pop af + call _PHYSICAL_FORMAT + push af + or a + call HW_CONFIGURE_NAK_RETRY + pop af + ret +_PHYSICAL_FORMAT: + + endif + + ld hl,_UFI_FORMAT_UNIT_DATA_720K_SIDE_0 + jr nc,_PHYSICAL_FORMAT_2 + ld hl,_UFI_FORMAT_UNIT_DATA_1440K_SIDE_0 +_PHYSICAL_FORMAT_2: + + ld a,6 + call DO_SNSMAT + and 1 + jr nz,_PHYSICAL_FORMAT_DO_TRACK_BY_TRACK + + ;Usually devices implement single track formatting only, + ;so by default we'll format all the tracks one by one in a loop. + ;However the single all tracks format command will be used + ;if SHIFT is pressed (together with any other key) + ;when the "Strike a key when ready" command is presented. + +_PHYSICAL_FORMAT_DO_ALL_TRACKS: + ld bc,24 + add hl,bc ;Point to the _ALL_TRACKS command data + + ex de,hl + ld hl,_UFI_FORMAT_UNIT_CMD + ld bc,12 + ld a,1 + scf + call USB_EXECUTE_CBI_WITH_RETRY + + or a + ld a,12 + scf + ret nz + + ld a,d ;non-zero ASC? + or a + ret z + + jp ASC_TO_ERR + +_PHYSICAL_FORMAT_DO_TRACK_BY_TRACK: + ld ix,-_PHYSICAL_FORMAT_STACK_SPACE + add ix,sp + ld sp,ix + + push hl + push ix + pop de + ld hl,_UFI_FORMAT_UNIT_CMD + ld bc,12 + ldir + pop hl + + push hl + call _PHYSICAL_FORMAT_ONE_SIDE + pop hl + jr c,_PHYSICAL_FORMAT_END + ld bc,12 + add hl,bc ;Switch to the _SIDE_1 command + call _PHYSICAL_FORMAT_ONE_SIDE + +_PHYSICAL_FORMAT_END: + push af + pop hl + ld ix,_PHYSICAL_FORMAT_STACK_SPACE + add ix,sp + ld sp,ix + push hl + pop af + ret + + ;Format all the tracks on one side of the disk + ;Input: IX=Command, HL=Data + +_PHYSICAL_FORMAT_ONE_SIDE: + ld b,0 ;Track number + +_PHYSICAL_FORMAT_TRACK_LOOP: + ld (ix+2),b + + push ix + push hl + push bc + + ex de,hl + push ix + pop hl + ld bc,12 + ld a,1 + scf + call USB_EXECUTE_CBI_WITH_RETRY + + pop bc + pop hl + pop ix + + or a + ld a,12 + scf + ret nz + + ld a,d ;non-zero ASC? + or a + jr z,_PHYSICAL_FORMAT_NEXT_TRACK + + jp ASC_TO_ERR + +_PHYSICAL_FORMAT_NEXT_TRACK: + inc b + ld a,b + cp _PHYSICAL_FORMAT_TRACKS_PER_SIDE_COUNT + jr c,_PHYSICAL_FORMAT_TRACK_LOOP + ret + + +_UFI_FORMAT_UNIT_CMD: + db 4, 17h, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0 + +_UFI_FORMAT_UNIT_DATA_720K_SIDE_0: + db 0, 0B0h, 0, 8, 0, 0, 05h, 0A0h, 0, 0, 2, 0 +_UFI_FORMAT_UNIT_DATA_720K_SIDE_1: + db 0, 0B1h, 0, 8, 0, 0, 05h, 0A0h, 0, 0, 2, 0 +_UFI_FORMAT_UNIT_DATA_720K_ALL_TRACKS: + db 0, 0A0h, 0, 8, 0, 0, 05h, 0A0h, 0, 0, 2, 0 + +_UFI_FORMAT_UNIT_DATA_1440K_SIDE_0: + db 0, 0B0h, 0, 8, 0, 0, 0Bh, 040h, 0, 0, 2, 0 +_UFI_FORMAT_UNIT_DATA_1440K_SIDE_1: + db 0, 0B1h, 0, 8, 0, 0, 0Bh, 040h, 0, 0, 2, 0 +_UFI_FORMAT_UNIT_DATA_1440K_ALL_TRACKS: + db 0, 0A0h, 0, 8, 0, 0, 0Bh, 040h, 0, 0, 2, 0 + + +; ---------------------------------------------------------------------------- +; LOGICAL_FORMAT +; +; Initializes boot sector, FAT and root directory of the disk. +; +; MSX-DOS 1 doesn't support the standard 1.44MB format because this format +; uses 9 sectors per FAT, but DOS 1 loads the entire FAT in memory after +; having allocated just 1.5K (worth 3 sectors) for it. +; There isn't any validation so the computer just crashes. +; +; As a workaround for the above, this BIOS will apply a custom format +; of 3 sectors/FAT and 4 sectors/cluster when a 1.44MB is formatted +; in DOS 1 mode (I know, the driver shouldn't be aware of the DOS version +; under which it exists, but this is not a perfect world); in DOS2 mode +; the standard 9 sectors/FAT and 1 sector/cluster format will be applied. +; ---------------------------------------------------------------------------- +; Input: Cy = 0 for 720K disk +; 1 for 1.44M disk +; Output: Cy = 0 if ok +; Cy = 1 and A=DSKFMT error code on error + +LOGICAL_FORMAT: + ld hl,BOOT_PARAMETERS_720K + jr nc,_LOGICAL_FORMAT_DO + ld hl,BOOT_PARAMETERS_1440K_DOS1 + ld a,(DOSVER) ;We shouldn't do this but :shrug: + or a + jr z,_LOGICAL_FORMAT_DO + ld hl,BOOT_PARAMETERS_1440K + +_LOGICAL_FORMAT_DO: + + ;>>> Step 1: write boot sector + + push hl + call _LOGICAL_FORMAT_ZERO_SECBUF + ld hl,BOOT_SECTOR + ld de,(SECBUF) + ld bc,BOOT_SECTOR_END-BOOT_SECTOR + ldir + + ld hl,(SECBUF) + ld bc,BOOT_DISK_PARAMETERS-BOOT_SECTOR + add hl,bc + ex de,hl ;DE = Position of variable disk parameters in SECBUF + pop hl + push hl + ld bc,BOOT_DISK_PARAMETERS_END-BOOT_DISK_PARAMETERS + ldir + + ld de,0 + ld b,1 + call _LOGICAL_FORMAT_WR_SECTORS + pop ix + ret c + + ;>>> Step 2: write first sector of both copies of FAT + + call _LOGICAL_FORMAT_ZERO_SECBUF + + ld hl,(SECBUF) + ld a,(ix+8) ;Media ID + ld (hl),a + inc hl + ld a,0FFh + ld (hl),a + inc hl + ld (hl),a ;SECBUF contains now the initialized first FAT sector + + ld de,1 + ld b,1 + call _LOGICAL_FORMAT_WR_SECTORS ;Write first sector of first FAT + ret c + + ld e,(ix+9) ;Sectors per FAT + inc e ;DE = First sector of second FAT (skip boot sector + 1st FAT) + ld d,0 + ld b,1 + call _LOGICAL_FORMAT_WR_SECTORS + ret c + + ;>>> Step 3: clear the rest of the first FAT + + call _LOGICAL_FORMAT_ZERO_SECBUF + + ld b,(ix+9) ;Sectors per FAT + dec b ;First sector is already initialized + ld de,2 ;Skip boot sector + 1st sector of first FAT + call _LOGICAL_FORMAT_WR_SECTORS + ret c + + ;>>> Step 4: clear the rest of the second FAT and the root directory + + ld b,0 + ld c,(ix+4) ;Root directory entries + srl c + srl c + srl c + srl c ;BC = sectors for the root directory + + ld h,0 + ld l,(ix+9) ;Sectors per FAT + dec hl ;First sector is already initialized + add hl,bc + ld b,l ;B = How many sectors to clear (second FAT except 1st sector + root directory) + + ld d,0 + ld e,(ix+9) + inc e + inc e ;DE = First sector to clear (skip 1st FAT + boot sector + 1st sector of second FAT) + + jp _LOGICAL_FORMAT_WR_SECTORS + + + ;--- Write the contents of SECBUF repeatedly in a range of sectors + ; Input: DE = first sector, B = how many sectors + +_LOGICAL_FORMAT_WR_SECTORS: + push ix + push de + push bc + call WK_GET_LAST_REL_DRIVE + pop bc + pop de + ld h,a +_LOGICAL_FORMAT_WR_SECTORS_LOOP: + push bc + push de + push hl + ld a,h + ld hl,(SECBUF) + ld b,1 + scf + call DSKIO_IMPL + pop hl + pop de + pop bc + jr c,_LOGICAL_FORMAT_WR_SECTORS_LOOP_END + inc de + djnz _LOGICAL_FORMAT_WR_SECTORS_LOOP +_LOGICAL_FORMAT_WR_SECTORS_LOOP_END: + pop ix + ret + +_LOGICAL_FORMAT_ZERO_SECBUF: + ld hl,(SECBUF) + push hl + pop de + inc de + ld (hl),0 + ld bc,512-1 + ldir + ret + + +BOOT_SECTOR: + db 0EBh,0FEh,90h,"ROOKIENX" + db 00h,02h +BOOT_DISK_PARAMETERS: + db 02h,01h,00h,02h,70h,00h,0A0h,05h,0F9h,03h,00h,09h +BOOT_DISK_PARAMETERS_END: + db 00h,02h,00h,00h,00h,0D0h,0EDh + db 53h,59h,0C0h,32h,0C4h,0C0h,36h,56h,23h,36h,0C0h,31h,1Fh,0F5h,11h,9Fh + db 0C0h,0Eh,0Fh,0CDh,7Dh,0F3h,3Ch,0CAh,63h,0C0h,11h,00h,01h,0Eh,1Ah,0CDh + db 7Dh,0F3h,21h,01h,00h,22h,0ADh,0C0h,21h,00h,3Fh,11h,9Fh,0C0h,0Eh,27h + db 0CDh,7Dh,0F3h,0C3h,00h,01h,58h,0C0h,0CDh,00h,00h,79h,0E6h,0FEh,0FEh,02h + db 0C2h,6Ah,0C0h,3Ah,0C4h,0C0h,0A7h,0CAh,22h,40h,11h,79h,0C0h,0Eh,09h,0CDh + db 7Dh,0F3h,0Eh,07h,0CDh,7Dh,0F3h,18h,0B2h + db "Boot error",13,10 + db "Press any key for retry",13,10,"$",0 + db "MSXDOS SYS" +BOOT_SECTOR_END: + + +;Disk parameters that are different for each disk format: +;+0: Sectors per cluster +;+4: Root directory entries +;+6,7: Sector count +;+8: Media ID +;+9: Sectors per FAT +;+11: Sectors per track + +BOOT_PARAMETERS_720K: + db 02h,01h,00h,02h,70h,00h,0A0h,05h,0F9h,03h,00h,09h + +BOOT_PARAMETERS_1440K: + ;Media ID should be F0h here, but then DOS 2 complains with + ;"Not a DOS disk" after format finishes. Go figure. + db 01h,01h,00h,02h,0E0h,00h,40h,0Bh,0F8h,09h,00h,12h + +BOOT_PARAMETERS_1440K_DOS1: + db 04h,01h,00h,02h,0E0h,00h,40h,0Bh,0F8h,03h,00h,12h + + + if 0 + +; ----------------------------------------------------------------------------- +; Get information about the disk currently in the drive +; ----------------------------------------------------------------------------- +; Input: A = 1 to retry "disk changed" error +; Output: A = DSKIO error code (if Cy=1) +; Cy = 1 on error +; B = FFh if disk changed +; 1 if disk unchanged +; (only if A=0 at input) +; C = bit 0: 1 if disk is already formatted +; bit 1: 0 if disk is 720k, 1 if disk is 1.44M +; (only if Cy=0 and B=1) + +_GET_DISK_INFO_STACK_SPACE: equ 12 + +GET_DISK_INFO: + + if HW_IMPL_CONFIGURE_NAK_RETRY=1 + + push af + scf + call HW_CONFIGURE_NAK_RETRY + pop af + call _GET_DISK_INFO + push af + or a + call HW_CONFIGURE_NAK_RETRY + pop af + ret +_GET_DISK_INFO: + + endif + + ld ix,-_GET_DISK_INFO_STACK_SPACE + add ix,sp + ld sp,ix + + push ix + pop de + ld hl,_UFI_READ_FORMAT_CAPACITIES_CMD + ld bc,12 + or a + ld a,1 + push ix + call USB_EXECUTE_CBI_WITH_RETRY + pop ix + + or a + ld a,12 + scf + jr nz,_GET_DISK_INFO_END ;Return "other error" on USB error + + ld a,d + or a + jr z,_GET_DISK_INFO_NO_ERR + cp 28h ;"Disk changed" error + ld b,0FFh + jr z,_GET_DISK_INFO_OK + jr _GET_DISK_INFO_ASC_ERR + +_GET_DISK_INFO_NO_ERR: + + ;Useful information returned by the Read Format Capacities command: + ;+6: High byte of disk capacity in sectors: + ; 5h: 720K + ; 4h: 1.25M + ; Bh: 1.44M + ;+8: Disk format status: + ; 01b: unformatted + ; 10b: formatted + ; 11b: no disk in drive + + ld a,(ix+8) + and 11b + cp 3 + ld a,2 + scf + jr z,_GET_DISK_INFO_END ;Return "not ready" if no disk present + + ld a,(ix+8) + and 1 + xor 1 + ld c,a ;Now C = 0 for unformatted disk, 1 for formatted disk + + ld b,1 ;Disk not changed + ld a,(ix+6) + cp 05h + jr z,_GET_DISK_INFO_OK + set 1,c + cp 0Bh + jr z,_GET_DISK_INFO_OK + + ld c,10b ;If the disk is 1.25M, report it as unformatted 1.44M + jr _GET_DISK_INFO_END + +_GET_DISK_INFO_ASC_ERR: + call ASC_TO_ERR + scf + jr _GET_DISK_INFO_END +_GET_DISK_INFO_OK: + xor a +_GET_DISK_INFO_END: + push af + pop hl + ld ix,_GET_DISK_INFO_STACK_SPACE + add ix,sp + ld sp,ix + push hl + pop af + ret + +_UFI_READ_FORMAT_CAPACITIES_CMD: + db 23h, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0 + + endif From ee8444866c0620eb3418c8cefb25f0ad0ad6ddef Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 12 Mar 2021 15:55:36 +0100 Subject: [PATCH 48/65] Update version date --- msx/bank1/verbose_reset.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msx/bank1/verbose_reset.asm b/msx/bank1/verbose_reset.asm index 7956c03..9821c46 100644 --- a/msx/bank1/verbose_reset.asm +++ b/msx/bank1/verbose_reset.asm @@ -262,7 +262,7 @@ PRINT_ERROR: ROOKIE_S: db "Rookie Drive NestorBIOS v2.0",13,10 - db "Prerelease version 2021.02.22",13,10 + db "Prerelease version 2021.03.12",13,10 db "(c) Konamiman 2018,2021",13,10 db 13,10 db "Initializing device...",13 From b5d865d2e6ea74bacedd4b9586ae08e018649125 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 23 Apr 2021 18:30:33 +0200 Subject: [PATCH 49/65] Added the HWF_FIND_NTH_FILE routine --- msx/bank1/ch376.asm | 67 +++++++++++++++++++++++++++++++++---- msx/bank1/dsk.asm | 3 +- msx/bank1/inihrd_inienv.asm | 3 +- msx/bank1/verbose_reset.asm | 3 +- 4 files changed, 67 insertions(+), 9 deletions(-) diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index aa5a233..06f23d8 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -861,6 +861,46 @@ Num2: endif + push iy + ld iy,0 + call _HWF_ENUM_FILES_CORE + pop iy + ret + + +; ----------------------------------------------------------------------------- +; HWF_FIND_NTH_FILE: Find the Nth file in the current directory +; +; Files whose first character is not a letter or a digit will be skipped. +; +; The name of the files will be put at the specified address, +; sequentially and with no separators, as a fixed 11 bytes string in the +; same format as in the directory entry (e.g. "FILE EXT"). +; ----------------------------------------------------------------------------- +; Input: HL = Address of buffer to get file info into +; A = Index of file to find (first is 0) +; Output: A = 0: Ok +; 1: Generic error +; 2: File not found +; HL = Pointer after the filename + +HWF_FIND_NTH_FILE: + push iy + ld iy,1 + ld c,a + ld b,0 + inc bc + call _HWF_ENUM_FILES_CORE + pop iy + or a + ret z + cp USB_ERR_MISS_FILE + ld a,2 + ret z + dec a + ret + +_HWF_ENUM_FILES_CORE: if USE_FAKE_STORAGE_DEVICE = 0 ld a,CH_CMD_SET_FILE_NAME @@ -898,21 +938,26 @@ _HWF_ENUM_FILES_LOOP: push bc ld bc,11 - add hl,bc + add hl,bc ;Point to file attributes byte pop bc - ld a,(hl) ;File attributes byte - bit 1,a ;"Hidden" attribute set? - jr z,_HWF_ENUM_NO_HIDDEN + bit 1,(hl) ;"Hidden" attribute set? + jr nz,_HWF_ENUM_SKIP + ld a,iyl + or a + jr z,_HWF_ENUM_USE + bit 4,(hl) ;"Directory" attribute set? + jr z,_HWF_ENUM_DIR_OK +_HWF_ENUM_SKIP: push bc ld bc,-11 add hl,bc pop bc jr _HWF_ENUM_DIR_NEXT -_HWF_ENUM_NO_HIDDEN: - and 10h +_HWF_ENUM_USE: + bit 4,(hl) ;"Directory" attribute set? jr z,_HWF_ENUM_DIR_OK dec hl set 7,(hl) @@ -926,13 +971,23 @@ _HWF_ENUM_DIR_OK: or c jr z,_HWF_ENUM_FILES_END + ld a,iyl + or a + jr nz,_HWF_ENUM_SKIP + _HWF_ENUM_DIR_NEXT: ld a,CH_CMD_FILE_ENUM_GO out (CH_COMMAND_PORT),a jp _HWF_ENUM_FILES_LOOP _HWF_ENUM_FILES_END: + push af + ld a,iyl + or a + jr nz,_HWF_ENUM_FILES_END_2 ld (hl),0 +_HWF_ENUM_FILES_END_2: + pop af push de pop bc ret diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index 3d49d7b..dea3dd5 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -1183,7 +1183,8 @@ DSK_BOOTMODE_S: ; DSK_DO_BOOT_PROC: Do the boot procedure ; ----------------------------------------------------------------------------- ; Output: A = 0: Do the computer boot procedure -; 1: Do the device change boot procedure +; (on boot mode 1 jump to boot menu) +; 1: Do the device change boot procedure (always return) DSK_DO_BOOT_PROC: push iy diff --git a/msx/bank1/inihrd_inienv.asm b/msx/bank1/inihrd_inienv.asm index 095f013..d7e6fb6 100644 --- a/msx/bank1/inihrd_inienv.asm +++ b/msx/bank1/inihrd_inienv.asm @@ -44,12 +44,13 @@ INIENV_IMPL: xor a call WK_SET_LAST_REL_DRIVE - xor a + ld a,1 call VERBOSE_RESET ld b,30 DELAY_AFTER_PRINT: halt djnz DELAY_AFTER_PRINT + jp DO_BOOT_MENU ret diff --git a/msx/bank1/verbose_reset.asm b/msx/bank1/verbose_reset.asm index 9821c46..ea345fe 100644 --- a/msx/bank1/verbose_reset.asm +++ b/msx/bank1/verbose_reset.asm @@ -6,7 +6,8 @@ ; It is executed at boot time and by CALL USBRESET. ; ; Inpuy: A = 0: Called from computer boot -; 1: Called from CALL USBRESET +; (on boot mode 1 jump to boot menu) +; 1: Called from CALL USBRESET (always return) VERBOSE_RESET: push iy From 86d3b78c48ec85b809415cd30f1024d7f013e3fe Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 27 Apr 2021 17:25:41 +0200 Subject: [PATCH 50/65] Implement the disk image change mechanism. If GRAPH is pressed then CAPS lits and waits for a number or a letter (A-Z) and then mounts the Nth file corresponding to the key pressed (1-9, A=10, B=11, etc) in the same directory as the currently mounted file. Pressing GRAPH again cancels the operation. Additionally, the corresponding key can be pressed directly on disk access, without pressing GRAPH. --- msx/bank1/dskio_dskchg.asm | 130 ++++++ msx/bank1/misc.asm | 933 +++++++++++++++++++++++++------------ msx/constants.asm | 5 + 3 files changed, 771 insertions(+), 297 deletions(-) diff --git a/msx/bank1/dskio_dskchg.asm b/msx/bank1/dskio_dskchg.asm index a7f843b..a8637ce 100644 --- a/msx/bank1/dskio_dskchg.asm +++ b/msx/bank1/dskio_dskchg.asm @@ -332,6 +332,8 @@ CALL_XFER: ;=== DSKIO for storage devices (mounted file) === _DSKIO_IMPL_STDEV: + call MAYBE_CHANGE_DSK + push hl push bc @@ -551,6 +553,132 @@ CHECK_XFER_IS_NEEDED: ret + ;=== Handle possible disk image file change === + +MAYBE_CHANGE_DSK: + push af + push hl + push de + push bc + push ix + push iy + ld iy,-65 + add iy,sp + ld sp,iy + call _MAYBE_CHANGE_DSK + ld iy,65 + add iy,sp + ld sp,iy + pop iy + pop ix + pop bc + pop de + pop hl + pop af + ret + +_MAYBE_CHANGE_DSK: + push iy + call GETCURKEY + pop iy + or a + ret z + cp 0FFh + jr nz,CHGF3 + + call WAIT_KEY_RELEASE ;GRAPH pressed: wait for other keys to release... + +CHGWA2: + call CAPSON +CHGWA22: + push iy + call GETCURKEY ;...then to be pressed again. + pop iy + or a + jr z,CHGWA22 + + cp 0FFh ;User changed his mind and pressed GRAPH + jr nz,CHGF3 + + call WAIT_KEY_RELEASE + call CAPSOFF + ret + +CHGF3: + ld c,a + call CAPSOFF + + ;--- The key with index C is pressed + + push bc + push iy + pop hl + call DSK_GET_CURDIR + pop bc + + ld a,c + dec a + push iy + pop hl + push hl + call HWF_FIND_NTH_FILE + pop hl + or a + jr nz,CHGWA2 + + ld de,12 + add hl,de + ex de,hl + push iy + pop hl + push de + call BM_GENERATE_FILENAME + pop hl + + xor a + call DSK_MOUNT + or a + jr nz,CHGWA2 + +CHGF_END: + call WAIT_KEY_RELEASE + call MYKILBUF + call CAPSOFF + ret + + + ;--- Return in A the index of currently pressed key, 0 if none, FFh if GRAPH + +GETCURKEY: + xor a ;TODO: For now don't support russian keyboard + call SCANKEYS + bit 6,h + ld a,0FFh + ret nz + ld c,b + ld b,36 + ld a,1 + + ;HLDEC = key statuses + ;B = Keys left to check + ;A = Current key index + ;We do an initial rotation because we want to start at key 1. +CHGLOOP: + sra c + rr e + rr d + rr l + rr h + bit 0,c + ret nz + + inc a + djnz CHGLOOP + + xor a + ret + + ; ----------------------------------------------------------------------------- ; DSKCHG ; ----------------------------------------------------------------------------- @@ -610,6 +738,8 @@ _DSKCHG_IMPL_STDEV: cp 80h jp z,_DSKIO_IMPL_POPAF_RET_ERR ;Storage device but no disk mounted + call MAYBE_CHANGE_DSK + pop af call WK_GET_STORAGE_DEV_FLAGS diff --git a/msx/bank1/misc.asm b/msx/bank1/misc.asm index de87509..02d4d8c 100644 --- a/msx/bank1/misc.asm +++ b/msx/bank1/misc.asm @@ -1,297 +1,636 @@ -; Rookie Drive USB FDD BIOS -; By Konamiman, 2018 -; -; This file contains miscellaneous routines used by other modules. - - -; ----------------------------------------------------------------------------- -; ASC_TO_ERR: Convert UFI ASC to DSKIO error -; ----------------------------------------------------------------------------- -; Input: A = ASC -; Output: A = Error -; Cy = 1 - -ASC_TO_ERR: - call _ASC_TO_ERR - ld a,h - scf - ret - -_ASC_TO_ERR: - cp 27h ;Write protected - ld h,0 - ret z - cp 3Ah ;Not ready - ld h,2 - ret z - cp 10h ;CRC error - ld h,4 - ret z - cp 21h ;Invalid logical block - ld h,6 - ret z - cp 02h ;Seek error - ret z - cp 03h - ld h,10 - ret z - ld h,12 ;Other error - ret - - -; ----------------------------------------------------------------------------- -; TEST_DISK: Test if disk is present and if it has changed -; -; We need to call this before any attempt to access the disk, -; not only to actually check if it has changed, -; before some drives fail the READ and WRITE commands the first time -; they are executed after a disk change otherwise. -; ----------------------------------------------------------------------------- -; Output: F Cx set for error -; Cx reset for ok -; A if error, errorcode -; B if no error, disk change status -; 01 disk unchanged -; 00 unknown -; FF disk changed - -TEST_DISK: - call _RUN_TEST_UNIT_READY - ret c - - ld a,d - or a - ld b,1 ;No error: disk unchanged - ret z - - ld a,d - cp 28h ;Disk changed if ASC="Media changed" - ld b,0FFh - ret z - - cp 3Ah ;"Disk not present" - jp nz,ASC_TO_ERR - - ;Some units report "Disk not present" instead of "medium changed" - ;the first time TEST UNIT READY is executed after a disk change. - ;So let's execute it again, and if no error is returned, - ;report "disk changed". - - call _RUN_TEST_UNIT_READY - ret c - - ld b,0FFh - ld a,d - or a - ret z - cp 28h ;Test "Media changed" ASC again just in case - ret z - - jp ASC_TO_ERR - - -; Output: Cy=1 and A=12 on USB error -; Cy=0 and DE=ASC+ASCQ on USB success -_RUN_TEST_UNIT_READY: - ld b,3 ;Some drives stall on first command after reset so try a few times -TRY_TEST: - push bc - xor a ;Receive data + don't retry "Media changed" - ld hl,_UFI_TEST_UNIT_READY_CMD - ld bc,0 - ld de,0 - call USB_EXECUTE_CBI_WITH_RETRY - pop bc - or a - ret z - djnz TRY_TEST - - ld a,12 - scf - ret - -_UFI_TEST_UNIT_READY_CMD: - db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - - -; ----------------------------------------------------------------------------- -; CHECK_SAME_DRIVE -; -; If the drive passed in A is not the same that was passed last time, -; display the "Insert disk for drive X:" message. -; This is needed for phantom drive emulation. -; ----------------------------------------------------------------------------- -; Input: A Drive number -; Preserves AF, BC, DE, HL -; ----------------------------------------------------------------------------- - -CHECK_SAME_DRIVE: - push hl - push de - push bc - push af - - cp 2 - jr nc,_CHECK_SAME_DRIVE_END ;Bad drive number, let the caller handle the error - - call WK_GET_LAST_REL_DRIVE - pop bc - cp b - push bc - jr z,_CHECK_SAME_DRIVE_END - - ld a,b - call WK_SET_LAST_REL_DRIVE - ld ix,PROMPT - ld iy,ROM_BANK_0 - call CALL_BANK - -_CHECK_SAME_DRIVE_END: - pop af - pop bc - pop de - pop hl - ret - - -; ----------------------------------------------------------------------------- -; SNSMAT: Read the keyboard matrix -; -; This is the same SNSMAT provided by BIOS, it's copied here to avoid -; having to do an interslot call every time it's used -; ----------------------------------------------------------------------------- - -DO_SNSMAT: - ld c,a - di - in a,(0AAh) - and 0F0h - add c - out (0AAh),a - ei - in a,(0A9h) - ret - - ;row 6: F3 F2 F1 CODE CAPS GRAPH CTRL SHIFT - ;row 7: RET SELECT BS STOP TAB ESC F5 F4 - ;row 8: right down up left DEL INS HOME SPACE - - -; ----------------------------------------------------------------------------- -; BYTE2ASC: Convert a byte to ASCII -; ----------------------------------------------------------------------------- -; Input: A = Number to convert -; IX = Destination address for the string -; Output: IX points after the string -; Modifies: AF, C -; ----------------------------------------------------------------------------- - -;--- Convert a 1-byte number to an unterminated ASCII string -; Input: A = Number to convert -; IX = Destination address for the string -; Output: IX points after the string -; Modifies: AF, C - -BYTE2ASC: cp 10 - jr c,B2A_1D - cp 100 - jr c,B2A_2D - cp 200 - jr c,B2A_1XX - jr B2A_2XX - - ; One digit - -B2A_1D: add "0" - ld (ix),a - inc ix - ret - - ; Two digits - -B2A_2D: ld c,"0" -B2A_2D2: inc c - sub 10 - cp 10 - jr nc,B2A_2D2 - - ld (ix),c - inc ix - jr B2A_1D - - ; Between 100 and 199 - -B2A_1XX: ld (ix),"1" - sub 100 -B2A_XXX: inc ix - cp 10 - jr nc,B2A_2D ;If 1XY with X>0 - ld (ix),"0" ;If 10Y - inc ix - jr B2A_1D - - ;--- Between 200 and 255 - -B2A_2XX: ld (ix),"2" - sub 200 - jr B2A_XXX - - -; ----------------------------------------------------------------------------- -; IS_DIGIT_OR_LETTER: Check if a char is a digit or a letter -; ----------------------------------------------------------------------------- -; Input: A = Char to check -; Output: Cy=1 if it's a char or a letter (A-Z), 0 otherwise -; Modifies: AF -; ----------------------------------------------------------------------------- - -IS_DIGIT_OR_LETTER: - cp '0' - ccf - ret nc - cp '9'+1 - ret c - - cp 'Z'+1 - ret nc - cp 'A' - ccf - ret - - -; -; Divide 16-bit values (with 16-bit result) -; In: Divide BC by divider DE -; Out: BC = result, HL = rest -; -DIVIDE_16: - ld hl,0 - ld a,b - ld b,8 -Div16_Loop1: - rla - adc hl,hl - sbc hl,de - jr nc,Div16_NoAdd1 - add hl,de -Div16_NoAdd1: - djnz Div16_Loop1 - rla - cpl - ld b,a - ld a,c - ld c,b - ld b,8 -Div16_Loop2: - rla - adc hl,hl - sbc hl,de - jr nc,Div16_NoAdd2 - add hl,de -Div16_NoAdd2: - djnz Div16_Loop2 - rla - cpl - ld b,c - ld c,a - ret \ No newline at end of file +; Rookie Drive USB FDD BIOS +; By Konamiman, 2018 +; +; This file contains miscellaneous routines used by other modules. + + +; ----------------------------------------------------------------------------- +; ASC_TO_ERR: Convert UFI ASC to DSKIO error +; ----------------------------------------------------------------------------- +; Input: A = ASC +; Output: A = Error +; Cy = 1 + +ASC_TO_ERR: + call _ASC_TO_ERR + ld a,h + scf + ret + +_ASC_TO_ERR: + cp 27h ;Write protected + ld h,0 + ret z + cp 3Ah ;Not ready + ld h,2 + ret z + cp 10h ;CRC error + ld h,4 + ret z + cp 21h ;Invalid logical block + ld h,6 + ret z + cp 02h ;Seek error + ret z + cp 03h + ld h,10 + ret z + ld h,12 ;Other error + ret + + +; ----------------------------------------------------------------------------- +; TEST_DISK: Test if disk is present and if it has changed +; +; We need to call this before any attempt to access the disk, +; not only to actually check if it has changed, +; before some drives fail the READ and WRITE commands the first time +; they are executed after a disk change otherwise. +; ----------------------------------------------------------------------------- +; Output: F Cx set for error +; Cx reset for ok +; A if error, errorcode +; B if no error, disk change status +; 01 disk unchanged +; 00 unknown +; FF disk changed + +TEST_DISK: + call _RUN_TEST_UNIT_READY + ret c + + ld a,d + or a + ld b,1 ;No error: disk unchanged + ret z + + ld a,d + cp 28h ;Disk changed if ASC="Media changed" + ld b,0FFh + ret z + + cp 3Ah ;"Disk not present" + jp nz,ASC_TO_ERR + + ;Some units report "Disk not present" instead of "medium changed" + ;the first time TEST UNIT READY is executed after a disk change. + ;So let's execute it again, and if no error is returned, + ;report "disk changed". + + call _RUN_TEST_UNIT_READY + ret c + + ld b,0FFh + ld a,d + or a + ret z + cp 28h ;Test "Media changed" ASC again just in case + ret z + + jp ASC_TO_ERR + + +; Output: Cy=1 and A=12 on USB error +; Cy=0 and DE=ASC+ASCQ on USB success +_RUN_TEST_UNIT_READY: + ld b,3 ;Some drives stall on first command after reset so try a few times +TRY_TEST: + push bc + xor a ;Receive data + don't retry "Media changed" + ld hl,_UFI_TEST_UNIT_READY_CMD + ld bc,0 + ld de,0 + call USB_EXECUTE_CBI_WITH_RETRY + pop bc + or a + ret z + djnz TRY_TEST + + ld a,12 + scf + ret + +_UFI_TEST_UNIT_READY_CMD: + db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + + +; ----------------------------------------------------------------------------- +; CHECK_SAME_DRIVE +; +; If the drive passed in A is not the same that was passed last time, +; display the "Insert disk for drive X:" message. +; This is needed for phantom drive emulation. +; ----------------------------------------------------------------------------- +; Input: A Drive number +; Preserves AF, BC, DE, HL +; ----------------------------------------------------------------------------- + +CHECK_SAME_DRIVE: + push hl + push de + push bc + push af + + cp 2 + jr nc,_CHECK_SAME_DRIVE_END ;Bad drive number, let the caller handle the error + + call WK_GET_LAST_REL_DRIVE + pop bc + cp b + push bc + jr z,_CHECK_SAME_DRIVE_END + + ld a,b + call WK_SET_LAST_REL_DRIVE + ld ix,PROMPT + ld iy,ROM_BANK_0 + call CALL_BANK + +_CHECK_SAME_DRIVE_END: + pop af + pop bc + pop de + pop hl + ret + + +; ----------------------------------------------------------------------------- +; SNSMAT: Read the keyboard matrix +; +; This is the same SNSMAT provided by BIOS, it's copied here to avoid +; having to do an interslot call every time it's used +; ----------------------------------------------------------------------------- + +DO_SNSMAT: + ld c,a + di + in a,(0AAh) + and 0F0h + add c + out (0AAh),a + ei + in a,(0A9h) + ret + + ;row 6: F3 F2 F1 CODE CAPS GRAPH CTRL SHIFT + ;row 7: RET SELECT BS STOP TAB ESC F5 F4 + ;row 8: right down up left DEL INS HOME SPACE + + +; ----------------------------------------------------------------------------- +; BYTE2ASC: Convert a byte to ASCII +; ----------------------------------------------------------------------------- +; Input: A = Number to convert +; IX = Destination address for the string +; Output: IX points after the string +; Modifies: AF, C +; ----------------------------------------------------------------------------- + +;--- Convert a 1-byte number to an unterminated ASCII string +; Input: A = Number to convert +; IX = Destination address for the string +; Output: IX points after the string +; Modifies: AF, C + +BYTE2ASC: cp 10 + jr c,B2A_1D + cp 100 + jr c,B2A_2D + cp 200 + jr c,B2A_1XX + jr B2A_2XX + + ; One digit + +B2A_1D: add "0" + ld (ix),a + inc ix + ret + + ; Two digits + +B2A_2D: ld c,"0" +B2A_2D2: inc c + sub 10 + cp 10 + jr nc,B2A_2D2 + + ld (ix),c + inc ix + jr B2A_1D + + ; Between 100 and 199 + +B2A_1XX: ld (ix),"1" + sub 100 +B2A_XXX: inc ix + cp 10 + jr nc,B2A_2D ;If 1XY with X>0 + ld (ix),"0" ;If 10Y + inc ix + jr B2A_1D + + ;--- Between 200 and 255 + +B2A_2XX: ld (ix),"2" + sub 200 + jr B2A_XXX + + +; ----------------------------------------------------------------------------- +; IS_DIGIT_OR_LETTER: Check if a char is a digit or a letter +; ----------------------------------------------------------------------------- +; Input: A = Char to check +; Output: Cy=1 if it's a char or a letter (A-Z), 0 otherwise +; Modifies: AF +; ----------------------------------------------------------------------------- + +IS_DIGIT_OR_LETTER: + cp '0' + ccf + ret nc + cp '9'+1 + ret c + + cp 'Z'+1 + ret nc + cp 'A' + ccf + ret + + +; +; Divide 16-bit values (with 16-bit result) +; In: Divide BC by divider DE +; Out: BC = result, HL = rest +; +DIVIDE_16: + ld hl,0 + ld a,b + ld b,8 +Div16_Loop1: + rla + adc hl,hl + sbc hl,de + jr nc,Div16_NoAdd1 + add hl,de +Div16_NoAdd1: + djnz Div16_Loop1 + rla + cpl + ld b,a + ld a,c + ld c,b + ld b,8 +Div16_Loop2: + rla + adc hl,hl + sbc hl,de + jr nc,Div16_NoAdd2 + add hl,de +Div16_NoAdd2: + djnz Div16_Loop2 + rla + cpl + ld b,c + ld c,a + ret + + +; ----------------------------------------------------------------------------- +; SCANKEYS: Scan all the numeric and alphabetic keys, +; including the numeric keyboard. +; ----------------------------------------------------------------------------- +; Input: A = 0 for international keyboard, 1 for Russian keyboard +; Output: Keys in HLDEB (1 bit each, set if pressed): +; B: 76543210 +; E: FEDCBA98 +; D: NMLKJIHG +; L: VUTSRQPO +; H: ....ZYXW +; +; H holds also the status of CAPS, GRAPH, CTRL and SHIFT +; on bits 7,6,5,4 respectively. +; Mofifies: AF, C +; ----------------------------------------------------------------------------- + +SK_ROW_0: equ 0 +SK_ROW_1: equ 1 +SK_ROW_2: equ 2 +SK_ROW_3: equ 3 +SK_ROW_4: equ 4 +SK_ROW_5: equ 5 +SK_ROW_6: equ 6 +SK_ROW_9: equ 7 +SK_ROW_10: equ 8 +SK_B: equ 9 +SK_E: equ 10 +SK_D: equ 11 +SK_L: equ 12 +SK_H: equ 13 + +SK_SIZE: equ 14 + +SCANKEYS: + push iy + ld iy,-SK_SIZE + add iy,sp + ld sp,iy + + push af + ld bc,0700h + push iy + pop hl + call SK_GET_ROWS + + ld bc,0209h + call SK_GET_ROWS + + pop af + or a + jr nz,SCANK_RUSSIAN + call SK_INTERNATIONAL + jr SCANK_DONE +SCANK_RUSSIAN: + call SK_RUSSIAN +SCANK_DONE: + + ld b,(iy+SK_B) + ld e,(iy+SK_E) + ld d,(iy+SK_D) + ld l,(iy+SK_L) + ld h,(iy+SK_H) + + ld iy,SK_SIZE + add iy,sp + ld sp,iy + pop iy + ret + + + ;* International keyboard layout version + +;0: 76543210 +;1: ......98 +;2: BA...... +;3: JIHGFEDC +;4: RQPONMLK +;5: ZYXWVUTS +;6: .... CAPS GRAPH CTRL SHIFT +;Numeric: +;9: 43210... +;10: ...98765 + +SK_INTERNATIONAL: + + ;* 0-7 + + ld a,(iy+SK_ROW_0) ;76543210 + ld (iy+SK_B),a + + ;* 8-F + + ld a,(iy+SK_ROW_1) + and 00000011b + ld b,a ;......89 + + ld a,(iy+SK_ROW_2) ;BA...... + rrca + rrca + rrca + rrca + and 00001100b ;....BA.. + or b + ld b,a ;....BA89 + + ld a,(iy+SK_ROW_3) + rlca + rlca + rlca + rlca + ld c,a ;FEDCJIHG + and 11110000b ;FEDC.... + or b ;FEDCBA89 + + ld (iy+SK_E),a + + ;* G-N + + ld a,c + and 00001111b ;....JIHG + ld b,a + + ld a,(iy+SK_ROW_4) + rlca + rlca + rlca + rlca + ld c,a ;NMLKRQPO + and 11110000b ;NMLK.... + or b ;NMLKJIHG + + ld (iy+SK_D),a + + ;* O-V + + ld a,c + and 00001111b ;....RQPO + ld b,a + + ld a,(iy+SK_ROW_5) + rlca + rlca + rlca + rlca + ld c,a ;VUTSZYXW + and 11110000b ;VUTS.... + or b ;VUTSRQPO + + ld (iy+SK_L),a + + ;* W-Z + + ld a,c + and 00001111b ;....ZYXW + ld (iy+SK_H),a + ld h,a + +SK_COMMON: + ;Input: H = (SK_H) + + ;* CAPS-GRAPH-CTRL-SHIFT + + ld a,(iy+SK_ROW_6) + rlca + rlca + rlca + rlca + and 11110000b ;CAPS-GRAPH-CTRL-SHIFT-ZYXW + or h + + ld (iy+SK_H),a + + ;* Numeric keyboard + + ld a,(iy+SK_ROW_9) ;43210... from numeric keyboard + rrca + rrca + rrca + and 00011111b + ld b,a ;...43210 from numeric keyboard + + ld a,(iy+SK_ROW_10) ;...98765 from numeric keyboard + rlca + rlca + rlca + rlca + rlca + ld c,a ;C = 765...98, we'll use it later + and 11100000b ;765..... from numeric keyboard + or b ;76543210 from numeric keyboard + + or (iy+SK_B) ;76543210 from either the regular or the numeric keyboard + ld (iy+SK_B),a + + ld a,c + and 00000011b ;......98 from numeric keyboard + or (iy+SK_E) + ld (iy+SK_E),a ;FEDCBA98, with 98 from either the regular or the numeric keyboard + + ret + + + ;* Russian keyboard layout version + +;0: 654321.9 +;1: V.H..087 +;2: IF...B.. +;3: O.RPAUWS +;4: KJZ.TXDL +;5: QN.CMGEY +;6: .... CAPS GRAPH CTRL SHIFT +;Numeric: +;9: 43210... +;10: ...98765 + +SK_RUSSIAN: + ld a,(iy+SK_ROW_0) + ld c,a + ld b,(iy+SK_ROW_1) + ld e,0 + + and 11111100b ;654321.. + + srl b ;Cy = 7 + rra ;7654321. + srl a ;.7654321 + + srl c ;Cy = 9 + rl e ;E = .......9 + + srl b ;Cy = 8 + rl e ;E = ......98 + + srl b ;Cy = 0 + rl a ;76543210 + + ld (iy+SK_B),a + ld (iy+SK_E),e + + ;I'm sorry but that's it, only 9 disk image files supported in Russian keyboards. + ;Pull request implementing the (hellish) conversion of the rest of the keys will be welcome. + + xor a + ld (iy+SK_D),a + ld (iy+SK_L),a + ld (iy+SK_H),a + + ld h,a + jp SK_COMMON + + + ;Input: HL = First work area address, B=Rows count, C=First row + ;Output: HL = Last work area address used + 1 +SK_GET_ROWS: + ld a,c + push bc + call DO_SNSMAT + pop bc + cpl + ld (hl),a + inc hl + inc c + djnz SK_GET_ROWS + ret + + + ;Returns A=1 if we have a Russian keyboard, A=0 otherwise +CHECK_IS_RUSSIAN: ; in case of ZF + DI + CALL KILBUF + LD HL,(CAPST) + LD A,(CLIKSW) + PUSH AF + PUSH HL + XOR A + LD (KANAST),A ; KANA OFF + LD (CLIKSW),A ; Shut up! + DEC A + LD (CAPST),A ; CAPS ON + LD (NEWKEY+6),A ; No SHIFT, CTRL etc. + LD A,64 + LD B,7 + CALL 0D89H + POP HL + POP AF + LD (CLIKSW),A + LD (CAPST),HL + CALL CHGET + CP "J" + ld a,1 + RET z + dec a + ret + + +; ----------------------------------------------------------------------------- +; WAIT_KEY_RELEASE: Wait until none of the numeric and alphabetic keys +; or CAPS, GRAPH, CTRL, SHIFT is pressed. +; ----------------------------------------------------------------------------- + +WAIT_KEY_RELEASE: + call GETCURKEY + or a + jr nz,WAIT_KEY_RELEASE + ret + + +; ----------------------------------------------------------------------------- +; CAPSON and CAPSOFF: Turn the CAPS led on or off. +; Modifies: AF +; ----------------------------------------------------------------------------- + +CAPSON: + in a,(0AAh) + and 10111111b + out (0AAh),a + ret + +CAPSOFF: + push af + in a,(0AAh) + or 01000000b + out (0AAh),a + pop af + ret + + +; ----------------------------------------------------------------------------- +; MYKILBUF: Empty yhe keyboard buffer (copy of BIOS routine KILBUF) +; Modifies: HL +; ----------------------------------------------------------------------------- + +MYKILBUF: + ld hl,(PUTPNT) + ld (GETPNT),hl + ret diff --git a/msx/constants.asm b/msx/constants.asm index f70438b..c666cb3 100644 --- a/msx/constants.asm +++ b/msx/constants.asm @@ -19,10 +19,15 @@ LINL32: equ 0F3AFh LINLEN: equ 0F3B0h CRTCNT: equ 0F3B1h TXTCGP: equ 0F3B7h ;Address of pattern generator table in VRAM +CLIKSW: equ 0F3DBh CNSDFG: equ 0F3DEh +PUTPNT: equ 0F3F8h +GETPNT: equ 0F3FAh STREND: equ 0F6C6h ;End of memory used by BASIC OLDKEY: equ 0FBDAh NEWKEY: equ 0FBE5h +CAPST: equ 0FCABh +KANAST: equ 0FCACh SCRMOD: equ 0FCAFh ;Keyboard matrix: From 4a72c055a03284c134a2c3ebc6414624921ad44b Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sat, 1 May 2021 22:01:07 +0200 Subject: [PATCH 51/65] Add the CALL USBCD command --- msx/bank0/oemstat.asm | 294 +++++++++++++++++++++++++++++++++++- msx/bank1/dsk.asm | 21 +++ msx/bank1/inihrd_inienv.asm | 3 +- msx/constants.asm | 7 + 4 files changed, 317 insertions(+), 8 deletions(-) diff --git a/msx/bank0/oemstat.asm b/msx/bank0/oemstat.asm index 49ddf91..81166f0 100644 --- a/msx/bank0/oemstat.asm +++ b/msx/bank0/oemstat.asm @@ -73,6 +73,8 @@ OEM_COMMANDS: db "USBMENU",0 dw OEMC_USBMENU + db "USBCD",0 + dw OEMC_USBCD db 0 @@ -82,8 +84,7 @@ OEM_COMMANDS: OEMC_USBRESET: ld a,1 ld ix,VERBOSE_RESET - ld iy,ROM_BANK_1 - call CALL_BANK + call OEM_CALL_BANK_1 jp OEM_END @@ -93,8 +94,7 @@ OEMC_USBRESET: OEMC_USBERROR: ld ix,WK_GET_ERROR - ld iy,ROM_BANK_1 - call CALL_BANK + call OEM_CALL_BANK_1 or a jr z,_OEMC_USBERROR_ASC @@ -141,7 +141,9 @@ OEM_END: OEM_S_USBERR: db "USB error: ",0 OEM_S_H_CRLF: - db "h",13,10,0 + db "h" +OEM_S_CRLF: + db 13,10,0 OEM_S_ASC: db "ASC: ",0 OEM_S_ASCQ: @@ -156,8 +158,7 @@ OEM_S_NOERRDATA: OEMC_USBMENU: ld a,1 ld ix,DO_BOOT_MENU - ld iy,ROM_BANK_1 - call CALL_BANK + call OEM_CALL_BANK_1 cp 3 ld hl,OEM_S_NO_STDEV jp z,OEM_PRINT_AND_END @@ -172,6 +173,285 @@ OEM_S_NO_MEM: db "Not enough memory",7,0 + ;--- CALL USBCD - Print the current directory + ; CALL USBCD("dir/dir") - Change to the specified relative directory + ; CALL USBCD("/dir/dir") - Change to the specified absolute directory + +OEMC_USBCD: + pop hl + + push iy + ld iy,-65 + add iy,sp + ld sp,iy + call _OEMC_USBCD + ld iy,65 + add iy,sp + ld sp,iy + pop iy + + or a + ret +_OEMC_USBCD: + + dec hl + ld ix,CHRGTR + call OEM_CALBAS + jp z,OEMC_USBCD_PRINT + + ;--- Change the current directory + + cp '(' + jp nz,THROW_SYNTAX_ERROR + inc hl + ld ix,FRMEVL + call OEM_CALBAS + push hl + ld ix,FRESTR + call OEM_CALBAS + ex de,hl + pop hl + dec hl + ld ix,CHRGTR + call OEM_CALBAS + cp ')' + jp nz,THROW_SYNTAX_ERROR + + ;Here DE = Pointer to string descriptor + + push hl ;Save BASIC text pointer + ex de,hl + + ld a,(hl) + or a + jp z,THROW_ILLEGAL_FN_CALL + cp 64+1 + jp nc,THROW_STRING_TOO_LONG + + ld b,0 + ld c,a ;BC = Length of string + inc hl + ld a,(hl) + inc hl + ld h,(hl) + ld l,a ;HL = Pointer to string + + push iy + pop de + push bc + ldir + pop bc + xor a + ld (de),a ;IY contains now the zero-terminated string + + push iy + pop hl + ld a,(hl) + cp '.' + jr nz,_OEMC_USBCD_DO + inc hl + ld a,(hl) + dec hl + cp '.' + jp nz,THROW_DIR_NOT_FOUND + + ;"..": go to parent directory + + push iy + pop de + ld ix,DSK_READ_CURDIR_FILE + call OEM_CALL_BANK_1 + dec a + jp z,THROW_DISK_ERROR + + ld a,b ;Length of current directory + or a + jp z,THROW_DIR_NOT_FOUND ;Root directory: it has no parent + ld e,b + ld c,b + ld b,0 + push iy + pop hl + add hl,bc ;HL points now at the terminating zero + ld b,e +_OEMC_USBCD_FIND_PARENT: + dec hl + ld a,(hl) + cp '/' + jr z,_OEMC_USBCD_PARENT_FOUND + djnz _OEMC_USBCD_FIND_PARENT + ;If this is reached: no '/' in current dir, so parent is root + +_OEMC_USBCD_PARENT_FOUND: + ld (hl),0 ;Remove last '/' and everything after it + push iy + pop hl + ld a,1 ;Set absolute dir + jr _OEMC_USBCD_DO2 + +_OEMC_USBCD_DO: + cp '/' + ld a,0 + jr nz,_OEMC_USBCD_DO2 ;Relative dir + inc hl ;Absolute dir + inc a +_OEMC_USBCD_DO2: + call OEM_TOUPPER + ld ix,DSK_CHANGE_DIR_U + call OEM_CALL_BANK_1 + or a + jr z,_OEMC_USBCD_END + + push af + ld ix,DSK_REMOUNT + call OEM_CALL_BANK_1 + pop af + + dec a + dec a + jp z,THROW_DIR_NOT_FOUND + dec a + jp z,THROW_FILE_EXISTS + dec a + jp z,THROW_STRING_TOO_LONG + jp THROW_DISK_ERROR + +_OEMC_USBCD_END: + pop hl + inc hl + or a + ret + + ;--- Print the current directory + +OEMC_USBCD_PRINT: + push hl + + push iy + pop de + ld ix,DSK_READ_CURDIR_FILE + call OEM_CALL_BANK_1 + dec a + jp z,THROW_DISK_ERROR + + ld a,'/' + call CHPUT + push iy + pop hl + call OEM_PRINT + ld hl,OEM_S_CRLF + call OEM_PRINT + + ld ix,DSK_REMOUNT + call OEM_CALL_BANK_1 + + pop hl + ret + + +; ----------------------------------------------------------------------------- +; Call a routine in the ROM bank 1 preserving IY +; +; Input: IX = Routine address +; AF, BC, DE, HL: Depends on the routine +; Output: AF, BC, DE, HL: Depends on the routine + +OEM_CALL_BANK_1: + push iy + ld iy,ROM_BANK_1 + call CALL_BANK + pop iy + ret + + +; ----------------------------------------------------------------------------- +; Convert a string to uppercase (ASCII characters only) +; Input: HL = Address of string + +OEM_TOUPPER: + push af + push hl +_OEM_TOUPPER: + ld a,(hl) + or a + jr z,_TOUPPER_END + cp 'a' + jr c,_TOUPPER_NEXT + cp 'z'+1 + jr nc,_TOUPPER_NEXT + and 0DFh + ld (hl),a +_TOUPPER_NEXT: + inc hl + jr _OEM_TOUPPER +_TOUPPER_END: + pop hl + pop af + ret + + +; ----------------------------------------------------------------------------- +; Call a routine in the BASIC interpreter preserving IY +; +; Input: IX = Routine address +; AF, BC, DE, HL: Depends on the routine +; Output: AF, BC, DE, HL: Depends on the routine + +OEM_CALBAS: + push iy + call CALBAS + pop iy + ret + + +; ----------------------------------------------------------------------------- +; Throw various BASIC errors + +THROW_FILE_EXISTS: + ld e,65 + jr BASIC_ERR +THROW_STRING_TOO_LONG: + ld e,15 + jr BASIC_ERR +THROW_TYPE_MISMATCH: + ld e,13 + jr BASIC_ERR +THROW_ILLEGAL_FN_CALL: + ld e,5 + jr BASIC_ERR +THROW_SYNTAX_ERROR: + ld e,2 + jr BASIC_ERR +THROW_DIR_NOT_FOUND: + ld e,74 + ld a,(0F313h) + or a + jr nz,BASIC_ERR +THROW_FILE_NOT_FOUND: + ld e,53 + jr BASIC_ERR +THROW_DISK_ERROR: + ld e,69 + +BASIC_ERR: + ld a,(0F313h) + or a + jr nz,BASIC_ERR2 + + ld bc,0 + xor a + ld (NLONLY),a ; not loading basic program, close i/o channels when requested + ld (FLBMEM),a ; ascii mode + push de + ld ix,6B24h + call CALBAS + pop de + +BASIC_ERR2: + ld ix,406fh + jp CALBAS + + ; ----------------------------------------------------------------------------- ; Print the description of an USB error code ; diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index dea3dd5..d52222f 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -1294,3 +1294,24 @@ _DSK_DO_BOOT_4: or a ret z jr _DSK_DO_BOOT_3 + + +; ----------------------------------------------------------------------------- +; DSK_READ_CURDIR_FILE: Read the CURDIR config file in main directory +; ----------------------------------------------------------------------------- +; Input: DE = Destination address +; Output: A = 0: Ok +; 1: Other error +; 2: File not found +; B = Amount of bytes read if no error, 0 on error +; DE = Pointer to the zero terminator + +DSK_READ_CURDIR_FILE: + ld hl,DSK_CURDIR_S + ld b,64 + call DSK_READ_MAIN_CONFIG_FILE + push af + xor a + ld (de),a + pop af + ret diff --git a/msx/bank1/inihrd_inienv.asm b/msx/bank1/inihrd_inienv.asm index d7e6fb6..a12d951 100644 --- a/msx/bank1/inihrd_inienv.asm +++ b/msx/bank1/inihrd_inienv.asm @@ -50,7 +50,8 @@ INIENV_IMPL: DELAY_AFTER_PRINT: halt djnz DELAY_AFTER_PRINT - jp DO_BOOT_MENU + xor a + jp DSK_DO_BOOT_PROC ret diff --git a/msx/constants.asm b/msx/constants.asm index c666cb3..04dfc99 100644 --- a/msx/constants.asm +++ b/msx/constants.asm @@ -14,6 +14,10 @@ ERAFNK: equ 00CCh DSPFNK: equ 00CFh KILBUF: equ 0156h +CHRGTR: equ 4666h +FRMEVL: equ 4C64h +FRESTR: equ 67D0h + LINL40: equ 0F3AEh LINL32: equ 0F3AFh LINLEN: equ 0F3B0h @@ -24,11 +28,14 @@ CNSDFG: equ 0F3DEh PUTPNT: equ 0F3F8h GETPNT: equ 0F3FAh STREND: equ 0F6C6h ;End of memory used by BASIC +;NLONLY: equ 0F87Ch OLDKEY: equ 0FBDAh NEWKEY: equ 0FBE5h CAPST: equ 0FCABh KANAST: equ 0FCACh +;FLBMEM: equ 0FCAEh SCRMOD: equ 0FCAFh +;VALTYP: equ 0F663h ;Keyboard matrix: ; bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 From c7e7c1edacf05bcbfc2adf5470eca50b90cce70a Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sun, 2 May 2021 12:51:38 +0200 Subject: [PATCH 52/65] Fix: DSK_CHANGE_DIR_U adding initial / when relative setting from root --- msx/bank1/dsk.asm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index d52222f..72663f7 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -446,11 +446,15 @@ _DSK_CHANGE_DIR_U_LENGTH_OK_2: push iy pop hl inc hl ;Skip length - ld e,(iy) + ld a,(iy) + ld e,a ld d,0 + or a + jr z,_DSK_CHANGE_DIR_U_APPEND_OK ;It's root dir add hl,de ld (hl),'/' inc hl +_DSK_CHANGE_DIR_U_APPEND_OK: ex de,hl pop hl From 6b97038632dee6a6b46dd0480335a00961fb7f0a Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 6 May 2021 17:31:06 +0200 Subject: [PATCH 53/65] Add the CALL USBMOUNT command. --- msx/bank0/oemstat.asm | 259 ++++++++++++++++++++++++++++++++++++++-- msx/bank1/dsk.asm | 144 ++++++++++++---------- msx/bank1/work_area.asm | 2 +- msx/constants.asm | 1 + 4 files changed, 337 insertions(+), 69 deletions(-) diff --git a/msx/bank0/oemstat.asm b/msx/bank0/oemstat.asm index 81166f0..6cbb080 100644 --- a/msx/bank0/oemstat.asm +++ b/msx/bank0/oemstat.asm @@ -75,6 +75,8 @@ OEM_COMMANDS: dw OEMC_USBMENU db "USBCD",0 dw OEMC_USBCD + db "USBMOUNT",0 + dw OEMC_USBMOUNT db 0 @@ -152,25 +154,256 @@ OEM_S_NOERRDATA: db "No error data recorded",0 +; ----------------------------------------------------------------------------- +; Make sure that a storage device is connected, throw an error if not. + +OEMC_ENSURE_STORAGE_DEVICE: + push ix + push hl + ld ix,USB_CHECK_DEV_CHANGE + call OEM_CALL_BANK_1 + ld ix,WK_GET_STORAGE_DEV_FLAGS + call OEM_CALL_BANK_1 + pop hl + pop ix + jp z,THROW_ILLEGAL_FN_CALL + ret + + ;--- CALL USBMENU ; Open the USB menu if there's a storage device inserted OEMC_USBMENU: + call OEMC_ENSURE_STORAGE_DEVICE + ld a,1 ld ix,DO_BOOT_MENU call OEM_CALL_BANK_1 cp 3 - ld hl,OEM_S_NO_STDEV - jp z,OEM_PRINT_AND_END + jp z,THROW_ILLEGAL_FN_CALL cp 2 - ld hl,OEM_S_NO_MEM - jp z,OEM_PRINT_AND_END + jp z,THROW_OUT_OF_MEMORY jp OEM_END -OEM_S_NO_STDEV: - db "No USB storage device present",7,0 -OEM_S_NO_MEM: - db "Not enough memory",7,0 + + ;--- CALL USBMOUNT - Show file currently mounted + ; CALL USBMOUNT(-1) - Unmount file + ; CALL USBMOUNT(0) - Mount default file in current dir + ; CALL USBMOUNT(n) - Mount nth file in current dir + ; CALL USBMOUNT("file.ext") - Mount specified file in current dir + +OEMC_USBMOUNT: + call OEMC_ENSURE_STORAGE_DEVICE + + pop hl + + push iy + ld iy,-65 + add iy,sp + ld sp,iy + call _OEMC_USBMOUNT + ld iy,65 + add iy,sp + ld sp,iy + pop iy + + or a + ret + +_OEMC_USBMOUNT: + dec hl + ld ix,CHRGTR + call OEM_CALBAS + jp z,_OEMC_USBMOUNT_PRINT + + cp '(' + jp nz,THROW_SYNTAX_ERROR + inc hl + push hl ;Save BASIC text pointer in case we need to reevaluate expression + ld ix,FRMEVL + call OEM_CALBAS + dec hl + ld ix,CHRGTR + call OEM_CALBAS + cp ')' + jp nz,THROW_SYNTAX_ERROR + + ld a,(VALTYP) + cp 3 + jr z,_OEMC_USBMOUNT_BYNAME + ex (sp),hl ;Restore saved BASIC text pointer and at the same time save the current pointer + ld ix,FRMQNT + call OEM_CALBAS + pop hl ;Restore the current pointer + jr _OEMC_USBMOUNT_NUM + + ;--- Mount a file by name + +_OEMC_USBMOUNT_BYNAME: + pop bc ;Discard saved BASIC text pointer + push hl + ld ix,FRESTR + call OEM_CALBAS + ex de,hl + pop hl + + ;Here DE = Pointer to string descriptor + + push hl ;Save BASIC text pointer + ex de,hl + + ld a,(hl) + or a + jp z,THROW_ILLEGAL_FN_CALL + cp 12+1 + jp nc,THROW_STRING_TOO_LONG + + ld b,0 + ld c,a ;BC = Length of string + inc hl + ld a,(hl) + inc hl + ld h,(hl) + ld l,a ;HL = Pointer to string + + push iy + pop de + ldir + xor a + ld (de),a ;IY contains now the zero-terminated string + +_OEMC_USBMOUNT_BYNAME_GO: + push iy + pop hl + call OEM_TOUPPER + xor a + ld ix,DSK_MOUNT + call OEM_CALL_BANK_1 + or a + jp z,_OEM_USBMOUNT_END + + push af + ld ix,DSK_REMOUNT + call OEM_CALL_BANK_1 + pop af + dec a + dec a + jp z,THROW_FILE_NOT_FOUND + dec a + jp z,THROW_FILE_EXISTS + jp THROW_DISK_ERROR + +_OEMC_USBMOUNT_NUM: + bit 7,d + jr nz,_OEMC_USBMOUNT_UNMOUNT + + ld a,d + or a + jp nz,THROW_ILLEGAL_FN_CALL + + or e + jr z,_OEMC_USBMOUNT_DEFAULT + + ;--- Mount Nth file in the directory + + push hl + push de + + ld ix,DSK_REMOUNT_DIR + call OEM_CALL_BANK_1 + or a + jp nz,THROW_DISK_ERROR + + pop de + ld a,e + dec a + push iy + pop hl + ld bc,14 + add hl,bc + ld ix,HWF_FIND_NTH_FILE + call OEM_CALL_BANK_1 + or a + jr nz,_OEMC_USBMOUNT_DEFAULT_ERR + + push iy + pop hl + push hl + pop de + ld bc,14 + add hl,bc + ld ix,BM_GENERATE_FILENAME + call OEM_CALL_BANK_1 + + jr _OEMC_USBMOUNT_BYNAME_GO + + ;--- Unmount currently mounted file + +_OEMC_USBMOUNT_UNMOUNT: + push hl + + ld ix,DSK_CLOSE_FILE + call OEM_CALL_BANK_1 + + jr _OEM_USBMOUNT_END + + ;--- Mount default file for directory + +_OEMC_USBMOUNT_DEFAULT: + push hl + + ld ix,DSK_REMOUNT_DIR + call OEM_CALL_BANK_1 + or a + jp nz,THROW_DISK_ERROR + + push iy + pop hl + ld ix,DSK_GET_DEFAULT + call OEM_CALL_BANK_1 + or a + jp z,_OEMC_USBMOUNT_BYNAME_GO + +_OEMC_USBMOUNT_DEFAULT_ERR: + dec a + dec a + jp z,THROW_FILE_NOT_FOUND + jp THROW_DISK_ERROR + + ;--- Print currently mounted file + +_OEMC_USBMOUNT_PRINT: + push hl + + call OEMC_ENSURE_STORAGE_DEVICE + and 1 + jp z,THROW_FILE_NOT_FOUND + + push iy + pop de + ld ix,DSK_READ_CURFILE_FILE + call OEM_CALL_BANK_1 + dec a + jp z,THROW_DISK_ERROR + dec a + jp z,THROW_FILE_NOT_FOUND + + push iy + pop hl + call OEM_PRINT + ld hl,OEM_S_CRLF + call OEM_PRINT + + ld ix,DSK_REMOUNT + call OEM_CALL_BANK_1 + + pop hl + ret + +_OEM_USBMOUNT_END: + pop hl + inc hl + ret ;--- CALL USBCD - Print the current directory @@ -178,6 +411,8 @@ OEM_S_NO_MEM: ; CALL USBCD("/dir/dir") - Change to the specified absolute directory OEMC_USBCD: + call OEMC_ENSURE_STORAGE_DEVICE + pop hl push iy @@ -407,6 +642,14 @@ OEM_CALBAS: ; ----------------------------------------------------------------------------- ; Throw various BASIC errors +THROW_OUT_OF_MEMORY: + ld e,7 + jr BASIC_ERR +THROW_DIR_EXISTS: + ld e,73 + ld a,(0F313h) + or a + jr nz,BASIC_ERR THROW_FILE_EXISTS: ld e,65 jr BASIC_ERR diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index 72663f7..e6f6e4b 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -474,13 +474,15 @@ _DSK_CHANGE_DIR_U_APPEND_OK: ;input: HL = new absolute dir _DSK_CHANGE_DIR_U_UPD_CURDIR: - call DSK_SET_CURDIR + call _DSK_SET_CURDIR ;Try the actual dir change, return if ok ld a,1 + push hl call DSK_CHANGE_DIR - ret z + pop hl + jr z,_DSK_SET_CURDIR_OK ;Rewrite CURDIR with its old value, ;and change to the old directory again @@ -505,7 +507,7 @@ DSK_CURDIR_S: ;--- Set the value of CURDIR from HL, preserves HL -DSK_SET_CURDIR: +_DSK_SET_CURDIR: push hl call BM_STRLEN pop de @@ -515,6 +517,17 @@ DSK_SET_CURDIR: pop hl ret + ;--- Dir change ok: delete CURFILE since nothing is mounted now, + ; and set dir again. + +_DSK_SET_CURDIR_OK: + push hl + ld hl,DSK_CURDIR_S + ld de,DSK_ZERO_S + call DSK_WRITE_MAIN_CONFIG_FILE + pop hl + jp _DSK_SET_CURDIR + ; ----------------------------------------------------------------------------- ; DSK_MOUNT: Mount a file in the current directory @@ -575,6 +588,7 @@ _DSK_MOUNT: push hl ex de,hl ld hl,DSK_CURFILE_S + ld b,13 call DSK_READ_MAIN_CONFIG_FILE pop hl dec hl ;HL = Buffer for length of file name @@ -895,7 +909,10 @@ _DSK_GET_DEFAULT: _DSK_GET_DEFAULT_NODEF: push hl - call DSK_GET_FIRST + push iy + pop hl + xor a + call HWF_FIND_NTH_FILE pop hl or a ret nz @@ -1006,62 +1023,6 @@ DSK_DEFAULT_S: db "DEFAULT.DSK",0 -; ----------------------------------------------------------------------------- -; DSK_GET_FIRST: Get the first available file in the current directory -; -; Hidden files and files starting with "_" don't count. -; ----------------------------------------------------------------------------- -; Input: IY = Address of 32 byte buffer for directory entry -; Output: A = 0: Ok -; 1: Other error -; 2: File doesn't exist - -DSK_GET_FIRST: - ld a,CH_CMD_SET_FILE_NAME - out (CH_COMMAND_PORT),a - ld a,'*' - out (CH_DATA_PORT),a - xor a - out (CH_DATA_PORT),a - ld a,CH_CMD_FILE_OPEN - out (CH_COMMAND_PORT),a - -_DSK_GET_FIRST_LOOP: - call CH_WAIT_INT_AND_GET_RESULT - ld b,a - cp USB_ERR_MISS_FILE - ld a,2 - ret z - ld a,b - cp CH_ST_INT_DISK_READ - ld a,1 - ret nz - - push iy - pop hl - call CH_READ_DATA - ld a,b - cp 32 - ld a,1 - ret nz - - ld a,(iy) - cp '_' - jr z,_DSK_GET_FIRST_LOOP_NEXT - - ld a,(iy+11) - and 11010b ;Directory, hidden or volume? - jr nz,_DSK_GET_FIRST_LOOP_NEXT - - xor a - ret - -_DSK_GET_FIRST_LOOP_NEXT: - ld a,CH_CMD_FILE_ENUM_GO - out (CH_COMMAND_PORT),a - jr _DSK_GET_FIRST_LOOP - - ; ----------------------------------------------------------------------------- ; DSK_GET_BOOTDIR: Get the boot directory ; @@ -1313,9 +1274,72 @@ _DSK_DO_BOOT_4: DSK_READ_CURDIR_FILE: ld hl,DSK_CURDIR_S ld b,64 + jr _DSK_READ_FILE + + +; ----------------------------------------------------------------------------- +; DSK_READ_CURFILE_FILE: Read the CURFILE config file in main directory +; ----------------------------------------------------------------------------- +; Input: DE = Destination address +; Output: A = 0: Ok +; 1: Other error +; 2: File not found +; B = Amount of bytes read if no error, 0 on error +; DE = Pointer to the zero terminator + +DSK_READ_CURFILE_FILE: + ld hl,DSK_CURFILE_S + ld b,12 +_DSK_READ_FILE: call DSK_READ_MAIN_CONFIG_FILE push af xor a ld (de),a pop af ret + + +; ----------------------------------------------------------------------------- +; DSK_CLOSE_FILE: Close the current file, delete CURFILE, and update work area +; ----------------------------------------------------------------------------- + +DSK_CLOSE_FILE: + call HWF_CLOSE_FILE + ld hl,DSK_CURFILE_S + ld b,0 + call DSK_WRITE_MAIN_CONFIG_FILE + call WK_GET_STORAGE_DEV_FLAGS + and 0FEh + call WK_SET_STORAGE_DEV_FLAGS + ret + + +DSK_REMOUNT_DIR: + push iy + ld iy,-65 + add iy,sp + ld sp,iy + call _DSK_REMOUNT_DIR + ld iy,65 + add iy,sp + ld sp,iy + pop iy + ret + +_DSK_REMOUNT_DIR: + push iy + pop de + ld hl,DSK_CURDIR_S + ld b,64 + call DSK_READ_MAIN_CONFIG_FILE + or a + jp nz,DSK_OPEN_MAIN_DIR + ld (de),a + + push iy + pop hl + ld a,1 + call DSK_CHANGE_DIR + or a + ret z + jp DSK_OPEN_MAIN_DIR diff --git a/msx/bank1/work_area.asm b/msx/bank1/work_area.asm index f9b95c5..556a328 100644 --- a/msx/bank1/work_area.asm +++ b/msx/bank1/work_area.asm @@ -342,7 +342,7 @@ WK_GET_STORAGE_DEV_FLAGS: ; ----------------------------------------------------------------------------- ; Set the storage device flags ; -; Input: A = interface number +; Input: A = storage device flags byte WK_SET_STORAGE_DEV_FLAGS: push ix diff --git a/msx/constants.asm b/msx/constants.asm index 04dfc99..bab512f 100644 --- a/msx/constants.asm +++ b/msx/constants.asm @@ -16,6 +16,7 @@ KILBUF: equ 0156h CHRGTR: equ 4666h FRMEVL: equ 4C64h +FRMQNT: equ 542Fh FRESTR: equ 67D0h LINL40: equ 0F3AEh From b03387c4835cebb263d072b8fd1558041b424f3c Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 7 May 2021 15:38:48 +0200 Subject: [PATCH 54/65] Implement the CALLUSBFILES command --- msx/bank0/oemstat.asm | 123 ++++++++++++++++++++++++++++++++++++++++++ msx/constants.asm | 1 + 2 files changed, 124 insertions(+) diff --git a/msx/bank0/oemstat.asm b/msx/bank0/oemstat.asm index 6cbb080..b76028e 100644 --- a/msx/bank0/oemstat.asm +++ b/msx/bank0/oemstat.asm @@ -77,6 +77,8 @@ OEM_COMMANDS: dw OEMC_USBCD db "USBMOUNT",0 dw OEMC_USBMOUNT + db "USBFILES",0 + dw OEMC_USBFILES db 0 @@ -584,6 +586,127 @@ OEMC_USBCD_PRINT: ret + ;--- CALL USBFILES - List files in current directory + +OEMC_USBFILES: + call OEMC_ENSURE_STORAGE_DEVICE + + push iy + ld iy,-14-1 + add iy,sp + ld sp,iy + call _OEMC_USBFILES + ld iy,14+1 + add iy,sp + ld sp,iy + pop iy + + jp OEM_END + +_OEMC_USBFILES: + + ;Throw error if we have less than 1.5K of free space + + push hl + ld hl,0 + add hl,sp + ld de,(STREND) + or a + sbc hl,de + ld a,h + cp 6 + ld a,2 + pop de + jp c,THROW_OUT_OF_MEMORY + + ;How many columns to show? + + ld a,(LINLEN) + ld b,1 + cp 27 + jr c,_OEMC_USBFILES_SETCOLS + inc b + cp 40 + jr c,_OEMC_USBFILES_SETCOLS + inc b + cp 53 + jr c,_OEMC_USBFILES_SETCOLS + inc b + cp 66 + jr c,_OEMC_USBFILES_SETCOLS + inc b + cp 79 + jr c,_OEMC_USBFILES_SETCOLS + inc b +_OEMC_USBFILES_SETCOLS: + ld iyh,b + + ;How many files to list? + + ld bc,100 ;Work stack space + or a + sbc hl,bc + push hl + pop bc + push de + ld de,11 + ld ix,DIVIDE_16 ;Now BC = Files to enum + call OEM_CALL_BANK_1 + pop de + + ;Get files + + push bc + ld ix,DSK_REMOUNT_DIR + call OEM_CALL_BANK_1 + pop bc + + ld hl,(STREND) + ld ix,HWF_ENUM_FILES + call OEM_CALL_BANK_1 + ld a,b + or c + jp z,THROW_FILE_NOT_FOUND + + ;Print files + + ld hl,(STREND) + ld e,0 +_OEMC_USBFILES_LOOP: + ld a,e + inc e + cp iyh + jr c,_OEMC_USBFILES_GO + push hl + ld hl,OEM_S_CRLF + call OEM_PRINT + pop hl + ld e,1 + +_OEMC_USBFILES_GO: + ld a,(hl) + or a + jr z,_OEMC_USBFILES_END + + push de + ld ix,BM_PRINT_FILENAME + call OEM_CALL_BANK_1 + pop de +_OEMC_USBFILES_PAD: + ld a,c + cp 13 + jr nc,_OEMC_USBFILES_LOOP + ld a,' ' + call CHPUT + inc c + jr _OEMC_USBFILES_PAD + +_OEMC_USBFILES_END: + ld ix,DSK_REMOUNT + call OEM_CALL_BANK_1 + ret + + ; ----------------------------------------------------------------------------- ; Call a routine in the ROM bank 1 preserving IY ; diff --git a/msx/constants.asm b/msx/constants.asm index bab512f..c5b8155 100644 --- a/msx/constants.asm +++ b/msx/constants.asm @@ -25,6 +25,7 @@ LINLEN: equ 0F3B0h CRTCNT: equ 0F3B1h TXTCGP: equ 0F3B7h ;Address of pattern generator table in VRAM CLIKSW: equ 0F3DBh +CSRX: equ 0F3DDH CNSDFG: equ 0F3DEh PUTPNT: equ 0F3F8h GETPNT: equ 0F3FAh From 1cf3c529291e58977b20b650692b1fc8a971a277 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sat, 22 May 2021 21:44:22 +0200 Subject: [PATCH 55/65] Improvements in the disk image mode: - Introduced the "one time mount" mode: file is mounted and computer is reset, then the computer boots in mode 4 but only once; this is controlled by a config file named TMP4 that is read at boot and then deleted. CTRL+Enter enters that mode from the menu, _USBMOUNTR command from BASIC. - The disk change key is now CODE/KANA, not GRAPH. - Wait for VDP interrupt on disk access, this introduces a small delay that is required by some games. - Fixes in CAPS led handling. - Fix hang at boot when no device is found. - Fixes in help text. --- msx/bank0/oemstat.asm | 43 ++++++++++++++++++++++-- msx/bank1/boot_menu.asm | 45 +++++++++++++++++++++---- msx/bank1/dsk.asm | 66 +++++++++++++++++++++++++++++++++++++ msx/bank1/dskio_dskchg.asm | 62 ++++++++++++++++------------------ msx/bank1/inihrd_inienv.asm | 3 +- msx/bank1/misc.asm | 49 +++++++++++++++++++++++---- msx/bank1/verbose_reset.asm | 15 +++------ 7 files changed, 223 insertions(+), 60 deletions(-) diff --git a/msx/bank0/oemstat.asm b/msx/bank0/oemstat.asm index b76028e..d5d3100 100644 --- a/msx/bank0/oemstat.asm +++ b/msx/bank0/oemstat.asm @@ -77,6 +77,8 @@ OEM_COMMANDS: dw OEMC_USBCD db "USBMOUNT",0 dw OEMC_USBMOUNT + db "USBMOUNTR",0 + dw OEMC_USBMOUNTR db "USBFILES",0 dw OEMC_USBFILES db 0 @@ -86,9 +88,11 @@ OEM_COMMANDS: ; Resets USB hardware and prints device info, just like at boot time OEMC_USBRESET: - ld a,1 ld ix,VERBOSE_RESET call OEM_CALL_BANK_1 + ld a,1 + ld ix,DSK_DO_BOOT_PROC + call OEM_CALL_BANK_1 jp OEM_END @@ -97,6 +101,10 @@ OEMC_USBRESET: ; by the last executed UFI command OEMC_USBERROR: + ld ix,WK_GET_STORAGE_DEV_FLAGS + call OEM_CALL_BANK_1 + jp nz,THROW_ILLEGAL_FN_CALL + ld ix,WK_GET_ERROR call OEM_CALL_BANK_1 or a @@ -188,6 +196,25 @@ OEMC_USBMENU: jp OEM_END + ;--- CALL USBMOUNTR: + ; Same as USBMOUNT but resets the machine afterwards + ; (it doesn't support the "Show file currently mounted" mode) + +OEMC_USBMOUNTR: + pop hl + ld b,1 + call _OEMC_USBMOUNT_COMMON + + ld ix,DSK_CREATE_TMP_BOOT_FILE + call OEM_CALL_BANK_1 + or a + jp nz,THROW_DISK_ERROR + + ld iy,(EXPTBL-1) + ld ix,0 + jp CALSLT + + ;--- CALL USBMOUNT - Show file currently mounted ; CALL USBMOUNT(-1) - Unmount file ; CALL USBMOUNT(0) - Mount default file in current dir @@ -195,8 +222,14 @@ OEMC_USBMENU: ; CALL USBMOUNT("file.ext") - Mount specified file in current dir OEMC_USBMOUNT: - call OEMC_ENSURE_STORAGE_DEVICE + pop hl + ld b,0 +_OEMC_USBMOUNT_COMMON: + push hl + push bc + call OEMC_ENSURE_STORAGE_DEVICE + pop bc pop hl push iy @@ -215,7 +248,9 @@ OEMC_USBMOUNT: _OEMC_USBMOUNT: dec hl ld ix,CHRGTR + push bc call OEM_CALBAS + pop bc jp z,_OEMC_USBMOUNT_PRINT cp '(' @@ -375,6 +410,10 @@ _OEMC_USBMOUNT_DEFAULT_ERR: ;--- Print currently mounted file _OEMC_USBMOUNT_PRINT: + ld a,b + or a + jp nz,THROW_SYNTAX_ERROR + push hl call OEMC_ENSURE_STORAGE_DEVICE diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 9e6eb8b..099e6a7 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -249,6 +249,10 @@ BM_DO_ESC: ;--- ENTER key press handler BM_DO_ENTER: + ld de,0206h ;CTRL is pressed? + call BM_KEY_CHECK_CORE + ld (iy+BM_TEMP),a + ld l,(iy+BM_CUR_FILE_PNT) ld h,(iy+BM_CUR_FILE_PNT+1) @@ -304,8 +308,24 @@ _BM_DO_ENTER_WAIT_RELEASE: ;In case the "any key" pressed is enter _BM_DO_ENTER_FILE_SUCCESS: call KILBUF - xor a - ret ;Exit menu + + ld a,(iy+BM_TEMP) ;Was CTRL pressed? + or a + ld a,0 + ret nz ;Exit menu + + ld hl,BM_RESETTING_S + call BM_PRINT_STATUS + + call DSK_CREATE_TMP_BOOT_FILE + or a + ld iy,(EXPTBL-1) + ld ix,0 + jp z,CALSLT + + ld hl,BM_ERR_CREATING_TEMP_FILE_S + call BM_PRINT_STATUS_WAIT_KEY + jp BM_ENTER_MAIN_LOOP ;* It's a directory @@ -362,6 +382,9 @@ _BM_COPY_DIR_NAME_LOOP: ld de,0106h ;SHIFT is pressed? call BM_KEY_CHECK_CORE jr z,_BM_DO_MOUNT_DEFAULT + ld de,0206h ;CTRL is pressed? + call BM_KEY_CHECK_CORE + jr z,_BM_DO_MOUNT_DEFAULT _BM_DO_ENTER_DIR_END: call BM_ENUM_FILES @@ -1741,6 +1764,12 @@ BM_MOUNTING_DEF_S: BM_ERR_RETRIEVING_DEFAULT_S: db "Error retrieving default file for dir!",0 +BM_ERR_CREATING_TEMP_FILE_S: + db "Error creating temp file! Press any key",0 + +BM_RESETTING_S: + db "Resetting computer...",0 + BM_DOTS_BAR_S: db "/.../",0 @@ -1754,12 +1783,14 @@ BM_HELP_1: db 13,10 db " SHIFT+Up/Down: Up/down 10 pages",13,10 db 13,10 - db " Enter (on file): Mount file and boot",13,10 + db " Enter (on file): Mount file and exit",13,10 db 13,10 db " Enter (on dir): Enter directory",13,10 db 13,10 db " SHIFT+Enter (on dir):",13,10 - db " Mount first file on dir and boot",13,10 + db " Mount default file on dir and exit",13,10 + db 13,10 + db " CTRL+Enter: Mount and reset",13,10 db 13,10 db " BS: Back to parent directory",13,10 db 13,10 @@ -1781,11 +1812,11 @@ BM_HELP_2: db 13,10 db " After boot it is possible to switch",13,10 db " to another disk image file from the",13,10 - db " same directory (up to 36 files).",13,10 + db " same directory (up to 35 files).",13,10 db 13,10 db " On disk access press the key for the",13,10 - db " file (1-0, A-Z), or press CODE/KANA",13,10 - db " and when CAPS blinks press the key." + db " file (1-9, A-Z), or press CODE/KANA",13,10 + db " and when CAPS lits press the key." db 0 BM_CONFIG_BOOTDIR_S: diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index e6f6e4b..c26e98d 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -1184,6 +1184,15 @@ _DSK_DO_BOOT_PROC_2: and 0FEh call WK_SET_STORAGE_DEV_FLAGS + ld a,(iy) + or a + jr nz,_DSK_DO_BOOT_PROC_3 + + call DSK_TEST_DEL_TMP_BOOT_FILE + or a + jp z,_DSK_DO_BOOT_4 + +_DSK_DO_BOOT_PROC_3: call DSK_GET_BOOTMODE dec a @@ -1343,3 +1352,60 @@ _DSK_REMOUNT_DIR: or a ret z jp DSK_OPEN_MAIN_DIR + + +; ----------------------------------------------------------------------------- +; DSK_CREATE_TMP_BOOT_FILE: Create the temporary boot file +; ----------------------------------------------------------------------------- +; Input: - +; Output: A = 0: Ok +; 1: Error + +DSK_CREATE_TMP_BOOT_FILE: + ld hl,DSK_TMP4_S + ld de,DSK_1_S + ld b,1 + jp DSK_WRITE_MAIN_CONFIG_FILE + +DSK_TMP4_S: + db "TMP4",0 +DSK_1_S: + db "1" + + +; ----------------------------------------------------------------------------- +; DSK_TEST_DEL_TMP_BOOT_FILE: Checks if the temporary boot file exists, +; and deletes it +; ----------------------------------------------------------------------------- +; Input: - +; Output: A = 0: Ok, file existed +; 1: Error +; 2: Ok, file didn't exist + +DSK_TEST_DEL_TMP_BOOT_FILE: + push iy + ld iy,-1 + add iy,sp + ld sp,iy + call _DSK_TEST_DEL_TMP_BOOT_FILE + ld iy,1 + add iy,sp + ld sp,iy + pop iy + ret + +_DSK_TEST_DEL_TMP_BOOT_FILE: + ld hl,DSK_TMP4_S + push iy + pop de + ld b,1 + call DSK_READ_MAIN_CONFIG_FILE + + or a ;Not found or other error? + ret nz + + ld hl,DSK_TMP4_S + ld b,0 + call DSK_WRITE_MAIN_CONFIG_FILE + xor a + ret diff --git a/msx/bank1/dskio_dskchg.asm b/msx/bank1/dskio_dskchg.asm index a8637ce..403b10b 100644 --- a/msx/bank1/dskio_dskchg.asm +++ b/msx/bank1/dskio_dskchg.asm @@ -332,6 +332,26 @@ CALL_XFER: ;=== DSKIO for storage devices (mounted file) === _DSKIO_IMPL_STDEV: + ; Wait for VDP interrupt. + ; This introduces a small delay that is required by some games. + + push af + di + ld a,2 + out (99h),a + ld a,8fh + out (99h),a +WVDP: + in a,(99h) + and 81h + dec a + jr z,WVDP + xor a + out (99h),a + ld a,8fh + out (99h),a + pop af + call MAYBE_CHANGE_DSK push hl @@ -374,6 +394,12 @@ _DSKIO_IMPL_STDEV_SEEKOK: ld b,c pop af + call CAPSON + call _DSKIO_IMPL_STDEV_GO + call CAPSOFF + ret + +_DSKIO_IMPL_STDEV_GO: jp c,_DSKIO_IMPL_STDEW_WRITE @@ -586,7 +612,8 @@ _MAYBE_CHANGE_DSK: cp 0FFh jr nz,CHGF3 - call WAIT_KEY_RELEASE ;GRAPH pressed: wait for other keys to release... + call CAPSON + call WAIT_KEY_RELEASE ;CODE/KANA pressed: wait for other keys to release... CHGWA2: call CAPSON @@ -646,39 +673,6 @@ CHGF_END: call CAPSOFF ret - - ;--- Return in A the index of currently pressed key, 0 if none, FFh if GRAPH - -GETCURKEY: - xor a ;TODO: For now don't support russian keyboard - call SCANKEYS - bit 6,h - ld a,0FFh - ret nz - ld c,b - ld b,36 - ld a,1 - - ;HLDEC = key statuses - ;B = Keys left to check - ;A = Current key index - ;We do an initial rotation because we want to start at key 1. -CHGLOOP: - sra c - rr e - rr d - rr l - rr h - bit 0,c - ret nz - - inc a - djnz CHGLOOP - - xor a - ret - - ; ----------------------------------------------------------------------------- ; DSKCHG ; ----------------------------------------------------------------------------- diff --git a/msx/bank1/inihrd_inienv.asm b/msx/bank1/inihrd_inienv.asm index a12d951..de3962a 100644 --- a/msx/bank1/inihrd_inienv.asm +++ b/msx/bank1/inihrd_inienv.asm @@ -44,12 +44,13 @@ INIENV_IMPL: xor a call WK_SET_LAST_REL_DRIVE - ld a,1 call VERBOSE_RESET ld b,30 DELAY_AFTER_PRINT: halt djnz DELAY_AFTER_PRINT + call WK_GET_STORAGE_DEV_FLAGS + ret z xor a jp DSK_DO_BOOT_PROC diff --git a/msx/bank1/misc.asm b/msx/bank1/misc.asm index 02d4d8c..11fd074 100644 --- a/msx/bank1/misc.asm +++ b/msx/bank1/misc.asm @@ -309,7 +309,7 @@ Div16_NoAdd2: ; L: VUTSRQPO ; H: ....ZYXW ; -; H holds also the status of CAPS, GRAPH, CTRL and SHIFT +; H holds also the status of CODE/KANA, GRAPH, CTRL and SHIFT ; on bits 7,6,5,4 respectively. ; Mofifies: AF, C ; ----------------------------------------------------------------------------- @@ -376,7 +376,7 @@ SCANK_DONE: ;3: JIHGFEDC ;4: RQPONMLK ;5: ZYXWVUTS -;6: .... CAPS GRAPH CTRL SHIFT +;6: .... CODE/KANA GRAPH CTRL SHIFT ;Numeric: ;9: 43210... ;10: ...98765 @@ -465,8 +465,12 @@ SK_COMMON: rlca rlca rlca - and 11110000b ;CAPS-GRAPH-CTRL-SHIFT-ZYXW - or h + and 01110001b ;0-GRAPH-CTRL-SHIFT-000-CODE/KANA + bit 0,a + jr z,SK_COMMON_2 ;CODE/KANA pressed? + xor 10000001b ;Set bit 7 and reset bit 0 +SK_COMMON_2: + or h ;CODE/KANA-GRAPH-CTRL-SHIFT-ZYXW ld (iy+SK_H),a @@ -593,9 +597,41 @@ CHECK_IS_RUSSIAN: ; in case of ZF ret + ;--- Return in A the index of currently pressed key, 0 if none, FFh if CODE/KANA + +GETCURKEY: + xor a ;TODO: For now don't support russian keyboard + call SCANKEYS + bit 7,h + ld a,0FFh + ret nz + ld c,b + ld b,36 + ld a,1 + + ;HLDEC = key statuses + ;B = Keys left to check + ;A = Current key index + ;We do an initial rotation because we want to start at key 1. +CHGLOOP: + sra c + rr e + rr d + rr l + rr h + bit 0,c + ret nz + + inc a + djnz CHGLOOP + + xor a + ret + + ; ----------------------------------------------------------------------------- ; WAIT_KEY_RELEASE: Wait until none of the numeric and alphabetic keys -; or CAPS, GRAPH, CTRL, SHIFT is pressed. +; or CODE/KANA, GRAPH, CTRL, SHIFT is pressed. ; ----------------------------------------------------------------------------- WAIT_KEY_RELEASE: @@ -607,13 +643,14 @@ WAIT_KEY_RELEASE: ; ----------------------------------------------------------------------------- ; CAPSON and CAPSOFF: Turn the CAPS led on or off. -; Modifies: AF ; ----------------------------------------------------------------------------- CAPSON: + push af in a,(0AAh) and 10111111b out (0AAh),a + pop af ret CAPSOFF: diff --git a/msx/bank1/verbose_reset.asm b/msx/bank1/verbose_reset.asm index ea345fe..05ef335 100644 --- a/msx/bank1/verbose_reset.asm +++ b/msx/bank1/verbose_reset.asm @@ -4,25 +4,22 @@ ; This routine resets the USB hardware, resets and initializes the device, ; and prints the device name or the appropriate error message. ; It is executed at boot time and by CALL USBRESET. -; -; Inpuy: A = 0: Called from computer boot -; (on boot mode 1 jump to boot menu) -; 1: Called from CALL USBRESET (always return) VERBOSE_RESET: push iy - ld iy,-1-36 + ld iy,-36 add iy,sp ld sp,iy call _VERBOSE_RESET - ld iy,1+36 + ld iy,36 add iy,sp ld sp,iy pop iy ret _VERBOSE_RESET: - ld (iy),a + xor a + call WK_SET_STORAGE_DEV_FLAGS call HW_TEST ld hl,NOHARD_S @@ -30,7 +27,6 @@ _VERBOSE_RESET: push iy pop hl - inc hl push hl call HWF_MOUNT_DISK jr c,_HW_RESET_NO_STOR @@ -55,11 +51,10 @@ _HW_RESET_PRINT_GO: jr _HW_RESET_PRINT _HW_RESET_PRINT_END: call WK_INIT_FOR_STORAGE_DEV - ld a,(iy) - call DSK_DO_BOOT_PROC ret _HW_RESET_NO_STOR: + pop hl ld b,5 _HW_RESET_TRY: push bc From ff0cf9de64843ca4f30d493f940fdde51bb73505 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Mon, 24 May 2021 17:24:58 +0200 Subject: [PATCH 56/65] Add repeat control for cursor keys in boot menu --- msx/bank1/boot_menu.asm | 61 ++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 099e6a7..877d086 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -98,7 +98,7 @@ _BM_NO_REMOUNT: DO_BOOT_MENU_MAIN: xor a - ld (iy+BM_CURSOR_LAST),a + ld (iy+BM_CURSOR_DELAY),a ld (iy+BM_NO_STOR_DEV),a ; Init screen mode, draw fixed elements @@ -1426,30 +1426,65 @@ BM_CURSOR_IS_PRESSED: rlca ld b,2 - jr nc,_BM_CURSOR_IS_PRESSED_END + jr nc,_BM_CURSOR_IS_PRESSED_GO rlca ld b,3 - jr nc,_BM_CURSOR_IS_PRESSED_END + jr nc,_BM_CURSOR_IS_PRESSED_GO rlca ld b,1 - jr nc,_BM_CURSOR_IS_PRESSED_END + jr nc,_BM_CURSOR_IS_PRESSED_GO rlca ld b,4 - jr nc,_BM_CURSOR_IS_PRESSED_END + jr nc,_BM_CURSOR_IS_PRESSED_GO xor a - ld (iy+BM_CURSOR_LAST),a + ld (iy+BM_CURSOR_DELAY),a ret -_BM_CURSOR_IS_PRESSED_END: - ld a,(iy+BM_CURSOR_LAST) +_BM_CURSOR_IS_PRESSED_GO: + ;* Not previously pressed: return key, init delay counter + + ld a,(iy+BM_CURSOR_DELAY) or a - ld a,0 - ret nz ;Still pressed since last time + jr nz,_BM_CURSOR_IS_PRESSED_GO_2 + + inc a + ld (iy+BM_CURSOR_DELAY),a + jr _BM_CURSOR_IS_PRESSED_END +_BM_CURSOR_IS_PRESSED_GO_2: + + ;* Bit 7 is set: we are already repeating + + bit 7,a + jr z,_BM_CURSOR_IS_PRESSED_GO_3 + + cp 3+128 ;3 cycles passed since last repeat? + jr c,_BM_CURSOR_IS_PRESSED_INC_DELAY + + ld a,128 + ld (iy+BM_CURSOR_DELAY),a + jr _BM_CURSOR_IS_PRESSED_END +_BM_CURSOR_IS_PRESSED_GO_3: + + ;* Bit 7 is reset: we are waiting for the first repetition + + cp 40 ;40 cycles passed since pressing? + jr c,_BM_CURSOR_IS_PRESSED_INC_DELAY + + set 7,a + ld (iy+BM_CURSOR_DELAY),a + xor a + ret +_BM_CURSOR_IS_PRESSED_INC_DELAY: inc a - ld (iy+BM_CURSOR_LAST),a + ld (iy+BM_CURSOR_DELAY),a + xor a + ret + ;* Check for SHIFT and return, input: B = Pressed key + +_BM_CURSOR_IS_PRESSED_END: dec hl dec hl ;Row 6 (for SHIFT) ld a,(hl) @@ -1873,8 +1908,8 @@ BM_CUR_PAGE_PNT: equ BM_NUM_FILES+2 ;Pointer to 1st filename in current page BM_CUR_FILE_PNT: equ BM_CUR_PAGE_PNT+2 ;Pointer to current filename BM_CUR_ROW: equ BM_CUR_FILE_PNT+2 ;Current logical row, 0-19 BM_CUR_COL: equ BM_CUR_ROW+1 ;Current logical column, 0-2 -BM_CURSOR_LAST: equ BM_CUR_COL+1 ;Result of last call to BM_CURSOR_IS_PRESSED -BM_NO_STOR_DEV: equ BM_CURSOR_LAST+1 ;FFh if F5 was pressed and no storage device was found +BM_CURSOR_DELAY: equ BM_CUR_COL+1 ;Counter to control control key repetition delays +BM_NO_STOR_DEV: equ BM_CURSOR_DELAY+1 ;FFh if F5 was pressed and no storage device was found BM_CUR_DIR_LEVEL: equ BM_NO_STOR_DEV+1 ;Current direcrory level, 0 is root BM_CUR_DIR: equ BM_CUR_DIR_LEVEL+1 ;Current directory, up to BM_MAX_DIR_NAME_LENGTH chars + 0 BM_CUR_DIR_LENGTH: equ BM_CUR_DIR+BM_MAX_DIR_NAME_LENGTH+1 From a67a8d2573decf3816f525e0803e4f2bda9aa96f Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 25 May 2021 17:17:54 +0200 Subject: [PATCH 57/65] Add a setting for toggling on/off CAPS lit on file access --- msx/bank1/boot_menu.asm | 43 +++++++++++++++-- msx/bank1/dsk.asm | 93 +++++++++++++++++++++++++++++++++++++ msx/bank1/dskio_dskchg.asm | 6 +++ msx/bank1/misc.asm | 2 +- msx/bank1/usb.asm | 2 +- msx/bank1/verbose_reset.asm | 2 +- msx/bank1/work_area.asm | 1 + 7 files changed, 141 insertions(+), 8 deletions(-) diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 877d086..08299bb 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -215,7 +215,7 @@ BM_START_OVER: jp _BM_MAIN_LOOP _BM_START_OVER_OK: - call WK_INIT_FOR_STORAGE_DEV + call DSK_INIT_WK_FOR_STORAGE_DEV ld a,1 call DSK_DO_BOOT_PROC jp DO_BOOT_MENU_MAIN @@ -633,6 +633,20 @@ BM_DO_CONFIG_4: ld hl,BM_CONFIG_UNSET_DEF_S call PRINT + ;* Print "Enable/disable CAPS lit on file access" + + ld hl,BM_CONFIG_TWOCRLF_S + call PRINT + call DSK_TEST_CAPS_LIT + or a + ld hl,BM_CONFIG_ENABLE_8_S + jr z,BM_DO_CONFIG_5 + ld hl,BM_CONFIG_DISABLE_8_S +BM_DO_CONFIG_5: + call PRINT + ld hl,BM_CONFIG_CAPS_LIT_S + call PRINT + ;* All info printed, ask user what to do and do it BM_DO_CONFIG_ASK: @@ -655,6 +669,9 @@ BM_DO_CONFIG_ASK: cp 7 jr z,BM_DO_UNSET_DEFFILE + cp 8 + jr z,BM_DO_TOGGLE_CAPS_LIT + jr BM_DO_CONFIG_ASK ;Invalid action selected: ask again BM_DO_CONFIG_RETURN: @@ -694,6 +711,16 @@ BM_DO_UNSET_DEFFILE: call DSK_WRITE_DEFFILE_FILE jr BM_DO_CONFIG_AFTER_CHANGE +BM_DO_TOGGLE_CAPS_LIT: + call DSK_TEST_CAPS_LIT + xor 1 + call DSK_SET_OR_UNSET_CAPS_LIT + or a + jr nz,BM_DO_CONFIG_AFTER_CHANGE + call DSK_UPDATE_CAPS_LIT_WK + xor a + ;jr BM_DO_CONFIG_AFTER_CHANGE + ;* After doing an action, show error if needed, then start over BM_DO_CONFIG_AFTER_CHANGE: @@ -1861,9 +1888,7 @@ BM_CONFIG_DEFFILE_S: BM_CONFIG_BOOTMODE_S: db "Boot mode: ",0 BM_CONFIG_TEXT_S: - db 13,10 - db 13,10 - db "Change boot mode:",13,10 + db ", to change press:",13,10 db " 1: Show menu",13,10 db " 2: Don't show menu, don't mount",13,10 db " 3: Mount default file in boot dir",13,10 @@ -1876,12 +1901,20 @@ BM_CONFIG_SET_DEF_S: db "6: Set ",0 BM_CONFIG_TEXT_2_S: db " as default file",13,10 - db " in this dir",13,10 + db " in this dir" +BM_CONFIG_TWOCRLF_S: + db 13,10 db 13,10 db 0 BM_CONFIG_UNSET_DEF_S: db "7: Unset explicit default file",13,10 db " in this dir",0 +BM_CONFIG_ENABLE_8_S: + db "8: Enable",0 +BM_CONFIG_DISABLE_8_S: + db "8: Disable",0 +BM_CONFIG_CAPS_LIT_S: + db " CAPS lit on file access",0 BM_CONFIG_CHOOSE_S: db "Choose an option, or 0 to exit: ",0 diff --git a/msx/bank1/dsk.asm b/msx/bank1/dsk.asm index c26e98d..d0fa980 100644 --- a/msx/bank1/dsk.asm +++ b/msx/bank1/dsk.asm @@ -1409,3 +1409,96 @@ _DSK_TEST_DEL_TMP_BOOT_FILE: call DSK_WRITE_MAIN_CONFIG_FILE xor a ret + + +; ----------------------------------------------------------------------------- +; DSK_SET_OR_UNSET_CAPS_LIT: Set or unset the CAPS lit on file access setting, +; creating or deleting the NOCAPS config file +; ----------------------------------------------------------------------------- +; Input: A = 0 to unset, A = 1 to set +; Output: 0 = Ok, 1 = Error + +DSK_SET_OR_UNSET_CAPS_LIT: + xor 1 + ld b,a + ld hl,DSK_NOCAPS_S + ld de,DSK_1_S + jp DSK_WRITE_MAIN_CONFIG_FILE + +DSK_NOCAPS_S: + db "NOCAPS",0 + + +; ----------------------------------------------------------------------------- +; DSK_TEST_CAPS_LIT: Check the CAPS lit on file access setting +; by tryig to read the NOCAPS config file +; ----------------------------------------------------------------------------- +; Input: - +; Output: A = 0 if unset, 1 if set or error + +DSK_TEST_CAPS_LIT: + push iy + ld iy,-1 + add iy,sp + ld sp,iy + call _DSK_TEST_CAPS_LIT + ld iy,1 + add iy,sp + ld sp,iy + pop iy + ret + +_DSK_TEST_CAPS_LIT: + ld hl,DSK_NOCAPS_S + push iy + pop de + ld b,1 + call DSK_READ_MAIN_CONFIG_FILE + or a + ret z + ld a,1 + ret + + +; ----------------------------------------------------------------------------- +; DSK_UPDATE_CAPS_LIT_WK: Update work area flag for the CAPS lit on file +; access setting depending on the NOCAPS file existence +; ----------------------------------------------------------------------------- + +DSK_UPDATE_CAPS_LIT_WK: + push bc + call DSK_TEST_CAPS_LIT + rla + rla + rla + and 00001000b + ld b,a + call WK_GET_STORAGE_DEV_FLAGS + and 11110111b + or b + call WK_SET_STORAGE_DEV_FLAGS + pop bc + ret + + +; ----------------------------------------------------------------------------- +; DSK_TEST_CAPS_LIT_WK: Check if CAPS lite on file access is set +; by reading work area +; ----------------------------------------------------------------------------- +; Input: - +; Output: Z if unset, NZ if set + +DSK_TEST_CAPS_LIT_WK: + call WK_GET_STORAGE_DEV_FLAGS + and 00001000b + ret + + +; ----------------------------------------------------------------------------- +; DSK_INIT_WK_FOR_STORAGE_DEV: Initialize work area for a storage device +; ----------------------------------------------------------------------------- + +DSK_INIT_WK_FOR_STORAGE_DEV: + call WK_INIT_FOR_STORAGE_DEV + call DSK_UPDATE_CAPS_LIT_WK + ret diff --git a/msx/bank1/dskio_dskchg.asm b/msx/bank1/dskio_dskchg.asm index 403b10b..16e1821 100644 --- a/msx/bank1/dskio_dskchg.asm +++ b/msx/bank1/dskio_dskchg.asm @@ -393,6 +393,12 @@ WVDP: _DSKIO_IMPL_STDEV_SEEKOK: ld b,c + call DSK_TEST_CAPS_LIT_WK + jr nz,_DSKIO_IMPL_STDEV_GO_CAPS + pop af + jr _DSKIO_IMPL_STDEV_GO + +_DSKIO_IMPL_STDEV_GO_CAPS: pop af call CAPSON call _DSKIO_IMPL_STDEV_GO diff --git a/msx/bank1/misc.asm b/msx/bank1/misc.asm index 11fd074..2bea60c 100644 --- a/msx/bank1/misc.asm +++ b/msx/bank1/misc.asm @@ -663,7 +663,7 @@ CAPSOFF: ; ----------------------------------------------------------------------------- -; MYKILBUF: Empty yhe keyboard buffer (copy of BIOS routine KILBUF) +; MYKILBUF: Empty the keyboard buffer (copy of BIOS routine KILBUF) ; Modifies: HL ; ----------------------------------------------------------------------------- diff --git a/msx/bank1/usb.asm b/msx/bank1/usb.asm index 838e151..b976d53 100644 --- a/msx/bank1/usb.asm +++ b/msx/bank1/usb.asm @@ -58,7 +58,7 @@ _USB_CHECK_DEV_CHANGE_CHANGED: call HWF_MOUNT_DISK jr c,_USB_CHECK_DEV_CHANGE_NO_DEV - call WK_INIT_FOR_STORAGE_DEV + call DSK_INIT_WK_FOR_STORAGE_DEV ld a,1 call DSK_DO_BOOT_PROC or a diff --git a/msx/bank1/verbose_reset.asm b/msx/bank1/verbose_reset.asm index 05ef335..df165f3 100644 --- a/msx/bank1/verbose_reset.asm +++ b/msx/bank1/verbose_reset.asm @@ -50,7 +50,7 @@ _HW_RESET_PRINT_GO: call CHPUT jr _HW_RESET_PRINT _HW_RESET_PRINT_END: - call WK_INIT_FOR_STORAGE_DEV + call DSK_INIT_WK_FOR_STORAGE_DEV ret _HW_RESET_NO_STOR: diff --git a/msx/bank1/work_area.asm b/msx/bank1/work_area.asm index 556a328..d9b09d6 100644 --- a/msx/bank1/work_area.asm +++ b/msx/bank1/work_area.asm @@ -39,6 +39,7 @@ ; bit 0: set to 1 if there's a file mounted ; bit 1: set if mounted in read only mode ; bit 2: set if file has changed +; bit 3: set to enable CAPS lit on disk access ; +1: Current directory depth: ; 0: no directory currently open ; 1: root directory, etc From 8a2c9bbaf529859343cafe94b8ff456b84836989 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Sun, 30 May 2021 11:51:09 +0200 Subject: [PATCH 58/65] Add the CALL USBHELP command --- msx/bank0/oemstat.asm | 69 +++++++++++++++++++++++++++++++++++++++-- msx/bank1/boot_menu.asm | 3 +- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/msx/bank0/oemstat.asm b/msx/bank0/oemstat.asm index d5d3100..30609f2 100644 --- a/msx/bank0/oemstat.asm +++ b/msx/bank0/oemstat.asm @@ -64,13 +64,21 @@ OEM_COMMANDS: dw OEMC_USBRESET db "USBERROR2",0 dw OEMC_USBERROR + db "USBMENU2",0 + dw OEMC_USBMENU + db "USBCD2",0 + dw OEMC_USBCD + db "USBMOUNT2",0 + dw OEMC_USBMOUNT + db "USBMOUNTR2",0 + dw OEMC_USBMOUNTR + db "USBFILES2",0 + dw OEMC_USBFILES else db "USBRESET",0 dw OEMC_USBRESET db "USBERROR",0 dw OEMC_USBERROR - endif - db "USBMENU",0 dw OEMC_USBMENU db "USBCD",0 @@ -81,6 +89,63 @@ OEM_COMMANDS: dw OEMC_USBMOUNTR db "USBFILES",0 dw OEMC_USBFILES + endif + + db "USBHELP",0 + dw OEMC_USBHELP + db 0 + + ;--- CALL USBHELP + ; Show info on available CALL commands + +OEMC_USBHELP: + ld hl,OEM_S_HELP + call OEM_PRINT + jp OEM_END + +OEM_S_HELP: + ; ---------------------------------------- + if USE_ALTERNATIVE_PORTS=1 + db "_USBRESET2 - Re-initialize device",13,10 + db 13,10 + db "FDD device only:",13,10 + db "_USBERROR2 - Show last ASC/ASCQ err",13,10 + db 13,10 + db "Storage device only:",13,10 + db "_USBMENU2 - Show file navig menu",13,10 + db "_USBCD2 - Show current dir",13,10 + ;db"_USBCD2("dir/dir") - Change dir, rel",13,10 + db "_USBCD2(",34,"dir/dir",34,") - Change dir, rel",13,10 + ;db"_USBCD2("/dir/dir") - Change dir (abs)",13,10 + db "_USBCD2(",34,"/dir/dir",34,") - Change dir,abs",13,10 + db "_USBMOUNT2 - Show mounted file name",13,10 + ;db"_USBMOUNT2("file.ext") - Mount file",13,10 + db "_USBMOUNT2(",34,"file.ext",34,") - Mount file",13,10 + db "_USBMOUNT2(-1) - Unmount file",13,10 + db "_USBMOUNT2(0) - Mount default file",13,10 + db "_USBMOUNT2(n) - Mount nth file, 1-255",13,10 + db "_USBMOUNTR2(...) - Mount and reset",13,10 + else + db "_USBRESET - Re-initialize device",13,10 + db 13,10 + db "FDD device only:",13,10 + db "_USBERROR - Show last ASC/ASCQ error",13,10 + db 13,10 + db "Storage device only:",13,10 + db "_USBMENU - Show file navigation menu",13,10 + db "_USBCD - Show current dir",13,10 + ;db"_USBCD("dir/dir") - Change dir, rel",13,10 + db "_USBCD(",34,"dir/dir",34,") - Change dir, rel",13,10 + ;db"_USBCD("/dir/dir") - Change dir (abs)",13,10 + db "_USBCD(",34,"/dir/dir",34,") - Change dir, abs",13,10 + db "_USBMOUNT - Show mounted file name",13,10 + ;db"_USBMOUNT("file.ext") - Mount file",13,10 + db "_USBMOUNT(",34,"file.ext",34,") - Mount file",13,10 + db "_USBMOUNT(-1) - Unmount file",13,10 + db "_USBMOUNT(0) - Mount default file",13,10 + db "_USBMOUNT(n) - Mount nth file, 1-255",13,10 + db "_USBMOUNTR(...) - Mount and reset",13,10 + endif db 0 diff --git a/msx/bank1/boot_menu.asm b/msx/bank1/boot_menu.asm index 08299bb..1a1f6bd 100644 --- a/msx/bank1/boot_menu.asm +++ b/msx/bank1/boot_menu.asm @@ -1867,10 +1867,11 @@ BM_HELP_2: db " SHIFT+ESC: Set current dir and",13,10 db " exit without mounting",13,10 db 13,10 - db 13,10 db " TAB (while booting):",13,10 db " temporarily force boot mode 1",13,10 db 13,10 + db " CALL USBHELP / _USBHELP (in BASIC):",13,10 + db " show list of available CALL commands",13,10 db 13,10 db " After boot it is possible to switch",13,10 db " to another disk image file from the",13,10 From 0f419b6746c21720d3369b09f3bb495d8935d55c Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 3 Jun 2021 08:11:07 +0200 Subject: [PATCH 59/65] Add the DISK_IMAGE_MODE.md file. --- DISK_IMAGE_MODE.md | 158 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 10 ++- 2 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 DISK_IMAGE_MODE.md diff --git a/DISK_IMAGE_MODE.md b/DISK_IMAGE_MODE.md new file mode 100644 index 0000000..59cddd8 --- /dev/null +++ b/DISK_IMAGE_MODE.md @@ -0,0 +1,158 @@ +# Rookie Drive floppy disk controller ROM - disk image mode + +When a USB storage device is connected to the USB port of the Rookie Drive the ROM will switch to disk image mode. In this mode you are able to mount disk image files and work with them as if they were regular floppy disks: when you "mount" a disk image file, accessing the drive associated to the ROM will actually read or write the mounted file. + +Note that the storage device must hold a FAT12, FAT16 or FAT32 filesystem. Also, long filenames are not supported so all file and directory names will be handled as 8.3 names. + + +## The main directory + +First of all you need to know that the ROM will create some small files in the storage device for the purpose of storing configuration. These files will be stored inside a directory named `_USB` which is itself inside what the ROM considers the _main directory_ of the storage device. This main directory is a directory named `MSX` in the root directory of the storage if that directory exists; otherwise the main directory is just the root directory itself. + +If you plan to use a storage device exclusively with your MSX you may not want to create a `MSX` directory, otherwise creating it and putting all your disk image files (and ROM configuration) there is a clean way to have everything in one single place. If you decide to use a `MSX` directory, make sure to create it before you first plug the device in your Rookie Drive! (othersiwe you'll need to manually delete or move the `_USB` directory that the ROM will have created). + + +## The boot menu + +When your computer boots with a storage device plugged in, and unless configured otherwise, the ROM will present a "graphical" user interface (40 column text mode actually) with a list of the files and directories found in the _boot directory_ (the boot directory is the main directory unless configured otherwise). At this point you can press F1 to get help on the keys you can use to navigate the menu, but the basic ones are: + +- Use the cursor keys to select one file or directory. +- Press `Enter` when a directory is selected to enter it, press `BS` to go back to the parent directory. +- Press `Enter` when a file is selected to mount it and exit the menu (and then continue the computer boot process). +- Press `ESC` to exit the menu (and then continue the computer boot process) without mounting any file. + +Hidden files and directories, and those whose name starts with an underscore "`_`" character, won't be listed. + +The boot menu can also be invoked by executing `CALL USBMENU` from BASIC. + + +## The default file + +Each directory that is not empty has a _default file_. This is the file that will be mounted when you press `Shift+Enter` while the directory is selected, when you run the `CALL USBMOUNT(0)` command from BASIC, and when booting the computer in boot mode 3. + +The default file for a given directory is determined as follows: + +* It's the file whose name is stored in a `_USB/DEFFILE` file in the directory; or if that file doesn't exist... +* It's a file named `DEFAULT.DSK` in the directory; or if that file doesn't exist... +* It's the first file found in the directory. + +The default file for any directory can be set from the configuration menu. + + +## The boot mode + +The ROM supports four boot modes, that is, four different behaviors when the computer boots and a USB storage device is detected: + +1. Change to the boot directory and show the boot menu. +2. Change to the boot directory but don't show the boot menu and don't mount any file. +3. Change to the boot directory and mount the default file in that directory. +4. Mount the last file that has been mounted. + +The boot mode can be set from the configuration menu, being 1 the default mode when nothing has been configured. When booting in boot mode 4, if the file that was mounted the last time no longer exists then the ROM will revert to boot mode 3. + +Pressing the `TAB` key while booting will force the boot mode 1 temporarily, this is useful in boot modes 3 and 4 as an alternative to unplugging the device if you don't want the corresponding file to be mounted at boot time. + + +### Temporary boot mode 4 + +When mounting a file from the boot menu with `Ctrl+Enter` or from BASIC with the `CALL USBMOUNTR` command, the computer will be reset and the ROM will boot in "temporary boot mode 4". This means that the file that had been selected will be mounted at boot but only once, and in the next computer reset the configured boot mode will be restored. This is achieved by creating a temporary configuration file that is read and then deleted at boot time. + +By the way `Ctrl+Enter` works for directories too, in this case what will be mounted is the default file of the directory. + + +## The configuration menu + +Pressing F2 while in the boot menu will open the configuration directory, from here you can: + +* Set the boot mode. +* Set the boot directory (as the current directory). +* Set the default file for the current directory (as the file currently selected). +* Enable or disable the CAPS led litting when disk access is performed while a file is mounted. + +All of these settings are stored in configuration files and thus they are permanent (they remain after computer resets and poweroffs). + + +## Hot swap of disk images + +The mounted disk image can be changed via the boot menu and the `CALL USBMOUNT` command, but often you'll want a more dynamic mechanism, especially when playing multidisk games. The _hot swap_ mechanism allows to quickly mount a different disk image file from the same directory at the exact moment in which disk access is about to be performed. + +That's how it works: when the ROM is about to perform disk access (for example after a game says "change disk and press any key"), press the key corresponding to the numbers 1-9 or the letters A-Z, then the Nth disk image file found in the current directory (the directory of the currently mounted file) will be mounted right before the actual disk access happens. For example, press "1" to mount the first file, or "A" to mount the 10th file. Using this mechanism you can change between 35 different disk image files. + +Alternatively, you can press the `Code/Kana` key instead. Then the CAPS led will lit and the ROM will wait for you to press the appropriate 1-9 or A-Z key; or you can just press `Code/Kana` again if you change your mind. + +The files taken in account when using this mechanism are the same ones that are listed in the boot menu, this means that hidden files and files whose name starts with an underscore "`_`" character won't be counted. + + +## CALL commands reference + +There are a few `CALL` commands that allow you to control directories and disk images from BASIC. You'll get a quick summary if you execute `CALL USBHELP`, but here's the complete reference. + + +### CALL USBMENU + +Shows the boot menu as when it's displayed during the boot process (the only difference is that when pressing `Esc` it'll go back to BASIC instead of continuing the boot process). + + +### CALL USBCD + +Use this command to handle directories in the USB device. It supports these variants: + +* **CALL USBCD** - Simply print the current directory. +* **CALL USBCD("dir/dir")** - Change to the specified directory, relative to the current one. +* **CALL USBCD("/dir/dir")** - Change to the specified absolute directory. Note that the difference is an extra slash at the beginning of the specified directory chain. + +Changing the current directory will unmount the currently mounted file, this is due to a limitation on how the underlying USB controller hardware works. + +Note that an alternative way to change the current directory (without mounting any file) is to go to the boot menu, enter the desired directory, and then pressing `Shift+Esc` (`Esc` alone will restore the previous directory and mounted file). + + +### CALL USBFILES + +Use this command to list the disk images files and directories in the current directory, in a similar format as the DiskBASIC `FILES` command (but you can't specify wildcards, all the files will be listed). + + +### CALL USBMOUNT + +Use this command to mount disk image files. It supports these variants: + +* **CALL USBMOUNT** - Simply print the name of the currently mounted file. +* **CALL USBMOUNT("file.ext")** - Mount the specified file in the current directory. If you want to mount a file in a different directory, change to that directory first using `CALL USBCD`. +* **CALL USBMOUNT(-1)** - Unmount the currently mounted file. +* **CALL USBMOUNT(0)** - Mount the default file in the current directory. +* **CALL USBMOUNT(n)** - Mount the Nth file in the current directory (with "n" between 1 and 255). Hidden files and files whose name starts with an underscore "`_`" character don't count. + + +### CALL USBMOUNTR + +This command works the same way as `CALL USBMOUNT(...)`, but after a successful file mount the computer will be reset and the ROM will boot in mode 4 temporarily. + + +## Configuration files reference + +The configuration set via the configuration menu is stored in a set of files within the `_USB` directory in the main directory. Occasionally you may want to manipulate these files manually using another computer, so here's a reference of what these files are named and what are their contents. + +* **BOOTMODE**: This file contains one single ASCII character with the current boot mode, "1" to "4". If the file doesn't exist the default boot mode is 1. +* **BOOTDIR**: Contains the full path of the boot directory, using a slash "`/`" as directory separator, with no slashes at either end; for example "`MSX/GAMES`". If the file doesn't exist then the boot directory is the main directory. +* **CURDIR**: Contains the full path of the current directory, with the same format as `BOOTDIR`. If the file doesn't exist then the current directory is the main directory. +* **CURFILE**: Contains the name of the file currently mounted. The file doesn't exist when no file is mounted. +* **NOCAPS**: When this file exists and is not empty then the CAPS lit on disk access when a file is mounted is disabled. +* **TMP4**: If this file exists and is not empty then at the next computer boot the ROM will delete it and then it will boot in mode 4. +* **DEFFILE**: Contains the name of the default file for the directory. This file is special in that it can exist not only in the `_USB` directory of the main directory, but also in the `_USB` directory of any other directory. + +File and directory names must be stored in uppercase and in 8.3 format. + +The `CURDIR` and `CURFILE` files are the ones that the ROM reads in order to determine which file is to be mounted when booting in mode 4. + +The ROM will treat CR (ASCII 13) and LF (ASCII 10) characters found in configuration files as an end of file mark, keep this in mind if you manipulate these files by hand. + + +## Other features + +A disk image file will be mounted as read-only if it has the read-only attribute set. + + +## Limitations + +The ROM doesn't currently provide any way to create, delete, rename, move, change attributes, or otherwise manipulate the directories and disk image files on the storage device from within the MSX itself; you'll have to do that from other USB-capable computer (you can, of course, write to mounted disk image files using the regular MSX-DOS/DiskBASIC functions). These missing bits might be added in a future version of the ROM. + +The files and directories are always listed (in the boot menu and with `CALL USBFILES`) in the order in which their directory entries are physically located in the device, if you want to see them in alphabetical order you'll have to use a tool to permanently reorder them from within another computer. diff --git a/README.md b/README.md index 84b41dd..9ca7507 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ This project implements a standard MSX-DOS 1 DiskROM that allows using standard USB floppy disk drives, thus effectively turning Rookie Drive into an "old-school" MSX floppy disk controller with a few extra perks. A few variants are offered that differ in behavior as explained below. +Since version 2.0 this ROM also supports working with disk image files contained in standard USB storage devices such as pendrives or SD card readers. The "disk image mode" will activate automatically whenever a standard USB storage device is connected to the USB port; if a floppy disk drive is connected then the "floppy disk mode" (the only mode available in older versions of the ROM) will activate instead. See [the documentation about the disk image mode](DISK_IMAGE_MODE.md) for details. + ## Compiling To compile this ROM you can use [Sjasm](https://github.com/Konamiman/sjasm). Adjust the configuration flags as desired in [the config.asm file](/msx/config.asm) and run: @@ -18,7 +20,7 @@ This ROM adds a few extra features to what a standard DiskROM offers, some of th ### Hot-plug support -Although the ROM will detect and initialize the FDD at boot time, you can also plug it later if you want and it will be usable immediately. You can even unplug the device, plug it again (or even plug a different one!) and everything will continue working. +Although the ROM will detect and initialize the FDD or storage device at boot time, you can also plug it later if you want and it will be usable immediately. You can even unplug the device, plug it again (or even plug a different one!) and everything will continue working. ### SHIFT key @@ -36,7 +38,7 @@ If you plan to use this DiskROM primarily to load games, the recommended variant ### Quick format -Additionally to the usual full formatting, the `(CALL) FORMAT` command offers quick formatting option. This one skips the physical formatting and only initializes the boot sector, FAT and root directory of the disk. +Additionally to the usual full formatting, the `(CALL) FORMAT` command offers quick formatting option. This one skips the physical formatting and only initializes the boot sector, FAT and root directory of the disk. Currently the `(CALL) FORMAT` command works on floppy disk drives only (it won't work with disk images). ### 1.44M disks support @@ -57,6 +59,8 @@ If the error happened at the USB physical or protocol level, you will see it as ASC: 3Ah ASCQ: 00h +Currently the `CALL USBERROR` command will work only when a floppy disk drive is connected. + ### The panic button Executing USB transactions involves sending a command to the USB host controller hardware and waiting for it to notify completion (or error) with an interrupt. Under normal circumstances this always happens, but if for some reason it doesn't, the computer will hang waiting forever for this interrupt. @@ -71,7 +75,7 @@ Rookie Drive usually uses ports 20h and 21h to communicate with the USB host con It is possible to adapt this project to work with hardware other than Rookie Drive. Such hardware should have at least 32K of mapped ROM in page 1, and of course, some kind of USB host controller. -Regarding the USB host controller, all the code that is specific to the CH376 lives in [the ch376.asm file](/msx/bank1/ch376.asm), you will need to create a new file that implements the same "public" routines but adapted to the new controller. Look at the header of that file for detailed instructions. +Regarding the USB host controller, all the code that is specific to the CH376 lives in [the ch376.asm file](/msx/bank1/ch376.asm), you will need to create a new file that implements the same "public" routines but adapted to the new controller. Look at the header of that file for detailed instructions. (Since version 2.0 this file also contains some routines that are specific for handling FAT filesystems, these are the ones whose names are prefixed with `HWF_`). As for the ROM mapper implemented by your hardware, if it's DOS 2/ASCII16 you don't need to change anything else from the existing code. If it's ASCII8, set the `USE_ASCII8_ROM_MAPPER` flag in [the config.asm file](/msx/config.asm) to 1. For any other mapping mechanism you will need to manually change the code, search for usages of the `ROM_BANK_SWITCH` constant for guidance. From 062c932ccdb93092247b7e24c4ae802a650baf7a Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 3 Jun 2021 08:33:44 +0200 Subject: [PATCH 60/65] Add USBFILES to the USBHELP command --- msx/bank0/oemstat.asm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/msx/bank0/oemstat.asm b/msx/bank0/oemstat.asm index 30609f2..8a4a4ef 100644 --- a/msx/bank0/oemstat.asm +++ b/msx/bank0/oemstat.asm @@ -118,6 +118,7 @@ OEM_S_HELP: db "_USBCD2(",34,"dir/dir",34,") - Change dir, rel",13,10 ;db"_USBCD2("/dir/dir") - Change dir (abs)",13,10 db "_USBCD2(",34,"/dir/dir",34,") - Change dir,abs",13,10 + db "_USBFILES2 - List files in curr dir",13,10 db "_USBMOUNT2 - Show mounted file name",13,10 ;db"_USBMOUNT2("file.ext") - Mount file",13,10 db "_USBMOUNT2(",34,"file.ext",34,") - Mount file",13,10 @@ -138,6 +139,7 @@ OEM_S_HELP: db "_USBCD(",34,"dir/dir",34,") - Change dir, rel",13,10 ;db"_USBCD("/dir/dir") - Change dir (abs)",13,10 db "_USBCD(",34,"/dir/dir",34,") - Change dir, abs",13,10 + db "_USBFILES - List files in curr dir",13,10 db "_USBMOUNT - Show mounted file name",13,10 ;db"_USBMOUNT("file.ext") - Mount file",13,10 db "_USBMOUNT(",34,"file.ext",34,") - Mount file",13,10 From fa116524af3090ba1bfbfda466681cd1e37f2105 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 3 Jun 2021 08:34:40 +0200 Subject: [PATCH 61/65] Improvements in filed/dir enumeration - Ignore files starting with "_", not those not starting with letter or digit - Ignore "System" and "Volume" dir entries too (this includes long filename entries) --- DISK_IMAGE_MODE.md | 4 ++-- msx/bank1/ch376.asm | 12 ++++++------ msx/bank1/misc.asm | 22 ---------------------- 3 files changed, 8 insertions(+), 30 deletions(-) diff --git a/DISK_IMAGE_MODE.md b/DISK_IMAGE_MODE.md index 59cddd8..6ec27b8 100644 --- a/DISK_IMAGE_MODE.md +++ b/DISK_IMAGE_MODE.md @@ -28,7 +28,7 @@ The boot menu can also be invoked by executing `CALL USBMENU` from BASIC. ## The default file -Each directory that is not empty has a _default file_. This is the file that will be mounted when you press `Shift+Enter` while the directory is selected, when you run the `CALL USBMOUNT(0)` command from BASIC, and when booting the computer in boot mode 3. +Each directory that is not empty has a _default file_. This is the file that will be mounted when you press `Shift+Enter` while the directory is selected in the boot menu, when you run the `CALL USBMOUNT(0)` command from BASIC, and when booting the computer in boot mode 3. The default file for a given directory is determined as follows: @@ -153,6 +153,6 @@ A disk image file will be mounted as read-only if it has the read-only attribute ## Limitations -The ROM doesn't currently provide any way to create, delete, rename, move, change attributes, or otherwise manipulate the directories and disk image files on the storage device from within the MSX itself; you'll have to do that from other USB-capable computer (you can, of course, write to mounted disk image files using the regular MSX-DOS/DiskBASIC functions). These missing bits might be added in a future version of the ROM. +The ROM doesn't currently provide any way to create, delete, rename, move, change attributes, or otherwise manipulate the directories and disk image files on the storage device from within the MSX itself; you'll have to do that from another USB-capable computer (you can, of course, write to mounted disk image files using the regular MSX-DOS/DiskBASIC functions). These missing bits might be added in a future version of the ROM. The files and directories are always listed (in the boot menu and with `CALL USBFILES`) in the order in which their directory entries are physically located in the device, if you want to see them in alphabetical order you'll have to use a tool to permanently reorder them from within another computer. diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index 06f23d8..89c8dd7 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -754,8 +754,7 @@ HWF_DELETE_FILE: ; ----------------------------------------------------------------------------- ; HWF_ENUM_FILES: Enumerate files and directories in the current directory ; -; Files/directories whose first character is not a letter or a digit -; will be skipped. +; Files/directories whose first character is "_" will be skipped. ; ; The name of each files/directory will be put at the specified address, ; sequentially and with no separators, as a fixed 11 bytes string in the @@ -871,7 +870,7 @@ Num2: ; ----------------------------------------------------------------------------- ; HWF_FIND_NTH_FILE: Find the Nth file in the current directory ; -; Files whose first character is not a letter or a digit will be skipped. +; Files whose first character is "_" will be skipped. ; ; The name of the files will be put at the specified address, ; sequentially and with no separators, as a fixed 11 bytes string in the @@ -933,15 +932,16 @@ _HWF_ENUM_FILES_LOOP: pop bc ld a,(hl) - call IS_DIGIT_OR_LETTER - jr nc,_HWF_ENUM_DIR_NEXT + cp "_" + jr z,_HWF_ENUM_DIR_NEXT push bc ld bc,11 add hl,bc ;Point to file attributes byte pop bc - bit 1,(hl) ;"Hidden" attribute set? + ld a,(hl) + and 1110b ;"Hidden", "System" or "Volume" attribute set? jr nz,_HWF_ENUM_SKIP ld a,iyl or a diff --git a/msx/bank1/misc.asm b/msx/bank1/misc.asm index 2bea60c..fe9b328 100644 --- a/msx/bank1/misc.asm +++ b/msx/bank1/misc.asm @@ -237,28 +237,6 @@ B2A_2XX: ld (ix),"2" jr B2A_XXX -; ----------------------------------------------------------------------------- -; IS_DIGIT_OR_LETTER: Check if a char is a digit or a letter -; ----------------------------------------------------------------------------- -; Input: A = Char to check -; Output: Cy=1 if it's a char or a letter (A-Z), 0 otherwise -; Modifies: AF -; ----------------------------------------------------------------------------- - -IS_DIGIT_OR_LETTER: - cp '0' - ccf - ret nc - cp '9'+1 - ret c - - cp 'Z'+1 - ret nc - cp 'A' - ccf - ret - - ; ; Divide 16-bit values (with 16-bit result) ; In: Divide BC by divider DE From 9c88daa58d03b11916cf6b698be44b0e53e60e32 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 3 Jun 2021 15:25:02 +0200 Subject: [PATCH 62/65] Remove prerelease notice --- msx/bank1/verbose_reset.asm | 1 - 1 file changed, 1 deletion(-) diff --git a/msx/bank1/verbose_reset.asm b/msx/bank1/verbose_reset.asm index df165f3..4ada676 100644 --- a/msx/bank1/verbose_reset.asm +++ b/msx/bank1/verbose_reset.asm @@ -258,7 +258,6 @@ PRINT_ERROR: ROOKIE_S: db "Rookie Drive NestorBIOS v2.0",13,10 - db "Prerelease version 2021.03.12",13,10 db "(c) Konamiman 2018,2021",13,10 db 13,10 db "Initializing device...",13 From 9ad4a8fc4ca3f37590b5bdb66e57f5350ef2aa1e Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Wed, 9 Jun 2021 15:37:18 +0200 Subject: [PATCH 63/65] Fix:'.' and '..' entries showing up in the boot menu. --- msx/bank1/ch376.asm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/msx/bank1/ch376.asm b/msx/bank1/ch376.asm index 89c8dd7..70c764b 100644 --- a/msx/bank1/ch376.asm +++ b/msx/bank1/ch376.asm @@ -934,6 +934,8 @@ _HWF_ENUM_FILES_LOOP: ld a,(hl) cp "_" jr z,_HWF_ENUM_DIR_NEXT + cp "." ;Skip "." and ".." entries + jr z,_HWF_ENUM_DIR_NEXT push bc ld bc,11 From 4ffd2794e8938dcda84a7c312d786299e7446f6e Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Wed, 30 Jun 2021 15:38:09 +0200 Subject: [PATCH 64/65] Small leftover code fixes --- msx/.gitignore | 3 ++- msx/bank1/inihrd_inienv.asm | 10 ---------- msx/config.asm | 2 +- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/msx/.gitignore b/msx/.gitignore index 9368e1e..cc37949 100644 --- a/msx/.gitignore +++ b/msx/.gitignore @@ -1,5 +1,6 @@ sandbox/ +.vscode/ *.lst *.out *.rom -.sym +*.sym diff --git a/msx/bank1/inihrd_inienv.asm b/msx/bank1/inihrd_inienv.asm index de3962a..648af4e 100644 --- a/msx/bank1/inihrd_inienv.asm +++ b/msx/bank1/inihrd_inienv.asm @@ -53,13 +53,3 @@ DELAY_AFTER_PRINT: ret z xor a jp DSK_DO_BOOT_PROC - - ret - - - call WK_INIT_FOR_STORAGE_DEV - xor a - call WK_SET_LAST_REL_DRIVE - - call DO_BOOT_MENU - ret diff --git a/msx/config.asm b/msx/config.asm index a84b094..149ddbf 100644 --- a/msx/config.asm +++ b/msx/config.asm @@ -39,7 +39,7 @@ USE_ALTERNATIVE_PORTS: equ 0 ;Enable this if you are Konamiman and you are using NestorMSX with ;the almigthy Arduino board that Xavirompe sent you -USING_ARDUINO_BOARD: equ 1 +USING_ARDUINO_BOARD: equ 0 ;Enable to debug DSKIO calls: whenever DSKIO is called, text mode is enabled, ;the input parameters are printed, and system stops waiting for a key press From 2d8112367edee6247c9416a27ddeec33771370b9 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Wed, 30 Jun 2021 15:38:51 +0200 Subject: [PATCH 65/65] Commit sandbox code used during development --- arduino/Noobtocol/.gitignore | 2 + dotNet/NestorMsxPlugin/RookieDrivePorts.cs | 24 +++- dotNet/Sandbox/Program.cs | 45 +++++--- dotNet/Usb/CH376UsbHostHardware.cs | 123 ++++++++++++++++++--- 4 files changed, 155 insertions(+), 39 deletions(-) diff --git a/arduino/Noobtocol/.gitignore b/arduino/Noobtocol/.gitignore index da4560a..e796024 100644 --- a/arduino/Noobtocol/.gitignore +++ b/arduino/Noobtocol/.gitignore @@ -1,5 +1,7 @@ __vm/ .vs/ +.vscode/ +build/ *.user *.filters *.elf diff --git a/dotNet/NestorMsxPlugin/RookieDrivePorts.cs b/dotNet/NestorMsxPlugin/RookieDrivePorts.cs index b1dea02..ac852e3 100644 --- a/dotNet/NestorMsxPlugin/RookieDrivePorts.cs +++ b/dotNet/NestorMsxPlugin/RookieDrivePorts.cs @@ -16,6 +16,7 @@ public class RookieDrivePortsPlugin const byte CMD_RD_USB_DATA0 = 0x27; const byte CMD_WR_HOST_DATA = 0x2C; + private byte aaPortValue = 0; private readonly ICH376Ports chPorts; private byte[] multiDataTransferBuffer; public int multiDataTransferPointer; @@ -106,12 +107,12 @@ private void Cpu_BeforeInstructionFetch(object sender, BeforeInstructionFetchEve private void Cpu_MemoryAccess(object sender, MemoryAccessEventArgs e) { - if(e.Address == 0x20) + if (e.Address == 0x20) { if (e.EventType == MemoryAccessEventType.BeforePortRead) { e.CancelMemoryAccess = true; - if(waitingMultiDataTransferLength) + if (waitingMultiDataTransferLength) { waitingMultiDataTransferLength = false; e.Value = chPorts.ReadData(); @@ -148,7 +149,7 @@ private void Cpu_MemoryAccess(object sender, MemoryAccessEventArgs e) multiDataTransferBuffer[multiDataTransferPointer] = e.Value; multiDataTransferPointer++; multiDataTransferRemaining--; - if(multiDataTransferRemaining == 0) + if (multiDataTransferRemaining == 0) chPorts.WriteMultipleData(multiDataTransferBuffer); } else @@ -173,7 +174,22 @@ private void Cpu_MemoryAccess(object sender, MemoryAccessEventArgs e) waitingMultiDataTransferLength = true; } } - + else if (e.Address == 0xAA) { + if (e.EventType == MemoryAccessEventType.AfterPortWrite) + { + var wasOn = (aaPortValue & 0x40) == 0; + var on = (e.Value & 0x40) == 0; + if (on != wasOn) + { + Debug.WriteLine("CAPS " + (on ? "ON" : "OFF")); + } + aaPortValue = e.Value; + } + else if(e.EventType == MemoryAccessEventType.AfterPortRead) + { + e.Value = aaPortValue; + } + } } } } diff --git a/dotNet/Sandbox/Program.cs b/dotNet/Sandbox/Program.cs index 988c3ec..b9dbde4 100644 --- a/dotNet/Sandbox/Program.cs +++ b/dotNet/Sandbox/Program.cs @@ -12,6 +12,12 @@ class Program static void Main(string[] args) { + var port = args.Length == 0 ? "COM5" : args[0]; + var ch = new CH376PortsViaNoobtocol(port); + var hw = new CH372DeviceHardware(ch); + hw.HardwareReset(); + return; + try { Console.SetWindowSize(Console.WindowWidth, Console.WindowHeight + 10); @@ -43,9 +49,10 @@ static void _Main(string[] args) Console.WriteLine($"Filesystem: {diskTypeAndCapacity.filesystem}"); Console.WriteLine(); + string[] files; hw.InitFilesystem(); - var files = hw.EnumerateFiles("/"); - if(files.Length == 0) + files = hw.EnumerateFiles("/"); + if (files.Length == 0) { Console.WriteLine("*** No files found"); } @@ -56,25 +63,27 @@ static void _Main(string[] args) Console.WriteLine(name); Console.WriteLine(); - Console.WriteLine("Files found in DSK:"); - files = hw.EnumerateFiles("DSK"); - foreach (var name in files) - Console.WriteLine(name); + } - Console.WriteLine("Writing file... " + hw.WriteFileContents("NBASIC.TXT", longString)); - Console.WriteLine(); + Console.WriteLine("Files found in DSK:"); + files = hw.EnumerateFiles("/DSK"); + foreach (var name in files) + Console.WriteLine(name); - Console.WriteLine(); - if (!hw.ChangeDir("/DSK")) - { - Console.WriteLine("*** Can't change to dir DSK"); - } - else - { - Console.WriteLine("Contents of DSK/NBASIC.TXT:"); - Console.Write(hw.ReadFileContents("NBASIC.TXT")); - } + Console.WriteLine("Writing file... " + hw.WriteFileContents("NBASICX.TXT", longString)); + Console.WriteLine(); + + Console.WriteLine(); + if (!hw.ChangeDir("/DSK")) + { + Console.WriteLine("*** Can't change to dir DSK"); } + else + { + Console.WriteLine("Contents of DSK/NBASIC.TXT:"); + Console.Write(hw.ReadFileContents("NBASIC.TXT")); + } + Console.ReadKey(); return; diff --git a/dotNet/Usb/CH376UsbHostHardware.cs b/dotNet/Usb/CH376UsbHostHardware.cs index d85b539..84f92e0 100644 --- a/dotNet/Usb/CH376UsbHostHardware.cs +++ b/dotNet/Usb/CH376UsbHostHardware.cs @@ -30,6 +30,11 @@ public class CH376UsbHostHardware : IUsbHostHardware, IUsbHardwareShortcuts const byte CMD_RET_SUCCESS = 0x51; const byte CMD_RET_ABORT = 0x5F; + const byte CMD_GET_IC_VER = 0x01; + const byte CMD_READ_VAR8 = 0x0A; + const byte CMD_WRITE_VAR8 = 0x0B; + const byte CMD_READ_VAR32 = 0x0C; + const byte CMD_WRITE_VAR32 = 0x0D; const byte CMD_TEST_CONNECT = 0x16; const byte CMD_DISK_CONNECT = 0x30; const byte CMD_DISK_MOUNT = 0x31; @@ -371,6 +376,25 @@ public string InitDisk() public object GetDiskTypeAndCapacity() { + byte d; + ch.WriteCommand(CMD_GET_IC_VER); + d = ch.ReadData(); + if (d < 0x43) + { + // This is supposed to be a fix for bad handling of FAT32 + // columes in older versions of the chip + ch.WriteCommand(CMD_READ_VAR8); + ch.WriteData(0x28); //VAR_DISK_STATUS + d = ch.ReadData(); + if (d >= 0x10) //DEF_DISK_READY + { + ch.WriteCommand(CMD_WRITE_VAR8); + ch.WriteData(0x28); + ch.WriteData(3); //DEF_DISK_MOUNTED + } + } + + ch.WriteCommand(CMD_DISK_QUERY); var result = WaitAndGetResult(); if (result != UsbPacketResult.Ok) @@ -396,25 +420,41 @@ public object GetDiskTypeAndCapacity() public void InitFilesystem() { + return; + FixSetFilename(); ch.WriteCommand(CMD_SET_FILE_NAME); ch.WriteData(0); ch.WriteCommand(CMD_FILE_OPEN); } - public string[] EnumerateFiles(string searchPath = "/") + private UsbPacketResult DoFileOpen(string name) { + FixSetFilename(); ch.WriteCommand(CMD_SET_FILE_NAME); - ch.WriteMultipleData(Encoding.ASCII.GetBytes(searchPath + "\0")); + ch.WriteMultipleData(Encoding.ASCII.GetBytes(name + "\0")); + + if (name[0] == '/') + { + ch.WriteCommand(CMD_WRITE_VAR32); + ch.WriteData(0x64); //VAR_CURRENT_CLUST + ch.WriteData(0); + ch.WriteData(0); + ch.WriteData(0); + ch.WriteData(0); + } + ch.WriteCommand(CMD_FILE_OPEN); - var result = WaitAndGetResult(); + return WaitAndGetResult(); + } + + public string[] EnumerateFiles(string searchPath = "/") + { + var result = DoFileOpen(searchPath); if (result != UsbPacketResult.ERR_OPEN_DIR) return new[] { $"*** Error opening directory: {result}" }; - ch.WriteCommand(CMD_SET_FILE_NAME); - ch.WriteMultipleData(Encoding.ASCII.GetBytes("*\0")); - ch.WriteCommand(CMD_FILE_OPEN); + result = DoFileOpen("*"); - result = WaitAndGetResult(); var data = new byte[32]; var names = new List(); while (result == UsbPacketResult.USB_INT_DISK_READ) @@ -443,10 +483,7 @@ public string ReadFileContents(string filename) UsbPacketResult result; var data = new byte[65535]; - ch.WriteCommand(CMD_SET_FILE_NAME); - ch.WriteMultipleData(Encoding.ASCII.GetBytes(filename + "\0")); - ch.WriteCommand(CMD_FILE_OPEN); - result = WaitAndGetResult(); + result = DoFileOpen(filename); if (result != UsbPacketResult.Ok) return "*** Error opening file: " + result.ToString(); @@ -478,10 +515,7 @@ public string WriteFileContents(string filename, string contents) { UsbPacketResult result; - ch.WriteCommand(CMD_SET_FILE_NAME); - ch.WriteMultipleData(Encoding.ASCII.GetBytes(filename + "\0")); - ch.WriteCommand(CMD_FILE_OPEN); - result = WaitAndGetResult(); + result = DoFileOpen(filename); if(result == UsbPacketResult.ERR_MISS_FILE) { Console.WriteLine(">>> File doesn't exist, creating"); @@ -531,16 +565,71 @@ public string WriteFileContents(string filename, string contents) return "*** Error updating file dir entry after write: " + result.ToString(); } + ch.WriteCommand(CMD_FILE_CLOSE); + ch.WriteData(1); + WaitAndGetResult(); return ">>> Write ok!"; } public bool ChangeDir(string dir) { + var result = DoFileOpen(dir); + return result == UsbPacketResult.ERR_OPEN_DIR; + } + + private void FixSetFilename() + { + /*ch.WriteCommand(CMD_FILE_CLOSE); + ch.WriteData(0); + WaitAndGetResult();*/ + + byte d; + ch.WriteCommand(CMD_GET_IC_VER); + d = ch.ReadData(); + if (d >= 0x43) + return; + + ch.WriteCommand(CMD_READ_VAR8); + ch.WriteData(0x2B); //VAR_DISK_STATUS + d = ch.ReadData(); + if (d >= 0x10) //DEF_DISK_READY + return; + ch.WriteCommand(CMD_SET_FILE_NAME); - ch.WriteMultipleData(Encoding.ASCII.GetBytes(dir + "\0")); + ch.WriteData(0); ch.WriteCommand(CMD_FILE_OPEN); var result = WaitAndGetResult(); - return result == UsbPacketResult.ERR_OPEN_DIR; + if (result != UsbPacketResult.Ok) + return; + + ch.WriteCommand(CMD_READ_VAR8); + ch.WriteData(0xCF); + d = ch.ReadData(); + if (d == 0) + return; + + WriteFix(0x4C, d); + WriteFix(0x50, d); + ch.WriteCommand(CMD_WRITE_VAR32); + ch.WriteData(0x70); + ch.WriteData(0); + ch.WriteData(0); + ch.WriteData(0); + ch.WriteData(0); + } + + private void WriteFix(byte address, byte value) + { + ch.WriteCommand(CMD_READ_VAR32); + ch.WriteData(address); + uint value32 = (uint)(ch.ReadData() + ch.ReadData() << 8 + ch.ReadData() << 16 + ch.ReadData() << 24); + value32 += (uint)(value << 8); + ch.WriteCommand(CMD_WRITE_VAR32); + ch.WriteData(address); + ch.WriteData((byte)(value32 & 0xFF)); + ch.WriteData((byte)((value32 >> 8) & 0xFF)); + ch.WriteData((byte)((value32 >> 16) & 0xFF)); + ch.WriteData((byte)((value32 >> 24) & 0xFF)); } } }