📄 aehowto.txt
字号:
you out. Pascal is dead as a new development language, except maybe for
hobbyists, though I must admit Borland did a pretty damn good job of
making Turbo Pascal a viable entity. With all of their extensions and
nicities, it rivals C in its functionality. The same holds true for Visual
Basic. It's not really BASIC in the literal sense anymore - it's a C-like
language. The other reason is that about 95% of the CPU emulators I've
found are written in C. I think I found 1 that was written in Pascal.
[If you decide to use C++] you'll never make it on anything less
than a Penitum Pro 200. CPU emulation is very time consuming, and even
a single instruction or two can kill processor performance. To give you
an idea, my original 6502 emulator ran at 1.2MHZ when written in
optimized C (not C++). That was on a Pentium 120, and I'm no slouch
when it comes to optimizing. I rewrote my 6502 emulator in 32 bit
assembly and it's running at 15MHZ. Compilers are still no match for
a seasoned assembly programmer. Add in the extra overhead [of C++], and
you're toast. You'll never get good performance out of OO CPU emulation
code... Add in big-time overhead for class alignment [and the] CPU
emulator will be HORRIBLY slow... This is a really bad place to use C++.
C++ has its place in UI and API abstraction, but when you're talking
performance it's a *BAD* idea... Not to be too frank, but writing
something like a CPU emulator in C++ would be considered shitty
programming practice. ;-) If you'll notice, all well-performed emulators
are written in assembly - at least as far as the CPU emulation goes."
Mike Perry adds:
"I can tell you now that you do NOT want to use Delphi. Delphi is for
rapid prototyping and for developing graphical applications. An emulator
is not an application that is suited for development in Delphi.
Additionally, Delphi applications are only usable in Win95 and NT.
DOS, being a single user, single-tasking OS, is more likely to bring
better performance. [Using] Pascal is a possibility but Borland Pascal
has serious limitations in terms of efficiency. For instance, someone
was handling opcodes using a case statement
case op1: blah blah blah; return;
case op2: blah blah blah; return;
case op3: blah.....; return;
....
Now any reasonable C compiler, including Borland C++, converts this to
a jump table (ie, code array) for fast case determination. BPascal
on the other hands generates a series of mov, cmp (compare) and jmp
instructions, like a big if-else. This means that opcode 212 will
take around (212 * 4) cycles just to GET to the code using BPascal
while it takes less than 6 cycles using C!! Even if you DO use C,
your task is made MUCH easier using inline assembly. Better yet,
make assembly the main language and link in external C or pascal
function if necessary. The graphics routines should DEFINITELY
be in assembly. [You] WILL be better off learning [assembly]."
Dave Spicer warns:
"IMHO, writing an emulator in Pascal is not a particulatly good idea.
You'll be emulating machine code, so you want something that resembles
that in form."
Q.3.1 Do I *have* to use Assembly?
Neil Bradley says:
"Regardless of what some academics would like to believe, a compiler
can't outclass a good assembly programmer. You'll spend plenty of time
optimizing, and if you rewrote it in assembly, you're almost assuredly
going to get a 30-40% speed improvement. C compilers (and others for
that matter) solve for the general case, and make assumptions on what
registers/variables need to be saved. In assembly, you know the code,
and can write, at the CPU level, and write the most optimal instruction
sequence to match the common-case path of your code.
You really do need to know assembly to do a project like this - that is
to do it in an effective amount of time."
Mike Perry says:
"Normally I would not recommend writing an application primarily or
entirely in assembly. Assembly is minimally portable and if an
application spends 90% of its time executing 5% of its code, it does
precious little good to hand optimize the remaining 95% in assembly.
An emulator, on the other hand, is not your normal application. An
emulator's job is to emulate hardware. In emulation, you will be dealing
with registers, memory addressing and memory reads/writes. The
instructions the real processors use to do this sort of stuff are very
"basic". They are so basic that its actually easier to use x86 asm and
the intel registers to do what you want than it is to use a high level
language. Assembly makes it easy to manipulate 8-bit, 16-bit and 32-bit
values. C and Pascal make it downright tedious to manipulate more than
one size variable in an expression. At the least, your HLL code will
contain many many typecasts, making it very hard to read."
Q.3.1.1 Are you SURE about this Assembly business? :)
Paul Kahler points out:
"A number of people indicated that assembly is the only way to get good
performance on anything short of a pentium pro. I'd just like to say that
the first rev of the Cinematronics emulator was written in TURBO PASCAL
and seemed to run just fine on a Pentium-90. That was almost 2 years ago,
so we were trying to run on a 486 and had to move on to assembly. TP
allowed me to create an array of functions so I could grab the opcode and
call the proper function. That's really good performance considering the
CineProcessor doesn't map at all to x86 or anything else, and it ran at
1.7 MIPS! A 6502 should be no problem for C code on a Pentium or even a
486. But then there's graphics and sound also... I just wanted to point
out that ASM isn't the only way to go, and if you do things in C they'll
be portable. BTW I used the BGI drivers for the vector display back then
too!"
Pete Rittwage adds:
"I've been able to get stellar performance out of my 6502 purely in C,
including graphics overhead, even on my lowly 486/100.
I've also seen people get pretty good performance out of Marat's Z80 code
in such things as the Donkey Kong emulators, and that code is FAR from
optimized. It accesses things a couple of structures deep at times, which
is very inefficient."
Q.3.1.2 Doesn't the choice of language depend on the target game/system?
Neil Bradley clears things up:
"Writing an emulator strictly in C++, including CPU emulation and graphics
emulation will not give you good performance on anything short of a
pentium pro. The author of the Tempest emulator that runs under Windows
runs fine at 150MHZ, and it's written in C. If that's your target
platform, great. And if your target platform is a 486/66 and your graphics
are heavily intensive or running on a slow ISA card, you better not use C
or C++. To give you some benchmarks on some "famous" CPU emulators, here
are some #'s (not including graphics - just RAW CPU time) that indicate
the emulated speed on a 486/66 running Asteroids, compiled under Watcom
C++ 10.6 with the 486 compile option thrown:
Emulator Emulated speed
Marat's 6502 1.6MHZ
Apple IIe emu 800KHZ
Optimized Apple IIe emu 1.9MHZ
EMU's first 6502 C emulator 2.5MHZ
EMU's 100% Assembly 6502 6.8MHZ
My background is assembly & C optimization. I've spent greater than 20
years on numerous processors, and have programmed everything from tiny
microcontroller circuits to multi-CPU applications, so I'm no slouch when
it comes to C or assembly optimization. ;-) . The results above speak for
themselves. Keep in mind that there aren't any graphics routines or sound
routines in this code under this test.
So I'll reiterate what I've tried to say in the past: If your target
machine is a 486/66 with a crappy ISA card, you'd better squeeze
everything out of the emulator that you possibly can, because you'll need
it. EMU Uses a single page of 256 color graphics. It erases the prior
frame and draws the new one. Typical frames are 300 vectors. 600 Lines per
"frame", and roughly 25 frames per second. That's 15000 lines per second
that must be drawn, and if we say that the average line is 50 pixels,
that's 750,000 pixels a second.
Most games, such as Donkey Kong or Space Invaders aren't coming even close
to moving that many pixels on the screen. So in that case, you can get
away with having a less than totally optimized CPU. But with EMU, I
couldn't get away with it. There was too much to do. Linedraws are
extremely expensive, and I spent days working on high speed linedraw
routines (those of you who've been with EMU since the early days know what
I'm talking about).
The point I'm trying to make is that the more you optimize your CPU
emulation, the less of an impact it will have on your graphics emulation,
and the faster your code will run on a slower machine. If you want to make
your minimum platform a Pentium 166, you can probably get away with
writing it in Quick Basic.
I want as little intrusion from the CPU emulation as I possibly can get,
and I got better emulation by almost a factor of 3 by rewriting it in
assembly.
I don't think anyone said that ASM was the only way to go. I remember
saying that it is the most optimal way to go."
Laurent Desnogues says:
"I got a two times speed-up when converting a 6809 emulator written in C
to SPARC assembly language.
So I'm one of the exceptions... I wrote a Phoenix emulator that should
run on any Unix/X platform (one or eight graphics planes); it uses Marat's
Z80 emulator package and I get decent speed even on low end Suns. The
problem with Unix is that most of its implementations can not handle
real-time programs; the game often freezes while the kernel is doing
internal jobs... So I have to admit these platforms are not very well
suited to arcade game playing; but programming an emulator is by itself
enjoing, isn't it?"
Q.3.1.3 What about portability?
Neil Bradley answers:
"Just because you do things in C doesn't mean they're portable. There
are basically two platforms that need any attention for gaming: PC & Mac.
That's it. I don't know of anyone owning a Silicon Graphics workstation
saying to themselves, "Gee, wouldn't it be cool to fire up an emulated
version of Space Invaders on this thing?". The people I know who own
SparcStations or run Unix aren't interested in emulation or gaming in
general. Granted there are exceptions to that rule, but for the most part
the "other" platforms aren't really in the running.
But if I'm forced into a corner where I can get 3X performance out of
something by coding it in assembly for a platform I know, I'll do it and
blow off "portability". At the same time, as I've said before, I'd gladly
help out others on other platforms, giving them hints and helping them
with their emulation projects that are for a platform that I'm not
familiar with.
Besides, most code written to be "portable" isn't. It starts off that way,
but ends up using OS specific calls to improve speed, etc... The road to
non-portable code is paved with portability in mind. ;-) BTW, I run Unix
on synthcom, Win 95 on my sequencer/sound studio, Windows NT 4.0 Server on
one of my development machines, and DOS on the other. Guess which one I
use for games..."
Q.3.2 But haven't some arcade emulators been written in C/C++?
According to what I've heard, C and C++ have been *used* in some
emulators, but an entire emulator has not been written in only C or C++.
Neil Bradley says:
"Name one emulator that was written in C++ that runs reasonably on
anything less than a Pentium Pro 200. ;-) I don't know of an emulator that
is ENTIRELY written in C. EMU, for example, is written in C and assembly.
C for all the glue code and non-speed critical things, and assembly for
everything else. That's why it runs reasonably on a 486/66 with a decent
PCI video card.
[Chris Hardy's Phoenix emulator was coded in VC++ using Direct/X...
Note that it was written in C (not C++!) and compiled on VC++]
Not to lessen anything that Chris has done, but Phoenix isn't exactly a
CPU hogging game, as is something like Tempest, Battle Zone, or Red Baron.
The vector emulation is very time consuming, and even the originals slow
down in spots."
Q.3.3 What about Java?
Neil Bradley, after cringing in terror, says:
"The only way that you'd even have a prayer to get something to run fairly
quickly in Java is to make sure the client compiles it for their native
CPU (Visual J++, anyone?). In the case where you write an emulator in
Java, and it runs on a browser, you'd have an interpreter interpreting an
interpreter of a CPU in addition to the interpreter interpreting the
hardware actions as well. Interpreted Java is not built for speed.
The guys at Microsoft are getting almost identical performance out of
Visual J++ as the Visual C++ guys are (according to a Java proponent at
the last PDC), so compiled Java apps are a possibility.
It's hard enough getting optimal assembly emulations to run at full tilt
on a 486/66 without having an interpreter interpreting the emulator. Your
hit by doing that would be about 30:1.
If we had 2 Gigahertz Pentium PROs, it might be possible, but not with the
speed of the Java virtual machine interpreter. Don't bother unless you're
compiling it. You might have a chance then, but interpreted, no way. I
wouldn't bother trying it. ;-)"
Q.4 Could you explain CPU emulation?
The CPU emulation is the heart of any emulator. If the code is correct,
it will handle the ROM data, so you don't necessarily have to worry about
how the game ROM itself operates.
Since the CPU is the 'brains' of the machine, it can get very complicated.
Neil Bradley had this to say:
"When doing something with the Z80, for example, it's quite extensive.
You've got the functions of 300+ opcodes to deal with, and permutations.
Not to mention that some arcade manufacturers' code use the Z80
'undocumented' opcodes (though they're not so 'undocumented' anymore...).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -