Scott Hanselman

The Weekly Source Code 44 - Virtu, an Apple Emulator in C# for Silverlight, WPF and XNA

July 14, 2009 Comment on this post [8] Posted in Arcade | Open Source | Silverlight | Source Code | Windows Client | WPF
Sponsored By

Virtu.RasterBlaster I really advocate folks reading as much source as they can because you become a better writer by reading as much as writing. That's the whole point of the Weekly Source Code - reading code to be a better developer.

Reading code in Open Source projects is a good way to learn, especially if the project has been around a while and been successful, or if you already respect the team of people working on it. Less reliably, you can find snippets of code by searching and sharing code.

I love Emulators. They are magical. Earlier this year I interviewed Pete Brown when he created a C64 Emulator in Silverlight.

Now, it's Apple IIe time. From the Virtu Project Site, you can see that this source has been around in various forms for years...morphing from form to form.

Originally developed for RISC OS (3.11) on the Acorn Archimedes in 1995 using some C but mostly ARM assembly language. Published on the cover disk of the October 1997 issue of Acorn User. Later that year we started porting Virtu to Microsoft Windows (95) on the 'PC' using only C++ with DirectX. A port to Microsoft Windows CE (2.11) soon followed. These were tweaked over the next couple of years but never published. Fast forward to the present and the latest incarnation of Virtu, this time ported to the Microsoft .NET Framework (3.5 SP 1) using only C# with Silverlight, WPF and XNA (on both Windows and Xbox 360, which is limited to the .NET Compact Framework).

In this form, Virtu was written by Sean Fausett with some help from Nick Westgate. This code is interesting for a number of reasons. First, because it's a freaking AppleIIe emulator in a language I like to read (*cough* Not C *cough*), but also because it is cleanly structured and includes Silverlight (that means Mac also!), WPF and XNA (Xbox360) versions. It illustrates a way one can factor their code into an engine and various hosts.

IMPORTANT NOTE: To run, Virtu needs two files that are not included: An image of the standard or preferably the enhanced Apple IIe monitor ROM needs to be copied as 'AppleIIe.rom' (16 KB) to the Roms directory. An image of the Disk II (16 sector) interface card ROM needs to be copied as 'DiskII.rom' (256 bytes) to the Roms directory. You'll also need some disk in the form of a ".nib" file like RasterBlaster.nib, for example. I can't give you those files.

After a successful build, you should be able to run the emulator and perform a self test by pressing the hallowed key combination Control+OpenApple+CloseApple+Reset.

Looking at the WpfKeyboardService.cs, I can see how those keys I don't have are mapped to keys I do:

ModifierKeys modifiers = keyboard.Modifiers;
IsOpenAppleKeyDown = keyboard.IsKeyDown(Key.LeftAlt);
IsCloseAppleKeyDown = keyboard.IsKeyDown(Key.RightAlt);
IsResetKeyDown = ((modifiers & ModifierKeys.Control) != 0) && keyboard.IsKeyDown(Key.F12);

IsCpuThrottleKeyDown = keyboard.IsKeyDown(Key.F8);
IsVideoFullScreenKeyDown = keyboard.IsKeyDown(Key.F11);
IsVideoMonochromeKeyDown = keyboard.IsKeyDown(Key.F9);

Looks like that's ALT, ALT, CTRL, F12 which gives me a weird series of self test screens then "System OK" which is a good sign.

image

This is nice, now I can do a little Applesoft BASIC by booting to the monitor with Ctrl-F12 then typing this, then RUN.

10 TEXT:HOME
20 ?"HELLO WORLD"

Thrilling!

image

It's really fun code to read and it's a lot cleaner than you'd think for an emulator, although there's the expected Giant Scary Switch Statements here and there. Other parts definitely feel like they've been brought along from the past, although, how else would you do them? (Don't look in VideoData.cs, your face will melt.) For example, here's how they draw text (remembering that we're not using Fonts here, we've got a REALLY low res screen):

private void DrawText40(int data, int x, int y)
{
int color = Machine.Settings.Video.IsMonochrome ? ColorMono00 : ColorWhite00;
int index = _charSet[data] * CharBitmapBytes;
int inverseMask = (_isTextInversed && !_memory.IsCharSetAlternate && (0x40 <= data) && (data <= 0x7F)) ? 0x7F : 0x00;
for (int i = 0; i < TextHeight; i++, y++)
{
data = CharBitmap[index + i] ^ inverseMask;
SetPixel(x + 0, y, color | (data & 0x01));
SetPixel(x + 1, y, color | (data & 0x01));
SetPixel(x + 2, y, color | (data & 0x02));
SetPixel(x + 3, y, color | (data & 0x02));
SetPixel(x + 4, y, color | (data & 0x04));
SetPixel(x + 5, y, color | (data & 0x04));
SetPixel(x + 6, y, color | (data & 0x08));
SetPixel(x + 7, y, color | (data & 0x08));
SetPixel(x + 8, y, color | (data & 0x10));
SetPixel(x + 9, y, color | (data & 0x10));
SetPixel(x + 10, y, color | (data & 0x20));
SetPixel(x + 11, y, color | (data & 0x20));
SetPixel(x + 12, y, color | (data & 0x40));
SetPixel(x + 13, y, color | (data & 0x40));
}
}

In Silverlight, they use the same (only) technique that Pete Brown's C64 emulator used to use, the new WriteableBitmap class. This means the XAML is just a single Image, and everything is a dynamically generated Bitmap. Here's the SilverlightVideoService.cs:

namespace Jellyfish.Virtu.Services
{
public sealed class SilverlightVideoService : VideoService
{
public SilverlightVideoService(Image image)
{
_image = image;
SetImageSize();

_bitmap = new WriteableBitmap(BitmapWidth, BitmapHeight, BitmapPixelFormat);
_pixels = new uint[BitmapWidth * BitmapHeight];

Application.Current.Host.Content.Resized += (sender, e) => SetImageSize();
}

[SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "y*560")]
public override void SetPixel(int x, int y, uint color)
{
_pixels[y * BitmapWidth + x] = color;
_pixelsDirty = true;
}

public override void Update()
{
if (Application.Current.RunningOffline && /*_window.IsActive &&*/ (_isFullScreen != IsFullScreen))
{
_isFullScreen = IsFullScreen;
}

if (_pixelsDirty)
{
_pixelsDirty = false;
_bitmap.Lock();
for (int i = 0; i < BitmapWidth * BitmapHeight; i++)
{
_bitmap[i] = (int)_pixels[i];
}
_bitmap.Invalidate();
_bitmap.Unlock();
_image.Source = _bitmap; // shouldn't have to set source each frame; SL bug?
}
}

private void SetImageSize()
{
Content content = Application.Current.Host.Content;
int uniformScale = Math.Min((int)content.ActualWidth / BitmapWidth, (int)content.ActualHeight / BitmapHeight);
_image.Width = uniformScale * BitmapWidth;
_image.Height = uniformScale * BitmapHeight;
}

private const int BitmapWidth = 560;
private const int BitmapHeight = 384;
private static readonly PixelFormat BitmapPixelFormat = PixelFormats.Bgr32;

private Image _image;
private WriteableBitmap _bitmap;
private uint[] _pixels;
private bool _pixelsDirty;
private bool _isFullScreen;
}
}

It's a nice codebase and fun to step through. If you're interested in learning about emulation, check it out.

There are Wiki pages with details and quirks for each platform, WPF, XNA and Silverlight. There's still work to be done, so you might head over there and offer to help!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

It's a Man-Bag - Muzetto Laptop Messenger Bag Review

July 14, 2009 Comment on this post [28] Posted in Reviews
Sponsored By

muzetto_large_color_black_md Yes, this is a blog post about a Purse. I mean, a Murse, er, a Man-Bag. It's manly and I like it.

It's probably best you stop reading this now, as this post has no code. You've been warned. (This means you, Jeff.)

I like nice shoes, and I like nice bags. I'm always replacing whatever bag I have with a new bag, usually one that I get from a conference. Unfortunately these bags are often cheap nylon and they only last for a few months and they rarely look nice.

I was in the market for a great messenger bag, but one with a tech-person in mind. I wanted separate pockets for my laptop, my Moleskine notebook, USB keys and a few magazines. I shopped around, looked at LOTS of backpacks, then messenger bags. Then I remembered the bag company that I got my Amazon Kindle Sleeve from, SFBags.com (Waterfield). They just came out with a new vertical messenger back for laptops.

muzetto_large_inside_md It's called the "Muzetto" and comes in a 13" and 15" size. They've got a Laptop Sizer that will tell you what to get, given your Make and Model of Laptop.

I got the one with the back inside trim and dark brown leather. It holds my Lenovo T60p or W500 perfectly. I also put my Amazon Kindle and Moleskine in for the perfect hipster bag.

The only downside is that the bag bulges just a little bit when I add my laptops AC Adapter, which was a little disappointing. Just like laptop manufacturers always seem to design the AC Adapter last, and least, so do bag manufacturers. This bag would have been perfect if it had a little AC Adapter "side car" or something.

It is expensive, ranging from $179 to $259 for the largest size, but the quality is clear as soon as you touch it. It's made locally and it shows. I took the bag with me to Norway and it worked great at every point. It's looking a little weathered, as leather does, but it's still the best looking laptop bag I've ever had. Even Scott Bellware thinks it's fabulous!

This is my second item from SFBags/Waterfield and I've been very happy. If you're not into the whole leather/suede thing, they do nylon and more traditional bags for geeks as well.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Hanselminutes on 9 - OmniTechNews - I wasn't nearly this cool when I was 12

July 14, 2009 Comment on this post [2] Posted in Channel9 | Podcast | Reviews
Sponsored By

imageI wasn't nearly this cool when I was 12. We had a Nerd Dinner last time I was up visiting campus. We had nerds of various shapes and sizes, but three nerds stood out. They were tweens, and they're the proprietors of their own media empire, OmniTechNews.

They post product reviews, host a podcast and have their own YouTube Channel. They are truly the nerds of tomorrow, today. They've even got their own T-Shirt and Swag Shop.

I recorded an interview with them and I present to you, with Mom and Dad's permision, the gentlemen of OmniTechNews.

Hanselminutes on 9 - The Nerds of Tomorrow

Go check them out and subscribe! I think they'd especially appreciate it if you subscribed to them on YouTube.

Enjoy!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Cheesy ASP.NET MVC Project Upgrader for Visual Studio 2010 Beta 1

July 11, 2009 Comment on this post [8] Posted in ASP.NET MVC
Sponsored By

WARNING: This is obscure and you likely don't care.

As Phil mentioned a little while back, ASP.NET MVC didn't ship with Visual Studio 2010 Beta 1, but will ship with Visual Studio 2010 Beta 2 (and beyond.)

When VS10 Beta 2 comes out, you won’t need to download a separate standalone installer to get ASP.NET MVC (though a standalone installer will be made available for VS2008 users that will run on ASP.NET 3.5 SP1).

If you're using Visual Studio 2010 Beta 1 and want to use ASP.NET MVC, you can go get a drop of MVC for just this purpose, up on CodePlex.

This particular version of MVC is ONLY for use on Visual Studio 2010 Beta and is temporary. As such, it's got a placeholder version of 1.1, rather than 1.0.

If you have existing ASP.NET MVC 1.0 applications under .NET 3.5 lying around that you want to run them on VS 2010 Beta 1, you'll have to make some version number changes in your web.config.

I had a bunch of existing MVC apps lying around so I did this little upgrader application. It's poop, but it Works On My Machine©. Enjoy.

The code is here and is likely a blot on my soul. It will update the version numbers in the main web.config as well as the one in ~\views. It'll also make up to two backups, just in case.

The app is a .NET 4.0 Beta 1 Application and is zipped up here. You just run ASPNETMVCUpgrader "c:\path to your app"

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ASPNETMVCUpgrader
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("Usage: ASPNETMVCUpgrader c:\\pathtomyprojectdir");
System.Environment.Exit(1);
}

//Remember there's TWO, count 'em, TWO web.configs. Madness!
TidyUpFile(Path.Combine(args[0], "web.config"));
TidyUpFile(Path.Combine(args[0], "Views\\web.config"));
}

private static void TidyUpFile(string filename)
{
string oldMvcType = "System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35";
string newMvcType = "System.Web.Mvc, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35";

string oldRoutingLine = "<add name=\"UrlRoutingModule\" type=\"System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\"/>";
string newRoutingLine = "<add name=\"UrlRoutingModule\" type=\"System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\"/>";

if (!File.Exists(filename))
{
Console.WriteLine(String.Format("Can't find {0}. You sure it's there?", filename));
System.Environment.Exit(1);
}

//Fix up the references!
string webconfigtext = File.ReadAllText(filename);
string newwebconfigtext = webconfigtext.Replace(oldMvcType, newMvcType);
newwebconfigtext = newwebconfigtext.Replace(oldRoutingLine, newRoutingLine);

//Keep up to two backups
string backupWebConfig = Path.ChangeExtension(filename, ".mvc10backup");
if (File.Exists(backupWebConfig))
{
var twoIsEnough = Path.ChangeExtension(filename, ".mvc10backup2");
File.Delete(twoIsEnough);
File.Copy(backupWebConfig,twoIsEnough);
File.Delete(backupWebConfig);
}
File.Copy(filename, backupWebConfig);

File.WriteAllText(filename, newwebconfigtext);

//Toot!
Console.WriteLine(String.Format("Updated MVC 1.0 references to MVC 1.1 for Dev10 Betas. \n Created a {0} backup. Toot.", filename));
}
}
}

Enjoy.

Extra Credit: If you'd like to show off for no reason, feel free to rewrite this application in as few lines as possible (but still in C#, Ruby people) and post in the comments.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Hanselminutes on 9 - The .NET Micro Framework with Colin Miller

July 10, 2009 Comment on this post [3] Posted in Podcast | Programming
Sponsored By

image

I'm was Building 42 yesterday and stopped by the offices of Colin Miller. He runs the .NET Micro Framework, which is a "Tiny CLR" and supporting libraries that run on embedded systems in as little as 32k! (although usually more). There's 1.5 million devices running the .NET Micro Framework.

Check out the Video at Channel 9, it's short, sweet and to the point and Colin covers a lot of ground. It's also the first video that I filmed and posted in 16:9 720p without changing the aspect ratio, so let me know if you like the video quality.

This means that C# developers with little or NO background in electronics can create very sophisticated hardware systems including sensors, servos, whatever! Colin gives me the whole scoop and explains how the whole thing works from Virtual Machine to Firmware to Hardware.

Getting Started with .NET Micro Framework

1. About .NET Micro Framework

2. Get .NET Micro Framework

3. Learn .NET Micro Framework

I'm going to take a look at this and see how it can improve my arcade machine with some touch-screens and maybe a tilt-sensor for pinball. ;)

You don't need hardware to get stared as there's an emulator. I've got a small starter development point, though, and I'll post more as I explore.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.