private Scheduler.Task task;// = new TaskSC(this); public RTC(X8086 cpu, InterruptRequest irq) { task = new TaskSC(this); this.irq = irq; for (int i = 0x70; i <= 0x71; i++) { ValidPortAddress.Add((uint)i); } for (int i = 0x240; i <= 0x24F; i++) { ValidPortAddress.Add((uint)i); } // FIXME: Although this works, when pausing the emulation causes the internal timers to get out of sync: // The contents at 46C no longer reflect what's returned by INT 1A, 02 // So the x8086.Resume method should perform a re-sync setting the new tick values into 46C. // It also appears that the x8086.Resume method should also advance the time... cpu.TryAttachHook((byte)(0x8), new X8086.IntHandler(() => { uint ticks = (uint)((DateTime.Now - new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0)).Ticks / 10000000 * 18.206); //cpu.RAM16[0x40, 0x6E] = (ticks >> 16) & 0xFFFF; //cpu.RAM16[0x40, 0x6C] = ticks & 0xFFFF; //cpu.RAM8[0x40, 0x70] = 0; cpu.set_RAM16(0x40, 0x6E, 0x0, false, (ushort)((long)(ticks >> 16) & 0xFFFF)); cpu.set_RAM16(0x40, 0x6C, 0x0, false, (ushort)((long)(ticks) & 0xFFFF)); cpu.set_RAM8(0x40, 0x70, 0x0, false, 0x00); cpu.TryDetachHook(0x8); return(false); })); cpu.TryAttachHook((byte)(0x1A), new X8086.IntHandler(() => { switch (cpu.Registers.AH) { case 0x2: // Read real time clock time cpu.Registers.CH = (byte)ToBCD((ushort)DateTime.Now.Hour); cpu.Registers.CL = (byte)ToBCD((ushort)DateTime.Now.Minute); cpu.Registers.DH = (byte)ToBCD((ushort)DateTime.Now.Second); cpu.Registers.DL = 0; cpu.Flags.CF = 0; return(true); case 0x4: // Read real time clock date cpu.Registers.CH = (byte)ToBCD((ushort)(DateTime.Now.Year / 100)); cpu.Registers.CL = (byte)ToBCD((ushort)DateTime.Now.Year); cpu.Registers.DH = (byte)ToBCD((ushort)DateTime.Now.Month); cpu.Registers.DL = (byte)ToBCD((ushort)DateTime.Now.Day); cpu.Flags.CF = 0; return(true); default: return(false); } })); }