forked from KolibriOS/kolibrios
ea1a60faa3
git-svn-id: svn://kolibrios.org@9837 a494cfbc-eb01-0410-851d-a64ba20cac60
252 lines
7.0 KiB
Plaintext
252 lines
7.0 KiB
Plaintext
************************************************
|
|
* *
|
|
* CZ80 (Z80 CPU emulator) version 0.91 *
|
|
* Compiled with Dev-C++ *
|
|
* Copyright 2004-2005 Stéphane Dallongeville *
|
|
* *
|
|
************************************************
|
|
|
|
CZ80 is a Z80 CPU emulator, priorities were given to :
|
|
- code size
|
|
- speed
|
|
- accuracy
|
|
- portablity
|
|
|
|
It supports almost all undocumented opcodes and flags.
|
|
|
|
The emulator can be freely distribued and used for any non commercial
|
|
project as long you don't forget to credit me somewhere :)
|
|
If you want some support about the CZ80, you can contact me on
|
|
the Gens forum (http://gens.consolemul.com then go to the forum).
|
|
|
|
|
|
You should find the following files in the emulation pack :
|
|
- cz80.h -> header file (prototypes, declarations...)
|
|
- cz80.c -> contains emulation core itself
|
|
- cz80.inc -> contains most used macros
|
|
- cz80jmp.inc -> Jump table definition when Jump Table used
|
|
- cz80exec.inc -> contains the major Cz80_Exec(...) function
|
|
- cz80_op.inc -> contains code for simple Z80 opcodes emulation
|
|
- cz80_opCB.inc -> contains code for CB prefixed Z80 opcodes emulation
|
|
- cz80_opED.inc -> contains code for ED prefixed Z80 opcodes emulation
|
|
- cz80_opXY.inc -> contains code for DD/FD prefixed Z80 opcodes emulation
|
|
- cz80_opXYCB.inc -> contains code for DD/FD + CB prefixed Z80 opcodes emulation
|
|
- readme.txt -> the current file you're reading ;)
|
|
|
|
|
|
* How compile the emulator ?
|
|
****************************
|
|
|
|
The emulator has been written with Dev-CPP 4.9.X.X
|
|
You will maybe need to modify the u8, u16, u32, s8, s16, s32 and FASTCALL
|
|
definitions (cz80.h) according to your C compiler and the target system.
|
|
Then compile the cz80.c file, you should obtain a cz80.o (or cz80.obj) file...
|
|
at this moment, you're ready to use the emulator just by linking the file in your project :)
|
|
|
|
|
|
* How to use the emulator ?
|
|
***************************
|
|
|
|
1) Include the header file in your source :
|
|
------------------------------------------
|
|
|
|
#include "cz80.h"
|
|
|
|
|
|
2) Init the CZ80 core :
|
|
-----------------------
|
|
|
|
If you want to use the internal CZ80 context offered :
|
|
|
|
Cz80_Init(&CZ80);
|
|
|
|
but you can also define your own CZ80 context :
|
|
|
|
cz80_struc My_Z80;
|
|
|
|
....
|
|
|
|
Cz80_Init(&My_Z80);
|
|
|
|
|
|
You'll can emulate as many Z80 CPU as you want by defining severals CZ80 contexts.
|
|
|
|
An arbitrary pointer can also be stored in the CZ80 context.
|
|
This pointer is passed to each I/O callback:
|
|
|
|
Cz80_Set_Ctx(&CZ80, &user_context);
|
|
|
|
|
|
3) Set up your fetch region (where the Z80 will run code from) :
|
|
----------------------------------------------------------------
|
|
|
|
Cz80_Set_Fetch(&CZ80, 0x0000, 0x7FFF, (u32) your_ROM);
|
|
Cz80_Set_Fetch(&CZ80, 0xA000, 0xFFFF, (u32) your_RAM);
|
|
...
|
|
|
|
|
|
4) Set up your memory (where the Z80 will read and write data) :
|
|
----------------------------------------------------------------
|
|
|
|
Cz80_Set_ReadB(&CZ80, your_z80readbyte_function);
|
|
Cz80_Set_WriteB(&CZ80, your_z80readbyte_function);
|
|
|
|
You can improve CZ80 performance by using WORD read/write function.
|
|
For that, you need to enable the 'CZ80_USE_WORD_HANDLER' define in cz80.h file.
|
|
In this case, you'll need to add that :
|
|
|
|
#if CZ80_USE_WORD_HANDLER
|
|
Cz80_Set_ReadW(&CZ80, your_z80readword_function);
|
|
Cz80_Set_WriteW(&CZ80, your_z80readword_function);
|
|
#endif
|
|
|
|
Your read function need to be of CZ80_READ type :
|
|
typedef u32 FASTCALL CZ80_READ(u32 adr);
|
|
|
|
Your write function need to be of CZ80_WRITE type :
|
|
typedef void FASTCALL CZ80_WRITE(u32 adr, u32 data);
|
|
|
|
|
|
5) Set Up your port (where the Z80 will read and write IO data) :
|
|
-----------------------------------------------------------------
|
|
|
|
Cz80_Set_INPort(&CZ80, your_z80readport_function);
|
|
Cz80_Set_OUTPort(&CZ80, your_z80writport_function);
|
|
|
|
Your readPort function need to be of CZ80_READ type :
|
|
typedef u32 FASTCALL CZ80_READ(u32 adr);
|
|
|
|
Your writePort function need to be of CZ80_WRITE type :
|
|
typedef void FASTCALL CZ80_WRITE(u32 adr, u32 data);
|
|
|
|
|
|
6) Set Up your interrupt callback function :
|
|
--------------------------------------------
|
|
|
|
Cz80_Set_IRQ_Callback(&CZ80, your_z80irqcallback_function);
|
|
|
|
Your IRQ callback function need to be of CZ80_INT_CALLBACK type :
|
|
typedef s32 FASTCALL CZ80_INT_CALLBACK(s32 param);
|
|
|
|
If you don't understand what i am talking about here, just ignore...
|
|
it's not needed in almost case.
|
|
|
|
|
|
6) Set Up your RETI callback function :
|
|
---------------------------------------
|
|
|
|
Cz80_Set_RETI_Callback(&CZ80, your_z80reticallback_function);
|
|
|
|
Your RETI callback function need to be of CZ80_RETI_CALLBACKtype :
|
|
typedef void FASTCALL CZ80_RETI_CALLBACK();
|
|
|
|
Again, if you don't understand what i am talking about here, ignore...
|
|
|
|
|
|
7) Reset the CZ80 core before fisrt use :
|
|
-----------------------------------------
|
|
|
|
Cz80_Reset(&CZ80);
|
|
|
|
|
|
8) Do some cycles :
|
|
-------------------
|
|
|
|
Then it's time to really do some work, if you want to execute 1000 cycles, just do :
|
|
|
|
cycles_done = Cz80_Exec(&CZ80, 1000);
|
|
|
|
Cz80_Exec function return the number of cycles actually done.
|
|
Since each instruction take more than 1 cycle, Cz80_Exec will execute a bit more than
|
|
you requested, for instance here, it can return 1008 cycles instead of 1000.
|
|
In this case, adjust the number of cycle to do like that :
|
|
|
|
cycles_by_frame = 4800;
|
|
extra_cycles = 0;
|
|
while (true)
|
|
{
|
|
...
|
|
extra_cycles = CZ80_Exec(&CZ80, cycles_by_frame - extra_cycles) - cycles_by_frame;
|
|
...
|
|
}
|
|
|
|
If Cz80_Exec returns a negatif value, an error occured.
|
|
|
|
|
|
9) Do an interrupt request :
|
|
----------------------------
|
|
|
|
Cz80_Set_IRQ(&CZ80, 0);
|
|
|
|
or for a NMI :
|
|
|
|
Cz80_Set_NMI(&CZ80);
|
|
|
|
|
|
10) Cancel an interrupt request :
|
|
---------------------------------
|
|
|
|
Cz80_Clear_IRQ(&CZ80);
|
|
|
|
or for a NMI :
|
|
|
|
Cz80_Clear_NMI(&CZ80);
|
|
|
|
|
|
|
|
* Switchs
|
|
*********
|
|
|
|
There are severals switchs in the cz80.h file which permit you to configure
|
|
CZ80 depending your needs.
|
|
|
|
- CZ80_FETCH_BITS (default = 4)
|
|
|
|
This defines the number of bits to select fetch region.
|
|
This value must be 4 <= X <= 12
|
|
Greater value offers permit to have more fetch region.
|
|
In almost case, 4 is enough, but if you have fetch region smaller than 0x1000 bytes,
|
|
increase this value.
|
|
|
|
- CZ80_LITTLE_ENDIAN
|
|
|
|
Define the endianess of the target platform.
|
|
x86 CPU use Little Endian.
|
|
|
|
- CZ80_USE_JUMPTABLE
|
|
|
|
Set it to 1 to use Jump table instead of big case statement.
|
|
This can bring some small speed improvemen.
|
|
Be careful, some compiler doesn't support (computed label) so it's
|
|
saffer to not use it.
|
|
|
|
- CZ80_SIZE_OPT
|
|
|
|
Add some extras optimisation for the code size versus speed.
|
|
Minor changes anyway...
|
|
|
|
- CZ80_USE_WORD_HANDLER
|
|
|
|
See the "Set Up Memory" section for more détail.
|
|
|
|
- CZ80_EXACT
|
|
|
|
Enable accurate emulation of extended undocumented opcode and flags.
|
|
minor speed decrease when activated.
|
|
Even without that flag, CZ80 is already uite accurate, keep it
|
|
disable unless you need it or if speed isn't important for you.
|
|
|
|
- CZ80_DEBUG
|
|
|
|
Used by me, keep it disable :p
|
|
|
|
|
|
|
|
* History
|
|
*********
|
|
|
|
Version 0.90 :
|
|
--------------
|
|
|
|
* Initial release for debugging purpose ^^
|