每周源代码44-Virtu,这是一个使用C#的Apple模拟器,用于Silverlight,WPF和XNA

博客介绍了Virtu,这是一个用C#编写的Apple IIe模拟器,可在Silverlight,WPF和XNA上运行。作者强调了阅读源代码对于开发者成长的重要性,并分享了如何运行和使用该模拟器的细节。代码结构清晰,使用了WriteableBitmap类来绘制文本,提供了在不同平台上实现模拟器的示例。
摘要由CSDN通过智能技术生成

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.

我爱模拟器。 他们是神奇的。 今年早些时候,我采访了皮特·布朗(Pete Brown)在Silverlight中创建C64仿真器的过程

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.

现在,该到Apple IIe了。Virtu项目站点上,您可以看到该源已经以多种形式存在了很多年……形式之间不断变化。

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).

最初是1995年在Acorn Archimedes针对RISC OS (3.11)开发的,使用的是C语言,但大多数都是ARM汇编语言。 发布在Acorn User的1997年10月版封面上 那年下半年,我们开始仅使用带有DirectX的C ++将Virtu移植到“ PC”上的Microsoft Windows (95) 紧随其后的Microsoft Windows CE (2.11)的端口 这些在接下来的几年中进行了调整,但从未发布过。 快进到Virtu的当前和最新版本,这次仅使用C#以及Silverlight WPFXNA (在Windows和Xbox 360均受限于.NET )移植到Microsoft .NET Framework (3.5 SP 1)紧凑框架)。

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.

在这种形式下,Virtu由Sean Fausett撰写,并得到了Nick Westgate的帮助。 出于许多原因,此代码很有趣。 首先,因为它是一种我喜欢阅读的语言(*咳嗽*不是C *咳嗽*),却是一种令人难以置信的AppleIIe模拟器,而且还因为它的结构清晰且包含Silverlight(这也意味着Mac!),WPFXNA(Xbox360)版本。 它说明了一种可以将其代码分解为引擎和各种主机的方法。

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.

重要说明:要运行, Virtu需要两个不包含的文件标准或最好是增强型Apple IIe监视器ROM的映像需要作为“ AppleIIe.rom”(16 KB)复制到Roms目录中。 Disk II(16扇区)接口卡ROM的映像需要作为“ DiskII.rom”(256字节)复制到Roms目录。 例如,您还需要一些“ .nib”文件形式的磁盘,例如RasterBlaster.nib。 我不能给你那些文件。

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.

成功构建之后,您应该能够通过按组合键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:

查看WpfKeyboardService.cs,我可以看到没有的那些键如何映射到我做的键:

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.

看起来是ALT,ALT,CTRL,F12,这给了我一系列奇怪的自检屏幕,然后是“ System OK”,这是一个好兆头。

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

很好,现在我可以通过使用Ctrl-F12引导到显示器,然后键入此代码,然后运行,来做一点Applesoft BASIC。

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):

这是一个非常有趣的代码,比您想像的模拟器要干净得多,尽管到处都有预期的Giant Scary Switch语句。 其他部分肯定会感觉它们是从过去带入的,但是,您还怎么做? (不要在VideoData.cs中查看,您的脸会融化。)例如,这是他们绘制文本的方式(请记住,这里我们没有使用Fonts,我们的屏幕分辨率非常低):

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:

在Silverlight中,他们使用与Pete Brown的C64模拟器曾经使用过的相同(唯一)技术,即新的WriteableBitmap类。 这意味着XAML只是一个图像,所有内容都是动态生成的位图。 这是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!

Wiki页面包含有关每个平台, WPFXNASilverlight的详细信息和怪癖。 仍有工作要做,所以您可能会去那里并提供帮助

翻译自: https://www.hanselman.com/blog/the-weekly-source-code-44-virtu-an-apple-emulator-in-c-for-silverlight-wpf-and-xna

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值