mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 07:17:45 -04:00
remove unused/unmaintained code
RIP Symbian.. mz80 is unused
This commit is contained in:
parent
1b85bf1c23
commit
fb7a7fea87
112 changed files with 0 additions and 45924 deletions
|
@ -1,13 +0,0 @@
|
|||
CFLAGS = -Wno-conversion -Wno-sign-compare # -Wno-pointer-sign
|
||||
|
||||
all : mz80.asm
|
||||
|
||||
mz80.asm : makez80
|
||||
./makez80 -s -l -x86 $@
|
||||
|
||||
makez80 : makez80.o
|
||||
|
||||
|
||||
clean :
|
||||
$(RM) makez80 makez80.o mz80.asm
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
all : mz80.obj
|
||||
|
||||
mz80.obj : mz80.asm
|
||||
nasm -f win32 mz80.asm -o $@
|
||||
|
||||
mz80.asm : makez80.exe
|
||||
makez80.exe -s -x86 $@
|
||||
|
||||
makez80.exe : makez80.c
|
||||
cl /DWIN32 /W3 makez80.c
|
||||
|
||||
|
||||
clean : tidy
|
||||
del mz80.obj
|
||||
|
||||
tidy :
|
||||
del mz80.asm makez80.exe makez80.obj
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
/* compiler dependence */
|
||||
#ifndef UINT8
|
||||
typedef unsigned char UINT8; /* unsigned 8bit */
|
||||
typedef unsigned short UINT16; /* unsigned 16bit */
|
||||
typedef unsigned int UINT32; /* unsigned 32bit */
|
||||
#endif
|
||||
#ifndef INT8
|
||||
typedef signed char INT8; /* signed 8bit */
|
||||
typedef signed short INT16; /* signed 16bit */
|
||||
typedef signed int INT32; /* signed 32bit */
|
||||
#endif
|
||||
|
||||
|
9512
cpu/mz80/makez80.c
9512
cpu/mz80/makez80.c
File diff suppressed because it is too large
Load diff
17053
cpu/mz80/mz80.c
17053
cpu/mz80/mz80.c
File diff suppressed because it is too large
Load diff
394
cpu/mz80/mz80.h
394
cpu/mz80/mz80.h
|
@ -1,394 +0,0 @@
|
|||
/* Multi-Z80 32 Bit emulator */
|
||||
|
||||
/* Copyright 1996, Neil Bradley, All rights reserved
|
||||
*
|
||||
* License agreement:
|
||||
*
|
||||
* The mZ80 emulator may be distributed in unmodified form to any medium.
|
||||
*
|
||||
* mZ80 May not be sold, or sold as a part of a commercial package without
|
||||
* the express written permission of Neil Bradley (neil@synthcom.com). This
|
||||
* includes shareware.
|
||||
*
|
||||
* Modified versions of mZ80 may not be publicly redistributed without author
|
||||
* approval (neil@synthcom.com). This includes distributing via a publicly
|
||||
* accessible LAN. You may make your own source modifications and distribute
|
||||
* mZ80 in object only form.
|
||||
*
|
||||
* mZ80 Licensing for commercial applications is available. Please email
|
||||
* neil@synthcom.com for details.
|
||||
*
|
||||
* Synthcom Systems, Inc, and Neil Bradley will not be held responsible for
|
||||
* any damage done by the use of mZ80. It is purely "as-is".
|
||||
*
|
||||
* If you use mZ80 in a freeware application, credit in the following text:
|
||||
*
|
||||
* "Multi-Z80 CPU emulator by Neil Bradley (neil@synthcom.com)"
|
||||
*
|
||||
* must accompany the freeware application within the application itself or
|
||||
* in the documentation.
|
||||
*
|
||||
* Legal stuff aside:
|
||||
*
|
||||
* If you find problems with mZ80, please email the author so they can get
|
||||
* resolved. If you find a bug and fix it, please also email the author so
|
||||
* that those bug fixes can be propogated to the installed base of mZ80
|
||||
* users. If you find performance improvements or problems with mZ80, please
|
||||
* email the author with your changes/suggestions and they will be rolled in
|
||||
* with subsequent releases of mZ80.
|
||||
*
|
||||
* The whole idea of this emulator is to have the fastest available 32 bit
|
||||
* Multi-z80 emulator for the PC, giving maximum performance.
|
||||
*/
|
||||
|
||||
/* General z80 based defines */
|
||||
|
||||
#ifndef _MZ80_H_
|
||||
#define _MZ80_H_
|
||||
|
||||
#ifndef UINT32
|
||||
#define UINT32 unsigned long int
|
||||
#endif
|
||||
|
||||
#ifndef UINT16
|
||||
#define UINT16 unsigned short int
|
||||
#endif
|
||||
|
||||
#ifndef UINT8
|
||||
#define UINT8 unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef INT32
|
||||
#define INT32 signed long int
|
||||
#endif
|
||||
|
||||
#ifndef INT16
|
||||
#define INT16 signed short int
|
||||
#endif
|
||||
|
||||
#ifndef INT8
|
||||
#define INT8 signed char
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _MEMORYREADWRITEBYTE_
|
||||
#define _MEMORYREADWRITEBYTE_
|
||||
|
||||
struct MemoryWriteByte
|
||||
{
|
||||
UINT32 lowAddr;
|
||||
UINT32 highAddr;
|
||||
void (*memoryCall)(UINT32, UINT8, struct MemoryWriteByte *);
|
||||
void *pUserArea;
|
||||
};
|
||||
|
||||
struct MemoryReadByte
|
||||
{
|
||||
UINT32 lowAddr;
|
||||
UINT32 highAddr;
|
||||
UINT8 (*memoryCall)(UINT32, struct MemoryReadByte *);
|
||||
void *pUserArea;
|
||||
};
|
||||
|
||||
#endif // _MEMORYREADWRITEBYTE_
|
||||
|
||||
struct z80PortWrite
|
||||
{
|
||||
UINT16 lowIoAddr;
|
||||
UINT16 highIoAddr;
|
||||
void (*IOCall)(UINT16, UINT8, struct z80PortWrite *);
|
||||
void *pUserArea;
|
||||
};
|
||||
|
||||
struct z80PortRead
|
||||
{
|
||||
UINT16 lowIoAddr;
|
||||
UINT16 highIoAddr;
|
||||
UINT16 (*IOCall)(UINT16, struct z80PortRead *);
|
||||
void *pUserArea;
|
||||
};
|
||||
|
||||
struct z80TrapRec
|
||||
{
|
||||
UINT16 trapAddr;
|
||||
UINT8 skipCnt;
|
||||
UINT8 origIns;
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
UINT32 af;
|
||||
|
||||
struct
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
UINT16 wFiller;
|
||||
UINT8 a;
|
||||
UINT8 f;
|
||||
#else
|
||||
UINT8 f;
|
||||
UINT8 a;
|
||||
UINT16 wFiller;
|
||||
#endif
|
||||
} half;
|
||||
} reg_af;
|
||||
|
||||
#define z80AF z80af.af
|
||||
#define z80A z80af.half.a
|
||||
#define z80F z80af.half.f
|
||||
|
||||
typedef union
|
||||
{
|
||||
UINT32 bc;
|
||||
|
||||
struct
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
UINT16 wFiller;
|
||||
UINT8 b;
|
||||
UINT8 c;
|
||||
#else
|
||||
UINT8 c;
|
||||
UINT8 b;
|
||||
UINT16 wFiller;
|
||||
#endif
|
||||
} half;
|
||||
} reg_bc;
|
||||
|
||||
#define z80BC z80bc.bc
|
||||
#define z80B z80bc.half.b
|
||||
#define z80C z80bc.half.c
|
||||
|
||||
typedef union
|
||||
{
|
||||
UINT32 de;
|
||||
|
||||
struct
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
UINT16 wFiller;
|
||||
UINT8 d;
|
||||
UINT8 e;
|
||||
#else
|
||||
UINT8 e;
|
||||
UINT8 d;
|
||||
UINT16 wFiller;
|
||||
#endif
|
||||
} half;
|
||||
} reg_de;
|
||||
|
||||
#define z80DE z80de.de
|
||||
#define z80D z80de.half.d
|
||||
#define z80E z80de.half.e
|
||||
|
||||
typedef union
|
||||
{
|
||||
UINT32 hl;
|
||||
|
||||
struct
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
UINT16 wFiller;
|
||||
UINT8 h;
|
||||
UINT8 l;
|
||||
#else
|
||||
UINT8 l;
|
||||
UINT8 h;
|
||||
UINT16 wFiller;
|
||||
#endif
|
||||
} half;
|
||||
} reg_hl;
|
||||
|
||||
#define z80HL z80hl.hl
|
||||
#define z80H z80hl.half.h
|
||||
#define z80L z80hl.half.l
|
||||
|
||||
#define z80SP z80sp.sp
|
||||
|
||||
typedef union
|
||||
{
|
||||
UINT32 ix;
|
||||
|
||||
struct
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
UINT16 wFiller;
|
||||
UINT8 xh;
|
||||
UINT8 xl;
|
||||
#else
|
||||
UINT8 xl;
|
||||
UINT8 xh;
|
||||
UINT16 wFiller;
|
||||
#endif
|
||||
} half;
|
||||
} reg_ix;
|
||||
|
||||
#define z80IX z80ix.ix
|
||||
#define z80XH z80ix.half.xh
|
||||
#define z80XL z80ix.half.xl
|
||||
|
||||
typedef union
|
||||
{
|
||||
UINT32 iy;
|
||||
|
||||
struct
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
UINT16 wFiller;
|
||||
UINT8 yh;
|
||||
UINT8 yl;
|
||||
#else
|
||||
UINT8 yl;
|
||||
UINT8 yh;
|
||||
UINT16 wFiller;
|
||||
#endif
|
||||
} half;
|
||||
} reg_iy;
|
||||
|
||||
#define z80IY z80iy.iy
|
||||
#define z80YH z80iy.half.yh
|
||||
#define z80YL z80iy.half.yl
|
||||
|
||||
struct mz80context
|
||||
{
|
||||
UINT8 *z80Base;
|
||||
struct MemoryReadByte *z80MemRead;
|
||||
struct MemoryWriteByte *z80MemWrite;
|
||||
struct z80PortRead *z80IoRead;
|
||||
struct z80PortWrite *z80IoWrite;
|
||||
UINT32 z80clockticks;
|
||||
UINT32 z80iff;
|
||||
UINT32 z80interruptMode;
|
||||
UINT32 z80halted;
|
||||
|
||||
reg_af z80af;
|
||||
reg_bc z80bc;
|
||||
reg_de z80de;
|
||||
reg_hl z80hl;
|
||||
UINT32 z80afprime;
|
||||
UINT32 z80bcprime;
|
||||
UINT32 z80deprime;
|
||||
UINT32 z80hlprime;
|
||||
reg_ix z80ix;
|
||||
reg_iy z80iy;
|
||||
UINT32 z80sp;
|
||||
UINT32 z80pc;
|
||||
UINT32 z80nmiAddr;
|
||||
UINT32 z80intAddr;
|
||||
UINT32 z80rCounter;
|
||||
UINT8 z80i;
|
||||
UINT8 z80r;
|
||||
UINT8 z80intPending;
|
||||
};
|
||||
|
||||
// These are the enumerations used for register access. DO NOT ALTER THEIR
|
||||
// ORDER! It must match the same order as in the mz80.c/mz80.asm files!
|
||||
|
||||
enum
|
||||
{
|
||||
#ifndef CPUREG_PC
|
||||
CPUREG_PC = 0,
|
||||
#endif
|
||||
CPUREG_Z80_AF = 1,
|
||||
CPUREG_Z80_BC,
|
||||
CPUREG_Z80_DE,
|
||||
CPUREG_Z80_HL,
|
||||
CPUREG_Z80_AFPRIME,
|
||||
CPUREG_Z80_BCPRIME,
|
||||
CPUREG_Z80_DEPRIME,
|
||||
CPUREG_Z80_HLPRIME,
|
||||
CPUREG_Z80_IX,
|
||||
CPUREG_Z80_IY,
|
||||
CPUREG_Z80_SP,
|
||||
CPUREG_Z80_I,
|
||||
CPUREG_Z80_R,
|
||||
CPUREG_Z80_A,
|
||||
CPUREG_Z80_B,
|
||||
CPUREG_Z80_C,
|
||||
CPUREG_Z80_D,
|
||||
CPUREG_Z80_E,
|
||||
CPUREG_Z80_H,
|
||||
CPUREG_Z80_L,
|
||||
CPUREG_Z80_F,
|
||||
CPUREG_Z80_CARRY,
|
||||
CPUREG_Z80_NEGATIVE,
|
||||
CPUREG_Z80_PARITY,
|
||||
CPUREG_Z80_OVERFLOW,
|
||||
CPUREG_Z80_HALFCARRY,
|
||||
CPUREG_Z80_ZERO,
|
||||
CPUREG_Z80_SIGN,
|
||||
CPUREG_Z80_IFF1,
|
||||
CPUREG_Z80_IFF2,
|
||||
|
||||
// Leave this here!
|
||||
|
||||
CPUREG_Z80_MAX_INDEX
|
||||
};
|
||||
|
||||
extern UINT32 mz80exec(UINT32);
|
||||
extern UINT32 mz80GetContextSize(void);
|
||||
extern UINT32 mz80GetElapsedTicks(UINT32);
|
||||
extern void mz80ReleaseTimeslice(void);
|
||||
extern void mz80GetContext(void *);
|
||||
extern void mz80SetContext(void *);
|
||||
extern void mz80reset(void);
|
||||
extern void mz80ClearPendingInterrupt(void);
|
||||
extern UINT32 mz80int(UINT32);
|
||||
extern UINT32 mz80nmi(void);
|
||||
extern void mz80init(void);
|
||||
extern void mz80shutdown(void);
|
||||
extern UINT32 z80intAddr;
|
||||
extern UINT32 z80nmiAddr;
|
||||
|
||||
// Debugger useful routines
|
||||
|
||||
extern UINT8 mz80SetRegisterValue(void *, UINT32, UINT32);
|
||||
extern UINT32 mz80GetRegisterValue(void *, UINT32);
|
||||
extern UINT32 mz80GetRegisterTextValue(void *, UINT32, UINT8 *);
|
||||
extern UINT8 *mz80GetRegisterName(UINT32);
|
||||
|
||||
// Memory/IO read/write commands
|
||||
|
||||
#ifndef VALUE_BYTE
|
||||
#define VALUE_BYTE 0
|
||||
#endif
|
||||
|
||||
#ifndef VALUE_WORD
|
||||
#define VALUE_WORD 1
|
||||
#endif
|
||||
|
||||
#ifndef VALUE_DWORD
|
||||
#define VALUE_DWORD 2
|
||||
#endif
|
||||
|
||||
#ifndef VALUE_IO
|
||||
#define VALUE_IO 3
|
||||
#endif
|
||||
|
||||
extern void mz80WriteValue(UINT8 bWhat, UINT32 dwAddr, UINT32 dwData);
|
||||
extern UINT32 mz80ReadValue(UINT8 bWhat, UINT32 dwAddr);
|
||||
|
||||
// Flag definitions
|
||||
|
||||
#define Z80_FLAG_CARRY 0x01
|
||||
#define Z80_FLAG_NEGATIVE 0x02
|
||||
#define Z80_FLAG_OVERFLOW_PARITY 0x04
|
||||
#define Z80_FLAG_UNDEFINED1 0x08
|
||||
#define Z80_FLAG_HALF_CARRY 0x10
|
||||
#define Z80_FLAG_UNDEFINED2 0x20
|
||||
#define Z80_FLAG_ZERO 0x40
|
||||
#define Z80_FLAG_SIGN 0x80
|
||||
|
||||
#define IFF1 0x01
|
||||
#define IFF2 0x02
|
||||
|
||||
typedef struct mz80context CONTEXTMZ80;
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // _MZ80_H_
|
|
@ -1,809 +0,0 @@
|
|||
Multi-Z80 32 Bit emulator
|
||||
Copyright 1996, 1997, 1998, 1999, 2000 - Neil Bradley, All rights reserved
|
||||
|
||||
MZ80 License agreement
|
||||
-----------------------
|
||||
|
||||
(MZ80 Refers to both the assembly code emitted by makez80.c and makez80.c
|
||||
itself)
|
||||
|
||||
MZ80 May be distributed in unmodified form to any medium.
|
||||
|
||||
MZ80 May not be sold, or sold as a part of a commercial package without
|
||||
the express written permission of Neil Bradley (neil@synthcom.com). This
|
||||
includes shareware.
|
||||
|
||||
Modified versions of MZ80 may not be publicly redistributed without author
|
||||
approval (neil@synthcom.com). This includes distributing via a publicly
|
||||
accessible LAN. You may make your own source modifications and distribute
|
||||
MZ80 in source or object form, but if you make modifications to MZ80
|
||||
then it should be noted in the top as a comment in makez80.c.
|
||||
|
||||
MZ80 Licensing for commercial applications is available. Please email
|
||||
neil@synthcom.com for details.
|
||||
|
||||
Synthcom Systems, Inc, and Neil Bradley will not be held responsible for
|
||||
any damage done by the use of MZ80. It is purely "as-is".
|
||||
|
||||
If you use MZ80 in a freeware application, credit in the following text:
|
||||
|
||||
"Multi-Z80 CPU emulator by Neil Bradley (neil@synthcom.com)"
|
||||
|
||||
must accompany the freeware application within the application itself or
|
||||
in the documentation.
|
||||
|
||||
Legal stuff aside:
|
||||
|
||||
If you find problems with MZ80, please email the author so they can get
|
||||
resolved. If you find a bug and fix it, please also email the author so
|
||||
that those bug fixes can be propogated to the installed base of MZ80
|
||||
users. If you find performance improvements or problems with MZ80, please
|
||||
email the author with your changes/suggestions and they will be rolled in
|
||||
with subsequent releases of MZ80.
|
||||
|
||||
The whole idea of this emulator is to have the fastest available 32 bit
|
||||
Multi-Z80 emulator for the x86, giving maximum performance.
|
||||
|
||||
MZ80 Contact information
|
||||
-------------------------
|
||||
|
||||
Author : Neil Bradley (neil@synthcom.com)
|
||||
Distribution: ftp://ftp.synthcom.com/pub/emulators/cpu/makez80.zip (latest)
|
||||
|
||||
You can join the cpuemu mailing list on Synthcom for discussion of Neil
|
||||
Bradley's Z80 (and other) CPU emulators. Send a message to
|
||||
"cpuemu-request@synthcom.com" with "subscribe" in the message body. The
|
||||
traffic is fairly low, and is used as a general discussion and announcement
|
||||
for aforementioned emulators.
|
||||
|
||||
|
||||
MZ80 Documentation
|
||||
-------------------
|
||||
|
||||
MZ80 Is a full featured Z80 emulator coded in 32 bit assembly. It runs well
|
||||
over a hundred games, in addition to it supporting many undocumented Z80
|
||||
instructions required to run some of the Midway MCR games, Galaga, and
|
||||
countless other wonderful Z80 based arcade games.
|
||||
|
||||
MZ80 Contains a makez80.c program that must be compiled. It is the program
|
||||
that emits the assembly code that NASM will compile. This minimizes the
|
||||
possibility of bugs creeping in to MZ80 for the different addressing modes
|
||||
for each instruction. It requires NASM 0.97 or greater.
|
||||
|
||||
The goal of MZ80 is to have a high performance Z80 emulator that is capable
|
||||
of running multiple emulations concurrently at full speed, even on lower-end
|
||||
machines (486/33). MZ80 Harnesses the striking similarities of both the Z80
|
||||
and the x86 instruction sets to take advantage of flag handling which greatly
|
||||
reduces the time required to emulate a processor, so no extra time is spent
|
||||
computing things that are already available in the native x86 processor,
|
||||
allowing it to perform leaps and bounds over comparable C based Z80 emulators
|
||||
on the same platform.
|
||||
|
||||
MZ80 Is designed exclusively for use with NASM, the Netwide Assembler. This
|
||||
gives the ultimate in flexibility, as NASM can emit object files that work
|
||||
with Watcom, Microsoft Visual C++ (4.0-current), DJGPP, Borland C++, and
|
||||
gcc under FreeBSD or Linux. MZ80 Has been tested with each one of these
|
||||
compilers and is known to work properly on each.
|
||||
|
||||
|
||||
What's in the package
|
||||
---------------------
|
||||
|
||||
MZ80.TXT - This text file
|
||||
|
||||
MAKEZ80.C - Multi Z80 32 Bit emulator emitter program
|
||||
|
||||
MZ80.H - C Header file for MZ80 functions
|
||||
|
||||
|
||||
What's new in this release
|
||||
--------------------------
|
||||
|
||||
Revision 3.4:
|
||||
|
||||
* Fixed the overflow flag not getting cleared in the SetOverflow()
|
||||
routine. It caused strange problems with a handful of Genesis games
|
||||
* Removed invalid instruction in the C version so that more
|
||||
instructions will execute
|
||||
|
||||
Revision 3.3:
|
||||
|
||||
* Undocumented opcodes added to the C emitter
|
||||
* Bug fix to the C emission that properly handles shared RAM regions
|
||||
(I.E. with handlers that are NULL)
|
||||
* Now using 32 bit registers to do register/memory access. Slight
|
||||
speed increase (assembly version only)
|
||||
|
||||
Revision 3.2:
|
||||
|
||||
* R Register emulation now accurate with a real Z80
|
||||
* mz80int() Called when interrupts are disabled causes the
|
||||
z80intPending flag to be set, and an interrupt will be caused after
|
||||
the execution of EI and the next instruction. See "IMPORTANT NOTE
|
||||
ABOUT INTERRUPTS" below
|
||||
* The instruction after EI executes fully before interrupt status is
|
||||
checked. (as does a real Z80)
|
||||
|
||||
|
||||
Revision 3.1:
|
||||
|
||||
* Fixed bug in memory dereference when handler was set to NULL (keeps
|
||||
system from crashing or faulting)
|
||||
* Removed the only stricmp() from the entire file and replaced it
|
||||
with strcmp() so that stdlibs without it will compile
|
||||
* Changed cyclesRemaining > 0 to cyclesRemaining >= 0 to be compatible
|
||||
with the ASM core
|
||||
* Removed additional sub [dwCyclesRemaining], 5 at the beginning of
|
||||
mz80exec() (ASM Core only). Increases timing accuracy.
|
||||
* NMIs And INTs add additional time to dwElapsedTicks as it should
|
||||
* mz80ReleaseTimeslice() Sets remaining clocks to 0 instead of 1
|
||||
|
||||
|
||||
Revision 3.0:
|
||||
|
||||
* All instructions validated against a real Z80. Used an ISA card
|
||||
with a Z80 on it to validate flag handling, instruction handling,
|
||||
timing, and other goodies. The only thing not implemented/emulated
|
||||
is flag bit 3 & 5 emulation. Believed to be 100% bug free!
|
||||
* 80% Speed improvement over version 2.7 of mz80
|
||||
* z80stb.c Removed. Use -c to emit a C version of mz80! API compatible!
|
||||
Note that this is mostly, but not fully, debugged, so consider the
|
||||
C version a beta! It's at least healthier than z80stb.c was. The C
|
||||
version does not include the undocumented Z80 instructions.
|
||||
* mz80nmi() No longer trashes registers it uses when using -cs
|
||||
* IN/OUT Instructions work properly when using -16
|
||||
* IN A, (xxh) uses A as high 8 bits of I/O fetch address when using -16
|
||||
* IM 0/IM 1 Description in documentation fixed
|
||||
* Sizes of all context registers increased to 32 bits - for speed!
|
||||
* IFF1/IFF2 Now properly emulated
|
||||
* JR Instruction offset can fetch from $ffff and properly wrap
|
||||
* LDIR/LDDR Instruction now won't go to completion - instead it will
|
||||
run until BC=0 or the # of cycles to execute have expired. These
|
||||
instructions used to run to completion - even beyond the # of cycles
|
||||
left to execute
|
||||
* INI/IND/INIR/INDR countdown bug fixed - it was decrementing B twice
|
||||
for each IN! Whoops!
|
||||
* If you specify NULL as a handler address to a memory region, mz80 will
|
||||
use vpData as a pointer to where that block of data resides. Quite
|
||||
useful for multiprocessor emulations that share the same memory.
|
||||
* EDI Now keeps track of cycle counting for faster execution
|
||||
* Modified memory region scanning code to use 32 bit registers instead
|
||||
of their 16 bit counterparts
|
||||
* Get/SetContext() uses rep movsd/movsb. Insignificant overall, but
|
||||
why waste the time?
|
||||
* Debugging routines added. See the "DEBUGGING" section below for more
|
||||
information. NOTE: The debugging routines are not yet available in
|
||||
the C emission.
|
||||
* Timing done slightly differently now. Mz80 now executes one
|
||||
instruction past the timing given on input. For example, mz80exec(0)
|
||||
will cause a single instruction to be executed (thusly -ss was
|
||||
removed).
|
||||
|
||||
Revision 2.7:
|
||||
|
||||
* Fixed OTIR/OTDR/INIR/INDR instructions so their 16 bit counterparts
|
||||
work properly
|
||||
* Emulation core 30-70% faster overall than 2.6 due to optimization to
|
||||
the timing routines
|
||||
* Replaced word reads/writes with a special word write routine rather
|
||||
than the standard calling to read/write byte functions
|
||||
* z80stb.c (the C equivalent of mz80) compiles properly now
|
||||
* Fixed OS/2 text/segment issue
|
||||
* Fixed bug in set/getCPU context that ensures that ES=DS and avoids
|
||||
crashes. Caused crashes under OS/2 and other OS's
|
||||
|
||||
Revision 2.6:
|
||||
|
||||
* Emulator core 5-30% faster overall. Some 16 and 8 bit instructions
|
||||
sped up when using their 32 bit equivalents.
|
||||
* Fix to -l so that proper labels without leading and trailing
|
||||
underscores so Linux/FreeBSD compiles will work properly
|
||||
* Single step now executes the # of instructions passed in to z80exec()
|
||||
instead of just 1 as it had in prior releases. This is only active
|
||||
when the -ss option is used.
|
||||
* The -nt option was added. This will cause the timing information to
|
||||
not be added in, speeding up execution. Warning: Only do this if your
|
||||
emulated target does not require instruction timing!
|
||||
* Updated documentation errors
|
||||
* C Version of mz80 (mz80.c) that is API compliant is distributed with
|
||||
the archive (With kind permission of Edward Massey).
|
||||
|
||||
Revision 2.5:
|
||||
|
||||
* Fixed an unconditional flag being cleared in the ddcbxx instructions.
|
||||
It caused Donkey Kong's barrels to not roll.
|
||||
|
||||
Revision 2.4:
|
||||
|
||||
* Fixed improper HALT handling (didn't advance the PTR when it should)
|
||||
* Fixed SRL (IX+$xx) instruction so that carry wasn't trashed
|
||||
* Fixed single stepping problems with it giving too much time to
|
||||
any given instruction
|
||||
* Fixed half carry flag handling with 16 bit SBC and ADD instructions
|
||||
* Fixed DAA emulation so that parity flags weren't getting trashed
|
||||
|
||||
Revision 2.3:
|
||||
|
||||
* Fixed many stack handling bugs
|
||||
* Timing problems fixed. The prior version was causing massive
|
||||
overruns on maximum timeslices with some insutructions.
|
||||
|
||||
Revision 2.2:
|
||||
|
||||
* Fixed a bug in CPI/CPD/CPIR/CPDR that mishandled flags
|
||||
* All known bugs are out of mz80 now
|
||||
* Added the -cs option to route all stack operations through the
|
||||
handlers (required for games like Galaga)
|
||||
|
||||
Revision 2.1:
|
||||
|
||||
* Fixed a bug in CPI/CPD/CPIR/CPDR that caused intermittent lockups.
|
||||
Also fixed a bug that caused erratic behavior in several video games.
|
||||
* Added INI/IND/INIR/INDR instruction group
|
||||
* Added OUTI/OUTD/OTIR/OTDR instruction group
|
||||
|
||||
Revision 1.0:
|
||||
|
||||
* First release! The whole thing is new!
|
||||
|
||||
|
||||
ASSEMBLING FOR USE WITH WATCOM C/C++
|
||||
------------------------------------
|
||||
|
||||
Watcom, by default, uses register calling conventions, as does MZ80. To
|
||||
create a proper emulator for Watcom:
|
||||
|
||||
makez80 MZ80.asm -x86
|
||||
|
||||
From here:
|
||||
|
||||
nasm -f win32 MZ80.asm
|
||||
|
||||
Link the MZ80.obj with your Watcom linker.
|
||||
|
||||
|
||||
ASSEMBLING FOR USE WITH MICROSOFT VISUAL C++ AND BORLAND C++
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Visual C++ and Borland C++ use stack calling conventions by default. To
|
||||
create a proper emulator for these compilers:
|
||||
|
||||
makez80 MZ80.asm -s -x86
|
||||
|
||||
For Visual C++ or Borland C++:
|
||||
|
||||
nasm -f win32 MZ80.asm
|
||||
|
||||
Link with your standard Visual C++ or Borland C++.
|
||||
|
||||
|
||||
ASSEMBLING FOR USE WITH DJGPP, GCC/FREEBSD, OR GCC/LINUX
|
||||
--------------------------------------------------------------------
|
||||
|
||||
DJGPP Uses stack calling conventions:
|
||||
|
||||
makez80 MZ80.asm -s -x86
|
||||
|
||||
To assemble:
|
||||
|
||||
nasm -f coff MZ80.asm
|
||||
|
||||
Link with your standard DJGPP linker. The same holds true for GCC under
|
||||
FreeBSD or Linux. If you're using GCC, use the -l option to generate "plain"
|
||||
labels so that gcc's linker will properly link things.
|
||||
|
||||
|
||||
MAKEZ80 COMMAND LINE OPTIONS
|
||||
----------------------------
|
||||
|
||||
-s - Use stack calling conventions (DJGPP, MSVC, Borland, etc...)
|
||||
|
||||
-cs - Force all stack operations to go through the Read/Write memory handlers.
|
||||
This slows things down, but is useful when needed.
|
||||
|
||||
-16 - Treat all I/O input and output as 16 bit (BC)
|
||||
|
||||
-l - Create 'plain' labels - ones without leading and trailing underscores
|
||||
|
||||
-nt - Do not generate timing code - this speeds the emulator up, but the
|
||||
downside is that no timing info is available.
|
||||
|
||||
-c - Emit a C mz80 emulator (API Compatible with the assembly version -
|
||||
handy for porters!)
|
||||
|
||||
-x86 - Emit an assembly (x86) mz80 emulator
|
||||
|
||||
-os2 - Generate OS/2 compatible segmentation
|
||||
|
||||
|
||||
IMPORTANT NOTE ABOUT INTERRUPTS
|
||||
-------------------------------
|
||||
|
||||
A minor change was made between the 3.1 and 3.2 versions of makez80 in the
|
||||
way that interrupts were handled.
|
||||
|
||||
On a real Z80, the !INT line is a level triggered interrupt, meaning that if
|
||||
the interrupt line is held low, the Z80 will continue to take interrupts
|
||||
immediately after the instruction after the EI instruction is executed until
|
||||
the interrupt line is high again.
|
||||
|
||||
In 3.1, if an interrupt came in and interrupts were disabled, the interrupt
|
||||
would never be "latched" for later execution. The Z80 does not have any
|
||||
internal latching capabilities, however external hardware often does hold
|
||||
the interrupt line low until the interrupt is executed, in effect, a latch.
|
||||
|
||||
I've only found one video game so far that requires the "raising/lowering"
|
||||
of the interrupt line (Ataxx). In the games that I've tried, it has improved
|
||||
performance, in some cases drastically, and in others not at all. This can
|
||||
be accounted for by interrupts being taken now, where they were being dropped
|
||||
in prior mz80 releases.
|
||||
|
||||
mz80 Emulates the most commonly used scenario. Now when mz80int() is executed
|
||||
and a nonzero value is returned (indicating interrupts were disabled), it
|
||||
will set z80intPending, and the interrupt will be taken after execution of
|
||||
one instruction beyond the EI instruction.
|
||||
|
||||
So now, if mz80int() returns a nonzero value, that means an interrupt is
|
||||
latched. If clearing this latch is desired or the old behavior of 3.1 is
|
||||
desired, make a call to the mz80ClearPendingInterrupt() call. It's a 2
|
||||
instruction call that has extremely small overhead and will not affect
|
||||
performance in any measurable way.
|
||||
|
||||
In any case, MZ80 will now execute one instruction after EI regardless of
|
||||
how much time is available to avoid the possibility of an interrupt request
|
||||
coming in directly after the EI instruction.
|
||||
|
||||
|
||||
STEPS TO EMULATION
|
||||
------------------
|
||||
|
||||
NOTE: -16 Is a command line option that will treat all I/O as 16 bit. That
|
||||
is, in an instruction like "IN AL, (C)", the addressed passed to the I/O
|
||||
handler will be BC instead of just C. Bear this in mind when considering your
|
||||
emulated platform.
|
||||
|
||||
There are a few steps you want to go through to get proper emulation, and a
|
||||
few guidelines must be followed.
|
||||
|
||||
1) Create a MZ80CONTEXT
|
||||
|
||||
2) Create your virtual 64K memory space using whatever means of obtaining
|
||||
memory you need to do.
|
||||
|
||||
3) Set mz80Base in your context to be the base of your 64K memory space
|
||||
|
||||
4) Load up your image to be emulated within that 64K address space.
|
||||
|
||||
5) Set z80IoRead and z80IoWrite to their appropriate structure arrays. Here's
|
||||
an example:
|
||||
|
||||
struct z80PortRead ReadPorts[] =
|
||||
{
|
||||
{0x10, 0x1f, SoundChip1Read},
|
||||
{0x20, 0x2f, SoundChip2Read}
|
||||
{(UINT32) -1, (UINT32) -1, NULL}
|
||||
};
|
||||
|
||||
When an IN instruction occurs, mz80 will probe this table looking for a
|
||||
handler to the address of the "IN" instruction. If it is found in the list,
|
||||
it's up to the handler to return the proper value. Otherwise, a value of
|
||||
0ffh is returned internally if no handler for that I/O address is found. In
|
||||
the case above, SoundChip1Read is called when the I/O address is between 0x10-
|
||||
0x1f. A similar structure is used for I/O writes as well (OUT):
|
||||
|
||||
struct z80PortWrite WritePorts[] =
|
||||
{
|
||||
{0x20, 0x2f, SoundChip2Write},
|
||||
{0x30, 0x36, VideoCtrlWrite},
|
||||
{(UINT32) -1, (UINT32) -1, NULL}
|
||||
}
|
||||
|
||||
Of course, this does the opposite that the z80PortRead struct, and instead
|
||||
looks for a handler to hand some data to. If it doesn't find an appropriate
|
||||
handler, nothing happens.
|
||||
|
||||
6) Set mz80MemoryRead & mz80MemoryWrite to their appropriate structure
|
||||
arrays. Here is an example:
|
||||
|
||||
struct MemoryWriteByte GameWrite[] =
|
||||
{
|
||||
{0x3000, 0x3fff, VideoWrite},
|
||||
{0x4000, 0x4fff, SpriteWrite},
|
||||
{(UINT32) -1, (UINT32) -1, NULL}
|
||||
};
|
||||
|
||||
The above example says that any time a write occurs in the 0x3000-0x3fff
|
||||
range, call the VideoWrite routine. The same holds true for the SpriteWrite
|
||||
region as well.
|
||||
|
||||
NOTE: When your write handler is called, it is passed the address of the
|
||||
write and the data that is to be written to it. If your handler doesn't
|
||||
write the data to the virtual image, the mz80 internal code will not.
|
||||
|
||||
NOTE: These routines will *NOT* be called when execution asks for these
|
||||
addresses. It will only call them when a particular instruction uses the
|
||||
memory at these locations.
|
||||
|
||||
If you wish for a region to be RAM, just leave it out of your memory region
|
||||
exception list. The WriteMemoryByte routine will treat it as read/write
|
||||
RAM and will write to mz80Base + addr directly.
|
||||
|
||||
If you wish to protect ROM regions (not often necessary), create a range that
|
||||
encompasses the ROM image, and have it call a routine that does nothing. This
|
||||
will prevent data from being written back onto the ROM image.
|
||||
|
||||
Leave your last entry in the table as shown above, with a null handler and
|
||||
0xffffffff-0xffffffff as your read address. Even though the Z80 only
|
||||
addresses 64K of space, the read/write handlers are defined as 32 bit so
|
||||
the compiler won't pass junk in the upper 16 bits of the address lines. Not
|
||||
only that, it allows orthoganality for future CPU emulators that may use
|
||||
these upper bits.
|
||||
|
||||
You can do a mz80GetContext() if you'd like to read the current context of
|
||||
the registers. Note that by the time your handler gets called, the program
|
||||
counter will be pointing to the *NEXT* instruction.
|
||||
|
||||
struct MemoryReadByte GameRead[] =
|
||||
{
|
||||
{0x2000, 0x200f, ReadHandler},
|
||||
{(UINT32) -1, (UINT32) -1, NULL}
|
||||
};
|
||||
|
||||
Same story here. If you have a special handler for an attempted read at a
|
||||
particular address, place its range in this table and create a handler
|
||||
routine for it.
|
||||
|
||||
If you don't define a handler for a particular region, then the ReadMemoryByte
|
||||
in mz80.ASM will actually read the value out of mz80Base + the offset
|
||||
required to complete the instruction.
|
||||
|
||||
7) Set the intAddr and nmiAddr to the addresses where you want mz80 to start
|
||||
executing when an interrupt or NMI happens. Take a look at the section
|
||||
entitled "INTERRUPTS" below for more information on this.
|
||||
|
||||
8) Call mz80SetContext() on your Z80 context
|
||||
|
||||
9) Call mz80Reset(). This will prime the program counter and cause a virtual
|
||||
CPU-wide reset.
|
||||
|
||||
10) Once you have those defined, you're ready to begin emulation. There's some
|
||||
sort of main loop that you'll want. Maybe something like:
|
||||
|
||||
while (hit == 0)
|
||||
{
|
||||
if (lastSec != (UINT32) time(0))
|
||||
{
|
||||
diff = (mz80clockticks - prior) / 3000000;
|
||||
printf("%ld Clockticks, %ld frames, %ld Times original speed\n", MZ80clockticks - prior, frames, diff);
|
||||
frames = 0;
|
||||
prior = mz80clockticks;
|
||||
lastSec = time(0);
|
||||
if (kbhit())
|
||||
{
|
||||
getch();
|
||||
hit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 9000 Cycles per NMI (~3 milliseconds @ 3MHZ) */
|
||||
|
||||
dwResult = mz80exec(9000);
|
||||
mz80clockticks += mz80GetElapsedTicks(TRUE);
|
||||
mz80nmi();
|
||||
|
||||
/* If the result is not 0x80000000, it's an address where
|
||||
an invalid instruction was hit. */
|
||||
|
||||
if (0x80000000 != dwResult)
|
||||
{
|
||||
mz80GetContext(&sCpu1);
|
||||
printf("Invalid instruction at %.2x\n", sCpu1.MZ80pc);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Call mz80exec() With the # of virtual CPU cycles you'd like mz80 to
|
||||
execute. Be sure to use the mz80GetElapsedTicks() call *AFTER* execution to
|
||||
see how many virtual CPU cycles it actually executed. For example, if you tell
|
||||
mz80 to execute 500 virtual CPU cycles, it will execute slightly more. Anything
|
||||
from 500 to 524 (24 cycles being the longest any 1 instruction takes in the
|
||||
Z80).
|
||||
|
||||
Use the mz80GetElapsedTicks() call for more accurate cycle counting. Of course,
|
||||
this is only if you have *NOT* included the -nt option.
|
||||
|
||||
If you pass FALSE to the mz80GetElapsedTicks() function, the internal CPU
|
||||
elapsed tick clock will not be reset. The elapsed tick counter is something
|
||||
that continues to increase every emulated instruction, and like an odometer,
|
||||
will keep counting unless you pass TRUE to mz80GetElapsedTicks(), of which
|
||||
case it will return you the current value of the elapsed ticks and set it to
|
||||
0 when complete.
|
||||
|
||||
NOTE: The bigger value you pass to mz80exec, the greater benefit you get out
|
||||
of the virtual registers persisting within the emulator, and it will run
|
||||
faster. Pass in a value that is large enough to take advantage of it, but
|
||||
not so often that you can't handle nmi or int's properly.
|
||||
|
||||
If you wish to create a virtual NMI, call mz80nmi(), and it will be taken
|
||||
the next time you call mz80exec, or alternately if you have a handler call
|
||||
mz80nmi/mz80int(), the interrupt will be taken upon return. Note that
|
||||
mz80nmi() doesn't actually execute any code - it only primes the emulator to
|
||||
begin executing NMI/INT code.
|
||||
|
||||
NOTE: mz80int() is defined with a UINT32 as a formal parameter. Depending
|
||||
upon what interrupt mode you're executing in (described later), it may or may
|
||||
not take a value.
|
||||
|
||||
NMI's can interrupt interrupts, but not the other way around - just like a
|
||||
real Z80. If your program is already in an interrupt, another one will not be
|
||||
taken. The same holds true for an NMI - Just like a real Z80!
|
||||
|
||||
|
||||
MUTLI-PROCESSOR NOTES
|
||||
---------------------
|
||||
|
||||
Doing multi processor support is a bit trickier, but is still fairly straight-
|
||||
forward.
|
||||
|
||||
For each processor to be emulated, go through steps 1-7 above - giving each
|
||||
CPU its own memory space, register storage, and read/write handlers.
|
||||
|
||||
|
||||
EXECUTION OF MULTI-CPUS:
|
||||
-------------------------
|
||||
|
||||
When you're ready to execute a given CPU, do the following:
|
||||
|
||||
mz80SetContext(contextPointer);
|
||||
|
||||
This will load up all information saved before into the emulator and ready it
|
||||
for execution. Then execute step 7 above to do your virtual NMI's, interrupts,
|
||||
etc... All CPU state information is saved within a context.
|
||||
|
||||
When the execution cycle is complete, do the following to save the updated
|
||||
context away for later:
|
||||
|
||||
mz80GetContext(contextPointer);
|
||||
|
||||
Give each virtual processor a slice of time to execute. Don't make the values
|
||||
too small or it will spend its time swapping contexts. While this in itself
|
||||
isn't particularly CPU expensive, the more time you spend executing the better.
|
||||
mz80 Keeps all of the Z80 register in native x86 register (including most
|
||||
of the flags, HL, BC, and A). If no context swap is needed, then you get the
|
||||
added advantage of the register storage. For example, let's say you were
|
||||
running two Z80s - one at 2.0MHZ and one at 3.0MHZ. An example like this
|
||||
might be desirable:
|
||||
|
||||
mz80SetContext(cpu1Context); // Set CPU #1's information
|
||||
mz80exec(2000); // 2000 Instructions for 2.0MHZ CPU
|
||||
mz80GetContext(cpu1Context); // Get CPU #1's state info
|
||||
|
||||
mz80SetContext(cpu2Context); // Set CPU #2's state information
|
||||
mz80exec(3000); // 3000 Instructions for 3.0MHZ CPU
|
||||
mz80GetContext(cpu2Context); // Get CPU #2's state information
|
||||
|
||||
This isn't entirely realistic, but if you keep the instruction or timing
|
||||
ratios between the emulated CPUs even, then timing is a bit more accurate.
|
||||
|
||||
NOTE: If you need to make a particular CPU give up its own time cycle because
|
||||
of a memory read/write, simply trap a particular address (say, a write to a
|
||||
slave processor) and call mz80ReleaseTimeslice(). It will not execute any
|
||||
further instructions, and will give up its timeslice. Put this in your
|
||||
read/write memory trap.
|
||||
|
||||
NOTE: You are responsible for "holding back" the processor emulator from
|
||||
running too fast.
|
||||
|
||||
|
||||
INTERRUPTS
|
||||
----------
|
||||
|
||||
The Z80 has three interrupt modes: IM 0 - IM 2. Each act differently. Here's
|
||||
a description of each:
|
||||
|
||||
IM 0
|
||||
|
||||
This mode will cause the Z80 to be able to pull a "single byte instruction"
|
||||
off the bus when an interrupt occurs. Since we're not doing bus cycle
|
||||
emulation, it acts identically to mode 1 (described below). The formal
|
||||
parameter to mz80int() is ignored. There is really no point in actually
|
||||
emulating the instruction execution since any instruction that would be
|
||||
executed would be a branch instruction!
|
||||
|
||||
IM 1
|
||||
|
||||
This mode is the "default" mode that the Z80 (and mz80 for that matter) comes
|
||||
up in. When you call mz80reset(), the interrupt address is set to 38h and
|
||||
the NMI address is set to 66h. So when you're in IM 1 and mz80int() is
|
||||
called, the formal parameter is ignored and the z80intAddr/z80nmiAddr values
|
||||
are appropriately loaded into the program counter.
|
||||
|
||||
IM 2
|
||||
|
||||
This mode causes the Z80 to read the upper 8 bits from the current value
|
||||
of the "I" register, and the lower 8 bits from the value passed into mz80int().
|
||||
So, if I contained 35h, and you did an mz80int(0x64), then an interrupt at
|
||||
address 3564h would be taken. Simple!
|
||||
|
||||
|
||||
OTHER GOODIES
|
||||
-------------
|
||||
|
||||
MZ80 Has a nice feature for allowing the same handler to handle different
|
||||
data regions on a single handler. Here's an example:
|
||||
|
||||
struct PokeyDataStruct Pokey1;
|
||||
struct PokeyDataStruct Pokey2;
|
||||
|
||||
struct MemoryWriteByte GameWrite[] =
|
||||
{
|
||||
{0x1000, 0x100f, PokeyHandler, Pokey1},
|
||||
{0x1010, 0x101f, PokeyHandler, Pokey2},
|
||||
{(UINT32) -1, (UINT32) -1, NULL}
|
||||
};
|
||||
|
||||
void PokeyHandler(UINT32 dwAddr, UINT8 bData, struct sMemoryWriteByte *psMem)
|
||||
{
|
||||
struct PokeyDataStruct *psPokey = psMem->pUserArea;
|
||||
|
||||
// Do stuff with psPokey here....
|
||||
}
|
||||
|
||||
This passes in the pointer to the sMemoryWriteByte structure that caused
|
||||
the handler to be called. The pUserArea is a user defined address that can
|
||||
be anything. It is not necessary to fill it in with anything or even
|
||||
initialize it if the handler doesn't actually use it.
|
||||
|
||||
This allows a single handler to handle multiple data references. This is
|
||||
particularly useful when handling sound chip emulation, where there might
|
||||
be more than one of a given device. Sure beats having multiple unique
|
||||
handlers that are identical with the exception of the data area where it
|
||||
writes! This allows a good deal of flexibility.
|
||||
|
||||
The same construct holds for MemoryReadByte, z80PortRead, and z80PortWrite,
|
||||
so all can take advantage of this feature.
|
||||
|
||||
|
||||
SHARED MEMORY FEATURES
|
||||
----------------------
|
||||
|
||||
MZ80 Also has another useful feature for dealing with shared memory regions:
|
||||
|
||||
UINT8 bSharedRAM[0x100];
|
||||
|
||||
struct MemoryWriteByte Processor1[] =
|
||||
{
|
||||
{0x1000, 0x10ff, NULL, bSharedRAM},
|
||||
{(UINT32) -1, (UINT32) -1, NULL}
|
||||
};
|
||||
|
||||
struct MemoryWriteByte Processor2[] =
|
||||
{
|
||||
{0x1000, 0x10ff, NULL, bSharedRAM},
|
||||
{(UINT32) -1, (UINT32) -1, NULL}
|
||||
};
|
||||
|
||||
If the handler address is NULL, mz80 will look at the pUserArea field as a
|
||||
pointer to RAM to read from/write to. This comes in extremely handy when you
|
||||
have an emulation that requires two or more processors writing to the same
|
||||
memory block. And it's lots faster than creating a handler that writes to
|
||||
a common area as well.
|
||||
|
||||
|
||||
DEBUGGING
|
||||
---------
|
||||
|
||||
Several new functions have been added to mz80 that assist the emulator
|
||||
author by providing a standard set of functions for register access:
|
||||
|
||||
UINT8 mz80SetRegisterValue(void *pContext, UINT32 dwRegister, UINT32 dwValue)
|
||||
|
||||
This allows setting of any register within the Z80. The register field can be
|
||||
one of the following values (defined in mz80.h):
|
||||
|
||||
CPUREG_PC
|
||||
CPUREG_Z80_AF
|
||||
CPUREG_Z80_BC
|
||||
CPUREG_Z80_DE
|
||||
CPUREG_Z80_HL
|
||||
CPUREG_Z80_AFPRIME
|
||||
CPUREG_Z80_BCPRIME
|
||||
CPUREG_Z80_DEPRIME
|
||||
CPUREG_Z80_HLPRIME
|
||||
CPUREG_Z80_IX
|
||||
CPUREG_Z80_IY
|
||||
CPUREG_Z80_SP
|
||||
CPUREG_Z80_I
|
||||
CPUREG_Z80_R
|
||||
CPUREG_Z80_A
|
||||
CPUREG_Z80_B
|
||||
CPUREG_Z80_C
|
||||
CPUREG_Z80_D
|
||||
CPUREG_Z80_E
|
||||
CPUREG_Z80_H
|
||||
CPUREG_Z80_L
|
||||
CPUREG_Z80_F
|
||||
CPUREG_Z80_CARRY
|
||||
CPUREG_Z80_NEGATIVE
|
||||
CPUREG_Z80_PARITY
|
||||
CPUREG_Z80_OVERFLOW
|
||||
CPUREG_Z80_HALFCARRY
|
||||
CPUREG_Z80_ZERO
|
||||
CPUREG_Z80_SIGN
|
||||
CPUREG_Z80_IFF1
|
||||
CPUREG_Z80_IFF2
|
||||
|
||||
Each individual register's value can be set, including the flags at the end.
|
||||
The only valid values for the flags are 1 and 0. Setting these will
|
||||
automatically adjust the "F" register.
|
||||
|
||||
If pContext is NULL, then the registers in the currently active context are
|
||||
changed. If pContext points to a non-NULL area, that area is assumed to be
|
||||
a CONTEXTMZ80 structure where the new register value will be written.
|
||||
|
||||
If mz80SetRegisterValue() returns a nonzero value, either the register value
|
||||
or register is out of range or invalid.
|
||||
|
||||
|
||||
UINT32 mz80GetRegisterValue(void *pContext, UINT32 dwRegister)
|
||||
|
||||
This returns the value of the register given on input (listed above as
|
||||
CPUREG_Z80_xxxxx). Flag values will be 1 or 0.
|
||||
|
||||
If pContext is NULL, then the registers in the currently active context are
|
||||
read. If pContext points to a non-NULL area, that area is assumed to be
|
||||
a CONTEXTMZ80 structure from which register values are pulled.
|
||||
|
||||
|
||||
UINT32 mz80GetRegisterTextValue(void *pContext, UINT32 dwRegister,
|
||||
UINT8 *pbTextArea)
|
||||
|
||||
This returns the textual representation of the value of a given register.
|
||||
It is a text printable string that can be used in sprintf() statements and
|
||||
the like. This function is useful because different representations for
|
||||
registers (like flags) can be a group of 8 flag bytes instead of a single
|
||||
value.
|
||||
|
||||
On entry, pContext being set to NULL indicates that mz80 should get the
|
||||
register value from the currently active context. Otherwise, it is assumed
|
||||
to be pointing to a CONTEXTMZ80 structure, which contains the value of the
|
||||
registers to be read.
|
||||
|
||||
pbTextArea points to a buffer where the value text can be written. This points
|
||||
to a user supplied buffer.
|
||||
|
||||
On exit, if any nonzero value is encountered, either the register # is out
|
||||
of range or pbTextArea is NULL.
|
||||
|
||||
|
||||
UINT8 *mz80GetRegisterName(UINT32 dwRegister)
|
||||
|
||||
This returns a pointer to the textual name of the register passed in. NULL
|
||||
Is returned if the register index (CPUREG_Z80_xxxx table described above) is
|
||||
out of range. DO NOT MODIFY THE TEXT! It is static data.
|
||||
|
||||
|
||||
FINAL NOTES
|
||||
-----------
|
||||
|
||||
I have debugged MZ80.ASM to the best of my abilities. There might still be
|
||||
a few bugs floating around in it, but I'm not aware of any. I've validated
|
||||
all instructions (That I could) against a custom built Z80 on an ISA card
|
||||
(that fits in a PC) so I'm quite confident that it works just like a real
|
||||
Z80.
|
||||
|
||||
If you see any problems, please point them out to me, as I am eager to make
|
||||
mz80 the best emulator that I can.
|
||||
|
||||
If you have questions, comments, etc... about mz80, please don't hesitate
|
||||
to send me an email. And if you use mz80 in your emulator, I'd love to take
|
||||
a look at your work. If you have special needs, or need implementation
|
||||
specific hints, feel free to email me, Neil Bradley (neil@synthcom.com). I
|
||||
will do my best to help you.
|
||||
|
||||
Enjoy!
|
||||
|
||||
Neil Bradley
|
||||
neil@synthcom.com
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue