1
0
mirror of https://github.com/livingcomputermuseum/ContrAlto.git synced 2026-01-21 10:12:20 +00:00

Implemented basic installer for Contralto. Fixed a couple of small display rendering issues.

This commit is contained in:
Josh Dersch 2016-03-11 11:38:35 -08:00
parent 4cbb74c033
commit a79fd5f016
20 changed files with 440 additions and 33 deletions

View File

@ -5,6 +5,8 @@ VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contralto", "Contralto\Contralto.csproj", "{CC6D96B3-8099-4497-8AD8-B0795A3353EA}"
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ContraltoSetup", "ContraltoSetup\ContraltoSetup.wixproj", "{47BBC195-80C5-43F3-B691-7D27B0803B84}"
EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
@ -28,6 +30,14 @@ Global
{CC6D96B3-8099-4497-8AD8-B0795A3353EA}.Release|Any CPU.Build.0 = Release|Any CPU
{CC6D96B3-8099-4497-8AD8-B0795A3353EA}.Release|x64.ActiveCfg = Release|x64
{CC6D96B3-8099-4497-8AD8-B0795A3353EA}.Release|x86.ActiveCfg = Release|x86
{47BBC195-80C5-43F3-B691-7D27B0803B84}.Debug|Any CPU.ActiveCfg = Debug|x86
{47BBC195-80C5-43F3-B691-7D27B0803B84}.Debug|x64.ActiveCfg = Debug|x86
{47BBC195-80C5-43F3-B691-7D27B0803B84}.Debug|x86.ActiveCfg = Debug|x86
{47BBC195-80C5-43F3-B691-7D27B0803B84}.Debug|x86.Build.0 = Debug|x86
{47BBC195-80C5-43F3-B691-7D27B0803B84}.Release|Any CPU.ActiveCfg = Release|x86
{47BBC195-80C5-43F3-B691-7D27B0803B84}.Release|x64.ActiveCfg = Release|x86
{47BBC195-80C5-43F3-B691-7D27B0803B84}.Release|x86.ActiveCfg = Release|x86
{47BBC195-80C5-43F3-B691-7D27B0803B84}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -79,6 +79,9 @@ namespace Contralto.CPU
_rdRam = false;
_rb = 0;
_firstInstructionAfterSwitch = false;
_swMode = false;
_wrtRam = false;
}
public virtual void SoftReset()
@ -545,7 +548,7 @@ namespace Contralto.CPU
protected bool _rdRam; // Whether to load uCode RAM onto the bus during the next cycle.
protected bool _wrtRam; // Whether to write uCode RAM from M and ALU outputs during the next cycle.
protected bool _swMode; // Whether to switch uCode banks during the next cycle.
protected bool _softReset; // Whether this instruction caused a soft reset (so MPC should not come from instruction's NEXT field)
protected bool _softReset; // Whether this instruction caused a soft reset (so MPC should not come from instruction's NEXT field)
//

View File

@ -126,8 +126,9 @@ namespace Contralto.CPU
/// </summary>
/// <param name="nextAddress"></param>
public static void SwitchMode(ushort nextAddress, TaskType task)
{
Log.Write(Logging.LogComponent.Microcode, "SWMODE: Current Bank {0}", _microcodeBank[(int)task]);
{
// Log.Write(Logging.LogComponent.Microcode, "SWMODE: Current Bank {0}", _microcodeBank[(int)task]);
switch (Configuration.SystemType)
{
@ -198,7 +199,7 @@ namespace Contralto.CPU
break;
}
Log.Write(Logging.LogComponent.Microcode, "SWMODE: New Bank {0} for Task {1}", _microcodeBank[(int)task], task);
// Log.Write(Logging.LogComponent.Microcode, "SWMODE: New Bank {0} for Task {1}", _microcodeBank[(int)task], task);
}
public static ushort ReadRAM()

View File

@ -11,6 +11,21 @@
<AssemblyName>Contralto</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -225,7 +240,10 @@
<None Include="Disk\st76boot.dsk">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Disk\st76new.dsk">
<None Include="Disk\st76.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\st80.dsk">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Disk\tdisk4.dsk">
@ -383,9 +401,22 @@
<Content Include="pcap\PcapDotNet.Packets.dll" />
<Content Include="pcap\PcapDotNet.Packets.pdb" />
<Content Include="pcap\PcapDotNet.Packets.xml" />
<Content Include="readme.txt" />
<EmbeddedResource Include="Alto.ico" />
<Content Include="Notes.txt" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Contralto/Disk/st76.dsk Normal file

Binary file not shown.

Binary file not shown.

BIN
Contralto/Disk/st80.dsk Normal file

Binary file not shown.

Binary file not shown.

View File

@ -48,7 +48,7 @@ namespace Contralto.Display
{
get
{
return _dataBuffer.Count >= 16;
return _dataBuffer.Count >= 14;
}
}
@ -89,11 +89,20 @@ namespace Contralto.Display
_system.CPU.BlockTask(TaskType.DisplayHorizontal);
_system.CPU.BlockTask(TaskType.DisplayWord);
// TODO: this eliminates the garbage on the top two lines of the screen. We are likely
// not stopping the Word task at the right point at the end of the field, leading to it reading
// garbage for the first word(s) or so of the next field...
// OR: we need more time at the start of the scanline before rendering starts...
// Fix this right!
_system.CPU.Tasks[(int)TaskType.DisplayWord].Reset();
_fields++;
_scanline = _evenField ? 0 : 1;
_vblankScanlineCount = 0;
_dataBuffer.Clear();
@ -125,7 +134,7 @@ namespace Contralto.Display
_dataBuffer.Clear();
_dwtBlocked = false;
_dhtBlocked = false;
_dhtBlocked = false;
// Run CURT
_system.CPU.WakeupTask(TaskType.Cursor);
@ -158,10 +167,12 @@ namespace Contralto.Display
{
_cursorXLatched = _cursorX;
_cursorXLatch = false;
}
}
// Schedule immediate wakeup for first word on this scanline
_wordWakeup.TimestampNsec = 0;
// Schedule wakeup for first word on this scanline
// TODO: the delay below is chosen to reduce flicker on first scanline;
// investigate.
_wordWakeup.TimestampNsec = _wordDuration * 3;
_system.Scheduler.Schedule(_wordWakeup);
}
@ -195,12 +206,12 @@ namespace Contralto.Display
// Draw cursor for this scanline first
if (_cursorXLatched < 606)
{
_display.DrawCursorWord(_scanline, _cursorXLatched, _cursorRegLatched);
_display.DrawCursorWord(_scanline, _cursorXLatched, _whiteOnBlack, _cursorRegLatched);
}
_scanline += 2;
if (_scanline > 807)
if (_scanline >= 808)
{
// Done with field.
@ -224,13 +235,13 @@ namespace Contralto.Display
_dwtBlocked = false;
_dataBuffer.Clear();
// Deal with SWMODE latches for the scanline we're about to draw
// Deal with SWMODE latches for the scanline we're about to draw
if (_swModeLatch)
{
_lowRes = _lowResLatch;
_whiteOnBlack = _whiteOnBlackLatch;
_swModeLatch = false;
}
}
}
}
@ -270,9 +281,7 @@ namespace Contralto.Display
_dataBuffer.Enqueue(word);
// Sanity check: data length should never exceed 16 words.
// TODO: we're allowing up to 18 before we start discarding things.
// This indicates that our timing is messed up somewhere...
if (_dataBuffer.Count > 18)
if (_dataBuffer.Count > 16)
{
_dataBuffer.Dequeue();
}
@ -298,13 +307,10 @@ namespace Contralto.Display
public void SETMODE(ushort word)
{
// These take effect at the beginning of the next scanline.
if (!_swModeLatch)
{
_lowResLatch = (word & 0x8000) != 0;
_whiteOnBlackLatch = (word & 0x4000) != 0;
_swModeLatch = true;
}
// These take effect at the beginning of the next scanline.
_lowResLatch = (word & 0x8000) != 0;
_whiteOnBlackLatch = (word & 0x4000) != 0;
_swModeLatch = true;
}
public bool EVENFIELD

View File

@ -24,7 +24,7 @@ namespace Contralto.Display
/// <param name="wordOffset"></param>
/// <param name="dataWord"></param>
/// <param name="lowRes"></param>
void DrawCursorWord(int scanline, int xOffset, ushort cursorWord);
void DrawCursorWord(int scanline, int xOffset, bool whiteOnBlack, ushort cursorWord);
/// <summary>
/// Causes the display to be rendered

View File

@ -44,22 +44,22 @@
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(74, 13);
this.label1.TabIndex = 0;
this.label1.Text = "ContrAlto v0.1";
this.label1.Text = "ContrAlto v0.2";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(45, 68);
this.label2.Location = new System.Drawing.Point(45, 45);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(168, 13);
this.label2.TabIndex = 1;
this.label2.Text = "(c) 2015 Living Computer Museum";
this.label2.Text = "(c) 2016 Living Computer Museum";
this.label2.Click += new System.EventHandler(this.label2_Click);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(68, 43);
this.label3.Location = new System.Drawing.Point(68, 32);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(109, 13);
this.label3.TabIndex = 2;
@ -86,7 +86,7 @@
// linkLabel1
//
this.linkLabel1.AutoSize = true;
this.linkLabel1.Location = new System.Drawing.Point(45, 123);
this.linkLabel1.Location = new System.Drawing.Point(45, 112);
this.linkLabel1.Name = "linkLabel1";
this.linkLabel1.Size = new System.Drawing.Size(168, 13);
this.linkLabel1.TabIndex = 5;

View File

@ -386,7 +386,7 @@ namespace Contralto
/// <param name="scanline">The scanline (Y)</param>
/// <param name="xOffset">X offset (in pixels)</param>
/// <param name="cursorWord">The word to be drawn</param>
public void DrawCursorWord(int scanline, int xOffset, ushort cursorWord)
public void DrawCursorWord(int scanline, int xOffset, bool whiteOnBlack, ushort cursorWord)
{
int address = scanline * 76 + xOffset / 8;
@ -399,9 +399,17 @@ namespace Contralto
(_currentBuffer[address + 2] << 8) |
_currentBuffer[address + 3]);
UInt32 longcursorWord = (UInt32)(cursorWord << 16);
// Slide the cursor word to the proper X position
UInt32 adjustedCursorWord = (UInt32)(cursorWord << (16 - (xOffset % 8)));
displayWord ^= (longcursorWord >> (xOffset % 8));
if (!whiteOnBlack)
{
displayWord &= ~adjustedCursorWord;
}
else
{
displayWord |= adjustedCursorWord;
}
_currentBuffer[address] = (byte)(displayWord >> 24);
_currentBuffer[address + 1] = (byte)(displayWord >> 16);

193
Contralto/readme.txt Normal file
View File

@ -0,0 +1,193 @@
Readme.txt for Contralto v0.1:
1. Introduction and Overview
----------------------------
ContrAlto purports to be a faithful emulation of the Xerox Alto series of
pioneering graphical workstations developed at Xerox PARC in 1973.
1.1 What's Emulated
-------------------
ContrAlto currently emulates the following Alto hardware:
- Alto IIxm CPU
- Microcode RAM (in 1K RAM, 1K RAM/2K ROM, or 3K RAM configurations)
- 256KW of main memory (in 64KW banks)
- Diablo Model 31 drives
- Ethernet (encapsulated in either UDP datagrams or raw Ethernet frames
on the host machine)
- Standard Keyboard/Mouse/Video
At this time, ContrAlto does not support more exotic hardware such as Diablo 44
and Trident disks, the Orbit printer interface, or the keyset input device.
2.0 Requirements
----------------
ContrAlto will run on any Windows PC running Windows XP or later, with version
2.0 or later of the .NET Framework installed. .NET should be present by default
on Windows Vista and later; if it is not installed on your computer it can be
obtained at https://www.microsoft.com/net.
As ContrAlto is a .NET application and has no Windows-specific dependencies,
it will also run under Mono (http://www.mono-project.com/) on Unix and MacOS,
however this usage is not as well tested -- please file bugs if you find them
(see Section 7 for details).
3.0 Getting Started
-------------------
To launch ContrAlto, simply click on the shortcut created by the installer
on your Start Menu (or Start Screen, depending on your Windows version.) Two
windows will appear: a console window for diagnostic output and the main display
window, labeled "ContrAlto." This latter window is where you will interact
with your virtual Alto.
On a real Alto, the system is booted by loading a 14" disk pack into the front
of a Diablo 31 drive, waiting for it to spin up for 20 seconds and then
pressing the "Reset" button on the back of the keyboard.
Booting an emulated Alto under ContrAlto is slightly less time-consuming.
To load a disk pack into the virtual Diablo drive, click on the "System"
menu and go to "Drive 0 -> Load...". You will be presented with a file dialog
allowing selection of the disk image (effectively a "virtual disk pack") to
be loaded. Several images are provided with ContrAlto, select one and click
the "Open" button.
Once the pack has been loaded, you can start the Alto by clicking on the
"System->Start" menu (or hitting Ctrl+Alt+S). The display will turn white and
after 5-10 seconds a mouse cursor will appear, followed shortly by the banner
of the Xerox Alto Executive. Congratulations, your Alto is now running! Click
on the display window to start interacting with it using the keyboard and mouse
(and if you need your mouse back for other things, press either "Alt" key on
your keyboard.)
3.1 Using the Alto
------------------
3.1.1 The Basics
----------------
3.1.2 Reading Materials
-----------------------
4.0 Configuration
-----------------
4.1 CPU
-------
4.2 Ethernet
------------
4.3 Display
-----------
5.0 Debugger
------------
ContrAlto contains a fairly capable debugger window that can be invoked via
the "System->Show Debugger" menu (or Ctrl+Alt+D) at any time. When the debugger
is invoked, it takes over control of the system from the main display window.
The system can be micro-stepped or single-stepped and breakpoints can be set on
microcode addresses or Nova instruction addresses.
Usage of the debugger is mostly straightforward but it is intended for "expert"
users only and still has many rough edges.
5.1 The Controls
----------------
At the very bottom of the debugger window is a row of buttons. These are (from
left to right):
Step: Runs the Alto CPU for one clock cycle. Normally this coincides with
a single microinstruction, but not always (for example, memory accesses
may require multiple cycles.) The next microinstruction to be
executed will be highlighted in the "Microcode Source" pane.
Auto: Automatically single-steps the CPU at a relatively slow rate, while
refreshing the debugger UI after every step. Not particularly useful
in most circumstances (but it looks neat.)
Run: Starts the CPU running normally. Execution will continue until a
breakpoint is hit one of the other control buttons are pressed.
Run T: Runs the CPU until the next TASK switch occurs
Nova Step: Runs the CPU until the current Nova instruction is completed. This
will only work properly if the standard Nova microcode is running (if
you are executing a Mesa program, this will not work correctly.)
Stop: Stops the CPU
Reset: Resets the Alto system.
5.2 Microcode Source Pane
-------------------------
The pane in the upper left of the debugger window shows the microcode listings
for ROM0, ROM1, and RAM1. The listings for ROM0 and ROM1 are derived from the
original source code listings. The listing for RAM1 is automatically
disassembled from the contents of control RAM (and is generally more annoying
to read.)
ROM0 contains the listing for the main microcode ROMs -- this 1K of ROM contains
code for all of the microcode tasks (Emulator, Disk Sector, Ethernet, Memory
Refresh, Display Word, Cursor, Display Horizontal, Display Vertical, Parity, and
Disk Word). The source code for each task is highlighted in a different color
to make it easy to differentiate.
ROM1 contains the listing for the Mesa microcode ROMs.
5.3 Memory Pane
---------------
The pane near the lower-left (labeled "Memory") shows a view into the main
memory of the Alto, providing address/data and an automated disassembly of Alto
(Nova) instructions.
5.4 Breakpoints
---------------
Breakpoints can be set on either microcode or Nova code by checking the box
in the "B" column next to the instruction. Unchecking the box will remove the
breakpoint.
Nova code breakpoints will only work if the standard Nova microcode is running.
5.5 Everything Else
-------------------
The other panes in the debugger are:
Disk: Shows registers and other status of the disk hardware
Tasks: Shows the current microcode task status. The "T" column indicates the
task name, "S" indicates the status ("W"akeup and "R"unning), and the
"uPC" column indicates the micro-PC for the corresponding task. There
are 16 possible tasks, not all are used on most Altos.
CPU Registers:
Shows the CPU L, M and T registers as well as ALU and memory registers.
General Registers:
Shows the contents of the 32 R and 32 S registers (in octal).
Reserved Memory:
Shows the contents of most "well known" memory locations. See the
Alto HW Reference manual (link in Sectoin 3.1.2) for what these mean.
6.0 Known Issues
----------------
7.0 Reporting Bugs
------------------

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.10</ProductVersion>
<ProjectGuid>47bbc195-80c5-43f3-b691-7d27b0803b84</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>ContraltoSetup</OutputName>
<OutputType>Package</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="Product.wxs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Contralto\Contralto.csproj">
<Name>Contralto</Name>
<Project>{cc6d96b3-8099-4497-8ad8-b0795a3353ea}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
</ItemGroup>
<Import Project="$(WixTargetsPath)" />
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Wix.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

110
ContraltoSetup/Product.wxs Normal file
View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="CE5F3D08-3BD6-4BDF-9C64-0C2B852B899C" Name="ContrAlto" Language="1033" Version="1.0.0.0" Manufacturer="Living Computer Museum" UpgradeCode="38d6b09f-6e7b-4854-844a-5d4ab707a357">
<Package Id="*" InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<Media Id="1" Cabinet="ContrAlto.cab" EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="ContrAlto" Level="1">
<ComponentGroupRef Id="ProductComponents" />
<ComponentGroupRef Id="MicrocodeComponents" />
<ComponentGroupRef Id="DiskComponents" />
<ComponentGroupRef Id="CodeComponents" />
<ComponentRef Id="ProgramMenuDir" />
</Feature>
<Icon Id="ContrAlto.exe" SourceFile="$(var.Contralto.TargetPath)"/>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="LCM" Name="Living Computer Museum">
<Directory Id="INSTALLFOLDER" Name="Contralto">
<Directory Id="ROMFOLDER" Name="ROM"/>
<Directory Id="DISKFOLDER" Name="Disk"/>
<Directory Id="DISASSEMBLYFOLDER" Name="Disassembly"/>
</Directory>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="ProgramMenuDir" Name="ContrAlto">
<Component Id="ProgramMenuDir" Guid="007ADB59-BCE4-43CB-9AEC-DD5962136A7D">
<RemoveFolder Id="ProgramMenuDir" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\Living Computer Museum\ContrAlto" Type="string" Value="" KeyPath="yes" />
</Component>
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<!-- Main Contralto EXE and dependencies-->
<Component Id="ContraltoExecutable" Guid="0AF4F077-3858-4CEA-A3CD-CF8585F98AAA">
<File Id="exe" Name="ContrAlto.exe" Source="$(var.Contralto.TargetPath)" KeyPath="yes"/>
<Shortcut Id="shortcut" Directory="ProgramMenuDir" Name="ContrAlto"
WorkingDirectory="INSTALLFOLDER" Icon="ContrAlto.exe" IconIndex="0" Advertise="yes" />
<!-- PCAP libs -->
<File Source="$(var.Contralto.TargetDir)\PcapDotNet.Base.dll"/>
<File Source="$(var.Contralto.TargetDir)\PcapDotNet.Core.dll"/>
<File Source="$(var.Contralto.TargetDir)\PcapDotNet.Core.Extensions.dll"/>
<File Source="$(var.Contralto.TargetDir)\PcapDotNet.Packets.dll"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="MicrocodeComponents" Directory="ROMFOLDER">
<!-- Microcode and other ROM files -->
<Component Id="Microcode" Guid="74E9E780-8D35-40D0-92EB-05B399D06EB6" KeyPath="yes">
<File Id="u52" Name="u52" Source="$(var.Contralto.TargetDir)\ROM\u52"/>
<File Id="u53" Name="u53" Source="$(var.Contralto.TargetDir)\ROM\u53"/>
<File Id="u54" Name="u54" Source="$(var.Contralto.TargetDir)\ROM\u54"/>
<File Id="u55" Name="u55" Source="$(var.Contralto.TargetDir)\ROM\u55"/>
<File Id="u60" Name="u60" Source="$(var.Contralto.TargetDir)\ROM\u60"/>
<File Id="u61" Name="u61" Source="$(var.Contralto.TargetDir)\ROM\u61"/>
<File Id="u62" Name="u62" Source="$(var.Contralto.TargetDir)\ROM\u62"/>
<File Id="u63" Name="u63" Source="$(var.Contralto.TargetDir)\ROM\u63"/>
<File Id="u64" Name="u64" Source="$(var.Contralto.TargetDir)\ROM\u64"/>
<File Id="u65" Name="u65" Source="$(var.Contralto.TargetDir)\ROM\u65"/>
<File Id="u70" Name="u70" Source="$(var.Contralto.TargetDir)\ROM\u70"/>
<File Id="u71" Name="u71" Source="$(var.Contralto.TargetDir)\ROM\u71"/>
<File Id="u72" Name="u72" Source="$(var.Contralto.TargetDir)\ROM\u72"/>
<File Id="u73" Name="u73" Source="$(var.Contralto.TargetDir)\ROM\u73"/>
<File Id="u74" Name="u74" Source="$(var.Contralto.TargetDir)\ROM\u74"/>
<File Id="u75" Name="u75" Source="$(var.Contralto.TargetDir)\ROM\u75"/>
<File Id="c0" Name="C0" Source="$(var.Contralto.TargetDir)\ROM\C0"/>
<File Id="c1" Name="C1" Source="$(var.Contralto.TargetDir)\ROM\C1"/>
<File Id="c2" Name="C2" Source="$(var.Contralto.TargetDir)\ROM\C2"/>
<File Id="c3" Name="C3" Source="$(var.Contralto.TargetDir)\ROM\C3"/>
<File Id="Twokctl" Name="2kctl.u3" Source="$(var.Contralto.TargetDir)\ROM\2kctl.u3"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="DiskComponents" Directory="DISKFOLDER">
<!-- Disk Images -->
<Component Id="DiskImages" Guid="A0977605-CD44-462D-80A0-A6347D87B700" KeyPath="yes">
<File Id="allgames" Name="AllGames.dsk" Source="$(var.Contralto.TargetDir)\Disk\allgames.dsk"/>
<File Id="bcpl" Name="Bcpl.dsk" Source="$(var.Contralto.TargetDir)\Disk\bcpl.dsk"/>
<File Id="diag" Name="Diag.dsk" Source="$(var.Contralto.TargetDir)\Disk\diag.dsk"/>
<File Id="nonprog" Name="NonProg.dsk" Source="$(var.Contralto.TargetDir)\Disk\nonprog.dsk"/>
<File Id="st76" Name="ST76.dsk" Source="$(var.Contralto.TargetDir)\Disk\st76.dsk"/>
<File Id="st80" Name="ST80.dsk" Source="$(var.Contralto.TargetDir)\Disk\st80.dsk"/>
<File Id="xmsmall" Name="XmSmall.dsk" Source="$(var.Contralto.TargetDir)\Disk\xmsmall.dsk"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="CodeComponents" Directory="DISASSEMBLYFOLDER">
<!-- Annotated disassemblies -->
<Component Id="Disassembly" Guid="F4530D99-D8C5-45C4-A64F-EEE15F473933" KeyPath="yes">
<File Id="altoIIcode" Name="altoIIcode3.mu" Source="$(var.Contralto.TargetDir)\Disassembly\altoIIcode3.mu"/>
<File Id="MesaROM" Name="MesaROM.mu" Source="$(var.Contralto.TargetDir)\Disassembly\MesaROM.mu"/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>