Add emulators: 'DosBox' (binary only), 'e80', 'fceu' (binary only).

git-svn-id: svn://kolibrios.org@1814 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Yogev Ezra 2011-01-30 14:48:24 +00:00
parent 95261888a5
commit b2ba8d7766
33 changed files with 10992 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,233 @@
# This is the configurationfile for DOSBox 0.73.
# Lines starting with a # are commentlines.
# They are used to (briefly) document the effect of each option.
[sdl]
# fullscreen: Start dosbox directly in fullscreen.
# fulldouble: Use double buffering in fullscreen.
# fullresolution: What resolution to use for fullscreen: original or fixed size (e.g. 1024x768).
# windowresolution: Scale the window to this size IF the output device supports hardware scaling.
# output: What video system to use for output.
# Possible values: surface, overlay, opengl, openglnb, ddraw.
# autolock: Mouse will automatically lock, if you click on the screen.
# sensitivity: Mouse sensitivity.
# waitonerror: Wait before closing the console if dosbox has an error.
# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. (pause is only valid for the second entry)
# Possible values: lowest, lower, normal, higher, highest, pause.
# mapperfile: File used to load/save the key/event mappings from.
# usescancodes: Avoid usage of symkeys, might not work on all operating systems.
fullscreen=false
fulldouble=false
fullresolution=original
windowresolution=original
output=surface
autolock=true
sensitivity=100
waitonerror=true
priority=higher,normal
mapperfile=mapper.txt
usescancodes=true
[dosbox]
# language: Select another language file.
# machine: The type of machine tries to emulate.
# Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe.
# captures: Directory where things like wave, midi, screenshot get captured.
# memsize: Amount of memory DOSBox has in megabytes.
# This value is best left at its default to avoid problems with some games,
# though few games might require a higher value.
# There is generally no speed advantage when raising this value.
language=
machine=svga_s3
captures=capture
memsize=16
[render]
# frameskip: How many frames DOSBox skips before drawing one.
# aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down!.
# scaler: Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended,the scaler will be used even if the result might not be desired.
# Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x.
frameskip=0
aspect=false
scaler=normal2x
[cpu]
# core: CPU Core used in emulation. auto will switch to dynamic if available and appropriate.
# Possible values: auto, dynamic, normal, simple.
# cputype: CPU Type used in emulation. auto is the fastest choice.
# Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch.
# cycles: Amount of instructions DOSBox tries to emulate each millisecond. Setting this value too high results in sound dropouts and lags. Cycles can be set in 3 ways:
# 'auto' tries to guess what a game needs.
# It usually works, but can fail for certain games.
# 'fixed #number' will set a fixed amount of cycles. This is what you usually need if 'auto' fails.
# (Example: fixed 4000)
# 'max' will allocate as much cycles as your computer is able to handle
#
# Possible values: auto, fixed, max.
# cycleup: Amount of cycles to increase/decrease with keycombo.
# cycledown: Setting it lower than 100 will be a percentage.
core=auto
cputype=auto
cycles=auto
cycleup=500
cycledown=20
[mixer]
# nosound: Enable silent mode, sound is still emulated though.
# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality.
# Possible values: 22050, 44100, 48000, 32000, 16000, 11025, 8000, 49716.
# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged.
# Possible values: 2048, 4096, 8192, 1024, 512, 256.
# prebuffer: How many milliseconds of data to keep on top of the blocksize.
nosound=false
rate=22050
blocksize=2048
prebuffer=10
[midi]
# mpu401: Type of MPU-401 to emulate.
# Possible values: intelligent, uart, none.
# mididevice: Device that will receive the MIDI data from MPU-401.
# Possible values: default, win32, alsa, oss, coreaudio, coremidi, none.
# midiconfig: Special configuration options for the device driver. This is usually the id of the device you want to use. See README for details.
mpu401=intelligent
mididevice=default
midiconfig=
[sblaster]
# sbtype: Type of sblaster to emulate.
# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, none.
# sbbase: The IO address of the soundblaster.
# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300.
# irq: The IRQ number of the soundblaster.
# Possible values: 7, 5, 3, 9, 10, 11, 12.
# dma: The DMA number of the soundblaster.
# Possible values: 1, 5, 0, 3, 6, 7.
# hdma: The High DMA number of the soundblaster.
# Possible values: 1, 5, 0, 3, 6, 7.
# sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer.
# oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'.
# Possible values: auto, cms, opl2, dualopl2, opl3, none.
# oplemu: Provider for the OPL emulation. compat or old might provide better quality (see oplrate as well).
# Possible values: default, compat, fast, old.
# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly).
# Possible values: 22050, 49716, 44100, 48000, 32000, 16000, 11025, 8000.
sbtype=sb16
sbbase=220
irq=7
dma=1
hdma=5
sbmixer=true
oplmode=auto
oplemu=default
oplrate=22050
[gus]
# gus: Enable the Gravis Ultrasound emulation.
# gusrate: Sample rate of Ultrasound emulation.
# Possible values: 22050, 44100, 48000, 32000, 16000, 11025, 8000, 49716.
# gusbase: The IO base address of the Gravis Ultrasound.
# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300.
# gusirq: The IRQ number of the Gravis Ultrasound.
# Possible values: 5, 3, 7, 9, 10, 11, 12.
# gusdma: The DMA channel of the Gravis Ultrasound.
# Possible values: 3, 0, 1, 5, 6, 7.
# ultradir: Path to Ultrasound directory. In this directory
# there should be a MIDI directory that contains
# the patch files for GUS playback. Patch sets used
# with Timidity should work fine.
gus=false
gusrate=22050
gusbase=240
gusirq=5
gusdma=3
ultradir=C:\ULTRASND
[speaker]
# pcspeaker: Enable PC-Speaker emulation.
# pcrate: Sample rate of the PC-Speaker sound generation.
# Possible values: 22050, 44100, 48000, 32000, 16000, 11025, 8000, 49716.
# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'.
# Possible values: auto, on, off.
# tandyrate: Sample rate of the Tandy 3-Voice generation.
# Possible values: 22050, 44100, 48000, 32000, 16000, 11025, 8000, 49716.
# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible).
pcspeaker=true
pcrate=22050
tandy=auto
tandyrate=22050
disney=true
[joystick]
# joysticktype: Type of joystick to emulate: auto (default), none,
# 2axis (supports two joysticks),
# 4axis (supports one joystick, first joystick used),
# 4axis_2 (supports one joystick, second joystick used),
# fcs (Thrustmaster), ch (CH Flightstick).
# none disables joystick emulation.
# auto chooses emulation depending on real joystick(s).
# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none.
# timed: enable timed intervals for axis. (false is old style behaviour).
# autofire: continuously fires as long as you keep the button pressed.
# swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks.
# buttonwrap: enable button wrapping at the number of emulated buttons.
joysticktype=auto
timed=true
autofire=false
swap34=false
buttonwrap=true
[serial]
# serial1: set type of device connected to com port.
# Can be disabled, dummy, modem, nullmodem, directserial.
# Additional parameters must be in the same line in the form of
# parameter:value. Parameter for all types is irq.
# for directserial: realport (required), rxdelay (optional).
# (realport:COM1 realport:ttyS0).
# for modem: listenport (optional).
# for nullmodem: server, rxdelay, txdelay, telnet, usedtr,
# transparent, port, inhsocket (all optional).
# Example: serial1=modem listenport:5000
# Possible values: dummy, disabled, modem, nullmodem, directserial.
# serial2: see serial1
# Possible values: dummy, disabled, modem, nullmodem, directserial.
# serial3: see serial1
# Possible values: dummy, disabled, modem, nullmodem, directserial.
# serial4: see serial1
# Possible values: dummy, disabled, modem, nullmodem, directserial.
serial1=dummy
serial2=dummy
serial3=disabled
serial4=disabled
[dos]
# xms: Enable XMS support.
# ems: Enable EMS support.
# umb: Enable UMB support.
# keyboardlayout: Language code of the keyboard layout (or none).
xms=true
ems=true
umb=true
keyboardlayout=auto
[ipx]
# ipx: Enable ipx over UDP/IP emulation.
ipx=false
[autoexec]
# Lines in this section will be run at startup.
keyb ru 866

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,39 @@
format MS COFF
public Start
public _hStack
public _KOL_PATH
public _KOL_PARAM
extrn Memory
extrn hEnd
extrn _kol_main
section ".text" code
db "MENUET01"
dd 1, Start, hEnd, Memory, _hStack, _KOL_PARAM, _KOL_PATH
Start:
; èíèöèàëèçàöèÿ êó÷è
mov eax, 68
mov ebx, 11
int 0x40
; âûçîâ ãëàâíîé ïðîöåäóðû
mov eax, _kol_main
call eax
; çàâåðøåíèå ðàáîòû ïðîãðàììû
mov eax, -1
int 0x40
section ".bss"
_KOL_PARAM rb 256
_KOL_PATH rb 256
rb 16*1024
_hStack:

View File

@ -0,0 +1,3 @@
del e80.kex
del backup.sna
del *.o

View File

@ -0,0 +1,11 @@
del *.o
fasm asm_code.asm start.o
gcc -c z80/z80.c
gcc -c system/kolibri.c
gcc -c system/stdlib.c
gcc -c system/string.c
gcc -c e80.c
ld -nostdlib -T kolibri.ld -o e80.kex start.o kolibri.o stdlib.o string.o z80.o e80.o
objcopy e80.kex -O binary
kpack e80.kex
pause

View File

@ -0,0 +1,534 @@
#include "system/kolibri.h"
#include "system/stdlib.h"
#include "system/string.h"
#include "z80/z80.h"
#include "48.h"
#include "system/msgbox.c"
///=============================
#define TYPE_NO 0
#define TYPE_SNA 1
#define TYPE_Z80 2
#define SCREEN_LEN 3*3*256*192*3
char WND_CAPTION[] = {"e80 v0.5.1"};
extern char KOL_PARAM[256];
extern char KOL_PATH[256];
char szBackup[256];
char szScreen[256];
int fila[5][5];
int main_tecla, hay_tecla;
int SSCS = 0;
int debug=0, scanl=0;
int frame_counter;
int target_cycle;
Z80Regs spectrumZ80;
char *screen;
unsigned screen_w, screen_h;
#define screen_a_w 512
#define screen_a_h 384
int flash = 0;
unsigned time = 0;
///=============================
#include "keyboard.c"
///=============================
int get_ext(char *filename)
{
return TYPE_SNA;
}
///=============================
void memory_print(Z80Regs *regs, char *filename)
{
kol_struct70 file;
file.p00 = 2;
file.p04 = 0;
file.p08 = 0;
file.p12 = 64*1024;
file.p16 = (unsigned)(regs->RAM);
file.p20 = 0;
file.p21 = filename;
kol_file_70(&file);
}
///=============================
void all_print(Z80Regs *regs, char *filename)
{
kol_struct70 file;
file.p00 = 2;
file.p04 = 0;
file.p08 = 0;
file.p12 = sizeof (Z80Regs);
file.p16 = (unsigned)regs;
file.p20 = 0;
file.p21 = filename;
kol_file_70(&file);
}
///=============================
void screen_print(Z80Regs *regs)
{
kol_struct70 file;
char palette[]=
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xB0, 0x00, 0x00, 0xB0, 0x00, 0x00,
0x00, 0x00, 0xB0, 0x00, 0x00, 0xB0,
0xB0, 0x00, 0xB0, 0xB0, 0x00, 0xB0,
0x00, 0xB0, 0x00, 0x00, 0xB0, 0x00,
0xB0, 0xB0, 0x00, 0xB0, 0xB0, 0x00,
0x00, 0xB0, 0xB0, 0x00, 0xB0, 0xB0,
0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00,
0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
char *scr;
char *atr;
char a, c, s;
int i, j, k, l, m;
unsigned bri;
char *color;
char *addr;
int n = 0;
int z = 0;
int x, y;
scr = malloc(6144);
atr = malloc(768);
memcpy(scr, regs->RAM + 0x4000 , 6144);
memcpy(atr, regs->RAM + 0x5800 , 768);
for (j = 0; j < 3 ; j++)
for (i = 0; i < 8; i++)
for (k = 0; k < 8; k++)
for (l = 0; l < 32; l++)
{
c = scr[j*2048 + k*256 + i*32 + l];
for (m = 0; m < 8; m++)
{
s = (c & 128) >> 7;
a = atr[j*256 + i*32 + l];
if ( (a & 64) == 64 )
bri = 8;
else
bri = 0;
if ( 0 == s )
{
if (!(flash && (128 == (a&128))))
color = &palette[6*(bri+((a>>3)&7))];
else
color = &palette[6*(bri+(a&7))];
addr = screen + 2*screen_a_w*3*z + 2*3*n;
for (y = 0; y < 2; y++)
memcpy( addr + y*screen_a_w*3,
color, 6);
}
else
{
if (!(flash && (128 == (a&128))))
color = &palette[6*(bri+(a&7))];
else
color = &palette[6*(bri+((a>>3)&7))];
addr = screen + 2*screen_a_w*3*z + 2*3*n;
for (y = 0; y < 2; y++)
memcpy( addr + y*screen_a_w*3,
color, 6);
}
n++;
if (256 == n)
{
n = 0;
z++;
}
c <<= 1;
}
}
if ( 33 < (kol_time_tick() - time))
{
if (0 == flash)
flash = 1;
else
flash = 0;
time = kol_time_tick();
}
free(scr);
free(atr);
}
///=============================
void memory_load_z80(Z80Regs *regs, char *filename)
{
char header[30];
kol_struct70 file;
file.p00 = 0;
file.p04 = 0;
file.p08 = 0;
file.p12 = 30;
file.p16 = (unsigned) header;
file.p20 = 0;
file.p21 = filename;
}
///=============================
void memory_load_sna(Z80Regs *regs, char *filename)
{
char buffer[27];
kol_struct70 file;
file.p00 = 0;
file.p04 = 0;
file.p08 = 0;
file.p12 = 27;
file.p16 = (unsigned) buffer;
file.p20 = 0;
file.p21 = filename;
kol_file_70(&file);
regs->I = buffer[ 0];
regs->HLs.B.l = buffer[ 1];
regs->HLs.B.h = buffer[ 2];
regs->DEs.B.l = buffer[ 3];
regs->DEs.B.h = buffer[ 4];
regs->BCs.B.l = buffer[ 5];
regs->BCs.B.h = buffer[ 6];
regs->AFs.B.l = buffer[ 7];
regs->AFs.B.h = buffer[ 8];
regs->HL.B.l = buffer[ 9];
regs->HL.B.h = buffer[10];
regs->DE.B.l = buffer[11];
regs->DE.B.h = buffer[12];
regs->BC.B.l = buffer[13];
regs->BC.B.h = buffer[14];
regs->IY.B.l = buffer[15];
regs->IY.B.h = buffer[16];
regs->IX.B.l = buffer[17];
regs->IX.B.h = buffer[18];
regs->IFF1 = regs->IFF2 = (buffer[19]&0x04) >>2;
regs->R.W = buffer[20];
regs->AF.B.l = buffer[21];
regs->AF.B.h = buffer[22];
regs->SP.B.l =buffer[23];
regs->SP.B.h =buffer[24];
regs->IM = buffer[25];
regs->BorderColor = buffer[26];
file.p00 = 0;
file.p04 = 27;
file.p08 = 0;
file.p12 = 0x4000*3;
file.p16 = (unsigned) regs->RAM+16384;
file.p20 = 0;
file.p21 = filename;
kol_file_70(&file);
regs->PC.B.l = Z80MemRead(regs->SP.W, regs);
regs->SP.W++;
regs->PC.B.h = Z80MemRead(regs->SP.W, regs);
regs->SP.W++;
}
///=============================
void memory_save_sna(Z80Regs *regs, char *filename)
{
char buffer[27];
unsigned char sptmpl, sptmph;
kol_struct70 file;
buffer[ 0] = regs->I;
buffer[ 1] = regs->HLs.B.l;
buffer[ 2] = regs->HLs.B.h;
buffer[ 3] = regs->DEs.B.l;
buffer[ 4] = regs->DEs.B.h;
buffer[ 5] = regs->BCs.B.l;
buffer[ 6] = regs->BCs.B.h;
buffer[ 7] = regs->AFs.B.l;
buffer[ 8] = regs->AFs.B.h;
buffer[ 9] = regs->HL.B.l;
buffer[10] = regs->HL.B.h;
buffer[11] = regs->DE.B.l;
buffer[12] = regs->DE.B.h;
buffer[13] = regs->BC.B.l;
buffer[14] = regs->BC.B.h;
buffer[15] = regs->IY.B.l;
buffer[16] = regs->IY.B.h;
buffer[17] = regs->IX.B.l;
buffer[18] = regs->IX.B.h;
buffer[19] = regs->IFF1 << 2;
buffer[20] = regs->R.W & 0xFF;
buffer[21] = regs->AF.B.l;
buffer[22] = regs->AF.B.h;
sptmpl = Z80MemRead( regs->SP.W-1, regs );
sptmph = Z80MemRead( regs->SP.W-2, regs );
Z80MemWrite( --(regs->SP.W), regs->PC.B.h, regs);
Z80MemWrite( --(regs->SP.W), regs->PC.B.l, regs);
buffer[23] = regs->SP.B.l;
buffer[24] = regs->SP.B.h;
buffer[25] = regs->IM;
buffer[26] = regs->BorderColor;
file.p00 = 2;
file.p04 = 0;
file.p08 = 0;
file.p12 = 27;
file.p16 = (unsigned) buffer;
file.p20 = 0;
file.p21 = filename;
kol_file_70(&file);
file.p00 = 3;
file.p04 = 27;
file.p08 = 0;
file.p12 = 0x4000*3;
file.p16 = (unsigned) regs->RAM+16384;
file.p20 = 0;
file.p21 = filename;
kol_file_70(&file);
regs->SP.W += 2;
Z80MemWrite( regs->SP.W-1, sptmpl, regs );
Z80MemWrite( regs->SP.W-2, sptmph, regs );
}
///=============================
void memory_save_scr(Z80Regs *regs, char *filename)
{
kol_struct70 file;
file.p00 = 2;
file.p04 = 0x4000;
file.p08 = 0;
file.p12 = 6912;
file.p16 = (unsigned) regs->RAM+16384;
file.p20 = 0;
file.p21 = filename;
kol_file_70(&file);
}
///=============================
void wnd_draw()
{
kol_paint_start();
kol_wnd_define( (screen_w-540)/2, (screen_h-440)/2, 540, 440, 0x34b0b0b0);
kol_wnd_caption(WND_CAPTION);
screen_print(&spectrumZ80);
kol_paint_image((540 - screen_a_w)/2-5,
(440 - screen_a_h-kol_skin_height())/2,
screen_a_w, screen_a_h, screen);
kol_paint_end();
}
///=============================
void kol_main()
{
unsigned event;
unsigned key;
for (event = strlen(KOL_PATH); event > 0; --event)
if ( '/' == KOL_PATH[event] )
{
KOL_PATH[event+1]=0;
break;
}
strcpy(szBackup, KOL_PATH);
strcpy(szScreen, KOL_PATH);
strcat(szBackup, "backup.sna");
strcat(szScreen, "screen.scr");
kol_screen_get_size(&screen_w, &screen_h);
screen = malloc(SCREEN_LEN);
spectrumZ80.RAM = (char*) malloc(64*1024);
memcpy(spectrumZ80.RAM, BIOS48, 16*1024);
Z80Reset( &spectrumZ80, 69888 );
Z80FlagTables();
fila[1][1] = fila[1][2] = fila[2][2] = fila[3][2] = fila[4][2] =
fila[4][1] = fila[3][1] = fila[2][1] = 0xFF;
debug = 0;
if (KOL_PARAM != NULL)
{
int type = get_ext(KOL_PARAM);
if (TYPE_SNA == type)
memory_load_sna(&spectrumZ80, KOL_PARAM);
}
hay_tecla = main_tecla = 0;
//keyboard_process(0);
kol_key_mode_set(1);
for (;;)
{
// event = kol_event_check();
event = kol_event_wait_time(1);
switch (event)
{
case 1:
wnd_draw();
break;
case 2:
key = (kol_key_get()>>8)&0xff;
switch (key)
{
case 60: // F2
if ( IDOK == MessageBox("Save snapshot?",
WND_CAPTION, MB_OKCANCEL) )
memory_save_sna(&spectrumZ80,
szBackup);
break;
case 61: // F3
if ( IDOK == MessageBox("Load snapshot?",
WND_CAPTION, MB_OKCANCEL) )
memory_load_sna(&spectrumZ80,
szBackup);
break;
case 62: // F4
if ( IDOK == MessageBox("Save screenshot?",
WND_CAPTION, MB_OKCANCEL) )
memory_save_scr(&spectrumZ80,
szScreen);
break;
case 88: // F12 Reset
if ( IDOK == MessageBox("Reset?",
WND_CAPTION, MB_OKCANCEL) )
{
Z80Reset( &spectrumZ80, 69888 );
Z80FlagTables();
fila[1][1] = fila[1][2] =
fila[2][2] = fila[3][2] =
fila[4][2] = fila[4][1] =
fila[3][1] = fila[2][1] = 0xFF;
}
break;
default:
keyboard_process(key);
};
break;
case 3:
if ( 1 == (kol_btn_get() & 0xff00)>>8 )
{
free(screen);
free(spectrumZ80.RAM);
kol_exit();
}
break;
default:
if (0 == debug)
{
Z80Run( &spectrumZ80, 224*64 );
for( scanl=0; scanl<192; scanl++ )
Z80Run( &spectrumZ80, 224 );
Z80Run( &spectrumZ80, 224*56 );
if( target_cycle < 2 || frame_counter == 0 )
{
screen_print(&spectrumZ80);
kol_screen_wait_rr();
kol_paint_image((540 - screen_a_w)/2-5,
(440 - screen_a_h-kol_skin_height())/2,
screen_a_w, screen_a_h, screen);
}
while( target_cycle == 0 )
{
target_cycle--;
frame_counter++;
}
}
break;
};
}
}
///=============================

Binary file not shown.

View File

@ -0,0 +1,408 @@
///=============================
void keyboard_process(unsigned key)
{
switch (key)
{
case 42: // L-Shift Down
case 54: // R-Shift Down
fila[4][1] &= 0xFE;
break;
case 42+128: // L-Shift Up
case 54+128: // R-Shift Up
fila[4][1] |= 1;
break;
case 29: // Ctrl Down
fila[4][2] &= 0xFD;
break;
case 29+128: // Ctrl Up
fila[4][2] |= 2;
break;
case 56: // Alt Down
fila[4][1] &= 0xFE;
fila[4][2] &= 0xFD;
break;
case 56+128: // Alt Up
fila[4][1] |= 1;
fila[4][2] |= 2;
break;
case 28: // Enter Down
fila[3][2] &= 0xFE;
break;
case 28+128: // Enter Up
fila[3][2] |= 1;
break;
case 2: // 1 Down
fila[1][1] &= 0xFE;
break;
case 2+128: // 1 Up
fila[1][1] |= 1;
break;
case 3: // 2 Down
fila[1][1] &= 0xFD;
break;
case 3+128: // 2 Up
fila[1][1] |= 2;
break;
case 4: // 3 Down
fila[1][1] &= 0xFB;
break;
case 4+128: // 3 Up
fila[1][1] |= 4;
break;
case 5: // 4 Down
fila[1][1] &= 0xF7;
break;
case 5+128: // 4 Up
fila[1][1] |= 8;
break;
case 6: // 5 Down
fila[1][1] &= 0xEF;
break;
case 6+128: // 5 Up
fila[1][1] |= 16;
break;
case 7: // 6 Down
fila[1][2] &= 0xEF;
break;
case 7+128: // 6 Up
fila[1][2] |= 16;
break;
case 8: // 7 Down
fila[1][2] &= 0xF7;
break;
case 8+128: // 7 Up
fila[1][2] |= 8;
break;
case 9: // 8 Down
fila[1][2] &= 0xFB;
break;
case 9+128: // 8 Up
fila[1][2] |= 4;
break;
case 10: // 9 Down
fila[1][2] &= 0xFD;
break;
case 10+128: // 9 Up
fila[1][2] |= 2;
break;
case 11: // 0 Down
fila[1][2] &= 0xFE;
break;
case 11+128: // 0 Up
fila[1][2] |= 1;
break;
case 16: // Q Down
fila[2][1] &= 0xFE;
break;
case 16+128: // Q Up
fila[2][1] |= 1;
break;
case 17: // W Down
fila[2][1] &= 0xFD;
break;
case 17+128: // W Up
fila[2][1] |= 2;
break;
case 18: // E Down
fila[2][1] &= 0xFB;
break;
case 18+128: // E Up
fila[2][1] |= 4;
break;
case 19: // R Down
fila[2][1] &= 0xF7;
break;
case 19+128: // R Up
fila[2][1] |= 8;
break;
case 20: // T Down
fila[2][1] &= 0xEF;
break;
case 20+128: // T Up
fila[2][1] |= 16;
break;
case 21: // Y Down
fila[2][2] &= 0xEF;
break;
case 21+128: // Y Up
fila[2][2] |= 16;
break;
case 22: // U Down
fila[2][2] &= 0xF7;
break;
case 22+128: // U Up
fila[2][2] |= 8;
break;
case 23: // I Down
fila[2][2] &= 0xFB;
break;
case 23+128: // I Up
fila[2][2] |= 4;
break;
case 24: // O Down
fila[2][2] &= 0xFD;
break;
case 24+128: // O Up
fila[2][2] |= 2;
break;
case 25: // P Down
fila[2][2] &= 0xFE;
break;
case 25+128: // P Up
fila[2][2] |= 1;
break;
case 30: // A Down
fila[3][1] &= 0xFE;
break;
case 30+128: // A Up
fila[3][1] |= 1;
break;
case 31: // S Down
fila[3][1] &= 0xFD;
break;
case 31+128: // S Up
fila[3][1] |= 2;
break;
case 32: // D Down
fila[3][1] &= 0xFB;
break;
case 32+128: // D Up
fila[3][1] |= 4;
break;
case 33: // F Down
fila[3][1] &= 0xF7;
break;
case 33+128: // F Up
fila[3][1] |= 8;
break;
case 34: // G Down
fila[3][1] &= 0xEF;
break;
case 34+128: // G Up
fila[3][1] |= 16;
break;
case 35: // H Down
fila[3][2] &= 0xEF;
break;
case 35+128: // H Up
fila[3][2] |= 16;
break;
case 36: // J Down
fila[3][2] &= 0xF7;
break;
case 36+128: // J Up
fila[3][2] |= 8;
break;
case 37: // K Down
fila[3][2] &= 0xFB;
break;
case 37+128: // K Up
fila[3][2] |= 4;
break;
case 38: // L Down
fila[3][2] &= 0xFD;
break;
case 38+128: // L Up
fila[3][2] |= 2;
break;
case 44: // Z Down
fila[4][1] &= 0xFD;
break;
case 44+128: // Z Up
fila[4][1] |= 2;
break;
case 45: // X Down
fila[4][1] &= 0xFB;
break;
case 45+128: // X Up
fila[4][1] |= 4;
break;
case 46: // C Down
fila[4][1] &= 0xF7;
break;
case 46+128: // C Up
fila[4][1] |= 8;
break;
case 47: // V Down
fila[4][1] &= 0xEF;
break;
case 47+128: // V Up
fila[4][1] |= 16;
break;
case 48: // B Down
fila[4][2] &= 0xEF;
break;
case 48+128: // B Up
fila[4][2] |= 16;
break;
case 49: // N Down
fila[4][2] &= 0xF7;
break;
case 49+128: // N Up
fila[4][2] |= 8;
break;
case 50: // M Down
fila[4][2] &= 0xFB;
break;
case 50+128: // M Up
fila[4][2] |= 4;
break;
case 57: // Space Down
fila[4][2] &= 0xFE;
break;
case 57+128: // Space Up
fila[4][2] |= 1;
break;
case 14: // Backspace Down
fila[1][2] &= 0xFE;
fila[4][1] &= 0xFE;
break;
case 14+128: // Backspace Up
fila[1][2] |= 1;
fila[4][1] |= 1;
break;
case 12: // - Down
fila[3][2] &= 0xF7;
fila[4][2] &= 0xFD;
break;
case 12+128: // - Up
fila[3][2] |= 8;
fila[4][2] |= 2;
break;
case 53: // / Down
fila[4][1] &= 0xEF;
fila[4][2] &= 0xFD;
break;
case 53+128: // / Up
fila[4][1] |= 16;
fila[4][2] |= 2;
break;
case 52: // . Down
fila[4][2] &= 0xFB;
fila[4][2] &= 0xFD;
break;
case 52+128: // . Up
fila[4][2] |= 4;
fila[4][2] |= 2;
break;
case 51: // , Down
fila[4][2] &= 0xF7;
fila[4][2] &= 0xFD;
break;
case 51+128: // , Up
fila[4][2] |= 8;
fila[4][2] |= 2;
break;
case 13: // = Down
fila[3][2] &= 0xFD;
fila[4][2] &= 0xFD;
break;
case 13+128: // = Up
fila[3][2] |= 2;
fila[4][2] |= 2;
break;
};
}
///=============================

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -0,0 +1,20 @@
/*OUTPUT_FORMAT("binary")*/
ENTRY(Start)
SECTIONS
{
.text 0x000000:
{
*(.text)
}
.data : {
*(.data)
hEnd = . ;
}
.bss :
{
*(.bss)
}
Memory = . ;
}

View File

@ -0,0 +1,45 @@
============================================
e80. Версия 0.5.1 15 февраля 2010 года
============================================
Эмулятор ZX-Spectrum для ОС Колибри.
Для запуска программ нужно в KFAR
сделать ассоциацию с файлами SNA.
Автор ядра эмулятора Z80:
Santiago Romero Iglesias,
sromero@escomposlinux.org
============================================
Внимание!
Эмулятор повторяет клавиатуру
реального Спектрума.
Поэтому см. файл keyboard.png
Клавиша Shift соответствует CS (CAPS SHIFT)
Клавиша Ctrl соответствует SS (SYMBOL SHIFT)
Клавиша Alt соответствует переключению CS+SS
============================================
Другие клавиши:
F12 - перезагрузка эмулятора
F2 - сохранение в текущую папку
файла backup.sna
F3 - загрузка из текущей папки
файла backup.sna
F4 - сохранение в текущую папку
файла screen.scr
============================================
Александр Богомаз, albom85@yandex.ru
http://albom06.boom.ru

View File

@ -0,0 +1,412 @@
#include "kolibri.h"
#include "string.h"
extern char KOL_PATH[256];
extern char KOL_PARAM[256];
extern char KOL_DIR[256];
void kol_exit()
{
asm ("int $0x40"::"a"(-1));
}
void kol_sleep(unsigned d)
{
asm ("int $0x40"::"a"(5), "b"(d));
}
void kol_wnd_define(unsigned x, unsigned y, unsigned w, unsigned h, unsigned c)
{
asm ("nop"::"a"(0), "b"(x*65536+w), "c"(y*65536+h), "d"(c));
asm ("movl $0xffffff, %esi \n int $0x40");
}
void kol_wnd_move(unsigned x, unsigned y)
{
asm ("nop"::"a"(67), "b"(x), "c"(y));
asm ("movl $-1, %edx \n movl $-1, %esi \n int $0x40");
}
void kol_event_mask(unsigned e)
{
asm ("int $0x40"::"a"(40), "b"(e));
}
unsigned kol_event_wait()
{
asm ("int $0x40"::"a"(10));
}
unsigned kol_event_wait_time(unsigned time)
{
asm ("int $0x40"::"a"(23), "b"(time));
}
unsigned kol_event_check()
{
asm ("int $0x40"::"a"(11));
}
void kol_paint_start()
{
asm ("int $0x40"::"a"(12), "b"(1));
}
void kol_paint_end()
{
asm ("int $0x40"::"a"(12), "b"(2));
}
void kol_paint_pixel(unsigned x, unsigned y, unsigned c)
{
asm ("int $0x40"::"a"(1), "b"(x), "c"(y), "d"(c));
}
void kol_paint_bar(unsigned x, unsigned y, unsigned w, unsigned h, unsigned c)
{
asm ("int $0x40"::"a"(13), "b"(x*65536+w), "c"(y*65536+h), "d"(c));
}
void kol_paint_line(unsigned x1, unsigned y1, unsigned x2, unsigned y2, unsigned c)
{
asm ("int $0x40"::"a"(38), "b"(x1*65536+x2), "c"(y1*65536+y2), "d"(c));
}
void kol_paint_string(unsigned x, unsigned y, char *s, unsigned c)
{
asm ("int $0x40"::"a"(4), "b"(x*65536+y), "c"(c), "d"(s));
}
void kol_paint_image(unsigned x, unsigned y, unsigned w, unsigned h, char *d)
{
asm ("int $0x40"::"a"(7), "c"(w*65536+h), "d"(x*65536+y), "b"(d));
}
void kol_paint_image_pal(unsigned x, unsigned y, unsigned w, unsigned h, char *d, unsigned *palette)
{
asm ("nop"::"c"(w*65536+h), "d"(x*65536+y), "b"(d));
asm ("nop"::"a"(palette));
asm ("movl %eax, %edi");
asm ("xor %eax, %eax");
asm ("movl %eax, %ebp");
asm ("pushl $8");
asm ("popl %esi");
asm ("int $0x40"::"a"(65));
}
unsigned kol_key_get()
{
asm ("int $0x40"::"a"(2));
}
unsigned kol_key_control()
{
asm ("int $0x40"::"a"(66), "b"(3));
}
void kol_key_lang_set(unsigned lang)
{
asm ("int $0x40"::"a"(21), "b"(2), "c"(9), "d"(lang));
}
unsigned kol_key_lang_get()
{
asm ("int $0x40"::"a"(26), "b"(2), "c"(9));
}
void kol_key_mode_set(unsigned mode)
{
asm ("int $0x40"::"a"(66), "b"(1), "c"(mode));
}
unsigned kol_key_mode_get()
{
asm ("int $0x40"::"a"(66), "b"(2));
}
unsigned kol_btn_get()
{
asm ("int $0x40"::"a"(17));
}
void kol_btn_define(unsigned x, unsigned y, unsigned w, unsigned h, unsigned d, unsigned c)
{
asm ("nop"::"b"(x*65536+w), "c"(y*65536+h), "d"(d));
asm ("nop"::"a"(c));
asm ("movl %eax, %esi");
asm ("int $0x40"::"a"(8));
}
void kol_btn_type(unsigned t)
{
asm ("int $0x40"::"a"(48), "b"(1), "c"(t));
}
void kol_wnd_caption(char *s)
{
asm ("int $0x40"::"a"(71), "b"(1), "c"(s));
}
unsigned kol_mouse_pos()
{
asm ("int $0x40"::"a"(37), "b"(0));
}
unsigned kol_mouse_posw()
{
asm ("int $0x40"::"a"(37), "b"(1));
}
unsigned kol_mouse_btn()
{
asm ("int $0x40"::"a"(37), "b"(2));
}
void kol_board_putc(char c)
{
asm ("int $0x40"::"a"(63), "b"(1), "c"(c));
}
void kol_board_puts(char *s)
{
unsigned i;
i = 0;
while (*(s+i))
{
asm ("int $0x40"::"a"(63), "b"(1), "c"(*(s+i)));
i++;
}
}
void kol_board_puti(int n)
{
char c;
int i = 0;
do
{
c = n % 10 + '0';
asm ("int $0x40"::"a"(63), "b"(1), "c"(c));
i++;
}
while ((n /= 10) > 0);
}
int kol_file_70(kol_struct70 *k)
{
asm ("int $0x40"::"a"(70), "b"(k));
}
kol_struct_import* kol_cofflib_load(char *name)
{
asm ("int $0x40"::"a"(68), "b"(19), "c"(name));
}
void* kol_cofflib_procload (kol_struct_import *imp, char *name)
{
int i;
for (i=0;;i++)
if ( NULL == ((imp+i) -> name))
break;
else
if ( 0 == strcmp(name, (imp+i)->name) )
return (imp+i)->data;
return NULL;
}
unsigned kol_cofflib_procnum (kol_struct_import *imp)
{
unsigned i, n;
for (i=n=0;;i++)
if ( NULL == ((imp+i) -> name))
break;
else
n++;
return n;
}
void kol_cofflib_procname (kol_struct_import *imp, char *name, unsigned n)
{
unsigned i;
*name = 0;
for (i=0;;i++)
if ( NULL == ((imp+i) -> name))
break;
else
if ( i == n )
{
strcpy(name, ((imp+i)->name));
break;
}
}
unsigned kol_system_cpufreq()
{
asm ("int $0x40"::"a"(18), "b"(5));
}
unsigned kol_system_mem()
{
asm ("int $0x40"::"a"(18), "b"(17));
}
unsigned kol_system_memfree()
{
asm ("int $0x40"::"a"(18), "b"(16));
}
unsigned kol_system_time_get()
{
asm ("int $0x40"::"a"(3));
}
unsigned kol_system_date_get()
{
asm ("int $0x40"::"a"(29));
}
unsigned kol_system_end(unsigned param)
{
asm ("int $0x40"::"a"(18), "b"(9), "c"(param));
}
void kol_path_file2dir(char *dir, char *fname)
{
unsigned i;
strcpy (dir, fname);
for ( i = strlen(dir);; --i)
if ( '/' == dir[i])
{
dir[i] = '\0';
return;
}
}
void kol_path_full(char *full, char *fname)
{
char temp[256];
switch (*fname)
{
case '/':
strncpy(temp, fname+1, 2);
temp[2]=0;
if ( (!strcmp("rd", temp)) || (!strcmp("hd", temp)) || (!strcmp("cd", temp)) )
strcpy (full, fname);
break;
case '.':
break;
default:
break;
};
}
void kol_screen_wait_rr()
{
asm ("int $0x40"::"a"(18), "b"(14));
}
void kol_screen_get_size(unsigned *w, unsigned *h)
{
unsigned size;
asm ("int $0x40":"=a"(size):"a"(14));
*w = size / 65536;
*h = size % 65536;
}
unsigned kol_skin_height()
{
asm ("int $0x40"::"a"(48), "b"(4));
}
unsigned kol_thread_start(unsigned start, unsigned stack)
{
asm ("int $0x40"::"a"(51), "b"(1), "c"(start), "d"(stack));
}
unsigned kol_time_tick()
{
asm ("int $0x40"::"a"(26), "b"(9));
}
unsigned kol_sound_speaker(char data[])
{
asm ("movl %0, %%esi"::"a"(data));
asm ("int $0x40"::"a"(55), "b"(55));
}
unsigned kol_process_info(unsigned slot, char buf1k[])
{
asm ("int $0x40"::"a"(9), "b"(buf1k), "c"(slot));
}
int kol_process_kill_pid(unsigned process)
{
asm ("int $0x40"::"a"(18), "b"(18), "c"(process));
}

View File

@ -0,0 +1,90 @@
#define NULL ((void*)0)
typedef struct
{
unsigned p00 __attribute__((packed));
unsigned p04 __attribute__((packed));
unsigned p08 __attribute__((packed));
unsigned p12 __attribute__((packed));
unsigned p16 __attribute__((packed));
char p20 __attribute__((packed));
char *p21 __attribute__((packed));
} kol_struct70 __attribute__((packed));
typedef struct
{
unsigned p00 __attribute__((packed));
char p04 __attribute__((packed));
char p05[3] __attribute__((packed));
unsigned p08 __attribute__((packed));
unsigned p12 __attribute__((packed));
unsigned p16 __attribute__((packed));
unsigned p20 __attribute__((packed));
unsigned p24 __attribute__((packed));
unsigned p28 __attribute__((packed));
unsigned p32[2] __attribute__((packed));
unsigned p40 __attribute__((packed));
} kol_struct_BDVK __attribute__((packed));
typedef struct
{
char *name __attribute__((packed));
void *data __attribute__((packed));
} kol_struct_import __attribute__((packed));
void kol_exit();
void kol_sleep(unsigned d);
void kol_wnd_define(unsigned x, unsigned y, unsigned w, unsigned h, unsigned c);
void kol_wnd_move(unsigned x, unsigned y);
void kol_wnd_caption(char *s);
void kol_event_mask(unsigned e);
unsigned kol_event_wait();
unsigned kol_event_wait_time(unsigned time);
unsigned kol_event_check();
void kol_paint_start();
void kol_paint_end();
void kol_paint_pixel(unsigned x, unsigned y, unsigned c);
void kol_paint_bar(unsigned x, unsigned y, unsigned w, unsigned h, unsigned c);
void kol_paint_line(unsigned x1, unsigned y1, unsigned x2, unsigned y2, unsigned c);
void kol_paint_string(unsigned x, unsigned y, char *s, unsigned c);
void kol_paint_image(unsigned x, unsigned y, unsigned w, unsigned h, char *d);
void kol_paint_image_pal(unsigned x, unsigned y, unsigned w, unsigned h, char *d, unsigned *palette);
unsigned kol_key_get();
unsigned kol_key_control();
void kol_key_lang_set(unsigned lang);
unsigned kol_key_lang_get();
void kol_key_mode_set(unsigned mode);
unsigned kol_key_mode_get();
void kol_btn_define(unsigned x, unsigned y, unsigned w, unsigned h, unsigned d, unsigned c);
unsigned kol_btn_get();
void kol_btn_type(unsigned t);
unsigned kol_mouse_pos();
unsigned kol_mouse_posw();
unsigned kol_mouse_btn();
void kol_board_putc(char c);
void kol_board_puts(char *s);
void kol_board_puti(int n);
int kol_file_70(kol_struct70 *k);
kol_struct_import* kol_cofflib_load(char *name);
void* kol_cofflib_procload (kol_struct_import *imp, char *name);
unsigned kol_cofflib_procnum (kol_struct_import *imp);
void kol_cofflib_procname (kol_struct_import *imp, char *name, unsigned n);
unsigned kol_system_end(unsigned param);
unsigned kol_system_cpufreq();
unsigned kol_system_mem();
unsigned kol_system_memfree();
unsigned kol_system_time_get();
unsigned kol_system_date_get();
void kol_path_file2dir(char *dir, char *fname);
void kol_path_full(char *full, char *fname);
void kol_screen_wait_rr();
void kol_screen_get_size(unsigned *w, unsigned *h);
unsigned kol_skin_height();
unsigned kol_thread_start(unsigned start, unsigned stack);
unsigned kol_time_tick();
unsigned kol_sound_speaker(char data[]);
unsigned kol_process_info(unsigned slot, char buf1k[]);
int kol_process_kill_pid(unsigned process);

View File

@ -0,0 +1,167 @@
///=============================
#define MB_OK 0
#define MB_OKCANCEL 1
#define MB_ABORTRETRYIGNORE 2
#define MB_YESNOCANCEL 3
#define MB_YESNO 4
#define MB_RETRYCANCEL 5
#define IDOK 1
#define IDCANCEL 2
#define IDABORT 3
#define IDRETRY 4
#define IDIGNORE 5
#define IDYES 6
#define IDNO 7
///=============================
#define LANG_EN
#ifdef LANG_RU
char BTN_OK[]={"OK"};
char BTN_CANCEL[]={"Žâ¬¥­ "};
char BTN_ABORT[]={"<EFBFBD>४à â¨âì"};
char BTN_RETRY[]={"<EFBFBD>®¢â®à¨âì"};
char BTN_INGNORE[]={"ˆ£­®à¨à®¢ âì"};
char BTN_NO[]={"<EFBFBD>¥â"};
#endif
#ifdef LANG_EN
char BTN_OK[]={"OK"};
char BTN_CANCEL[]={"Cancel"};
char BTN_ABORT[]={"Abort"};
char BTN_RETRY[]={"Retry"};
char BTN_INGNORE[]={"Ignore"};
char BTN_NO[]={"No"};
#endif
///=============================
kol_struct_import *MSG_BOX_IMPORT = NULL;
int (* _stdcall mb_create)(char *m, char* t);
char msg[1024];
char thread[1024];
///=============================
char MessageBox(char *text, char *caption, int type)
{
int i, j;
if (MSG_BOX_IMPORT == NULL)
{
MSG_BOX_IMPORT = kol_cofflib_load("/sys/lib/Msgbox.obj");
if (MSG_BOX_IMPORT == NULL)
kol_exit();
mb_create = kol_cofflib_procload (MSG_BOX_IMPORT, "mb_create");
if (mb_create == NULL)
kol_exit();
}
msg[0] = 255;
msg[1] = 0;
for (i = 2, j = 0; ;i++, j++)
{
msg[i] = caption[j];
if (0 == msg[i])
break;
}
i++;
msg[i] = 0;
for (j = 0; ;i++, j++)
{
msg[i] = text[j];
if (0 == msg[i])
break;
}
i++;
msg[i] = 0;
switch (type)
{
case MB_OK:
for (j = 0; ;i++, j++)
{
msg[i] = BTN_OK[j];
if (0 == msg[i])
break;
}
break;
case MB_OKCANCEL:
for (j = 0; ;i++, j++)
{
msg[i] = BTN_OK[j];
if (0 == msg[i])
break;
}
i++;
msg[i] = 0;
for (j = 0; ;i++, j++)
{
msg[i] = BTN_CANCEL[j];
if (0 == msg[i])
break;
}
break;
default:
break;
}
i++;
msg[i] = 0;
mb_create(msg, thread+1024);
for (;;)
{
if ( (unsigned char) msg[0] != 255 )
switch (type)
{
case MB_OK:
if (msg[0] == 1)
return IDOK;
else
return 0;
break;
case MB_OKCANCEL:
switch(msg[0])
{
case 1:
return IDOK;
case 2:
return IDCANCEL;
default:
return 0;
};
break;
default:
return 0;
};
kol_sleep(10);
}
}
///=============================

View File

@ -0,0 +1,33 @@
unsigned int seed_o = 0x45168297;
void srand (unsigned seed)
{
seed_o = seed;
}
int rand (void)
{
seed_o = seed_o * 0x15a4e35 + 1;
return(seed_o >> 16);
}
void* malloc(unsigned s)
{
asm ("int $0x40"::"a"(68), "b"(12), "c"(s) );
}
void free(void *p)
{
asm ("int $0x40"::"a"(68), "b"(13), "c"(p) );
}
void* realloc(void *p, unsigned s)
{
asm ("int $0x40"::"a"(68), "b"(12), "c"(p), "d"(s) );
}

View File

@ -0,0 +1,14 @@
#define RAND_MAX 0x7FFFU
#define isspace(c) ((c)==' ')
#define abs(i) (((i)<0)?(-(i)):(i))
#define random(num) ((rand()*(num))/((RAND_MAX+1)))
void* malloc(unsigned size);
void free(void *pointer);
void* realloc(void* pointer, unsigned size);
void srand (unsigned seed);
int rand (void);

View File

@ -0,0 +1,124 @@
#include "string.h"
void* memset(void *mem, int c, unsigned size)
{
unsigned i;
for ( i = 0; i < size; i++ )
*((char *)mem+i) = (char) c;
return NULL;
}
void* memcpy(void *dst, const void *src, unsigned size)
{
unsigned i;
for ( i = 0; i < size; i++)
*(char *)(dst+i) = *(char *)(src+i);
return NULL;
}
int memcmp(const void* buf1, const void* buf2, int count)
{
int i;
for (i=0;i<count;i++)
{
if (*(unsigned char*)buf1<*(unsigned char*)buf2)
return -1;
if (*(unsigned char*)buf1>*(unsigned char*)buf2)
return 1;
}
return 0;
}
void strcat(char strDest[], char strSource[])
{
int i, j;
i = j = 0;
while (strDest[i] != '\0')
i++;
while ((strDest[i++] = strSource[j++]) != '\0')
;
}
int strcmp(const char* string1, const char* string2)
{
while (1)
{
if (*string1<*string2)
return -1;
if (*string1>*string2)
return 1;
if (*string1=='\0')
return 0;
string1++;
string2++;
}
}
void strcpy(char strDest[], const char strSource[])
{
unsigned i;
i = 0;
while ((strDest[i] = strSource[i]) != '\0')
i++;
}
char* strncpy(char *strDest, const char *strSource, unsigned n)
{
unsigned i;
if (! n )
return strDest;
i = 0;
while ((strDest[i] = strSource[i]) != '\0')
if ( (n-1) == i )
break;
else
i++;
return strDest;
}
int strlen(const char* string)
{
int i;
i=0;
while (*string++) i++;
return i;
}
char* strchr(const char* string, int c)
{
while (*string)
{
if (*string==c)
return (char*)string;
string++;
}
return (char*)0;
}

View File

@ -0,0 +1,15 @@
#ifndef NULL
#define NULL ((void*)0)
#endif
void* memset(void *mem, int c, unsigned size);
void* memcpy(void *dst, const void *src, unsigned size);
int memcmp(const void* buf1, const void* buf2, int count);
void strcat(char strDest[], char strSource[]);
int strcmp(const char* string1, const char* string2);
void strcpy(char strDest[], const char strSource[]);
char* strncpy(char *strDest, const char *strSource, unsigned n);
int strlen(const char* string);
char *strchr(const char* string, int c);

View File

@ -0,0 +1,447 @@
/*=====================================================================
Macros.c -> Macros used on the opcode execution.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Copyright (c) 2000 Santiago Romero Iglesias.
Email: sromero@escomposlinux.org
======================================================================*/
/* defines for the registers: faster access to them when coding... */
#define r_PC regs->PC.W
#define r_PCl regs->PC.B.l
#define r_PCh regs->PC.B.h
#define r_SP regs->SP.W
#define r_IFF1 regs->IFF1
#define r_IFF2 regs->IFF2
#define r_R regs->R.W
#define r_AF regs->AF.W
#define r_A regs->AF.B.h
#define r_F regs->AF.B.l
#define r_BC regs->BC.W
#define r_B regs->BC.B.h
#define r_C regs->BC.B.l
#define r_DE regs->DE.W
#define r_D regs->DE.B.h
#define r_E regs->DE.B.l
#define r_HL regs->HL.W
#define r_H regs->HL.B.h
#define r_L regs->HL.B.l
#define r_IX regs->IX.W
#define r_IXh regs->IX.B.h
#define r_IXl regs->IX.B.l
#define r_IY regs->IY.W
#define r_IYh regs->IY.B.h
#define r_IYl regs->IY.B.l
#define r_AFs regs->AFs.W
#define r_As regs->AFs.B.h
#define r_Fs regs->AFs.B.l
#define r_BCs regs->BCs.W
#define r_Bs regs->BCs.B.h
#define r_Cs regs->BCs.B.l
#define r_DEs regs->DEs.W
#define r_Ds regs->DEs.B.h
#define r_Es regs->DEs.B.l
#define r_HLs regs->HLs.W
#define r_Hs regs->HLs.B.h
#define r_Ls regs->HLs.B.l
#define r_IXs regs->IX.W
#define r_IXhs regs->IX.B.h
#define r_IXls regs->IX.B.l
#define r_IYs regs->IY.W
#define r_IYhs regs->IY.B.h
#define r_IYls regs->IY.B.l
#define r_op ops.W
#define r_oph ops.B.h
#define r_opl ops.B.l
#define r_tmp tmpreg2.W
#define r_tmph tmpreg2.B.h
#define r_tmpl tmpreg2.B.l
#define r_mem mread.W
#define r_memh mread.B.h
#define r_meml mread.B.l
#ifndef _DISASM_
/*--- Flag tables by Philip Kendall, taken from it's fuse emulator -*/
/*--- I was having headache trying to emulate correctly the FLAGS,
so I finished using the FLAG tables used by P. Kendall. ------*/
#define FLAG_C 0x01
#define FLAG_N 0x02
#define FLAG_P 0x04
#define FLAG_V FLAG_P
#define FLAG_3 0x08
#define FLAG_H 0x10
#define FLAG_5 0x20
#define FLAG_Z 0x40
#define FLAG_S 0x80
/* Whether a half carry occured or not can be determined by looking at
the 3rd bit of the two arguments and the result; these are hashed
into this table in the form r12, where r is the 3rd bit of the
result, 1 is the 3rd bit of the 1st argument and 2 is the
third bit of the 2nd argument; the tables differ for add and subtract
operations */
/* Whether a half carry occured or not can be determined by looking at
the 3rd bit of the two arguments and the result; these are hashed
into this table in the form r12, where r is the 3rd bit of the
result, 1 is the 3rd bit of the 1st argument and 2 is the
third bit of the 2nd argument; the tables differ for add and subtract
operations */
byte halfcarry_add_table[] = { 0, FLAG_H, FLAG_H, FLAG_H, 0, 0, 0, FLAG_H };
byte halfcarry_sub_table[] = { 0, 0, FLAG_H, 0, FLAG_H, 0, FLAG_H, FLAG_H };
/* Similarly, overflow can be determined by looking at the 7th bits; again
the hash into this table is r12 */
byte overflow_add_table[] = { 0, 0, 0, FLAG_V, FLAG_V, 0, 0, 0 };
byte overflow_sub_table[] = { 0, FLAG_V, 0, 0, 0, 0, FLAG_V, 0 };
/* Some more tables; initialised in z80_init_tables() */
byte sz53_table[0x100]; /* The S, Z, 5 and 3 bits of the temp value */
byte parity_table[0x100]; /* The parity of the temp value */
byte sz53p_table[0x100]; /* OR the above two tables together */
/*------------------------------------------------------------------*/
// Contributed by Metalbrain to implement OUTI, etc.
byte ioblock_inc1_table[64];
byte ioblock_dec1_table[64];
byte ioblock_2_table[0x100];
/*--- Memory Write on the A address on no bank machines -------------*/
void Z80WriteMem( word where, word A, Z80Regs *regs)
{
if( where >= 16384 )
regs->RAM[where] = A;
}
#endif
/*--- Memory Read from the A address on no bank machines -------------*/
#define Z80ReadMem(A) ((regs->RAM[(A)]))
// return( regs->RAM[A] );
/* macros to change the ICount register */
#define AddCycles(n) regs->ICount-=(n)
#define SubCycles(n) regs->ICount+=(n)
//#define AddR(n) r_R = (r_R+(n))
#define AddR(n) r_R = ((r_R & 0x80) | ((r_R+(n)) & 0x7f ))
#define SubR(n) r_R = ((r_R & 0x80) | ((r_R-(n)) & 0x7f ))
/* setting and resetting the flag bits: */
#define SET_FLAG(flag) (r_F |= (flag))
#define RESET_FLAG(flag) (r_F &= ~(flag))
#define TEST_FLAG(flag) (r_F & (flag))
/* store a given register in the stack (hi and lo bytes) */
#define PUSH(rreg) \
Z80WriteMem( --(r_SP), regs->rreg.B.h, regs); \
Z80WriteMem( --(r_SP), regs->rreg.B.l, regs)
#define POP(rreg)\
regs->rreg.B.l = Z80ReadMem(r_SP); r_SP++;\
regs->rreg.B.h = Z80ReadMem(r_SP); r_SP++
#define PUSH_IXYr() \
Z80WriteMem( --(r_SP), REGH, regs); \
Z80WriteMem( --(r_SP), REGL, regs)
#define POP_IXYr()\
REGL = Z80ReadMem(r_SP); r_SP++; \
REGH = Z80ReadMem(r_SP); r_SP++
#define RST(rstval) PUSH(PC); r_PC=(rstval)
/*--- Move data to mem or regs --------------------------------------*/
#define LD_r_r(dreg, sreg) (dreg) = (sreg)
#define STORE_r(daddreg, sreg) Z80WriteMem((daddreg), (sreg), regs)
#define STORE_nn_rr(dreg) \
r_opl = Z80ReadMem(r_PC); r_PC++;\
r_oph = Z80ReadMem(r_PC); r_PC++; \
r_tmp = dreg; \
Z80WriteMem((r_op),r_tmpl, regs); \
Z80WriteMem((r_op+1),r_tmph, regs)
#define STORE_nn_r(sreg) \
r_opl = Z80ReadMem(r_PC); r_PC++; \
r_oph = Z80ReadMem(r_PC); r_PC++; \
Z80WriteMem((r_op),(sreg), regs)
#define LOAD_r(dreg, saddreg) (dreg)=Z80ReadMem((saddreg))
#define LOAD_rr_nn(dreg) r_opl = Z80ReadMem(r_PC); r_PC++; \
r_oph = Z80ReadMem(r_PC); r_PC++; \
r_tmpl = Z80ReadMem(r_op); \
r_tmph = Z80ReadMem((r_op)+1); \
dreg=r_tmp
#define LOAD_r_nn(dreg) r_opl = Z80ReadMem(r_PC); r_PC++; \
r_oph = Z80ReadMem(r_PC); r_PC++; \
dreg = Z80ReadMem(r_op)
#define LD_r_n(reg) (reg) = Z80ReadMem(r_PC++)
#define LD_rr_nn(reg) r_opl = Z80ReadMem(r_PC); r_PC++; \
r_oph = Z80ReadMem(r_PC); r_PC++; \
reg = r_op
#define EX(reg1,reg2) r_opl=(reg1); (reg1)=(reg2); (reg2)=r_opl
#define EX_WORD(reg1,reg2) r_op=(reg1); (reg1)=(reg2); (reg2)=r_op
/*--- Increments/Decrements -----------------------------------------*/
#define INC(reg) (reg)++; \
r_F = ( r_F & FLAG_C ) | ( (reg)==0x80 ? FLAG_V : 0 ) | \
( (reg)&0x0f ? 0 : FLAG_H ) | ( (reg) ? 0 : FLAG_Z ) | \
sz53_table[(reg)]
#define DEC(reg) \
r_F = ( r_F & FLAG_C ) | ( (reg)&0x0f ? 0 : FLAG_H ) | FLAG_N; \
(reg)--; \
r_F |= ( (reg)==0x7f ? FLAG_V : 0 ) | sz53_table[(reg)]
// it was:
// r_F |= ( (reg)==0x79 ? FLAG_V : 0 ) | sz53_table[(reg)]
// But Kak pointed my was not 0x79 -> 0x7F, changed 7-3-2001
/*--- Bit operations ------------------------------------------------*/
#define BIT_RES(b,reg) reg &= ~(0x1<<b)
#define BIT_SET(b,reg) reg |= (0x1<<b)
#define BIT_mem_RES(b,addr) r_opl = Z80ReadMem(addr); \
r_opl &= ~(0x1<<b); \
Z80WriteMem(addr, r_opl, regs)
#define BIT_mem_SET(b,addr) r_opl = Z80ReadMem(addr); \
r_opl |= (0x1<<b); \
Z80WriteMem(addr, r_opl, regs)
#define BIT_RES_mem(b,addr,reg) reg &= ~(0x1<<b); \
Z80WriteMem((addr), (reg), regs)
#define BIT_SET_mem(b,addr,reg) reg |= (0x1<<b); \
Z80WriteMem((addr), (reg), regs)
#define BIT_BIT(b,reg) r_F = ( r_F & FLAG_C ) | \
( (reg) & ( FLAG_3 | FLAG_5 ) ) |\
(((reg) & ( 0x01 << b ) ) ? FLAG_H : \
(FLAG_P|FLAG_H|FLAG_Z ) )
#define BIT_mem_BIT(b,reg) r_opl = Z80ReadMem(reg); \
r_F = ( r_F & FLAG_C ) | \
( (r_opl) & ( FLAG_3 | FLAG_5 ) ) |\
(((r_opl) & ( 0x01 << b ) ) ? FLAG_H : \
(FLAG_P|FLAG_H|FLAG_Z ) )
#define BIT_BIT7(reg) r_F = ( r_F & FLAG_C ) | ( (reg) & \
( FLAG_3 | FLAG_5 ) ) |\
(((reg) & 0x80 ) ? ( FLAG_H | FLAG_S ) :\
( FLAG_P | FLAG_H | FLAG_Z ) )
#define BIT_mem_BIT7(reg) r_opl = Z80ReadMem(reg); \
r_F = ( r_F & FLAG_C ) | ( (r_opl) & \
( FLAG_3 | FLAG_5 ) ) |\
(((r_opl) & 0x80 ) ? ( FLAG_H | FLAG_S ) :\
( FLAG_P | FLAG_H | FLAG_Z ) )
#define RLC(reg) (reg) = ( (reg)<<1 ) | ( (reg)>>7 ); \
r_F = ( (reg) & FLAG_C ) | sz53p_table[(reg)]
#define RRC(reg) r_F = (reg) & FLAG_C; \
(reg) = ( (reg)>>1 ) | ( (reg)<<7 );\
r_F |= sz53p_table[(reg)]
#define RL(reg) r_opl = (reg); \
(reg) = ( (reg)<<1 ) | ( r_F & FLAG_C ); \
r_F = ( r_opl >> 7 ) | sz53p_table[(reg)]
#define RR(reg) r_opl = (reg); \
(reg) = ( (reg)>>1 ) | ( r_F << 7 );\
r_F = ( r_opl & FLAG_C ) | sz53p_table[(reg)]
#define SLA(reg) r_F = (reg) >> 7;\
(reg) <<= 1;\
r_F |= sz53p_table[(reg)]
#define SRA(reg) r_F = (reg) & FLAG_C; \
(reg) = ( (reg) & 0x80 ) | ( (reg) >> 1 );\
r_F |= sz53p_table[(reg)]
#define SLL(reg) r_F = (reg) >> 7;\
(reg) = ( (reg) << 1 ) | 0x01;\
r_F |= sz53p_table[(reg)]
#define SRL(reg) r_F = (reg) & FLAG_C;\
(reg) >>= 1;\
r_F |= sz53p_table[(reg)]
/*--- JP operations -------------------------------------------------*/
#define JP_nn() r_opl = Z80ReadMem(r_PC); \
r_PC++; \
r_oph = Z80ReadMem(r_PC); \
r_PC = r_op
#define JR_n() r_PC += (offset) (Z80ReadMem(r_PC)); r_PC++
#define RET_nn() r_PCl = Z80ReadMem (r_SP); r_SP++; \
r_PCh = Z80ReadMem (r_SP); r_SP++;
#define CALL_nn() r_opl = Z80ReadMem (r_PC); r_PC++; \
r_oph = Z80ReadMem (r_PC); r_PC++; \
Z80WriteMem( --(r_SP), r_PCh, regs ); \
Z80WriteMem( --(r_SP), r_PCl, regs ); \
r_PC = r_op
/*--- ALU operations ------------------------------------------------*/
#define AND(reg) r_A &= (reg); \
r_F = FLAG_H | sz53p_table[r_A]
#define OR(reg) r_A |= (reg); \
r_F = sz53p_table[r_A]
#define XOR(reg) r_A ^= (reg); \
r_F = sz53p_table[r_A]
#define AND_mem(raddress) r_opl = Z80ReadMem(raddress); \
r_A &= (r_opl); \
r_F = FLAG_H | sz53p_table[r_A]
#define OR_mem(raddress) r_opl = Z80ReadMem(raddress); \
r_A |= (r_opl); \
r_F = sz53p_table[r_A]
#define XOR_mem(raddress) r_opl = Z80ReadMem(raddress); \
r_A ^= (r_opl); \
r_F = sz53p_table[r_A]
#define ADD(val) tempword = r_A + (val); \
r_oph = ((r_A&0x88)>>3)|(((val)&0x88)>>2) | \
( (tempword & 0x88) >> 1 ); \
r_A = tempword; \
r_F = ( tempword & 0x100 ? FLAG_C : 0 ) | \
halfcarry_add_table[ r_oph & 0x07] | \
overflow_add_table[ r_oph >> 4] | \
sz53_table[r_A]
#define ADD_WORD(value1,value2) \
tempdword = (value1) + (value2); \
r_oph = ( ( (value1) & 0x0800 ) >> 11 ) | \
( ( (value2) & 0x0800 ) >> 10 ) | \
( ( tempdword & 0x0800 ) >> 9 ); \
(value1) = tempdword; \
r_F = ( r_F & ( FLAG_V | FLAG_Z | FLAG_S ) ) | \
( tempdword & 0x10000 ? FLAG_C : 0 ) | \
(( tempdword >> 8 ) & ( FLAG_3 | FLAG_5 ) ) | \
halfcarry_add_table[r_oph]
#define ADC(value) \
tempword = r_A + (value) + ( r_F & FLAG_C ); \
r_oph = ( (r_A & 0x88) >> 3 ) | ( ( (value) & 0x88 ) >> 2 ) |\
( (tempword & 0x88) >> 1 ); \
r_A = tempword; \
r_F = ( tempword & 0x100 ? FLAG_C : 0 ) | \
halfcarry_add_table[r_oph & 0x07] | \
overflow_add_table[r_oph >> 4] | \
sz53_table[r_A]
#define ADC_WORD(value) \
tempdword= r_HL + (value) + ( r_F & FLAG_C ); \
r_oph = ( ( r_HL & 0x8800 ) >> 11 ) | \
( ( (value) & 0x8800 ) >> 10 ) | \
( ( tempdword & 0x8800 ) >> 9 ); \
r_HL = tempdword; \
r_F = ( tempdword & 0x10000 ? FLAG_C : 0 )| \
overflow_add_table[r_oph >> 4] | \
( r_H & ( FLAG_3 | FLAG_5 | FLAG_S ) ) | \
halfcarry_add_table[ r_oph & 0x0f ]| \
( r_HL ? 0 : FLAG_Z )
#define SUB(value) \
tempword = r_A - (value);\
r_opl = ( (r_A & 0x88) >> 3 ) | \
( ( (value) & 0x88 ) >> 2 ) | \
( (tempword & 0x88) >> 1 ); \
r_A = tempword; \
r_F = ( tempword & 0x100 ? FLAG_C : 0 ) | FLAG_N | \
halfcarry_sub_table[r_opl & 0x07] | \
overflow_sub_table[r_opl >> 4] | \
sz53_table[r_A]
#define SBC(value) \
tempword = r_A - (value) - ( r_F & FLAG_C ); \
r_opl = ( (r_A & 0x88) >> 3 ) | \
( ( (value) & 0x88 ) >> 2 ) | \
( (tempword & 0x88) >> 1 ); \
r_A = tempword; \
r_F = ( tempword & 0x100 ? FLAG_C : 0 ) | FLAG_N | \
halfcarry_sub_table[r_opl & 0x07] | \
overflow_sub_table[r_opl >> 4] | \
sz53_table[r_A]
#define SBC_WORD(Rg) \
tempword=r_F & C_FLAG; r_op=(r_HL-Rg-tempword)&0xFFFF; \
r_F= \
N_FLAG| \
(((long)r_HL-(long)Rg-(long)tempword)&0x10000? C_FLAG:0)| \
((r_HL^Rg)&(r_HL^r_op)&0x8000? O_FLAG:0)| \
((r_HL^Rg^r_op)&0x1000? H_FLAG:0)| \
(r_op? 0:Z_FLAG)|(r_oph&S_FLAG); \
r_HL=r_op
#define CP(value) \
tempword = r_A - (value);\
r_opl = ( (r_A & 0x88) >> 3 ) | ( ( (value) & 0x88 ) >> 2 ) | \
( (tempword & 0x88) >> 1 ); \
r_F = ( tempword & 0x100 ? FLAG_C : ( tempword ? 0 : FLAG_Z ) ) | FLAG_N |\
halfcarry_sub_table[r_opl & 0x07] | \
overflow_sub_table[r_opl >> 4] | \
( value & ( FLAG_3 | FLAG_5 ) ) | \
( tempword & FLAG_S )
#define NEG_A() r_opl = r_A; r_A=0; SUB(r_opl)
/*--- MISC operations -----------------------------------------------*/
#define IN(reg,port) (reg)=Z80InPort((port)); \
r_F = ( r_F & FLAG_C) | sz53p_table[(reg)]

View File

@ -0,0 +1,356 @@
/*====================================================================/*
opcodes_cb.c -> This file executes the CB PREFIX opcodes.
When you find the CB opcode, it means that you must fetch another
byte from memory and treat it as a new opcode with different
meaning than the single-byte opcodes. This is a common way to extend
the number of opcodes (8 bits of instruction word = just 256 opcodes)
and it's called an OPCODE PREFIX (now we have another 256 new opcodes
by using this trick).
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Copyright (c) 2000 Santiago Romero Iglesias.
Email: sromero@escomposlinux.org
=====================================================================*/
/* 8 clock cycles minimum = CB opcode = 4+4 */
opcode = Z80ReadMem( r_PC );
r_PC++;
switch(opcode)
{
case RLC_B : RLC(r_B); AddCycles( 4+4 ); break;
case RLC_C : RLC(r_C); AddCycles( 4+4 ); break;
case RLC_D : RLC(r_D); AddCycles( 4+4 ); break;
case RLC_E : RLC(r_E); AddCycles( 4+4 ); break;
case RLC_H : RLC(r_H); AddCycles( 4+4 ); break;
case RLC_L : RLC(r_L); AddCycles( 4+4 ); break;
case RLC_xHL : r_meml = Z80ReadMem( r_HL );
RLC(r_meml);
Z80WriteMem( r_HL, r_meml, regs );
AddCycles( 4+4+3+3+1 ); break;
case RLC_A : RLC(r_A); AddCycles( 4+4 ); break;
case RRC_B : RRC(r_B); AddCycles( 4+4 ); break;
case RRC_C : RRC(r_C); AddCycles( 4+4 ); break;
case RRC_D : RRC(r_D); AddCycles( 4+4 ); break;
case RRC_E : RRC(r_E); AddCycles( 4+4 ); break;
case RRC_H : RRC(r_H); AddCycles( 4+4 ); break;
case RRC_L : RRC(r_L); AddCycles( 4+4 ); break;
case RRC_xHL : r_meml = Z80ReadMem( r_HL );
RRC(r_meml);
Z80WriteMem( r_HL, r_meml, regs );
AddCycles( 4+4+3+3+1 ); break;
case RRC_A : RRC(r_A); AddCycles( 4+4 ); break;
case RL_B : RL(r_B); AddCycles( 4+4 ); break;
case RL_C : RL(r_C); AddCycles( 4+4 ); break;
case RL_D : RL(r_D); AddCycles( 4+4 ); break;
case RL_E : RL(r_E); AddCycles( 4+4 ); break;
case RL_H : RL(r_H); AddCycles( 4+4 ); break;
case RL_L : RL(r_L); AddCycles( 4+4 ); break;
case RL_xHL : r_meml = Z80ReadMem( r_HL );
RL(r_meml);
Z80WriteMem( r_HL, r_meml, regs );
AddCycles( 4+4+3+3+1 ); break;
case RL_A : RL(r_A); AddCycles( 4+4 ); break;
case RR_B : RR(r_B); AddCycles( 4+4 ); break;
case RR_C : RR(r_C); AddCycles( 4+4 ); break;
case RR_D : RR(r_D); AddCycles( 4+4 ); break;
case RR_E : RR(r_E); AddCycles( 4+4 ); break;
case RR_H : RR(r_H); AddCycles( 4+4 ); break;
case RR_L : RR(r_L); AddCycles( 4+4 ); break;
case RR_xHL : r_meml = Z80ReadMem( r_HL );
RR(r_meml);
Z80WriteMem( r_HL, r_meml, regs );
AddCycles( 4+4+3+3+1 ); break;
case RR_A : RR(r_A); AddCycles( 4+4 ); break;
case SLA_B : SLA(r_B); AddCycles( 4+4 ); break;
case SLA_C : SLA(r_C); AddCycles( 4+4 ); break;
case SLA_D : SLA(r_D); AddCycles( 4+4 ); break;
case SLA_E : SLA(r_E); AddCycles( 4+4 ); break;
case SLA_H : SLA(r_H); AddCycles( 4+4 ); break;
case SLA_L : SLA(r_L); AddCycles( 4+4 ); break;
case SLA_xHL : r_meml = Z80ReadMem( r_HL );
SLA(r_meml);
Z80WriteMem( r_HL, r_meml, regs );
AddCycles( 4+4+3+3+1 ); break;
case SLA_A : SLA(r_A); AddCycles( 4+4 ); break;
case SRA_B : SRA(r_B); AddCycles( 4+4 ); break;
case SRA_C : SRA(r_C); AddCycles( 4+4 ); break;
case SRA_D : SRA(r_D); AddCycles( 4+4 ); break;
case SRA_E : SRA(r_E); AddCycles( 4+4 ); break;
case SRA_H : SRA(r_H); AddCycles( 4+4 ); break;
case SRA_L : SRA(r_L); AddCycles( 4+4 ); break;
case SRA_xHL : r_meml = Z80ReadMem( r_HL );
SRA(r_meml);
Z80WriteMem( r_HL, r_meml, regs );
AddCycles( 4+4+3+3+1 ); break;
case SRA_A : SRA(r_A); AddCycles( 4+4 ); break;
case SLL_B : SLL(r_B); AddCycles( 4+4 ); break;
case SLL_C : SLL(r_C); AddCycles( 4+4 ); break;
case SLL_D : SLL(r_D); AddCycles( 4+4 ); break;
case SLL_E : SLL(r_E); AddCycles( 4+4 ); break;
case SLL_H : SLL(r_H); AddCycles( 4+4 ); break;
case SLL_L : SLL(r_L); AddCycles( 4+4 ); break;
case SLL_xHL : r_meml = Z80ReadMem( r_HL );
SLL(r_meml);
Z80WriteMem( r_HL, r_meml, regs );
AddCycles( 4+4+3+3+1 ); break;
case SLL_A : SLL(r_A); AddCycles( 4+4 ); break;
case SRL_B : SRL(r_B); AddCycles( 4+4 ); break;
case SRL_C : SRL(r_C); AddCycles( 4+4 ); break;
case SRL_D : SRL(r_D); AddCycles( 4+4 ); break;
case SRL_E : SRL(r_E); AddCycles( 4+4 ); break;
case SRL_H : SRL(r_H); AddCycles( 4+4 ); break;
case SRL_L : SRL(r_L); AddCycles( 4+4 ); break;
case SRL_xHL : r_meml = Z80ReadMem( r_HL );
SRL(r_meml);
Z80WriteMem( r_HL, r_meml, regs );
AddCycles( 4+4+3+3+1 ); break;
case SRL_A : SRL(r_A); AddCycles( 4+4 ); break;
case BIT_0_B : BIT_BIT(0, r_B); AddCycles( 4+4 ); break;
case BIT_0_C : BIT_BIT(0, r_C); AddCycles( 4+4 ); break;
case BIT_0_D : BIT_BIT(0, r_D); AddCycles( 4+4 ); break;
case BIT_0_E : BIT_BIT(0, r_E); AddCycles( 4+4 ); break;
case BIT_0_H : BIT_BIT(0, r_H); AddCycles( 4+4 ); break;
case BIT_0_L : BIT_BIT(0, r_L); AddCycles( 4+4 ); break;
case BIT_0_xHL : BIT_mem_BIT(0, r_HL); AddCycles( 12 ); break;
case BIT_0_A : BIT_BIT(0, r_A); AddCycles( 4+4 ); break;
case BIT_1_B : BIT_BIT(1, r_B); AddCycles( 4+4 ); break;
case BIT_1_C : BIT_BIT(1, r_C); AddCycles( 4+4 ); break;
case BIT_1_D : BIT_BIT(1, r_D); AddCycles( 4+4 ); break;
case BIT_1_E : BIT_BIT(1, r_E); AddCycles( 4+4 ); break;
case BIT_1_H : BIT_BIT(1, r_H); AddCycles( 4+4 ); break;
case BIT_1_L : BIT_BIT(1, r_L); AddCycles( 4+4 ); break;
case BIT_1_xHL : BIT_mem_BIT(1, r_HL); AddCycles( 12 ); break;
case BIT_1_A : BIT_BIT(1, r_A); AddCycles( 4+4 ); break;
case BIT_2_B : BIT_BIT(2, r_B); AddCycles( 4+4 ); break;
case BIT_2_C : BIT_BIT(2, r_C); AddCycles( 4+4 ); break;
case BIT_2_D : BIT_BIT(2, r_D); AddCycles( 4+4 ); break;
case BIT_2_E : BIT_BIT(2, r_E); AddCycles( 4+4 ); break;
case BIT_2_H : BIT_BIT(2, r_H); AddCycles( 4+4 ); break;
case BIT_2_L : BIT_BIT(2, r_L); AddCycles( 4+4 ); break;
case BIT_2_xHL : BIT_mem_BIT(2, r_HL); AddCycles( 12 ); break;
case BIT_2_A : BIT_BIT(2, r_A); AddCycles( 4+4 ); break;
case BIT_3_B : BIT_BIT(3, r_B); AddCycles( 4+4 ); break;
case BIT_3_C : BIT_BIT(3, r_C); AddCycles( 4+4 ); break;
case BIT_3_D : BIT_BIT(3, r_D); AddCycles( 4+4 ); break;
case BIT_3_E : BIT_BIT(3, r_E); AddCycles( 4+4 ); break;
case BIT_3_H : BIT_BIT(3, r_H); AddCycles( 4+4 ); break;
case BIT_3_L : BIT_BIT(3, r_L); AddCycles( 4+4 ); break;
case BIT_3_xHL : BIT_mem_BIT(3, r_HL); AddCycles( 12 ); break;
case BIT_3_A : BIT_BIT(3, r_A); AddCycles( 4+4 ); break;
case BIT_4_B : BIT_BIT(4, r_B); AddCycles( 4+4 ); break;
case BIT_4_C : BIT_BIT(4, r_C); AddCycles( 4+4 ); break;
case BIT_4_D : BIT_BIT(4, r_D); AddCycles( 4+4 ); break;
case BIT_4_E : BIT_BIT(4, r_E); AddCycles( 4+4 ); break;
case BIT_4_H : BIT_BIT(4, r_H); AddCycles( 4+4 ); break;
case BIT_4_L : BIT_BIT(4, r_L); AddCycles( 4+4 ); break;
case BIT_4_xHL : BIT_mem_BIT(4, r_HL); AddCycles( 12 ); break;
case BIT_4_A : BIT_BIT(4, r_A); AddCycles( 4+4 ); break;
case BIT_5_B : BIT_BIT(5, r_B); AddCycles( 4+4 ); break;
case BIT_5_C : BIT_BIT(5, r_C); AddCycles( 4+4 ); break;
case BIT_5_D : BIT_BIT(5, r_D); AddCycles( 4+4 ); break;
case BIT_5_E : BIT_BIT(5, r_E); AddCycles( 4+4 ); break;
case BIT_5_H : BIT_BIT(5, r_H); AddCycles( 4+4 ); break;
case BIT_5_L : BIT_BIT(5, r_L); AddCycles( 4+4 ); break;
case BIT_5_xHL : BIT_mem_BIT(5, r_HL); AddCycles( 12 ); break;
case BIT_5_A : BIT_BIT(5, r_A); AddCycles( 4+4 ); break;
case BIT_6_B : BIT_BIT(6, r_B); AddCycles( 4+4 ); break;
case BIT_6_C : BIT_BIT(6, r_C); AddCycles( 4+4 ); break;
case BIT_6_D : BIT_BIT(6, r_D); AddCycles( 4+4 ); break;
case BIT_6_E : BIT_BIT(6, r_E); AddCycles( 4+4 ); break;
case BIT_6_H : BIT_BIT(6, r_H); AddCycles( 4+4 ); break;
case BIT_6_L : BIT_BIT(6, r_L); AddCycles( 4+4 ); break;
case BIT_6_xHL : BIT_mem_BIT(6, r_HL); AddCycles( 12 ); break;
case BIT_6_A : BIT_BIT(6, r_A); AddCycles( 4+4 ); break;
case BIT_7_B : BIT_BIT7(r_B); AddCycles( 4+4 ); break;
case BIT_7_C : BIT_BIT7(r_C); AddCycles( 4+4 ); break;
case BIT_7_D : BIT_BIT7(r_D); AddCycles( 4+4 ); break;
case BIT_7_E : BIT_BIT7(r_E); AddCycles( 4+4 ); break;
case BIT_7_H : BIT_BIT7(r_H); AddCycles( 4+4 ); break;
case BIT_7_L : BIT_BIT7(r_L); AddCycles( 4+4 ); break;
case BIT_7_xHL : BIT_mem_BIT7(r_HL); AddCycles( 12 ); break;
case BIT_7_A : BIT_BIT7(r_A); AddCycles( 4+4 ); break;
case RES_0_B : BIT_RES(0, r_B); AddCycles( 4+4 ); break;
case RES_0_C : BIT_RES(0, r_C); AddCycles( 4+4 ); break;
case RES_0_D : BIT_RES(0, r_D); AddCycles( 4+4 ); break;
case RES_0_E : BIT_RES(0, r_E); AddCycles( 4+4 ); break;
case RES_0_H : BIT_RES(0, r_H); AddCycles( 4+4 ); break;
case RES_0_L : BIT_RES(0, r_L); AddCycles( 4+4 ); break;
case RES_0_xHL : BIT_mem_RES(0, r_HL); AddCycles( 4+4+7 ); break;
case RES_0_A : BIT_RES(0, r_A); AddCycles( 4+4 ); break;
case RES_1_B : BIT_RES(1, r_B); AddCycles( 4+4 ); break;
case RES_1_C : BIT_RES(1, r_C); AddCycles( 4+4 ); break;
case RES_1_D : BIT_RES(1, r_D); AddCycles( 4+4 ); break;
case RES_1_E : BIT_RES(1, r_E); AddCycles( 4+4 ); break;
case RES_1_H : BIT_RES(1, r_H); AddCycles( 4+4 ); break;
case RES_1_L : BIT_RES(1, r_L); AddCycles( 4+4 ); break;
case RES_1_xHL : BIT_mem_RES(1, r_HL); AddCycles( 4+4+7 ); break;
case RES_1_A : BIT_RES(1, r_A); AddCycles( 4+4 ); break;
case RES_2_B : BIT_RES(2, r_B); AddCycles( 4+4 ); break;
case RES_2_C : BIT_RES(2, r_C); AddCycles( 4+4 ); break;
case RES_2_D : BIT_RES(2, r_D); AddCycles( 4+4 ); break;
case RES_2_E : BIT_RES(2, r_E); AddCycles( 4+4 ); break;
case RES_2_H : BIT_RES(2, r_H); AddCycles( 4+4 ); break;
case RES_2_L : BIT_RES(2, r_L); AddCycles( 4+4 ); break;
case RES_2_xHL : BIT_mem_RES(2, r_HL); AddCycles( 4+4+7 ); break;
case RES_2_A : BIT_RES(2, r_A); AddCycles( 4+4 ); break;
case RES_3_B : BIT_RES(3, r_B); AddCycles( 4+4 ); break;
case RES_3_C : BIT_RES(3, r_C); AddCycles( 4+4 ); break;
case RES_3_D : BIT_RES(3, r_D); AddCycles( 4+4 ); break;
case RES_3_E : BIT_RES(3, r_E); AddCycles( 4+4 ); break;
case RES_3_H : BIT_RES(3, r_H); AddCycles( 4+4 ); break;
case RES_3_L : BIT_RES(3, r_L); AddCycles( 4+4 ); break;
case RES_3_xHL : BIT_mem_RES(3, r_HL); AddCycles( 4+4+7 ); break;
case RES_3_A : BIT_RES(3, r_A); AddCycles( 4+4 ); break;
case RES_4_B : BIT_RES(4, r_B); AddCycles( 4+4 ); break;
case RES_4_C : BIT_RES(4, r_C); AddCycles( 4+4 ); break;
case RES_4_D : BIT_RES(4, r_D); AddCycles( 4+4 ); break;
case RES_4_E : BIT_RES(4, r_E); AddCycles( 4+4 ); break;
case RES_4_H : BIT_RES(4, r_H); AddCycles( 4+4 ); break;
case RES_4_L : BIT_RES(4, r_L); AddCycles( 4+4 ); break;
case RES_4_xHL : BIT_mem_RES(4, r_HL); AddCycles( 4+4+7 ); break;
case RES_4_A : BIT_RES(4, r_A); AddCycles( 4+4 ); break;
case RES_5_B : BIT_RES(5, r_B); AddCycles( 4+4 ); break;
case RES_5_C : BIT_RES(5, r_C); AddCycles( 4+4 ); break;
case RES_5_D : BIT_RES(5, r_D); AddCycles( 4+4 ); break;
case RES_5_E : BIT_RES(5, r_E); AddCycles( 4+4 ); break;
case RES_5_H : BIT_RES(5, r_H); AddCycles( 4+4 ); break;
case RES_5_L : BIT_RES(5, r_L); AddCycles( 4+4 ); break;
case RES_5_xHL : BIT_mem_RES(5, r_HL); AddCycles( 4+4+7 ); break;
case RES_5_A : BIT_RES(5, r_A); AddCycles( 4+4 ); break;
case RES_6_B : BIT_RES(6, r_B); AddCycles( 4+4 ); break;
case RES_6_C : BIT_RES(6, r_C); AddCycles( 4+4 ); break;
case RES_6_D : BIT_RES(6, r_D); AddCycles( 4+4 ); break;
case RES_6_E : BIT_RES(6, r_E); AddCycles( 4+4 ); break;
case RES_6_H : BIT_RES(6, r_H); AddCycles( 4+4 ); break;
case RES_6_L : BIT_RES(6, r_L); AddCycles( 4+4 ); break;
case RES_6_xHL : BIT_mem_RES(6, r_HL); AddCycles( 4+4+7 ); break;
case RES_6_A : BIT_RES(6, r_A); AddCycles( 4+4 ); break;
case RES_7_B : BIT_RES(7, r_B); AddCycles( 4+4 ); break;
case RES_7_C : BIT_RES(7, r_C); AddCycles( 4+4 ); break;
case RES_7_D : BIT_RES(7, r_D); AddCycles( 4+4 ); break;
case RES_7_E : BIT_RES(7, r_E); AddCycles( 4+4 ); break;
case RES_7_H : BIT_RES(7, r_H); AddCycles( 4+4 ); break;
case RES_7_L : BIT_RES(7, r_L); AddCycles( 4+4 ); break;
case RES_7_xHL : BIT_mem_RES(7, r_HL); AddCycles( 4+4+7 ); break;
case RES_7_A : BIT_RES(7, r_A); AddCycles( 4+4 ); break;
case SET_0_B : BIT_SET(0, r_B); AddCycles( 4+4 ); break;
case SET_0_C : BIT_SET(0, r_C); AddCycles( 4+4 ); break;
case SET_0_D : BIT_SET(0, r_D); AddCycles( 4+4 ); break;
case SET_0_E : BIT_SET(0, r_E); AddCycles( 4+4 ); break;
case SET_0_H : BIT_SET(0, r_H); AddCycles( 4+4 ); break;
case SET_0_L : BIT_SET(0, r_L); AddCycles( 4+4 ); break;
case SET_0_xHL : BIT_mem_SET(0, r_HL); AddCycles( 4+4+7 ); break;
case SET_0_A : BIT_SET(0, r_A); AddCycles( 4+4 ); break;
case SET_1_B : BIT_SET(1, r_B); AddCycles( 4+4 ); break;
case SET_1_C : BIT_SET(1, r_C); AddCycles( 4+4 ); break;
case SET_1_D : BIT_SET(1, r_D); AddCycles( 4+4 ); break;
case SET_1_E : BIT_SET(1, r_E); AddCycles( 4+4 ); break;
case SET_1_H : BIT_SET(1, r_H); AddCycles( 4+4 ); break;
case SET_1_L : BIT_SET(1, r_L); AddCycles( 4+4 ); break;
case SET_1_xHL : BIT_mem_SET(1, r_HL); AddCycles( 4+4+7 ); break;
case SET_1_A : BIT_SET(1, r_A); AddCycles( 4+4 ); break;
case SET_2_B : BIT_SET(2, r_B); AddCycles( 4+4 ); break;
case SET_2_C : BIT_SET(2, r_C); AddCycles( 4+4 ); break;
case SET_2_D : BIT_SET(2, r_D); AddCycles( 4+4 ); break;
case SET_2_E : BIT_SET(2, r_E); AddCycles( 4+4 ); break;
case SET_2_H : BIT_SET(2, r_H); AddCycles( 4+4 ); break;
case SET_2_L : BIT_SET(2, r_L); AddCycles( 4+4 ); break;
case SET_2_xHL : BIT_mem_SET(2, r_HL); AddCycles( 4+4+7 ); break;
case SET_2_A : BIT_SET(2, r_A); AddCycles( 4+4 ); break;
case SET_3_B : BIT_SET(3, r_B); AddCycles( 4+4 ); break;
case SET_3_C : BIT_SET(3, r_C); AddCycles( 4+4 ); break;
case SET_3_D : BIT_SET(3, r_D); AddCycles( 4+4 ); break;
case SET_3_E : BIT_SET(3, r_E); AddCycles( 4+4 ); break;
case SET_3_H : BIT_SET(3, r_H); AddCycles( 4+4 ); break;
case SET_3_L : BIT_SET(3, r_L); AddCycles( 4+4 ); break;
case SET_3_xHL : BIT_mem_SET(3, r_HL); AddCycles( 4+4+7 ); break;
case SET_3_A : BIT_SET(3, r_A); AddCycles( 4+4 ); break;
case SET_4_B : BIT_SET(4, r_B); AddCycles( 4+4 ); break;
case SET_4_C : BIT_SET(4, r_C); AddCycles( 4+4 ); break;
case SET_4_D : BIT_SET(4, r_D); AddCycles( 4+4 ); break;
case SET_4_E : BIT_SET(4, r_E); AddCycles( 4+4 ); break;
case SET_4_H : BIT_SET(4, r_H); AddCycles( 4+4 ); break;
case SET_4_L : BIT_SET(4, r_L); AddCycles( 4+4 ); break;
case SET_4_xHL : BIT_mem_SET(4, r_HL); AddCycles( 4+4+7 ); break;
case SET_4_A : BIT_SET(4, r_A); AddCycles( 4+4 ); break;
case SET_5_B : BIT_SET(5, r_B); AddCycles( 4+4 ); break;
case SET_5_C : BIT_SET(5, r_C); AddCycles( 4+4 ); break;
case SET_5_D : BIT_SET(5, r_D); AddCycles( 4+4 ); break;
case SET_5_E : BIT_SET(5, r_E); AddCycles( 4+4 ); break;
case SET_5_H : BIT_SET(5, r_H); AddCycles( 4+4 ); break;
case SET_5_L : BIT_SET(5, r_L); AddCycles( 4+4 ); break;
case SET_5_xHL : BIT_mem_SET(5, r_HL); AddCycles( 4+4+7 ); break;
case SET_5_A : BIT_SET(5, r_A); AddCycles( 4+4 ); break;
case SET_6_B : BIT_SET(6, r_B); AddCycles( 4+4 ); break;
case SET_6_C : BIT_SET(6, r_C); AddCycles( 4+4 ); break;
case SET_6_D : BIT_SET(6, r_D); AddCycles( 4+4 ); break;
case SET_6_E : BIT_SET(6, r_E); AddCycles( 4+4 ); break;
case SET_6_H : BIT_SET(6, r_H); AddCycles( 4+4 ); break;
case SET_6_L : BIT_SET(6, r_L); AddCycles( 4+4 ); break;
case SET_6_xHL : BIT_mem_SET(6, r_HL); AddCycles( 4+4+7 ); break;
case SET_6_A : BIT_SET(6, r_A); AddCycles( 4+4 ); break;
case SET_7_B : BIT_SET(7, r_B); AddCycles( 4+4 ); break;
case SET_7_C : BIT_SET(7, r_C); AddCycles( 4+4 ); break;
case SET_7_D : BIT_SET(7, r_D); AddCycles( 4+4 ); break;
case SET_7_E : BIT_SET(7, r_E); AddCycles( 4+4 ); break;
case SET_7_H : BIT_SET(7, r_H); AddCycles( 4+4 ); break;
case SET_7_L : BIT_SET(7, r_L); AddCycles( 4+4 ); break;
case SET_7_xHL : BIT_mem_SET(7, r_HL); AddCycles( 4+4+7 ); break;
case SET_7_A : BIT_SET(7, r_A); AddCycles( 4+4 ); break;
default:
// exit(1);
///!!! if( regs->DecodingErrors )
///!!! printf("z80 core: Unknown instruction: CB %02Xh at PC=%04Xh.\n",
///!!! Z80ReadMem(r_PC-1), r_PC-2 );
break;
}

View File

@ -0,0 +1,239 @@
/*====================================================================/*
opcodes_dd_fd.c -> This file executes the DD/FD PREFIX opcodes.
The DD prefix "creates" some new instructions by changing HL to IX
on the opcode defined by the next byte on memory.
The FD prefix "creates" some new instructions by changing HL to IY
on the opcode defined by the next byte on memory.
Change the REGISTER variable to IX or HY before including this file.
Something like:
#define REGISTER regs->IX
#include "op_dd_fd.c"
#undef REGISTER
On this code, this REGISTER variable is used as REGISTER.W or
REGISTER.B.h and REGISTER.B.l ...
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Copyright (c) 2000 Santiago Romero Iglesias.
Email: sromero@escomposlinux.org
=====================================================================*/
/* 8 clock cycles minimum = DD opcode = FD opcode = 4 + 4 */
#define REG REGISTER.W
#define REGL REGISTER.B.l
#define REGH REGISTER.B.h
opcode = Z80ReadMem( r_PC );
r_PC++;
switch(opcode)
{
case ADD_IXY_BC : ADD_WORD(REG, r_BC); AddCycles( 4+4+7 ); break;
case ADD_IXY_DE : ADD_WORD(REG, r_DE); AddCycles( 4+4+7 ); break;
case ADD_IXY_SP : ADD_WORD(REG, r_SP); AddCycles( 4+4+7 ); break;
case ADD_IXY_IXY : ADD_WORD(REG, REG); AddCycles( 4+4+7 ); break;
case DEC_IXY : REG--; AddCycles( 4+4+2 ); break;
case INC_IXY : REG++; AddCycles( 4+4 ); break;
case JP_IXY : r_PC = REG; AddCycles( 4+4 );break;
case LD_SP_IXY : r_SP = REG; AddCycles( 4+4+2 ); break;
case PUSH_IXY : PUSH_IXYr(); AddCycles( 4+4+3+3+1 ); break;
case POP_IXY : POP_IXYr(); AddCycles( 4+4+3+3 ); break;
case EX_IXY_xSP : r_meml = Z80ReadMem(r_SP);
r_memh = Z80ReadMem(r_SP+1);
Z80WriteMem( r_SP, REGL, regs );
Z80WriteMem( r_SP+1, REGH, regs );
REGL=r_meml; REGH=r_memh;
AddCycles( 4+4+3+3+3+3+3 ); break;
case LD_A_xIXY : r_A = Z80ReadMem( REG+ ((offset) Z80ReadMem(r_PC)) );
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
case LD_B_xIXY : r_B = Z80ReadMem( REG+ ((offset) Z80ReadMem(r_PC)) );
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
case LD_C_xIXY : r_C = Z80ReadMem( REG+ ((offset) Z80ReadMem(r_PC)) );
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
case LD_D_xIXY : r_D = Z80ReadMem( REG+ ((offset) Z80ReadMem(r_PC)) );
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
case LD_E_xIXY : r_E = Z80ReadMem( REG+ ((offset) Z80ReadMem(r_PC)) );
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
case LD_xIXY_A : Z80WriteMem( REG+(offset)Z80ReadMem(r_PC), r_A, regs );
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
case LD_xIXY_B : Z80WriteMem( REG+(offset)Z80ReadMem(r_PC), r_B, regs );
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
case LD_xIXY_C : Z80WriteMem( REG+(offset)Z80ReadMem(r_PC), r_C, regs );
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
case LD_xIXY_D : Z80WriteMem( REG+(offset)Z80ReadMem(r_PC), r_D, regs );
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
case LD_xIXY_E : Z80WriteMem( REG+(offset)Z80ReadMem(r_PC), r_E, regs );
r_PC++; AddCycles( 4+3+3+3+3+3 ); break;
case INC_xIXY : r_mem = REG+(offset)Z80ReadMem(r_PC);
r_PC++;
tmpreg.B.l = Z80ReadMem(r_mem);
INC(tmpreg.B.l);
Z80WriteMem(r_mem, tmpreg.B.l, regs );
AddCycles( 4+3+3 + 3+3+3+ 3+1); break;
case DEC_xIXY : r_mem = REG+(offset)Z80ReadMem(r_PC);
r_PC++;
tmpreg.B.l = Z80ReadMem(r_mem);
DEC(tmpreg.B.l);
Z80WriteMem(r_mem, tmpreg.B.l, regs );
AddCycles( 4+3+3 + 3+3+3+ 3+1); break;
case ADC_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC)); r_PC++;
ADC(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
case SBC_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
r_PC++;
SBC(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
case ADD_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
r_PC++;
ADD(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
case SUB_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
r_PC++;
SUB(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
case AND_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
r_PC++;
AND(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
case OR_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
r_PC++;
OR(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
case XOR_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
r_PC++;
XOR(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
case CP_xIXY : r_meml = Z80ReadMem(REG+(offset)Z80ReadMem(r_PC));
r_PC++;
CP(r_meml); AddCycles( 4+3+3+3+3+3 ); break;
case LD_IXY_NN : REGL = Z80ReadMem(r_PC); r_PC++;
REGH = Z80ReadMem(r_PC); r_PC++;
AddCycles( 4+1+3+3+3 ); break;
case LD_xIXY_N : r_mem = REG + (offset) Z80ReadMem(r_PC); r_PC++;
Z80WriteMem( r_mem, Z80ReadMem(r_PC), regs ); r_PC++;
AddCycles( 4+3+3+3+3+3 ); break;
case LD_IXY_xNN : LOAD_rr_nn(REG);
AddCycles( 4+3+3+3+3+3+1 ); break;
case LD_xNN_IXY : STORE_nn_rr(REG);
AddCycles( 4+3+3+ 3+3+3+1 ); break;
/* some undocumented opcodes: may be wrong: */
case LD_A_IXYh : r_A = REGH; AddCycles(4+4); break;
case LD_A_IXYl : r_A = REGL; AddCycles(4+4); break;
case LD_B_IXYh : r_B = REGH; AddCycles(4+4); break;
case LD_B_IXYl : r_B = REGL; AddCycles(4+4); break;
case LD_C_IXYh : r_C = REGH; AddCycles(4+4); break;
case LD_C_IXYl : r_C = REGL; AddCycles(4+4); break;
case LD_D_IXYh : r_D = REGH; AddCycles(4+4); break;
case LD_D_IXYl : r_D = REGL; AddCycles(4+4); break;
case LD_E_IXYh : r_E = REGH; AddCycles(4+4); break;
case LD_E_IXYl : r_E = REGL; AddCycles(4+4); break;
case LD_IXYh_A : REGH = r_A; AddCycles(4+4); break;
case LD_IXYh_B : REGH = r_B; AddCycles(4+4); break;
case LD_IXYh_C : REGH = r_C; AddCycles(4+4); break;
case LD_IXYh_D : REGH = r_D; AddCycles(4+4); break;
case LD_IXYh_E : REGH = r_E; AddCycles(4+4); break;
case LD_IXYh_IXYh : AddCycles(4+4); break;
case LD_IXYh_IXYl : REGH = REGL; AddCycles(4+4); break;
case LD_IXYl_A : REGL = r_A; AddCycles(4+4); break;
case LD_IXYl_B : REGL = r_B; AddCycles(4+4); break;
case LD_IXYl_C : REGL = r_C; AddCycles(4+4); break;
case LD_IXYl_D : REGL = r_D; AddCycles(4+4); break;
case LD_IXYl_E : REGL = r_E; AddCycles(4+4); break;
case LD_IXYl_IXYh : REGL = REGH; AddCycles(4+4); break;
case LD_IXYl_IXYl : AddCycles(4+4); break;
case LD_IXYh_N : REGH = Z80ReadMem(r_PC); r_PC++;
AddCycles(4+4+3); break;
case LD_IXYl_N : REGL = Z80ReadMem(r_PC); r_PC++;
AddCycles(4+4+3); break;
case ADD_IXYh : ADD(REGH); AddCycles(4+4); break;
case ADD_IXYl : ADD(REGL); AddCycles(4+4); break;
case ADC_IXYh : ADC(REGH); AddCycles(4+4); break;
case ADC_IXYl : ADC(REGL); AddCycles(4+4); break;
case SUB_IXYh : SUB(REGH); AddCycles(4+4); break;
case SUB_IXYl : SUB(REGL); AddCycles(4+4); break;
case SBC_IXYh : SBC(REGH); AddCycles(4+4); break;
case SBC_IXYl : SBC(REGL); AddCycles(4+4); break;
case AND_IXYh : AND(REGH); AddCycles(4+4); break;
case AND_IXYl : AND(REGL); AddCycles(4+4); break;
case XOR_IXYh : XOR(REGH); AddCycles(4+4); break;
case XOR_IXYl : XOR(REGL); AddCycles(4+4); break;
case OR_IXYh : OR(REGH); AddCycles(4+4); break;
case OR_IXYl : OR(REGL); AddCycles(4+4); break;
case CP_IXYh : CP(REGH); AddCycles(4+4); break;
case CP_IXYl : CP(REGL); AddCycles(4+4); break;
case INC_IXYh : INC(REGH); AddCycles(4+4); break;
case INC_IXYl : INC(REGL); AddCycles(4+4); break;
case DEC_IXYh : DEC(REGH); AddCycles(4+4); break;
case DEC_IXYl : DEC(REGL); AddCycles(4+4); break;
case LD_xIXY_H : r_meml =Z80ReadMem(r_PC); r_PC++;
Z80WriteMem( REG+(offset)(r_meml), r_H, regs );
AddCycles( 4+3+3+3+3+3 ); break;
case LD_xIXY_L : r_meml =Z80ReadMem(r_PC); r_PC++;
Z80WriteMem( REG+(offset)(r_meml), r_L, regs );
AddCycles( 4+3+3+3+3+3 ); break;
case LD_H_xIXY : r_meml =Z80ReadMem(r_PC); r_PC++;
r_H = Z80ReadMem( REG+(offset)(r_meml));
AddCycles( 4+3+3+3+3+3 ); break;
case LD_L_xIXY : r_meml =Z80ReadMem(r_PC); r_PC++;
r_L = Z80ReadMem( REG+(offset)(r_meml));
AddCycles( 4+3+3+3+3+3 ); break;
case PREFIX_CB:
#include "opddfdcb.c"
break;
/*
case PREFIX_DD:
case PREFIX_FD: AddCycles( 4 );
r_PC--; // decode it the next time :)
break;
*/
default: AddCycles( 4 );
r_PC--; /* decode it the next time :) */
SubR(1);
// exit(1);
// if( regs->DecodingErrors )
// {
// printf("z80 core: Unknown instruction: ");
// if ( regs->we_are_on_ddfd == WE_ARE_ON_DD )
// printf("DD ");
// else
// printf("FD ");
// printf("%02Xh at PC=%04Xh.\n", Z80ReadMem(r_PC-1), r_PC-2 );
// }
break;
}
#undef REG
#undef REGL
#undef REGH

View File

@ -0,0 +1,417 @@
/*====================================================================/*
opcodes_ed.c -> This file executes the ED opcodes.
Another prefix that "creates" new instructions. This prefix also
introduces some undocumented opcodes that we've tried to include
here. Maybe their implementation it's wrong: if you can find any
mistake about how we have implemented/interpreted them, please
let us know.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Copyright (c) 2000 Santiago Romero Iglesias.
Email: sromero@escomposlinux.org
=====================================================================*/
/* 8 clock cycles minimum = ED opcode = 4 + 4 */
opcode = Z80ReadMem( r_PC );
r_PC++;
switch(opcode)
{
case LD_BC_xNNe : LOAD_rr_nn(r_BC); AddCycles( 4+4+12 ); break;
case LD_DE_xNNe : LOAD_rr_nn(r_DE); AddCycles( 4+4+12 ); break;
case LD_HL_xNNe : LOAD_rr_nn(r_HL); AddCycles( 4+4+12 ); break;
case LD_SP_xNNe : LOAD_rr_nn(r_SP); AddCycles( 4+4+12 ); break;
case LD_xNNe_BC : STORE_nn_rr(r_BC); AddCycles( 4+4+12 ); break;
case LD_xNNe_DE : STORE_nn_rr(r_DE); AddCycles( 4+4+12 ); break;
case LD_xNNe_HL : STORE_nn_rr(r_HL); AddCycles( 4+4+12 ); break;
case LD_xNNe_SP : STORE_nn_rr(r_SP); AddCycles( 4+4+12 ); break;
case NEG :
case ED_5C :
case ED_74 :
case ED_7C :
case ED_6C :
case ED_54 :
case ED_4C :
case ED_64 : NEG_A(); AddCycles( 4+4 ); break;
case RETI :
case RETN :
case ED_65 :
case ED_6D :
case ED_75 :
case ED_7D :
case ED_5D :
case ED_55 :
r_IFF1 = r_IFF2;
RET_nn();
AddCycles( 4+4+6 ); break;
case IM_0 :
case ED_4E : /* * IM 0/1 */
case ED_6E :
case ED_66 : regs->IM = 0;
AddCycles( 4+4 ); break; /* * IM 0 */
case IM_1 :
case ED_76 : regs->IM = 1;
AddCycles( 4+4 ); break;
case IM_2 :
case ED_7E : regs->IM = 2;
AddCycles( 4+4 ); break;
case ED_77 :
case ED_7F : AddCycles( 4+4 ); break; /* * NOP */
case OUT_xC_B : Z80OutPort(regs,r_BC, r_B); AddCycles( 4+4+4 ); break;
case OUT_xC_C : Z80OutPort(regs,r_BC, r_C); AddCycles( 4+4+4 ); break;
case OUT_xC_D : Z80OutPort(regs,r_BC, r_D); AddCycles( 4+4+4 ); break;
case OUT_xC_E : Z80OutPort(regs,r_BC, r_E); AddCycles( 4+4+4 ); break;
case OUT_xC_H : Z80OutPort(regs,r_BC, r_H); AddCycles( 4+4+4 ); break;
case OUT_xC_L : Z80OutPort(regs,r_BC, r_L); AddCycles( 4+4+4 ); break;
case OUT_xC_A : Z80OutPort(regs,r_BC, r_A); AddCycles( 4+4+4 ); break;
/* * OUT (C), 0 */
case ED_71 : Z80OutPort(regs,r_BC, 0); AddCycles( 4+4+4 ); break;
case IN_B_xC : IN(r_B, r_BC); AddCycles( 4+4+4 ); break;
case IN_C_xC : IN(r_C, r_BC); AddCycles( 4+4+4 ); break;
case IN_D_xC : IN(r_D, r_BC); AddCycles( 4+4+4 ); break;
case IN_E_xC : IN(r_E, r_BC); AddCycles( 4+4+4 ); break;
case IN_L_xC : IN(r_L, r_BC); AddCycles( 4+4+4 ); break;
case IN_H_xC : IN(r_H, r_BC); AddCycles( 4+4+4 ); break;
case IN_A_xC : IN(r_A, r_BC); AddCycles( 4+4+4 ); break;
case IN_F_xC : IN(r_meml, r_BC); AddCycles( 4+4+4 ); break;
case LD_A_I : r_A = regs->I;
r_F = ( r_F & FLAG_C )|sz53_table[r_A]|
( regs->IFF2 ? FLAG_V:0 );
AddCycles( 4+4+1 ); break;
case LD_I_A : regs->I = r_A; AddCycles( 4+4+1 ); break;
case LD_A_R : r_A = ( regs->R.W & 0x7f ) | (regs->R.W & 0x80);
r_F = (r_F&FLAG_C)|sz53_table[r_A] | (regs->IFF2?FLAG_V:0);
AddCycles( 4+4+1 ); break;
case LD_R_A : regs->R.W = r_A;
AddCycles( 4+4+1 ); break;
case ADC_HL_BC : ADC_WORD(r_BC); AddCycles( 4+4+4+1+2 ); break;
case ADC_HL_DE : ADC_WORD(r_DE); AddCycles( 4+4+4+1+2 ); break;
case ADC_HL_HL : ADC_WORD(r_HL); AddCycles( 4+4+4+1+2 ); break;
case ADC_HL_SP : ADC_WORD(r_SP); AddCycles( 4+4+4+1+2 ); break;
case SBC_HL_BC : SBC_WORD(r_BC); AddCycles( 4+4+4+1+2 ); break;
case SBC_HL_DE : SBC_WORD(r_DE); AddCycles( 4+4+4+1+2 ); break;
case SBC_HL_HL : SBC_WORD(r_HL); AddCycles( 4+4+4+1+2 ); break;
case SBC_HL_SP : SBC_WORD(r_SP); AddCycles( 4+4+4+1+2 ); break;
case RRD : r_meml = Z80ReadMem(r_HL);
Z80WriteMem(r_HL, ( r_A << 4 ) | ( r_meml >> 4 ), regs );
r_A = ( r_A & 0xf0 ) | ( r_meml & 0x0f );
r_F = ( r_F & FLAG_C ) | sz53p_table[r_A];
AddCycles( 4+4+10 ); break;
case RLD : r_meml = Z80ReadMem(r_HL);
Z80WriteMem(r_HL, (r_meml << 4 ) | ( r_A & 0x0f ), regs );
r_A = ( r_A & 0xf0 ) | ( r_meml >> 4 );
r_F = ( r_F & FLAG_C ) | sz53p_table[r_A];
AddCycles( 4+4+10 ); break;
case LDI : r_meml = Z80ReadMem(r_HL); r_HL++;
Z80WriteMem( r_DE, r_meml, regs ); r_DE++;
r_BC--; r_meml += r_A;
r_F = ( r_F & ( FLAG_C|FLAG_Z|FLAG_S ) ) |
( r_BC ? FLAG_V:0 ) | ( r_meml & FLAG_3 ) |
((r_meml & 0x02) ? FLAG_5 : 0 );
AddCycles( 4+4+4+4 ); break;
case LDIR : r_meml = Z80ReadMem(r_HL); r_HL++;
Z80WriteMem( r_DE, r_meml, regs ); r_DE++;
r_BC--; r_meml += r_A;
r_F = ( r_F & ( FLAG_C|FLAG_Z|FLAG_S ) ) |
( r_BC ? FLAG_V:0 ) | ( r_meml & FLAG_3 ) |
((r_meml & 0x02) ? FLAG_5 : 0 );
AddCycles( 4+4+4+4 );
if( r_BC ) { r_PC-=2; AddCycles(5); }
break;
case LDD : r_meml = Z80ReadMem(r_HL); r_HL--;
Z80WriteMem( r_DE, r_meml, regs ); r_DE--;
r_BC--; r_meml += r_A;
r_F = ( r_F & ( FLAG_C | FLAG_Z | FLAG_S ) ) |
(r_BC ? FLAG_V : 0 ) | ( r_meml & FLAG_3 ) |
((r_meml & 0x02) ? FLAG_5 : 0 );
AddCycles( 4+4+4+4 ); break;
case LDDR : r_meml = Z80ReadMem(r_HL);
Z80WriteMem( r_DE, r_meml, regs );
r_HL--; r_DE--; r_BC--; r_meml += r_A;
r_F = ( r_F & ( FLAG_C | FLAG_Z | FLAG_S ) ) |
(r_BC ? FLAG_V : 0 ) | ( r_meml & FLAG_3 ) |
((r_meml & 0x02) ? FLAG_5 : 0 );
AddCycles( 4+4+4+4+1 );
if( r_BC ) { r_PC-=2; AddCycles(4); }
break;
// I had lots of problems with CPI, INI, CPD, IND, OUTI, OUTD and so...
// Thanks a lot to Philip Kendall for letting me to take a look to his
// fuse emulator and allowing me to use their flag routines :-)
case CPI : r_meml = Z80ReadMem(r_HL);
r_memh = r_A - r_meml;
r_opl = ( (r_A & 0x08) >> 3 ) |
( ( (r_meml) & 0x08 ) >> 2 ) |
( (r_meml & 0x08) >> 1 );
r_HL++; r_BC--;
r_F = ( r_F & FLAG_C ) |
( r_BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |
halfcarry_sub_table[r_opl] |
( r_memh ? 0 : FLAG_Z ) |
( r_memh & FLAG_S );
if( r_F & FLAG_H) r_memh--;
r_F |= ( r_memh & FLAG_3 ) |
( (r_memh&0x02) ? FLAG_5 : 0 );
AddCycles( 4+4+4+4); break;
case CPIR : r_meml = Z80ReadMem(r_HL);
r_memh = r_A - r_meml;
r_opl = ( (r_A & 0x08) >> 3 ) |
( ( (r_meml) & 0x08 ) >> 2 ) |
( (r_meml & 0x08) >> 1 );
r_HL++; r_BC--;
r_F = ( r_F & FLAG_C ) |
( r_BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |
halfcarry_sub_table[r_opl] |
( r_memh ? 0 : FLAG_Z ) |
( r_memh & FLAG_S );
if( r_F & FLAG_H) r_memh--;
r_F |= ( r_memh & FLAG_3 ) |
( (r_memh&0x02) ? FLAG_5 : 0 );
if( ( r_F & ( FLAG_V | FLAG_Z ) ) == FLAG_V )
{ AddCycles(5); r_PC-=2; }
AddCycles( 4+4+4+4); break;
case CPD : r_meml = Z80ReadMem(r_HL);
r_memh = r_A-r_meml;
r_opl = ( (r_A & 0x08) >> 3 ) |
( ( (r_meml) & 0x08 ) >> 2 ) |
( (r_memh & 0x08) >> 1 );
r_HL--; r_BC--;
r_F = ( r_F & FLAG_C ) |
( r_BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |
halfcarry_sub_table[r_opl] |
( r_memh ? 0 : FLAG_Z ) |
( r_memh & FLAG_S );
if(r_F & FLAG_H) r_memh--;
r_F |= ( r_memh & FLAG_3 ) |
( (r_memh&0x02) ? FLAG_5 : 0 );
AddCycles( 4+4+4+4); break;
case CPDR : r_meml = Z80ReadMem(r_HL);
r_memh = r_A-r_meml;
r_opl = ( (r_A & 0x08) >> 3 ) |
( ( (r_meml) & 0x08 ) >> 2 ) |
( (r_memh & 0x08) >> 1 );
r_HL--; r_BC--;
r_F = ( r_F & FLAG_C ) |
( r_BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |
halfcarry_sub_table[r_opl] |
( r_memh ? 0 : FLAG_Z ) |
( r_memh & FLAG_S );
if(r_F & FLAG_H) r_memh--;
r_F |= ( r_memh & FLAG_3 ) |
( (r_memh&0x02) ? FLAG_5 : 0 );
if( ( r_F & ( FLAG_V | FLAG_Z ) ) == FLAG_V )
{ AddCycles(5); r_PC-=2; }
AddCycles( 4+4+4+4 ); break;
/*
// OUTI contributed by Alvaro Alea
case OUTI : Z80OutPort( regs, r_BC, Z80ReadMem( r_HL )) ;
r_HL++ ; r_B-- ;
if (r_B==0)
r_F |= FLAG_Z;
else
r_F &= !FLAG_Z;
r_F |= FLAG_N;
AddCycles( 4+4+4+4 ); break;
*/
// I/O block instructions by Metalbrain - 14-5-2001
case IND : r_meml = Z80InPort((r_BC)); r_memh=0;
r_F = ( r_F & FLAG_C ) | ( (r_B)&0x0f ? 0 : FLAG_H ) | FLAG_N; \
(r_B)--;
r_F |= ( (r_B)==0x7f ? FLAG_V : 0 ) | sz53_table[(r_B)];
r_F &= 0xE8;
Z80WriteMem( r_HL, r_meml, regs );
r_F |= ( (r_meml & 0x80 ) >> 6);
r_opl = r_C; r_oph = 0;
r_opl--;
r_op += r_mem;
r_oph += (r_oph << 4);
r_F |= r_oph;
r_opl = (r_meml & 7) + ( (r_C & 7) << 3 );
r_F |= ( ioblock_2_table[(r_B)] ^ ioblock_dec1_table[(r_opl)] );
r_HL--;
AddCycles( 4+4+4+4); break;
case INDR : r_meml = Z80InPort((r_BC)); r_memh=0;
r_F = ( r_F & FLAG_C ) | ( (r_B)&0x0f ? 0 : FLAG_H ) | FLAG_N; \
(r_B)--;
r_F |= ( (r_B)==0x7f ? FLAG_V : 0 ) | sz53_table[(r_B)];
r_F &= 0xE8;
Z80WriteMem( r_HL, r_meml, regs );
r_F |= ( (r_meml & 0x80 ) >> 6);
r_opl = r_C; r_oph = 0;
r_opl--;
r_op += r_mem;
r_oph += (r_oph << 4);
r_F |= r_oph;
r_opl = (r_meml & 7) + ( (r_C & 7) << 3 );
r_F |= ( ioblock_2_table[(r_B)] ^ ioblock_dec1_table[(r_opl)] );
r_HL--;
if( r_B ) { r_PC-=2; AddCycles(5); }
AddCycles( 4+4+4+4); break;
case INI : r_meml = Z80InPort((r_BC)); r_memh=0;
r_F = ( r_F & FLAG_C ) | ( (r_B)&0x0f ? 0 : FLAG_H ) | FLAG_N; \
(r_B)--;
r_F |= ( (r_B)==0x7f ? FLAG_V : 0 ) | sz53_table[(r_B)];
r_F &= 0xE8;
Z80WriteMem( r_HL, r_meml, regs );
r_F |= ( (r_meml & 0x80 ) >> 6);
r_opl = r_C; r_oph = 0;
r_opl++;
r_op += r_mem;
r_oph += (r_oph << 4);
r_F |= r_oph;
r_opl = (r_meml & 7) + ( (r_C & 7) << 3 );
r_F |= ( ioblock_2_table[(r_B)] ^ ioblock_inc1_table[(r_opl)] );
r_HL++;
AddCycles( 4+4+4+4); break;
case INIR : r_meml = Z80InPort((r_BC)); r_memh=0;
r_F = ( r_F & FLAG_C ) | ( (r_B)&0x0f ? 0 : FLAG_H ) | FLAG_N; \
(r_B)--;
r_F |= ( (r_B)==0x7f ? FLAG_V : 0 ) | sz53_table[(r_B)];
r_F &= 0xE8;
Z80WriteMem( r_HL, r_meml, regs );
r_F |= ( (r_meml & 0x80 ) >> 6);
r_opl = r_C; r_oph = 0;
r_opl++;
r_op += r_mem;
r_oph += (r_oph << 4);
r_F |= r_oph;
r_opl = (r_meml & 7) + ( (r_C & 7) << 3 );
r_F |= ( ioblock_2_table[(r_B)] ^ ioblock_inc1_table[(r_opl)] );
r_HL++;
if( r_B ) { r_PC-=2; AddCycles(5); }
AddCycles( 4+4+4+4); break;
case OUTI : r_meml = Z80ReadMem(r_HL); r_memh = 0;
r_F = ( r_F & FLAG_C ) | ( (r_B)&0x0f ? 0 : FLAG_H ) | FLAG_N; \
(r_B)--;
r_F |= ( (r_B)==0x7f ? FLAG_V : 0 ) | sz53_table[(r_B)];
r_F &= 0xE8;
Z80OutPort( regs, r_BC, r_meml);
r_F |= ((r_meml & 0x80 ) >> 6);
r_opl = r_C; r_oph=0;
r_opl++;
r_op += r_mem;
r_oph += (r_oph<<4);
r_F |= r_oph;
r_opl = (r_meml & 7) + ( (r_C & 7) << 3 );
r_F |= ( ioblock_2_table[(r_B)] ^ ioblock_inc1_table[(r_opl)] );
r_HL++;
AddCycles( 4+4+4+4); break;
case OTIR : r_meml = Z80ReadMem(r_HL); r_memh = 0;
r_F = ( r_F & FLAG_C ) | ( (r_B)&0x0f ? 0 : FLAG_H ) | FLAG_N; \
(r_B)--;
r_F |= ( (r_B)==0x7f ? FLAG_V : 0 ) | sz53_table[(r_B)];
r_F &= 0xE8;
Z80OutPort( regs, r_BC, r_meml);
r_F |= ((r_meml & 0x80 ) >> 6);
r_opl = r_C; r_oph=0;
r_opl++;
r_op += r_mem;
r_oph += (r_oph<<4);
r_F |= r_oph;
r_opl = (r_meml & 7) + ( (r_C & 7) << 3 );
r_F |= ( ioblock_2_table[(r_B)] ^ ioblock_inc1_table[(r_opl)] );
r_HL++;
if( r_B ) { r_PC-=2; AddCycles(5); }
AddCycles( 4+4+4+4); break;
case OUTD : r_meml = Z80ReadMem(r_HL); r_memh = 0;
r_F = ( r_F & FLAG_C ) | ( (r_B)&0x0f ? 0 : FLAG_H ) | FLAG_N; \
(r_B)--;
r_F |= ( (r_B)==0x7f ? FLAG_V : 0 ) | sz53_table[(r_B)];
r_F &= 0xE8;
Z80OutPort( regs, r_BC, r_meml);
r_F |= ((r_meml & 0x80 ) >> 6);
r_opl = r_C; r_oph=0;
r_opl--;
r_op += r_mem;
r_oph += (r_oph<<4);
r_F |= r_oph;
r_opl = (r_meml & 7) + ( (r_C & 7) << 3 );
r_F |= ( ioblock_2_table[(r_B)] ^ ioblock_dec1_table[(r_opl)] );
r_HL--;
AddCycles( 4+4+4+4); break;
case OTDR : r_meml = Z80ReadMem(r_HL); r_memh = 0;
r_F = ( r_F & FLAG_C ) | ( (r_B)&0x0f ? 0 : FLAG_H ) | FLAG_N; \
(r_B)--;
r_F |= ( (r_B)==0x7f ? FLAG_V : 0 ) | sz53_table[(r_B)];
r_F &= 0xE8;
Z80OutPort( regs, r_BC, r_meml);
r_F |= ((r_meml & 0x80 ) >> 6);
r_opl = r_C; r_oph=0;
r_opl--;
r_op += r_mem;
r_oph += (r_oph<<4);
r_F |= r_oph;
r_opl = (r_meml & 7) + ( (r_C & 7) << 3 );
r_F |= ( ioblock_2_table[(r_B)] ^ ioblock_dec1_table[(r_opl)] );
r_HL--;
if( r_B ) { r_PC-=2; AddCycles(5); }
AddCycles( 4+4+4+4); break;
// End of Metalbrain's contribution
case PREFIX_ED: AddCycles( 4 ); /* ED ED xx = 12 cycles min = 4+8 */
r_PC-- ;
break;
default:
// exit(1);
AddCycles( 4+4 ); /* Just a NOP */
///!!! if(regs->DecodingErrors)
///!!! printf( "z80 core: Unknown instruction: ED %02Xh at PC=%04Xh.\n",
///!!! Z80ReadMem(r_PC-1),r_PC-2 );
break;
}

View File

@ -0,0 +1,901 @@
/*====================================================================/*
opcodes.c -> This file executes the single-byte Z80 opcodes.
The CPU fetchs the byte pointed by the PC register (Program Counter)
into de IR (Instruction Register) and decodes it. The value of this
fetched byte (opcode) determines what operation the CPU must do.
On Z80 (which uses 8 bit for the IW register) this means that we
can have 256 (2^8) different opcodes. The z80 uses a simple trick
called PREFIXES to obtain more opcodes by using more than one byte
in the decoding (see opcodes_cb.c to know how it does it).
This file executes the whole list of single-byte opcodes.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Copyright (c) 2000 Santiago Romero Iglesias.
Email: sromero@escomposlinux.org
=====================================================================*/
/* About the AddCycles(4) -> Remember that reading from memory
takes 3 cycles plus 1 of the decoding.
Add 3 cycles for each operand fetch, and
3 more for each memory write/read. */
case NOP : AddCycles( 4 ); break;
case LD_BC_NN : LD_rr_nn(r_BC); AddCycles( 4+3+3 ); break;
case LD_xBC_A : STORE_r(r_BC, r_A); AddCycles( 4+3 ); break;
case INC_BC : r_BC++; AddCycles( 4+2 ); break;
case INC_B : INC(r_B); AddCycles( 4 ); break;
case DEC_B : DEC(r_B); AddCycles( 4 ); break;
case LD_B_N : LD_r_n(r_B);
AddCycles( 4+3 );
break;
case EX_AF_AF : EX_WORD(r_AF, r_AFs);
AddCycles( 4 );
break;
case LD_A_xBC : LOAD_r(r_A, r_BC);
AddCycles( 4+3 );
break;
case DEC_BC : r_BC--;
AddCycles( 4+2 );
break;
case INC_C : INC(r_C);
AddCycles( 4 );
break;
case DEC_C : DEC(r_C);
AddCycles( 4 );
break;
case LD_C_N : LD_r_n(r_C);
AddCycles( 4+3 );
break;
case LD_DE_NN : LD_rr_nn(r_DE);
AddCycles( 4+3+3 );
break;
case LD_xDE_A : STORE_r(r_DE, r_A);
AddCycles( 4+3 );
break;
case INC_DE : r_DE++;
AddCycles( 4+2 );
break;
case INC_D : INC(r_D);
AddCycles( 4 );
break;
case DEC_D : DEC(r_D);
AddCycles( 4 );
break;
case LD_D_N : LD_r_n(r_D);
AddCycles( 4+3 );
break;
case ADD_HL_BC : ADD_WORD(r_HL, r_BC); AddCycles( 4+3+3+1 ); break;
case ADD_HL_DE : ADD_WORD(r_HL, r_DE); AddCycles( 4+3+3+1 ); break;
case ADD_HL_HL : ADD_WORD(r_HL, r_HL); AddCycles( 4+3+3+1 ); break;
case ADD_HL_SP : ADD_WORD(r_HL, r_SP); AddCycles( 4+3+3+1 ); break;
case LD_A_xDE : LOAD_r(r_A, r_DE);
AddCycles( 4+3 );
break;
case DEC_DE : r_DE--;
AddCycles( 4+2 );
break;
case INC_E : INC(r_E);
AddCycles( 4 );
break;
case DEC_E : DEC(r_E);
AddCycles( 4 );
break;
case LD_E_N : LD_r_n(r_E);
AddCycles( 4+3 );
break;
case LD_HL_NN : LD_rr_nn(r_HL);
AddCycles( 4+3+3 );
break;
case LD_xNN_HL : STORE_nn_rr(r_HL);
AddCycles( 4+3+3+3+3 );
break;
case INC_HL : r_HL++;
AddCycles( 4+2 );
break;
case INC_H : INC(r_H);
AddCycles( 4 );
break;
case DEC_H : DEC(r_H);
AddCycles( 4 );
break;
case LD_H_N : LD_r_n(r_H);
AddCycles( 4+3 );
break;
case LD_HL_xNN : LOAD_rr_nn(r_HL);
AddCycles( 4+3+3+3+3 );
break;
case DEC_HL : r_HL--;
AddCycles( 4+2 );
break;
case INC_L : INC(r_L);
AddCycles( 4 );
break;
case DEC_L : DEC(r_L);
AddCycles( 4 );
break;
case LD_L_N : LD_r_n(r_L);
AddCycles( 4+3 );
break;
case LD_SP_NN : LD_rr_nn(r_SP);
AddCycles( 10 );
break;
case LD_xNN_A : STORE_nn_r(r_A);
AddCycles( 13 );
break;
case INC_SP : r_SP++;
AddCycles( 6 );
break;
case LD_xHL_N : r_meml = Z80ReadMem(r_PC); r_PC++;
STORE_r( r_HL, r_meml );
AddCycles( 10 );
break;
case LD_A_xNN : LOAD_r_nn( r_A );
AddCycles( 13 );
break;
case DEC_SP : r_SP--;
AddCycles( 6 );
break;
case INC_A : INC(r_A);
AddCycles( 4 );
break;
case DEC_A : DEC(r_A);
AddCycles( 4 );
break;
case LD_A_N : LD_r_n(r_A);
AddCycles( 4+3 );
break;
case LD_B_B : LD_r_r( r_B, r_B );
AddCycles( 4 );
break;
case LD_B_C : LD_r_r( r_B, r_C );
AddCycles( 4 );
break;
case LD_B_D : LD_r_r( r_B, r_D );
AddCycles( 4 );
break;
case LD_B_E : LD_r_r( r_B, r_E );
AddCycles( 4 );
break;
case LD_B_H : LD_r_r( r_B, r_H );
AddCycles( 4 );
break;
case LD_B_L : LD_r_r( r_B, r_L );
AddCycles( 4 );
break;
case LD_B_xHL : LOAD_r(r_B, r_HL);
AddCycles( 4+3 );
break;
case LD_B_A : LD_r_r( r_B, r_A );
AddCycles( 4 );
break;
case LD_C_B : LD_r_r( r_C, r_B );
AddCycles( 4 );
break;
case LD_C_C : LD_r_r( r_C, r_C );
AddCycles( 4 );
break;
case LD_C_D : LD_r_r( r_C, r_D );
AddCycles( 4 );
break;
case LD_C_E : LD_r_r( r_C, r_E );
AddCycles( 4 );
break;
case LD_C_H : LD_r_r( r_C, r_H );
AddCycles( 4 );
break;
case LD_C_L : LD_r_r( r_C, r_L );
AddCycles( 4 );
break;
case LD_C_xHL : LOAD_r(r_C, r_HL);
AddCycles( 4+3 );
break;
case LD_C_A : LD_r_r( r_C, r_A );
AddCycles( 4 );
break;
case LD_D_B : LD_r_r( r_D, r_B );
AddCycles( 4 );
break;
case LD_D_C : LD_r_r( r_D, r_C );
AddCycles( 4 );
break;
case LD_D_D : LD_r_r( r_D, r_D );
AddCycles( 4 );
break;
case LD_D_E : LD_r_r( r_D, r_E );
AddCycles( 4 );
break;
case LD_D_H : LD_r_r( r_D, r_H );
AddCycles( 4 );
break;
case LD_D_L : LD_r_r( r_D, r_L );
AddCycles( 4 );
break;
case LD_D_xHL : LOAD_r(r_D, r_HL);
AddCycles( 4+3 );
break;
case LD_D_A : LD_r_r( r_D, r_A );
AddCycles( 4 );
break;
case LD_E_B : LD_r_r( r_E, r_B );
AddCycles( 4 );
break;
case LD_E_C : LD_r_r( r_E, r_C );
AddCycles( 4 );
break;
case LD_E_D : LD_r_r( r_E, r_D );
AddCycles( 4 );
break;
case LD_E_E : LD_r_r( r_E, r_E );
AddCycles( 4 );
break;
case LD_E_H : LD_r_r( r_E, r_H );
AddCycles( 4 );
break;
case LD_E_L : LD_r_r( r_E, r_L );
AddCycles( 4 );
break;
case LD_E_xHL : LOAD_r(r_E, r_HL);
AddCycles( 4+3 );
break;
case LD_E_A : LD_r_r( r_E, r_A );
AddCycles( 4 );
break;
case LD_H_B : LD_r_r( r_H, r_B );
AddCycles( 4 );
break;
case LD_H_C : LD_r_r( r_H, r_C );
AddCycles( 4 );
break;
case LD_H_D : LD_r_r( r_H, r_D );
AddCycles( 4 );
break;
case LD_H_E : LD_r_r( r_H, r_E );
AddCycles( 4 );
break;
case LD_H_H : LD_r_r( r_H, r_H );
AddCycles( 4 );
break;
case LD_H_L : LD_r_r( r_H, r_L );
AddCycles( 4 );
break;
case LD_H_xHL : LOAD_r(r_H, r_HL);
AddCycles( 4+3 );
break;
case LD_H_A : LD_r_r( r_H, r_A );
AddCycles( 4 );
break;
case LD_L_B : LD_r_r( r_L, r_B );
AddCycles( 4 );
break;
case LD_L_C : LD_r_r( r_L, r_C );
AddCycles( 4 );
break;
case LD_L_D : LD_r_r( r_L, r_D );
AddCycles( 4 );
break;
case LD_L_E : LD_r_r( r_L, r_E );
AddCycles( 4 );
break;
case LD_L_H : LD_r_r( r_L, r_H );
AddCycles( 4 );
break;
case LD_L_L : LD_r_r( r_L, r_L );
AddCycles( 4 );
break;
case LD_L_xHL : LOAD_r(r_L, r_HL);
AddCycles( 7 );
break;
case LD_L_A : LD_r_r( r_L, r_A );
AddCycles( 4 );
break;
case LD_xHL_B : STORE_r( r_HL, r_B );
AddCycles( 4+3 );
break;
case LD_xHL_C : STORE_r( r_HL, r_C );
AddCycles( 4+3 );
break;
case LD_xHL_D : STORE_r( r_HL, r_D );
AddCycles( 4+3 );
break;
case LD_xHL_E : STORE_r( r_HL, r_E );
AddCycles( 4+3 );
break;
case LD_xHL_H : STORE_r( r_HL, r_H );
AddCycles( 4+3 );
break;
case LD_xHL_L : STORE_r( r_HL, r_L );
AddCycles( 4+3 );
break;
case LD_xHL_A : STORE_r(r_HL, r_A );
AddCycles( 4+3 );
break;
case LD_A_B : LD_r_r( r_A, r_B );
AddCycles( 4 );
break;
case LD_A_C : LD_r_r( r_A, r_C );
AddCycles( 4 );
break;
case LD_A_D : LD_r_r( r_A, r_D );
AddCycles( 4 );
break;
case LD_A_E : LD_r_r( r_A, r_E );
AddCycles( 4 );
break;
case LD_A_H : LD_r_r( r_A, r_H );
AddCycles( 4 );
break;
case LD_A_L : LD_r_r( r_A, r_L );
AddCycles( 4 );
break;
case LD_A_xHL : LOAD_r( r_A, r_HL);
AddCycles( 4+3 );
break;
case LD_A_A : LD_r_r( r_A, r_A );
AddCycles( 4 );
break;
case LD_SP_HL : LD_r_r( r_SP, r_HL );
AddCycles( 6 ); break;
case ADD_B : ADD(r_B); AddCycles( 4 ); break;
case ADD_C : ADD(r_C); AddCycles( 4 ); break;
case ADD_D : ADD(r_D); AddCycles( 4 ); break;
case ADD_E : ADD(r_E); AddCycles( 4 ); break;
case ADD_H : ADD(r_H); AddCycles( 4 ); break;
case ADD_L : ADD(r_L); AddCycles( 4 ); break;
case ADD_xHL : r_meml = Z80ReadMem(r_HL);
ADD(r_meml);
AddCycles( 4+3 );
break;
case ADD_A : ADD(r_A); AddCycles( 4 ); break;
case ADC_B : ADC(r_B); AddCycles( 4 ); break;
case ADC_C : ADC(r_C); AddCycles( 4 ); break;
case ADC_D : ADC(r_D); AddCycles( 4 ); break;
case ADC_E : ADC(r_E); AddCycles( 4 ); break;
case ADC_H : ADC(r_H); AddCycles( 4 ); break;
case ADC_L : ADC(r_L); AddCycles( 4 ); break;
case ADC_xHL : r_meml = Z80ReadMem(r_HL);
ADC(r_meml);
AddCycles( 4+3 );
break;
case ADC_A : ADC(r_A); AddCycles( 4 ); break;
case ADC_N : r_meml = Z80ReadMem(r_PC); r_PC++;
ADC(r_meml);
AddCycles( 4+3 );
break;
case SUB_A : SUB(r_A); AddCycles( 4 ); break;
case SUB_B : SUB(r_B); AddCycles( 4 ); break;
case SUB_C : SUB(r_C); AddCycles( 4 ); break;
case SUB_D : SUB(r_D); AddCycles( 4 ); break;
case SUB_E : SUB(r_E); AddCycles( 4 ); break;
case SUB_H : SUB(r_H); AddCycles( 4 ); break;
case SUB_L : SUB(r_L); AddCycles( 4 ); break;
case SUB_xHL : r_meml = Z80ReadMem(r_HL);
SUB(r_meml);
AddCycles( 4+3 );
break;
case SUB_N : r_meml = Z80ReadMem(r_PC); r_PC++;
SUB(r_meml);
AddCycles( 4+3 );
break;
case SBC_A : SBC(r_A); AddCycles( 4 ); break;
case SBC_B : SBC(r_B); AddCycles( 4 ); break;
case SBC_C : SBC(r_C); AddCycles( 4 ); break;
case SBC_D : SBC(r_D); AddCycles( 4 ); break;
case SBC_E : SBC(r_E); AddCycles( 4 ); break;
case SBC_H : SBC(r_H); AddCycles( 4 ); break;
case SBC_L : SBC(r_L); AddCycles( 4 ); break;
case SBC_xHL : r_meml = Z80ReadMem(r_HL);
SBC(r_meml);
AddCycles( 4+3 );
break;
case SBC_N : r_meml = Z80ReadMem(r_PC); r_PC++;
SBC(r_meml);
AddCycles( 4 );
break;
case AND_B : AND( r_B ); AddCycles( 4 ); break;
case AND_C : AND( r_C ); AddCycles( 4 ); break;
case AND_D : AND( r_D ); AddCycles( 4 ); break;
case AND_E : AND( r_E ); AddCycles( 4 ); break;
case AND_H : AND( r_H ); AddCycles( 4 ); break;
case AND_L : AND( r_L ); AddCycles( 4 ); break;
case AND_xHL : AND_mem( r_HL ); AddCycles( 4+3 ); break;
case AND_A : AND( r_A ); AddCycles( 4 ); break;
case XOR_B : XOR( r_B ); AddCycles( 4 ); break;
case XOR_C : XOR( r_C ); AddCycles( 4 ); break;
case XOR_D : XOR( r_D ); AddCycles( 4 ); break;
case XOR_E : XOR( r_E ); AddCycles( 4 ); break;
case XOR_H : XOR( r_H ); AddCycles( 4 ); break;
case XOR_L : XOR( r_L ); AddCycles( 4 ); break;
case XOR_xHL : XOR_mem( r_HL ); AddCycles( 4+3 ); break;
case XOR_A : XOR( r_A ); AddCycles( 4 ); break;
case OR_B : OR( r_B ); AddCycles( 4 ); break;
case OR_C : OR( r_C ); AddCycles( 4 ); break;
case OR_D : OR( r_D ); AddCycles( 4 ); break;
case OR_E : OR( r_E ); AddCycles( 4 ); break;
case OR_H : OR( r_H ); AddCycles( 4 ); break;
case OR_L : OR( r_L ); AddCycles( 4 ); break;
case OR_xHL : OR_mem( r_HL ); AddCycles( 4+3 ); break;
case OR_A : OR( r_A ); AddCycles( 4 ); break;
case CP_A : CP(r_A); AddCycles( 4 ); break;
case CP_B : CP(r_B); AddCycles( 4 ); break;
case CP_C : CP(r_C); AddCycles( 4 ); break;
case CP_D : CP(r_D); AddCycles( 4 ); break;
case CP_E : CP(r_E); AddCycles( 4 ); break;
case CP_H : CP(r_H); AddCycles( 4 ); break;
case CP_L : CP(r_L); AddCycles( 4 ); break;
case CP_xHL : r_meml = Z80ReadMem( r_HL );
CP(r_meml); AddCycles( 4+3 ); break;
case CP_N : r_meml = Z80ReadMem(r_PC); r_PC++;
CP(r_meml);
AddCycles( 4+3);
break;
case RET_Z : if( TEST_FLAG(Z_FLAG) )
{ RET_nn(); AddCycles( 4+1+3+3 ); }
else { AddCycles( 4+1 ); }
break;
case RET_C : if( TEST_FLAG(C_FLAG) )
{ RET_nn(); AddCycles( 4+1+3+3 ); }
else { AddCycles( 4+1 ); }
break;
case RET_M : if( TEST_FLAG(S_FLAG) )
{ RET_nn(); AddCycles( 4+1+3+3 ); }
else { AddCycles( 4+1 ); }
break;
case RET_PE : if( TEST_FLAG(P_FLAG) )
{ RET_nn(); AddCycles( 4+1+3+3 ); }
else { AddCycles( 4+1 ); }
break;
case RET_PO : if( TEST_FLAG(P_FLAG) )
{ AddCycles( 4+1 ); }
else { RET_nn(); AddCycles( 4+1+3+3 ); }
break;
case RET_P : if( TEST_FLAG(S_FLAG) )
{ AddCycles( 4+1 ); }
else { RET_nn(); AddCycles( 4+1+3+3 ); }
break;
case RET : RET_nn();
AddCycles( 4+3+3 );
break;
case RET_NZ : if( TEST_FLAG(Z_FLAG) )
{ AddCycles( 4+1 ); }
else { RET_nn(); AddCycles( 4+1+3+3 ); }
break;
case RET_NC : if( TEST_FLAG(C_FLAG) )
{ AddCycles( 4+1 ); }
else { RET_nn(); AddCycles( 4+1+3+3 ); }
break;
case ADD_N : r_meml = Z80ReadMem(r_PC); r_PC++;
ADD(r_meml);
AddCycles( 4+3 );
break;
case JR : JR_n();
AddCycles( 4+3+3+2 );
break;
case JR_NZ : if( TEST_FLAG(Z_FLAG) )
{ r_PC++; AddCycles( 4+3 ); }
else
{ JR_n(); AddCycles( 4+8 ); }
break;
case JR_Z : if( TEST_FLAG(Z_FLAG) )
{ JR_n(); AddCycles( 4+8 ); }
else
{ r_PC++; AddCycles( 4+3 ); }
break;
case JR_NC : if( TEST_FLAG(C_FLAG) )
{ r_PC++; AddCycles( 4+3 ); }
else
{ JR_n(); AddCycles( 4+8 ); }
break;
case JR_C : if( TEST_FLAG(C_FLAG) )
{ JR_n(); AddCycles( 4+8 ); }
else
{ r_PC++; AddCycles( 4+3 ); }
break;
case JP_NZ : if( TEST_FLAG(Z_FLAG) ) { r_PC += 2; }
else { JP_nn(); }
AddCycles( 4+3+3 );
break;
case JP : JP_nn();
AddCycles( 4+3+3 );
break;
case JP_Z : if( TEST_FLAG(Z_FLAG) ) { JP_nn(); }
else { r_PC += 2; }
AddCycles( 4+3+3 );
break;
case JP_NC : if( TEST_FLAG(C_FLAG) ) { r_PC += 2; }
else { JP_nn(); }
AddCycles( 4+3+3 );
break;
case JP_C : if( TEST_FLAG(C_FLAG) ) { JP_nn(); }
else { r_PC += 2; }
AddCycles( 4+3+3 );
break;
case JP_PO : if( TEST_FLAG(P_FLAG) ) { r_PC += 2; }
else { JP_nn(); }
AddCycles( 4+3+3 );
break;
case JP_PE : if( TEST_FLAG(P_FLAG) ) { JP_nn(); }
else { r_PC += 2; }
AddCycles( 4+3+3 );
break;
case JP_P : if( TEST_FLAG(S_FLAG) ) { r_PC += 2; }
else { JP_nn(); }
AddCycles( 4+3+3 );
break;
case JP_M : if( TEST_FLAG(S_FLAG) ) { JP_nn(); }
else { r_PC += 2; }
AddCycles( 4+3+3 );
break;
case JP_xHL : r_PC = r_HL; AddCycles( 4 ); break;
case CPL : r_A ^= 0xFF;
r_F = ( r_F & (FLAG_C|FLAG_P|FLAG_Z|FLAG_S)) |
( r_A & (FLAG_3|FLAG_5))|(FLAG_N|FLAG_H);
AddCycles( 4 ); break;
case INC_xHL : r_meml = Z80ReadMem( r_HL );
INC(r_meml);
Z80WriteMem( r_HL, r_meml, regs );
AddCycles( 4+3+3+1 ); break;
case DEC_xHL : r_meml = Z80ReadMem( r_HL );
DEC(r_meml);
Z80WriteMem( r_HL, r_meml, regs );
AddCycles( 4+3+3+1 ); break;
case SCF : r_F = r_F | FLAG_C;
r_F &= FLAG_Z | FLAG_S | FLAG_P;
if(r_F & FLAG_H) r_F ^= FLAG_H;
r_F |= FLAG_C;
AddCycles( 4 ); break;
case CCF : r_F = (r_F & (FLAG_P|FLAG_Z|FLAG_S) ) |
((r_F & FLAG_C) ? FLAG_H : FLAG_C) |
( r_A & (FLAG_3 | FLAG_5) );
AddCycles( 4 ); break;
case HALT : regs->halted = 1;
AddCycles(4);
break;
case POP_BC : POP(BC); AddCycles( 10 ); break;
case PUSH_BC : PUSH(BC); AddCycles( 11 ); break;
case POP_HL : POP(HL); AddCycles( 10 ); break;
case PUSH_HL : PUSH(HL); AddCycles( 11 ); break;
case POP_AF : POP(AF); AddCycles( 10 ); break;
case PUSH_AF : PUSH(AF); AddCycles( 11 ); break;
case POP_DE : POP(DE); AddCycles( 10 ); break;
case PUSH_DE : PUSH(DE); AddCycles( 11 ); break;
case RLCA : r_A = (r_A << 1) | (r_A >> 7);
r_F = ( r_F & (FLAG_P|FLAG_Z|FLAG_S)) |
( r_A & (FLAG_C|FLAG_3|FLAG_5) );
AddCycles( 4 ); break;
case RRCA : r_F = ( r_F & (FLAG_P|FLAG_Z|FLAG_S)) |
( r_A & FLAG_C );
r_A = ( r_A >> 1) | ( r_A << 7 );
r_F |= ( r_A & ( FLAG_3 | FLAG_5 ) );
AddCycles( 4 ); break;
case DJNZ : r_B--;
if( r_B ) { JR_n(); AddCycles(13); }
else { r_PC++ ; AddCycles(8); }
break;
case RLA : r_meml = r_A;
r_A = ( r_A << 1 ) | ( r_F & FLAG_C );
r_F = ( r_F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |
(r_A & ( FLAG_3 | FLAG_5 ) ) | ( r_meml >> 7);
AddCycles( 4 ); break;
case RRA : r_meml = r_A;
r_A = ( r_A >> 1 ) | ( r_F << 7 );
r_F = ( r_F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |
( r_A & ( FLAG_3 | FLAG_5 ) ) | ( r_meml & FLAG_C );
AddCycles( 4 ); break;
case DAA : r_meml = 0;
r_memh = ( r_F & FLAG_C );
if( ( r_F & FLAG_H ) || ( (r_A & 0x0f)>9 ) ) r_meml=6;
if( r_memh || (r_A > 0x9f ) ) r_meml |= 0x60;
if( r_A > 0x99 ) r_memh=1;
if ( r_F & FLAG_N ) { SUB(r_meml); }
else
{
if( (r_A>0x90) && ( (r_A & 0x0f)>9) ) r_meml|=0x60;
ADD(r_meml);
}
r_F = ( r_F & ~( FLAG_C | FLAG_P) ) | r_memh |
parity_table[r_A];
AddCycles( 4 ); break;
case OUT_N_A : Z80OutPort( regs, Z80ReadMem( r_PC ), r_A ); r_PC++;
AddCycles( 11 ); break;
case IN_A_N : r_A = Z80InPort( Z80ReadMem( r_PC ) + (r_A << 8));
r_PC++; AddCycles( 11 ); break;
case EX_HL_xSP : r_meml = Z80ReadMem(r_SP);
r_memh = Z80ReadMem(r_SP+1);
Z80WriteMem(r_SP, r_L, regs);
Z80WriteMem(r_SP+1, r_H, regs);
r_L = r_meml;
r_H = r_memh;
AddCycles( 19 ); break;
case EXX : EX_WORD(r_BC, r_BCs); EX_WORD(r_DE, r_DEs);
EX_WORD(r_HL, r_HLs);
AddCycles( 4 ); break;
case EX_DE_HL : EX_WORD( r_DE, r_HL );
AddCycles( 4 );
break;
case AND_N : AND_mem( r_PC );
r_PC++;
AddCycles( 4+3 );
break;
case XOR_N : XOR_mem( r_PC );
r_PC++;
AddCycles( 4+3 );
break;
case OR_N : OR_mem( r_PC );
r_PC++;
AddCycles( 4+3 );
break;
case DI : r_IFF1 = r_IFF2 = 0;
AddCycles( 4 );
break;
case CALL :
CALL_nn();
AddCycles( 4+3+3+3+3+1 );
break;
case CALL_NZ : if( TEST_FLAG(Z_FLAG) )
{ r_PC += 2; AddCycles( 4+3+3 ); }
else
{
CALL_nn();
AddCycles( 4+3+3+3+3+1 );
}
break;
case CALL_NC : if( TEST_FLAG(C_FLAG) )
{ r_PC += 2; AddCycles( 4+3+3 ); }
else
{ CALL_nn();
AddCycles( 4+3+3+3+3+1 );
}
break;
case CALL_PO : if( TEST_FLAG(P_FLAG) )
{ r_PC += 2; AddCycles( 4+3+3 ); }
else
{ CALL_nn();
AddCycles( 4+3+3+ 3+3+1 );
}
break;
case CALL_P : if( TEST_FLAG(S_FLAG) )
{ r_PC += 2; AddCycles( 4+3+3 ); }
else
{ CALL_nn();
AddCycles( 4+3+3+3+3+1 );
}
break;
case CALL_Z : if( TEST_FLAG(Z_FLAG) )
{ CALL_nn();
AddCycles( 4+3+3+3+3+1 );
}
else
{ r_PC += 2; AddCycles( 4+3+3 ); }
break;
case CALL_C : if( TEST_FLAG(C_FLAG) )
{ CALL_nn();
AddCycles( 4+3+3+ 3+3+4 );
}
else
{ r_PC += 2; AddCycles( 4+3+3 ); }
break;
case CALL_PE : if( TEST_FLAG(P_FLAG) )
{ CALL_nn();
AddCycles( 4+3+3+3+3+1 );
}
else
{ r_PC += 2; AddCycles( 4+3+3 ); }
break;
case CALL_M : if( TEST_FLAG(S_FLAG) )
{ CALL_nn();
AddCycles( 4+3+3+3+3+1 );
}
else
{ r_PC += 2; AddCycles( 4+3+3 ); }
break;
case EI : r_IFF1 = r_IFF2 = 1;
/*
Why Marat Fayzullin does this? ->
regs->IFF2 |= 0x01;
if( regs->IRequest != INT_NOINT )
{
regs->IBackup = regs->ICount;
regs->ICount = 0x1;
r_IFF |= 0x20;
}*/
AddCycles( 4 );
break;
case RST_00 : RST(0x00); AddCycles( 11 ); break;
case RST_08 : RST(0x08); AddCycles( 11 ); break;
case RST_10 : RST(0x10); AddCycles( 11 ); break;
case RST_18 : RST(0x18); AddCycles( 11 ); break;
case RST_20 : RST(0x20); AddCycles( 11 ); break;
case RST_28 : RST(0x28); AddCycles( 11 ); break;
case RST_30 : RST(0x30); AddCycles( 11 ); break;
case RST_38 : RST(0x38); AddCycles( 11 ); break;
default:
// exit(1);
///!!! if( regs->DecodingErrors )
///!!! printf("z80 core: Unknown instruction: %02Xh at PC=%04Xh.\n",
///!!! Z80ReadMem(r_PC-1), r_PC-1 );
break;

View File

@ -0,0 +1,196 @@
/*====================================================================/*
opcodes_ddfdcb.c -> This file executes the DD/FD CB PREFIX opcodes.
Those are the double prefix opcodes. We found the DD prefix, which
means that we must treat HL as IX, and then we found the CB prefix,
so we must apply this rule to the CB PREFIX list of opcodes. A
signed byte displacement is also added, and it's located BEFORE
the DD CB opcode:
ie: CB 2E = SRA (HL)
DD CB xx 2E = SRA (IX+xx)
(or...)
Those are the double prefix opcodes. We found the FD prefix, which
means that we must treat HL as IY, and then we found the CB prefix,
so we must apply this rule to the CB PREFIX list of opcodes. A
signed byte displacement is also added, and it's located BEFORE
the FD CB opcode:
ie: CB 2E = SRA (HL)
FD CB xx 2E = SRA (IY+xx)
Call here using something like #define REGISTER regs->IX
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Copyright (c) 2000 Santiago Romero Iglesias.
Email: sromero@escomposlinux.org
=====================================================================*/
/* 15 clock cycles minimum = FD/DD CB xx opcode = 4 + 4 + 3 + 4 */
tmpreg.W = REGISTER.W + (offset) Z80ReadMem( r_PC );
r_PC++;
r_meml = Z80ReadMem( tmpreg.W );
opcode = Z80ReadMem( r_PC );
r_PC++;
switch(opcode)
{
case RLC_xIXY : RLC(r_meml); Z80WriteMem(tmpreg.W, r_meml, regs);
AddCycles( 23 ); break;
case RRC_xIXY : RRC(r_meml); Z80WriteMem(tmpreg.W, r_meml, regs);
AddCycles( 23 ); break;
case RL_xIXY : RL(r_meml); Z80WriteMem(tmpreg.W, r_meml, regs);
AddCycles( 23 ); break;
case RR_xIXY : RR(r_meml); Z80WriteMem(tmpreg.W, r_meml, regs);
AddCycles( 23 ); break;
case SLA_xIXY : SLA(r_meml); Z80WriteMem(tmpreg.W, r_meml, regs);
AddCycles( 23 ); break;
case SRA_xIXY : SRA(r_meml); Z80WriteMem(tmpreg.W, r_meml, regs);
AddCycles( 23 ); break;
case SLL_xIXY : SLL(r_meml); Z80WriteMem(tmpreg.W, r_meml, regs);
AddCycles( 23 ); break;
case SRL_xIXY : SRL(r_meml); Z80WriteMem(tmpreg.W, r_meml, regs);
AddCycles( 23 ); break;
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x47:
case BIT_0_xIXY : BIT_BIT(0, r_meml); AddCycles( 15+5 ); break;
case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
case 0x4c:
case 0x4d:
case 0x4f:
case BIT_1_xIXY :
BIT_BIT(1, r_meml); AddCycles( 15+5 ); break;
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x57:
case BIT_2_xIXY : BIT_BIT(2, r_meml); AddCycles( 15+5 ); break;
case 0x58:
case 0x59:
case 0x5a:
case 0x5b:
case 0x5c:
case 0x5d:
case 0x5f:
case BIT_3_xIXY : BIT_BIT(3, r_meml); AddCycles( 15+5 ); break;
case 0x60:
case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x67:
case BIT_4_xIXY : BIT_BIT(4, r_meml); AddCycles( 15+5 ); break;
case 0x68:
case 0x69:
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6f:
case BIT_5_xIXY : BIT_BIT(5, r_meml); AddCycles( 15+5 ); break;
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x77:
case BIT_6_xIXY : BIT_BIT(6, r_meml); AddCycles( 15+5 ); break;
case 0x78:
case 0x79:
case 0x7a:
case 0x7b:
case 0x7c:
case 0x7d:
case 0x7f:
case BIT_7_xIXY : BIT_BIT7(r_meml); AddCycles( 15+5 ); break;
case RES_0_xIXY : BIT_RES_mem(0, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case RES_1_xIXY : BIT_RES_mem(1, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case RES_2_xIXY : BIT_RES_mem(2, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case RES_3_xIXY : BIT_RES_mem(3, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case RES_4_xIXY : BIT_RES_mem(4, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case RES_5_xIXY : BIT_RES_mem(5, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case RES_6_xIXY : BIT_RES_mem(6, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case RES_7_xIXY : BIT_RES_mem(7, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case SET_0_xIXY : BIT_SET_mem(0, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case SET_1_xIXY : BIT_SET_mem(1, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case SET_2_xIXY : BIT_SET_mem(2, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case SET_3_xIXY : BIT_SET_mem(3, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case SET_4_xIXY : BIT_SET_mem(4, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case SET_5_xIXY : BIT_SET_mem(5, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case SET_6_xIXY : BIT_SET_mem(6, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
case SET_7_xIXY : BIT_SET_mem(7, tmpreg.W, r_meml );
AddCycles( 15+5+3 ); break;
/*
I must still include the undocumented opcodes such as:
LD B, RLC(REGISTER+dd) and so on ...
*/
default:
AddCycles( 15 );
// exit(1);
///!!! if(regs->DecodingErrors)
///!!! {
///!!! printf("z80 core: Unknown instruction: ");
///!!! if( regs->we_are_on_ddfd == WE_ARE_ON_DD )
///!!! printf("DD");
///!!! else
///!!! printf("FD");
///!!! printf("CB %02Xh %02Xh at PC=%04Xh.\n",
///!!! Z80ReadMem(r_PC-2), Z80ReadMem(r_PC-1), r_PC-4 );
///!!! }
break;
}

View File

@ -0,0 +1,829 @@
/*=====================================================================
tables.h -> Header file containing the defines for Z80 opcodes.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Copyright (c) 2000 Santiago Romero Iglesias.
Email: sromero@escomposlinux.org
======================================================================*/
#ifndef TABLES_H
#define TABLES_H
/*--- One byte opcodes: ----------------------------------------------*/
#define NOP 0
#define LD_BC_NN 1
#define LD_xBC_A 2
#define INC_BC 3
#define INC_B 4
#define DEC_B 5
#define LD_B_N 6
#define RLCA 7
#define EX_AF_AF 8
#define ADD_HL_BC 9
#define LD_A_xBC 10
#define DEC_BC 11
#define INC_C 12
#define DEC_C 13
#define LD_C_N 14
#define RRCA 15
#define DJNZ 16
#define LD_DE_NN 17
#define LD_xDE_A 18
#define INC_DE 19
#define INC_D 20
#define DEC_D 21
#define LD_D_N 22
#define RLA 23
#define JR 24
#define ADD_HL_DE 25
#define LD_A_xDE 26
#define DEC_DE 27
#define INC_E 28
#define DEC_E 29
#define LD_E_N 30
#define RRA 31
#define JR_NZ 32
#define LD_HL_NN 33
#define LD_xNN_HL 34
#define INC_HL 35
#define INC_H 36
#define DEC_H 37
#define LD_H_N 38
#define DAA 39
#define JR_Z 40
#define ADD_HL_HL 41
#define LD_HL_xNN 42
#define DEC_HL 43
#define INC_L 44
#define DEC_L 45
#define LD_L_N 46
#define CPL 47
#define JR_NC 48
#define LD_SP_NN 49
#define LD_xNN_A 50
#define INC_SP 51
#define INC_xHL 52
#define DEC_xHL 53
#define LD_xHL_N 54
#define SCF 55
#define JR_C 56
#define ADD_HL_SP 57
#define LD_A_xNN 58
#define DEC_SP 59
#define INC_A 60
#define DEC_A 61
#define LD_A_N 62
#define CCF 63
#define LD_B_B 64
#define LD_B_C 65
#define LD_B_D 66
#define LD_B_E 67
#define LD_B_H 68
#define LD_B_L 69
#define LD_B_xHL 70
#define LD_B_A 71
#define LD_C_B 72
#define LD_C_C 73
#define LD_C_D 74
#define LD_C_E 75
#define LD_C_H 76
#define LD_C_L 77
#define LD_C_xHL 78
#define LD_C_A 79
#define LD_D_B 80
#define LD_D_C 81
#define LD_D_D 82
#define LD_D_E 83
#define LD_D_H 84
#define LD_D_L 85
#define LD_D_xHL 86
#define LD_D_A 87
#define LD_E_B 88
#define LD_E_C 89
#define LD_E_D 90
#define LD_E_E 91
#define LD_E_H 92
#define LD_E_L 93
#define LD_E_xHL 94
#define LD_E_A 95
#define LD_H_B 96
#define LD_H_C 97
#define LD_H_D 98
#define LD_H_E 99
#define LD_H_H 100
#define LD_H_L 101
#define LD_H_xHL 102
#define LD_H_A 103
#define LD_L_B 104
#define LD_L_C 105
#define LD_L_D 106
#define LD_L_E 107
#define LD_L_H 108
#define LD_L_L 109
#define LD_L_xHL 110
#define LD_L_A 111
#define LD_xHL_B 112
#define LD_xHL_C 113
#define LD_xHL_D 114
#define LD_xHL_E 115
#define LD_xHL_H 116
#define LD_xHL_L 117
#define HALT 118
#define LD_xHL_A 119
#define LD_A_B 120
#define LD_A_C 121
#define LD_A_D 122
#define LD_A_E 123
#define LD_A_H 124
#define LD_A_L 125
#define LD_A_xHL 126
#define LD_A_A 127
#define ADD_B 128
#define ADD_C 129
#define ADD_D 130
#define ADD_E 131
#define ADD_H 132
#define ADD_L 133
#define ADD_xHL 134
#define ADD_A 135
#define ADC_B 136
#define ADC_C 137
#define ADC_D 138
#define ADC_E 139
#define ADC_H 140
#define ADC_L 141
#define ADC_xHL 142
#define ADC_A 143
#define SUB_B 144
#define SUB_C 145
#define SUB_D 146
#define SUB_E 147
#define SUB_H 148
#define SUB_L 149
#define SUB_xHL 150
#define SUB_A 151
#define SBC_B 152
#define SBC_C 153
#define SBC_D 154
#define SBC_E 155
#define SBC_H 156
#define SBC_L 157
#define SBC_xHL 158
#define SBC_A 159
#define AND_B 160
#define AND_C 161
#define AND_D 162
#define AND_E 163
#define AND_H 164
#define AND_L 165
#define AND_xHL 166
#define AND_A 167
#define XOR_B 168
#define XOR_C 169
#define XOR_D 170
#define XOR_E 171
#define XOR_H 172
#define XOR_L 173
#define XOR_xHL 174
#define XOR_A 175
#define OR_B 176
#define OR_C 177
#define OR_D 178
#define OR_E 179
#define OR_H 180
#define OR_L 181
#define OR_xHL 182
#define OR_A 183
#define CP_B 184
#define CP_C 185
#define CP_D 186
#define CP_E 187
#define CP_H 188
#define CP_L 189
#define CP_xHL 190
#define CP_A 191
#define RET_NZ 192
#define POP_BC 193
#define JP_NZ 194
#define JP 195
#define CALL_NZ 196
#define PUSH_BC 197
#define ADD_N 198
#define RST_00 199
#define RET_Z 200
#define RET 201
#define JP_Z 202
#define PREFIX_CB 203
#define CALL_Z 204
#define CALL 205
#define ADC_N 206
#define RST_08 207
#define RET_NC 208
#define POP_DE 209
#define JP_NC 210
#define OUT_N_A 211
#define CALL_NC 212
#define PUSH_DE 213
#define SUB_N 214
#define RST_10 215
#define RET_C 216
#define EXX 217
#define JP_C 218
#define IN_A_N 219
#define CALL_C 220
#define PREFIX_DD 221
#define SBC_N 222
#define RST_18 223
#define RET_PO 224
#define POP_HL 225
#define JP_PO 226
#define EX_HL_xSP 227
#define CALL_PO 228
#define PUSH_HL 229
#define AND_N 230
#define RST_20 231
#define RET_PE 232
#define JP_xHL 233
#define JP_PE 234
#define EX_DE_HL 235
#define CALL_PE 236
#define PREFIX_ED 237
#define XOR_N 238
#define RST_28 239
#define RET_P 240
#define POP_AF 241
#define JP_P 242
#define DI 243
#define CALL_P 244
#define PUSH_AF 245
#define OR_N 246
#define RST_30 247
#define RET_M 248
#define LD_SP_HL 249
#define JP_M 250
#define EI 251
#define CALL_M 252
#define PREFIX_FD 253
#define CP_N 254
#define RST_38 255
/*--- CB Prefix opcodes: ---------------------------------------------*/
#define RLC_B 0
#define RLC_C 1
#define RLC_D 2
#define RLC_E 3
#define RLC_H 4
#define RLC_L 5
#define RLC_xHL 6
#define RLC_A 7
#define RRC_B 8
#define RRC_C 9
#define RRC_D 10
#define RRC_E 11
#define RRC_H 12
#define RRC_L 13
#define RRC_xHL 14
#define RRC_A 15
#define RL_B 16
#define RL_C 17
#define RL_D 18
#define RL_E 19
#define RL_H 20
#define RL_L 21
#define RL_xHL 22
#define RL_A 23
#define RR_B 24
#define RR_C 25
#define RR_D 26
#define RR_E 27
#define RR_H 28
#define RR_L 29
#define RR_xHL 30
#define RR_A 31
#define SLA_B 32
#define SLA_C 33
#define SLA_D 34
#define SLA_E 35
#define SLA_H 36
#define SLA_L 37
#define SLA_xHL 38
#define SLA_A 39
#define SRA_B 40
#define SRA_C 41
#define SRA_D 42
#define SRA_E 43
#define SRA_H 44
#define SRA_L 45
#define SRA_xHL 46
#define SRA_A 47
#define SLL_B 48
#define SLL_C 49
#define SLL_D 50
#define SLL_E 51
#define SLL_H 52
#define SLL_L 53
#define SLL_xHL 54
#define SLL_A 55
#define SRL_B 56
#define SRL_C 57
#define SRL_D 58
#define SRL_E 59
#define SRL_H 60
#define SRL_L 61
#define SRL_xHL 62
#define SRL_A 63
#define BIT_0_B 64
#define BIT_0_C 65
#define BIT_0_D 66
#define BIT_0_E 67
#define BIT_0_H 68
#define BIT_0_L 69
#define BIT_0_xHL 70
#define BIT_0_A 71
#define BIT_1_B 72
#define BIT_1_C 73
#define BIT_1_D 74
#define BIT_1_E 75
#define BIT_1_H 76
#define BIT_1_L 77
#define BIT_1_xHL 78
#define BIT_1_A 79
#define BIT_2_B 80
#define BIT_2_C 81
#define BIT_2_D 82
#define BIT_2_E 83
#define BIT_2_H 84
#define BIT_2_L 85
#define BIT_2_xHL 86
#define BIT_2_A 87
#define BIT_3_B 88
#define BIT_3_C 89
#define BIT_3_D 90
#define BIT_3_E 91
#define BIT_3_H 92
#define BIT_3_L 93
#define BIT_3_xHL 94
#define BIT_3_A 95
#define BIT_4_B 96
#define BIT_4_C 97
#define BIT_4_D 98
#define BIT_4_E 99
#define BIT_4_H 100
#define BIT_4_L 101
#define BIT_4_xHL 102
#define BIT_4_A 103
#define BIT_5_B 104
#define BIT_5_C 105
#define BIT_5_D 106
#define BIT_5_E 107
#define BIT_5_H 108
#define BIT_5_L 109
#define BIT_5_xHL 110
#define BIT_5_A 111
#define BIT_6_B 112
#define BIT_6_C 113
#define BIT_6_D 114
#define BIT_6_E 115
#define BIT_6_H 116
#define BIT_6_L 117
#define BIT_6_xHL 118
#define BIT_6_A 119
#define BIT_7_B 120
#define BIT_7_C 121
#define BIT_7_D 122
#define BIT_7_E 123
#define BIT_7_H 124
#define BIT_7_L 125
#define BIT_7_xHL 126
#define BIT_7_A 127
#define RES_0_B 128
#define RES_0_C 129
#define RES_0_D 130
#define RES_0_E 131
#define RES_0_H 132
#define RES_0_L 133
#define RES_0_xHL 134
#define RES_0_A 135
#define RES_1_B 136
#define RES_1_C 137
#define RES_1_D 138
#define RES_1_E 139
#define RES_1_H 140
#define RES_1_L 141
#define RES_1_xHL 142
#define RES_1_A 143
#define RES_2_B 144
#define RES_2_C 145
#define RES_2_D 146
#define RES_2_E 147
#define RES_2_H 148
#define RES_2_L 149
#define RES_2_xHL 150
#define RES_2_A 151
#define RES_3_B 152
#define RES_3_C 153
#define RES_3_D 154
#define RES_3_E 155
#define RES_3_H 156
#define RES_3_L 157
#define RES_3_xHL 158
#define RES_3_A 159
#define RES_4_B 160
#define RES_4_C 161
#define RES_4_D 162
#define RES_4_E 163
#define RES_4_H 164
#define RES_4_L 165
#define RES_4_xHL 166
#define RES_4_A 167
#define RES_5_B 168
#define RES_5_C 169
#define RES_5_D 170
#define RES_5_E 171
#define RES_5_H 172
#define RES_5_L 173
#define RES_5_xHL 174
#define RES_5_A 175
#define RES_6_B 176
#define RES_6_C 177
#define RES_6_D 178
#define RES_6_E 179
#define RES_6_H 180
#define RES_6_L 181
#define RES_6_xHL 182
#define RES_6_A 183
#define RES_7_B 184
#define RES_7_C 185
#define RES_7_D 186
#define RES_7_E 187
#define RES_7_H 188
#define RES_7_L 189
#define RES_7_xHL 190
#define RES_7_A 191
#define SET_0_B 192
#define SET_0_C 193
#define SET_0_D 194
#define SET_0_E 195
#define SET_0_H 196
#define SET_0_L 197
#define SET_0_xHL 198
#define SET_0_A 199
#define SET_1_B 200
#define SET_1_C 201
#define SET_1_D 202
#define SET_1_E 203
#define SET_1_H 204
#define SET_1_L 205
#define SET_1_xHL 206
#define SET_1_A 207
#define SET_2_B 208
#define SET_2_C 209
#define SET_2_D 210
#define SET_2_E 211
#define SET_2_H 212
#define SET_2_L 213
#define SET_2_xHL 214
#define SET_2_A 215
#define SET_3_B 216
#define SET_3_C 217
#define SET_3_D 218
#define SET_3_E 219
#define SET_3_H 220
#define SET_3_L 221
#define SET_3_xHL 222
#define SET_3_A 223
#define SET_4_B 224
#define SET_4_C 225
#define SET_4_D 226
#define SET_4_E 227
#define SET_4_H 228
#define SET_4_L 229
#define SET_4_xHL 230
#define SET_4_A 231
#define SET_5_B 232
#define SET_5_C 233
#define SET_5_D 234
#define SET_5_E 235
#define SET_5_H 236
#define SET_5_L 237
#define SET_5_xHL 238
#define SET_5_A 239
#define SET_6_B 240
#define SET_6_C 241
#define SET_6_D 242
#define SET_6_E 243
#define SET_6_H 244
#define SET_6_L 245
#define SET_6_xHL 246
#define SET_6_A 247
#define SET_7_B 248
#define SET_7_C 249
#define SET_7_D 250
#define SET_7_E 251
#define SET_7_H 252
#define SET_7_L 253
#define SET_7_xHL 254
#define SET_7_A 255
/*--- ED opcodes: ----------------------------------------------------*/
#define IN_B_xC 64
#define OUT_xC_B 65
#define SBC_HL_BC 66
#define LD_xNNe_BC 67
#define NEG 68
#define RETN 69
#define IM_0 70
#define LD_I_A 71
#define IN_C_xC 72
#define OUT_xC_C 73
#define ADC_HL_BC 74
#define LD_BC_xNNe 75
#define ED_4C 76 /* * NEG */
#define RETI 77
#define ED_4E 78 /* * IM 0/1 */
#define LD_R_A 79
#define IN_D_xC 80
#define OUT_xC_D 81
#define SBC_HL_DE 82
#define LD_xNNe_DE 83
#define ED_54 84 /* * NEG */
#define ED_55 85 /* * RET */
#define IM_1 86
#define LD_A_I 87
#define IN_E_xC 88
#define OUT_xC_E 89
#define ADC_HL_DE 90
#define LD_DE_xNNe 91
#define ED_5C 92 /* * NEG */
#define ED_5D 93 /* * RET */
#define IM_2 94
#define LD_A_R 95
#define IN_H_xC 96
#define OUT_xC_H 97
#define SBC_HL_HL 98
#define LD_xNNe_HL 99
#define ED_64 100 /* * NEG */
#define ED_65 101 /* * RET */
#define ED_66 102 /* * IM 0 */
#define RRD 103
#define IN_L_xC 104
#define OUT_xC_L 105
#define ADC_HL_HL 106
#define LD_HL_xNNe 107
#define ED_6C 108 /* * NEG */
#define ED_6D 109 /* * RET */
#define ED_6E 110 /* * IM 0 */
#define RLD 111
#define IN_F_xC 112
#define ED_71 113 /* * OUT (C), 0 */
#define SBC_HL_SP 114
#define LD_xNNe_SP 115
#define ED_74 116 /* * NEG */
#define ED_75 117 /* * RET */
#define ED_76 118 /* * IM 1 */
#define ED_77 119 /* * NOP */
#define IN_A_xC 120
#define OUT_xC_A 121
#define ADC_HL_SP 122
#define LD_SP_xNNe 123
#define ED_7C 124 /* * NEG */
#define ED_7D 125 /* * RET */
#define ED_7E 126 /* * IM 2 */
#define ED_7F 127 /* * NOP */
#define LDI 160
#define CPI 161
#define INI 162
#define OUTI 163
#define LDD 168
#define CPD 169
#define IND 170
#define OUTD 171
#define LDIR 176
#define CPIR 177
#define INIR 178
#define OTIR 179
#define LDDR 184
#define CPDR 185
#define INDR 186
#define OTDR 187
#define ED_FE 254
/*--- DD xx opcodes: -------------------------------------------------*/
/* Those are the DD xx opcodes where HL is treated as IX + a
signed byte displacement n when required: DD opcode n: */
/*--- FD xx opcodes: -------------------------------------------------*/
/* Those are the FD xx opcodes where HL is treated as IY + a
signed byte displacement n when required: FD opcode n: */
#define ADD_IXY_BC 9
#define ADD_IXY_DE 25
#define LD_IXY_NN 33
#define LD_xNN_IXY 34
#define INC_IXY 35
#define INC_IXYh 36
#define DEC_IXYh 37
#define LD_IXYh_N 38
#define ADD_IXY_IXY 41
#define LD_IXY_xNN 42
#define DEC_IXY 43
#define INC_IXYl 44
#define DEC_IXYl 45
#define LD_IXYl_N 46
#define INC_xIXY 52
#define DEC_xIXY 53
#define LD_xIXY_N 54
#define ADD_IXY_SP 57
#define LD_B_IXYh 68
#define LD_B_IXYl 69
#define LD_B_xIXY 70
#define LD_C_IXYh 76
#define LD_C_IXYl 77
#define LD_C_xIXY 78
#define LD_D_IXYh 84
#define LD_D_IXYl 85
#define LD_D_xIXY 86
#define LD_E_IXYh 92
#define LD_E_IXYl 93
#define LD_E_xIXY 94
#define LD_IXYh_B 96
#define LD_IXYh_C 97
#define LD_IXYh_D 98
#define LD_IXYh_E 99
#define LD_IXYh_IXYh 100
#define LD_IXYh_IXYl 101
#define LD_H_xIXY 102
#define LD_IXYh_A 103
#define LD_IXYl_B 104
#define LD_IXYl_C 105
#define LD_IXYl_D 106
#define LD_IXYl_E 107
#define LD_IXYl_IXYh 108
#define LD_IXYl_IXYl 109
#define LD_L_xIXY 110
#define LD_IXYl_A 111
#define LD_xIXY_B 112
#define LD_xIXY_C 113
#define LD_xIXY_D 114
#define LD_xIXY_E 115
#define LD_xIXY_H 116
#define LD_xIXY_L 117
#define LD_xIXY_A 119
#define LD_A_IXYh 124
#define LD_A_IXYl 125
#define LD_A_xIXY 126
#define ADD_IXYh 132
#define ADD_IXYl 133
#define ADD_xIXY 134
#define ADC_IXYh 140
#define ADC_IXYl 141
#define ADC_xIXY 142
#define SUB_IXYh 148
#define SUB_IXYl 149
#define SUB_xIXY 150
#define SBC_IXYh 156
#define SBC_IXYl 157
#define SBC_xIXY 158
#define AND_IXYh 164
#define AND_IXYl 165
#define AND_xIXY 166
#define XOR_IXYh 172
#define XOR_IXYl 173
#define XOR_xIXY 174
#define OR_IXYh 180
#define OR_IXYl 181
#define OR_xIXY 182
#define CP_IXYh 188
#define CP_IXYl 189
#define CP_xIXY 190
#define POP_IXY 225
#define EX_IXY_xSP 227
#define PUSH_IXY 229
#define JP_IXY 233
#define LD_SP_IXY 249
/*--- DD CB Prefix opcodes: ------------------------------------------*/
/* Those are the CB xx opcodes where HL is treated as IX + a
signed byte displacement n: DD CB n opcode: */
/*--- FD CB Prefix opcodes: ------------------------------------------*/
/* Those are the CB xx opcodes where HL is treated as IY + a
signed byte displacement n: FD CB n opcode: */
#define RLC_IXYh 4
#define RLC_IXYl 5
#define RLC_xIXY 6
#define RRC_IXYh 12
#define RRC_IXYl 13
#define RRC_xIXY 14
#define RL_IXYh 20
#define RL_IXYl 21
#define RL_xIXY 22
#define RR_IXYh 28
#define RR_IXYl 29
#define RR_xIXY 30
#define SLA_IXYh 36
#define SLA_IXYl 37
#define SLA_xIXY 38
#define SRA_IXYh 44
#define SRA_IXYl 45
#define SRA_xIXY 46
#define SLL_IXYh 52
#define SLL_IXYl 53
#define SLL_xIXY 54
#define SRL_IXYh 60
#define SRL_IXYl 61
#define SRL_xIXY 62
#define BIT_0_IXYh 68
#define BIT_0_IXYl 69
#define BIT_0_xIXY 70
#define BIT_1_IXYh 76
#define BIT_1_IXYl 77
#define BIT_1_xIXY 78
#define BIT_2_IXYh 84
#define BIT_2_IXYl 85
#define BIT_2_xIXY 86
#define BIT_3_IXYh 92
#define BIT_3_IXYl 93
#define BIT_3_xIXY 94
#define BIT_4_IXYh 100
#define BIT_4_IXYl 101
#define BIT_4_xIXY 102
#define BIT_5_IXYh 108
#define BIT_5_IXYl 109
#define BIT_5_xIXY 110
#define BIT_6_IXYh 116
#define BIT_6_IXYl 117
#define BIT_6_xIXY 118
#define BIT_7_IXYh 124
#define BIT_7_IXYl 125
#define BIT_7_xIXY 126
#define RES_0_IXYh 132
#define RES_0_IXYl 133
#define RES_0_xIXY 134
#define RES_1_IXYh 140
#define RES_1_IXYl 141
#define RES_1_xIXY 142
#define RES_2_IXYh 148
#define RES_2_IXYl 149
#define RES_2_xIXY 150
#define RES_3_IXYh 156
#define RES_3_IXYl 157
#define RES_3_xIXY 158
#define RES_4_IXYh 164
#define RES_4_IXYl 165
#define RES_4_xIXY 166
#define RES_5_IXYh 172
#define RES_5_IXYl 173
#define RES_5_xIXY 174
#define RES_6_IXYh 180
#define RES_6_IXYl 181
#define RES_6_xIXY 182
#define RES_7_IXYh 188
#define RES_7_IXYl 189
#define RES_7_xIXY 190
#define SET_0_IXYh 196
#define SET_0_IXYl 197
#define SET_0_xIXY 198
#define SET_1_IXYh 204
#define SET_1_IXYl 205
#define SET_1_xIXY 206
#define SET_2_IXYh 212
#define SET_2_IXYl 213
#define SET_2_xIXY 214
#define SET_3_IXYh 220
#define SET_3_IXYl 221
#define SET_3_xIXY 222
#define SET_4_IXYh 228
#define SET_4_IXYl 229
#define SET_4_xIXY 230
#define SET_5_IXYh 236
#define SET_5_IXYl 237
#define SET_5_xIXY 238
#define SET_6_IXYh 244
#define SET_6_IXYl 245
#define SET_6_xIXY 246
#define SET_7_IXYh 252
#define SET_7_IXYl 253
#define SET_7_xIXY 254
#endif

View File

@ -0,0 +1,407 @@
/*=====================================================================
z80.c -> Main File related to the Z80 emulation code.
Please read documentation files to know how this works :)
Thanks go to Marat Fayzullin (read z80.h for more info), Raúl Gomez
(check his great R80 Spectrum emulator!), Philip Kendall (some code
of this emulator, such as the flags lookup tabled are from his fuse
Spectrum emulator) and more people I forget to name here ...
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Copyright (c) 2000 Santiago Romero Iglesias.
Email: sromero@escomposlinux.org
======================================================================*/
#include "z80.h"
#include "tables.h"
/* RAM variable, debug toggle variable, pressed key and
row variables for keyboard emulation */
extern byte *RAM;
extern int debug, main_tecla, scanl;
extern int fila[5][5];
//extern char *tapfile;
//extern FILE *tapfile;
extern char *tfont;
#include "macros.c"
/*====================================================================
void Z80Reset( Z80Regs *regs, int cycles )
This function simulates a z80 reset by setting the registers
to the values they are supposed to take on a real z80 reset.
You must pass it the Z80 register structure and the number
of cycles required to check for interrupts and do special
hardware checking/updating.
===================================================================*/
void Z80Reset( Z80Regs *regs, int int_cycles )
{
/* reset PC and the rest of main registers: */
regs->PC.W = regs->R.W = 0x0000;
regs->AF.W = regs->BC.W = regs->DE.W = regs->HL.W =
regs->AFs.W = regs->BCs.W = regs->DEs.W = regs->HLs.W =
regs->IX.W = regs->IY.W = 0x0000;
/* Make the stack point to $F000 */
regs->SP.W = 0xF000;
/* reset variables to their default values */
regs->I = 0x00;
regs->IFF1 = regs->IFF2 = regs->IM = regs->halted = 0x00;
regs->ICount = regs->IPeriod = int_cycles;
regs->IRequest = INT_NOINT;
regs->we_are_on_ddfd = regs->dobreak = regs->BorderColor = 0;
//#ifdef _DEBUG_
regs->DecodingErrors = 1;
//#endif
}
/*====================================================================
word Z80Run( Z80Regs *regs, int numopcodes )
This function does the whole Z80 simulation. It consists on a
for(;;) loop (as stated on Marat's Fayzullin HOWTO -How to
Write a Computer Emulator-) which fetchs the next opcode,
interprets it (using a switch statement) and then it's
executed in the right CASE: of that switch. I've put the different
case statements into C files included here with #include to
make this more readable (and programming easier! :).
This function will change regs->ICount register and will execute
an interrupt when it reaches 0 (or <0). You can then do anything
related to your machine emulation here, using the Z80Hardware()
function. This function must be filled by yourself: put there
the code related to the emulated machine hardware, such as
screen redrawing, sound playing and so on. This functions can
return an special value to make Z80Run stop the emulation (and
return to the caller): that's INT_QUIT. If there is time to
execute an interrupt, please return INT_IRQ or INT_NMI. Return
INT_NOINT if there is no time for an interrupt :) .
Z80Execute() will change PC and all the z80 registers acording
to the executed opcode, and those values will be returned when
a INT_QUIT is received.
Pass as numcycles the number of clock cycle you want to execute
z80 opcodes for or < 0 (negative) to execute "infinite" opcodes.
===================================================================*/
word Z80Run( Z80Regs *regs, int numcycles )
{
/* opcode and temp variables */
register byte opcode;
eword tmpreg, ops, mread, tmpreg2;
unsigned long tempdword;
register int loop;
unsigned short tempword;
/* emulate <numcycles> cycles */
loop = (regs->ICount - numcycles);
/* this is the emulation main loop */
while( regs->ICount > loop )
{
#ifdef DEBUG
/* test if we have reached the trap address */
if( regs->PC.W == regs->TrapAddress && regs->dobreak != 0 )
return(regs->PC.W);
#endif
if( regs->halted == 1 )
{ r_PC--; AddCycles(4); }
/* read the opcode from memory (pointed by PC) */
opcode = Z80ReadMem(regs->PC.W);
regs->PC.W++;
/* increment the R register and decode the instruction */
AddR(1);
switch(opcode)
{
#include "opcodes.c"
case PREFIX_CB:
AddR(1);
#include "op_cb.c"
break;
case PREFIX_ED:
AddR(1);
#include "op_ed.c"
break;
case PREFIX_DD:
case PREFIX_FD:
AddR(1);
if( opcode == PREFIX_DD )
{
#define REGISTER regs->IX
regs->we_are_on_ddfd = WE_ARE_ON_DD;
#include "op_dd_fd.c"
#undef REGISTER
}
else
{
#define REGISTER regs->IY
regs->we_are_on_ddfd = WE_ARE_ON_FD;
#include "op_dd_fd.c"
#undef REGISTER
}
regs->we_are_on_ddfd = 0;
break;
}
/* patch ROM loading routine */
// address contributed by Ignacio Burgueño :)
// if( r_PC == 0x0569 )
if( r_PC >= 0x0556 && r_PC <= 0x056c )
Z80Patch( regs );
/* check if it's time to do other hardware emulation */
if( regs->ICount <= 0 )
{
tmpreg.W = Z80Hardware(regs);
regs->ICount += regs->IPeriod;
loop = regs->ICount + loop;
/* check if we must exit the emulation or there is an INT */
if( tmpreg.W == INT_QUIT )
return( regs->PC.W );
if( tmpreg.W != INT_NOINT )
Z80Interrupt( regs, tmpreg.W );
}
}
return(regs->PC.W);
}
/*====================================================================
void Z80Interrupt( Z80Regs *regs, word ivec )
===================================================================*/
void Z80Interrupt( Z80Regs *regs, word ivec )
{
word intaddress;
/* unhalt the computer */
if( regs->halted == 1 )
regs->halted = 0;
if( regs->IFF1 )
{
PUSH(PC);
regs->IFF1 = 0;
switch(regs->IM)
{
case 0: r_PC = 0x0038; AddCycles(12); break;
case 1: r_PC = 0x0038; AddCycles(13); break;
case 2: intaddress = (((regs->I & 0xFF)<<8) | 0xFF);
regs->PC.B.l = Z80ReadMem(intaddress);
regs->PC.B.h = Z80ReadMem(intaddress+1);
AddCycles(19);
break;
}
}
}
/*====================================================================
word Z80Hardware(register Z80Regs *regs)
Do here your emulated machine hardware emulation. Read Z80Execute()
to know about how to quit emulation and generate interrupts.
===================================================================*/
word Z80Hardware( register Z80Regs *regs )
{
if(
debug != 1 // && scanl >= 224
)
{
;
}
return( INT_IRQ );
}
/*====================================================================
void Z80Patch( register Z80Regs *regs )
Write here your patches to some z80 opcodes that are quite related
to the emulated machines (i.e. maybe accessing to the I/O ports
and so on), such as ED_FE opcode:
case ED_FE: Z80Patch(regs);
break;
This allows "BIOS" patching (cassette loading, keyboard ...).
===================================================================*/
void Z80Patch( register Z80Regs *regs )
{
///!!! if( tapfile != NULL )
///!!! {
///!!! LoadTAP( regs, tapfile );
///!!! POP(PC);
///!!! }
/*
if( strlen(tapfile) != 0 )
{
if( LoadTapFile( regs, tapfile ) )
{ POP(PC); }
}
else
{
FileMenu( tfont, 3, tapfile );
if( strlen(tapfile) != 0 )
if( LoadTapFile( regs, tapfile ) )
{ POP(PC); }
}
*/
}
/*====================================================================
byte Z80Debug( register Z80Regs *regs )
This function is written for debugging purposes (it's supposed to
be a debugger by itself!). It will debug a single opcode, given
by the current PC address.
Return DEBUG_OK to state success and DEBUG_QUIT to quit emulation.
===================================================================*/
byte Z80Debug( register Z80Regs *regs )
{
return( DEBUG_QUIT );
}
/*====================================================================
byte Z80MemRead( register word address )
This function reads from the given memory address. It is not inlined,
and it's written for debugging purposes.
===================================================================*/
byte Z80MemRead( register word address, Z80Regs *regs )
{
return(Z80ReadMem(address));
}
/*====================================================================
void Z80MemWrite( register word address, register byte value )
This function writes on memory the given value. It is not inlined,
ands it's written for debugging purposes.
===================================================================*/
void Z80MemWrite( register word address, register byte value, Z80Regs *regs )
{
Z80WriteMem( address, value, regs );
}
/*====================================================================
byte Z80InPort( register word port )
This function reads from the given I/O port. It is not inlined,
and it's written for debugging purposes.
===================================================================*/
byte Z80InPort( register word port )
{
int porth;
int code = 0xFF;
porth = port >> 8;
if (!(porth & 0x01)) code &= fila[4][1];
if (!(porth & 0x02)) code &= fila[3][1];
if (!(porth & 0x04)) code &= fila[2][1];
if (!(porth & 0x08)) code &= fila[1][1];
if (!(porth & 0x10)) code &= fila[1][2];
if (!(porth & 0x20)) code &= fila[2][2];
if (!(porth & 0x40)) code &= fila[3][2];
if (!(porth & 0x80)) code &= fila[4][2];
/*
issue 2 emulation, thx to Raul Gomez!!!!!
I should implement this also:
if( !ear_on && mic_on )
code &= 0xbf;
where earon = bit 4 of the last OUT to the 0xFE port
and micon = bit 3 of the last OUT to the 0xFE port
*/
code &= 0xbf;
if( (port & 0xFF) == 0xFF )
{
if( (rand() % 10) > 7 ) return(0xff);
else return( rand()%0xFF );
}
return( code );
}
/*====================================================================
void Z80OutPort( register word port, register byte value )
This function outs a value to a given I/O port. It is not inlined,
and it's written for debugging purposes.
===================================================================*/
void Z80OutPort( register Z80Regs *regs,
register word port, register byte value )
{
/* change border colour */
if( ! (port & 0x01) )
regs->BorderColor = (value & 0x07);
}
/*====================================================================
static void Z80FlagTables ( void );
Creates a look-up table for future flag setting...
Taken from fuse's sources. Thanks to Philip Kendall.
===================================================================*/
void Z80FlagTables(void)
{
int i,j,k;
byte parity;
for(i=0;i<0x100;i++) {
sz53_table[i]= i & ( FLAG_3 | FLAG_5 | FLAG_S );
j=i; parity=0;
for(k=0;k<8;k++) { parity ^= j & 1; j >>=1; }
parity_table[i]= ( parity ? 0 : FLAG_P );
sz53p_table[i] = sz53_table[i] | parity_table[i];
}
sz53_table[0] |= FLAG_Z;
sz53p_table[0] |= FLAG_Z;
}

View File

@ -0,0 +1,188 @@
/*=====================================================================
z80.c -> Header file related to the Z80 emulation code.
Please read documentation files to know how this works :)
Thanks to Marat Fayzullin for writing the "How to write a Computer
Eemulator" HOWTO. This emulator is based on his tutorials and the
code organization (very readable!) of his "Z80 Portable Emulator".
I've learnt a lot from it, and I've taken some ideas of his code
to write this emulator.I think that almost all of the undocumented
Z80 opcodes are covered on this emulator. I also asked Marat
Fayzullin (by email) about ideas and so on (his Z80 emulator is
quite good, so go check it :-).
Of course, I can't forget Raúl Gomez (he answered me thousands
of email questions) and Philip Kendall. Whitout his ___kind___
people surely you won't be reading this file now...
"Programming the Z80" (from Rodnay Zaks) and the comp.sys.sinclair
FAQ were another excelent sources of info!
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Copyright (c) 2000 Santiago Romero Iglesias.
Email: sromero@escomposlinux.org
======================================================================*/
#ifndef Z80_H
#define Z80_H
#define USING_ALLEGRO
#define DEBUG
#define _DEV_DEBUG_ /* development debugging */
#define LOW_ENDIAN
/*#define HI_ENDIAN */
/* Used by the Z80Debug() function */
#define DEBUG_OK 1
#define DEBUG_QUIT 0
#define video vscreen
/*=== Some common standard data types: ==============================*/
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
typedef signed char offset;
/*--- Thanks to Philip Kendall for it's help using the flags --------*/
extern byte halfcarry_add_table[];
extern byte halfcarry_sub_table[];
extern byte overflow_add_table[];
extern byte overflow_sub_table[];
extern byte sz53_table[];
extern byte sz53p_table[];
extern byte parity_table[];
extern byte ioblock_inc1_table[];
extern byte ioblock_dec1_table[];
extern byte ioblock_2_table[];
/*=====================================================================
Z80 Flag Register: ---------------------------------
| 7 6 5 4 3 2 1 0 |
---------------------------------
| S Z x H x O/P N C |
---------------------------------
If (1) means that: S = Negative result.
Z = Zero result.
x = special cases (by opcode)
H = Halfcarry/borrow.
O/P = Overflow/Parity Flag.
N = Substraction.
C = Carry/borrow.
====================================================================*/
#define S_FLAG 0x80
#define Z_FLAG 0x40
#define H_FLAG 0x10
#define P_FLAG 0x04
#define O_FLAG 0x04
#define N_FLAG 0x02
#define C_FLAG 0x01
/*
Defines for interrupts and special Z80Hardware() codes:
=======================================================================
INT_QUIT = Exit the emulation (for Z80Run())
INT_NOINT = No interrupt required
INT_IRQ = Standard RST 38h interrupt
INT_NMI = Non-maskerable interrupt
*/
#define INT_QUIT 0xFFFE
#define INT_NOINT 0xFFFF
#define INT_IRQ 0x0038
#define INT_NMI 0x0066
/*=== A register is defined as follows: =============================*/
typedef union
{
#ifdef LOW_ENDIAN
struct
{
byte l,h;
} B;
#else
struct
{
byte h,l;
} B;
#endif
word W;
} eword;
#define WE_ARE_ON_DD 1
#define WE_ARE_ON_FD 2
/*=== Now we define the Z80 registers using the previous definition =*/
typedef struct
{
char machine_type;
byte *RAM;
int we_are_on_ddfd;
/* general and shadow z80 registers */
eword AF, BC, DE, HL, IX, IY, PC, SP, R,
AFs, BCs, DEs, HLs;
/* IFF and I registers, used on interrupts. */
byte IFF1, IFF2, I, halted;
char IM;
word IRequest;
/* the following is to take care of cycle counting */
int IPeriod, ICount, IBackup;
/* DecodingErrors = set this to 1 for debugging purposes in order
to trap undocumented or non implemented opcodes.
Trace = set this to 1 to start tracing. It's also set
when PC reaches TrapAddress value. */
byte DecodingErrors;
word TrapAddress;
byte Trace, dobreak;
byte BorderColor;
} Z80Regs;
/*====================================================================
Function declarations, read the .c file to know what they do.
===================================================================*/
void Z80Reset( register Z80Regs *regs, int );
void Z80Interrupt( register Z80Regs *, register word );
word Z80Run( register Z80Regs *, int );
byte Z80MemRead( register word, Z80Regs * );
void Z80MemWrite( register word, register byte, Z80Regs * );
byte Z80InPort( register word );
void Z80OutPort( register Z80Regs *regs, register word, register byte );
void Z80Patch( register Z80Regs * );
byte Z80Debug( register Z80Regs * );
word Z80Hardware( register Z80Regs * );
void Z80FlagTables(void);
word ParseOpcode( char *, char *, char *, word, Z80Regs * );
word Z80Dissasembler ( Z80Regs *, char *, char * );
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
*******************************RUSSIAN****************************************
==Î ïðîãðàììå FCEU==
FCE Ultra - îäèí èç ëó÷øèõ ýìóëÿòîðîâ NES íà Linux, DOS, Windows,
BeOS, Mac OS X, à òåïåðü è íà Kolibri è Menuet!
Ñàéò: http://fceultra.sourceforge.net
Ïîääåðæèâàåìûå ìàïïåðû: 0-11, 13, 15-19, 21-26, 32-34, 40-49, 51, 52, 57, 61, 64-80,
82, 83, 85-90, 92-97, 99, 105, 107, 112-119, 140, 144,
151-156, 180, 182, 184, 189, 225-229, 232, 234, 235, 240,
242, 246, 248-250
Ïîñëå çàïóñêà ïðîãðàììû íóæíî ïðîïèñàòü ïîëíûé ïóòü ê íóæíîìó ôàéëó NES
è íàæàòü Enter (ïóòü îòîáðàæàåòñÿ â âåðõíåé ÷àñòè îêíà).
Âåðñèÿ ýìóëÿòîðà: 0.96
Âåðñèÿ ïîðòà: 0.3
==Ïîðòåð==
Asper
Ïèñàòü ñþäà: asper.85@mail.ru
Îñíîâíûå êëàâèøè:
Äëÿ ýìóëèðóåìîãî óñòðîéñòâà Family BASIC Keyboard:
Âêëþ÷èòü/Âûêëþ÷èòü Ââîä Êëàâèàòóðû Scroll Lock
(âêëþ÷åíèå ââîäà ñ ýìóëèðóåìîé êëàâèàòóðû îòêëþ÷àåò
êîììàíäíûå êëàâèøè)
Âñå ýìóëèðóåìûå êëàâèøè îòîáðàæàþòñÿ íà áëèæàéøóþ äîñòóïíóþ êëàâèøó
íà êëàâèàòóðå ÏÊ çà íåáîëüøèìè èñêëþ÷åíèÿìè. Ýìóëèðóåìàÿ êëàâèøà "@"
îòîáðàæàåòñÿ íà êëàâèøó "`"(grave), è ýìóëèðóåìàÿ êëàâèøà "kana"
îòîáðàæàåòñÿ íà êëàâèøó "Insert" (â áëîêå êëàâèø ðàçìåðà 3x2 íàä
êóðñîðíûìè êëàâèøàìè).
Äëÿ ýìóëèðóåìûõ óñòðîéñòâ game pads:
A Turbo B
S Turbo A
Left Control or Z or Space B
Left Alt or X A
Enter/Return Ñòàðò
Tab or BackSpace Ñåëåêò
Cursor Down Âíèç
Cursor Up Ââåðõ
Cursor Left Âëåâî
Cursor Right Âïðàâî
Äëÿ ýìóëèðóåìûõ óñòðîéñòâ power pads(êëàâèøè ñîîòâåòñòâóþò ðàñïîëîæåíèþ
êíîïîê íà ñòîðîíå "B"):
O P [ ]
K L ; '
M , . /
Äëÿ FDS èãð:
F6 Âûáðàòü äèñê/ñòîðîíó äèñêà.
F8 Èçâëå÷ü/Âñòàâèòü äèñê.
Äëÿ VS Unisystem èãð:
F8 Âñòàâèòü ìîíåòó.
F6 Îòîáðàçèòü/Ñêðûòü dip ïåðåêëþ÷àòåëè.
1-8 Ïåðåêëþ÷èòü dip ïåðåêëþ÷àòåëè (êîãäà dip
ïåðåêëþ÷àòåëè îòîáàæàþòñÿ).
0-9 Âûáðàòü ñëîò ñîõðàíåíèÿ.
Caps Lock Âûáðàòü âèðòóàëüíûé äæîéñòèê.
F2 Ìàññøòàáèðîâàòü îêíî.
F3 Îòêðûòü ôàéë.
F5/F7 Ñîõðàíèòü/Çàãðóçèòü ñîõðàíåíèå.
F9 Ñîõðàíèòü ñíèìîê ýêðàíà.
F10 Ïåðåçàãðóçêà.
F11 Âûêëþ÷èòü/Âêëþ÷èòü.
ESC/F12 Âûõîä.
*******************************ENGLISH****************************************
==About program FCEU==
FCE Ultra - is is one of the best emulators of NES on Linux, DOS, Windows,
BeOS, Mac OS X, and now on Kolibri and Menuet!
Website: http://fceultra.sourceforge.net
Supported mappers: 0-11, 13, 15-19, 21-26, 32-34, 40-49, 51, 52, 57, 61, 64-80,
82, 83, 85-90, 92-97, 99, 105, 107, 112-119, 140, 144,
151-156, 180, 182, 184, 189, 225-229, 232, 234, 235, 240,
242, 246, 248-250
After program executing you have to input full path to the NES file that you want
to be executed and press Enter (the path echo on the upper part of the window).
Emulator version number: 0.96
Port version 0.3
==Porter==
Asper
mailto: asper.85@mail.ru
Main keys:
For emulated Family BASIC Keyboard:
Enable/Disable Keyboard Input Scroll Lock
(enabling emulated keyboard input will disable
commands keys)
All emulated keys are mapped to the closest open key on the PC
keyboard, with a few exceptions. The emulated "@" key is
mapped to the "`"(grave) key, and the emulated "kana" key
is mapped to the "Insert" key(in the 3x2 key block above the
cursor keys).
For emulated game pads:
A Turbo B
S Turbo A
Left Control or Z or Space B
Left Alt or X A
Enter/Return Start
Tab or BackSpace Select
Cursor Down Down
Cursor Up Up
Cursor Left Left
Cursor Right Right
For emulated power pads(keys correspond to button locations on
side "B"):
O P [ ]
K L ; '
M , . /
For FDS games:
F6 Select disk/disk side.
F8 Eject/Insert disk.
For VS Unisystem games:
F8 Insert coin.
F6 Show/Hide dip switches.
1-8 Toggle dip switches(when dip switches
are shown).
0-9 Select save state.
Caps Lock Select virtual joystick.
F2 Scale window.
F3 Open file.
F5/F7 Save/Load state.
F9 Save screen snapshot.
F10 Reset.
F11 Power off/on.
ESC/F12 Exit.

View File

@ -0,0 +1,33 @@
01.09.08 == Port v0.1 == Emulator v0.42
- çàãðóçêà NES ôàéëîâ | - load NES files
- èñïîëíåíèå NES ôàéëîâ | - execute NES files
- ìàññøòàáèðîâàíèå ðàçìåðà îêíà | - scale window size
- ðàáîòàåò â ÎÑ Kolibri è Menuet | - work in OS Kolibri and Menuet
24.10.08 == Port v0.2 == Emulator v0.42
- ðàáîòà ñ ñèñ. ôóíêöèåé 70 | - working with sys. function 70
- ñîçäàíèå ñîõðàíåíèé | - make saves
- çàãðóçêà ñîõðàíåíèé | - load saves
- ñîçäàíèå ñêðèíøîòîâ | - make screenshots
- äîáàâëåíû êëàâèøè Òóðáî A è Òóðáî B | - Turbo A and Turbo B keys were added
- ðàáîòàåò òîëüêî â ÎÑ Kolibri èç-çà | - work in OS Kolibri only because of
èñïîëüçîâàíèÿ ñèñ. ôóíêöèè 70 | using sys. function 70
09.07.09 == Port v0.3 == Emulator v0.96
- äîáàâëåíî 33 íîâûõ ìàïïåðà | - 33 new mappers were add
( 48, 51, 52, 57, 61, 72, 74, 77, 82, 83, 88, 92, 96, 114, 115-117, 140,
144, 152-156, 189, 227, 232, 234, 235, 242, 248-250 )
- äîáàâëåíû íîâûå ýìóëèðóåìûå | - new emulated devices were add
óñòðîéñòâà |
( power pads, game pads, zapper, arkanoid, shadow, Family BASIC Keyboard )
- âûáîð âèðòóàëüíîãî äæîéñòèêà | - select virtual joysticks
- óñêîðåííûé âûâîä ãðàôèêè | - faster graphics output
- âûâîä fps | - fps output
- ñîîáùåíèÿ òåïåðü âûâîäÿòñÿ íà äîñêó | - messages now output to the debug board
îòëàäêè |
- ñì. ôàéë "ChangeLog.txt" ÷òîáû | - see file "ChangeLog.txt" for full list of changes
ïðîñìîòðåòü âåñü ñïèñîê èçìåíåíèé |

BIN
programs/emulator/fceu/fce Normal file

Binary file not shown.