Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
9837 turbocat 1
Multi-Z80 32 Bit emulator
2
Copyright 1996, 1997, 1998, 1999, 2000 - Neil Bradley, All rights reserved
3
 
4
			    MZ80 License agreement
5
			    -----------------------
6
 
7
(MZ80 Refers to both the assembly code emitted by makez80.c and makez80.c
8
itself)
9
 
10
MZ80 May be distributed in unmodified form to any medium.
11
 
12
MZ80 May not be sold, or sold as a part of a commercial package without
13
the express written permission of Neil Bradley (neil@synthcom.com). This
14
includes shareware.
15
 
16
Modified versions of MZ80 may not be publicly redistributed without author
17
approval (neil@synthcom.com). This includes distributing via a publicly
18
accessible LAN. You may make your own source modifications and distribute
19
MZ80 in source or object form, but if you make modifications to MZ80
20
then it should be noted in the top as a comment in makez80.c.
21
 
22
MZ80 Licensing for commercial applications is available. Please email
23
neil@synthcom.com for details.
24
 
25
Synthcom Systems, Inc, and Neil Bradley will not be held responsible for
26
any damage done by the use of MZ80. It is purely "as-is".
27
 
28
If you use MZ80 in a freeware application, credit in the following text:
29
 
30
"Multi-Z80 CPU emulator by Neil Bradley (neil@synthcom.com)"
31
 
32
must accompany the freeware application within the application itself or
33
in the documentation.
34
 
35
Legal stuff aside:
36
 
37
If you find problems with MZ80, please email the author so they can get
38
resolved. If you find a bug and fix it, please also email the author so
39
that those bug fixes can be propogated to the installed base of MZ80
40
users. If you find performance improvements or problems with MZ80, please
41
email the author with your changes/suggestions and they will be rolled in
42
with subsequent releases of MZ80.
43
 
44
The whole idea of this emulator is to have the fastest available 32 bit
45
Multi-Z80 emulator for the x86, giving maximum performance.
46
 
47
                         MZ80 Contact information
48
			  -------------------------
49
 
50
Author      : Neil Bradley (neil@synthcom.com)
51
Distribution: ftp://ftp.synthcom.com/pub/emulators/cpu/makez80.zip (latest)
52
 
53
You can join the cpuemu mailing list on Synthcom for discussion of Neil
54
Bradley's Z80 (and other) CPU emulators. Send a message to
55
"cpuemu-request@synthcom.com" with "subscribe" in the message body. The
56
traffic is fairly low, and is used as a general discussion and announcement
57
for aforementioned emulators.
58
 
59
 
60
			     MZ80 Documentation
61
			     -------------------
62
 
63
MZ80 Is a full featured Z80 emulator coded in 32 bit assembly. It runs well
64
over a hundred games, in addition to it supporting many undocumented Z80
65
instructions required to run some of the Midway MCR games, Galaga, and
66
countless other wonderful Z80 based arcade games.
67
 
68
MZ80 Contains a makez80.c program that must be compiled. It is the program
69
that emits the assembly code that NASM will compile. This minimizes the
70
possibility of bugs creeping in to MZ80 for the different addressing modes
71
for each instruction. It requires NASM 0.97 or greater.
72
 
73
The goal of MZ80 is to have a high performance Z80 emulator that is capable
74
of running multiple emulations concurrently at full speed, even on lower-end
75
machines (486/33). MZ80 Harnesses the striking similarities of both the Z80
76
and the x86 instruction sets to take advantage of flag handling which greatly
77
reduces the time required to emulate a processor, so no extra time is spent
78
computing things that are already available in the native x86 processor,
79
allowing it to perform leaps and bounds over comparable C based Z80 emulators
80
on the same platform.
81
 
82
MZ80 Is designed exclusively for use with NASM, the Netwide Assembler. This
83
gives the ultimate in flexibility, as NASM can emit object files that work
84
with Watcom, Microsoft Visual C++ (4.0-current), DJGPP, Borland C++, and
85
gcc under FreeBSD or Linux. MZ80 Has been tested with each one of these
86
compilers and is known to work properly on each.
87
 
88
 
89
			    What's in the package
90
			    ---------------------
91
 
92
MZ80.TXT               - This text file
93
 
94
MAKEZ80.C              - Multi Z80 32 Bit emulator emitter program
95
 
96
MZ80.H                 - C Header file for MZ80 functions
97
 
98
 
99
			  What's new in this release
100
			  --------------------------
101
 
102
Revision 3.4:
103
 
104
	* Fixed the overflow flag not getting cleared in the SetOverflow()
105
	  routine. It caused strange problems with a handful of Genesis games
106
	* Removed invalid instruction in the C version so that more
107
	  instructions will execute
108
 
109
Revision 3.3:
110
 
111
	* Undocumented opcodes added to the C emitter
112
	* Bug fix to the C emission that properly handles shared RAM regions
113
	  (I.E. with handlers that are NULL)
114
	* Now using 32 bit registers to do register/memory access. Slight
115
	  speed increase (assembly version only)
116
 
117
Revision 3.2:
118
 
119
	* R Register emulation now accurate with a real Z80
120
	* mz80int() Called when interrupts are disabled causes the
121
	  z80intPending flag to be set, and an interrupt will be caused after
122
	  the execution of EI and the next instruction. See "IMPORTANT NOTE
123
	  ABOUT INTERRUPTS" below
124
	* The instruction after EI executes fully before interrupt status is
125
	  checked. (as does a real Z80)
126
 
127
 
128
Revision 3.1:
129
 
130
	* Fixed bug in memory dereference when handler was set to NULL (keeps
131
	  system from crashing or faulting)
132
	* Removed the only stricmp() from the entire file and replaced it
133
	  with strcmp() so that stdlibs without it will compile
134
	* Changed cyclesRemaining > 0 to cyclesRemaining >= 0 to be compatible
135
	  with the ASM core
136
	* Removed additional sub [dwCyclesRemaining], 5 at the beginning of
137
	  mz80exec() (ASM Core only). Increases timing accuracy.
138
	* NMIs And INTs add additional time to dwElapsedTicks as it should
139
	* mz80ReleaseTimeslice() Sets remaining clocks to 0 instead of 1
140
 
141
 
142
Revision 3.0:
143
 
144
	* All instructions validated against a real Z80. Used an ISA card
145
	  with a Z80 on it to validate flag handling, instruction handling,
146
	  timing, and other goodies. The only thing not implemented/emulated
147
	  is flag bit 3 & 5 emulation. Believed to be 100% bug free!
148
	* 80% Speed improvement over version 2.7 of mz80
149
	* z80stb.c Removed. Use -c to emit a C version of mz80! API compatible!
150
	  Note that this is mostly, but not fully, debugged, so consider the
151
	  C version a beta! It's at least healthier than z80stb.c was. The C
152
	  version does not include the undocumented Z80 instructions.
153
	* mz80nmi() No longer trashes registers it uses when using -cs
154
	* IN/OUT Instructions work properly when using -16
155
	* IN A, (xxh) uses A as high 8 bits of I/O fetch address when using -16
156
	* IM 0/IM 1 Description in documentation fixed
157
	* Sizes of all context registers increased to 32 bits - for speed!
158
	* IFF1/IFF2 Now properly emulated
159
	* JR Instruction offset can fetch from $ffff and properly wrap
160
	* LDIR/LDDR Instruction now won't go to completion - instead it will
161
	  run until BC=0 or the # of cycles to execute have expired. These
162
	  instructions used to run to completion - even beyond the # of cycles
163
	  left to execute
164
	* INI/IND/INIR/INDR countdown bug fixed - it was decrementing B twice
165
	  for each IN! Whoops!
166
	* If you specify NULL as a handler address to a memory region, mz80 will
167
	  use vpData as a pointer to where that block of data resides. Quite
168
	  useful for multiprocessor emulations that share the same memory.
169
	* EDI Now keeps track of cycle counting for faster execution
170
	* Modified memory region scanning code to use 32 bit registers instead
171
	  of their 16 bit counterparts
172
	* Get/SetContext() uses rep movsd/movsb. Insignificant overall, but
173
	  why waste the time?
174
	* Debugging routines added. See the "DEBUGGING" section below for more
175
	  information. NOTE: The debugging routines are not yet available in
176
	  the C emission.
177
	* Timing done slightly differently now. Mz80 now executes one
178
	  instruction past the timing given on input. For example, mz80exec(0)
179
	  will cause a single instruction to be executed (thusly -ss was
180
	  removed).
181
 
182
Revision 2.7:
183
 
184
	* Fixed OTIR/OTDR/INIR/INDR instructions so their 16 bit counterparts
185
	  work properly
186
	* Emulation core 30-70% faster overall than 2.6 due to optimization to
187
	  the timing routines
188
	* Replaced word reads/writes with a special word write routine rather
189
	  than the standard calling to read/write byte functions
190
	* z80stb.c (the C equivalent of mz80) compiles properly now
191
	* Fixed OS/2 text/segment issue
192
	* Fixed bug in set/getCPU context that ensures that ES=DS and avoids
193
	  crashes. Caused crashes under OS/2 and other OS's
194
 
195
Revision 2.6:
196
 
197
	* Emulator core 5-30% faster overall. Some 16 and 8 bit instructions
198
	  sped up when using their 32 bit equivalents.
199
	* Fix to -l so that proper labels without leading and trailing
200
	  underscores so Linux/FreeBSD compiles will work properly
201
	* Single step now executes the # of instructions passed in to z80exec()
202
	  instead of just 1 as it had in prior releases. This is only active
203
	  when the -ss option is used.
204
	* The -nt option was added. This will cause the timing information to
205
	  not be added in, speeding up execution. Warning: Only do this if your
206
	  emulated target does not require instruction timing!
207
	* Updated documentation errors
208
	* C Version of mz80 (mz80.c) that is API compliant is distributed with
209
	  the archive (With kind permission of Edward Massey).
210
 
211
Revision 2.5:
212
 
213
	* Fixed an unconditional flag being cleared in the ddcbxx instructions.
214
	  It caused Donkey Kong's barrels to not roll.
215
 
216
Revision 2.4:
217
 
218
	* Fixed improper HALT handling (didn't advance the PTR when it should)
219
	* Fixed SRL (IX+$xx) instruction so that carry wasn't trashed
220
	* Fixed single stepping problems with it giving too much time to
221
	  any given instruction
222
	* Fixed half carry flag handling with 16 bit SBC and ADD instructions
223
	* Fixed DAA emulation so that parity flags weren't getting trashed
224
 
225
Revision 2.3:
226
 
227
	* Fixed many stack handling bugs
228
	* Timing problems fixed. The prior version was causing massive
229
	  overruns on maximum timeslices with some insutructions.
230
 
231
Revision 2.2:
232
 
233
	* Fixed a bug in CPI/CPD/CPIR/CPDR that mishandled flags
234
	* All known bugs are out of mz80 now
235
	* Added the -cs option to route all stack operations through the
236
	  handlers (required for games like Galaga)
237
 
238
Revision 2.1:
239
 
240
	* Fixed a bug in CPI/CPD/CPIR/CPDR that caused intermittent lockups.
241
	  Also fixed a bug that caused erratic behavior in several video games.
242
	* Added INI/IND/INIR/INDR instruction group
243
	* Added OUTI/OUTD/OTIR/OTDR instruction group
244
 
245
Revision 1.0:
246
 
247
	* First release! The whole thing is new!
248
 
249
 
250
ASSEMBLING FOR USE WITH WATCOM C/C++
251
------------------------------------
252
 
253
Watcom, by default, uses register calling conventions, as does MZ80. To
254
create a proper emulator for Watcom:
255
 
256
	makez80 MZ80.asm -x86
257
 
258
From here:
259
 
260
	nasm -f win32 MZ80.asm
261
 
262
Link the MZ80.obj with your Watcom linker.
263
 
264
 
265
ASSEMBLING FOR USE WITH MICROSOFT VISUAL C++ AND BORLAND C++
266
--------------------------------------------------------------------
267
 
268
Visual C++ and Borland C++ use stack calling conventions by default. To
269
create a proper emulator for these compilers:
270
 
271
	makez80 MZ80.asm -s -x86
272
 
273
For Visual C++ or Borland C++:
274
 
275
	nasm -f win32 MZ80.asm
276
 
277
Link with your standard Visual C++ or Borland C++.
278
 
279
 
280
ASSEMBLING FOR USE WITH DJGPP, GCC/FREEBSD, OR GCC/LINUX
281
--------------------------------------------------------------------
282
 
283
DJGPP Uses stack calling conventions:
284
 
285
	makez80 MZ80.asm -s -x86
286
 
287
To assemble:
288
 
289
	nasm -f coff MZ80.asm
290
 
291
Link with your standard DJGPP linker. The same holds true for GCC under
292
FreeBSD or Linux. If you're using GCC, use the -l option to generate "plain"
293
labels so that gcc's linker will properly link things.
294
 
295
 
296
MAKEZ80 COMMAND LINE OPTIONS
297
----------------------------
298
 
299
-s	- Use stack calling conventions (DJGPP, MSVC, Borland, etc...)
300
 
301
-cs	- Force all stack operations to go through the Read/Write memory handlers.
302
	  This slows things down, but is useful when needed.
303
 
304
-16	- Treat all I/O input and output as 16 bit (BC)
305
 
306
-l	- Create 'plain' labels - ones without leading and trailing underscores
307
 
308
-nt	- Do not generate timing code - this speeds the emulator up, but the
309
	  downside is that no timing info is available.
310
 
311
-c	- Emit a C mz80 emulator (API Compatible with the assembly version -
312
	  handy for porters!)
313
 
314
-x86	- Emit an assembly (x86) mz80 emulator
315
 
316
-os2	- Generate OS/2 compatible segmentation
317
 
318
 
319
IMPORTANT NOTE ABOUT INTERRUPTS
320
-------------------------------
321
 
322
A minor change was made between the 3.1 and 3.2 versions of makez80 in the
323
way that interrupts were handled.
324
 
325
On a real Z80, the !INT line is a level triggered interrupt, meaning that if
326
the interrupt line is held low, the Z80 will continue to take interrupts
327
immediately after the instruction after the EI instruction is executed until
328
the interrupt line is high again.
329
 
330
In 3.1, if an interrupt came in and interrupts were disabled, the interrupt
331
would never be "latched" for later execution. The Z80 does not have any
332
internal latching capabilities, however external hardware often does hold
333
the interrupt line low until the interrupt is executed, in effect, a latch.
334
 
335
I've only found one video game so far that requires the "raising/lowering"
336
of the interrupt line (Ataxx). In the games that I've tried, it has improved
337
performance, in some cases drastically, and in others not at all. This can
338
be accounted for by interrupts being taken now, where they were being dropped
339
in prior mz80 releases.
340
 
341
mz80 Emulates the most commonly used scenario. Now when mz80int() is executed
342
and a nonzero value is returned (indicating interrupts were disabled), it
343
will set z80intPending, and the interrupt will be taken after execution of
344
one instruction beyond the EI instruction.
345
 
346
So now, if mz80int() returns a nonzero value, that means an interrupt is
347
latched. If clearing this latch is desired or the old behavior of 3.1 is
348
desired, make a call to the mz80ClearPendingInterrupt() call. It's a 2
349
instruction call that has extremely small overhead and will not affect
350
performance in any measurable way.
351
 
352
In any case, MZ80 will now execute one instruction after EI regardless of
353
how much time is available to avoid the possibility of an interrupt request
354
coming in directly after the EI instruction.
355
 
356
 
357
STEPS TO EMULATION
358
------------------
359
 
360
NOTE: -16 Is a command line option that will treat all I/O as 16 bit. That
361
is, in an instruction like "IN AL, (C)", the addressed passed to the I/O
362
handler will be BC instead of just C. Bear this in mind when considering your
363
emulated platform.
364
 
365
There are a few steps you want to go through to get proper emulation, and a
366
few guidelines must be followed.
367
 
368
1) Create a MZ80CONTEXT
369
 
370
2) Create your virtual 64K memory space using whatever means of obtaining
371
   memory you need to do.
372
 
373
3) Set mz80Base in your context to be the base of your 64K memory space
374
 
375
4) Load up your image to be emulated within that 64K address space.
376
 
377
5) Set z80IoRead and z80IoWrite to their appropriate structure arrays. Here's
378
   an example:
379
 
380
struct z80PortRead ReadPorts[] =
381
{
382
	{0x10,	0x1f,	SoundChip1Read},
383
	{0x20,	0x2f,	SoundChip2Read}
384
	{(UINT32) -1,     (UINT32) -1, NULL}
385
};
386
 
387
When an IN instruction occurs, mz80 will probe this table looking for a
388
handler to the address of the "IN" instruction. If it is found in the list,
389
it's up to the handler to return the proper value. Otherwise, a value of
390
0ffh is returned internally if no handler for that I/O address is found. In
391
the case above, SoundChip1Read is called when the I/O address is between 0x10-
392
0x1f. A similar structure is used for I/O writes as well (OUT):
393
 
394
struct z80PortWrite WritePorts[] =
395
{
396
	{0x20,	0x2f,	SoundChip2Write},
397
	{0x30,	0x36,	VideoCtrlWrite},
398
	{(UINT32) -1, 	(UINT32) -1, NULL}
399
}
400
 
401
Of course, this does the opposite that the z80PortRead struct, and instead
402
looks for a handler to hand some data to. If it doesn't find an appropriate
403
handler, nothing happens.
404
 
405
6) Set mz80MemoryRead & mz80MemoryWrite to their appropriate structure
406
   arrays. Here is an example:
407
 
408
struct MemoryWriteByte GameWrite[] =
409
{
410
	{0x3000, 0x3fff,  VideoWrite},
411
	{0x4000, 0x4fff,  SpriteWrite},
412
	{(UINT32) -1,     (UINT32) -1, NULL}
413
};
414
 
415
The above example says that any time a write occurs in the 0x3000-0x3fff
416
range, call the VideoWrite routine. The same holds true for the SpriteWrite
417
region as well.
418
 
419
NOTE: When your write handler is called, it is passed the address of the
420
write and the data that is to be written to it. If your handler doesn't
421
write the data to the virtual image, the mz80 internal code will not.
422
 
423
NOTE: These routines will *NOT* be called when execution asks for these
424
addresses. It will only call them when a particular instruction uses the
425
memory at these locations.
426
 
427
If you wish for a region to be RAM, just leave it out of your memory region
428
exception list. The WriteMemoryByte routine will treat it as read/write
429
RAM and will write to mz80Base + addr directly.
430
 
431
If you wish to protect ROM regions (not often necessary), create a range that
432
encompasses the ROM image, and have it call a routine that does nothing. This
433
will prevent data from being written back onto the ROM image.
434
 
435
Leave your last entry in the table as shown above, with a null handler and
436
0xffffffff-0xffffffff as your read address. Even though the Z80 only
437
addresses 64K of space, the read/write handlers are defined as 32 bit so
438
the compiler won't pass junk in the upper 16 bits of the address lines. Not
439
only that, it allows orthoganality for future CPU emulators that may use
440
these upper bits.
441
 
442
You can do a mz80GetContext() if you'd like to read the current context of
443
the registers. Note that by the time your handler gets called, the program
444
counter will be pointing to the *NEXT* instruction.
445
 
446
struct MemoryReadByte GameRead[] =
447
{
448
	{0x2000,        0x200f,         ReadHandler},
449
	{(UINT32) -1,     (UINT32) -1,  NULL}
450
};
451
 
452
Same story here. If you have a special handler for an attempted read at a
453
particular address, place its range in this table and create a handler
454
routine for it.
455
 
456
If you don't define a handler for a particular region, then the ReadMemoryByte
457
in mz80.ASM will actually read the value out of mz80Base + the offset
458
required to complete the instruction.
459
 
460
7) Set the intAddr and nmiAddr to the addresses where you want mz80 to start
461
   executing when an interrupt or NMI happens. Take a look at the section
462
   entitled "INTERRUPTS" below for more information on this.
463
 
464
8) Call mz80SetContext() on your Z80 context
465
 
466
9) Call mz80Reset(). This will prime the program counter and cause a virtual
467
   CPU-wide reset.
468
 
469
10) Once you have those defined, you're ready to begin emulation. There's some
470
    sort of main loop that you'll want. Maybe something like:
471
 
472
	while (hit == 0)
473
	{
474
		if (lastSec != (UINT32) time(0))
475
		{
476
			diff = (mz80clockticks - prior) / 3000000;
477
			printf("%ld Clockticks, %ld frames, %ld Times original speed\n", MZ80clockticks - prior, frames, diff);
478
			frames = 0;
479
			prior = mz80clockticks;
480
			lastSec = time(0);
481
			if (kbhit())
482
			{
483
				getch();
484
				hit = 1;
485
			}
486
		}
487
 
488
		/* 9000 Cycles per NMI (~3 milliseconds @ 3MHZ) */
489
 
490
		dwResult = mz80exec(9000);
491
		mz80clockticks += mz80GetElapsedTicks(TRUE);
492
		mz80nmi();
493
 
494
		/* If the result is not 0x80000000, it's an address where
495
		   an invalid instruction was hit. */
496
 
497
		if (0x80000000 != dwResult)
498
		{
499
			mz80GetContext(&sCpu1);
500
			printf("Invalid instruction at %.2x\n", sCpu1.MZ80pc);
501
			exit(1);
502
		}
503
	}
504
 
505
Call mz80exec() With the # of virtual CPU cycles you'd like mz80 to
506
execute. Be sure to use the mz80GetElapsedTicks() call *AFTER* execution to
507
see how many virtual CPU cycles it actually executed. For example, if you tell
508
mz80 to execute 500 virtual CPU cycles, it will execute slightly more. Anything
509
from 500 to 524 (24 cycles being the longest any 1 instruction takes in the
510
Z80).
511
 
512
Use the mz80GetElapsedTicks() call for more accurate cycle counting. Of course,
513
this is only if you have *NOT* included the -nt option.
514
 
515
If you pass FALSE to the mz80GetElapsedTicks() function, the internal CPU
516
elapsed tick clock will not be reset. The elapsed tick counter is something
517
that continues to increase every emulated instruction, and like an odometer,
518
will keep counting unless you pass TRUE to mz80GetElapsedTicks(), of which
519
case it will return you the current value of the elapsed ticks and set it to
520
 
521
 
522
NOTE: The bigger value you pass to mz80exec, the greater benefit you get out
523
of the virtual registers persisting within the emulator, and it will run
524
faster. Pass in a value that is large enough to take advantage of it, but
525
not so often that you can't handle nmi or int's properly.
526
 
527
If you wish to create a virtual NMI, call mz80nmi(), and it will be taken
528
the next time you call mz80exec, or alternately if you have a handler call
529
mz80nmi/mz80int(), the interrupt will be taken upon return. Note that
530
mz80nmi() doesn't actually execute any code - it only primes the emulator to
531
begin executing NMI/INT code.
532
 
533
NOTE: mz80int() is defined with a UINT32 as a formal parameter. Depending
534
upon what interrupt mode you're executing in (described later), it may or may
535
not take a value.
536
 
537
NMI's can interrupt interrupts, but not the other way around - just like a
538
real Z80. If your program is already in an interrupt, another one will not be
539
taken. The same holds true for an NMI - Just like a real Z80!
540
 
541
 
542
MUTLI-PROCESSOR NOTES
543
---------------------
544
 
545
Doing multi processor support is a bit trickier, but is still fairly straight-
546
forward.
547
 
548
For each processor to be emulated, go through steps 1-7 above - giving each
549
CPU its own memory space, register storage, and read/write handlers.
550
 
551
 
552
EXECUTION OF MULTI-CPUS:
553
-------------------------
554
 
555
When you're ready to execute a given CPU, do the following:
556
 
557
	mz80SetContext(contextPointer);
558
 
559
This will load up all information saved before into the emulator and ready it
560
for execution. Then execute step 7 above to do your virtual NMI's, interrupts,
561
etc... All CPU state information is saved within a context.
562
 
563
When the execution cycle is complete, do the following to save the updated
564
context away for later:
565
 
566
	mz80GetContext(contextPointer);
567
 
568
Give each virtual processor a slice of time to execute. Don't make the values
569
too small or it will spend its time swapping contexts. While this in itself
570
isn't particularly CPU expensive, the more time you spend executing the better.
571
mz80 Keeps all of the Z80 register in native x86 register (including most
572
of the flags, HL, BC, and A). If no context swap is needed, then you get the
573
added advantage of the register storage. For example, let's say you were
574
running two Z80s - one at 2.0MHZ and one at 3.0MHZ. An example like this
575
might be desirable:
576
 
577
	mz80SetContext(cpu1Context);	// Set CPU #1's information
578
	mz80exec(2000);		// 2000 Instructions for 2.0MHZ CPU
579
	mz80GetContext(cpu1Context);	// Get CPU #1's state info
580
 
581
	mz80SetContext(cpu2Context);	// Set CPU #2's state information
582
	mz80exec(3000);		// 3000 Instructions for 3.0MHZ CPU
583
	mz80GetContext(cpu2Context);	// Get CPU #2's state information
584
 
585
This isn't entirely realistic, but if you keep the instruction or timing
586
ratios between the emulated CPUs even, then timing is a bit more accurate.
587
 
588
NOTE: If you need to make a particular CPU give up its own time cycle because
589
of a memory read/write, simply trap a particular address (say, a write to a
590
slave processor) and call mz80ReleaseTimeslice(). It will not execute any
591
further instructions, and will give up its timeslice. Put this in your
592
read/write memory trap.
593
 
594
NOTE: You are responsible for "holding back" the processor emulator from
595
running too fast.
596
 
597
 
598
INTERRUPTS
599
----------
600
 
601
The Z80 has three interrupt modes: IM 0 - IM 2. Each act differently. Here's
602
a description of each:
603
 
604
IM 0
605
 
606
This mode will cause the Z80 to be able to pull a "single byte instruction"
607
off the bus when an interrupt occurs. Since we're not doing bus cycle
608
emulation, it acts identically to mode 1 (described below). The formal
609
parameter to mz80int() is ignored. There is really no point in actually
610
emulating the instruction execution since any instruction that would be
611
executed would be a branch instruction!
612
 
613
IM 1
614
 
615
This mode is the "default" mode that the Z80 (and mz80 for that matter) comes
616
up in. When you call mz80reset(), the interrupt address is set to 38h and
617
the NMI address is set to 66h. So when you're in IM 1 and mz80int() is
618
called, the formal parameter is ignored and the z80intAddr/z80nmiAddr values
619
are appropriately loaded into the program counter.
620
 
621
IM 2
622
 
623
This mode causes the Z80 to read the upper 8 bits from the current value
624
of the "I" register, and the lower 8 bits from the value passed into mz80int().
625
So, if I contained 35h, and you did an mz80int(0x64), then an interrupt at
626
address 3564h would be taken. Simple!
627
 
628
 
629
OTHER GOODIES
630
-------------
631
 
632
MZ80 Has a nice feature for allowing the same handler to handle different
633
data regions on a single handler. Here's an example:
634
 
635
struct PokeyDataStruct Pokey1;
636
struct PokeyDataStruct Pokey2;
637
 
638
struct MemoryWriteByte GameWrite[] =
639
{
640
	{0x1000, 0x100f,  PokeyHandler, Pokey1},
641
	{0x1010, 0x101f,  PokeyHandler, Pokey2},
642
	{(UINT32) -1,     (UINT32) -1, NULL}
643
};
644
 
645
void PokeyHandler(UINT32 dwAddr, UINT8 bData, struct sMemoryWriteByte *psMem)
646
{
647
	struct PokeyDataStruct *psPokey = psMem->pUserArea;
648
 
649
	// Do stuff with psPokey here....
650
}
651
 
652
This passes in the pointer to the sMemoryWriteByte structure that caused
653
the handler to be called. The pUserArea is a user defined address that can
654
be anything. It is not necessary to fill it in with anything or even
655
initialize it if the handler doesn't actually use it.
656
 
657
This allows a single handler to handle multiple data references. This is
658
particularly useful when handling sound chip emulation, where there might
659
be more than one of a given device. Sure beats having multiple unique
660
handlers that are identical with the exception of the data area where it
661
writes! This allows a good deal of flexibility.
662
 
663
The same construct holds for MemoryReadByte, z80PortRead, and z80PortWrite,
664
so all can take advantage of this feature.
665
 
666
 
667
SHARED MEMORY FEATURES
668
----------------------
669
 
670
MZ80 Also has another useful feature for dealing with shared memory regions:
671
 
672
UINT8 bSharedRAM[0x100];
673
 
674
struct MemoryWriteByte Processor1[] =
675
{
676
	{0x1000, 0x10ff, NULL, bSharedRAM},
677
	{(UINT32) -1, (UINT32) -1, NULL}
678
};
679
 
680
struct MemoryWriteByte Processor2[] =
681
{
682
	{0x1000, 0x10ff, NULL, bSharedRAM},
683
	{(UINT32) -1, (UINT32) -1, NULL}
684
};
685
 
686
If the handler address is NULL, mz80 will look at the pUserArea field as a
687
pointer to RAM to read from/write to. This comes in extremely handy when you
688
have an emulation that requires two or more processors writing to the same
689
memory block. And it's lots faster than creating a handler that writes to
690
a common area as well.
691
 
692
 
693
DEBUGGING
694
---------
695
 
696
Several new functions have been added to mz80 that assist the emulator
697
author by providing a standard set of functions for register access:
698
 
699
UINT8 mz80SetRegisterValue(void *pContext, UINT32 dwRegister, UINT32 dwValue)
700
 
701
This allows setting of any register within the Z80. The register field can be
702
one of the following values (defined in mz80.h):
703
 
704
	CPUREG_PC
705
	CPUREG_Z80_AF
706
	CPUREG_Z80_BC
707
	CPUREG_Z80_DE
708
	CPUREG_Z80_HL
709
	CPUREG_Z80_AFPRIME
710
	CPUREG_Z80_BCPRIME
711
	CPUREG_Z80_DEPRIME
712
	CPUREG_Z80_HLPRIME
713
	CPUREG_Z80_IX
714
	CPUREG_Z80_IY
715
	CPUREG_Z80_SP
716
	CPUREG_Z80_I
717
	CPUREG_Z80_R
718
	CPUREG_Z80_A
719
	CPUREG_Z80_B
720
	CPUREG_Z80_C
721
	CPUREG_Z80_D
722
	CPUREG_Z80_E
723
	CPUREG_Z80_H
724
	CPUREG_Z80_L
725
	CPUREG_Z80_F
726
	CPUREG_Z80_CARRY
727
	CPUREG_Z80_NEGATIVE
728
	CPUREG_Z80_PARITY
729
	CPUREG_Z80_OVERFLOW
730
	CPUREG_Z80_HALFCARRY
731
	CPUREG_Z80_ZERO
732
	CPUREG_Z80_SIGN
733
	CPUREG_Z80_IFF1
734
	CPUREG_Z80_IFF2
735
 
736
Each individual register's value can be set, including the flags at the end.
737
The only valid values for the flags are 1 and 0. Setting these will
738
automatically adjust the "F" register.
739
 
740
If pContext is NULL, then the registers in the currently active context are
741
changed. If pContext points to a non-NULL area, that area is assumed to be
742
a CONTEXTMZ80 structure where the new register value will be written.
743
 
744
If mz80SetRegisterValue() returns a nonzero value, either the register value
745
or register is out of range or invalid.
746
 
747
 
748
UINT32 mz80GetRegisterValue(void *pContext, UINT32 dwRegister)
749
 
750
This returns the value of the register given on input (listed above as
751
CPUREG_Z80_xxxxx). Flag values will be 1 or 0.
752
 
753
If pContext is NULL, then the registers in the currently active context are
754
read. If pContext points to a non-NULL area, that area is assumed to be
755
a CONTEXTMZ80 structure from which register values are pulled.
756
 
757
 
758
UINT32 mz80GetRegisterTextValue(void *pContext, UINT32 dwRegister,
759
				 UINT8 *pbTextArea)
760
 
761
This returns the textual representation of the value of a given register.
762
It is a text printable string that can be used in sprintf() statements and
763
the like. This function is useful because different representations for
764
registers (like flags) can be a group of 8 flag bytes instead of a single
765
value.
766
 
767
On entry, pContext being set to NULL indicates that mz80 should get the
768
register value from the currently active context. Otherwise, it is assumed
769
to be pointing to a CONTEXTMZ80 structure, which contains the value of the
770
registers to be read.
771
 
772
pbTextArea points to a buffer where the value text can be written. This points
773
to a user supplied buffer.
774
 
775
On exit, if any nonzero value is encountered, either the register # is out
776
of range or pbTextArea is NULL.
777
 
778
 
779
UINT8 *mz80GetRegisterName(UINT32 dwRegister)
780
 
781
This returns a pointer to the textual name of the register passed in. NULL
782
Is returned if the register index (CPUREG_Z80_xxxx table described above) is
783
out of range. DO NOT MODIFY THE TEXT! It is static data.
784
 
785
 
786
FINAL NOTES
787
-----------
788
 
789
I have debugged MZ80.ASM to the best of my abilities. There might still be
790
a few bugs floating around in it, but I'm not aware of any. I've validated
791
all instructions (That I could) against a custom built Z80 on an ISA card
792
(that fits in a PC) so I'm quite confident that it works just like a real
793
Z80.
794
 
795
If you see any problems, please point them out to me, as I am eager to make
796
mz80 the best emulator that I can.
797
 
798
If you have questions, comments, etc... about mz80, please don't hesitate
799
to send me an email. And if you use mz80 in your emulator, I'd love to take
800
a look at your work. If you have special needs, or need implementation
801
specific hints, feel free to email me, Neil Bradley (neil@synthcom.com). I
802
will do my best to help you.
803
 
804
Enjoy!
805
 
806
Neil Bradley
807
neil@synthcom.com
808