Imports x8086NetEmu

Public Class FormEmulator
    Private cpu As x8086
    Private cpuState As EmulatorState

    Private fMonitor As FormMonitor
    Private fConsole As FormConsole

    Private Sub frmMain_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        SaveSettings()

        If fMonitor IsNot Nothing Then fMonitor.Close()
        If fConsole IsNot Nothing Then fConsole.Close()

        cpu.Close()
    End Sub

    Private Sub frmMain_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        AddHandler MonitorToolStripMenuItem.Click, Sub() ShowMonitor()
        AddHandler ConsoleToolStripMenuItem.Click, Sub() ShowConsole()
        AddHandler FloppyManagerToolStripMenuItem.Click, Sub()
                                                             Using dlg As New FormDiskManager()
                                                                 dlg.Emulator = cpu
                                                                 dlg.HardDiskMode = False

                                                                 dlg.ShowDialog(Me)
                                                             End Using
                                                         End Sub
        AddHandler HardDiskManagerToolStripMenuItem.Click, Sub()
                                                               Using dlg As New FormDiskManager()
                                                                   dlg.Emulator = cpu
                                                                   dlg.HardDiskMode = True

                                                                   dlg.ShowDialog(Me)
                                                               End Using
                                                           End Sub

        Me.BackColor = Color.Black

        StartEmulation()
    End Sub

    Private Sub StartEmulation()
        cpu = New x8086(True)
        cpuState = New EmulatorState(cpu)

        Dim fc As New FloppyControllerAdapter(cpu)

        cpu.Adapters.Add(fc)
        cpu.Adapters.Add(New CGAWinForms(cpu, videoPort))
        cpu.Adapters.Add(New KeyboardAdapter(cpu))
#If win32 Then
        cpu.Adapters.Add(New SpeakerAdpater(cpu))
#End If

        LoadSettings()
        'fc.DiskImage(128) = New DiskImage("E:\Documents\Visual Studio 2012\Projects\x8086NetEmu\Other Emulators & Resources\PCE - PC Emulator\bin\hd0.img", False, True)

        AddHandler videoPort.SizeChanged, AddressOf AdjustFormSize
        AddHandler SoftResetToolStripMenuItem.Click, Sub() cpu.SoftReset()
        AddHandler HardResetToolStripMenuItem.Click, Sub() cpu.HardReset()

        CType(cpu.VideoAdapter, CGAWinForms).AutoSize()
        AdjustFormSize()

        cpu.EmulateINT13 = True
        cpu.Run(False)
    End Sub

    Private Sub ShowConsole()
        If fConsole Is Nothing Then
            fConsole = New FormConsole()
            fConsole.Show()
            fConsole.Emulator = cpu
            fConsole.BringToFront()

            AddHandler fConsole.FormClosed, Sub()
                                                fConsole.Dispose()
                                                fConsole = Nothing
                                            End Sub
        End If
    End Sub

    Private Sub ShowMonitor()
        If fMonitor Is Nothing Then
            fMonitor = New FormMonitor()
            fMonitor.Show()
            fMonitor.Emulator = cpu
            fMonitor.BringToFront()

            AddHandler fMonitor.FormClosed, Sub()
                                                fMonitor.Dispose()
                                                fMonitor = Nothing
                                            End Sub
        End If
    End Sub

    Private Sub AdjustFormSize()
        Dim m As Integer = 0
        videoPort.Location = New Point(m, m + MenuStripMain.Height + 1)
        Me.ClientSize = New Size(videoPort.Size.Width + m * 2, videoPort.Size.Height + MenuStripMain.Height + 2 + m * 2)
    End Sub

    Private Sub SetZoom(sender As Object, e As EventArgs) Handles Zoom25ToolStripMenuItem.Click, Zoom50ToolStripMenuItem.Click, Zoom100ToolStripMenuItem.Click,
                                                                        Zoom150ToolStripMenuItem.Click, Zoom200ToolStripMenuItem.Click, Zoom400ToolStripMenuItem.Click

        Dim zoomText As String = CType(sender, ToolStripMenuItem).Text
        Dim zoomPercentage As Integer = Integer.Parse(zoomText.Replace("%", ""))

        For Each ddi As ToolStripItem In ZoomToolStripMenuItem.DropDownItems
            If TypeOf ddi Is ToolStripMenuItem Then
                Dim mi = CType(ddi, ToolStripMenuItem)
                If mi.Text.StartsWith("Custom") Then

                Else
                    mi.Checked = (ddi.Text = zoomText)
                End If
            End If
        Next

        CType(cpu.VideoAdapter, CGAWinForms).Zoom = zoomPercentage / 100
    End Sub

    Private Sub SetSpeed(sender As Object, e As EventArgs) Handles ToolStripMenuItemSpeed25.Click, ToolStripMenuItemSpeed50.Click,
                                                                                        ToolStripMenuItemSpeed100.Click, ToolStripMenuItemSpeed150.Click,
                                                                                        ToolStripMenuItemSpeed200.Click, ToolStripMenuItemSpeed400.Click,
                                                                                        ToolStripMenuItemSpeed800.Click, ToolStripMenuItemSpeed1000.Click
        Dim speedText As String = CType(sender, ToolStripMenuItem).Text
        Dim speedPercentage As Integer = Integer.Parse(speedText.Replace("%", ""))

        For Each ddi As ToolStripItem In SpeedToolStripMenuItem.DropDownItems
            If TypeOf ddi Is ToolStripMenuItem Then
                Dim mi = CType(ddi, ToolStripMenuItem)
                If mi.Text.StartsWith("Custom") Then

                Else
                    mi.Checked = (ddi.Text = speedText)
                End If
            End If
        Next

        cpu.ClockFrequency = x8086.BaseClock * speedPercentage / 100
    End Sub

    Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ExitToolStripMenuItem.Click
        Me.Close()
    End Sub

    Private Sub LoadSettings()
        If IO.File.Exists("settings.dat") Then
            Dim xml = XDocument.Load("settings.dat")

            ParseSettings(xml.<settings>(0))
        End If
    End Sub

    Private Sub ParseSettings(xml As XElement)
        cpu.ClockFrequency = xml.<clockSpeed>.Value
        Dim speedText As String = (xml.<clockSpeed>.Value / x8086.BaseClock * 100).ToString() + "%"
        For Each ddi As ToolStripItem In SpeedToolStripMenuItem.DropDownItems
            If TypeOf ddi Is ToolStripMenuItem Then
                Dim mi = CType(ddi, ToolStripMenuItem)
                If mi.Text.StartsWith("Custom") Then

                Else
                    mi.Checked = (ddi.Text = speedText)
                End If
            End If
        Next

        CType(cpu.VideoAdapter, CGAWinForms).Zoom = xml.<videoZoom>.Value
        Dim zoomText As String = (xml.<videoZoom>.Value * 100).ToString() + "%"
        For Each ddi As ToolStripItem In ZoomToolStripMenuItem.DropDownItems
            If TypeOf ddi Is ToolStripMenuItem Then
                Dim mi = CType(ddi, ToolStripMenuItem)
                If mi.Text.StartsWith("Custom") Then

                Else
                    mi.Checked = (ddi.Text = zoomText)
                End If
            End If
        Next

        For i As Integer = 0 To 512 - 1
            If cpu.FloppyContoller.DiskImage(i) IsNot Nothing Then cpu.FloppyContoller.DiskImage(i).Close()
        Next

        For Each f In xml.<floppies>.<floppy>
            Dim index As Integer = Asc(f.<letter>.Value) - 65
            Dim image As String = f.<image>.Value
            Dim ro As Boolean = Boolean.Parse(f.<readOnly>.Value)

            cpu.FloppyContoller.DiskImage(index) = New DiskImage(image, ro)
        Next

        For Each d In xml.<disks>.<disk>
            Dim index As Integer = Asc(d.<letter>.Value) - 67 + 128
            Dim image As String = d.<image>.Value
            Dim ro As Boolean = Boolean.Parse(d.<readOnly>.Value)

            cpu.FloppyContoller.DiskImage(index) = New DiskImage(image, ro, True)
        Next

        Try
            If Boolean.Parse(xml.<extras>.<consoleVisible>.Value) Then ShowConsole()
            If Boolean.Parse(xml.<extras>.<monitorVisible>.Value) Then ShowMonitor()
        Catch
        End Try
    End Sub

    Private Sub SaveSettings()
        cpuState.SaveSettings("settings.dat",
                              <extras>
                                  <consoleVisible><%= (fConsole IsNot Nothing).ToString() %></consoleVisible>
                                  <monitorVisible><%= (fMonitor IsNot Nothing).ToString() %></monitorVisible>
                              </extras>)
    End Sub

    Private Sub SaveStateToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SaveStateToolStripMenuItem.Click
        cpu.Pause()

        Using dlg As New SaveFileDialog()
            dlg.Title = "Save Emulator State"
            dlg.Filter = "x8086NetEmu State|*.state"
            dlg.AddExtension = True

            If dlg.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
                cpuState.SaveState(dlg.FileName)
            End If
        End Using

        cpu.Resume()
    End Sub

    Private Sub LoadStateToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles LoadStateToolStripMenuItem.Click
        Using dlg As New OpenFileDialog()
            dlg.Title = "Load Emulator State"
            dlg.Filter = "x8086NetEmu State|*.state"

            If dlg.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
                cpu.Init()

                Dim xml = XDocument.Load(dlg.FileName)
                ParseSettings(xml.<state>.<settings>(0))
                PowerState(xml.<state>(0))

                cpu.Run(cpu.DebugMode)
            End If
        End Using
    End Sub

    Private Sub PowerState(xml As XElement)
        cpu.Flags.EFlags = xml.<flags>.Value

        cpu.Registers.AX = xml.<registers>.<AX>.Value
        cpu.Registers.BX = xml.<registers>.<BX>.Value
        cpu.Registers.CX = xml.<registers>.<CX>.Value
        cpu.Registers.DX = xml.<registers>.<DX>.Value
        cpu.Registers.CS = xml.<registers>.<CS>.Value
        cpu.Registers.IP = xml.<registers>.<IP>.Value
        cpu.Registers.SS = xml.<registers>.<SS>.Value
        cpu.Registers.SP = xml.<registers>.<SP>.Value
        cpu.Registers.DS = xml.<registers>.<DS>.Value
        cpu.Registers.SI = xml.<registers>.<SI>.Value
        cpu.Registers.ES = xml.<registers>.<ES>.Value
        cpu.Registers.DI = xml.<registers>.<DI>.Value
        cpu.Registers.BP = xml.<registers>.<BP>.Value
        cpu.Registers.ActiveSegmentRegister = [Enum].Parse(GetType(x8086.GPRegisters.RegistersTypes), xml.<registers>.<AS>.Value)

        cpu.Memory = Convert.FromBase64String(xml.<memory>.Value)
        cpu.DebugMode = Boolean.Parse(xml.<debugMode>.Value)

        cpu.VideoAdapter.VideoMode = [Enum].Parse(GetType(CGAAdapter.VideoModes), xml.<videoMode>.Value)
    End Sub
End Class
