1
0
mirror of https://github.com/livingcomputermuseum/ContrAlto.git synced 2026-01-17 00:23:24 +00:00

Readme updates, installer updates. A couple of smallish (10%) performance enhancements.

This commit is contained in:
Josh Dersch 2016-03-14 16:50:41 -07:00
parent a79fd5f016
commit dc0a85aed8
19 changed files with 258 additions and 82 deletions

View File

@ -8,9 +8,6 @@ EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ContraltoSetup", "ContraltoSetup\ContraltoSetup.wixproj", "{47BBC195-80C5-43F3-B691-7D27B0803B84}"
EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64

View File

@ -21,7 +21,7 @@ namespace Contralto
_scheduler = new Scheduler();
_memBus = new MemoryBus();
_mem = new Memory.Memory();
_mem = new Memory.Memory();
_keyboard = new Keyboard();
_diskController = new DiskController(this);
_displayController = new DisplayController(this);
@ -30,6 +30,7 @@ namespace Contralto
_cpu = new AltoCPU(this);
// Attach memory-mapped devices to the bus
_memBus.AddDevice(_mem);
_memBus.AddDevice(_keyboard);
@ -37,8 +38,7 @@ namespace Contralto
// Register devices that need clocks
_clockableDevices = new List<IClockable>();
_clockableDevices.Add(_memBus);
_clockableDevices.Add(_displayController);
_clockableDevices.Add(_memBus);
_clockableDevices.Add(_cpu);
Reset();
@ -176,11 +176,15 @@ namespace Contralto
{
get { return _scheduler; }
}
public int _novaInst;
private void T_Elapsed(object sender, ElapsedEventArgs e)
{
System.Console.WriteLine("{0} CPU clocks/sec %{1}. {2} fields/sec", _clocks, ((double)_clocks / 5882353.0) * 100.0, _displayController.Fields);
System.Console.WriteLine("{0} nova instructions/sec.", _novaInst);
_clocks = 0;
_novaInst = 0;
_displayController.Fields = 0;
}

View File

@ -191,7 +191,7 @@ namespace Contralto.CPU
{
if (_tasks[(int)task] != null)
{
Log.Write(LogComponent.TaskSwitch, "Wakeup enabled for Task {0}", task);
// Log.Write(LogComponent.TaskSwitch, "Wakeup enabled for Task {0}", task);
_tasks[(int)task].WakeupTask();
}
}
@ -205,7 +205,7 @@ namespace Contralto.CPU
{
if (_tasks[(int)task] != null)
{
Log.Write(LogComponent.TaskSwitch, "Removed wakeup for Task {0}", task);
// Log.Write(LogComponent.TaskSwitch, "Removed wakeup for Task {0}", task);
_tasks[(int)task].BlockTask();
}
}
@ -239,7 +239,7 @@ namespace Contralto.CPU
if (_tasks[i] != null && _tasks[i].Wakeup)
{
_nextTask = _tasks[i];
_nextTask.FirstInstructionAfterSwitch = true;
_nextTask.FirstInstructionAfterSwitch = true;
/*
if (_nextTask != _currentTask && _currentTask != null)

View File

@ -21,6 +21,9 @@ namespace Contralto.CPU
protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
{
// We put ourselves back to sleep immediately once we've started running
// TODO: for this and other similar patterns: rework this so we don't need to
// override ExecuteInstruction just to do this (or similar polling). Virtual calls
// are expensive, especially when millions of them are being made a second.
_wakeup = false;
return base.ExecuteInstruction(instruction);

View File

@ -17,18 +17,7 @@ namespace Contralto.CPU
_wakeup = false;
_displayController = _cpu._system.DisplayController;
}
protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
{
// We remove our wakeup only if there isn't a wakeup being generated for us by the
// display controller.
_wakeup = (!_displayController.FIFOFULL &&
!_displayController.DHTBLOCK &&
!_displayController.DWTBLOCK);
return base.ExecuteInstruction(instruction);
}
}
protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
{

View File

@ -14,6 +14,7 @@
_wakeup = false;
}
/*
protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
{
//
@ -22,7 +23,7 @@
// "; This version assumes MRTACT is cleared by BLOCK, not MAR<- R37"
//
return base.ExecuteInstruction(instruction);
}
}*/
}
}
}

View File

@ -250,8 +250,18 @@ namespace Contralto.CPU
//
ExecuteSpecialFunction1Early(instruction);
// Do ALU operation
aluData = ALU.Execute(instruction.ALUF, _busData, _cpu._t, _skip);
// Do ALU operation.
// Small optimization: if we're just taking bus data across the ALU, we
// won't go through the ALU.Execute call; this is a decent performance gain for a bit
// more ugly code...
if (instruction.ALUF != AluFunction.Bus)
{
aluData = ALU.Execute(instruction.ALUF, _busData, _cpu._t, _skip);
}
else
{
aluData = _busData;
}
//
// If there was a WRTRAM operation last cycle, we write the uCode RAM here
@ -463,9 +473,9 @@ namespace Contralto.CPU
// (And apparently the modifier applied to NEXT in this instruction -- MADTEST expects this.)
//
if (swMode)
{
UCodeMemory.SwitchMode((ushort)(instruction.NEXT | nextModifier), _taskType);
Log.Write(Logging.LogComponent.Microcode, "SWMODE: uPC {0}, next uPC {1}", Conversion.ToOctal(_mpc), Conversion.ToOctal(instruction.NEXT | nextModifier));
{
// Log.Write(Logging.LogComponent.Microcode, "SWMODE: uPC {0}, next uPC {1} (NEXT is {2})", Conversion.ToOctal(_mpc), Conversion.ToOctal(instruction.NEXT | nextModifier), Conversion.ToOctal(instruction.NEXT));
UCodeMemory.SwitchMode((ushort)(instruction.NEXT | nextModifier), _taskType);
}
//

View File

@ -127,7 +127,6 @@ namespace Contralto.CPU
/// <param name="nextAddress"></param>
public static void SwitchMode(ushort nextAddress, TaskType task)
{
// Log.Write(Logging.LogComponent.Microcode, "SWMODE: Current Bank {0}", _microcodeBank[(int)task]);
switch (Configuration.SystemType)
@ -235,7 +234,8 @@ namespace Contralto.CPU
// No-op, can't write to ROM.
return;
}
/*
Log.Write(Logging.LogComponent.Microcode, "CRAM address for write: Bank {0}, addr {1}",
_ramBank,
Conversion.ToOctal(_ramAddr));
@ -243,6 +243,7 @@ namespace Contralto.CPU
Log.Write(Logging.LogComponent.Microcode, "CRAM write of low {0}, high {1}",
Conversion.ToOctal(low),
Conversion.ToOctal(high));
*/
ushort address = (ushort)(_ramAddr + _ramBank * 1024);

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram />

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram />

View File

@ -86,6 +86,9 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Alto.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="PcapDotNet.Base, Version=1.0.2.21699, Culture=neutral, PublicKeyToken=4b6f3e583145a652, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@ -194,8 +197,6 @@
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="ClassDiagram1.cd" />
<None Include="ClassDiagram2.cd" />
<None Include="Disassembly\altocode24.mu" />
<None Include="App.config" />
<None Include="Disassembly\altoIIcode3.mu">
@ -401,8 +402,10 @@
<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="readme.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Resource Include="Alto.ico" />
<Content Include="Notes.txt" />
</ItemGroup>
<ItemGroup>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -8,7 +8,7 @@ namespace Contralto.Display
/// as it scans across the screen. It implements the logic of the display's sync generator
/// and wakes up the DVT and DHT tasks as necessary during a display field.
/// </summary>
public class DisplayController : IClockable
public class DisplayController
{
public DisplayController(AltoSystem system)
{
@ -35,13 +35,21 @@ namespace Contralto.Display
public bool DWTBLOCK
{
get { return _dwtBlocked; }
set { _dwtBlocked = value; }
set
{
_dwtBlocked = value;
CheckWordWakeup();
}
}
public bool DHTBLOCK
{
get { return _dhtBlocked; }
set { _dhtBlocked = value; }
set
{
_dhtBlocked = value;
CheckWordWakeup();
}
}
public bool FIFOFULL
@ -59,6 +67,12 @@ namespace Contralto.Display
_word = 0;
_dwtBlocked = true;
_dhtBlocked = false;
_dataBuffer.Clear();
if (_system.CPU != null)
{
CheckWordWakeup();
}
_whiteOnBlack = _whiteOnBlackLatch = false;
_lowRes = _lowResLatch = false;
@ -133,8 +147,8 @@ namespace Contralto.Display
_dataBuffer.Clear();
_dwtBlocked = false;
_dhtBlocked = false;
DWTBLOCK = false;
DHTBLOCK = false;
// Run CURT
_system.CPU.WakeupTask(TaskType.Cursor);
@ -188,6 +202,7 @@ namespace Contralto.Display
if (_dataBuffer.Count > 0)
{
displayWord = _whiteOnBlack ? _dataBuffer.Dequeue() : (ushort)~_dataBuffer.Dequeue();
CheckWordWakeup();
}
_display.DrawDisplayWord(_scanline, _word, displayWord, _lowRes);
@ -232,7 +247,7 @@ namespace Contralto.Display
// Schedule HBlank wakeup for end of next HBlank
_horizontalWakeup.TimestampNsec = _horizontalBlankDuration - skewNsec;
_system.Scheduler.Schedule(_horizontalWakeup);
_dwtBlocked = false;
DWTBLOCK = false;
_dataBuffer.Clear();
// Deal with SWMODE latches for the scanline we're about to draw
@ -261,21 +276,28 @@ namespace Contralto.Display
}
}
public void Clock()
{
//
// "If the DWT has not executed a BLOCK, if DHT is not blocked, and if the
// buffer is not full, DWT wakeups are generated."
//
// TODO: move this logic elsewhere so it doesn't have to be polled.
if (_dataBuffer.Count < 16 &&
!_dhtBlocked &&
!_dwtBlocked)
{
private void CheckWordWakeup()
{
if (FIFOFULL ||
DHTBLOCK ||
DWTBLOCK)
{
// If the fifo is full or either the horizontal or word tasks have blocked,
// the word task must be blocked.
_system.CPU.BlockTask(TaskType.DisplayWord);
}
else if (!FIFOFULL &&
!DHTBLOCK &&
!DWTBLOCK)
{
//
// "If the DWT has not executed a BLOCK, if DHT is not blocked, and if the
// buffer is not full, DWT wakeups are generated."
//
_system.CPU.WakeupTask(TaskType.DisplayWord);
}
}
}
public void LoadDDR(ushort word)
{
_dataBuffer.Enqueue(word);
@ -285,6 +307,8 @@ namespace Contralto.Display
{
_dataBuffer.Dequeue();
}
CheckWordWakeup();
}
public void LoadXPREG(ushort word)

View File

@ -754,12 +754,13 @@ namespace Contralto
_keyMap.Add(Keys.F1, AltoKey.BlankTop);
_keyMap.Add(Keys.F2, AltoKey.BlankMiddle);
_keyMap.Add(Keys.F3, AltoKey.BlankBottom);
_keyMap.Add(Keys.F4, AltoKey.Lock);
_keyMap.Add(Keys.Back, AltoKey.BS);
_keyMap.Add(Keys.Tab, AltoKey.TAB);
_keyMap.Add(Keys.OemSemicolon, AltoKey.Semicolon);
_keyMap.Add(Keys.OemOpenBrackets, AltoKey.LBracket);
_keyMap.Add(Keys.OemCloseBrackets, AltoKey.RBracket);
_keyMap.Add(Keys.Down, AltoKey.LF);
_keyMap.Add(Keys.Down, AltoKey.LF);
}

View File

@ -826,8 +826,13 @@ namespace Contralto
}
}
#endif
if (_system.CPU.CurrentTask.MPC == 0x10) // MPC is 20(octal) meaning a new Nova instruction.
{
// count nova instructions (for profiling)
_system._novaInst++;
}
// See if we need to stop here
// See if we need to stop here
if (_execAbort || // The Stop button was hit
_microcodeBreakpointEnabled[(int)UCodeMemory.GetBank(_system.CPU.CurrentTask.TaskType),_system.CPU.CurrentTask.MPC] || // A microcode breakpoint was hit
(_execType == ExecutionType.NextTask &&

View File

@ -1,11 +1,12 @@
Readme.txt for Contralto v0.1:
1. Introduction and Overview
----------------------------
============================
ContrAlto purports to be a faithful emulation of the Xerox Alto series of
ContrAlto aspires to be a faithful emulation of the Xerox Alto II series of
pioneering graphical workstations developed at Xerox PARC in 1973.
1.1 What's Emulated
-------------------
@ -21,8 +22,9 @@ ContrAlto currently emulates the following Alto hardware:
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
@ -34,9 +36,14 @@ 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).
A three-button mouse is essential for using most Alto software. On most mice,
the "mousewheel" can be clicked to provide the third (middle) button. Laptops
with trackpads may have configuration options to simulate three buttons but
will likely be clumsy to use.
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
@ -63,19 +70,127 @@ 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
-----------------------
3.1.1.1 Mouse
-------------
ContrAlto uses your computer's mouse to simulate the one the Alto uses.
In order to accurately simulate the mouse, ContrAlto must "capture" the real
mouse, which effectively makes your system's mouse exclusive to the ContrAlto
window. (If you've ever used virtualization software like VMWare, VirtualBox,
Virtual PC, or Parallels, you may be familiar with this behavior.)
Clicking on the ContrAlto display window will cause ContrAlto to capture the
mouse. Once the mouse has been captured, any mouse movements will be reflected
by the Alto's mouse cursor. While ContrAlto has control of the mouse, you will
not be able to use the mouse for other programs running on your PC. To release
ContrAlto's control, press either "Alt" key on your keyboard. Mouse movements
will return to normal, and you will not be able to control the Alto's mouse
until you click on the ContrAlto display window again.
The Alto mouse is a three-button mouse. Alto mouse buttons are mapped as you
would expect. If you have a real three-button mouse then this is completely
straightforward. If you have a two button mouse with a "mousewheel" then
a mousewheel click maps to a click of the Alto's middle mouse button.
If you have a trackpad or other pointing device, using the middle mouse button
may be more complicated. See what configuration options your operating system
and/or drivers provides you for mapping mouse buttons.
3.1.1.2 Keyboard
----------------
ContrAlto emulates the 61-key Alto II keyboard. The vast majority of keys
(the alphanumerics and punctuation) work as you would expect them to, but the
Alto has a few special keys, which are described below:
Alto Key PC Key
-------- ----------
LF Down Arrow
BS Backspace
Blank-Bottom F3
Blank-Middle F2
Blank-Top F1
<- (arrow) Left Arrow
DEL Del
LOCK F4
3.1.1.3 Disk Packs
------------------
A real Alto uses large 14" disk packs for disk storage, each containing
approximately 2.5 megabytes of data. ContrAlto uses files, referred to as
"disk images" or just "images" that contain a bit-for-bit copy of these original
packs. These are a lot easier to use with a modern PC.
Disk images can be loaded and unloaded via the "System->Drive 0" and
System->Drive 1" menus.
If you modify the contents of a loaded disk (for example creating new files or
deleting existing ones) the changes will be written back out to the disk image
when a new image is loaded or when ContrAlto exits. For this reason it may be
a good idea to make backups of packs from time to time (just like on the real
machine.)
3.1.1.4 Startup, Reset and Shutdown
-----------------------------------
The system can be started at any time by using the "System->Start" menu, though
in general having a pack image loaded first is a good idea. Similarly, the
"Start->Reset" menu will reset the Alto.
You can shut down the Alto by closing the ContrAlto window; this will commit
disk changes made to the currently loaded disks back to the disk image files.
However, you will want to be sure the software running on the Alto is ready
to be shutdown first, or else you may lose work or corrupt your disk.
3.1.2 Additional Reading Materials
----------------------------------
The Bitsavers Alto archive at http://http://bitsavers.org/pdf/xerox/alto is an
excellent repository of original Alto documentation, here are a few documents to
get you started:
- The "Alto User's Handbook" is indispensable and contains an overview of the
Alto Executive (the OS "shell"), Bravo (great-granddaddy of Microsoft Word)
and other utilities.
http://bitsavers.org/pdf/xerox/alto/Alto_Users_Handbook_Sep79.pdf
- "Alto Subsystems" documents many of the common Alto programs and tools
("Subsystems" in Alto parlance) in detail.
http://bitsavers.org/pdf/xerox/alto/AltoSubsystems_Oct79.pdf
- "Alto Operating System Reference Manual" is useful if you are going to do
any programming for the Alto.
http://bitsavers.org/pdf/xerox/alto/AltoSWRef.part1.pdf
http://bitsavers.org/pdf/xerox/alto/AltoSWRef.part2.pdf
- "BCPL Reference Manual" is definitely required if you are going to do any
programming on the Alto (in BCPL, anyway...)
http://bitsavers.org/pdf/xerox/alto/bcpl/AltoBCPLdoc.pdf
- "Bravo Course Outline" is a tutorial that will show you how to use the Bravo
editor.
http://bitsavers.org/pdf/xerox/alto/BravoCourse.pdf
- The "Alto Hardware Manual" is fun to read through if you're planning on
writing an Alto emulator of your own. If you're into that sort of thing.
http://bitsavers.org/pdf/xerox/alto/AltoHWRef.part1.pdf
http://bitsavers.org/pdf/xerox/alto/AltoHWRef.part2.pdf
4.0 Configuration
-----------------
=================
4.1 CPU
-------
@ -89,8 +204,13 @@ your keyboard.)
-----------
4.4 Alternate ("keyboard") Boots
--------------------------------
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
@ -101,6 +221,7 @@ 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
@ -145,6 +266,7 @@ to make it easy to differentiate.
ROM1 contains the listing for the Mesa microcode ROMs.
5.3 Memory Pane
---------------
@ -152,6 +274,7 @@ 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
---------------
@ -161,6 +284,7 @@ breakpoint.
Nova code breakpoints will only work if the standard Nova microcode is running.
5.5 Everything Else
-------------------
@ -185,9 +309,9 @@ Reserved Memory:
6.0 Known Issues
----------------
================
7.0 Reporting Bugs
------------------
==================

View File

@ -10,7 +10,8 @@
<Feature Id="ProductFeature" Title="ContrAlto" Level="1">
<ComponentGroupRef Id="ProductComponents" />
<ComponentGroupRef Id="MicrocodeComponents" />
<ComponentGroupRef Id="DiskComponents" />
<ComponentRef Id="UserDiskFolder"/>
<ComponentGroupRef Id="DiskComponents" />
<ComponentGroupRef Id="CodeComponents" />
<ComponentRef Id="ProgramMenuDir" />
</Feature>
@ -23,8 +24,7 @@
<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="ROMFOLDER" Name="ROM"/>
<Directory Id="DISASSEMBLYFOLDER" Name="Disassembly"/>
</Directory>
</Directory>
@ -37,24 +37,37 @@
</Component>
</Directory>
</Directory>
</Directory>
</Fragment>
<Directory Id="PersonalFolder">
<Directory Id="DISKFOLDER" Name="ContrAlto Disks">
<Component Id="UserDiskFolder" Guid="007ADB59-BCE4-43CB-9AEC-DD5962136A7E">
<RemoveFolder Id="DiskFolderFiles" 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" />
<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" />
</File>
<!-- 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>
</Component>
<Component Id="ContraltoReadme" Guid="0AF4F077-3858-4CEA-A3CD-CF8585F98AAB">
<File Id="readme" Name="readme.txt" Source="$(var.Contralto.TargetDir)\readme.txt">
<Shortcut Id="docshortcut" Directory="ProgramMenuDir" Name="ContrAlto Readme" Advertise="yes" />
</File>
</Component>
</ComponentGroup>
<ComponentGroup Id="MicrocodeComponents" Directory="ROMFOLDER">
@ -87,8 +100,13 @@
</ComponentGroup>
<ComponentGroup Id="DiskComponents" Directory="DISKFOLDER">
<!-- Disk Images -->
<Component Id="DiskImages" Guid="A0977605-CD44-462D-80A0-A6347D87B700" KeyPath="yes">
<!-- Disk Images: Not removed during uninstall -->
<Component Id="DiskImages" Guid="A0977605-CD44-462D-80A0-A6347D87B700" Permanent="yes">
<RegistryValue Root="HKCU" Key="Software\Living Computer Museum\ContrAlto"
Name="InstallFolder"
Value="[INSTALLFOLDER]"
Type="string"
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"/>