Skip to content

Commit 3293c32

Browse files
committed
Add interrupt handler 21h 57h
- Add GetSetFileDateAndTime method - Add DateTimeFormDosDateAndTime method - Setup int 21h 57h to call GetSetFileDateAndTime method
1 parent 6fdee16 commit 3293c32

1 file changed

Lines changed: 74 additions & 1 deletion

File tree

src/Spice86.Core/Emulator/InterruptHandlers/Dos/DosInt21Handler.cs

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,16 +176,17 @@ private void FillDispatchTable() {
176176
AddAction(0x47, () => GetCurrentDirectory(true));
177177
AddAction(0x48, () => AllocateMemoryBlock(true));
178178
AddAction(0x49, () => FreeMemoryBlock(true));
179-
AddAction(0x50, () => SetCurrentPsp());
180179
AddAction(0x4A, () => ModifyMemoryBlock(true));
181180
AddAction(0x4B, () => LoadAndOrExecute(true));
182181
AddAction(0x4C, QuitWithExitCode);
183182
AddAction(0x4D, GetReturnCode);
184183
AddAction(0x4E, () => FindFirstMatchingFile(true));
185184
AddAction(0x4F, () => FindNextMatchingFile(true));
185+
AddAction(0x50, () => SetCurrentPsp());
186186
AddAction(0x51, GetPspAddress);
187187
AddAction(0x52, GetListOfLists);
188188
AddAction(0x55, CreateChildPsp);
189+
AddAction(0x57, () => GetSetFileDateAndTime(true));
189190
AddAction(0x58, () => AllocationStrategyOrUpperMemoryLinkState(true));
190191
AddAction(0x62, GetPspAddress);
191192
AddAction(0x63, GetLeadByteTable);
@@ -1951,6 +1952,78 @@ public void GetSetFileAttributes(bool calledFromVm) {
19511952
}
19521953
}
19531954

1955+
/// <summary>
1956+
/// Gets (AL: 0) or sets (AL: 1) file attributes for the file identified via its file path at DS:DX.
1957+
/// TODO: The Set File Attributes operation is not implemented.
1958+
/// </summary>
1959+
/// <returns>
1960+
/// CF is cleared on success. <br/>
1961+
/// CF is set on error. Possible error code in AX: 0x2 (File not found). <br/>
1962+
/// TODO: Always returns that the file is read / write in Get File Attributes mode.
1963+
/// </returns>
1964+
/// <exception cref="UnhandledOperationException">When the operation in the AL Register is not supported.</exception>
1965+
/// <param name="calledFromVm">Whether this was called from internal emulator code.</param>
1966+
public void GetSetFileDateAndTime(bool calledFromVm) {
1967+
byte op = State.AL;
1968+
string dosFileName = _dosStringDecoder.GetZeroTerminatedStringAtDsDx();
1969+
string? fileName = _dosFileManager.TryGetFullHostPathFromDos(dosFileName);
1970+
if (!File.Exists(fileName)) {
1971+
LogDosError(calledFromVm);
1972+
SetCarryFlag(true, calledFromVm);
1973+
// invalid handle
1974+
State.AX = 0x6;
1975+
return;
1976+
}
1977+
switch (op) {
1978+
case 0: {
1979+
if (LoggerService.IsEnabled(LogEventLevel.Verbose)) {
1980+
LoggerService.Verbose("GET FILE DATETIME {FileName}", fileName);
1981+
}
1982+
DateTime dateTime = File.GetLastAccessTime(fileName);
1983+
State.CX = DosFileManager.ToDosTime(dateTime);
1984+
State.DX = DosFileManager.ToDosDate(dateTime);
1985+
SetCarryFlag(false, calledFromVm);
1986+
break;
1987+
}
1988+
case 1: {
1989+
ushort dosFileTime = State.CX;
1990+
ushort dosFileDate = State.DX;
1991+
if (LoggerService.IsEnabled(LogEventLevel.Verbose)) {
1992+
LoggerService.Verbose("SET FILE DATETIME {FileName}, {FileTime}, {FileDate}",
1993+
fileName, dosFileDate, dosFileTime);
1994+
}
1995+
DateTime fileDateTime = DateTimeFormDosDateAndTime(dosFileTime, dosFileDate);
1996+
File.SetLastAccessTime(fileName, fileDateTime);
1997+
SetCarryFlag(false, calledFromVm);
1998+
break;
1999+
}
2000+
default: {
2001+
// throw new UnhandledOperationException(State, "getSetFileDateTime operation unhandled: " + op);
2002+
SetCarryFlag(true, calledFromVm);
2003+
// function number invalid
2004+
State.AX = 0x1;
2005+
break;
2006+
}
2007+
}
2008+
}
2009+
2010+
/// <summary>
2011+
/// Converts DOS Date and Time to DateTime
2012+
/// DOS date format: bits 15-9=year-1980, bits 8-5=month, bits 4-0=day.
2013+
/// DOS time format: bits 15-11=hour, bits 10-5=minute, bits 4-0=seconds/2.
2014+
/// </summary>
2015+
public static DateTime DateTimeFormDosDateAndTime(ushort dosDate, ushort dosTime) {
2016+
int day = (dosDate >> 0) & 0b11111;
2017+
int month = (dosDate >> 5) & 0b1111;
2018+
int year = (dosDate >> 9) & 0b1111111 + 1980;
2019+
2020+
int seconds = (dosTime >> 0) & 0b11111 * 2;
2021+
int minutes = (dosTime >> 5) & 0b111111;
2022+
int hours = (dosTime >> 11) & 0b11111;
2023+
2024+
return new DateTime(year, month, day, hours, minutes, seconds);
2025+
}
2026+
19542027
/// <summary>
19552028
/// Gets the FCB linear address from DS:DX.
19562029
/// </summary>

0 commit comments

Comments
 (0)