add speccy emulator to T-COMPUTER
This commit is contained in:
parent
bc854b7c3b
commit
c814359090
30 changed files with 28408 additions and 0 deletions
9160
MCUME_teensy41/bin/TEECOMPUTER/TFT/teensyspeccy.ino.hex
Normal file
9160
MCUME_teensy41/bin/TEECOMPUTER/TFT/teensyspeccy.ino.hex
Normal file
File diff suppressed because it is too large
Load diff
9160
MCUME_teensy41/bin/TEECOMPUTER/VGA/teensyspeccy.ino.hex
Normal file
9160
MCUME_teensy41/bin/TEECOMPUTER/VGA/teensyspeccy.ino.hex
Normal file
File diff suppressed because it is too large
Load diff
315
MCUME_teensy41/teensyspeccy/AY8910.c
Normal file
315
MCUME_teensy41/teensyspeccy/AY8910.c
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
/** EMULib Emulation Library *********************************/
|
||||
/** **/
|
||||
/** AY8910.c **/
|
||||
/** **/
|
||||
/** This file contains emulation for the AY8910 sound chip **/
|
||||
/** produced by General Instruments, Yamaha, etc. See **/
|
||||
/** AY8910.h for declarations. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2014 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
#include "AY8910.h"
|
||||
#include "emuapi.h"
|
||||
#include <string.h>
|
||||
|
||||
static const unsigned char Envelopes[16][32] =
|
||||
{
|
||||
{ 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
|
||||
{ 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
|
||||
{ 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
|
||||
{ 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
|
||||
{ 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 },
|
||||
{ 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
|
||||
{ 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 },
|
||||
{ 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 },
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 },
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 },
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 },
|
||||
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
|
||||
};
|
||||
|
||||
static const int Volumes[16] =
|
||||
{ 0,1,2,4,6,8,11,16,23,32,45,64,90,128,180,255 };
|
||||
//{ 0,16,33,50,67,84,101,118,135,152,169,186,203,220,237,254 };
|
||||
|
||||
/** Reset8910() **********************************************/
|
||||
/** Reset the sound chip and use sound channels from the **/
|
||||
/** one given in First. **/
|
||||
/*************************************************************/
|
||||
void Reset8910(register AY8910 *D,int ClockHz,int First)
|
||||
{
|
||||
static byte RegInit[16] =
|
||||
{
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFD,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00
|
||||
};
|
||||
int J;
|
||||
|
||||
/* Reset state */
|
||||
memcpy(D->R,RegInit,sizeof(D->R));
|
||||
D->EPhase = 0;
|
||||
D->Clock = ClockHz>>4;
|
||||
D->First = First;
|
||||
D->Sync = AY8910_ASYNC;
|
||||
D->Changed = 0x00;
|
||||
D->EPeriod = 0;
|
||||
D->ECount = 0;
|
||||
D->Latch = 0x00;
|
||||
|
||||
/* Set sound types */
|
||||
//SetSound(0+First,SND_MELODIC);
|
||||
//SetSound(1+First,SND_MELODIC);
|
||||
//SetSound(2+First,SND_MELODIC);
|
||||
//SetSound(3+First,SND_NOISE);
|
||||
//SetSound(4+First,SND_NOISE);
|
||||
//SetSound(5+First,SND_NOISE);
|
||||
|
||||
/* Silence all channels */
|
||||
for(J=0;J<AY8910_CHANNELS;J++)
|
||||
{
|
||||
D->Freq[J]=D->Volume[J]=0;
|
||||
#if HAS_SND
|
||||
emu_sndPlaySound(J+First, 0, 0);
|
||||
#endif
|
||||
//Sound(J+First,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
/** WrCtrl8910() *********************************************/
|
||||
/** Write a value V to the PSG Control Port. **/
|
||||
/*************************************************************/
|
||||
void WrCtrl8910(AY8910 *D,byte V)
|
||||
{
|
||||
D->Latch=V&0x0F;
|
||||
}
|
||||
|
||||
/** WrData8910() *********************************************/
|
||||
/** Write a value V to the PSG Data Port. **/
|
||||
/*************************************************************/
|
||||
void WrData8910(AY8910 *D,byte V)
|
||||
{
|
||||
Write8910(D,D->Latch,V);
|
||||
}
|
||||
|
||||
/** RdData8910() *********************************************/
|
||||
/** Read a value from the PSG Data Port. **/
|
||||
/*************************************************************/
|
||||
byte RdData8910(AY8910 *D)
|
||||
{
|
||||
return(D->R[D->Latch]);
|
||||
}
|
||||
|
||||
/** Write8910() **********************************************/
|
||||
/** Call this function to output a value V into the sound **/
|
||||
/** chip. **/
|
||||
/*************************************************************/
|
||||
void Write8910(register AY8910 *D,register byte R,register byte V)
|
||||
{
|
||||
register int J,I;
|
||||
|
||||
switch(R)
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
case 5:
|
||||
V&=0x0F;
|
||||
/* Fall through */
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
/* Write value */
|
||||
D->R[R]=V;
|
||||
/* Exit if the channel is silenced */
|
||||
if(D->R[7]&(1<<(R>>1))) return;
|
||||
/* Go to the first register in the pair */
|
||||
R&=0xFE;
|
||||
/* Compute frequency */
|
||||
J=((int)(D->R[R+1]&0x0F)<<8)+D->R[R];
|
||||
/* Compute channel number */
|
||||
R>>=1;
|
||||
/* Assign frequency */
|
||||
D->Freq[R]=D->Clock/(J? J:0x1000);
|
||||
/* Compute changed channels mask */
|
||||
D->Changed|=1<<R;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
/* Write value */
|
||||
D->R[6]=V&=0x1F;
|
||||
/* Exit if noise channels are silenced */
|
||||
if(!(~D->R[7]&0x38)) return;
|
||||
/* Compute and assign noise frequency */
|
||||
/* Shouldn't do <<2, but need to keep frequency down */
|
||||
J=D->Clock/((V&0x1F? (V&0x1F):0x20)<<2);
|
||||
if(!(D->R[7]&0x08)) D->Freq[3]=J;
|
||||
if(!(D->R[7]&0x10)) D->Freq[4]=J;
|
||||
if(!(D->R[7]&0x20)) D->Freq[5]=J;
|
||||
/* Compute changed channels mask */
|
||||
D->Changed|=0x38&~D->R[7];
|
||||
break;
|
||||
|
||||
case 7:
|
||||
/* Find changed channels */
|
||||
R=(V^D->R[7])&0x3F;
|
||||
D->Changed|=R;
|
||||
/* Write value */
|
||||
D->R[7]=V;
|
||||
/* Update frequencies */
|
||||
for(J=0;R&&(J<AY8910_CHANNELS);J++,R>>=1,V>>=1)
|
||||
if(R&1)
|
||||
{
|
||||
if(V&1) D->Freq[J]=0;
|
||||
else if(J<3)
|
||||
{
|
||||
I=((int)(D->R[J*2+1]&0x0F)<<8)+D->R[J*2];
|
||||
D->Freq[J]=D->Clock/(I? I:0x1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Shouldn't do <<2, but need to keep frequency down */
|
||||
I=D->R[6]&0x1F;
|
||||
D->Freq[J]=D->Clock/((I? I:0x20)<<2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
/* Write value */
|
||||
D->R[R]=V&=0x1F;
|
||||
/* Compute channel number */
|
||||
R-=8;
|
||||
/* Compute and assign new volume */
|
||||
J=Volumes[V&0x10? Envelopes[D->R[13]&0x0F][D->EPhase]:(V&0x0F)];
|
||||
D->Volume[R]=J;
|
||||
D->Volume[R+3]=(J+1)>>1;
|
||||
/* Compute changed channels mask */
|
||||
D->Changed|=(0x09<<R)&~D->R[7];
|
||||
break;
|
||||
|
||||
case 11:
|
||||
case 12:
|
||||
/* Write value */
|
||||
D->R[R]=V;
|
||||
/* Compute envelope period (why not <<4?) */
|
||||
J=((int)D->R[12]<<8)+D->R[11];
|
||||
D->EPeriod=1000*(J? J:0x10000)/D->Clock;
|
||||
/* No channels changed */
|
||||
return;
|
||||
|
||||
case 13:
|
||||
/* Write value */
|
||||
D->R[R]=V&=0x0F;
|
||||
/* Reset envelope */
|
||||
D->ECount = 0;
|
||||
D->EPhase = 0;
|
||||
for(J=0;J<AY8910_CHANNELS/2;++J)
|
||||
if(D->R[J+8]&0x10)
|
||||
{
|
||||
I = Volumes[Envelopes[V][0]];
|
||||
D->Volume[J] = I;
|
||||
D->Volume[J+3] = (I+1)>>1;
|
||||
D->Changed |= (0x09<<J)&~D->R[7];
|
||||
}
|
||||
break;
|
||||
|
||||
case 14:
|
||||
case 15:
|
||||
/* Write value */
|
||||
D->R[R]=V;
|
||||
/* No channels changed */
|
||||
return;
|
||||
|
||||
default:
|
||||
/* Wrong register, do nothing */
|
||||
return;
|
||||
}
|
||||
|
||||
/* For asynchronous mode, make Sound() calls right away */
|
||||
if(!D->Sync&&D->Changed) Sync8910(D,AY8910_FLUSH);
|
||||
}
|
||||
|
||||
/** Loop8910() ***********************************************/
|
||||
/** Call this function periodically to update volume **/
|
||||
/** envelopes. Use mS to pass the time since the last call **/
|
||||
/** of Loop8910() in milliseconds. **/
|
||||
/*************************************************************/
|
||||
void Loop8910(register AY8910 *D,int mS)
|
||||
{
|
||||
register int J,I;
|
||||
|
||||
/* Exit if no envelope running */
|
||||
if(!D->EPeriod) return;
|
||||
|
||||
/* Count milliseconds */
|
||||
D->ECount += mS;
|
||||
if(D->ECount<D->EPeriod) return;
|
||||
|
||||
/* Count steps */
|
||||
J = D->ECount/D->EPeriod;
|
||||
D->ECount -= J*D->EPeriod;
|
||||
|
||||
/* Count phases */
|
||||
D->EPhase += J;
|
||||
if(D->EPhase>31)
|
||||
D->EPhase = (D->R[13]&0x09)==0x08? (D->EPhase&0x1F):31;
|
||||
|
||||
/* Set envelope volumes for relevant channels */
|
||||
for(I=0;I<3;++I)
|
||||
if(D->R[I+8]&0x10)
|
||||
{
|
||||
J = Volumes[Envelopes[D->R[13]&0x0F][D->EPhase]];
|
||||
D->Volume[I] = J;
|
||||
D->Volume[I+3] = (J+1)>>1;
|
||||
D->Changed |= (0x09<<I)&~D->R[7];
|
||||
}
|
||||
|
||||
/* For asynchronous mode, make Sound() calls right away */
|
||||
if(!D->Sync&&D->Changed) Sync8910(D,AY8910_FLUSH);
|
||||
}
|
||||
|
||||
/** Sync8910() ***********************************************/
|
||||
/** Flush all accumulated changes by issuing Sound() calls **/
|
||||
/** and set the synchronization on/off. The second argument **/
|
||||
/** should be AY8910_SYNC/AY8910_ASYNC to set/reset sync, **/
|
||||
/** or AY8910_FLUSH to leave sync mode as it is. To emulate **/
|
||||
/** noise channels with MIDI drums, OR second argument with **/
|
||||
/** AY8910_DRUMS. **/
|
||||
/*************************************************************/
|
||||
void Sync8910(register AY8910 *D,register byte Sync)
|
||||
{
|
||||
register int J,I;
|
||||
|
||||
/* Hit MIDI drums for noise channels, if requested */
|
||||
if(Sync&AY8910_DRUMS)
|
||||
{
|
||||
Sync&=~AY8910_DRUMS;
|
||||
J = (D->Freq[3]? D->Volume[3]:0)
|
||||
+ (D->Freq[4]? D->Volume[4]:0)
|
||||
+ (D->Freq[5]? D->Volume[5]:0);
|
||||
if(J) {
|
||||
//Drum(DRM_MIDI|28,(J+2)/3);
|
||||
}
|
||||
}
|
||||
|
||||
if(Sync!=AY8910_FLUSH) D->Sync=Sync;
|
||||
|
||||
for(J=0,I=D->Changed;I&&(J<AY8910_CHANNELS);J++,I>>=1)
|
||||
if(I&1) {
|
||||
#if HAS_SND
|
||||
emu_sndPlaySound(J+D->First, D->Volume[J], D->Freq[J]);
|
||||
#endif
|
||||
//Sound(J+D->First,D->Freq[J],D->Volume[J]);
|
||||
}
|
||||
|
||||
D->Changed=0x00;
|
||||
}
|
||||
97
MCUME_teensy41/teensyspeccy/AY8910.h
Executable file
97
MCUME_teensy41/teensyspeccy/AY8910.h
Executable file
|
|
@ -0,0 +1,97 @@
|
|||
/** EMULib Emulation Library *********************************/
|
||||
/** **/
|
||||
/** AY8910.h **/
|
||||
/** **/
|
||||
/** This file contains emulation for the AY8910 sound chip **/
|
||||
/** produced by General Instruments, Yamaha, etc. See **/
|
||||
/** AY8910.c for the actual code. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2014 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#ifndef AY8910_H
|
||||
#define AY8910_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AY8910_CHANNELS 6 /* 3 melodic + 3 noise chanls */
|
||||
|
||||
#define AY8910_ASYNC 0 /* Asynchronous emulation */
|
||||
#define AY8910_SYNC 1 /* Synchronous emulation */
|
||||
#define AY8910_FLUSH 2 /* Flush buffers only */
|
||||
#define AY8910_DRUMS 0x80 /* Hit drums for noise chnls */
|
||||
|
||||
#ifndef BYTE_TYPE_DEFINED
|
||||
#define BYTE_TYPE_DEFINED
|
||||
typedef unsigned char byte;
|
||||
#endif
|
||||
|
||||
/** AY8910 ***************************************************/
|
||||
/** This data structure stores AY8910 state. **/
|
||||
/*************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
byte R[16]; /* PSG registers contents */
|
||||
int Freq[AY8910_CHANNELS]; /* Frequencies (0 for off) */
|
||||
int Volume[AY8910_CHANNELS]; /* Volumes (0..255) */
|
||||
int Clock; /* Base clock used by PSG */
|
||||
int First; /* First used Sound() channel */
|
||||
byte Changed; /* Bitmap of changed channels */
|
||||
byte Sync; /* AY8910_SYNC/AY8910_ASYNC */
|
||||
byte Latch; /* Latch for the register num */
|
||||
int EPeriod; /* Envelope step in msecs */
|
||||
int ECount; /* Envelope step counter */
|
||||
int EPhase; /* Envelope phase */
|
||||
} AY8910;
|
||||
|
||||
/** Reset8910() **********************************************/
|
||||
/** Reset the sound chip and use sound channels from the **/
|
||||
/** one given in First. **/
|
||||
/*************************************************************/
|
||||
void Reset8910(register AY8910 *D,int ClockHz,int First);
|
||||
|
||||
/** Write8910() **********************************************/
|
||||
/** Call this function to output a value V into the sound **/
|
||||
/** chip. **/
|
||||
/*************************************************************/
|
||||
void Write8910(register AY8910 *D,register byte R,register byte V);
|
||||
|
||||
/** WrCtrl8910() *********************************************/
|
||||
/** Write a value V to the PSG Control Port. **/
|
||||
/*************************************************************/
|
||||
void WrCtrl8910(AY8910 *D,byte V);
|
||||
|
||||
/** WrData8910() *********************************************/
|
||||
/** Write a value V to the PSG Data Port. **/
|
||||
/*************************************************************/
|
||||
void WrData8910(AY8910 *D,byte V);
|
||||
|
||||
/** RdData8910() *********************************************/
|
||||
/** Read a value from the PSG Data Port. **/
|
||||
/*************************************************************/
|
||||
byte RdData8910(AY8910 *D);
|
||||
|
||||
/** Sync8910() ***********************************************/
|
||||
/** Flush all accumulated changes by issuing Sound() calls **/
|
||||
/** and set the synchronization on/off. The second argument **/
|
||||
/** should be AY8910_SYNC/AY8910_ASYNC to set/reset sync, **/
|
||||
/** or AY8910_FLUSH to leave sync mode as it is. To emulate **/
|
||||
/** noise channels with MIDI drums, OR second argument with **/
|
||||
/** AY8910_DRUMS. **/
|
||||
/*************************************************************/
|
||||
void Sync8910(register AY8910 *D,register byte Sync);
|
||||
|
||||
/** Loop8910() ***********************************************/
|
||||
/** Call this function periodically to update volume **/
|
||||
/** envelopes. Use mS to pass the time since the last call **/
|
||||
/** of Loop8910() in milliseconds. **/
|
||||
/*************************************************************/
|
||||
void Loop8910(register AY8910 *D,int mS);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* AY8910_H */
|
||||
361
MCUME_teensy41/teensyspeccy/AudioPlaySystem.cpp
Normal file
361
MCUME_teensy41/teensyspeccy/AudioPlaySystem.cpp
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
#include "emuapi.h"
|
||||
|
||||
#ifdef HAS_SND
|
||||
|
||||
#include "AudioPlaySystem.h"
|
||||
#include <Arduino.h>
|
||||
#define SAMPLERATE AUDIO_SAMPLE_RATE_EXACT
|
||||
#define CLOCKFREQ 985248
|
||||
|
||||
#ifndef CUSTOM_SND
|
||||
PROGMEM static const short square[]={
|
||||
32767,32767,32767,32767,
|
||||
32767,32767,32767,32767,
|
||||
32767,32767,32767,32767,
|
||||
32767,32767,32767,32767,
|
||||
32767,32767,32767,32767,
|
||||
32767,32767,32767,32767,
|
||||
32767,32767,32767,32767,
|
||||
32767,32767,32767,32767,
|
||||
-32767,-32767,-32767,-32767,
|
||||
-32767,-32767,-32767,-32767,
|
||||
-32767,-32767,-32767,-32767,
|
||||
-32767,-32767,-32767,-32767,
|
||||
-32767,-32767,-32767,-32767,
|
||||
-32767,-32767,-32767,-32767,
|
||||
-32767,-32767,-32767,-32767,
|
||||
-32767,-32767,-32767,-32767,
|
||||
};
|
||||
|
||||
PROGMEM const short noise[] {
|
||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,
|
||||
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,32767,-32767,
|
||||
-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,
|
||||
-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,32767,32767,-32767,
|
||||
-32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,-32767,32767,32767,-32767,
|
||||
-32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767,
|
||||
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767,
|
||||
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
|
||||
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
|
||||
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,-32767,-32767,
|
||||
32767,-32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
|
||||
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767,-32767,
|
||||
32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
|
||||
32767,-32767,32767,-32767,-32767,32767,32767,-32767,32767,32767,-32767,32767,-32767,32767,-32767,-32767,
|
||||
32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
|
||||
32767,-32767,32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,32767,-32767,32767,-32767,-32767,
|
||||
};
|
||||
|
||||
#define NOISEBSIZE 0x100
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int spos;
|
||||
unsigned int sinc;
|
||||
unsigned int vol;
|
||||
} Channel;
|
||||
|
||||
static Channel chan[6] = {
|
||||
{0,0,0},
|
||||
{0,0,0},
|
||||
{0,0,0},
|
||||
{0,0,0},
|
||||
{0,0,0},
|
||||
{0,0,0} };
|
||||
|
||||
#endif
|
||||
|
||||
volatile bool playing = false;
|
||||
|
||||
|
||||
static void snd_Reset(void)
|
||||
{
|
||||
#ifndef CUSTOM_SND
|
||||
chan[0].vol = 0;
|
||||
chan[1].vol = 0;
|
||||
chan[2].vol = 0;
|
||||
chan[3].vol = 0;
|
||||
chan[4].vol = 0;
|
||||
chan[5].vol = 0;
|
||||
chan[0].sinc = 0;
|
||||
chan[1].sinc = 0;
|
||||
chan[2].sinc = 0;
|
||||
chan[3].sinc = 0;
|
||||
chan[4].sinc = 0;
|
||||
chan[5].sinc = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef CUSTOM_SND
|
||||
//extern "C" {
|
||||
void SND_Process(void *sndbuffer, int sndn);
|
||||
//}
|
||||
#endif
|
||||
|
||||
|
||||
FASTRUN void AudioPlaySystem::snd_Mixer(short * stream, int len )
|
||||
{
|
||||
if (playing)
|
||||
{
|
||||
#ifdef CUSTOM_SND
|
||||
SND_Process((void*)stream, len);
|
||||
#else
|
||||
int i;
|
||||
long s;
|
||||
len = len >> 1;
|
||||
short v0=chan[0].vol;
|
||||
short v1=chan[1].vol;
|
||||
short v2=chan[2].vol;
|
||||
short v3=chan[3].vol;
|
||||
short v4=chan[4].vol;
|
||||
short v5=chan[5].vol;
|
||||
for (i=0;i<len;i++)
|
||||
{
|
||||
s =((v0*square[(chan[0].spos>>8)&0x3f])>>11);
|
||||
s+=((v1*square[(chan[1].spos>>8)&0x3f])>>11);
|
||||
s+=((v2*square[(chan[2].spos>>8)&0x3f])>>11);
|
||||
s+=((v3*noise[(chan[3].spos>>8)&(NOISEBSIZE-1)])>>11);
|
||||
s+=((v4*noise[(chan[4].spos>>8)&(NOISEBSIZE-1)])>>11);
|
||||
s+=((v5*noise[(chan[5].spos>>8)&(NOISEBSIZE-1)])>>11);
|
||||
*stream++ = (short)(s);
|
||||
*stream++ = (short)(s);
|
||||
chan[0].spos += chan[0].sinc;
|
||||
chan[1].spos += chan[1].sinc;
|
||||
chan[2].spos += chan[2].sinc;
|
||||
chan[3].spos += chan[3].sinc;
|
||||
chan[4].spos += chan[4].sinc;
|
||||
chan[5].spos += chan[5].sinc;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void AudioPlaySystem::begin(void)
|
||||
{
|
||||
this->reset();
|
||||
}
|
||||
|
||||
void AudioPlaySystem::start(void)
|
||||
{
|
||||
playing = true;
|
||||
}
|
||||
|
||||
void AudioPlaySystem::setSampleParameters(float clockfreq, float samplerate) {
|
||||
}
|
||||
|
||||
void AudioPlaySystem::reset(void)
|
||||
{
|
||||
snd_Reset();
|
||||
}
|
||||
|
||||
void AudioPlaySystem::stop(void)
|
||||
{
|
||||
//__disable_irq();
|
||||
playing = false;
|
||||
//__enable_irq();
|
||||
}
|
||||
|
||||
bool AudioPlaySystem::isPlaying(void)
|
||||
{
|
||||
return playing;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AudioPlaySystem::sound(int C, int F, int V) {
|
||||
#ifndef CUSTOM_SND
|
||||
if (C < 6) {
|
||||
chan[C].vol = V;
|
||||
chan[C].sinc = F>>1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioPlaySystem::step(void) {
|
||||
}
|
||||
|
||||
|
||||
#ifndef HAS_T4_VGA
|
||||
/*******************************************************************
|
||||
Experimental I2S interrupt based sound driver for PCM51xx !!!
|
||||
*******************************************************************/
|
||||
|
||||
FLASHMEM static void set_audioClock(int nfact, int32_t nmult, uint32_t ndiv, bool force) // sets PLL4
|
||||
{
|
||||
if (!force && (CCM_ANALOG_PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_ENABLE)) return;
|
||||
|
||||
CCM_ANALOG_PLL_AUDIO = CCM_ANALOG_PLL_AUDIO_BYPASS | CCM_ANALOG_PLL_AUDIO_ENABLE
|
||||
| CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2) // 2: 1/4; 1: 1/2; 0: 1/1
|
||||
| CCM_ANALOG_PLL_AUDIO_DIV_SELECT(nfact);
|
||||
|
||||
CCM_ANALOG_PLL_AUDIO_NUM = nmult & CCM_ANALOG_PLL_AUDIO_NUM_MASK;
|
||||
CCM_ANALOG_PLL_AUDIO_DENOM = ndiv & CCM_ANALOG_PLL_AUDIO_DENOM_MASK;
|
||||
|
||||
CCM_ANALOG_PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_POWERDOWN;//Switch on PLL
|
||||
while (!(CCM_ANALOG_PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK)) {}; //Wait for pll-lock
|
||||
|
||||
const int div_post_pll = 1; // other values: 2,4
|
||||
CCM_ANALOG_MISC2 &= ~(CCM_ANALOG_MISC2_DIV_MSB | CCM_ANALOG_MISC2_DIV_LSB);
|
||||
if(div_post_pll>1) CCM_ANALOG_MISC2 |= CCM_ANALOG_MISC2_DIV_LSB;
|
||||
if(div_post_pll>3) CCM_ANALOG_MISC2 |= CCM_ANALOG_MISC2_DIV_MSB;
|
||||
|
||||
CCM_ANALOG_PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_BYPASS;//Disable Bypass
|
||||
}
|
||||
|
||||
#define AUDIO_SAMPLE_RATE_EXACT 11025.0 //44117.64706 //11025.0 //22050.0 //44117.64706 //31778.0
|
||||
|
||||
FLASHMEM static void config_sai1()
|
||||
{
|
||||
CCM_CCGR5 |= CCM_CCGR5_SAI1(CCM_CCGR_ON);
|
||||
double fs = AUDIO_SAMPLE_RATE_EXACT;
|
||||
// PLL between 27*24 = 648MHz und 54*24=1296MHz
|
||||
int n1 = 4; //SAI prescaler 4 => (n1*n2) = multiple of 4
|
||||
int n2 = 1 + (24000000 * 27) / (fs * 256 * n1);
|
||||
double C = (fs * 256 * n1 * n2) / 24000000;
|
||||
int c0 = C;
|
||||
int c2 = 10000;
|
||||
int c1 = C * c2 - (c0 * c2);
|
||||
|
||||
set_audioClock(c0, c1, c2, true);
|
||||
// clear SAI1_CLK register locations
|
||||
CCM_CSCMR1 = (CCM_CSCMR1 & ~(CCM_CSCMR1_SAI1_CLK_SEL_MASK))
|
||||
| CCM_CSCMR1_SAI1_CLK_SEL(2); // &0x03 // (0,1,2): PLL3PFD0, PLL5, PLL4
|
||||
|
||||
n1 = n1 / 2; //Double Speed for TDM
|
||||
|
||||
CCM_CS1CDR = (CCM_CS1CDR & ~(CCM_CS1CDR_SAI1_CLK_PRED_MASK | CCM_CS1CDR_SAI1_CLK_PODF_MASK))
|
||||
| CCM_CS1CDR_SAI1_CLK_PRED(n1 - 1) // &0x07
|
||||
| CCM_CS1CDR_SAI1_CLK_PODF(n2 - 1); // &0x3f
|
||||
|
||||
IOMUXC_GPR_GPR1 = (IOMUXC_GPR_GPR1 & ~(IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL_MASK))
|
||||
| (IOMUXC_GPR_GPR1_SAI1_MCLK_DIR | IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL(0)); //Select MCLK
|
||||
|
||||
|
||||
// configure transmitter
|
||||
int rsync = 0;
|
||||
int tsync = 1;
|
||||
|
||||
I2S1_TMR = 0;
|
||||
I2S1_TCR1 = I2S_TCR1_RFW(1);
|
||||
I2S1_TCR2 = I2S_TCR2_SYNC(tsync) | I2S_TCR2_BCP // sync=0; tx is async;
|
||||
| (I2S_TCR2_BCD | I2S_TCR2_DIV((1)) | I2S_TCR2_MSEL(1));
|
||||
I2S1_TCR3 = I2S_TCR3_TCE;
|
||||
I2S1_TCR4 = I2S_TCR4_FRSZ((2-1)) | I2S_TCR4_SYWD((32-1)) | I2S_TCR4_MF
|
||||
| I2S_TCR4_FSD | I2S_TCR4_FSE | I2S_TCR4_FSP;
|
||||
I2S1_TCR5 = I2S_TCR5_WNW((32-1)) | I2S_TCR5_W0W((32-1)) | I2S_TCR5_FBT((32-1));
|
||||
|
||||
|
||||
I2S1_RMR = 0;
|
||||
I2S1_RCR1 = I2S_RCR1_RFW(1);
|
||||
I2S1_RCR2 = I2S_RCR2_SYNC(rsync) | I2S_RCR2_BCP // sync=0; rx is async;
|
||||
| (I2S_RCR2_BCD | I2S_RCR2_DIV((1)) | I2S_RCR2_MSEL(1));
|
||||
I2S1_RCR3 = I2S_RCR3_RCE;
|
||||
I2S1_RCR4 = I2S_RCR4_FRSZ((2-1)) | I2S_RCR4_SYWD((32-1)) | I2S_RCR4_MF
|
||||
| I2S_RCR4_FSE | I2S_RCR4_FSP | I2S_RCR4_FSD;
|
||||
I2S1_RCR5 = I2S_RCR5_WNW((32-1)) | I2S_RCR5_W0W((32-1)) | I2S_RCR5_FBT((32-1));
|
||||
|
||||
//CORE_PIN23_CONFIG = 3; // MCLK
|
||||
CORE_PIN21_CONFIG = 3; // RX_BCLK
|
||||
CORE_PIN20_CONFIG = 3; // RX_SYNC
|
||||
CORE_PIN7_CONFIG = 3; // TX_DATA0
|
||||
I2S1_RCSR |= I2S_RCSR_RE | I2S_RCSR_BCE;
|
||||
I2S1_TCSR = I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FRDE ;//<-- not using DMA */;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//DMAMEM __attribute__((aligned(32))) static uint32_t i2s_tx[1024];
|
||||
|
||||
static bool fillfirsthalf = true;
|
||||
static uint16_t cnt = 0;
|
||||
static uint16_t sampleBufferSize = 0;
|
||||
|
||||
static void (*fillsamples)(short * stream, int len) = nullptr;
|
||||
|
||||
static uint32_t * i2s_tx_buffer __attribute__((aligned(32)));
|
||||
static uint16_t * i2s_tx_buffer16;
|
||||
static uint16_t * txreg = (uint16_t *)((uint32_t)&I2S1_TDR0 + 2);
|
||||
|
||||
|
||||
FASTRUN void AudioPlaySystem::AUDIO_isr() {
|
||||
|
||||
*txreg = i2s_tx_buffer16[cnt];
|
||||
cnt = cnt + 1;
|
||||
cnt = cnt & (sampleBufferSize*2-1);
|
||||
|
||||
if (cnt == 0) {
|
||||
fillfirsthalf = false;
|
||||
NVIC_SET_PENDING(IRQ_SOFTWARE);
|
||||
}
|
||||
else if (cnt == sampleBufferSize) {
|
||||
fillfirsthalf = true;
|
||||
NVIC_SET_PENDING(IRQ_SOFTWARE);
|
||||
}
|
||||
/*
|
||||
I2S1_TDR0 = i2s_tx_buffer[cnt];
|
||||
cnt = cnt + 1;
|
||||
cnt = cnt & (sampleBufferSize-1);
|
||||
if (cnt == 0) {
|
||||
fillfirsthalf = false;
|
||||
NVIC_SET_PENDING(IRQ_SOFTWARE);
|
||||
}
|
||||
else if (cnt == sampleBufferSize/2) {
|
||||
fillfirsthalf = true;
|
||||
NVIC_SET_PENDING(IRQ_SOFTWARE);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
FASTRUN void AudioPlaySystem::SOFTWARE_isr() {
|
||||
//Serial.println("x");
|
||||
if (fillfirsthalf) {
|
||||
fillsamples((short *)i2s_tx_buffer, sampleBufferSize);
|
||||
arm_dcache_flush_delete((void*)i2s_tx_buffer, (sampleBufferSize/2)*sizeof(uint32_t));
|
||||
}
|
||||
else {
|
||||
fillsamples((short *)&i2s_tx_buffer[sampleBufferSize/2], sampleBufferSize);
|
||||
arm_dcache_flush_delete((void*)&i2s_tx_buffer[sampleBufferSize/2], (sampleBufferSize/2)*sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
// display VGA image
|
||||
FLASHMEM void AudioPlaySystem::begin_audio(int samplesize, void (*callback)(short * stream, int len))
|
||||
{
|
||||
fillsamples = callback;
|
||||
i2s_tx_buffer = (uint32_t*)malloc(samplesize*sizeof(uint32_t)); //&i2s_tx[0];
|
||||
|
||||
if (i2s_tx_buffer == NULL) {
|
||||
Serial.println("could not allocate audio samples");
|
||||
return;
|
||||
}
|
||||
memset((void*)i2s_tx_buffer,0, samplesize*sizeof(uint32_t));
|
||||
arm_dcache_flush_delete((void*)i2s_tx_buffer, samplesize*sizeof(uint32_t));
|
||||
i2s_tx_buffer16 = (uint16_t*)i2s_tx_buffer;
|
||||
|
||||
sampleBufferSize = samplesize;
|
||||
|
||||
config_sai1();
|
||||
attachInterruptVector(IRQ_SAI1, AUDIO_isr);
|
||||
NVIC_ENABLE_IRQ(IRQ_SAI1);
|
||||
NVIC_SET_PRIORITY(IRQ_QTIMER3, 0); // 0 highest priority, 255 = lowest priority
|
||||
NVIC_SET_PRIORITY(IRQ_SAI1, 127);
|
||||
attachInterruptVector(IRQ_SOFTWARE, SOFTWARE_isr);
|
||||
NVIC_SET_PRIORITY(IRQ_SOFTWARE, 208);
|
||||
NVIC_ENABLE_IRQ(IRQ_SOFTWARE);
|
||||
|
||||
I2S1_TCSR |= 1<<8; // start generating TX FIFO interrupts
|
||||
|
||||
Serial.print("Audio sample buffer = ");
|
||||
Serial.println(samplesize);
|
||||
}
|
||||
|
||||
FLASHMEM void AudioPlaySystem::end_audio()
|
||||
{
|
||||
if (i2s_tx_buffer != NULL) {
|
||||
free(i2s_tx_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
34
MCUME_teensy41/teensyspeccy/AudioPlaySystem.h
Normal file
34
MCUME_teensy41/teensyspeccy/AudioPlaySystem.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef audioplaysystem_h_
|
||||
#define audioplaysystem_h_
|
||||
|
||||
#ifdef HAS_SND
|
||||
|
||||
#include "platform_config.h"
|
||||
|
||||
class AudioPlaySystem
|
||||
{
|
||||
public:
|
||||
AudioPlaySystem(void) { };
|
||||
void begin(void);
|
||||
void setSampleParameters(float clockfreq, float samplerate);
|
||||
void reset(void);
|
||||
void start(void);
|
||||
void stop(void);
|
||||
bool isPlaying(void);
|
||||
void sound(int C, int F, int V);
|
||||
void buzz(int size, int val);
|
||||
void step(void);
|
||||
static void snd_Mixer(short * stream, int len );
|
||||
#ifndef HAS_T4_VGA
|
||||
void begin_audio(int samplesize, void (*callback)(short * stream, int len));
|
||||
void end_audio();
|
||||
static void AUDIO_isr(void);
|
||||
static void SOFTWARE_isr(void);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
385
MCUME_teensy41/teensyspeccy/Codes.h
Executable file
385
MCUME_teensy41/teensyspeccy/Codes.h
Executable file
|
|
@ -0,0 +1,385 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Codes.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for the main table of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case JR_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
|
||||
case JR_NC: if(R->AF.B.l&C_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
|
||||
case JR_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
|
||||
case JR_C: if(R->AF.B.l&C_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
|
||||
|
||||
case JP_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_Z: if(R->AF.B.l&Z_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_C: if(R->AF.B.l&C_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_PE: if(R->AF.B.l&P_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_M: if(R->AF.B.l&S_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
|
||||
case RET_NZ: if(!(R->AF.B.l&Z_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_NC: if(!(R->AF.B.l&C_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_PO: if(!(R->AF.B.l&P_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_P: if(!(R->AF.B.l&S_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_C: if(R->AF.B.l&C_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_M: if(R->AF.B.l&S_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
|
||||
case CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_C: if(R->AF.B.l&C_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_M: if(R->AF.B.l&S_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
|
||||
case ADD_B: M_ADD(R->BC.B.h);break;
|
||||
case ADD_C: M_ADD(R->BC.B.l);break;
|
||||
case ADD_D: M_ADD(R->DE.B.h);break;
|
||||
case ADD_E: M_ADD(R->DE.B.l);break;
|
||||
case ADD_H: M_ADD(R->HL.B.h);break;
|
||||
case ADD_L: M_ADD(R->HL.B.l);break;
|
||||
case ADD_A: M_ADD(R->AF.B.h);break;
|
||||
case ADD_xHL: I=RdZ80(R->HL.W);M_ADD(I);break;
|
||||
case ADD_BYTE: I=OpZ80(R->PC.W++);M_ADD(I);break;
|
||||
|
||||
case SUB_B: M_SUB(R->BC.B.h);break;
|
||||
case SUB_C: M_SUB(R->BC.B.l);break;
|
||||
case SUB_D: M_SUB(R->DE.B.h);break;
|
||||
case SUB_E: M_SUB(R->DE.B.l);break;
|
||||
case SUB_H: M_SUB(R->HL.B.h);break;
|
||||
case SUB_L: M_SUB(R->HL.B.l);break;
|
||||
case SUB_A: R->AF.B.h=0;R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case SUB_xHL: I=RdZ80(R->HL.W);M_SUB(I);break;
|
||||
case SUB_BYTE: I=OpZ80(R->PC.W++);M_SUB(I);break;
|
||||
|
||||
case AND_B: M_AND(R->BC.B.h);break;
|
||||
case AND_C: M_AND(R->BC.B.l);break;
|
||||
case AND_D: M_AND(R->DE.B.h);break;
|
||||
case AND_E: M_AND(R->DE.B.l);break;
|
||||
case AND_H: M_AND(R->HL.B.h);break;
|
||||
case AND_L: M_AND(R->HL.B.l);break;
|
||||
case AND_A: M_AND(R->AF.B.h);break;
|
||||
case AND_xHL: I=RdZ80(R->HL.W);M_AND(I);break;
|
||||
case AND_BYTE: I=OpZ80(R->PC.W++);M_AND(I);break;
|
||||
|
||||
case OR_B: M_OR(R->BC.B.h);break;
|
||||
case OR_C: M_OR(R->BC.B.l);break;
|
||||
case OR_D: M_OR(R->DE.B.h);break;
|
||||
case OR_E: M_OR(R->DE.B.l);break;
|
||||
case OR_H: M_OR(R->HL.B.h);break;
|
||||
case OR_L: M_OR(R->HL.B.l);break;
|
||||
case OR_A: M_OR(R->AF.B.h);break;
|
||||
case OR_xHL: I=RdZ80(R->HL.W);M_OR(I);break;
|
||||
case OR_BYTE: I=OpZ80(R->PC.W++);M_OR(I);break;
|
||||
|
||||
case ADC_B: M_ADC(R->BC.B.h);break;
|
||||
case ADC_C: M_ADC(R->BC.B.l);break;
|
||||
case ADC_D: M_ADC(R->DE.B.h);break;
|
||||
case ADC_E: M_ADC(R->DE.B.l);break;
|
||||
case ADC_H: M_ADC(R->HL.B.h);break;
|
||||
case ADC_L: M_ADC(R->HL.B.l);break;
|
||||
case ADC_A: M_ADC(R->AF.B.h);break;
|
||||
case ADC_xHL: I=RdZ80(R->HL.W);M_ADC(I);break;
|
||||
case ADC_BYTE: I=OpZ80(R->PC.W++);M_ADC(I);break;
|
||||
|
||||
case SBC_B: M_SBC(R->BC.B.h);break;
|
||||
case SBC_C: M_SBC(R->BC.B.l);break;
|
||||
case SBC_D: M_SBC(R->DE.B.h);break;
|
||||
case SBC_E: M_SBC(R->DE.B.l);break;
|
||||
case SBC_H: M_SBC(R->HL.B.h);break;
|
||||
case SBC_L: M_SBC(R->HL.B.l);break;
|
||||
case SBC_A: M_SBC(R->AF.B.h);break;
|
||||
case SBC_xHL: I=RdZ80(R->HL.W);M_SBC(I);break;
|
||||
case SBC_BYTE: I=OpZ80(R->PC.W++);M_SBC(I);break;
|
||||
|
||||
case XOR_B: M_XOR(R->BC.B.h);break;
|
||||
case XOR_C: M_XOR(R->BC.B.l);break;
|
||||
case XOR_D: M_XOR(R->DE.B.h);break;
|
||||
case XOR_E: M_XOR(R->DE.B.l);break;
|
||||
case XOR_H: M_XOR(R->HL.B.h);break;
|
||||
case XOR_L: M_XOR(R->HL.B.l);break;
|
||||
case XOR_A: R->AF.B.h=0;R->AF.B.l=P_FLAG|Z_FLAG;break;
|
||||
case XOR_xHL: I=RdZ80(R->HL.W);M_XOR(I);break;
|
||||
case XOR_BYTE: I=OpZ80(R->PC.W++);M_XOR(I);break;
|
||||
|
||||
case CP_B: M_CP(R->BC.B.h);break;
|
||||
case CP_C: M_CP(R->BC.B.l);break;
|
||||
case CP_D: M_CP(R->DE.B.h);break;
|
||||
case CP_E: M_CP(R->DE.B.l);break;
|
||||
case CP_H: M_CP(R->HL.B.h);break;
|
||||
case CP_L: M_CP(R->HL.B.l);break;
|
||||
case CP_A: R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case CP_xHL: I=RdZ80(R->HL.W);M_CP(I);break;
|
||||
case CP_BYTE: I=OpZ80(R->PC.W++);M_CP(I);break;
|
||||
|
||||
case LD_BC_WORD: M_LDWORD(BC);break;
|
||||
case LD_DE_WORD: M_LDWORD(DE);break;
|
||||
case LD_HL_WORD: M_LDWORD(HL);break;
|
||||
case LD_SP_WORD: M_LDWORD(SP);break;
|
||||
|
||||
case LD_PC_HL: R->PC.W=R->HL.W;JumpZ80(R->PC.W);break;
|
||||
case LD_SP_HL: R->SP.W=R->HL.W;break;
|
||||
case LD_A_xBC: R->AF.B.h=RdZ80(R->BC.W);break;
|
||||
case LD_A_xDE: R->AF.B.h=RdZ80(R->DE.W);break;
|
||||
|
||||
case ADD_HL_BC: M_ADDW(HL,BC);break;
|
||||
case ADD_HL_DE: M_ADDW(HL,DE);break;
|
||||
case ADD_HL_HL: M_ADDW(HL,HL);break;
|
||||
case ADD_HL_SP: M_ADDW(HL,SP);break;
|
||||
|
||||
case DEC_BC: R->BC.W--;break;
|
||||
case DEC_DE: R->DE.W--;break;
|
||||
case DEC_HL: R->HL.W--;break;
|
||||
case DEC_SP: R->SP.W--;break;
|
||||
|
||||
case INC_BC: R->BC.W++;break;
|
||||
case INC_DE: R->DE.W++;break;
|
||||
case INC_HL: R->HL.W++;break;
|
||||
case INC_SP: R->SP.W++;break;
|
||||
|
||||
case DEC_B: M_DEC(R->BC.B.h);break;
|
||||
case DEC_C: M_DEC(R->BC.B.l);break;
|
||||
case DEC_D: M_DEC(R->DE.B.h);break;
|
||||
case DEC_E: M_DEC(R->DE.B.l);break;
|
||||
case DEC_H: M_DEC(R->HL.B.h);break;
|
||||
case DEC_L: M_DEC(R->HL.B.l);break;
|
||||
case DEC_A: M_DEC(R->AF.B.h);break;
|
||||
case DEC_xHL: I=RdZ80(R->HL.W);M_DEC(I);WrZ80(R->HL.W,I);break;
|
||||
|
||||
case INC_B: M_INC(R->BC.B.h);break;
|
||||
case INC_C: M_INC(R->BC.B.l);break;
|
||||
case INC_D: M_INC(R->DE.B.h);break;
|
||||
case INC_E: M_INC(R->DE.B.l);break;
|
||||
case INC_H: M_INC(R->HL.B.h);break;
|
||||
case INC_L: M_INC(R->HL.B.l);break;
|
||||
case INC_A: M_INC(R->AF.B.h);break;
|
||||
case INC_xHL: I=RdZ80(R->HL.W);M_INC(I);WrZ80(R->HL.W,I);break;
|
||||
|
||||
case RLCA:
|
||||
I=R->AF.B.h&0x80? C_FLAG:0;
|
||||
R->AF.B.h=(R->AF.B.h<<1)|I;
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RLA:
|
||||
I=R->AF.B.h&0x80? C_FLAG:0;
|
||||
R->AF.B.h=(R->AF.B.h<<1)|(R->AF.B.l&C_FLAG);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRCA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(I? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(R->AF.B.l&C_FLAG? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
|
||||
case RST00: M_RST(0x0000);break;
|
||||
case RST08: M_RST(0x0008);break;
|
||||
case RST10: M_RST(0x0010);break;
|
||||
case RST18: M_RST(0x0018);break;
|
||||
case RST20: M_RST(0x0020);break;
|
||||
case RST28: M_RST(0x0028);break;
|
||||
case RST30: M_RST(0x0030);break;
|
||||
case RST38: M_RST(0x0038);break;
|
||||
|
||||
case PUSH_BC: M_PUSH(BC);break;
|
||||
case PUSH_DE: M_PUSH(DE);break;
|
||||
case PUSH_HL: M_PUSH(HL);break;
|
||||
case PUSH_AF: M_PUSH(AF);break;
|
||||
|
||||
case POP_BC: M_POP(BC);break;
|
||||
case POP_DE: M_POP(DE);break;
|
||||
case POP_HL: M_POP(HL);break;
|
||||
case POP_AF: M_POP(AF);break;
|
||||
|
||||
case DJNZ: if(--R->BC.B.h) { R->ICount-=5;M_JR; } else R->PC.W++;break;
|
||||
case JP: M_JP;break;
|
||||
case JR: M_JR;break;
|
||||
case CALL: M_CALL;break;
|
||||
case RET: M_RET;break;
|
||||
case SCF: S(C_FLAG);R(N_FLAG|H_FLAG);break;
|
||||
case CPL: R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break;
|
||||
case NOP: break;
|
||||
case OUTA: I=OpZ80(R->PC.W++);OutZ80(I|(R->AF.W&0xFF00),R->AF.B.h);break;
|
||||
case INA: I=OpZ80(R->PC.W++);R->AF.B.h=InZ80(I|(R->AF.W&0xFF00));break;
|
||||
|
||||
case HALT:
|
||||
R->PC.W--;
|
||||
R->IFF|=IFF_HALT;
|
||||
R->IBackup=0;
|
||||
R->ICount=0;
|
||||
break;
|
||||
|
||||
case DI:
|
||||
if(R->IFF&IFF_EI) R->ICount+=R->IBackup-1;
|
||||
R->IFF&=~(IFF_1|IFF_2|IFF_EI);
|
||||
break;
|
||||
|
||||
case EI:
|
||||
if(!(R->IFF&(IFF_1|IFF_EI)))
|
||||
{
|
||||
R->IFF|=IFF_2|IFF_EI;
|
||||
R->IBackup=R->ICount;
|
||||
R->ICount=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CCF:
|
||||
R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG);
|
||||
R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG;
|
||||
break;
|
||||
|
||||
case EXX:
|
||||
J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W;
|
||||
J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W;
|
||||
J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W;
|
||||
break;
|
||||
|
||||
case EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break;
|
||||
case EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break;
|
||||
|
||||
case LD_B_B: R->BC.B.h=R->BC.B.h;break;
|
||||
case LD_C_B: R->BC.B.l=R->BC.B.h;break;
|
||||
case LD_D_B: R->DE.B.h=R->BC.B.h;break;
|
||||
case LD_E_B: R->DE.B.l=R->BC.B.h;break;
|
||||
case LD_H_B: R->HL.B.h=R->BC.B.h;break;
|
||||
case LD_L_B: R->HL.B.l=R->BC.B.h;break;
|
||||
case LD_A_B: R->AF.B.h=R->BC.B.h;break;
|
||||
case LD_xHL_B: WrZ80(R->HL.W,R->BC.B.h);break;
|
||||
|
||||
case LD_B_C: R->BC.B.h=R->BC.B.l;break;
|
||||
case LD_C_C: R->BC.B.l=R->BC.B.l;break;
|
||||
case LD_D_C: R->DE.B.h=R->BC.B.l;break;
|
||||
case LD_E_C: R->DE.B.l=R->BC.B.l;break;
|
||||
case LD_H_C: R->HL.B.h=R->BC.B.l;break;
|
||||
case LD_L_C: R->HL.B.l=R->BC.B.l;break;
|
||||
case LD_A_C: R->AF.B.h=R->BC.B.l;break;
|
||||
case LD_xHL_C: WrZ80(R->HL.W,R->BC.B.l);break;
|
||||
|
||||
case LD_B_D: R->BC.B.h=R->DE.B.h;break;
|
||||
case LD_C_D: R->BC.B.l=R->DE.B.h;break;
|
||||
case LD_D_D: R->DE.B.h=R->DE.B.h;break;
|
||||
case LD_E_D: R->DE.B.l=R->DE.B.h;break;
|
||||
case LD_H_D: R->HL.B.h=R->DE.B.h;break;
|
||||
case LD_L_D: R->HL.B.l=R->DE.B.h;break;
|
||||
case LD_A_D: R->AF.B.h=R->DE.B.h;break;
|
||||
case LD_xHL_D: WrZ80(R->HL.W,R->DE.B.h);break;
|
||||
|
||||
case LD_B_E: R->BC.B.h=R->DE.B.l;break;
|
||||
case LD_C_E: R->BC.B.l=R->DE.B.l;break;
|
||||
case LD_D_E: R->DE.B.h=R->DE.B.l;break;
|
||||
case LD_E_E: R->DE.B.l=R->DE.B.l;break;
|
||||
case LD_H_E: R->HL.B.h=R->DE.B.l;break;
|
||||
case LD_L_E: R->HL.B.l=R->DE.B.l;break;
|
||||
case LD_A_E: R->AF.B.h=R->DE.B.l;break;
|
||||
case LD_xHL_E: WrZ80(R->HL.W,R->DE.B.l);break;
|
||||
|
||||
case LD_B_H: R->BC.B.h=R->HL.B.h;break;
|
||||
case LD_C_H: R->BC.B.l=R->HL.B.h;break;
|
||||
case LD_D_H: R->DE.B.h=R->HL.B.h;break;
|
||||
case LD_E_H: R->DE.B.l=R->HL.B.h;break;
|
||||
case LD_H_H: R->HL.B.h=R->HL.B.h;break;
|
||||
case LD_L_H: R->HL.B.l=R->HL.B.h;break;
|
||||
case LD_A_H: R->AF.B.h=R->HL.B.h;break;
|
||||
case LD_xHL_H: WrZ80(R->HL.W,R->HL.B.h);break;
|
||||
|
||||
case LD_B_L: R->BC.B.h=R->HL.B.l;break;
|
||||
case LD_C_L: R->BC.B.l=R->HL.B.l;break;
|
||||
case LD_D_L: R->DE.B.h=R->HL.B.l;break;
|
||||
case LD_E_L: R->DE.B.l=R->HL.B.l;break;
|
||||
case LD_H_L: R->HL.B.h=R->HL.B.l;break;
|
||||
case LD_L_L: R->HL.B.l=R->HL.B.l;break;
|
||||
case LD_A_L: R->AF.B.h=R->HL.B.l;break;
|
||||
case LD_xHL_L: WrZ80(R->HL.W,R->HL.B.l);break;
|
||||
|
||||
case LD_B_A: R->BC.B.h=R->AF.B.h;break;
|
||||
case LD_C_A: R->BC.B.l=R->AF.B.h;break;
|
||||
case LD_D_A: R->DE.B.h=R->AF.B.h;break;
|
||||
case LD_E_A: R->DE.B.l=R->AF.B.h;break;
|
||||
case LD_H_A: R->HL.B.h=R->AF.B.h;break;
|
||||
case LD_L_A: R->HL.B.l=R->AF.B.h;break;
|
||||
case LD_A_A: R->AF.B.h=R->AF.B.h;break;
|
||||
case LD_xHL_A: WrZ80(R->HL.W,R->AF.B.h);break;
|
||||
|
||||
case LD_xBC_A: WrZ80(R->BC.W,R->AF.B.h);break;
|
||||
case LD_xDE_A: WrZ80(R->DE.W,R->AF.B.h);break;
|
||||
|
||||
case LD_B_xHL: R->BC.B.h=RdZ80(R->HL.W);break;
|
||||
case LD_C_xHL: R->BC.B.l=RdZ80(R->HL.W);break;
|
||||
case LD_D_xHL: R->DE.B.h=RdZ80(R->HL.W);break;
|
||||
case LD_E_xHL: R->DE.B.l=RdZ80(R->HL.W);break;
|
||||
case LD_H_xHL: R->HL.B.h=RdZ80(R->HL.W);break;
|
||||
case LD_L_xHL: R->HL.B.l=RdZ80(R->HL.W);break;
|
||||
case LD_A_xHL: R->AF.B.h=RdZ80(R->HL.W);break;
|
||||
|
||||
case LD_B_BYTE: R->BC.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_C_BYTE: R->BC.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_D_BYTE: R->DE.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_E_BYTE: R->DE.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_H_BYTE: R->HL.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_L_BYTE: R->HL.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_A_BYTE: R->AF.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_xHL_BYTE: WrZ80(R->HL.W,OpZ80(R->PC.W++));break;
|
||||
|
||||
case LD_xWORD_HL:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->HL.B.l);
|
||||
WrZ80(J.W,R->HL.B.h);
|
||||
break;
|
||||
|
||||
case LD_HL_xWORD:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->HL.B.l=RdZ80(J.W++);
|
||||
R->HL.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_A_xWORD:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->AF.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_xWORD_A:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->AF.B.h);
|
||||
break;
|
||||
|
||||
case EX_HL_xSP:
|
||||
J.B.l=RdZ80(R->SP.W);WrZ80(R->SP.W++,R->HL.B.l);
|
||||
J.B.h=RdZ80(R->SP.W);WrZ80(R->SP.W--,R->HL.B.h);
|
||||
R->HL.W=J.W;
|
||||
break;
|
||||
|
||||
case DAA:
|
||||
J.W=R->AF.B.h;
|
||||
if(R->AF.B.l&C_FLAG) J.W|=256;
|
||||
if(R->AF.B.l&H_FLAG) J.W|=512;
|
||||
if(R->AF.B.l&N_FLAG) J.W|=1024;
|
||||
R->AF.W=DAATable[J.W];
|
||||
break;
|
||||
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: %02X at PC=%04X\n",
|
||||
(long)R->User,OpZ80(R->PC.W-1),R->PC.W-1
|
||||
);
|
||||
break;
|
||||
204
MCUME_teensy41/teensyspeccy/CodesCB.h
Executable file
204
MCUME_teensy41/teensyspeccy/CodesCB.h
Executable file
|
|
@ -0,0 +1,204 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesCB.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for the CB table of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case RLC_B: M_RLC(R->BC.B.h);break; case RLC_C: M_RLC(R->BC.B.l);break;
|
||||
case RLC_D: M_RLC(R->DE.B.h);break; case RLC_E: M_RLC(R->DE.B.l);break;
|
||||
case RLC_H: M_RLC(R->HL.B.h);break; case RLC_L: M_RLC(R->HL.B.l);break;
|
||||
case RLC_xHL: I=RdZ80(R->HL.W);M_RLC(I);WrZ80(R->HL.W,I);break;
|
||||
case RLC_A: M_RLC(R->AF.B.h);break;
|
||||
|
||||
case RRC_B: M_RRC(R->BC.B.h);break; case RRC_C: M_RRC(R->BC.B.l);break;
|
||||
case RRC_D: M_RRC(R->DE.B.h);break; case RRC_E: M_RRC(R->DE.B.l);break;
|
||||
case RRC_H: M_RRC(R->HL.B.h);break; case RRC_L: M_RRC(R->HL.B.l);break;
|
||||
case RRC_xHL: I=RdZ80(R->HL.W);M_RRC(I);WrZ80(R->HL.W,I);break;
|
||||
case RRC_A: M_RRC(R->AF.B.h);break;
|
||||
|
||||
case RL_B: M_RL(R->BC.B.h);break; case RL_C: M_RL(R->BC.B.l);break;
|
||||
case RL_D: M_RL(R->DE.B.h);break; case RL_E: M_RL(R->DE.B.l);break;
|
||||
case RL_H: M_RL(R->HL.B.h);break; case RL_L: M_RL(R->HL.B.l);break;
|
||||
case RL_xHL: I=RdZ80(R->HL.W);M_RL(I);WrZ80(R->HL.W,I);break;
|
||||
case RL_A: M_RL(R->AF.B.h);break;
|
||||
|
||||
case RR_B: M_RR(R->BC.B.h);break; case RR_C: M_RR(R->BC.B.l);break;
|
||||
case RR_D: M_RR(R->DE.B.h);break; case RR_E: M_RR(R->DE.B.l);break;
|
||||
case RR_H: M_RR(R->HL.B.h);break; case RR_L: M_RR(R->HL.B.l);break;
|
||||
case RR_xHL: I=RdZ80(R->HL.W);M_RR(I);WrZ80(R->HL.W,I);break;
|
||||
case RR_A: M_RR(R->AF.B.h);break;
|
||||
|
||||
case SLA_B: M_SLA(R->BC.B.h);break; case SLA_C: M_SLA(R->BC.B.l);break;
|
||||
case SLA_D: M_SLA(R->DE.B.h);break; case SLA_E: M_SLA(R->DE.B.l);break;
|
||||
case SLA_H: M_SLA(R->HL.B.h);break; case SLA_L: M_SLA(R->HL.B.l);break;
|
||||
case SLA_xHL: I=RdZ80(R->HL.W);M_SLA(I);WrZ80(R->HL.W,I);break;
|
||||
case SLA_A: M_SLA(R->AF.B.h);break;
|
||||
|
||||
case SRA_B: M_SRA(R->BC.B.h);break; case SRA_C: M_SRA(R->BC.B.l);break;
|
||||
case SRA_D: M_SRA(R->DE.B.h);break; case SRA_E: M_SRA(R->DE.B.l);break;
|
||||
case SRA_H: M_SRA(R->HL.B.h);break; case SRA_L: M_SRA(R->HL.B.l);break;
|
||||
case SRA_xHL: I=RdZ80(R->HL.W);M_SRA(I);WrZ80(R->HL.W,I);break;
|
||||
case SRA_A: M_SRA(R->AF.B.h);break;
|
||||
|
||||
case SLL_B: M_SLL(R->BC.B.h);break; case SLL_C: M_SLL(R->BC.B.l);break;
|
||||
case SLL_D: M_SLL(R->DE.B.h);break; case SLL_E: M_SLL(R->DE.B.l);break;
|
||||
case SLL_H: M_SLL(R->HL.B.h);break; case SLL_L: M_SLL(R->HL.B.l);break;
|
||||
case SLL_xHL: I=RdZ80(R->HL.W);M_SLL(I);WrZ80(R->HL.W,I);break;
|
||||
case SLL_A: M_SLL(R->AF.B.h);break;
|
||||
|
||||
case SRL_B: M_SRL(R->BC.B.h);break; case SRL_C: M_SRL(R->BC.B.l);break;
|
||||
case SRL_D: M_SRL(R->DE.B.h);break; case SRL_E: M_SRL(R->DE.B.l);break;
|
||||
case SRL_H: M_SRL(R->HL.B.h);break; case SRL_L: M_SRL(R->HL.B.l);break;
|
||||
case SRL_xHL: I=RdZ80(R->HL.W);M_SRL(I);WrZ80(R->HL.W,I);break;
|
||||
case SRL_A: M_SRL(R->AF.B.h);break;
|
||||
|
||||
case BIT0_B: M_BIT(0,R->BC.B.h);break; case BIT0_C: M_BIT(0,R->BC.B.l);break;
|
||||
case BIT0_D: M_BIT(0,R->DE.B.h);break; case BIT0_E: M_BIT(0,R->DE.B.l);break;
|
||||
case BIT0_H: M_BIT(0,R->HL.B.h);break; case BIT0_L: M_BIT(0,R->HL.B.l);break;
|
||||
case BIT0_xHL: I=RdZ80(R->HL.W);M_BIT(0,I);break;
|
||||
case BIT0_A: M_BIT(0,R->AF.B.h);break;
|
||||
|
||||
case BIT1_B: M_BIT(1,R->BC.B.h);break; case BIT1_C: M_BIT(1,R->BC.B.l);break;
|
||||
case BIT1_D: M_BIT(1,R->DE.B.h);break; case BIT1_E: M_BIT(1,R->DE.B.l);break;
|
||||
case BIT1_H: M_BIT(1,R->HL.B.h);break; case BIT1_L: M_BIT(1,R->HL.B.l);break;
|
||||
case BIT1_xHL: I=RdZ80(R->HL.W);M_BIT(1,I);break;
|
||||
case BIT1_A: M_BIT(1,R->AF.B.h);break;
|
||||
|
||||
case BIT2_B: M_BIT(2,R->BC.B.h);break; case BIT2_C: M_BIT(2,R->BC.B.l);break;
|
||||
case BIT2_D: M_BIT(2,R->DE.B.h);break; case BIT2_E: M_BIT(2,R->DE.B.l);break;
|
||||
case BIT2_H: M_BIT(2,R->HL.B.h);break; case BIT2_L: M_BIT(2,R->HL.B.l);break;
|
||||
case BIT2_xHL: I=RdZ80(R->HL.W);M_BIT(2,I);break;
|
||||
case BIT2_A: M_BIT(2,R->AF.B.h);break;
|
||||
|
||||
case BIT3_B: M_BIT(3,R->BC.B.h);break; case BIT3_C: M_BIT(3,R->BC.B.l);break;
|
||||
case BIT3_D: M_BIT(3,R->DE.B.h);break; case BIT3_E: M_BIT(3,R->DE.B.l);break;
|
||||
case BIT3_H: M_BIT(3,R->HL.B.h);break; case BIT3_L: M_BIT(3,R->HL.B.l);break;
|
||||
case BIT3_xHL: I=RdZ80(R->HL.W);M_BIT(3,I);break;
|
||||
case BIT3_A: M_BIT(3,R->AF.B.h);break;
|
||||
|
||||
case BIT4_B: M_BIT(4,R->BC.B.h);break; case BIT4_C: M_BIT(4,R->BC.B.l);break;
|
||||
case BIT4_D: M_BIT(4,R->DE.B.h);break; case BIT4_E: M_BIT(4,R->DE.B.l);break;
|
||||
case BIT4_H: M_BIT(4,R->HL.B.h);break; case BIT4_L: M_BIT(4,R->HL.B.l);break;
|
||||
case BIT4_xHL: I=RdZ80(R->HL.W);M_BIT(4,I);break;
|
||||
case BIT4_A: M_BIT(4,R->AF.B.h);break;
|
||||
|
||||
case BIT5_B: M_BIT(5,R->BC.B.h);break; case BIT5_C: M_BIT(5,R->BC.B.l);break;
|
||||
case BIT5_D: M_BIT(5,R->DE.B.h);break; case BIT5_E: M_BIT(5,R->DE.B.l);break;
|
||||
case BIT5_H: M_BIT(5,R->HL.B.h);break; case BIT5_L: M_BIT(5,R->HL.B.l);break;
|
||||
case BIT5_xHL: I=RdZ80(R->HL.W);M_BIT(5,I);break;
|
||||
case BIT5_A: M_BIT(5,R->AF.B.h);break;
|
||||
|
||||
case BIT6_B: M_BIT(6,R->BC.B.h);break; case BIT6_C: M_BIT(6,R->BC.B.l);break;
|
||||
case BIT6_D: M_BIT(6,R->DE.B.h);break; case BIT6_E: M_BIT(6,R->DE.B.l);break;
|
||||
case BIT6_H: M_BIT(6,R->HL.B.h);break; case BIT6_L: M_BIT(6,R->HL.B.l);break;
|
||||
case BIT6_xHL: I=RdZ80(R->HL.W);M_BIT(6,I);break;
|
||||
case BIT6_A: M_BIT(6,R->AF.B.h);break;
|
||||
|
||||
case BIT7_B: M_BIT(7,R->BC.B.h);break; case BIT7_C: M_BIT(7,R->BC.B.l);break;
|
||||
case BIT7_D: M_BIT(7,R->DE.B.h);break; case BIT7_E: M_BIT(7,R->DE.B.l);break;
|
||||
case BIT7_H: M_BIT(7,R->HL.B.h);break; case BIT7_L: M_BIT(7,R->HL.B.l);break;
|
||||
case BIT7_xHL: I=RdZ80(R->HL.W);M_BIT(7,I);break;
|
||||
case BIT7_A: M_BIT(7,R->AF.B.h);break;
|
||||
|
||||
case RES0_B: M_RES(0,R->BC.B.h);break; case RES0_C: M_RES(0,R->BC.B.l);break;
|
||||
case RES0_D: M_RES(0,R->DE.B.h);break; case RES0_E: M_RES(0,R->DE.B.l);break;
|
||||
case RES0_H: M_RES(0,R->HL.B.h);break; case RES0_L: M_RES(0,R->HL.B.l);break;
|
||||
case RES0_xHL: I=RdZ80(R->HL.W);M_RES(0,I);WrZ80(R->HL.W,I);break;
|
||||
case RES0_A: M_RES(0,R->AF.B.h);break;
|
||||
|
||||
case RES1_B: M_RES(1,R->BC.B.h);break; case RES1_C: M_RES(1,R->BC.B.l);break;
|
||||
case RES1_D: M_RES(1,R->DE.B.h);break; case RES1_E: M_RES(1,R->DE.B.l);break;
|
||||
case RES1_H: M_RES(1,R->HL.B.h);break; case RES1_L: M_RES(1,R->HL.B.l);break;
|
||||
case RES1_xHL: I=RdZ80(R->HL.W);M_RES(1,I);WrZ80(R->HL.W,I);break;
|
||||
case RES1_A: M_RES(1,R->AF.B.h);break;
|
||||
|
||||
case RES2_B: M_RES(2,R->BC.B.h);break; case RES2_C: M_RES(2,R->BC.B.l);break;
|
||||
case RES2_D: M_RES(2,R->DE.B.h);break; case RES2_E: M_RES(2,R->DE.B.l);break;
|
||||
case RES2_H: M_RES(2,R->HL.B.h);break; case RES2_L: M_RES(2,R->HL.B.l);break;
|
||||
case RES2_xHL: I=RdZ80(R->HL.W);M_RES(2,I);WrZ80(R->HL.W,I);break;
|
||||
case RES2_A: M_RES(2,R->AF.B.h);break;
|
||||
|
||||
case RES3_B: M_RES(3,R->BC.B.h);break; case RES3_C: M_RES(3,R->BC.B.l);break;
|
||||
case RES3_D: M_RES(3,R->DE.B.h);break; case RES3_E: M_RES(3,R->DE.B.l);break;
|
||||
case RES3_H: M_RES(3,R->HL.B.h);break; case RES3_L: M_RES(3,R->HL.B.l);break;
|
||||
case RES3_xHL: I=RdZ80(R->HL.W);M_RES(3,I);WrZ80(R->HL.W,I);break;
|
||||
case RES3_A: M_RES(3,R->AF.B.h);break;
|
||||
|
||||
case RES4_B: M_RES(4,R->BC.B.h);break; case RES4_C: M_RES(4,R->BC.B.l);break;
|
||||
case RES4_D: M_RES(4,R->DE.B.h);break; case RES4_E: M_RES(4,R->DE.B.l);break;
|
||||
case RES4_H: M_RES(4,R->HL.B.h);break; case RES4_L: M_RES(4,R->HL.B.l);break;
|
||||
case RES4_xHL: I=RdZ80(R->HL.W);M_RES(4,I);WrZ80(R->HL.W,I);break;
|
||||
case RES4_A: M_RES(4,R->AF.B.h);break;
|
||||
|
||||
case RES5_B: M_RES(5,R->BC.B.h);break; case RES5_C: M_RES(5,R->BC.B.l);break;
|
||||
case RES5_D: M_RES(5,R->DE.B.h);break; case RES5_E: M_RES(5,R->DE.B.l);break;
|
||||
case RES5_H: M_RES(5,R->HL.B.h);break; case RES5_L: M_RES(5,R->HL.B.l);break;
|
||||
case RES5_xHL: I=RdZ80(R->HL.W);M_RES(5,I);WrZ80(R->HL.W,I);break;
|
||||
case RES5_A: M_RES(5,R->AF.B.h);break;
|
||||
|
||||
case RES6_B: M_RES(6,R->BC.B.h);break; case RES6_C: M_RES(6,R->BC.B.l);break;
|
||||
case RES6_D: M_RES(6,R->DE.B.h);break; case RES6_E: M_RES(6,R->DE.B.l);break;
|
||||
case RES6_H: M_RES(6,R->HL.B.h);break; case RES6_L: M_RES(6,R->HL.B.l);break;
|
||||
case RES6_xHL: I=RdZ80(R->HL.W);M_RES(6,I);WrZ80(R->HL.W,I);break;
|
||||
case RES6_A: M_RES(6,R->AF.B.h);break;
|
||||
|
||||
case RES7_B: M_RES(7,R->BC.B.h);break; case RES7_C: M_RES(7,R->BC.B.l);break;
|
||||
case RES7_D: M_RES(7,R->DE.B.h);break; case RES7_E: M_RES(7,R->DE.B.l);break;
|
||||
case RES7_H: M_RES(7,R->HL.B.h);break; case RES7_L: M_RES(7,R->HL.B.l);break;
|
||||
case RES7_xHL: I=RdZ80(R->HL.W);M_RES(7,I);WrZ80(R->HL.W,I);break;
|
||||
case RES7_A: M_RES(7,R->AF.B.h);break;
|
||||
|
||||
case SET0_B: M_SET(0,R->BC.B.h);break; case SET0_C: M_SET(0,R->BC.B.l);break;
|
||||
case SET0_D: M_SET(0,R->DE.B.h);break; case SET0_E: M_SET(0,R->DE.B.l);break;
|
||||
case SET0_H: M_SET(0,R->HL.B.h);break; case SET0_L: M_SET(0,R->HL.B.l);break;
|
||||
case SET0_xHL: I=RdZ80(R->HL.W);M_SET(0,I);WrZ80(R->HL.W,I);break;
|
||||
case SET0_A: M_SET(0,R->AF.B.h);break;
|
||||
|
||||
case SET1_B: M_SET(1,R->BC.B.h);break; case SET1_C: M_SET(1,R->BC.B.l);break;
|
||||
case SET1_D: M_SET(1,R->DE.B.h);break; case SET1_E: M_SET(1,R->DE.B.l);break;
|
||||
case SET1_H: M_SET(1,R->HL.B.h);break; case SET1_L: M_SET(1,R->HL.B.l);break;
|
||||
case SET1_xHL: I=RdZ80(R->HL.W);M_SET(1,I);WrZ80(R->HL.W,I);break;
|
||||
case SET1_A: M_SET(1,R->AF.B.h);break;
|
||||
|
||||
case SET2_B: M_SET(2,R->BC.B.h);break; case SET2_C: M_SET(2,R->BC.B.l);break;
|
||||
case SET2_D: M_SET(2,R->DE.B.h);break; case SET2_E: M_SET(2,R->DE.B.l);break;
|
||||
case SET2_H: M_SET(2,R->HL.B.h);break; case SET2_L: M_SET(2,R->HL.B.l);break;
|
||||
case SET2_xHL: I=RdZ80(R->HL.W);M_SET(2,I);WrZ80(R->HL.W,I);break;
|
||||
case SET2_A: M_SET(2,R->AF.B.h);break;
|
||||
|
||||
case SET3_B: M_SET(3,R->BC.B.h);break; case SET3_C: M_SET(3,R->BC.B.l);break;
|
||||
case SET3_D: M_SET(3,R->DE.B.h);break; case SET3_E: M_SET(3,R->DE.B.l);break;
|
||||
case SET3_H: M_SET(3,R->HL.B.h);break; case SET3_L: M_SET(3,R->HL.B.l);break;
|
||||
case SET3_xHL: I=RdZ80(R->HL.W);M_SET(3,I);WrZ80(R->HL.W,I);break;
|
||||
case SET3_A: M_SET(3,R->AF.B.h);break;
|
||||
|
||||
case SET4_B: M_SET(4,R->BC.B.h);break; case SET4_C: M_SET(4,R->BC.B.l);break;
|
||||
case SET4_D: M_SET(4,R->DE.B.h);break; case SET4_E: M_SET(4,R->DE.B.l);break;
|
||||
case SET4_H: M_SET(4,R->HL.B.h);break; case SET4_L: M_SET(4,R->HL.B.l);break;
|
||||
case SET4_xHL: I=RdZ80(R->HL.W);M_SET(4,I);WrZ80(R->HL.W,I);break;
|
||||
case SET4_A: M_SET(4,R->AF.B.h);break;
|
||||
|
||||
case SET5_B: M_SET(5,R->BC.B.h);break; case SET5_C: M_SET(5,R->BC.B.l);break;
|
||||
case SET5_D: M_SET(5,R->DE.B.h);break; case SET5_E: M_SET(5,R->DE.B.l);break;
|
||||
case SET5_H: M_SET(5,R->HL.B.h);break; case SET5_L: M_SET(5,R->HL.B.l);break;
|
||||
case SET5_xHL: I=RdZ80(R->HL.W);M_SET(5,I);WrZ80(R->HL.W,I);break;
|
||||
case SET5_A: M_SET(5,R->AF.B.h);break;
|
||||
|
||||
case SET6_B: M_SET(6,R->BC.B.h);break; case SET6_C: M_SET(6,R->BC.B.l);break;
|
||||
case SET6_D: M_SET(6,R->DE.B.h);break; case SET6_E: M_SET(6,R->DE.B.l);break;
|
||||
case SET6_H: M_SET(6,R->HL.B.h);break; case SET6_L: M_SET(6,R->HL.B.l);break;
|
||||
case SET6_xHL: I=RdZ80(R->HL.W);M_SET(6,I);WrZ80(R->HL.W,I);break;
|
||||
case SET6_A: M_SET(6,R->AF.B.h);break;
|
||||
|
||||
case SET7_B: M_SET(7,R->BC.B.h);break; case SET7_C: M_SET(7,R->BC.B.l);break;
|
||||
case SET7_D: M_SET(7,R->DE.B.h);break; case SET7_E: M_SET(7,R->DE.B.l);break;
|
||||
case SET7_H: M_SET(7,R->HL.B.h);break; case SET7_L: M_SET(7,R->HL.B.l);break;
|
||||
case SET7_xHL: I=RdZ80(R->HL.W);M_SET(7,I);WrZ80(R->HL.W,I);break;
|
||||
case SET7_A: M_SET(7,R->AF.B.h);break;
|
||||
304
MCUME_teensy41/teensyspeccy/CodesED.h
Executable file
304
MCUME_teensy41/teensyspeccy/CodesED.h
Executable file
|
|
@ -0,0 +1,304 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesED.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for the ED table of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
/** This is a special patch for emulating BIOS calls: ********/
|
||||
case DB_FE: PatchZ80(R);break;
|
||||
/*************************************************************/
|
||||
|
||||
case ADC_HL_BC: M_ADCW(BC);break;
|
||||
case ADC_HL_DE: M_ADCW(DE);break;
|
||||
case ADC_HL_HL: M_ADCW(HL);break;
|
||||
case ADC_HL_SP: M_ADCW(SP);break;
|
||||
|
||||
case SBC_HL_BC: M_SBCW(BC);break;
|
||||
case SBC_HL_DE: M_SBCW(DE);break;
|
||||
case SBC_HL_HL: M_SBCW(HL);break;
|
||||
case SBC_HL_SP: M_SBCW(SP);break;
|
||||
|
||||
case LD_xWORDe_HL:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->HL.B.l);
|
||||
WrZ80(J.W,R->HL.B.h);
|
||||
break;
|
||||
case LD_xWORDe_DE:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->DE.B.l);
|
||||
WrZ80(J.W,R->DE.B.h);
|
||||
break;
|
||||
case LD_xWORDe_BC:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->BC.B.l);
|
||||
WrZ80(J.W,R->BC.B.h);
|
||||
break;
|
||||
case LD_xWORDe_SP:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->SP.B.l);
|
||||
WrZ80(J.W,R->SP.B.h);
|
||||
break;
|
||||
|
||||
case LD_HL_xWORDe:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->HL.B.l=RdZ80(J.W++);
|
||||
R->HL.B.h=RdZ80(J.W);
|
||||
break;
|
||||
case LD_DE_xWORDe:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->DE.B.l=RdZ80(J.W++);
|
||||
R->DE.B.h=RdZ80(J.W);
|
||||
break;
|
||||
case LD_BC_xWORDe:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->BC.B.l=RdZ80(J.W++);
|
||||
R->BC.B.h=RdZ80(J.W);
|
||||
break;
|
||||
case LD_SP_xWORDe:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->SP.B.l=RdZ80(J.W++);
|
||||
R->SP.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case RRD:
|
||||
I=RdZ80(R->HL.W);
|
||||
J.B.l=(I>>4)|(R->AF.B.h<<4);
|
||||
WrZ80(R->HL.W,J.B.l);
|
||||
R->AF.B.h=(I&0x0F)|(R->AF.B.h&0xF0);
|
||||
R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG);
|
||||
break;
|
||||
case RLD:
|
||||
I=RdZ80(R->HL.W);
|
||||
J.B.l=(I<<4)|(R->AF.B.h&0x0F);
|
||||
WrZ80(R->HL.W,J.B.l);
|
||||
R->AF.B.h=(I>>4)|(R->AF.B.h&0xF0);
|
||||
R->AF.B.l=PZSTable[R->AF.B.h]|(R->AF.B.l&C_FLAG);
|
||||
break;
|
||||
|
||||
case LD_A_I:
|
||||
R->AF.B.h=R->I;
|
||||
R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h];
|
||||
break;
|
||||
|
||||
case LD_A_R:
|
||||
R->R++;
|
||||
R->AF.B.h=(byte)(R->R-R->ICount);
|
||||
R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h];
|
||||
break;
|
||||
|
||||
case LD_I_A: R->I=R->AF.B.h;break;
|
||||
case LD_R_A: break;
|
||||
|
||||
case IM_0: R->IFF&=~(IFF_IM1|IFF_IM2);break;
|
||||
case IM_1: R->IFF=(R->IFF&~IFF_IM2)|IFF_IM1;break;
|
||||
case IM_2: R->IFF=(R->IFF&~IFF_IM1)|IFF_IM2;break;
|
||||
|
||||
case RETI:
|
||||
case RETN: if(R->IFF&IFF_2) R->IFF|=IFF_1; else R->IFF&=~IFF_1;
|
||||
M_RET;break;
|
||||
|
||||
case NEG: I=R->AF.B.h;R->AF.B.h=0;M_SUB(I);break;
|
||||
|
||||
case IN_B_xC: M_IN(R->BC.B.h);break;
|
||||
case IN_C_xC: M_IN(R->BC.B.l);break;
|
||||
case IN_D_xC: M_IN(R->DE.B.h);break;
|
||||
case IN_E_xC: M_IN(R->DE.B.l);break;
|
||||
case IN_H_xC: M_IN(R->HL.B.h);break;
|
||||
case IN_L_xC: M_IN(R->HL.B.l);break;
|
||||
case IN_A_xC: M_IN(R->AF.B.h);break;
|
||||
case IN_F_xC: M_IN(J.B.l);break;
|
||||
|
||||
case OUT_xC_B: OutZ80(R->BC.W,R->BC.B.h);break;
|
||||
case OUT_xC_C: OutZ80(R->BC.W,R->BC.B.l);break;
|
||||
case OUT_xC_D: OutZ80(R->BC.W,R->DE.B.h);break;
|
||||
case OUT_xC_E: OutZ80(R->BC.W,R->DE.B.l);break;
|
||||
case OUT_xC_H: OutZ80(R->BC.W,R->HL.B.h);break;
|
||||
case OUT_xC_L: OutZ80(R->BC.W,R->HL.B.l);break;
|
||||
case OUT_xC_A: OutZ80(R->BC.W,R->AF.B.h);break;
|
||||
|
||||
case INI:
|
||||
WrZ80(R->HL.W++,InZ80(R->BC.W));
|
||||
--R->BC.B.h;
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);
|
||||
break;
|
||||
|
||||
case INIR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->HL.W++,InZ80(R->BC.W));
|
||||
--R->BC.B.h;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; }
|
||||
else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; }
|
||||
break;
|
||||
|
||||
case IND:
|
||||
WrZ80(R->HL.W--,InZ80(R->BC.W));
|
||||
--R->BC.B.h;
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);
|
||||
break;
|
||||
|
||||
case INDR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->HL.W--,InZ80(R->BC.W));
|
||||
--R->BC.B.h;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h) { R->AF.B.l=N_FLAG;R->PC.W-=2; }
|
||||
else { R->AF.B.l=Z_FLAG|N_FLAG;R->ICount+=5; }
|
||||
break;
|
||||
|
||||
case OUTI:
|
||||
--R->BC.B.h;
|
||||
I=RdZ80(R->HL.W++);
|
||||
OutZ80(R->BC.W,I);
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
break;
|
||||
|
||||
case OTIR:
|
||||
do
|
||||
{
|
||||
--R->BC.B.h;
|
||||
I=RdZ80(R->HL.W++);
|
||||
OutZ80(R->BC.W,I);
|
||||
R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h)
|
||||
{
|
||||
R->AF.B.l=N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
R->PC.W-=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
R->ICount+=5;
|
||||
}
|
||||
break;
|
||||
|
||||
case OUTD:
|
||||
--R->BC.B.h;
|
||||
I=RdZ80(R->HL.W--);
|
||||
OutZ80(R->BC.W,I);
|
||||
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
break;
|
||||
|
||||
case OTDR:
|
||||
do
|
||||
{
|
||||
--R->BC.B.h;
|
||||
I=RdZ80(R->HL.W--);
|
||||
OutZ80(R->BC.W,I);
|
||||
R->ICount-=21;
|
||||
}
|
||||
while(R->BC.B.h&&(R->ICount>0));
|
||||
if(R->BC.B.h)
|
||||
{
|
||||
R->AF.B.l=N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
R->PC.W-=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
|
||||
R->ICount+=5;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDI:
|
||||
WrZ80(R->DE.W++,RdZ80(R->HL.W++));
|
||||
--R->BC.W;
|
||||
R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case LDIR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->DE.W++,RdZ80(R->HL.W++));
|
||||
--R->BC.W;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&(R->ICount>0));
|
||||
R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG);
|
||||
if(R->BC.W) { R->AF.B.l|=N_FLAG;R->PC.W-=2; }
|
||||
else R->ICount+=5;
|
||||
break;
|
||||
|
||||
case LDD:
|
||||
WrZ80(R->DE.W--,RdZ80(R->HL.W--));
|
||||
--R->BC.W;
|
||||
R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case LDDR:
|
||||
do
|
||||
{
|
||||
WrZ80(R->DE.W--,RdZ80(R->HL.W--));
|
||||
--R->BC.W;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&(R->ICount>0));
|
||||
R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG);
|
||||
if(R->BC.W) { R->AF.B.l|=N_FLAG;R->PC.W-=2; }
|
||||
else R->ICount+=5;
|
||||
break;
|
||||
|
||||
case CPI:
|
||||
I=RdZ80(R->HL.W++);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
--R->BC.W;
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case CPIR:
|
||||
do
|
||||
{
|
||||
I=RdZ80(R->HL.W++);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
--R->BC.W;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&J.B.l&&(R->ICount>0));
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5;
|
||||
break;
|
||||
|
||||
case CPD:
|
||||
I=RdZ80(R->HL.W--);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
--R->BC.W;
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
break;
|
||||
|
||||
case CPDR:
|
||||
do
|
||||
{
|
||||
I=RdZ80(R->HL.W--);
|
||||
J.B.l=R->AF.B.h-I;
|
||||
--R->BC.W;R->ICount-=21;
|
||||
}
|
||||
while(R->BC.W&&J.B.l);
|
||||
R->AF.B.l =
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
|
||||
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
|
||||
if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5;
|
||||
break;
|
||||
64
MCUME_teensy41/teensyspeccy/CodesXCB.h
Executable file
64
MCUME_teensy41/teensyspeccy/CodesXCB.h
Executable file
|
|
@ -0,0 +1,64 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesXCB.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for FD/DD-CB tables **/
|
||||
/** of Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case RLC_xHL: I=RdZ80(J.W);M_RLC(I);WrZ80(J.W,I);break;
|
||||
case RRC_xHL: I=RdZ80(J.W);M_RRC(I);WrZ80(J.W,I);break;
|
||||
case RL_xHL: I=RdZ80(J.W);M_RL(I);WrZ80(J.W,I);break;
|
||||
case RR_xHL: I=RdZ80(J.W);M_RR(I);WrZ80(J.W,I);break;
|
||||
case SLA_xHL: I=RdZ80(J.W);M_SLA(I);WrZ80(J.W,I);break;
|
||||
case SRA_xHL: I=RdZ80(J.W);M_SRA(I);WrZ80(J.W,I);break;
|
||||
case SLL_xHL: I=RdZ80(J.W);M_SLL(I);WrZ80(J.W,I);break;
|
||||
case SRL_xHL: I=RdZ80(J.W);M_SRL(I);WrZ80(J.W,I);break;
|
||||
|
||||
case BIT0_B: case BIT0_C: case BIT0_D: case BIT0_E:
|
||||
case BIT0_H: case BIT0_L: case BIT0_A:
|
||||
case BIT0_xHL: I=RdZ80(J.W);M_BIT(0,I);break;
|
||||
case BIT1_B: case BIT1_C: case BIT1_D: case BIT1_E:
|
||||
case BIT1_H: case BIT1_L: case BIT1_A:
|
||||
case BIT1_xHL: I=RdZ80(J.W);M_BIT(1,I);break;
|
||||
case BIT2_B: case BIT2_C: case BIT2_D: case BIT2_E:
|
||||
case BIT2_H: case BIT2_L: case BIT2_A:
|
||||
case BIT2_xHL: I=RdZ80(J.W);M_BIT(2,I);break;
|
||||
case BIT3_B: case BIT3_C: case BIT3_D: case BIT3_E:
|
||||
case BIT3_H: case BIT3_L: case BIT3_A:
|
||||
case BIT3_xHL: I=RdZ80(J.W);M_BIT(3,I);break;
|
||||
case BIT4_B: case BIT4_C: case BIT4_D: case BIT4_E:
|
||||
case BIT4_H: case BIT4_L: case BIT4_A:
|
||||
case BIT4_xHL: I=RdZ80(J.W);M_BIT(4,I);break;
|
||||
case BIT5_B: case BIT5_C: case BIT5_D: case BIT5_E:
|
||||
case BIT5_H: case BIT5_L: case BIT5_A:
|
||||
case BIT5_xHL: I=RdZ80(J.W);M_BIT(5,I);break;
|
||||
case BIT6_B: case BIT6_C: case BIT6_D: case BIT6_E:
|
||||
case BIT6_H: case BIT6_L: case BIT6_A:
|
||||
case BIT6_xHL: I=RdZ80(J.W);M_BIT(6,I);break;
|
||||
case BIT7_B: case BIT7_C: case BIT7_D: case BIT7_E:
|
||||
case BIT7_H: case BIT7_L: case BIT7_A:
|
||||
case BIT7_xHL: I=RdZ80(J.W);M_BIT(7,I);break;
|
||||
|
||||
case RES0_xHL: I=RdZ80(J.W);M_RES(0,I);WrZ80(J.W,I);break;
|
||||
case RES1_xHL: I=RdZ80(J.W);M_RES(1,I);WrZ80(J.W,I);break;
|
||||
case RES2_xHL: I=RdZ80(J.W);M_RES(2,I);WrZ80(J.W,I);break;
|
||||
case RES3_xHL: I=RdZ80(J.W);M_RES(3,I);WrZ80(J.W,I);break;
|
||||
case RES4_xHL: I=RdZ80(J.W);M_RES(4,I);WrZ80(J.W,I);break;
|
||||
case RES5_xHL: I=RdZ80(J.W);M_RES(5,I);WrZ80(J.W,I);break;
|
||||
case RES6_xHL: I=RdZ80(J.W);M_RES(6,I);WrZ80(J.W,I);break;
|
||||
case RES7_xHL: I=RdZ80(J.W);M_RES(7,I);WrZ80(J.W,I);break;
|
||||
|
||||
case SET0_xHL: I=RdZ80(J.W);M_SET(0,I);WrZ80(J.W,I);break;
|
||||
case SET1_xHL: I=RdZ80(J.W);M_SET(1,I);WrZ80(J.W,I);break;
|
||||
case SET2_xHL: I=RdZ80(J.W);M_SET(2,I);WrZ80(J.W,I);break;
|
||||
case SET3_xHL: I=RdZ80(J.W);M_SET(3,I);WrZ80(J.W,I);break;
|
||||
case SET4_xHL: I=RdZ80(J.W);M_SET(4,I);WrZ80(J.W,I);break;
|
||||
case SET5_xHL: I=RdZ80(J.W);M_SET(5,I);WrZ80(J.W,I);break;
|
||||
case SET6_xHL: I=RdZ80(J.W);M_SET(6,I);WrZ80(J.W,I);break;
|
||||
case SET7_xHL: I=RdZ80(J.W);M_SET(7,I);WrZ80(J.W,I);break;
|
||||
396
MCUME_teensy41/teensyspeccy/CodesXX.h
Executable file
396
MCUME_teensy41/teensyspeccy/CodesXX.h
Executable file
|
|
@ -0,0 +1,396 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** CodesXX.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for FD/DD tables of **/
|
||||
/** Z80 commands. It is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
case JR_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
|
||||
case JR_NC: if(R->AF.B.l&C_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
|
||||
case JR_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
|
||||
case JR_C: if(R->AF.B.l&C_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
|
||||
|
||||
case JP_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_JP; } break;
|
||||
case JP_Z: if(R->AF.B.l&Z_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_C: if(R->AF.B.l&C_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_PE: if(R->AF.B.l&P_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
case JP_M: if(R->AF.B.l&S_FLAG) { M_JP; } else R->PC.W+=2; break;
|
||||
|
||||
case RET_NZ: if(!(R->AF.B.l&Z_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_NC: if(!(R->AF.B.l&C_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_PO: if(!(R->AF.B.l&P_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_P: if(!(R->AF.B.l&S_FLAG)) { R->ICount-=6;M_RET; } break;
|
||||
case RET_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_C: if(R->AF.B.l&C_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
case RET_M: if(R->AF.B.l&S_FLAG) { R->ICount-=6;M_RET; } break;
|
||||
|
||||
case CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
|
||||
case CALL_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_C: if(R->AF.B.l&C_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
case CALL_M: if(R->AF.B.l&S_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
|
||||
|
||||
case ADD_B: M_ADD(R->BC.B.h);break;
|
||||
case ADD_C: M_ADD(R->BC.B.l);break;
|
||||
case ADD_D: M_ADD(R->DE.B.h);break;
|
||||
case ADD_E: M_ADD(R->DE.B.l);break;
|
||||
case ADD_H: M_ADD(R->XX.B.h);break;
|
||||
case ADD_L: M_ADD(R->XX.B.l);break;
|
||||
case ADD_A: M_ADD(R->AF.B.h);break;
|
||||
case ADD_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_ADD(I);break;
|
||||
case ADD_BYTE: I=OpZ80(R->PC.W++);M_ADD(I);break;
|
||||
|
||||
case SUB_B: M_SUB(R->BC.B.h);break;
|
||||
case SUB_C: M_SUB(R->BC.B.l);break;
|
||||
case SUB_D: M_SUB(R->DE.B.h);break;
|
||||
case SUB_E: M_SUB(R->DE.B.l);break;
|
||||
case SUB_H: M_SUB(R->XX.B.h);break;
|
||||
case SUB_L: M_SUB(R->XX.B.l);break;
|
||||
case SUB_A: R->AF.B.h=0;R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case SUB_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_SUB(I);break;
|
||||
case SUB_BYTE: I=OpZ80(R->PC.W++);M_SUB(I);break;
|
||||
|
||||
case AND_B: M_AND(R->BC.B.h);break;
|
||||
case AND_C: M_AND(R->BC.B.l);break;
|
||||
case AND_D: M_AND(R->DE.B.h);break;
|
||||
case AND_E: M_AND(R->DE.B.l);break;
|
||||
case AND_H: M_AND(R->XX.B.h);break;
|
||||
case AND_L: M_AND(R->XX.B.l);break;
|
||||
case AND_A: M_AND(R->AF.B.h);break;
|
||||
case AND_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_AND(I);break;
|
||||
case AND_BYTE: I=OpZ80(R->PC.W++);M_AND(I);break;
|
||||
|
||||
case OR_B: M_OR(R->BC.B.h);break;
|
||||
case OR_C: M_OR(R->BC.B.l);break;
|
||||
case OR_D: M_OR(R->DE.B.h);break;
|
||||
case OR_E: M_OR(R->DE.B.l);break;
|
||||
case OR_H: M_OR(R->XX.B.h);break;
|
||||
case OR_L: M_OR(R->XX.B.l);break;
|
||||
case OR_A: M_OR(R->AF.B.h);break;
|
||||
case OR_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_OR(I);break;
|
||||
case OR_BYTE: I=OpZ80(R->PC.W++);M_OR(I);break;
|
||||
|
||||
case ADC_B: M_ADC(R->BC.B.h);break;
|
||||
case ADC_C: M_ADC(R->BC.B.l);break;
|
||||
case ADC_D: M_ADC(R->DE.B.h);break;
|
||||
case ADC_E: M_ADC(R->DE.B.l);break;
|
||||
case ADC_H: M_ADC(R->XX.B.h);break;
|
||||
case ADC_L: M_ADC(R->XX.B.l);break;
|
||||
case ADC_A: M_ADC(R->AF.B.h);break;
|
||||
case ADC_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_ADC(I);break;
|
||||
case ADC_BYTE: I=OpZ80(R->PC.W++);M_ADC(I);break;
|
||||
|
||||
case SBC_B: M_SBC(R->BC.B.h);break;
|
||||
case SBC_C: M_SBC(R->BC.B.l);break;
|
||||
case SBC_D: M_SBC(R->DE.B.h);break;
|
||||
case SBC_E: M_SBC(R->DE.B.l);break;
|
||||
case SBC_H: M_SBC(R->XX.B.h);break;
|
||||
case SBC_L: M_SBC(R->XX.B.l);break;
|
||||
case SBC_A: M_SBC(R->AF.B.h);break;
|
||||
case SBC_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_SBC(I);break;
|
||||
case SBC_BYTE: I=OpZ80(R->PC.W++);M_SBC(I);break;
|
||||
|
||||
case XOR_B: M_XOR(R->BC.B.h);break;
|
||||
case XOR_C: M_XOR(R->BC.B.l);break;
|
||||
case XOR_D: M_XOR(R->DE.B.h);break;
|
||||
case XOR_E: M_XOR(R->DE.B.l);break;
|
||||
case XOR_H: M_XOR(R->XX.B.h);break;
|
||||
case XOR_L: M_XOR(R->XX.B.l);break;
|
||||
case XOR_A: R->AF.B.h=0;R->AF.B.l=P_FLAG|Z_FLAG;break;
|
||||
case XOR_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_XOR(I);break;
|
||||
case XOR_BYTE: I=OpZ80(R->PC.W++);M_XOR(I);break;
|
||||
|
||||
case CP_B: M_CP(R->BC.B.h);break;
|
||||
case CP_C: M_CP(R->BC.B.l);break;
|
||||
case CP_D: M_CP(R->DE.B.h);break;
|
||||
case CP_E: M_CP(R->DE.B.l);break;
|
||||
case CP_H: M_CP(R->XX.B.h);break;
|
||||
case CP_L: M_CP(R->XX.B.l);break;
|
||||
case CP_A: R->AF.B.l=N_FLAG|Z_FLAG;break;
|
||||
case CP_xHL: I=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));
|
||||
M_CP(I);break;
|
||||
case CP_BYTE: I=OpZ80(R->PC.W++);M_CP(I);break;
|
||||
|
||||
case LD_BC_WORD: M_LDWORD(BC);break;
|
||||
case LD_DE_WORD: M_LDWORD(DE);break;
|
||||
case LD_HL_WORD: M_LDWORD(XX);break;
|
||||
case LD_SP_WORD: M_LDWORD(SP);break;
|
||||
|
||||
case LD_PC_HL: R->PC.W=R->XX.W;JumpZ80(R->PC.W);break;
|
||||
case LD_SP_HL: R->SP.W=R->XX.W;break;
|
||||
case LD_A_xBC: R->AF.B.h=RdZ80(R->BC.W);break;
|
||||
case LD_A_xDE: R->AF.B.h=RdZ80(R->DE.W);break;
|
||||
|
||||
case ADD_HL_BC: M_ADDW(XX,BC);break;
|
||||
case ADD_HL_DE: M_ADDW(XX,DE);break;
|
||||
case ADD_HL_HL: M_ADDW(XX,XX);break;
|
||||
case ADD_HL_SP: M_ADDW(XX,SP);break;
|
||||
|
||||
case DEC_BC: R->BC.W--;break;
|
||||
case DEC_DE: R->DE.W--;break;
|
||||
case DEC_HL: R->XX.W--;break;
|
||||
case DEC_SP: R->SP.W--;break;
|
||||
|
||||
case INC_BC: R->BC.W++;break;
|
||||
case INC_DE: R->DE.W++;break;
|
||||
case INC_HL: R->XX.W++;break;
|
||||
case INC_SP: R->SP.W++;break;
|
||||
|
||||
case DEC_B: M_DEC(R->BC.B.h);break;
|
||||
case DEC_C: M_DEC(R->BC.B.l);break;
|
||||
case DEC_D: M_DEC(R->DE.B.h);break;
|
||||
case DEC_E: M_DEC(R->DE.B.l);break;
|
||||
case DEC_H: M_DEC(R->XX.B.h);break;
|
||||
case DEC_L: M_DEC(R->XX.B.l);break;
|
||||
case DEC_A: M_DEC(R->AF.B.h);break;
|
||||
case DEC_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W));M_DEC(I);
|
||||
WrZ80(R->XX.W+(offset)OpZ80(R->PC.W++),I);
|
||||
break;
|
||||
|
||||
case INC_B: M_INC(R->BC.B.h);break;
|
||||
case INC_C: M_INC(R->BC.B.l);break;
|
||||
case INC_D: M_INC(R->DE.B.h);break;
|
||||
case INC_E: M_INC(R->DE.B.l);break;
|
||||
case INC_H: M_INC(R->XX.B.h);break;
|
||||
case INC_L: M_INC(R->XX.B.l);break;
|
||||
case INC_A: M_INC(R->AF.B.h);break;
|
||||
case INC_xHL: I=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W));M_INC(I);
|
||||
WrZ80(R->XX.W+(offset)OpZ80(R->PC.W++),I);
|
||||
break;
|
||||
|
||||
case RLCA:
|
||||
I=(R->AF.B.h&0x80? C_FLAG:0);
|
||||
R->AF.B.h=(R->AF.B.h<<1)|I;
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RLA:
|
||||
I=(R->AF.B.h&0x80? C_FLAG:0);
|
||||
R->AF.B.h=(R->AF.B.h<<1)|(R->AF.B.l&C_FLAG);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRCA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(I? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
case RRA:
|
||||
I=R->AF.B.h&0x01;
|
||||
R->AF.B.h=(R->AF.B.h>>1)|(R->AF.B.l&C_FLAG? 0x80:0);
|
||||
R->AF.B.l=(R->AF.B.l&~(C_FLAG|N_FLAG|H_FLAG))|I;
|
||||
break;
|
||||
|
||||
case RST00: M_RST(0x0000);break;
|
||||
case RST08: M_RST(0x0008);break;
|
||||
case RST10: M_RST(0x0010);break;
|
||||
case RST18: M_RST(0x0018);break;
|
||||
case RST20: M_RST(0x0020);break;
|
||||
case RST28: M_RST(0x0028);break;
|
||||
case RST30: M_RST(0x0030);break;
|
||||
case RST38: M_RST(0x0038);break;
|
||||
|
||||
case PUSH_BC: M_PUSH(BC);break;
|
||||
case PUSH_DE: M_PUSH(DE);break;
|
||||
case PUSH_HL: M_PUSH(XX);break;
|
||||
case PUSH_AF: M_PUSH(AF);break;
|
||||
|
||||
case POP_BC: M_POP(BC);break;
|
||||
case POP_DE: M_POP(DE);break;
|
||||
case POP_HL: M_POP(XX);break;
|
||||
case POP_AF: M_POP(AF);break;
|
||||
|
||||
case DJNZ: if(--R->BC.B.h) { R->ICount-=5;M_JR; } else R->PC.W++;break;
|
||||
case JP: M_JP;break;
|
||||
case JR: M_JR;break;
|
||||
case CALL: M_CALL;break;
|
||||
case RET: M_RET;break;
|
||||
case SCF: S(C_FLAG);R(N_FLAG|H_FLAG);break;
|
||||
case CPL: R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break;
|
||||
case NOP: break;
|
||||
case OUTA: I=OpZ80(R->PC.W++);OutZ80(I|(R->AF.W&0xFF00),R->AF.B.h);break;
|
||||
case INA: I=OpZ80(R->PC.W++);R->AF.B.h=InZ80(I|(R->AF.W&0xFF00));break;
|
||||
|
||||
case HALT:
|
||||
R->PC.W--;
|
||||
R->IFF|=IFF_HALT;
|
||||
R->IBackup=0;
|
||||
R->ICount=0;
|
||||
break;
|
||||
|
||||
case DI:
|
||||
if(R->IFF&IFF_EI) R->ICount+=R->IBackup-1;
|
||||
R->IFF&=~(IFF_1|IFF_2|IFF_EI);
|
||||
break;
|
||||
|
||||
case EI:
|
||||
if(!(R->IFF&(IFF_1|IFF_EI)))
|
||||
{
|
||||
R->IFF|=IFF_2|IFF_EI;
|
||||
R->IBackup=R->ICount;
|
||||
R->ICount=1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CCF:
|
||||
R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG);
|
||||
R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG;
|
||||
break;
|
||||
|
||||
case EXX:
|
||||
J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W;
|
||||
J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W;
|
||||
J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W;
|
||||
break;
|
||||
|
||||
case EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break;
|
||||
case EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break;
|
||||
|
||||
case LD_B_B: R->BC.B.h=R->BC.B.h;break;
|
||||
case LD_C_B: R->BC.B.l=R->BC.B.h;break;
|
||||
case LD_D_B: R->DE.B.h=R->BC.B.h;break;
|
||||
case LD_E_B: R->DE.B.l=R->BC.B.h;break;
|
||||
case LD_H_B: R->XX.B.h=R->BC.B.h;break;
|
||||
case LD_L_B: R->XX.B.l=R->BC.B.h;break;
|
||||
case LD_A_B: R->AF.B.h=R->BC.B.h;break;
|
||||
case LD_xHL_B: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->BC.B.h);break;
|
||||
|
||||
case LD_B_C: R->BC.B.h=R->BC.B.l;break;
|
||||
case LD_C_C: R->BC.B.l=R->BC.B.l;break;
|
||||
case LD_D_C: R->DE.B.h=R->BC.B.l;break;
|
||||
case LD_E_C: R->DE.B.l=R->BC.B.l;break;
|
||||
case LD_H_C: R->XX.B.h=R->BC.B.l;break;
|
||||
case LD_L_C: R->XX.B.l=R->BC.B.l;break;
|
||||
case LD_A_C: R->AF.B.h=R->BC.B.l;break;
|
||||
case LD_xHL_C: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->BC.B.l);break;
|
||||
|
||||
case LD_B_D: R->BC.B.h=R->DE.B.h;break;
|
||||
case LD_C_D: R->BC.B.l=R->DE.B.h;break;
|
||||
case LD_D_D: R->DE.B.h=R->DE.B.h;break;
|
||||
case LD_E_D: R->DE.B.l=R->DE.B.h;break;
|
||||
case LD_H_D: R->XX.B.h=R->DE.B.h;break;
|
||||
case LD_L_D: R->XX.B.l=R->DE.B.h;break;
|
||||
case LD_A_D: R->AF.B.h=R->DE.B.h;break;
|
||||
case LD_xHL_D: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->DE.B.h);break;
|
||||
|
||||
case LD_B_E: R->BC.B.h=R->DE.B.l;break;
|
||||
case LD_C_E: R->BC.B.l=R->DE.B.l;break;
|
||||
case LD_D_E: R->DE.B.h=R->DE.B.l;break;
|
||||
case LD_E_E: R->DE.B.l=R->DE.B.l;break;
|
||||
case LD_H_E: R->XX.B.h=R->DE.B.l;break;
|
||||
case LD_L_E: R->XX.B.l=R->DE.B.l;break;
|
||||
case LD_A_E: R->AF.B.h=R->DE.B.l;break;
|
||||
case LD_xHL_E: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->DE.B.l);break;
|
||||
|
||||
case LD_B_H: R->BC.B.h=R->XX.B.h;break;
|
||||
case LD_C_H: R->BC.B.l=R->XX.B.h;break;
|
||||
case LD_D_H: R->DE.B.h=R->XX.B.h;break;
|
||||
case LD_E_H: R->DE.B.l=R->XX.B.h;break;
|
||||
case LD_H_H: R->XX.B.h=R->XX.B.h;break;
|
||||
case LD_L_H: R->XX.B.l=R->XX.B.h;break;
|
||||
case LD_A_H: R->AF.B.h=R->XX.B.h;break;
|
||||
case LD_xHL_H: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->HL.B.h);break;
|
||||
|
||||
case LD_B_L: R->BC.B.h=R->XX.B.l;break;
|
||||
case LD_C_L: R->BC.B.l=R->XX.B.l;break;
|
||||
case LD_D_L: R->DE.B.h=R->XX.B.l;break;
|
||||
case LD_E_L: R->DE.B.l=R->XX.B.l;break;
|
||||
case LD_H_L: R->XX.B.h=R->XX.B.l;break;
|
||||
case LD_L_L: R->XX.B.l=R->XX.B.l;break;
|
||||
case LD_A_L: R->AF.B.h=R->XX.B.l;break;
|
||||
case LD_xHL_L: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->HL.B.l);break;
|
||||
|
||||
case LD_B_A: R->BC.B.h=R->AF.B.h;break;
|
||||
case LD_C_A: R->BC.B.l=R->AF.B.h;break;
|
||||
case LD_D_A: R->DE.B.h=R->AF.B.h;break;
|
||||
case LD_E_A: R->DE.B.l=R->AF.B.h;break;
|
||||
case LD_H_A: R->XX.B.h=R->AF.B.h;break;
|
||||
case LD_L_A: R->XX.B.l=R->AF.B.h;break;
|
||||
case LD_A_A: R->AF.B.h=R->AF.B.h;break;
|
||||
case LD_xHL_A: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->AF.B.h);break;
|
||||
|
||||
case LD_xBC_A: WrZ80(R->BC.W,R->AF.B.h);break;
|
||||
case LD_xDE_A: WrZ80(R->DE.W,R->AF.B.h);break;
|
||||
|
||||
case LD_B_xHL: R->BC.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_C_xHL: R->BC.B.l=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_D_xHL: R->DE.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_E_xHL: R->DE.B.l=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_H_xHL: R->HL.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_L_xHL: R->HL.B.l=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
case LD_A_xHL: R->AF.B.h=RdZ80(R->XX.W+(offset)OpZ80(R->PC.W++));break;
|
||||
|
||||
case LD_B_BYTE: R->BC.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_C_BYTE: R->BC.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_D_BYTE: R->DE.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_E_BYTE: R->DE.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_H_BYTE: R->XX.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_L_BYTE: R->XX.B.l=OpZ80(R->PC.W++);break;
|
||||
case LD_A_BYTE: R->AF.B.h=OpZ80(R->PC.W++);break;
|
||||
case LD_xHL_BYTE: J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,OpZ80(R->PC.W++));break;
|
||||
|
||||
case LD_xWORD_HL:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W++,R->XX.B.l);
|
||||
WrZ80(J.W,R->XX.B.h);
|
||||
break;
|
||||
|
||||
case LD_HL_xWORD:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->XX.B.l=RdZ80(J.W++);
|
||||
R->XX.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_A_xWORD:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
R->AF.B.h=RdZ80(J.W);
|
||||
break;
|
||||
|
||||
case LD_xWORD_A:
|
||||
J.B.l=OpZ80(R->PC.W++);
|
||||
J.B.h=OpZ80(R->PC.W++);
|
||||
WrZ80(J.W,R->AF.B.h);
|
||||
break;
|
||||
|
||||
case EX_HL_xSP:
|
||||
J.B.l=RdZ80(R->SP.W);WrZ80(R->SP.W++,R->XX.B.l);
|
||||
J.B.h=RdZ80(R->SP.W);WrZ80(R->SP.W--,R->XX.B.h);
|
||||
R->XX.W=J.W;
|
||||
break;
|
||||
|
||||
case DAA:
|
||||
J.W=R->AF.B.h;
|
||||
if(R->AF.B.l&C_FLAG) J.W|=256;
|
||||
if(R->AF.B.l&H_FLAG) J.W|=512;
|
||||
if(R->AF.B.l&N_FLAG) J.W|=1024;
|
||||
R->AF.W=DAATable[J.W];
|
||||
break;
|
||||
276
MCUME_teensy41/teensyspeccy/ConDebug.c
Executable file
276
MCUME_teensy41/teensyspeccy/ConDebug.c
Executable file
|
|
@ -0,0 +1,276 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** ConDebug.c **/
|
||||
/** **/
|
||||
/** This file contains a console version of the built-in **/
|
||||
/** debugger, using EMULib's Console.c. When -DCONDEBUG is **/
|
||||
/** ommitted, ConDebug.c just includes the default command **/
|
||||
/** line based debugger (Debug.c). **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 2005-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#ifdef DEBUG
|
||||
|
||||
#ifndef CONDEBUG
|
||||
/** Normal DebugZ80() ****************************************/
|
||||
/** When CONDEBUG #undefined, we use plain command line. **/
|
||||
/*************************************************************/
|
||||
#include "Debug.c"
|
||||
|
||||
#else
|
||||
/** Console DebugZ80() ***************************************/
|
||||
/** When CONDEBUG #defined, we use EMULib console. **/
|
||||
/*************************************************************/
|
||||
|
||||
#include "Z80.h"
|
||||
#include "Console.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DebugZ80 OriginalDebugZ80
|
||||
#include "Debug.c"
|
||||
#undef DebugZ80
|
||||
|
||||
#define CLR_BACK PIXEL(255,255,255)
|
||||
#define CLR_TEXT PIXEL(0,0,0)
|
||||
#define CLR_DIALOG PIXEL(0,100,0)
|
||||
#define CLR_PC PIXEL(255,0,0)
|
||||
#define CLR_SP PIXEL(0,0,100)
|
||||
|
||||
static byte ChrDump(byte C)
|
||||
{
|
||||
return((C>=32)&&(C<128)? C:'.');
|
||||
}
|
||||
|
||||
/** DebugZ80() ***********************************************/
|
||||
/** This function should exist if DEBUG is #defined. When **/
|
||||
/** Trace!=0, it is called after each command executed by **/
|
||||
/** the CPU, and given the Z80 registers. **/
|
||||
/*************************************************************/
|
||||
byte DebugZ80(Z80 *R)
|
||||
{
|
||||
char S[1024];
|
||||
word A,Addr,ABuf[20];
|
||||
int J,I,K,X,Y,MemoryDump,DrawWindow,ExitNow;
|
||||
|
||||
/* If we don't have enough screen estate... */
|
||||
if((VideoW<32*8)||(VideoH<23*8))
|
||||
{
|
||||
/* Show warning message */
|
||||
CONMsg(
|
||||
-1,-1,-1,-1,PIXEL(255,255,255),PIXEL(255,0,0),
|
||||
"Error","Screen is\0too small!\0\0"
|
||||
);
|
||||
/* Continue emulation */
|
||||
R->Trace=0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
X = ((VideoW>>3)-32)>>1;
|
||||
Y = ((VideoH>>3)-23)>>1;
|
||||
Addr = R->PC.W;
|
||||
A = ~Addr;
|
||||
K = 0;
|
||||
|
||||
for(DrawWindow=1,MemoryDump=ExitNow=0;!ExitNow&&VideoImg;)
|
||||
{
|
||||
if(DrawWindow)
|
||||
{
|
||||
CONWindow(X,Y,32,23,CLR_TEXT,CLR_BACK,"Z80 Debugger");
|
||||
|
||||
sprintf(S,"PC %04X",R->PC.W);
|
||||
CONSetColor(CLR_BACK,CLR_PC);
|
||||
CONPrint(X+24,Y+18,S);
|
||||
sprintf(S,"SP %04X",R->SP.W);
|
||||
CONSetColor(CLR_BACK,CLR_SP);
|
||||
CONPrint(X+24,Y+19,S);
|
||||
|
||||
CONSetColor(CLR_TEXT,CLR_BACK);
|
||||
sprintf(S,
|
||||
" %c%c%c%c%c%c\n\n"
|
||||
"AF %04X\nBC %04X\nDE %04X\nHL %04X\nIX %04X\nIY %04X\n\n"
|
||||
"AF'%04X\nBC'%04X\nDE'%04X\nHL'%04X\n\n"
|
||||
"IR %02X%02X",
|
||||
R->AF.B.l&0x80? 'S':'.',R->AF.B.l&0x40? 'Z':'.',R->AF.B.l&0x10? 'H':'.',
|
||||
R->AF.B.l&0x04? 'P':'.',R->AF.B.l&0x02? 'N':'.',R->AF.B.l&0x01? 'C':'.',
|
||||
R->AF.W,R->BC.W,R->DE.W,R->HL.W,
|
||||
R->IX.W,R->IY.W,
|
||||
R->AF1.W,R->BC1.W,R->DE1.W,R->HL1.W,
|
||||
R->I,R->R
|
||||
);
|
||||
CONPrint(X+24,Y+2,S);
|
||||
sprintf(S,
|
||||
"%s %s",
|
||||
R->IFF&0x04? "IM2":R->IFF&0x02? "IM1":"IM0",
|
||||
R->IFF&0x01? "EI":"DI"
|
||||
);
|
||||
CONPrint(X+25,Y+21,S);
|
||||
DrawWindow=0;
|
||||
A=~Addr;
|
||||
}
|
||||
|
||||
/* If top address has changed... */
|
||||
if(A!=Addr)
|
||||
{
|
||||
/* Clear display */
|
||||
CONBox((X+1)<<3,(Y+2)<<3,23*8,20*8,CLR_BACK);
|
||||
|
||||
if(MemoryDump)
|
||||
{
|
||||
/* Draw memory dump */
|
||||
for(J=0,A=Addr;J<20;J++,A+=4)
|
||||
{
|
||||
if(A==R->PC.W) CONSetColor(CLR_BACK,CLR_PC);
|
||||
else if(A==R->SP.W) CONSetColor(CLR_BACK,CLR_SP);
|
||||
else CONSetColor(CLR_TEXT,CLR_BACK);
|
||||
sprintf(S,"%04X%c",A,A==R->PC.W? CON_MORE:A==R->SP.W? CON_LESS:':');
|
||||
CONPrint(X+1,Y+J+2,S);
|
||||
|
||||
CONSetColor(CLR_TEXT,CLR_BACK);
|
||||
sprintf(S,
|
||||
"%02X %02X %02X %02X %c%c%c%c",
|
||||
RdZ80(A),RdZ80(A+1),RdZ80(A+2),RdZ80(A+3),
|
||||
ChrDump(RdZ80(A)),ChrDump(RdZ80(A+1)),
|
||||
ChrDump(RdZ80(A+2)),ChrDump(RdZ80(A+3))
|
||||
);
|
||||
CONPrint(X+7,Y+J+2,S);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Draw listing */
|
||||
for(J=0,A=Addr;J<20;J++)
|
||||
{
|
||||
if(A==R->PC.W) CONSetColor(CLR_BACK,CLR_PC);
|
||||
else if(A==R->SP.W) CONSetColor(CLR_BACK,CLR_SP);
|
||||
else CONSetColor(CLR_TEXT,CLR_BACK);
|
||||
sprintf(S,"%04X%c",A,A==R->PC.W? CON_MORE:A==R->SP.W? CON_LESS:':');
|
||||
CONPrint(X+1,Y+J+2,S);
|
||||
|
||||
ABuf[J]=A;
|
||||
A+=DAsm(S,A);
|
||||
|
||||
CONSetColor(CLR_TEXT,CLR_BACK);
|
||||
CONPrintN(X+7,Y+J+2,S,23);
|
||||
}
|
||||
}
|
||||
|
||||
/* Display redrawn */
|
||||
A=Addr;
|
||||
}
|
||||
|
||||
/* Draw pointer */
|
||||
CONChar(X+6,Y+K+2,CON_ARROW);
|
||||
|
||||
/* Show screen buffer */
|
||||
ShowVideo();
|
||||
|
||||
/* Get key code */
|
||||
I=WaitKey();
|
||||
|
||||
/* Clear pointer */
|
||||
CONChar(X+6,Y+K+2,' ');
|
||||
|
||||
/* Get and process key code */
|
||||
switch(I)
|
||||
{
|
||||
case 'H':
|
||||
CONMsg(
|
||||
-1,-1,-1,-1,
|
||||
CLR_BACK,CLR_DIALOG,
|
||||
"Debugger Help",
|
||||
"ENTER - Execute next opcode\0"
|
||||
" UP - Previous opcode\0"
|
||||
" DOWN - Next opcode\0"
|
||||
" LEFT - Page up\0"
|
||||
"RIGHT - Page down\0"
|
||||
" H - This help page\0"
|
||||
" G - Go to address\0"
|
||||
" D - Disassembler view\0"
|
||||
" M - Memory dump view\0"
|
||||
" S - Show stack\0"
|
||||
" J - Jump to cursor\0"
|
||||
" R - Run to cursor\0"
|
||||
" C - Continue execution\0"
|
||||
" Q - Quit emulator\0"
|
||||
);
|
||||
DrawWindow=1;
|
||||
break;
|
||||
case CON_UP:
|
||||
if(K) --K;
|
||||
else
|
||||
if(MemoryDump) Addr-=4;
|
||||
else for(--Addr;Addr+DAsm(S,Addr)>A;--Addr);
|
||||
break;
|
||||
case CON_DOWN:
|
||||
if(K<19) ++K;
|
||||
else
|
||||
if(MemoryDump) Addr+=4;
|
||||
else Addr+=DAsm(S,Addr);
|
||||
break;
|
||||
case CON_LEFT:
|
||||
if(MemoryDump)
|
||||
Addr-=4*20;
|
||||
else
|
||||
{
|
||||
for(I=20,Addr=~A;(Addr>A)||((A^Addr)&~Addr&0x8000);++I)
|
||||
for(J=0,Addr=A-I;J<20;++J) Addr+=DAsm(S,Addr);
|
||||
Addr=A-I+1;
|
||||
}
|
||||
break;
|
||||
case CON_RIGHT:
|
||||
if(MemoryDump)
|
||||
Addr+=4*20;
|
||||
else
|
||||
for(J=0;J<20;++J) Addr+=DAsm(S,Addr);
|
||||
break;
|
||||
case CON_OK:
|
||||
ExitNow=1;
|
||||
break;
|
||||
case 'Q':
|
||||
return(0);
|
||||
case CON_EXIT:
|
||||
case 'C':
|
||||
R->Trap=0xFFFF;
|
||||
R->Trace=0;
|
||||
ExitNow=1;
|
||||
break;
|
||||
case 'R':
|
||||
R->Trap=ABuf[K];
|
||||
R->Trace=0;
|
||||
ExitNow=1;
|
||||
break;
|
||||
case 'M':
|
||||
MemoryDump=1;
|
||||
A=~Addr;
|
||||
break;
|
||||
case 'S':
|
||||
MemoryDump=1;
|
||||
Addr=R->SP.W;
|
||||
K=0;
|
||||
A=~Addr;
|
||||
break;
|
||||
case 'D':
|
||||
MemoryDump=0;
|
||||
A=~Addr;
|
||||
break;
|
||||
case 'G':
|
||||
if(CONInput(-1,-1,CLR_BACK,CLR_DIALOG,"Go to Address:",S,5|CON_HEX))
|
||||
{ Addr=strtol(S,0,16);K=0; }
|
||||
DrawWindow=1;
|
||||
break;
|
||||
case 'J':
|
||||
R->PC.W=ABuf[K];
|
||||
A=~Addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Continue emulation */
|
||||
return(1);
|
||||
}
|
||||
|
||||
#endif /* CONDEBUG */
|
||||
#endif /* DEBUG */
|
||||
447
MCUME_teensy41/teensyspeccy/Tables.h
Executable file
447
MCUME_teensy41/teensyspeccy/Tables.h
Executable file
|
|
@ -0,0 +1,447 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Tables.h **/
|
||||
/** **/
|
||||
/** This file contains tables of used by Z80 emulation to **/
|
||||
/** compute SIGN,ZERO, PARITY flags, and decimal correction **/
|
||||
/** There are also timing tables for Z80 opcodes. This file **/
|
||||
/** is included from Z80.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
static const byte Cycles[256] =
|
||||
{
|
||||
4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4,
|
||||
8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4,
|
||||
7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4,
|
||||
7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
|
||||
5,10,10,10,10,11, 7,11, 5,10,10, 0,10,17, 7,11,
|
||||
5,10,10,11,10,11, 7,11, 5, 4,10,11,10, 0, 7,11,
|
||||
5,10,10,19,10,11, 7,11, 5, 4,10, 4,10, 0, 7,11,
|
||||
5,10,10, 4,10,11, 7,11, 5, 6,10, 4,10, 0, 7,11
|
||||
};
|
||||
|
||||
static const byte CyclesCB[256] =
|
||||
{
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8,
|
||||
8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8
|
||||
};
|
||||
|
||||
static const byte CyclesED[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
12,12,15,20, 8,14, 8, 9,12,12,15,20, 0,14, 0, 9,
|
||||
12,12,15,20, 0, 0, 8, 9,12,12,15,20, 0, 0, 8, 9,
|
||||
12,12,15,20, 0, 0, 0,18,12,12,15,20, 0, 0, 0,18,
|
||||
12, 0,15,20, 0, 0, 0, 0,12,12,15,20, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
16,16,16,16, 0, 0, 0, 0,16,16,16,16, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static const byte CyclesXX[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,15, 0, 0, 0, 0, 0, 0,
|
||||
0,14,20,10, 9, 9, 9, 0, 0,15,20,10, 9, 9, 9, 0,
|
||||
0, 0, 0, 0,23,23,19, 0, 0,15, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
9, 9, 9, 9, 9, 9,19, 9, 9, 9, 9, 9, 9, 9,19, 9,
|
||||
19,19,19,19,19,19,19,19, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 9, 9,19, 0, 0, 0, 0, 0, 9, 9,19, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,14, 0,23, 0,15, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,10, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static const byte CyclesXXCB[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0,
|
||||
0, 0, 0, 0, 0, 0,23, 0, 0, 0, 0, 0, 0, 0,23, 0
|
||||
};
|
||||
|
||||
static const byte ZSTable[256] =
|
||||
{
|
||||
Z_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG,S_FLAG
|
||||
};
|
||||
|
||||
static const byte PZSTable[256] =
|
||||
{
|
||||
Z_FLAG|P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,
|
||||
0,P_FLAG,P_FLAG,0,P_FLAG,0,0,P_FLAG,P_FLAG,0,0,P_FLAG,0,P_FLAG,P_FLAG,0,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG,S_FLAG|P_FLAG,S_FLAG|P_FLAG,S_FLAG,
|
||||
S_FLAG|P_FLAG,S_FLAG,S_FLAG,S_FLAG|P_FLAG
|
||||
};
|
||||
|
||||
static const word DAATable[2048] =
|
||||
{
|
||||
0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700,
|
||||
0x0808,0x090C,0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,
|
||||
0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704,
|
||||
0x180C,0x1908,0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,
|
||||
0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724,
|
||||
0x282C,0x2928,0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,
|
||||
0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720,
|
||||
0x3828,0x392C,0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,
|
||||
0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704,
|
||||
0x480C,0x4908,0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,
|
||||
0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700,
|
||||
0x5808,0x590C,0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,
|
||||
0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720,
|
||||
0x6828,0x692C,0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,
|
||||
0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724,
|
||||
0x782C,0x7928,0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,
|
||||
0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784,
|
||||
0x888C,0x8988,0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,
|
||||
0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780,
|
||||
0x9888,0x998C,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0045,0x0101,0x0201,0x0305,0x0401,0x0505,0x0605,0x0701,
|
||||
0x0809,0x090D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1001,0x1105,0x1205,0x1301,0x1405,0x1501,0x1601,0x1705,
|
||||
0x180D,0x1909,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2021,0x2125,0x2225,0x2321,0x2425,0x2521,0x2621,0x2725,
|
||||
0x282D,0x2929,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3025,0x3121,0x3221,0x3325,0x3421,0x3525,0x3625,0x3721,
|
||||
0x3829,0x392D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4001,0x4105,0x4205,0x4301,0x4405,0x4501,0x4601,0x4705,
|
||||
0x480D,0x4909,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5005,0x5101,0x5201,0x5305,0x5401,0x5505,0x5605,0x5701,
|
||||
0x5809,0x590D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x6025,0x6121,0x6221,0x6325,0x6421,0x6525,0x6625,0x6721,
|
||||
0x6829,0x692D,0x7031,0x7135,0x7235,0x7331,0x7435,0x7531,
|
||||
0x7021,0x7125,0x7225,0x7321,0x7425,0x7521,0x7621,0x7725,
|
||||
0x782D,0x7929,0x8091,0x8195,0x8295,0x8391,0x8495,0x8591,
|
||||
0x8081,0x8185,0x8285,0x8381,0x8485,0x8581,0x8681,0x8785,
|
||||
0x888D,0x8989,0x9095,0x9191,0x9291,0x9395,0x9491,0x9595,
|
||||
0x9085,0x9181,0x9281,0x9385,0x9481,0x9585,0x9685,0x9781,
|
||||
0x9889,0x998D,0xA0B5,0xA1B1,0xA2B1,0xA3B5,0xA4B1,0xA5B5,
|
||||
0xA0A5,0xA1A1,0xA2A1,0xA3A5,0xA4A1,0xA5A5,0xA6A5,0xA7A1,
|
||||
0xA8A9,0xA9AD,0xB0B1,0xB1B5,0xB2B5,0xB3B1,0xB4B5,0xB5B1,
|
||||
0xB0A1,0xB1A5,0xB2A5,0xB3A1,0xB4A5,0xB5A1,0xB6A1,0xB7A5,
|
||||
0xB8AD,0xB9A9,0xC095,0xC191,0xC291,0xC395,0xC491,0xC595,
|
||||
0xC085,0xC181,0xC281,0xC385,0xC481,0xC585,0xC685,0xC781,
|
||||
0xC889,0xC98D,0xD091,0xD195,0xD295,0xD391,0xD495,0xD591,
|
||||
0xD081,0xD185,0xD285,0xD381,0xD485,0xD581,0xD681,0xD785,
|
||||
0xD88D,0xD989,0xE0B1,0xE1B5,0xE2B5,0xE3B1,0xE4B5,0xE5B1,
|
||||
0xE0A1,0xE1A5,0xE2A5,0xE3A1,0xE4A5,0xE5A1,0xE6A1,0xE7A5,
|
||||
0xE8AD,0xE9A9,0xF0B5,0xF1B1,0xF2B1,0xF3B5,0xF4B1,0xF5B5,
|
||||
0xF0A5,0xF1A1,0xF2A1,0xF3A5,0xF4A1,0xF5A5,0xF6A5,0xF7A1,
|
||||
0xF8A9,0xF9AD,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0045,0x0101,0x0201,0x0305,0x0401,0x0505,0x0605,0x0701,
|
||||
0x0809,0x090D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1001,0x1105,0x1205,0x1301,0x1405,0x1501,0x1601,0x1705,
|
||||
0x180D,0x1909,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2021,0x2125,0x2225,0x2321,0x2425,0x2521,0x2621,0x2725,
|
||||
0x282D,0x2929,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3025,0x3121,0x3221,0x3325,0x3421,0x3525,0x3625,0x3721,
|
||||
0x3829,0x392D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4001,0x4105,0x4205,0x4301,0x4405,0x4501,0x4601,0x4705,
|
||||
0x480D,0x4909,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5005,0x5101,0x5201,0x5305,0x5401,0x5505,0x5605,0x5701,
|
||||
0x5809,0x590D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x0604,0x0700,0x0808,0x090C,0x0A0C,0x0B08,0x0C0C,0x0D08,
|
||||
0x0E08,0x0F0C,0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,
|
||||
0x1600,0x1704,0x180C,0x1908,0x1A08,0x1B0C,0x1C08,0x1D0C,
|
||||
0x1E0C,0x1F08,0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,
|
||||
0x2620,0x2724,0x282C,0x2928,0x2A28,0x2B2C,0x2C28,0x2D2C,
|
||||
0x2E2C,0x2F28,0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,
|
||||
0x3624,0x3720,0x3828,0x392C,0x3A2C,0x3B28,0x3C2C,0x3D28,
|
||||
0x3E28,0x3F2C,0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,
|
||||
0x4600,0x4704,0x480C,0x4908,0x4A08,0x4B0C,0x4C08,0x4D0C,
|
||||
0x4E0C,0x4F08,0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,
|
||||
0x5604,0x5700,0x5808,0x590C,0x5A0C,0x5B08,0x5C0C,0x5D08,
|
||||
0x5E08,0x5F0C,0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,
|
||||
0x6624,0x6720,0x6828,0x692C,0x6A2C,0x6B28,0x6C2C,0x6D28,
|
||||
0x6E28,0x6F2C,0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,
|
||||
0x7620,0x7724,0x782C,0x7928,0x7A28,0x7B2C,0x7C28,0x7D2C,
|
||||
0x7E2C,0x7F28,0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,
|
||||
0x8680,0x8784,0x888C,0x8988,0x8A88,0x8B8C,0x8C88,0x8D8C,
|
||||
0x8E8C,0x8F88,0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,
|
||||
0x9684,0x9780,0x9888,0x998C,0x9A8C,0x9B88,0x9C8C,0x9D88,
|
||||
0x9E88,0x9F8C,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0605,0x0701,0x0809,0x090D,0x0A0D,0x0B09,0x0C0D,0x0D09,
|
||||
0x0E09,0x0F0D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1601,0x1705,0x180D,0x1909,0x1A09,0x1B0D,0x1C09,0x1D0D,
|
||||
0x1E0D,0x1F09,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2621,0x2725,0x282D,0x2929,0x2A29,0x2B2D,0x2C29,0x2D2D,
|
||||
0x2E2D,0x2F29,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3625,0x3721,0x3829,0x392D,0x3A2D,0x3B29,0x3C2D,0x3D29,
|
||||
0x3E29,0x3F2D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4601,0x4705,0x480D,0x4909,0x4A09,0x4B0D,0x4C09,0x4D0D,
|
||||
0x4E0D,0x4F09,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5605,0x5701,0x5809,0x590D,0x5A0D,0x5B09,0x5C0D,0x5D09,
|
||||
0x5E09,0x5F0D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x6625,0x6721,0x6829,0x692D,0x6A2D,0x6B29,0x6C2D,0x6D29,
|
||||
0x6E29,0x6F2D,0x7031,0x7135,0x7235,0x7331,0x7435,0x7531,
|
||||
0x7621,0x7725,0x782D,0x7929,0x7A29,0x7B2D,0x7C29,0x7D2D,
|
||||
0x7E2D,0x7F29,0x8091,0x8195,0x8295,0x8391,0x8495,0x8591,
|
||||
0x8681,0x8785,0x888D,0x8989,0x8A89,0x8B8D,0x8C89,0x8D8D,
|
||||
0x8E8D,0x8F89,0x9095,0x9191,0x9291,0x9395,0x9491,0x9595,
|
||||
0x9685,0x9781,0x9889,0x998D,0x9A8D,0x9B89,0x9C8D,0x9D89,
|
||||
0x9E89,0x9F8D,0xA0B5,0xA1B1,0xA2B1,0xA3B5,0xA4B1,0xA5B5,
|
||||
0xA6A5,0xA7A1,0xA8A9,0xA9AD,0xAAAD,0xABA9,0xACAD,0xADA9,
|
||||
0xAEA9,0xAFAD,0xB0B1,0xB1B5,0xB2B5,0xB3B1,0xB4B5,0xB5B1,
|
||||
0xB6A1,0xB7A5,0xB8AD,0xB9A9,0xBAA9,0xBBAD,0xBCA9,0xBDAD,
|
||||
0xBEAD,0xBFA9,0xC095,0xC191,0xC291,0xC395,0xC491,0xC595,
|
||||
0xC685,0xC781,0xC889,0xC98D,0xCA8D,0xCB89,0xCC8D,0xCD89,
|
||||
0xCE89,0xCF8D,0xD091,0xD195,0xD295,0xD391,0xD495,0xD591,
|
||||
0xD681,0xD785,0xD88D,0xD989,0xDA89,0xDB8D,0xDC89,0xDD8D,
|
||||
0xDE8D,0xDF89,0xE0B1,0xE1B5,0xE2B5,0xE3B1,0xE4B5,0xE5B1,
|
||||
0xE6A1,0xE7A5,0xE8AD,0xE9A9,0xEAA9,0xEBAD,0xECA9,0xEDAD,
|
||||
0xEEAD,0xEFA9,0xF0B5,0xF1B1,0xF2B1,0xF3B5,0xF4B1,0xF5B5,
|
||||
0xF6A5,0xF7A1,0xF8A9,0xF9AD,0xFAAD,0xFBA9,0xFCAD,0xFDA9,
|
||||
0xFEA9,0xFFAD,0x0055,0x0111,0x0211,0x0315,0x0411,0x0515,
|
||||
0x0605,0x0701,0x0809,0x090D,0x0A0D,0x0B09,0x0C0D,0x0D09,
|
||||
0x0E09,0x0F0D,0x1011,0x1115,0x1215,0x1311,0x1415,0x1511,
|
||||
0x1601,0x1705,0x180D,0x1909,0x1A09,0x1B0D,0x1C09,0x1D0D,
|
||||
0x1E0D,0x1F09,0x2031,0x2135,0x2235,0x2331,0x2435,0x2531,
|
||||
0x2621,0x2725,0x282D,0x2929,0x2A29,0x2B2D,0x2C29,0x2D2D,
|
||||
0x2E2D,0x2F29,0x3035,0x3131,0x3231,0x3335,0x3431,0x3535,
|
||||
0x3625,0x3721,0x3829,0x392D,0x3A2D,0x3B29,0x3C2D,0x3D29,
|
||||
0x3E29,0x3F2D,0x4011,0x4115,0x4215,0x4311,0x4415,0x4511,
|
||||
0x4601,0x4705,0x480D,0x4909,0x4A09,0x4B0D,0x4C09,0x4D0D,
|
||||
0x4E0D,0x4F09,0x5015,0x5111,0x5211,0x5315,0x5411,0x5515,
|
||||
0x5605,0x5701,0x5809,0x590D,0x5A0D,0x5B09,0x5C0D,0x5D09,
|
||||
0x5E09,0x5F0D,0x6035,0x6131,0x6231,0x6335,0x6431,0x6535,
|
||||
0x0046,0x0102,0x0202,0x0306,0x0402,0x0506,0x0606,0x0702,
|
||||
0x080A,0x090E,0x0402,0x0506,0x0606,0x0702,0x080A,0x090E,
|
||||
0x1002,0x1106,0x1206,0x1302,0x1406,0x1502,0x1602,0x1706,
|
||||
0x180E,0x190A,0x1406,0x1502,0x1602,0x1706,0x180E,0x190A,
|
||||
0x2022,0x2126,0x2226,0x2322,0x2426,0x2522,0x2622,0x2726,
|
||||
0x282E,0x292A,0x2426,0x2522,0x2622,0x2726,0x282E,0x292A,
|
||||
0x3026,0x3122,0x3222,0x3326,0x3422,0x3526,0x3626,0x3722,
|
||||
0x382A,0x392E,0x3422,0x3526,0x3626,0x3722,0x382A,0x392E,
|
||||
0x4002,0x4106,0x4206,0x4302,0x4406,0x4502,0x4602,0x4706,
|
||||
0x480E,0x490A,0x4406,0x4502,0x4602,0x4706,0x480E,0x490A,
|
||||
0x5006,0x5102,0x5202,0x5306,0x5402,0x5506,0x5606,0x5702,
|
||||
0x580A,0x590E,0x5402,0x5506,0x5606,0x5702,0x580A,0x590E,
|
||||
0x6026,0x6122,0x6222,0x6326,0x6422,0x6526,0x6626,0x6722,
|
||||
0x682A,0x692E,0x6422,0x6526,0x6626,0x6722,0x682A,0x692E,
|
||||
0x7022,0x7126,0x7226,0x7322,0x7426,0x7522,0x7622,0x7726,
|
||||
0x782E,0x792A,0x7426,0x7522,0x7622,0x7726,0x782E,0x792A,
|
||||
0x8082,0x8186,0x8286,0x8382,0x8486,0x8582,0x8682,0x8786,
|
||||
0x888E,0x898A,0x8486,0x8582,0x8682,0x8786,0x888E,0x898A,
|
||||
0x9086,0x9182,0x9282,0x9386,0x9482,0x9586,0x9686,0x9782,
|
||||
0x988A,0x998E,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x4003,0x4107,0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,
|
||||
0x480F,0x490B,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x5007,0x5103,0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,
|
||||
0x580B,0x590F,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,
|
||||
0x682B,0x692F,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x7023,0x7127,0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,
|
||||
0x782F,0x792B,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x8083,0x8187,0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,
|
||||
0x888F,0x898B,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x9087,0x9183,0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,
|
||||
0x988B,0x998F,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,
|
||||
0xA0A7,0xA1A3,0xA2A3,0xA3A7,0xA4A3,0xA5A7,0xA6A7,0xA7A3,
|
||||
0xA8AB,0xA9AF,0xA4A3,0xA5A7,0xA6A7,0xA7A3,0xA8AB,0xA9AF,
|
||||
0xB0A3,0xB1A7,0xB2A7,0xB3A3,0xB4A7,0xB5A3,0xB6A3,0xB7A7,
|
||||
0xB8AF,0xB9AB,0xB4A7,0xB5A3,0xB6A3,0xB7A7,0xB8AF,0xB9AB,
|
||||
0xC087,0xC183,0xC283,0xC387,0xC483,0xC587,0xC687,0xC783,
|
||||
0xC88B,0xC98F,0xC483,0xC587,0xC687,0xC783,0xC88B,0xC98F,
|
||||
0xD083,0xD187,0xD287,0xD383,0xD487,0xD583,0xD683,0xD787,
|
||||
0xD88F,0xD98B,0xD487,0xD583,0xD683,0xD787,0xD88F,0xD98B,
|
||||
0xE0A3,0xE1A7,0xE2A7,0xE3A3,0xE4A7,0xE5A3,0xE6A3,0xE7A7,
|
||||
0xE8AF,0xE9AB,0xE4A7,0xE5A3,0xE6A3,0xE7A7,0xE8AF,0xE9AB,
|
||||
0xF0A7,0xF1A3,0xF2A3,0xF3A7,0xF4A3,0xF5A7,0xF6A7,0xF7A3,
|
||||
0xF8AB,0xF9AF,0xF4A3,0xF5A7,0xF6A7,0xF7A3,0xF8AB,0xF9AF,
|
||||
0x0047,0x0103,0x0203,0x0307,0x0403,0x0507,0x0607,0x0703,
|
||||
0x080B,0x090F,0x0403,0x0507,0x0607,0x0703,0x080B,0x090F,
|
||||
0x1003,0x1107,0x1207,0x1303,0x1407,0x1503,0x1603,0x1707,
|
||||
0x180F,0x190B,0x1407,0x1503,0x1603,0x1707,0x180F,0x190B,
|
||||
0x2023,0x2127,0x2227,0x2323,0x2427,0x2523,0x2623,0x2727,
|
||||
0x282F,0x292B,0x2427,0x2523,0x2623,0x2727,0x282F,0x292B,
|
||||
0x3027,0x3123,0x3223,0x3327,0x3423,0x3527,0x3627,0x3723,
|
||||
0x382B,0x392F,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x4003,0x4107,0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,
|
||||
0x480F,0x490B,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x5007,0x5103,0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,
|
||||
0x580B,0x590F,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x6027,0x6123,0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,
|
||||
0x682B,0x692F,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x7023,0x7127,0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,
|
||||
0x782F,0x792B,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x8083,0x8187,0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,
|
||||
0x888F,0x898B,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x9087,0x9183,0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,
|
||||
0x988B,0x998F,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,
|
||||
0xFABE,0xFBBA,0xFCBE,0xFDBA,0xFEBA,0xFFBE,0x0046,0x0102,
|
||||
0x0202,0x0306,0x0402,0x0506,0x0606,0x0702,0x080A,0x090E,
|
||||
0x0A1E,0x0B1A,0x0C1E,0x0D1A,0x0E1A,0x0F1E,0x1002,0x1106,
|
||||
0x1206,0x1302,0x1406,0x1502,0x1602,0x1706,0x180E,0x190A,
|
||||
0x1A1A,0x1B1E,0x1C1A,0x1D1E,0x1E1E,0x1F1A,0x2022,0x2126,
|
||||
0x2226,0x2322,0x2426,0x2522,0x2622,0x2726,0x282E,0x292A,
|
||||
0x2A3A,0x2B3E,0x2C3A,0x2D3E,0x2E3E,0x2F3A,0x3026,0x3122,
|
||||
0x3222,0x3326,0x3422,0x3526,0x3626,0x3722,0x382A,0x392E,
|
||||
0x3A3E,0x3B3A,0x3C3E,0x3D3A,0x3E3A,0x3F3E,0x4002,0x4106,
|
||||
0x4206,0x4302,0x4406,0x4502,0x4602,0x4706,0x480E,0x490A,
|
||||
0x4A1A,0x4B1E,0x4C1A,0x4D1E,0x4E1E,0x4F1A,0x5006,0x5102,
|
||||
0x5202,0x5306,0x5402,0x5506,0x5606,0x5702,0x580A,0x590E,
|
||||
0x5A1E,0x5B1A,0x5C1E,0x5D1A,0x5E1A,0x5F1E,0x6026,0x6122,
|
||||
0x6222,0x6326,0x6422,0x6526,0x6626,0x6722,0x682A,0x692E,
|
||||
0x6A3E,0x6B3A,0x6C3E,0x6D3A,0x6E3A,0x6F3E,0x7022,0x7126,
|
||||
0x7226,0x7322,0x7426,0x7522,0x7622,0x7726,0x782E,0x792A,
|
||||
0x7A3A,0x7B3E,0x7C3A,0x7D3E,0x7E3E,0x7F3A,0x8082,0x8186,
|
||||
0x8286,0x8382,0x8486,0x8582,0x8682,0x8786,0x888E,0x898A,
|
||||
0x8A9A,0x8B9E,0x8C9A,0x8D9E,0x8E9E,0x8F9A,0x9086,0x9182,
|
||||
0x9282,0x9386,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x3A3F,0x3B3B,0x3C3F,0x3D3B,0x3E3B,0x3F3F,0x4003,0x4107,
|
||||
0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x4A1B,0x4B1F,0x4C1B,0x4D1F,0x4E1F,0x4F1B,0x5007,0x5103,
|
||||
0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x5A1F,0x5B1B,0x5C1F,0x5D1B,0x5E1B,0x5F1F,0x6027,0x6123,
|
||||
0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x6A3F,0x6B3B,0x6C3F,0x6D3B,0x6E3B,0x6F3F,0x7023,0x7127,
|
||||
0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x7A3B,0x7B3F,0x7C3B,0x7D3F,0x7E3F,0x7F3B,0x8083,0x8187,
|
||||
0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x8A9B,0x8B9F,0x8C9B,0x8D9F,0x8E9F,0x8F9B,0x9087,0x9183,
|
||||
0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F,
|
||||
0x9A9F,0x9B9B,0x9C9F,0x9D9B,0x9E9B,0x9F9F,0xA0A7,0xA1A3,
|
||||
0xA2A3,0xA3A7,0xA4A3,0xA5A7,0xA6A7,0xA7A3,0xA8AB,0xA9AF,
|
||||
0xAABF,0xABBB,0xACBF,0xADBB,0xAEBB,0xAFBF,0xB0A3,0xB1A7,
|
||||
0xB2A7,0xB3A3,0xB4A7,0xB5A3,0xB6A3,0xB7A7,0xB8AF,0xB9AB,
|
||||
0xBABB,0xBBBF,0xBCBB,0xBDBF,0xBEBF,0xBFBB,0xC087,0xC183,
|
||||
0xC283,0xC387,0xC483,0xC587,0xC687,0xC783,0xC88B,0xC98F,
|
||||
0xCA9F,0xCB9B,0xCC9F,0xCD9B,0xCE9B,0xCF9F,0xD083,0xD187,
|
||||
0xD287,0xD383,0xD487,0xD583,0xD683,0xD787,0xD88F,0xD98B,
|
||||
0xDA9B,0xDB9F,0xDC9B,0xDD9F,0xDE9F,0xDF9B,0xE0A3,0xE1A7,
|
||||
0xE2A7,0xE3A3,0xE4A7,0xE5A3,0xE6A3,0xE7A7,0xE8AF,0xE9AB,
|
||||
0xEABB,0xEBBF,0xECBB,0xEDBF,0xEEBF,0xEFBB,0xF0A7,0xF1A3,
|
||||
0xF2A3,0xF3A7,0xF4A3,0xF5A7,0xF6A7,0xF7A3,0xF8AB,0xF9AF,
|
||||
0xFABF,0xFBBB,0xFCBF,0xFDBB,0xFEBB,0xFFBF,0x0047,0x0103,
|
||||
0x0203,0x0307,0x0403,0x0507,0x0607,0x0703,0x080B,0x090F,
|
||||
0x0A1F,0x0B1B,0x0C1F,0x0D1B,0x0E1B,0x0F1F,0x1003,0x1107,
|
||||
0x1207,0x1303,0x1407,0x1503,0x1603,0x1707,0x180F,0x190B,
|
||||
0x1A1B,0x1B1F,0x1C1B,0x1D1F,0x1E1F,0x1F1B,0x2023,0x2127,
|
||||
0x2227,0x2323,0x2427,0x2523,0x2623,0x2727,0x282F,0x292B,
|
||||
0x2A3B,0x2B3F,0x2C3B,0x2D3F,0x2E3F,0x2F3B,0x3027,0x3123,
|
||||
0x3223,0x3327,0x3423,0x3527,0x3627,0x3723,0x382B,0x392F,
|
||||
0x3A3F,0x3B3B,0x3C3F,0x3D3B,0x3E3B,0x3F3F,0x4003,0x4107,
|
||||
0x4207,0x4303,0x4407,0x4503,0x4603,0x4707,0x480F,0x490B,
|
||||
0x4A1B,0x4B1F,0x4C1B,0x4D1F,0x4E1F,0x4F1B,0x5007,0x5103,
|
||||
0x5203,0x5307,0x5403,0x5507,0x5607,0x5703,0x580B,0x590F,
|
||||
0x5A1F,0x5B1B,0x5C1F,0x5D1B,0x5E1B,0x5F1F,0x6027,0x6123,
|
||||
0x6223,0x6327,0x6423,0x6527,0x6627,0x6723,0x682B,0x692F,
|
||||
0x6A3F,0x6B3B,0x6C3F,0x6D3B,0x6E3B,0x6F3F,0x7023,0x7127,
|
||||
0x7227,0x7323,0x7427,0x7523,0x7623,0x7727,0x782F,0x792B,
|
||||
0x7A3B,0x7B3F,0x7C3B,0x7D3F,0x7E3F,0x7F3B,0x8083,0x8187,
|
||||
0x8287,0x8383,0x8487,0x8583,0x8683,0x8787,0x888F,0x898B,
|
||||
0x8A9B,0x8B9F,0x8C9B,0x8D9F,0x8E9F,0x8F9B,0x9087,0x9183,
|
||||
0x9283,0x9387,0x9483,0x9587,0x9687,0x9783,0x988B,0x998F
|
||||
};
|
||||
685
MCUME_teensy41/teensyspeccy/Z80.c
Normal file
685
MCUME_teensy41/teensyspeccy/Z80.c
Normal file
|
|
@ -0,0 +1,685 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Z80.c **/
|
||||
/** **/
|
||||
/** This file contains implementation for Z80 CPU. Don't **/
|
||||
/** forget to provide RdZ80(), WrZ80(), InZ80(), OutZ80(), **/
|
||||
/** LoopZ80(), and PatchZ80() functions to accomodate the **/
|
||||
/** emulated machine's architecture. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
#include "Z80.h"
|
||||
#include "Tables.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/** INLINE ***************************************************/
|
||||
/** C99 standard has "inline", but older compilers used **/
|
||||
/** __inline for the same purpose. **/
|
||||
/*************************************************************/
|
||||
#ifdef __C99__
|
||||
#define INLINE static inline
|
||||
#else
|
||||
#define INLINE static __inline
|
||||
#endif
|
||||
|
||||
/** System-Dependent Stuff ***********************************/
|
||||
/** This is system-dependent code put here to speed things **/
|
||||
/** up. It has to stay inlined to be fast. **/
|
||||
/*************************************************************/
|
||||
#ifdef COLEM
|
||||
#define RdZ80 RDZ80
|
||||
extern byte *ROMPage[];
|
||||
INLINE byte RdZ80(word A) { return(ROMPage[A>>13][A&0x1FFF]); }
|
||||
#endif
|
||||
|
||||
#ifdef SPECCY
|
||||
#define RdZ80 RDZ80
|
||||
#define WrZ80 WRZ80
|
||||
extern byte *Page[],*ROM;
|
||||
INLINE byte RdZ80(word A) { return(Page[A>>13][A&0x1FFF]); }
|
||||
INLINE void WrZ80(word A,byte V) { if(Page[A>>13]<ROM) Page[A>>13][A&0x1FFF]=V; }
|
||||
#endif
|
||||
|
||||
#ifdef MG
|
||||
#define RdZ80 RDZ80
|
||||
extern byte *Page[];
|
||||
INLINE byte RdZ80(word A) { return(Page[A>>13][A&0x1FFF]); }
|
||||
#endif
|
||||
|
||||
#ifdef FMSX
|
||||
#define FAST_RDOP
|
||||
extern byte *RAM[];
|
||||
INLINE byte OpZ80(word A) { return(RAM[A>>13][A&0x1FFF]); }
|
||||
#endif
|
||||
|
||||
/** FAST_RDOP ************************************************/
|
||||
/** With this #define not present, RdZ80() should perform **/
|
||||
/** the functions of OpZ80(). **/
|
||||
/*************************************************************/
|
||||
#ifndef FAST_RDOP
|
||||
#define OpZ80(A) RdZ80(A)
|
||||
#endif
|
||||
|
||||
#define S(Fl) R->AF.B.l|=Fl
|
||||
#define R(Fl) R->AF.B.l&=~(Fl)
|
||||
#define FLAGS(Rg,Fl) R->AF.B.l=Fl|ZSTable[Rg]
|
||||
|
||||
#define M_RLC(Rg) \
|
||||
R->AF.B.l=Rg>>7;Rg=(Rg<<1)|R->AF.B.l;R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_RRC(Rg) \
|
||||
R->AF.B.l=Rg&0x01;Rg=(Rg>>1)|(R->AF.B.l<<7);R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_RL(Rg) \
|
||||
if(Rg&0x80) \
|
||||
{ \
|
||||
Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l=PZSTable[Rg]|C_FLAG; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Rg=(Rg<<1)|(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l=PZSTable[Rg]; \
|
||||
}
|
||||
#define M_RR(Rg) \
|
||||
if(Rg&0x01) \
|
||||
{ \
|
||||
Rg=(Rg>>1)|(R->AF.B.l<<7); \
|
||||
R->AF.B.l=PZSTable[Rg]|C_FLAG; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Rg=(Rg>>1)|(R->AF.B.l<<7); \
|
||||
R->AF.B.l=PZSTable[Rg]; \
|
||||
}
|
||||
|
||||
#define M_SLA(Rg) \
|
||||
R->AF.B.l=Rg>>7;Rg<<=1;R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_SRA(Rg) \
|
||||
R->AF.B.l=Rg&C_FLAG;Rg=(Rg>>1)|(Rg&0x80);R->AF.B.l|=PZSTable[Rg]
|
||||
|
||||
#define M_SLL(Rg) \
|
||||
R->AF.B.l=Rg>>7;Rg=(Rg<<1)|0x01;R->AF.B.l|=PZSTable[Rg]
|
||||
#define M_SRL(Rg) \
|
||||
R->AF.B.l=Rg&0x01;Rg>>=1;R->AF.B.l|=PZSTable[Rg]
|
||||
|
||||
#define M_BIT(Bit,Rg) \
|
||||
R->AF.B.l=(R->AF.B.l&C_FLAG)|H_FLAG|PZSTable[Rg&(1<<Bit)]
|
||||
|
||||
#define M_SET(Bit,Rg) Rg|=1<<Bit
|
||||
#define M_RES(Bit,Rg) Rg&=~(1<<Bit)
|
||||
|
||||
#define M_POP(Rg) \
|
||||
R->Rg.B.l=OpZ80(R->SP.W++);R->Rg.B.h=OpZ80(R->SP.W++)
|
||||
#define M_PUSH(Rg) \
|
||||
WrZ80(--R->SP.W,R->Rg.B.h);WrZ80(--R->SP.W,R->Rg.B.l)
|
||||
|
||||
#define M_CALL \
|
||||
J.B.l=OpZ80(R->PC.W++);J.B.h=OpZ80(R->PC.W++); \
|
||||
WrZ80(--R->SP.W,R->PC.B.h);WrZ80(--R->SP.W,R->PC.B.l); \
|
||||
R->PC.W=J.W; \
|
||||
JumpZ80(J.W)
|
||||
|
||||
#define M_JP J.B.l=OpZ80(R->PC.W++);J.B.h=OpZ80(R->PC.W);R->PC.W=J.W;JumpZ80(J.W)
|
||||
#define M_JR R->PC.W+=(offset)OpZ80(R->PC.W)+1;JumpZ80(R->PC.W)
|
||||
#define M_RET R->PC.B.l=OpZ80(R->SP.W++);R->PC.B.h=OpZ80(R->SP.W++);JumpZ80(R->PC.W)
|
||||
|
||||
#define M_RST(Ad) \
|
||||
WrZ80(--R->SP.W,R->PC.B.h);WrZ80(--R->SP.W,R->PC.B.l);R->PC.W=Ad;JumpZ80(Ad)
|
||||
|
||||
#define M_LDWORD(Rg) \
|
||||
R->Rg.B.l=OpZ80(R->PC.W++);R->Rg.B.h=OpZ80(R->PC.W++)
|
||||
|
||||
#define M_ADD(Rg) \
|
||||
J.W=R->AF.B.h+Rg; \
|
||||
R->AF.B.l= \
|
||||
(~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \
|
||||
J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_SUB(Rg) \
|
||||
J.W=R->AF.B.h-Rg; \
|
||||
R->AF.B.l= \
|
||||
((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
|
||||
N_FLAG|-J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_ADC(Rg) \
|
||||
J.W=R->AF.B.h+Rg+(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l= \
|
||||
(~(R->AF.B.h^Rg)&(Rg^J.B.l)&0x80? V_FLAG:0)| \
|
||||
J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_SBC(Rg) \
|
||||
J.W=R->AF.B.h-Rg-(R->AF.B.l&C_FLAG); \
|
||||
R->AF.B.l= \
|
||||
((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
|
||||
N_FLAG|-J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG); \
|
||||
R->AF.B.h=J.B.l
|
||||
|
||||
#define M_CP(Rg) \
|
||||
J.W=R->AF.B.h-Rg; \
|
||||
R->AF.B.l= \
|
||||
((R->AF.B.h^Rg)&(R->AF.B.h^J.B.l)&0x80? V_FLAG:0)| \
|
||||
N_FLAG|-J.B.h|ZSTable[J.B.l]| \
|
||||
((R->AF.B.h^Rg^J.B.l)&H_FLAG)
|
||||
|
||||
#define M_AND(Rg) R->AF.B.h&=Rg;R->AF.B.l=H_FLAG|PZSTable[R->AF.B.h]
|
||||
#define M_OR(Rg) R->AF.B.h|=Rg;R->AF.B.l=PZSTable[R->AF.B.h]
|
||||
#define M_XOR(Rg) R->AF.B.h^=Rg;R->AF.B.l=PZSTable[R->AF.B.h]
|
||||
|
||||
#define M_IN(Rg) \
|
||||
Rg=InZ80(R->BC.W); \
|
||||
R->AF.B.l=PZSTable[Rg]|(R->AF.B.l&C_FLAG)
|
||||
|
||||
#define M_INC(Rg) \
|
||||
Rg++; \
|
||||
R->AF.B.l= \
|
||||
(R->AF.B.l&C_FLAG)|ZSTable[Rg]| \
|
||||
(Rg==0x80? V_FLAG:0)|(Rg&0x0F? 0:H_FLAG)
|
||||
|
||||
#define M_DEC(Rg) \
|
||||
Rg--; \
|
||||
R->AF.B.l= \
|
||||
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[Rg]| \
|
||||
(Rg==0x7F? V_FLAG:0)|((Rg&0x0F)==0x0F? H_FLAG:0)
|
||||
|
||||
#define M_ADDW(Rg1,Rg2) \
|
||||
J.W=(R->Rg1.W+R->Rg2.W)&0xFFFF; \
|
||||
R->AF.B.l= \
|
||||
(R->AF.B.l&~(H_FLAG|N_FLAG|C_FLAG))| \
|
||||
((R->Rg1.W^R->Rg2.W^J.W)&0x1000? H_FLAG:0)| \
|
||||
(((long)R->Rg1.W+(long)R->Rg2.W)&0x10000? C_FLAG:0); \
|
||||
R->Rg1.W=J.W
|
||||
|
||||
#define M_ADCW(Rg) \
|
||||
I=R->AF.B.l&C_FLAG;J.W=(R->HL.W+R->Rg.W+I)&0xFFFF; \
|
||||
R->AF.B.l= \
|
||||
(((long)R->HL.W+(long)R->Rg.W+(long)I)&0x10000? C_FLAG:0)| \
|
||||
(~(R->HL.W^R->Rg.W)&(R->Rg.W^J.W)&0x8000? V_FLAG:0)| \
|
||||
((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)| \
|
||||
(J.W? 0:Z_FLAG)|(J.B.h&S_FLAG); \
|
||||
R->HL.W=J.W
|
||||
|
||||
#define M_SBCW(Rg) \
|
||||
I=R->AF.B.l&C_FLAG;J.W=(R->HL.W-R->Rg.W-I)&0xFFFF; \
|
||||
R->AF.B.l= \
|
||||
N_FLAG| \
|
||||
(((long)R->HL.W-(long)R->Rg.W-(long)I)&0x10000? C_FLAG:0)| \
|
||||
((R->HL.W^R->Rg.W)&(R->HL.W^J.W)&0x8000? V_FLAG:0)| \
|
||||
((R->HL.W^R->Rg.W^J.W)&0x1000? H_FLAG:0)| \
|
||||
(J.W? 0:Z_FLAG)|(J.B.h&S_FLAG); \
|
||||
R->HL.W=J.W
|
||||
|
||||
enum Codes
|
||||
{
|
||||
NOP,LD_BC_WORD,LD_xBC_A,INC_BC,INC_B,DEC_B,LD_B_BYTE,RLCA,
|
||||
EX_AF_AF,ADD_HL_BC,LD_A_xBC,DEC_BC,INC_C,DEC_C,LD_C_BYTE,RRCA,
|
||||
DJNZ,LD_DE_WORD,LD_xDE_A,INC_DE,INC_D,DEC_D,LD_D_BYTE,RLA,
|
||||
JR,ADD_HL_DE,LD_A_xDE,DEC_DE,INC_E,DEC_E,LD_E_BYTE,RRA,
|
||||
JR_NZ,LD_HL_WORD,LD_xWORD_HL,INC_HL,INC_H,DEC_H,LD_H_BYTE,DAA,
|
||||
JR_Z,ADD_HL_HL,LD_HL_xWORD,DEC_HL,INC_L,DEC_L,LD_L_BYTE,CPL,
|
||||
JR_NC,LD_SP_WORD,LD_xWORD_A,INC_SP,INC_xHL,DEC_xHL,LD_xHL_BYTE,SCF,
|
||||
JR_C,ADD_HL_SP,LD_A_xWORD,DEC_SP,INC_A,DEC_A,LD_A_BYTE,CCF,
|
||||
LD_B_B,LD_B_C,LD_B_D,LD_B_E,LD_B_H,LD_B_L,LD_B_xHL,LD_B_A,
|
||||
LD_C_B,LD_C_C,LD_C_D,LD_C_E,LD_C_H,LD_C_L,LD_C_xHL,LD_C_A,
|
||||
LD_D_B,LD_D_C,LD_D_D,LD_D_E,LD_D_H,LD_D_L,LD_D_xHL,LD_D_A,
|
||||
LD_E_B,LD_E_C,LD_E_D,LD_E_E,LD_E_H,LD_E_L,LD_E_xHL,LD_E_A,
|
||||
LD_H_B,LD_H_C,LD_H_D,LD_H_E,LD_H_H,LD_H_L,LD_H_xHL,LD_H_A,
|
||||
LD_L_B,LD_L_C,LD_L_D,LD_L_E,LD_L_H,LD_L_L,LD_L_xHL,LD_L_A,
|
||||
LD_xHL_B,LD_xHL_C,LD_xHL_D,LD_xHL_E,LD_xHL_H,LD_xHL_L,HALT,LD_xHL_A,
|
||||
LD_A_B,LD_A_C,LD_A_D,LD_A_E,LD_A_H,LD_A_L,LD_A_xHL,LD_A_A,
|
||||
ADD_B,ADD_C,ADD_D,ADD_E,ADD_H,ADD_L,ADD_xHL,ADD_A,
|
||||
ADC_B,ADC_C,ADC_D,ADC_E,ADC_H,ADC_L,ADC_xHL,ADC_A,
|
||||
SUB_B,SUB_C,SUB_D,SUB_E,SUB_H,SUB_L,SUB_xHL,SUB_A,
|
||||
SBC_B,SBC_C,SBC_D,SBC_E,SBC_H,SBC_L,SBC_xHL,SBC_A,
|
||||
AND_B,AND_C,AND_D,AND_E,AND_H,AND_L,AND_xHL,AND_A,
|
||||
XOR_B,XOR_C,XOR_D,XOR_E,XOR_H,XOR_L,XOR_xHL,XOR_A,
|
||||
OR_B,OR_C,OR_D,OR_E,OR_H,OR_L,OR_xHL,OR_A,
|
||||
CP_B,CP_C,CP_D,CP_E,CP_H,CP_L,CP_xHL,CP_A,
|
||||
RET_NZ,POP_BC,JP_NZ,JP,CALL_NZ,PUSH_BC,ADD_BYTE,RST00,
|
||||
RET_Z,RET,JP_Z,PFX_CB,CALL_Z,CALL,ADC_BYTE,RST08,
|
||||
RET_NC,POP_DE,JP_NC,OUTA,CALL_NC,PUSH_DE,SUB_BYTE,RST10,
|
||||
RET_C,EXX,JP_C,INA,CALL_C,PFX_DD,SBC_BYTE,RST18,
|
||||
RET_PO,POP_HL,JP_PO,EX_HL_xSP,CALL_PO,PUSH_HL,AND_BYTE,RST20,
|
||||
RET_PE,LD_PC_HL,JP_PE,EX_DE_HL,CALL_PE,PFX_ED,XOR_BYTE,RST28,
|
||||
RET_P,POP_AF,JP_P,DI,CALL_P,PUSH_AF,OR_BYTE,RST30,
|
||||
RET_M,LD_SP_HL,JP_M,EI,CALL_M,PFX_FD,CP_BYTE,RST38
|
||||
};
|
||||
|
||||
enum CodesCB
|
||||
{
|
||||
RLC_B,RLC_C,RLC_D,RLC_E,RLC_H,RLC_L,RLC_xHL,RLC_A,
|
||||
RRC_B,RRC_C,RRC_D,RRC_E,RRC_H,RRC_L,RRC_xHL,RRC_A,
|
||||
RL_B,RL_C,RL_D,RL_E,RL_H,RL_L,RL_xHL,RL_A,
|
||||
RR_B,RR_C,RR_D,RR_E,RR_H,RR_L,RR_xHL,RR_A,
|
||||
SLA_B,SLA_C,SLA_D,SLA_E,SLA_H,SLA_L,SLA_xHL,SLA_A,
|
||||
SRA_B,SRA_C,SRA_D,SRA_E,SRA_H,SRA_L,SRA_xHL,SRA_A,
|
||||
SLL_B,SLL_C,SLL_D,SLL_E,SLL_H,SLL_L,SLL_xHL,SLL_A,
|
||||
SRL_B,SRL_C,SRL_D,SRL_E,SRL_H,SRL_L,SRL_xHL,SRL_A,
|
||||
BIT0_B,BIT0_C,BIT0_D,BIT0_E,BIT0_H,BIT0_L,BIT0_xHL,BIT0_A,
|
||||
BIT1_B,BIT1_C,BIT1_D,BIT1_E,BIT1_H,BIT1_L,BIT1_xHL,BIT1_A,
|
||||
BIT2_B,BIT2_C,BIT2_D,BIT2_E,BIT2_H,BIT2_L,BIT2_xHL,BIT2_A,
|
||||
BIT3_B,BIT3_C,BIT3_D,BIT3_E,BIT3_H,BIT3_L,BIT3_xHL,BIT3_A,
|
||||
BIT4_B,BIT4_C,BIT4_D,BIT4_E,BIT4_H,BIT4_L,BIT4_xHL,BIT4_A,
|
||||
BIT5_B,BIT5_C,BIT5_D,BIT5_E,BIT5_H,BIT5_L,BIT5_xHL,BIT5_A,
|
||||
BIT6_B,BIT6_C,BIT6_D,BIT6_E,BIT6_H,BIT6_L,BIT6_xHL,BIT6_A,
|
||||
BIT7_B,BIT7_C,BIT7_D,BIT7_E,BIT7_H,BIT7_L,BIT7_xHL,BIT7_A,
|
||||
RES0_B,RES0_C,RES0_D,RES0_E,RES0_H,RES0_L,RES0_xHL,RES0_A,
|
||||
RES1_B,RES1_C,RES1_D,RES1_E,RES1_H,RES1_L,RES1_xHL,RES1_A,
|
||||
RES2_B,RES2_C,RES2_D,RES2_E,RES2_H,RES2_L,RES2_xHL,RES2_A,
|
||||
RES3_B,RES3_C,RES3_D,RES3_E,RES3_H,RES3_L,RES3_xHL,RES3_A,
|
||||
RES4_B,RES4_C,RES4_D,RES4_E,RES4_H,RES4_L,RES4_xHL,RES4_A,
|
||||
RES5_B,RES5_C,RES5_D,RES5_E,RES5_H,RES5_L,RES5_xHL,RES5_A,
|
||||
RES6_B,RES6_C,RES6_D,RES6_E,RES6_H,RES6_L,RES6_xHL,RES6_A,
|
||||
RES7_B,RES7_C,RES7_D,RES7_E,RES7_H,RES7_L,RES7_xHL,RES7_A,
|
||||
SET0_B,SET0_C,SET0_D,SET0_E,SET0_H,SET0_L,SET0_xHL,SET0_A,
|
||||
SET1_B,SET1_C,SET1_D,SET1_E,SET1_H,SET1_L,SET1_xHL,SET1_A,
|
||||
SET2_B,SET2_C,SET2_D,SET2_E,SET2_H,SET2_L,SET2_xHL,SET2_A,
|
||||
SET3_B,SET3_C,SET3_D,SET3_E,SET3_H,SET3_L,SET3_xHL,SET3_A,
|
||||
SET4_B,SET4_C,SET4_D,SET4_E,SET4_H,SET4_L,SET4_xHL,SET4_A,
|
||||
SET5_B,SET5_C,SET5_D,SET5_E,SET5_H,SET5_L,SET5_xHL,SET5_A,
|
||||
SET6_B,SET6_C,SET6_D,SET6_E,SET6_H,SET6_L,SET6_xHL,SET6_A,
|
||||
SET7_B,SET7_C,SET7_D,SET7_E,SET7_H,SET7_L,SET7_xHL,SET7_A
|
||||
};
|
||||
|
||||
enum CodesED
|
||||
{
|
||||
DB_00,DB_01,DB_02,DB_03,DB_04,DB_05,DB_06,DB_07,
|
||||
DB_08,DB_09,DB_0A,DB_0B,DB_0C,DB_0D,DB_0E,DB_0F,
|
||||
DB_10,DB_11,DB_12,DB_13,DB_14,DB_15,DB_16,DB_17,
|
||||
DB_18,DB_19,DB_1A,DB_1B,DB_1C,DB_1D,DB_1E,DB_1F,
|
||||
DB_20,DB_21,DB_22,DB_23,DB_24,DB_25,DB_26,DB_27,
|
||||
DB_28,DB_29,DB_2A,DB_2B,DB_2C,DB_2D,DB_2E,DB_2F,
|
||||
DB_30,DB_31,DB_32,DB_33,DB_34,DB_35,DB_36,DB_37,
|
||||
DB_38,DB_39,DB_3A,DB_3B,DB_3C,DB_3D,DB_3E,DB_3F,
|
||||
IN_B_xC,OUT_xC_B,SBC_HL_BC,LD_xWORDe_BC,NEG,RETN,IM_0,LD_I_A,
|
||||
IN_C_xC,OUT_xC_C,ADC_HL_BC,LD_BC_xWORDe,DB_4C,RETI,DB_,LD_R_A,
|
||||
IN_D_xC,OUT_xC_D,SBC_HL_DE,LD_xWORDe_DE,DB_54,DB_55,IM_1,LD_A_I,
|
||||
IN_E_xC,OUT_xC_E,ADC_HL_DE,LD_DE_xWORDe,DB_5C,DB_5D,IM_2,LD_A_R,
|
||||
IN_H_xC,OUT_xC_H,SBC_HL_HL,LD_xWORDe_HL,DB_64,DB_65,DB_66,RRD,
|
||||
IN_L_xC,OUT_xC_L,ADC_HL_HL,LD_HL_xWORDe,DB_6C,DB_6D,DB_6E,RLD,
|
||||
IN_F_xC,DB_71,SBC_HL_SP,LD_xWORDe_SP,DB_74,DB_75,DB_76,DB_77,
|
||||
IN_A_xC,OUT_xC_A,ADC_HL_SP,LD_SP_xWORDe,DB_7C,DB_7D,DB_7E,DB_7F,
|
||||
DB_80,DB_81,DB_82,DB_83,DB_84,DB_85,DB_86,DB_87,
|
||||
DB_88,DB_89,DB_8A,DB_8B,DB_8C,DB_8D,DB_8E,DB_8F,
|
||||
DB_90,DB_91,DB_92,DB_93,DB_94,DB_95,DB_96,DB_97,
|
||||
DB_98,DB_99,DB_9A,DB_9B,DB_9C,DB_9D,DB_9E,DB_9F,
|
||||
LDI,CPI,INI,OUTI,DB_A4,DB_A5,DB_A6,DB_A7,
|
||||
LDD,CPD,IND,OUTD,DB_AC,DB_AD,DB_AE,DB_AF,
|
||||
LDIR,CPIR,INIR,OTIR,DB_B4,DB_B5,DB_B6,DB_B7,
|
||||
LDDR,CPDR,INDR,OTDR,DB_BC,DB_BD,DB_BE,DB_BF,
|
||||
DB_C0,DB_C1,DB_C2,DB_C3,DB_C4,DB_C5,DB_C6,DB_C7,
|
||||
DB_C8,DB_C9,DB_CA,DB_CB,DB_CC,DB_CD,DB_CE,DB_CF,
|
||||
DB_D0,DB_D1,DB_D2,DB_D3,DB_D4,DB_D5,DB_D6,DB_D7,
|
||||
DB_D8,DB_D9,DB_DA,DB_DB,DB_DC,DB_DD,DB_DE,DB_DF,
|
||||
DB_E0,DB_E1,DB_E2,DB_E3,DB_E4,DB_E5,DB_E6,DB_E7,
|
||||
DB_E8,DB_E9,DB_EA,DB_EB,DB_EC,DB_ED,DB_EE,DB_EF,
|
||||
DB_F0,DB_F1,DB_F2,DB_F3,DB_F4,DB_F5,DB_F6,DB_F7,
|
||||
DB_F8,DB_F9,DB_FA,DB_FB,DB_FC,DB_FD,DB_FE,DB_FF
|
||||
};
|
||||
|
||||
static void CodesCB(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesCB[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesCB.h"
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: CB %02X at PC=%04X\n",
|
||||
(long)(R->User),OpZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void CodesDDCB(register Z80 *R)
|
||||
{
|
||||
register pair J;
|
||||
register byte I;
|
||||
|
||||
#define XX IX
|
||||
J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXXCB[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXCB.h"
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: DD CB %02X %02X at PC=%04X\n",
|
||||
(long)(R->User),OpZ80(R->PC.W-2),OpZ80(R->PC.W-1),R->PC.W-4
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
static void CodesFDCB(register Z80 *R)
|
||||
{
|
||||
register pair J;
|
||||
register byte I;
|
||||
|
||||
#define XX IY
|
||||
J.W=R->XX.W+(offset)OpZ80(R->PC.W++);
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXXCB[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXCB.h"
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: FD CB %02X %02X at PC=%04X\n",
|
||||
(long)R->User,OpZ80(R->PC.W-2),OpZ80(R->PC.W-1),R->PC.W-4
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
static void CodesED(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesED[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesED.h"
|
||||
case PFX_ED:
|
||||
R->PC.W--;break;
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: ED %02X at PC=%04X\n",
|
||||
(long)R->User,OpZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void CodesDD(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
#define XX IX
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXX[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXX.h"
|
||||
case PFX_FD:
|
||||
case PFX_DD:
|
||||
R->PC.W--;break;
|
||||
case PFX_CB:
|
||||
CodesDDCB(R);break;
|
||||
default:
|
||||
if(R->TrapBadOps)
|
||||
printf
|
||||
(
|
||||
"[Z80 %lX] Unrecognized instruction: DD %02X at PC=%04X\n",
|
||||
(long)R->User,OpZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
static void CodesFD(register Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
#define XX IY
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=CyclesXX[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "CodesXX.h"
|
||||
case PFX_FD:
|
||||
case PFX_DD:
|
||||
R->PC.W--;break;
|
||||
case PFX_CB:
|
||||
CodesFDCB(R);break;
|
||||
default:
|
||||
printf
|
||||
(
|
||||
"Unrecognized instruction: FD %02X at PC=%04X\n",
|
||||
OpZ80(R->PC.W-1),R->PC.W-2
|
||||
);
|
||||
}
|
||||
#undef XX
|
||||
}
|
||||
|
||||
/** ResetZ80() ***********************************************/
|
||||
/** This function can be used to reset the register struct **/
|
||||
/** before starting execution with Z80(). It sets the **/
|
||||
/** registers to their supposed initial values. **/
|
||||
/*************************************************************/
|
||||
void ResetZ80(Z80 *R, register int Cycles)
|
||||
{
|
||||
R->IPeriod = Cycles;
|
||||
R->PC.W = 0x0000;
|
||||
R->SP.W = 0xF000;
|
||||
R->AF.W = 0x0000;
|
||||
R->BC.W = 0x0000;
|
||||
R->DE.W = 0x0000;
|
||||
R->HL.W = 0x0000;
|
||||
R->AF1.W = 0x0000;
|
||||
R->BC1.W = 0x0000;
|
||||
R->DE1.W = 0x0000;
|
||||
R->HL1.W = 0x0000;
|
||||
R->IX.W = 0x0000;
|
||||
R->IY.W = 0x0000;
|
||||
R->I = 0x00;
|
||||
R->R = 0x00;
|
||||
R->IFF = 0x00;
|
||||
R->ICount = R->IPeriod;
|
||||
R->IRequest = INT_NONE;
|
||||
R->IBackup = 0;
|
||||
|
||||
JumpZ80(R->PC.W);
|
||||
}
|
||||
|
||||
/** ExecZ80() ************************************************/
|
||||
/** This function will execute given number of Z80 cycles. **/
|
||||
/** It will then return the number of cycles left, possibly **/
|
||||
/** negative, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
#ifdef EXECZ80
|
||||
int ExecZ80(register Z80 *R,register int RunCycles)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
for(R->ICount=RunCycles;;)
|
||||
{
|
||||
while(R->ICount>0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
/* Turn tracing on when reached trap address */
|
||||
if(R->PC.W==R->Trap) R->Trace=1;
|
||||
/* Call single-step debugger, exit if requested */
|
||||
if(R->Trace)
|
||||
if(!DebugZ80(R)) return(R->ICount);
|
||||
#endif
|
||||
|
||||
/* Read opcode and count cycles */
|
||||
I=OpZ80(R->PC.W++);
|
||||
/* Count cycles */
|
||||
R->ICount-=Cycles[I];
|
||||
|
||||
/* Interpret opcode */
|
||||
switch(I)
|
||||
{
|
||||
#include "Codes.h"
|
||||
case PFX_CB: CodesCB(R);break;
|
||||
case PFX_ED: CodesED(R);break;
|
||||
case PFX_FD: CodesFD(R);break;
|
||||
case PFX_DD: CodesDD(R);break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unless we have come here after EI, exit */
|
||||
if(!(R->IFF&IFF_EI)) return(R->ICount);
|
||||
else
|
||||
{
|
||||
/* Done with AfterEI state */
|
||||
R->IFF=(R->IFF&~IFF_EI)|IFF_1;
|
||||
/* Restore the ICount */
|
||||
R->ICount+=R->IBackup-1;
|
||||
/* Interrupt CPU if needed */
|
||||
if((R->IRequest!=INT_NONE)&&(R->IRequest!=INT_QUIT)) IntZ80(R,R->IRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* EXECZ80 */
|
||||
|
||||
/** IntZ80() *************************************************/
|
||||
/** This function will generate interrupt of given vector. **/
|
||||
/*************************************************************/
|
||||
void IntZ80(Z80 *R,word Vector)
|
||||
{
|
||||
/* If HALTed, take CPU off HALT instruction */
|
||||
if(R->IFF&IFF_HALT) { R->PC.W++;R->IFF&=~IFF_HALT; }
|
||||
|
||||
if((R->IFF&IFF_1)||(Vector==INT_NMI))
|
||||
{
|
||||
/* Save PC on stack */
|
||||
M_PUSH(PC);
|
||||
|
||||
/* Automatically reset IRequest if needed */
|
||||
if(R->IAutoReset&&(Vector==R->IRequest)) R->IRequest=INT_NONE;
|
||||
|
||||
/* If it is NMI... */
|
||||
if(Vector==INT_NMI)
|
||||
{
|
||||
/* Clear IFF1 */
|
||||
R->IFF&=~(IFF_1|IFF_EI);
|
||||
/* Jump to hardwired NMI vector */
|
||||
R->PC.W=0x0066;
|
||||
JumpZ80(0x0066);
|
||||
/* Done */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Further interrupts off */
|
||||
R->IFF&=~(IFF_1|IFF_2|IFF_EI);
|
||||
|
||||
/* If in IM2 mode... */
|
||||
if(R->IFF&IFF_IM2)
|
||||
{
|
||||
/* Make up the vector address */
|
||||
Vector=(Vector&0xFF)|((word)(R->I)<<8);
|
||||
/* Read the vector */
|
||||
R->PC.B.l=RdZ80(Vector++);
|
||||
R->PC.B.h=RdZ80(Vector);
|
||||
JumpZ80(R->PC.W);
|
||||
/* Done */
|
||||
return;
|
||||
}
|
||||
|
||||
/* If in IM1 mode, just jump to hardwired IRQ vector */
|
||||
if(R->IFF&IFF_IM1) { R->PC.W=0x0038;JumpZ80(0x0038);return; }
|
||||
|
||||
/* If in IM0 mode... */
|
||||
|
||||
/* Jump to a vector */
|
||||
switch(Vector)
|
||||
{
|
||||
case INT_RST00: R->PC.W=0x0000;JumpZ80(0x0000);break;
|
||||
case INT_RST08: R->PC.W=0x0008;JumpZ80(0x0008);break;
|
||||
case INT_RST10: R->PC.W=0x0010;JumpZ80(0x0010);break;
|
||||
case INT_RST18: R->PC.W=0x0018;JumpZ80(0x0018);break;
|
||||
case INT_RST20: R->PC.W=0x0020;JumpZ80(0x0020);break;
|
||||
case INT_RST28: R->PC.W=0x0028;JumpZ80(0x0028);break;
|
||||
case INT_RST30: R->PC.W=0x0030;JumpZ80(0x0030);break;
|
||||
case INT_RST38: R->PC.W=0x0038;JumpZ80(0x0038);break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** RunZ80() *************************************************/
|
||||
/** This function will run Z80 code until an LoopZ80() call **/
|
||||
/** returns INT_QUIT. It will return the PC at which **/
|
||||
/** emulation stopped, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
#ifndef EXECZ80
|
||||
word RunZ80(Z80 *R)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
/* Turn tracing on when reached trap address */
|
||||
if(R->PC.W==R->Trap) R->Trace=1;
|
||||
/* Call single-step debugger, exit if requested */
|
||||
if(R->Trace)
|
||||
if(!DebugZ80(R)) return(R->PC.W);
|
||||
#endif
|
||||
|
||||
I=OpZ80(R->PC.W++);
|
||||
R->ICount-=Cycles[I];
|
||||
|
||||
switch(I)
|
||||
{
|
||||
#include "Codes.h"
|
||||
case PFX_CB: CodesCB(R);break;
|
||||
case PFX_ED: CodesED(R);break;
|
||||
case PFX_FD: CodesFD(R);break;
|
||||
case PFX_DD: CodesDD(R);break;
|
||||
}
|
||||
|
||||
/* If cycle counter expired... */
|
||||
if(R->ICount<=0)
|
||||
{
|
||||
/* If we have come after EI, get address from IRequest */
|
||||
/* Otherwise, get it from the loop handler */
|
||||
if(R->IFF&IFF_EI)
|
||||
{
|
||||
R->IFF=(R->IFF&~IFF_EI)|IFF_1; /* Done with AfterEI state */
|
||||
R->ICount+=R->IBackup-1; /* Restore the ICount */
|
||||
|
||||
/* Call periodic handler or set pending IRQ */
|
||||
if(R->ICount>0) J.W=R->IRequest;
|
||||
else
|
||||
{
|
||||
J.W=LoopZ80(R); /* Call periodic handler */
|
||||
R->ICount+=R->IPeriod; /* Reset the cycle counter */
|
||||
if(J.W==INT_NONE) J.W=R->IRequest; /* Pending IRQ */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
J.W=LoopZ80(R); /* Call periodic handler */
|
||||
R->ICount+=R->IPeriod; /* Reset the cycle counter */
|
||||
if(J.W==INT_NONE) J.W=R->IRequest; /* Pending IRQ */
|
||||
}
|
||||
|
||||
if(J.W==INT_QUIT) return(R->PC.W); /* Exit if INT_QUIT */
|
||||
if(J.W!=INT_NONE) IntZ80(R,J.W); /* Int-pt if needed */
|
||||
}
|
||||
}
|
||||
|
||||
/* Execution stopped */
|
||||
return(R->PC.W);
|
||||
}
|
||||
#endif /* !EXECZ80 */
|
||||
193
MCUME_teensy41/teensyspeccy/Z80.h
Normal file
193
MCUME_teensy41/teensyspeccy/Z80.h
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/** Z80: portable Z80 emulator *******************************/
|
||||
/** **/
|
||||
/** Z80.h **/
|
||||
/** **/
|
||||
/** This file contains declarations relevant to emulation **/
|
||||
/** of Z80 CPU. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1994-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#ifndef Z80_H
|
||||
#define Z80_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define EXECZ80 // run a few cycles
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Compilation options: */
|
||||
/* #define DEBUG */ /* Compile debugging version */
|
||||
#define LSB_FIRST /* Compile for low-endian CPU */
|
||||
// #define MSB_FIRST /* Compile for hi-endian CPU */
|
||||
|
||||
/* LoopZ80() may return: */
|
||||
#define INT_RST00 0x00C7 /* RST 00h */
|
||||
#define INT_RST08 0x00CF /* RST 08h */
|
||||
#define INT_RST10 0x00D7 /* RST 10h */
|
||||
#define INT_RST18 0x00DF /* RST 18h */
|
||||
#define INT_RST20 0x00E7 /* RST 20h */
|
||||
#define INT_RST28 0x00EF /* RST 28h */
|
||||
#define INT_RST30 0x00F7 /* RST 30h */
|
||||
#define INT_RST38 0x00FF /* RST 38h */
|
||||
#define INT_IRQ INT_RST38 /* Default IRQ opcode is FFh */
|
||||
#define INT_NMI 0xFFFD /* Non-maskable interrupt */
|
||||
#define INT_NONE 0xFFFF /* No interrupt required */
|
||||
#define INT_QUIT 0xFFFE /* Exit the emulation */
|
||||
|
||||
/* Bits in Z80 F register: */
|
||||
#define S_FLAG 0x80 /* 1: Result negative */
|
||||
#define Z_FLAG 0x40 /* 1: Result is zero */
|
||||
#define H_FLAG 0x10 /* 1: Halfcarry/Halfborrow */
|
||||
#define P_FLAG 0x04 /* 1: Result is even */
|
||||
#define V_FLAG 0x04 /* 1: Overflow occured */
|
||||
#define N_FLAG 0x02 /* 1: Subtraction occured */
|
||||
#define C_FLAG 0x01 /* 1: Carry/Borrow occured */
|
||||
|
||||
/* Bits in IFF flip-flops: */
|
||||
#define IFF_1 0x01 /* IFF1 flip-flop */
|
||||
#define IFF_IM1 0x02 /* 1: IM1 mode */
|
||||
#define IFF_IM2 0x04 /* 1: IM2 mode */
|
||||
#define IFF_2 0x08 /* IFF2 flip-flop */
|
||||
#define IFF_EI 0x20 /* 1: EI pending */
|
||||
#define IFF_HALT 0x80 /* 1: CPU HALTed */
|
||||
|
||||
/** Simple Datatypes *****************************************/
|
||||
/** NOTICE: sizeof(byte)=1 and sizeof(word)=2 **/
|
||||
/*************************************************************/
|
||||
#ifndef BYTE_TYPE_DEFINED
|
||||
#define BYTE_TYPE_DEFINED
|
||||
typedef uint8_t byte;
|
||||
#endif
|
||||
#ifndef WORD_TYPE_DEFINED
|
||||
#define WORD_TYPE_DEFINED
|
||||
typedef uint16_t word;
|
||||
#endif
|
||||
typedef int8_t offset;
|
||||
|
||||
/** Structured Datatypes *************************************/
|
||||
/** NOTICE: #define LSB_FIRST for machines where least **/
|
||||
/** signifcant byte goes first. **/
|
||||
/*************************************************************/
|
||||
typedef union
|
||||
{
|
||||
#ifdef LSB_FIRST
|
||||
struct { byte l,h; } B;
|
||||
#else
|
||||
struct { byte h,l; } B;
|
||||
#endif
|
||||
word W;
|
||||
} pair;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pair AF,BC,DE,HL,IX,IY,PC,SP; /* Main registers */
|
||||
pair AF1,BC1,DE1,HL1; /* Shadow registers */
|
||||
byte IFF,I; /* Interrupt registers */
|
||||
byte R; /* Refresh register */
|
||||
|
||||
int IPeriod,ICount; /* Set IPeriod to number of CPU cycles */
|
||||
/* between calls to LoopZ80() */
|
||||
int IBackup; /* Private, don't touch */
|
||||
word IRequest; /* Set to address of pending IRQ */
|
||||
byte IAutoReset; /* Set to 1 to autom. reset IRequest */
|
||||
byte TrapBadOps; /* Set to 1 to warn of illegal opcodes */
|
||||
word Trap; /* Set Trap to address to trace from */
|
||||
byte Trace; /* Set Trace=1 to start tracing */
|
||||
void *User; /* Arbitrary user data (ID,RAM*,etc.) */
|
||||
} Z80;
|
||||
|
||||
/** ResetZ80() ***********************************************/
|
||||
/** This function can be used to reset the registers before **/
|
||||
/** starting execution with RunZ80(). It sets registers to **/
|
||||
/** their initial values. **/
|
||||
/*************************************************************/
|
||||
void ResetZ80(register Z80 *R, register int Cycles);
|
||||
|
||||
/** ExecZ80() ************************************************/
|
||||
/** This function will execute given number of Z80 cycles. **/
|
||||
/** It will then return the number of cycles left, possibly **/
|
||||
/** negative, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
#ifdef EXECZ80
|
||||
int ExecZ80(register Z80 *R,register int RunCycles);
|
||||
#endif
|
||||
|
||||
/** IntZ80() *************************************************/
|
||||
/** This function will generate interrupt of given vector. **/
|
||||
/*************************************************************/
|
||||
void IntZ80(register Z80 *R,register word Vector);
|
||||
|
||||
/** RunZ80() *************************************************/
|
||||
/** This function will run Z80 code until an LoopZ80() call **/
|
||||
/** returns INT_QUIT. It will return the PC at which **/
|
||||
/** emulation stopped, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
#ifndef EXECZ80
|
||||
word RunZ80(register Z80 *R);
|
||||
#endif
|
||||
|
||||
/** RdZ80()/WrZ80() ******************************************/
|
||||
/** These functions are called when access to RAM occurs. **/
|
||||
/** They allow to control memory access. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
void WrZ80(register word Addr,register byte Value);
|
||||
byte RdZ80(register word Addr);
|
||||
|
||||
/** InZ80()/OutZ80() *****************************************/
|
||||
/** Z80 emulation calls these functions to read/write from **/
|
||||
/** I/O ports. There can be 65536 I/O ports, but only first **/
|
||||
/** 256 are usually used. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
void OutZ80(register word Port,register byte Value);
|
||||
byte InZ80(register word Port);
|
||||
|
||||
/** PatchZ80() ***********************************************/
|
||||
/** Z80 emulation calls this function when it encounters a **/
|
||||
/** special patch command (ED FE) provided for user needs. **/
|
||||
/** For example, it can be called to emulate BIOS calls, **/
|
||||
/** such as disk and tape access. Replace it with an empty **/
|
||||
/** macro for no patching. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
void PatchZ80(register Z80 *R);
|
||||
|
||||
/** DebugZ80() ***********************************************/
|
||||
/** This function should exist if DEBUG is #defined. When **/
|
||||
/** Trace!=0, it is called after each command executed by **/
|
||||
/** the CPU, and given the Z80 registers. Emulation exits **/
|
||||
/** if DebugZ80() returns 0. **/
|
||||
/*************************************************************/
|
||||
#ifdef DEBUG
|
||||
byte DebugZ80(register Z80 *R);
|
||||
#endif
|
||||
|
||||
/** LoopZ80() ************************************************/
|
||||
/** Z80 emulation calls this function periodically to check **/
|
||||
/** if the system hardware requires any interrupts. This **/
|
||||
/** function must return an address of the interrupt vector **/
|
||||
/** (0x0038, 0x0066, etc.) or INT_NONE for no interrupt. **/
|
||||
/** Return INT_QUIT to exit the emulation loop. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
word LoopZ80(register Z80 *R);
|
||||
|
||||
/** JumpZ80() ************************************************/
|
||||
/** Z80 emulation calls this function when it executes a **/
|
||||
/** JP, JR, CALL, RST, or RET. You can use JumpZ80() to **/
|
||||
/** trap these opcodes and switch memory layout. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
#ifndef JUMPZ80
|
||||
#define JumpZ80(PC)
|
||||
#else
|
||||
void JumpZ80(word PC);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* Z80_H */
|
||||
1731
MCUME_teensy41/teensyspeccy/emuapi.cpp
Normal file
1731
MCUME_teensy41/teensyspeccy/emuapi.cpp
Normal file
File diff suppressed because it is too large
Load diff
213
MCUME_teensy41/teensyspeccy/emuapi.h
Normal file
213
MCUME_teensy41/teensyspeccy/emuapi.h
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
#ifndef EMUAPI_H
|
||||
#define EMUAPI_H
|
||||
|
||||
#include "platform_config.h"
|
||||
|
||||
//#define TIMER_REND 1
|
||||
#define EXTRA_HEAP 0x10
|
||||
|
||||
// Title: < >
|
||||
#define TITLE " SPECTRUM Emulator"
|
||||
#define ROMSDIR "spec"
|
||||
|
||||
#define emu_Init(ROM) {spec_Init(); spec_Start(ROM);}
|
||||
#define emu_Step(x) {spec_Step();}
|
||||
#define emu_Input(x) {spec_Input(x);}
|
||||
|
||||
#define MAX_FILENAME_PATH 64
|
||||
#define NB_FILE_HANDLER 4
|
||||
#define PALETTE_SIZE 16
|
||||
#define VID_FRAME_SKIP 0x3
|
||||
#define TFT_VBUFFER_YCROP 0
|
||||
#define SINGLELINE_RENDERING 1
|
||||
|
||||
#define R32(rgb) ((rgb>>16)&0xff)
|
||||
#define G32(rgb) ((rgb>>8)&0xff)
|
||||
#define B32(rgb) (rgb & 0xff)
|
||||
|
||||
#define ACTION_NONE 0
|
||||
#define ACTION_MAXKBDVAL 16
|
||||
#define ACTION_EXITKBD 128
|
||||
#define ACTION_RUN1 129
|
||||
#define ACTION_RUN2 130
|
||||
#define ACTION_RUN3 131
|
||||
|
||||
#ifdef KEYMAP_PRESENT
|
||||
|
||||
#define keylables_map0_0 (char *)"qwertyuiop\x1a"
|
||||
#define keylables_map0_1 (char *)" asdfghjkl\x19"
|
||||
#define keylables_map0_2 (char *)" zxcvbnm,.;/"
|
||||
#define keylables_map0_3 (char *)" +\x10-"
|
||||
const unsigned short key_map0[] = {
|
||||
'q','w','e','r','t','y','u','i','o','p',127, //lowecase
|
||||
0,'a','s','d','f','g','h','j','k','l',10,
|
||||
0,'z','x','c','v','b','n','m',',','.',';','/',
|
||||
0,0,0,0,
|
||||
0,'+',' ','-'
|
||||
};
|
||||
|
||||
#define keylables_map1_0 (char *)"QWERTYUIOP@"
|
||||
#define keylables_map1_1 (char *)" ASDFGHJKL\x19"
|
||||
#define keylables_map1_2 (char *)" ZXCVBNM<>:?"
|
||||
#define keylables_map1_3 (char *)" =\x10 "
|
||||
const unsigned short key_map1[] = {
|
||||
'Q','W','E','R','T','Y','U','I','O','P','@', //shift uppercase
|
||||
0,'A','S','D','F','G','H','J','K','L',10,
|
||||
0,'Z','X','C','V','B','N','M','<','>',':','?',
|
||||
154,152,151,153, //U L R D
|
||||
0,'=',' ','_'
|
||||
};
|
||||
|
||||
#define keylables_map2_0 (char *)"!\"#$% &*()@"
|
||||
#define keylables_map2_1 (char *)" "
|
||||
#define keylables_map2_2 (char *)" <>:?"
|
||||
#define keylables_map2_3 (char *)" =\x10 "
|
||||
const unsigned short key_map2[] = {
|
||||
'!','"','#','$','%','^','&','*','(',')','@', // shiftothers
|
||||
0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0,0,0,0,0,0,0,'<','>',':','?',
|
||||
154,152,151,153, //U L R D
|
||||
0,'=',' ','_'
|
||||
};
|
||||
|
||||
#define keylables_map3_0 (char *)"1234567890 "
|
||||
#define keylables_map3_1 (char *)" "
|
||||
#define keylables_map3_2 (char *)" "
|
||||
#define keylables_map3_3 (char *)" "
|
||||
|
||||
const unsigned short key_map3[] = {
|
||||
'1','2','3','4','5','6','7','8','9','0',0, // digit keys
|
||||
0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0,0,0,0,0,0,0,0,0,0,0,
|
||||
154,152,151,153, //U L R D
|
||||
0,0,' ',0
|
||||
};
|
||||
|
||||
#define keylables_map4_0 (char *)" "
|
||||
#define keylables_map4_1 (char *)" "
|
||||
#define keylables_map4_2 (char *)" "
|
||||
#define keylables_map4_3 (char *)" "
|
||||
|
||||
const unsigned short key_map4[] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0, // function keys
|
||||
0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0,0,0,0,0,0,0,0,0,0,0,
|
||||
154,152,151,153, //U L R D
|
||||
0,0,' ',0
|
||||
};
|
||||
|
||||
#define keylables_map5_0 (char *)" "
|
||||
#define keylables_map5_1 (char *)" "
|
||||
#define keylables_map5_2 (char *)" "
|
||||
#define keylables_map5_3 (char *)" "
|
||||
|
||||
const unsigned short key_map5[] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0, // extra keys
|
||||
0, 0,0,0,0,0,0,0,0,0,0,
|
||||
0, 0,0,0,0,0,0,0,0,0,0,0,
|
||||
154,152,151,153, //U L R D
|
||||
0,0,' ',0
|
||||
};
|
||||
|
||||
const unsigned short matkeys[] = {
|
||||
0x004,0x008,0x108,0x104,0x208,0x204,0x308,0x304,0x408,0x404,0x410, // row 1
|
||||
0x502,0x002,0x020,0x102,0x120,0x202,0x220,0x302,0x320,0x402,0x420, // row 2
|
||||
0x508,0x001,0x040,0x101,0x140,0x201,0x240,0x210,0x340,0x301,0x401,0x440, // row 3
|
||||
0x504,0x520,0x540,0x501, // UP LEFT RIGHT DOWN
|
||||
0x510,0x010,0x110,0x310, // row 4
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define MASK_JOY2_RIGHT 0x0001
|
||||
#define MASK_JOY2_LEFT 0x0002
|
||||
#define MASK_JOY2_UP 0x0004
|
||||
#define MASK_JOY2_DOWN 0x0008
|
||||
#define MASK_JOY2_BTN 0x0010
|
||||
#define MASK_KEY_USER1 0x0020
|
||||
#define MASK_KEY_USER2 0x0040
|
||||
#define MASK_KEY_USER3 0x0080
|
||||
#define MASK_JOY1_RIGHT 0x0100
|
||||
#define MASK_JOY1_LEFT 0x0200
|
||||
#define MASK_JOY1_UP 0x0400
|
||||
#define MASK_JOY1_DOWN 0x0800
|
||||
#define MASK_JOY1_BTN 0x1000
|
||||
#define MASK_KEY_USER4 0x2000
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#else
|
||||
#define bool unsigned char
|
||||
#endif
|
||||
|
||||
extern void emu_init(void);
|
||||
extern void emu_start(void);
|
||||
extern void emu_printf(const char * text);
|
||||
extern void emu_printi(int val);
|
||||
extern void emu_printh(int val);
|
||||
extern void * emu_Malloc(unsigned int size);
|
||||
extern void * emu_MallocI(unsigned int size);
|
||||
extern void emu_Free(void * pt);
|
||||
|
||||
extern int emu_FileOpen(const char * filepath, const char * mode);
|
||||
extern int emu_FileRead(void * buf, int size, int handler);
|
||||
extern int emu_FileGetc(int handler);
|
||||
extern int emu_FileSeek(int handler, int seek, int origin);
|
||||
extern int emu_FileTell(int handler);
|
||||
extern void emu_FileClose(int handler);
|
||||
|
||||
extern unsigned int emu_FileSize(const char * filepath);
|
||||
extern unsigned int emu_LoadFile(const char * filepath, void * buf, int size);
|
||||
extern unsigned int emu_LoadFileSeek(const char * filepath, void * buf, int size, int seek);
|
||||
|
||||
extern void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int index);
|
||||
extern void emu_DrawScreen(unsigned char * VBuf, int width, int height, int stride);
|
||||
extern void emu_DrawLine(unsigned char * VBuf, int width, int height, int line);
|
||||
extern void emu_DrawLine16(unsigned short * VBuf, int width, int height, int line);
|
||||
extern void emu_DrawLine8(unsigned char * VBuf, int width, int height, int line);
|
||||
extern void emu_CopyLine(int width, int height, int ysrc, int ydst);
|
||||
extern void emu_DrawVsync(void);
|
||||
extern int emu_FrameSkip(void);
|
||||
extern void * emu_LineBuffer(int line);
|
||||
extern void emu_tweakVideo(int shiftdelta, int numdelta, int denomdelta);
|
||||
|
||||
extern bool menuActive(void);
|
||||
extern char * menuSelection(void);
|
||||
extern char * menuSecondSelection(void);
|
||||
extern void toggleMenu(bool on);
|
||||
extern int handleMenu(unsigned short bClick);
|
||||
|
||||
extern int handleOSKB(void);
|
||||
extern void toggleOSKB(bool forceon);
|
||||
|
||||
extern void emu_InitJoysticks(void);
|
||||
extern int emu_SwapJoysticks(int statusOnly);
|
||||
extern unsigned short emu_DebounceLocalKeys(void);
|
||||
extern int emu_ReadKeys(void);
|
||||
extern int emu_GetPad(void);
|
||||
extern int emu_GetMouse(int *x, int *y, int *buts);
|
||||
extern int emu_MouseDetected(void);
|
||||
extern int emu_KeyboardDetected(void);
|
||||
extern int emu_ReadAnalogJoyX(int min, int max);
|
||||
extern int emu_ReadAnalogJoyY(int min, int max);
|
||||
extern int emu_ReadI2CKeyboard(void);
|
||||
extern unsigned char emu_ReadI2CKeyboard2(int row);
|
||||
extern void emu_KeyboardOnUp(int keymodifer, int key);
|
||||
extern void emu_KeyboardOnDown(int keymodifer, int key);
|
||||
extern void emu_MidiOnDataReceived(unsigned char data);
|
||||
|
||||
extern void emu_sndPlaySound(int chan, int volume, int freq);
|
||||
extern void emu_sndPlayBuzz(int size, int val);
|
||||
extern void emu_sndInit();
|
||||
extern void emu_resetus(void);
|
||||
extern int emu_us(void);
|
||||
|
||||
extern int emu_setKeymap(int index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
148
MCUME_teensy41/teensyspeccy/font8x8.h
Normal file
148
MCUME_teensy41/teensyspeccy/font8x8.h
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
|
||||
// Font: c64_lower.64c
|
||||
|
||||
PROGMEM const unsigned char font8x8[128][8] =
|
||||
{
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F
|
||||
|
||||
{ 0x7f, 0x41, 0x41, 0x41, 0x41, 0x41, 0x7f, 0x00 }, // Space // 0x10
|
||||
{ 0x00, 0x27, 0x31, 0x27, 0x21, 0x71, 0x00, 0x00 }, // F1 // 0x11
|
||||
{ 0x00, 0x77, 0x41, 0x77, 0x11, 0x71, 0x00, 0x00 }, // F2
|
||||
{ 0x00, 0x77, 0x41, 0x77, 0x41, 0x71, 0x00, 0x00 }, // F3
|
||||
{ 0x00, 0x17, 0x51, 0x77, 0x41, 0x41, 0x00, 0x00 }, // F4
|
||||
{ 0x00, 0x77, 0x11, 0x77, 0x41, 0x71, 0x00, 0x00 }, // F5
|
||||
{ 0x00, 0x77, 0x11, 0x77, 0x51, 0x71, 0x00, 0x00 }, // F6
|
||||
{ 0x00, 0x77, 0x41, 0x47, 0x41, 0x41, 0x00, 0x00 }, // F7
|
||||
{ 0x00, 0x77, 0x51, 0x77, 0x51, 0x71, 0x00, 0x00 }, // F8 // 0x18
|
||||
{ 0x00, 0x00, 0x20, 0x24, 0x3e, 0x04, 0x00, 0x00 }, // Return // 0x19
|
||||
{ 0x00, 0x59, 0x4b, 0x5b, 0x4b, 0xd9, 0x00, 0x00 }, // Del // 0x1A
|
||||
//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010
|
||||
//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011
|
||||
//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012
|
||||
//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013
|
||||
//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014
|
||||
//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015
|
||||
//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016
|
||||
//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017
|
||||
//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018
|
||||
//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019
|
||||
//{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space)
|
||||
{ 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!)
|
||||
{ 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (")
|
||||
{ 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#)
|
||||
{ 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($)
|
||||
{ 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%)
|
||||
{ 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&)
|
||||
{ 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (')
|
||||
{ 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (()
|
||||
{ 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ())
|
||||
{ 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*)
|
||||
{ 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,)
|
||||
{ 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.)
|
||||
{ 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/)
|
||||
{ 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0)
|
||||
{ 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1)
|
||||
{ 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2)
|
||||
{ 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3)
|
||||
{ 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4)
|
||||
{ 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5)
|
||||
{ 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6)
|
||||
{ 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7)
|
||||
{ 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8)
|
||||
{ 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9)
|
||||
{ 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:)
|
||||
{ 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (//)
|
||||
{ 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<)
|
||||
{ 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=)
|
||||
{ 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>)
|
||||
{ 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?)
|
||||
{ 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@)
|
||||
{ 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A)
|
||||
{ 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B)
|
||||
{ 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C)
|
||||
{ 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D)
|
||||
{ 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E)
|
||||
{ 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F)
|
||||
{ 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G)
|
||||
{ 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H)
|
||||
{ 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I)
|
||||
{ 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J)
|
||||
{ 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K)
|
||||
{ 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L)
|
||||
{ 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M)
|
||||
{ 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N)
|
||||
{ 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O)
|
||||
{ 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P)
|
||||
{ 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q)
|
||||
{ 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R)
|
||||
{ 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S)
|
||||
{ 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T)
|
||||
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U)
|
||||
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V)
|
||||
{ 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W)
|
||||
{ 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X)
|
||||
{ 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y)
|
||||
{ 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z)
|
||||
{ 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([)
|
||||
{ 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\)
|
||||
{ 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (])
|
||||
{ 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_)
|
||||
{ 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`)
|
||||
{ 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a)
|
||||
{ 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b)
|
||||
{ 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c)
|
||||
{ 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d)
|
||||
{ 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e)
|
||||
{ 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f)
|
||||
{ 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g)
|
||||
{ 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h)
|
||||
{ 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i)
|
||||
{ 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j)
|
||||
{ 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k)
|
||||
{ 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l)
|
||||
{ 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m)
|
||||
{ 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n)
|
||||
{ 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o)
|
||||
{ 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p)
|
||||
{ 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q)
|
||||
{ 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r)
|
||||
{ 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s)
|
||||
{ 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t)
|
||||
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u)
|
||||
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v)
|
||||
{ 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w)
|
||||
{ 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x)
|
||||
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y)
|
||||
{ 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z)
|
||||
{ 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({)
|
||||
{ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|)
|
||||
{ 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (})
|
||||
{ 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F
|
||||
};
|
||||
|
||||
|
||||
124
MCUME_teensy41/teensyspeccy/iopins.h
Normal file
124
MCUME_teensy41/teensyspeccy/iopins.h
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
#ifndef IOPINS_H
|
||||
#define IOPINS_H
|
||||
|
||||
#include "platform_config.h"
|
||||
|
||||
#ifdef TEECOMPUTER
|
||||
|
||||
// Teecomputer layout
|
||||
|
||||
// VGA
|
||||
// R 3 2K
|
||||
// R 4 1K
|
||||
// R 33 500
|
||||
// G 11 2K
|
||||
// G 13 1K
|
||||
// G 2 500
|
||||
// B 10 820
|
||||
// B 12 390
|
||||
// HSYNC 15 82
|
||||
// VSYNC 8 82
|
||||
|
||||
// Display
|
||||
#define TFT_SCLK 27
|
||||
#define TFT_MOSI 26
|
||||
#define TFT_MISO 255
|
||||
#define TFT_TOUCH_CS 255
|
||||
#define TFT_TOUCH_INT 255
|
||||
#define TFT_DC 23
|
||||
#define TFT_CS 22 // 255 for LORES ST7789 (NO CS)
|
||||
#define TFT_RST 255 // 255 for ILI/ST if connected to 3.3V or 24 if really needed
|
||||
|
||||
|
||||
// SD
|
||||
#define SD_CS BUILTIN_SDCARD
|
||||
|
||||
// Audio
|
||||
#define AUDIO_I2S_DIN 7
|
||||
#define AUDIO_I2S_BCK 21
|
||||
#define AUDIO_I2S_LCK 20
|
||||
|
||||
// Keyboard matrix
|
||||
#define KLED 14
|
||||
//Cols (out)
|
||||
//pico 1,2,3,4,5,14
|
||||
//teen 16,6,24,25,28,31
|
||||
#define KCOLOUT1 16
|
||||
#define KCOLOUT2 6
|
||||
#define KCOLOUT3 24
|
||||
#define KCOLOUT4 25
|
||||
#define KCOLOUT5 28
|
||||
#define KCOLOUT6 31
|
||||
//Rows (in)
|
||||
//pico 9,8,6,15,7,22
|
||||
//teen 19,18,17,5,29,30,32 //5,6,16,17,18,19
|
||||
#define KROWIN1 19
|
||||
#define KROWIN2 18
|
||||
#define KROWIN3 17
|
||||
#define KROWIN4 5
|
||||
#define KROWIN5 29
|
||||
#define KROWIN6 30
|
||||
#define KROWIN7 32
|
||||
|
||||
#define PIN_KEY_USER1 41
|
||||
#define PIN_KEY_USER2 40
|
||||
|
||||
// Second joystick (external)
|
||||
#define PIN_JOY1_BTN 34
|
||||
#define PIN_JOY1_1 35 // UP
|
||||
#define PIN_JOY1_2 36 // DOWN
|
||||
#define PIN_JOY1_3 38 // RIGHT
|
||||
#define PIN_JOY1_4 37 // LEFT
|
||||
|
||||
#else
|
||||
|
||||
// Original Layout
|
||||
#define TFT_SCLK 13
|
||||
#define TFT_MOSI 11
|
||||
#define TFT_MISO 12
|
||||
#define TFT_TOUCH_CS 255
|
||||
#define TFT_TOUCH_INT 255
|
||||
#define TFT_DC 9
|
||||
#define TFT_CS 22 // 255 for LORES ST7789 (NO CS)
|
||||
#define TFT_RST 23 // 255 for ILI/ST if connected to 3.3V
|
||||
|
||||
// SD
|
||||
#define SD_CS BUILTIN_SDCARD
|
||||
|
||||
// I2C keyboard
|
||||
#define I2C_SCL_IO 19
|
||||
#define I2C_SDA_IO 18
|
||||
|
||||
// Analog joystick (primary) for JOY2 and 5 extra buttons
|
||||
#ifdef HAS_T4_VGA
|
||||
#define PIN_JOY2_A1X A3
|
||||
#define PIN_JOY2_A2Y A2
|
||||
#define PIN_JOY2_BTN 14
|
||||
#define PIN_KEY_USER1 22
|
||||
#define PIN_KEY_USER2 23
|
||||
|
||||
// Second joystick
|
||||
#define PIN_JOY1_BTN 34
|
||||
#define PIN_JOY1_1 35 // UP
|
||||
#define PIN_JOY1_2 36 // DOWN
|
||||
#define PIN_JOY1_3 38 // RIGHT
|
||||
#define PIN_JOY1_4 37 // LEFT
|
||||
|
||||
#else
|
||||
#define PIN_JOY2_A1X A1
|
||||
#define PIN_JOY2_A2Y A2
|
||||
#define PIN_JOY2_BTN 17
|
||||
#define PIN_KEY_USER1 3 //34
|
||||
#define PIN_KEY_USER2 4 //35
|
||||
|
||||
// Second joystick
|
||||
#define PIN_JOY1_BTN 2
|
||||
#define PIN_JOY1_1 14 // UP
|
||||
#define PIN_JOY1_2 7 // DOWN
|
||||
#define PIN_JOY1_3 6 // RIGHT
|
||||
#define PIN_JOY1_4 5 // LEFT
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
39
MCUME_teensy41/teensyspeccy/platform_config.h
Normal file
39
MCUME_teensy41/teensyspeccy/platform_config.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef _PLATFORM_CONFIG_H_
|
||||
#define _PLATFORM_CONFIG_H_
|
||||
|
||||
#define TEECOMPUTER 1
|
||||
|
||||
#ifdef TEECOMPUTER
|
||||
//#define ILI9341 1
|
||||
//#define ST7789 1
|
||||
//#define TFTSPI1 1
|
||||
#define HAS_T4_VGA 1
|
||||
#define HAS_SND 1
|
||||
#define HAS_USBKEY 1
|
||||
#define INVX 1
|
||||
#else
|
||||
|
||||
#define HAS_T4_VGA 1
|
||||
//#define INVX 1
|
||||
#define INVY 1
|
||||
#define HAS_SND 1
|
||||
#define HAS_USBKEY 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//#define ILI9341 1
|
||||
//#define ST7789 1
|
||||
//#define SWAP_JOYSTICK 1
|
||||
//#define LOHRES 1
|
||||
//#define ROTATE_SCREEN 1
|
||||
//#define EXTERNAL_SD 1
|
||||
|
||||
|
||||
//#define USE_SDFAT 1
|
||||
//#define SD_FAT_TYPE 1
|
||||
//#define USE_SDFS 1
|
||||
//#define SDFSDEV "1:"
|
||||
|
||||
|
||||
#endif
|
||||
595
MCUME_teensy41/teensyspeccy/spec.c
Normal file
595
MCUME_teensy41/teensyspeccy/spec.c
Normal file
|
|
@ -0,0 +1,595 @@
|
|||
#include "Z80.h"
|
||||
#include "spectrum.rom.h"
|
||||
#include "emuapi.h"
|
||||
#include "zx_filetyp_z80.h"
|
||||
|
||||
#include "AY8910.h"
|
||||
|
||||
#define RAM_SIZE 0xC000 //0x20000 // 0xC000
|
||||
|
||||
#define WIDTH 320
|
||||
#define HEIGHT 192
|
||||
|
||||
#define CYCLES_PER_FRAME 69888 //3500000/50
|
||||
|
||||
typedef struct {
|
||||
int port_ff; // 0xff = emulate the port, 0x00 alwais 0xFF
|
||||
int ts_lebo; // left border t states
|
||||
int ts_grap; // graphic zone t states
|
||||
int ts_ribo; // right border t states
|
||||
int ts_hore; // horizontal retrace t states
|
||||
int ts_line; // to speed the calc, the sum of 4 abobe
|
||||
int line_poin; // lines in retraze post interrup
|
||||
int line_upbo; // lines of upper border
|
||||
int line_grap; // lines of graphic zone = 192
|
||||
int line_bobo; // lines of bottom border
|
||||
int line_retr; // lines of the retrace
|
||||
/*
|
||||
int TSTATES_PER_LINE;
|
||||
int TOP_BORDER_LINES;
|
||||
int SCANLINES;
|
||||
int BOTTOM_BORDER_LINES;
|
||||
int tstate_border_left;
|
||||
int tstate_graphic_zone;
|
||||
int tstate_border_right;
|
||||
int hw_model;
|
||||
int int_type;
|
||||
int videopage;
|
||||
int BANKM;
|
||||
int BANK678;
|
||||
*/
|
||||
} HWOptions ;
|
||||
|
||||
static HWOptions hwopt = { 0xFF, 24, 128, 24, 48, 224, 16, 48, 192, 48, 8 };
|
||||
//224, 64, 192, 56, 24, 128, 72};
|
||||
|
||||
struct { unsigned char R,G,B; } Palette[16] = {
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 205},
|
||||
{ 205, 0, 0},
|
||||
{ 205, 0, 205},
|
||||
{ 0, 205, 0},
|
||||
{ 0, 205, 205},
|
||||
{ 205, 205, 0},
|
||||
{ 212, 212, 212},
|
||||
{ 0, 0, 0},
|
||||
{ 0, 0, 255},
|
||||
{ 255, 0, 0},
|
||||
{ 255, 0, 255},
|
||||
{ 0, 255, 0},
|
||||
{ 0, 255, 255},
|
||||
{ 255, 255, 0},
|
||||
{ 255, 255, 255}
|
||||
};
|
||||
|
||||
const byte map_qw[8][5] = {
|
||||
{25, 6,27,29,224}, // vcxz<caps shift=Lshift>
|
||||
{10, 9, 7,22, 4}, // gfdsa
|
||||
{23,21, 8,26,20}, // trewq
|
||||
{34,33,32,31,30}, // 54321
|
||||
{35,36,37,38,39}, // 67890
|
||||
{28,24,12,18,19}, // yuiop
|
||||
{11,13,14,15,40}, // hjkl<enter>
|
||||
{ 5,17,16,225,44}, // bnm <symbshift=RSHift> <space>
|
||||
};
|
||||
|
||||
|
||||
static byte Z80_RAM[RAM_SIZE]; // 48k RAM
|
||||
static Z80 myCPU;
|
||||
static byte * volatile VRAM=Z80_RAM; // What will be displayed. Generally ZX VRAM, can be changed for alt screens.
|
||||
|
||||
//extern const byte rom_zx48_rom[]; // 16k ROM
|
||||
static byte key_ram[8]={
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; // Keyboard buffer
|
||||
byte out_ram; // Output (fe port)
|
||||
static byte kempston_ram; // Kempston-Joystick Buffer
|
||||
|
||||
static int v_border=0;
|
||||
static int h_border=32;
|
||||
static int bordercolor=0;
|
||||
static byte * XBuf=0;
|
||||
|
||||
static int lastaudio=CYCLES_PER_FRAME;
|
||||
static byte buzzer_val;
|
||||
|
||||
#define INV_KEY 0
|
||||
|
||||
const int16_t keyboardAsciiConv[] = // Ascii to Spectrum keys
|
||||
{
|
||||
/* 0x00 */ INV_KEY,
|
||||
/* 0x01 */ INV_KEY,
|
||||
/* 0x02 */ INV_KEY,
|
||||
/* 0x03 */ INV_KEY,
|
||||
/* 0x04 */ INV_KEY,
|
||||
/* 0x05 */ INV_KEY,
|
||||
/* 0x06 */ INV_KEY,
|
||||
/* 0x07 */ INV_KEY,
|
||||
/* 0x08 */ INV_KEY,
|
||||
/* 0x09 */ INV_KEY, // tab
|
||||
/* 0x0A */ 40, // enter
|
||||
/* 0x0B */ INV_KEY,
|
||||
/* 0x0C */ INV_KEY,
|
||||
/* 0x0D */ INV_KEY,
|
||||
/* 0x0E */ INV_KEY,
|
||||
/* 0x0F */ INV_KEY,
|
||||
/* 0x10 */ INV_KEY,
|
||||
/* 0x11 */ INV_KEY,
|
||||
/* 0x12 */ INV_KEY,
|
||||
/* 0x13 */ INV_KEY,
|
||||
/* 0x14 */ INV_KEY,
|
||||
/* 0x15 */ INV_KEY,
|
||||
/* 0x16 */ INV_KEY,
|
||||
/* 0x17 */ INV_KEY,
|
||||
/* 0x18 */ INV_KEY,
|
||||
/* 0x19 */ INV_KEY,
|
||||
/* 0x1A */ INV_KEY,
|
||||
/* 0x1B */ INV_KEY, // esc
|
||||
/* 0x1C */ INV_KEY,
|
||||
/* 0x1D */ INV_KEY,
|
||||
/* 0x1E */ INV_KEY,
|
||||
/* 0x1F */ INV_KEY,
|
||||
/* 0x20 */ 44, // space
|
||||
/* 0x21 */ 30+64, // ! exclamation mark
|
||||
/* 0x22 */ 19+64, // " double quote
|
||||
/* 0x23 */ 32+64, // # dies
|
||||
/* 0x24 */ 33+64, // $ dollar
|
||||
/* 0x25 */ 34+64, // % percent
|
||||
/* 0x26 */ 35+64, // & ampercent
|
||||
/* 0x27 */ INV_KEY, // ' singlequote
|
||||
/* 0x28 */ 37+64, // ( bracket left
|
||||
/* 0x29 */ 38+64, // ) bracket right
|
||||
/* 0x2A */ 5+64, // * mult
|
||||
/* 0x2B */ 14+64, // + plus
|
||||
/* 0x2C */ 17+64, // , comma
|
||||
/* 0x2D */ 13+64, // - minus
|
||||
/* 0x2E */ 16+64, // . period
|
||||
/* 0x2F */ 25+64, // / slash
|
||||
/* 0x30 */ 39, // 0
|
||||
/* 0x31 */ 30, // 1
|
||||
/* 0x32 */ 31, // 2
|
||||
/* 0x33 */ 32, // 3
|
||||
/* 0x34 */ 33, // 4
|
||||
/* 0x35 */ 34, // 5
|
||||
/* 0x36 */ 35, // 6
|
||||
/* 0x37 */ 36, // 7
|
||||
/* 0x38 */ 37, // 8
|
||||
/* 0x39 */ 38, // 9
|
||||
/* 0x3A */ 29+64, // : colon
|
||||
/* 0x3B */ 18+64, // ; semi colon
|
||||
/* 0x3C */ 21+64, // <
|
||||
/* 0x3D */ 15+64, // = equal
|
||||
/* 0x3E */ 23+64, // >
|
||||
/* 0x3F */ 6+64, // ?
|
||||
/* 0x40 */ 31+64, // @
|
||||
/* 0x41 */ 4+128, // A
|
||||
/* 0x42 */ 5+128, // B
|
||||
/* 0x43 */ 6+128, // C
|
||||
/* 0x44 */ 7+128, // D
|
||||
/* 0x45 */ 8+128, // E
|
||||
/* 0x46 */ 9+128, // F
|
||||
/* 0x47 */ 10+128, // G
|
||||
/* 0x48 */ 11+128, // H
|
||||
/* 0x49 */ 12+128, // I
|
||||
/* 0x4A */ 13+128, // J
|
||||
/* 0x4B */ 14+128, // K
|
||||
/* 0x4C */ 15+128, // L
|
||||
/* 0x4D */ 16+128, // M
|
||||
/* 0x4E */ 17+128, // N
|
||||
/* 0x4F */ 18+128, // O
|
||||
/* 0x50 */ 19+128, // P
|
||||
/* 0x51 */ 20+128, // Q
|
||||
/* 0x52 */ 21+128, // R
|
||||
/* 0x53 */ 22+128, // S
|
||||
/* 0x54 */ 23+128, // T
|
||||
/* 0x55 */ 24+128, // U
|
||||
/* 0x56 */ 25+128, // V
|
||||
/* 0x57 */ 26+128, // W
|
||||
/* 0x58 */ 27+128, // X
|
||||
/* 0x59 */ 28+128, // Y
|
||||
/* 0x5A */ 29+128, // Z
|
||||
/* 0x5B */ INV_KEY, // square bracket open
|
||||
/* 0x5C */ INV_KEY, // baclslach
|
||||
/* 0x5D */ INV_KEY, // square braquet close
|
||||
/* 0x5E */ INV_KEY, // ^ circonflex
|
||||
/* 0x5F */ INV_KEY, // _ undescore
|
||||
/* 0x60 */ INV_KEY, // `backquote
|
||||
/* 0x61 */ 4, // a
|
||||
/* 0x62 */ 5, // b
|
||||
/* 0x63 */ 6, // c
|
||||
/* 0x64 */ 7, // d
|
||||
/* 0x65 */ 8, // e
|
||||
/* 0x66 */ 9, // f
|
||||
/* 0x67 */ 10, // g
|
||||
/* 0x68 */ 11, // h
|
||||
/* 0x69 */ 12, // i
|
||||
/* 0x6A */ 13, // j
|
||||
/* 0x6B */ 14, // k
|
||||
/* 0x6C */ 15, // l
|
||||
/* 0x6D */ 16, // m
|
||||
/* 0x6E */ 17, // n
|
||||
/* 0x6F */ 18, // o
|
||||
/* 0x70 */ 19, // p
|
||||
/* 0x71 */ 20, // q
|
||||
/* 0x72 */ 21, // r
|
||||
/* 0x73 */ 22, // s
|
||||
/* 0x74 */ 23, // t
|
||||
/* 0x75 */ 24, // u
|
||||
/* 0x76 */ 25, // v
|
||||
/* 0x77 */ 26, // w
|
||||
/* 0x78 */ 27, // x
|
||||
/* 0x79 */ 28, // y
|
||||
/* 0x7A */ 29, // z
|
||||
/* 0x7B */ INV_KEY, // curly bracket open
|
||||
/* 0x7C */ INV_KEY, // or
|
||||
/* 0x7D */ INV_KEY, // curly bracket close
|
||||
/* 0x7E */ INV_KEY, // tilt
|
||||
/* 0x7F */ 39+128, // backspace
|
||||
|
||||
/* 0xC0 */ INV_KEY,
|
||||
/* 0xC1 */ INV_KEY,
|
||||
/* 0xC2 */ INV_KEY, // F1
|
||||
/* 0xC3 */ INV_KEY, // F2
|
||||
/* 0xC4 */ INV_KEY, // F3
|
||||
/* 0xC5 */ INV_KEY, // F4
|
||||
/* 0xC6 */ INV_KEY, // F5
|
||||
/* 0xC7 */ INV_KEY, // F6
|
||||
/* 0xC8 */ INV_KEY, // F7
|
||||
/* 0xC9 */ INV_KEY, // F8
|
||||
/* 0xCA */ INV_KEY, // F9
|
||||
/* 0xCB */ INV_KEY, // F10
|
||||
/* 0xCC */ INV_KEY,
|
||||
/* 0xCD */ INV_KEY,
|
||||
/* 0xCE */ INV_KEY,
|
||||
/* 0xCF */ INV_KEY,
|
||||
/* 0xD0 */ INV_KEY,
|
||||
/* 0xD1 */ INV_KEY,
|
||||
/* 0xD2 */ INV_KEY,
|
||||
/* 0xD3 */ INV_KEY,
|
||||
/* 0xD4 */ INV_KEY, // DEL
|
||||
/* 0xD5 */ INV_KEY,
|
||||
/* 0xD6 */ INV_KEY,
|
||||
/* 0xD7 */ 37+128, // U
|
||||
/* 0xD8 */ 34+128, // L
|
||||
/* 0xD9 */ 35+128, // R
|
||||
/* 0xDA */ 36+128, // D
|
||||
/* 0xDB */ INV_KEY,
|
||||
/* 0xDC */ INV_KEY,
|
||||
/* 0xDD */ INV_KEY,
|
||||
/* 0xDE */ INV_KEY,
|
||||
/* 0xDF */ INV_KEY
|
||||
};
|
||||
|
||||
|
||||
void displayscanline(int y, int f_flash)
|
||||
{
|
||||
int x, row, col, dir_p, dir_a, pixeles, tinta, papel, atributos;
|
||||
|
||||
row = y + v_border; // 4 & 32 = graphical screen offset
|
||||
col = 0; // 32+256+32=320 4+192+4=200 (res=320x200)
|
||||
|
||||
for (x = 0; x < h_border; x++) {
|
||||
XBuf[col++] = bordercolor;
|
||||
}
|
||||
|
||||
dir_p = ((y & 0xC0) << 5) + ((y & 0x07) << 8) + ((y & 0x38) << 2);
|
||||
dir_a = 0x1800 + (32 * (y >> 3));
|
||||
|
||||
for (x = 0; x < 32; x++)
|
||||
{
|
||||
pixeles= VRAM[dir_p++];
|
||||
atributos=VRAM[dir_a++];
|
||||
|
||||
if (((atributos & 0x80) == 0) || (f_flash == 0))
|
||||
{
|
||||
tinta = (atributos & 0x07) + ((atributos & 0x40) >> 3);
|
||||
papel = (atributos & 0x78) >> 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
papel = (atributos & 0x07) + ((atributos & 0x40) >> 3);
|
||||
tinta = (atributos & 0x78) >> 3;
|
||||
}
|
||||
XBuf[col++] = ((pixeles & 0x80) ? tinta : papel);
|
||||
XBuf[col++] = ((pixeles & 0x40) ? tinta : papel);
|
||||
XBuf[col++] = ((pixeles & 0x20) ? tinta : papel);
|
||||
XBuf[col++] = ((pixeles & 0x10) ? tinta : papel);
|
||||
XBuf[col++] = ((pixeles & 0x08) ? tinta : papel);
|
||||
XBuf[col++] = ((pixeles & 0x04) ? tinta : papel);
|
||||
XBuf[col++] = ((pixeles & 0x02) ? tinta : papel);
|
||||
XBuf[col++] = ((pixeles & 0x01) ? tinta : papel);
|
||||
}
|
||||
|
||||
for (x = 0; x < h_border; x++) {
|
||||
XBuf[col++] = bordercolor;
|
||||
}
|
||||
|
||||
emu_DrawLine(XBuf, WIDTH, HEIGHT, y);
|
||||
}
|
||||
|
||||
static void displayScreen(void) {
|
||||
int y;
|
||||
static int f_flash = 1, f_flash2 = 0;
|
||||
f_flash2 = (f_flash2++) % 32;
|
||||
if (f_flash2 < 16)
|
||||
f_flash = 1;
|
||||
else
|
||||
f_flash = 0;
|
||||
|
||||
for (y = 0; y < HEIGHT; y++)
|
||||
displayscanline (y, f_flash);
|
||||
|
||||
emu_DrawVsync();
|
||||
}
|
||||
|
||||
|
||||
static int ik; // joypad key
|
||||
static int ihk; // I2C keyboard key
|
||||
static int iusbhk; // USB keyboard key
|
||||
static int prevhk; // previous keyboard key
|
||||
|
||||
static void InitKeyboard(void){
|
||||
memset(key_ram, 0xff, sizeof(key_ram));
|
||||
}
|
||||
|
||||
static void UpdateKeyboard (int asckey)
|
||||
{
|
||||
int hk = keyboardAsciiConv[asckey];
|
||||
memset(key_ram, 0xff, sizeof(key_ram));
|
||||
{
|
||||
//if (k & MASK_KEY_USER1) hk = 39;
|
||||
int shift = hk;
|
||||
if (hk >=128) hk -= 128;
|
||||
else if (hk >=64) hk -= 64;
|
||||
// scan all possibilities
|
||||
for (int j=0;j<8;j++) {
|
||||
for(int i=0;i<5;i++){
|
||||
if ( /*(k == map_qw[j][i]) ||*/ (hk == map_qw[j][i]) ) {
|
||||
key_ram[j] &= ~ (1<<(4-i));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shift >=128) key_ram[0] &= ~ (1<<0); // SHift
|
||||
else if (shift >=64) key_ram[7] &= ~ (1<<1); // SHift symboles
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define MAX_Z80SIZE RAM_SIZE
|
||||
|
||||
|
||||
int endsWith(const char * s, const char * suffix)
|
||||
{
|
||||
int retval = 0;
|
||||
int len = strlen(s);
|
||||
int slen = strlen(suffix);
|
||||
if (len > slen ) {
|
||||
if (!strcmp(&s[len-slen], suffix)) {
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
return (retval);
|
||||
}
|
||||
|
||||
void emu_KeyboardOnDown(int keymodifer, int key) {
|
||||
int keyCode = -1; //INV_KEY;
|
||||
if ((key >=0xc0) && (key <=0xdf)) {
|
||||
keyCode = ((key-0xc0) & 0x1f) + 0x80;
|
||||
}
|
||||
else {
|
||||
keyCode = key & 0x7f;
|
||||
}
|
||||
|
||||
//emu_printh(key);
|
||||
//emu_printh(keyCode);
|
||||
|
||||
if (keyCode != -1) {
|
||||
iusbhk = keyCode;
|
||||
}
|
||||
}
|
||||
|
||||
void emu_KeyboardOnUp(int keymodifer, int key) {
|
||||
iusbhk = 0;
|
||||
}
|
||||
|
||||
void spec_Start(char * filename) {
|
||||
memset(Z80_RAM, 0, RAM_SIZE);
|
||||
if ( (endsWith(filename, "SNA")) || (endsWith(filename, "sna")) ) {
|
||||
ZX_ReadFromFlash_SNA(&myCPU, filename);
|
||||
}
|
||||
else if ( (endsWith(filename, "Z80")) || (endsWith(filename, "z80")) ) {
|
||||
unsigned char * game = emu_Malloc(MAX_Z80SIZE);
|
||||
int size = emu_LoadFile(filename, game, MAX_Z80SIZE);
|
||||
ZX_ReadFromFlash_Z80(&myCPU, game,size);
|
||||
emu_Free(game);
|
||||
}
|
||||
#if HAS_SND
|
||||
emu_sndInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
void spec_Input(int click) {
|
||||
ik = emu_GetPad();
|
||||
ihk = emu_ReadI2CKeyboard();
|
||||
}
|
||||
|
||||
|
||||
static AY8910 ay;
|
||||
|
||||
void spec_Init(void) {
|
||||
int J;
|
||||
/* Set up the palette */
|
||||
for(J=0;J<16;J++)
|
||||
emu_SetPaletteEntry(Palette[J].R,Palette[J].G,Palette[J].B, J);
|
||||
|
||||
InitKeyboard();
|
||||
|
||||
Reset8910(&ay,3500000,0);
|
||||
|
||||
|
||||
if (XBuf == 0) XBuf = (byte *)emu_Malloc(WIDTH);
|
||||
VRAM = Z80_RAM;
|
||||
//memset(Z80_RAM, 0, RAM_SIZE);
|
||||
|
||||
ResetZ80(&myCPU, CYCLES_PER_FRAME);
|
||||
#if ALT_Z80CORE
|
||||
myCPU.RAM = Z80_RAM;
|
||||
Z80FlagTables();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void spec_Step(void) {
|
||||
// 32+256+32
|
||||
//#define NBLINES (48+192+56+16)
|
||||
|
||||
// Now run the emulator for all the real screen (192 lines)
|
||||
/*
|
||||
int scanl;
|
||||
for (scanl = 0; scanl < NBLINES; scanl++) {
|
||||
int ref=0;
|
||||
emu_resetus();
|
||||
ExecZ80(&myCPU,hwopt.ts_line);
|
||||
while (emu_us() < (20000/NBLINES)) {
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
ExecZ80(&myCPU,CYCLES_PER_FRAME); // 3.5MHz ticks for 6 lines @ 30 kHz = 700 cycles
|
||||
#if ALT_Z80CORE
|
||||
#else
|
||||
IntZ80(&myCPU,INT_IRQ); // must be called every 20ms
|
||||
#endif
|
||||
displayScreen();
|
||||
|
||||
int k = ik;
|
||||
int hk = ihk;
|
||||
if (iusbhk) hk = iusbhk;
|
||||
|
||||
kempston_ram = 0x00;
|
||||
if (k & MASK_JOY2_BTN)
|
||||
kempston_ram |= 0x10; //Fire
|
||||
if (k & MASK_JOY2_UP)
|
||||
kempston_ram |= 0x8; //Up
|
||||
if (k & MASK_JOY2_DOWN)
|
||||
kempston_ram |= 0x4; //Down
|
||||
if (k & MASK_JOY2_RIGHT)
|
||||
kempston_ram |= 0x2; //Right
|
||||
if (k & MASK_JOY2_LEFT)
|
||||
kempston_ram |= 0x1; //Left
|
||||
|
||||
UpdateKeyboard(hk);
|
||||
|
||||
Loop8910(&ay,20);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define BASERAM 0x4000
|
||||
|
||||
|
||||
void WrZ80(register word Addr,register byte Value)
|
||||
{
|
||||
if (Addr >= BASERAM)
|
||||
Z80_RAM[Addr-BASERAM]=Value;
|
||||
}
|
||||
|
||||
byte RdZ80(register word Addr)
|
||||
{
|
||||
if (Addr<BASERAM)
|
||||
return rom_zx48_rom[Addr];
|
||||
else
|
||||
return Z80_RAM[Addr-BASERAM];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void buzz(int val, int currentTstates)
|
||||
{
|
||||
//if (val==0) val = -1;
|
||||
//if (buzzer_val!=val)
|
||||
//if (val)
|
||||
{
|
||||
int sound_size = (currentTstates-lastaudio);
|
||||
if (sound_size < 0) sound_size += CYCLES_PER_FRAME;
|
||||
#if HAS_SND
|
||||
emu_sndPlayBuzz(sound_size,buzzer_val);
|
||||
#endif
|
||||
//if (val)
|
||||
// buzzer_val = 0;
|
||||
//else
|
||||
// buzzer_val = 1;
|
||||
buzzer_val = val;
|
||||
}
|
||||
lastaudio = currentTstates;
|
||||
}
|
||||
|
||||
void OutZ80(register word Port,register byte Value)
|
||||
{
|
||||
if ((Port & 0xC002) == 0xC000) {
|
||||
WrCtrl8910(&ay,(Value &0x0F));
|
||||
}
|
||||
else if ((Port & 0xC002) == 0x8000) {
|
||||
WrData8910(&ay,Value);
|
||||
}
|
||||
else if (!(Port & 0x01)) {
|
||||
bordercolor = (Value & 0x07);
|
||||
byte mic = (Value & 0x08);
|
||||
byte ear = (Value & 0x10);
|
||||
buzz(((/*mic|*/ear)?1:0), CYCLES_PER_FRAME-myCPU.ICount);
|
||||
}
|
||||
else if((Port&0xFF)==0xFE) {
|
||||
out_ram=Value; // update it
|
||||
}
|
||||
}
|
||||
|
||||
byte InZ80(register word port)
|
||||
{
|
||||
if (port == 0xFFFD) {
|
||||
return (RdData8910(&ay));
|
||||
}
|
||||
|
||||
if((port&0xFF)==0x1F) {
|
||||
// kempston RAM
|
||||
return kempston_ram;
|
||||
}
|
||||
|
||||
if ((port&0xFF)==0xFE) {
|
||||
switch(port>>8) {
|
||||
case 0xFE : return key_ram[0]; break;
|
||||
case 0xFD : return key_ram[1]; break;
|
||||
case 0xFB : return key_ram[2]; break;
|
||||
case 0xF7 : return key_ram[3]; break;
|
||||
case 0xEF : return key_ram[4]; break;
|
||||
case 0xDF : return key_ram[5]; break;
|
||||
case 0xBF : return key_ram[6]; break;
|
||||
case 0x7F : return key_ram[7]; break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((port & 0xFF) == 0xFF) {
|
||||
if (hwopt.port_ff == 0xFF) {
|
||||
return 0xFF;
|
||||
}
|
||||
else {
|
||||
//code = 1;
|
||||
//if (code == 0xFF) code = 0x00;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
||||
void PatchZ80(register Z80 *R)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
/*
|
||||
word LoopZ80(register Z80 *R)
|
||||
{
|
||||
// no interrupt triggered
|
||||
return INT_NONE;
|
||||
}
|
||||
*/
|
||||
4
MCUME_teensy41/teensyspeccy/spec.h
Normal file
4
MCUME_teensy41/teensyspeccy/spec.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
extern void spec_Init(void);
|
||||
extern void spec_Step(void);
|
||||
extern void spec_Start(char * filename);
|
||||
extern void spec_Input(int click);
|
||||
1373
MCUME_teensy41/teensyspeccy/spectrum.rom.h
Executable file
1373
MCUME_teensy41/teensyspeccy/spectrum.rom.h
Executable file
File diff suppressed because it is too large
Load diff
206
MCUME_teensy41/teensyspeccy/teensyspeccy.ino
Normal file
206
MCUME_teensy41/teensyspeccy/teensyspeccy.ino
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
extern "C" {
|
||||
#include "iopins.h"
|
||||
#include "emuapi.h"
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#include "spec.h"
|
||||
}
|
||||
|
||||
#ifdef HAS_T4_VGA
|
||||
#include "vga_t_dma.h"
|
||||
TFT_T_DMA tft;
|
||||
#else
|
||||
#include "tft_t_dma.h"
|
||||
TFT_T_DMA tft = TFT_T_DMA(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO, TFT_TOUCH_CS, TFT_TOUCH_INT);
|
||||
#endif
|
||||
|
||||
bool vgaMode = false;
|
||||
|
||||
static unsigned char palette8[PALETTE_SIZE];
|
||||
static unsigned short palette16[PALETTE_SIZE];
|
||||
static IntervalTimer myTimer;
|
||||
volatile boolean vbl=true;
|
||||
static int skip=0;
|
||||
static elapsedMicros tius;
|
||||
|
||||
static void vblCount() {
|
||||
if (vbl) {
|
||||
vbl = false;
|
||||
} else {
|
||||
vbl = true;
|
||||
}
|
||||
}
|
||||
|
||||
void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int index)
|
||||
{
|
||||
if (index<PALETTE_SIZE) {
|
||||
//Serial.println("%d: %d %d %d\n", index, r,g,b);
|
||||
palette8[index] = RGBVAL8(r,g,b);
|
||||
palette16[index] = RGBVAL16(r,g,b);
|
||||
}
|
||||
}
|
||||
|
||||
void emu_DrawVsync(void)
|
||||
{
|
||||
volatile boolean vb=vbl;
|
||||
skip += 1;
|
||||
skip &= VID_FRAME_SKIP;
|
||||
if (!vgaMode) {
|
||||
#ifdef HAS_T4_VGA
|
||||
tft.waitSync();
|
||||
#else
|
||||
while (vbl==vb) {};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void emu_DrawLine(unsigned char * VBuf, int width, int height, int line)
|
||||
{
|
||||
if (!vgaMode) {
|
||||
#ifdef HAS_T4_VGA
|
||||
tft.writeLine(width,1,line, VBuf, palette8);
|
||||
#else
|
||||
tft.writeLine(width,1,line, VBuf, palette16);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void emu_DrawLine8(unsigned char * VBuf, int width, int height, int line)
|
||||
{
|
||||
if (!vgaMode) {
|
||||
if (skip==0) {
|
||||
#ifdef HAS_T4_VGA
|
||||
tft.writeLine(width,height,line, VBuf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void emu_DrawLine16(unsigned short * VBuf, int width, int height, int line)
|
||||
{
|
||||
if (!vgaMode) {
|
||||
if (skip==0) {
|
||||
#ifdef HAS_T4_VGA
|
||||
tft.writeLine16(width,height,line, VBuf);
|
||||
#else
|
||||
tft.writeLine(width,height,line, VBuf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void emu_DrawScreen(unsigned char * VBuf, int width, int height, int stride)
|
||||
{
|
||||
if (!vgaMode) {
|
||||
if (skip==0) {
|
||||
#ifdef HAS_T4_VGA
|
||||
tft.writeScreen(width,height-TFT_VBUFFER_YCROP,stride, VBuf+(TFT_VBUFFER_YCROP/2)*stride, palette8);
|
||||
#else
|
||||
tft.writeScreen(width,height-TFT_VBUFFER_YCROP,stride, VBuf+(TFT_VBUFFER_YCROP/2)*stride, palette16);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int emu_FrameSkip(void)
|
||||
{
|
||||
return skip;
|
||||
}
|
||||
|
||||
void * emu_LineBuffer(int line)
|
||||
{
|
||||
if (!vgaMode) {
|
||||
return (void*)tft.getLineBuffer(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ****************************************************
|
||||
// the setup() method runs once, when the sketch starts
|
||||
// ****************************************************
|
||||
void setup() {
|
||||
|
||||
#ifdef HAS_T4_VGA
|
||||
tft.begin(VGA_MODE_320x240);
|
||||
// NVIC_SET_PRIORITY(IRQ_QTIMER3, 0);
|
||||
#else
|
||||
tft.begin();
|
||||
#endif
|
||||
|
||||
emu_init();
|
||||
}
|
||||
|
||||
|
||||
// ****************************************************
|
||||
// the loop() method runs continuously
|
||||
// ****************************************************
|
||||
void loop(void)
|
||||
{
|
||||
if (menuActive()) {
|
||||
uint16_t bClick = emu_DebounceLocalKeys();
|
||||
int action = handleMenu(bClick);
|
||||
char * filename = menuSelection();
|
||||
if (action == ACTION_RUN1) {
|
||||
toggleMenu(false);
|
||||
vgaMode = false;
|
||||
emu_start();
|
||||
emu_Init(filename);
|
||||
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
|
||||
tft.startDMA();
|
||||
myTimer.begin(vblCount, 16666); //to run every 16.666ms
|
||||
}
|
||||
delay(20);
|
||||
}
|
||||
else {
|
||||
uint16_t bClick = emu_DebounceLocalKeys();
|
||||
emu_Input(bClick);
|
||||
emu_Step();
|
||||
delay(10);
|
||||
//uint16_t bClick = emu_DebounceLocalKeys();
|
||||
//if (bClick & MASK_KEY_USER1) {
|
||||
// emu_Input(bClick);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAS_SND
|
||||
|
||||
#include "AudioPlaySystem.h"
|
||||
|
||||
AudioPlaySystem mymixer;
|
||||
|
||||
|
||||
void emu_sndInit() {
|
||||
Serial.println("sound init");
|
||||
#ifdef HAS_T4_VGA
|
||||
tft.begin_audio(256, mymixer.snd_Mixer);
|
||||
#else
|
||||
mymixer.begin_audio(256, mymixer.snd_Mixer);
|
||||
#endif
|
||||
// sgtl5000_1.enable();
|
||||
// sgtl5000_1.volume(0.6);
|
||||
mymixer.start();
|
||||
}
|
||||
|
||||
void emu_sndPlaySound(int chan, int volume, int freq)
|
||||
{
|
||||
if (chan < 6) {
|
||||
mymixer.sound(chan, freq, volume);
|
||||
}
|
||||
/*
|
||||
Serial.print(chan);
|
||||
Serial.print(":" );
|
||||
Serial.print(volume);
|
||||
Serial.print(":" );
|
||||
Serial.println(freq);
|
||||
*/
|
||||
}
|
||||
|
||||
void emu_sndPlayBuzz(int size, int val) {
|
||||
//mymixer.buzz(size,val);
|
||||
//Serial.print((val==1)?1:0);
|
||||
//Serial.print(":");
|
||||
//Serial.println(size);
|
||||
}
|
||||
#endif
|
||||
1243
MCUME_teensy41/teensyspeccy/tft_t_dma.cpp
Normal file
1243
MCUME_teensy41/teensyspeccy/tft_t_dma.cpp
Normal file
File diff suppressed because it is too large
Load diff
232
MCUME_teensy41/teensyspeccy/tft_t_dma.h
Normal file
232
MCUME_teensy41/teensyspeccy/tft_t_dma.h
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
Based on C64 ILI9341 dma driver from Frank Bösing, 2017
|
||||
*/
|
||||
|
||||
#ifndef _TFT_T_DMAH_
|
||||
#define _TFT_T_DMAH_
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
#include <DMAChannel.h>
|
||||
#endif
|
||||
|
||||
#include "tft_t_dma_config.h"
|
||||
|
||||
#define RGBVAL32(r,g,b) ( (r<<16) | (g<<8) | b )
|
||||
#define RGBVAL16(r,g,b) ( (((r>>3)&0x1f)<<11) | (((g>>2)&0x3f)<<5) | (((b>>3)&0x1f)<<0) )
|
||||
#define RGBVAL8(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
|
||||
#define R16(rgb) ((rgb>>8)&0xf8)
|
||||
#define G16(rgb) ((rgb>>3)&0xfc)
|
||||
#define B16(rgb) ((rgb<<3)&0xf8)
|
||||
|
||||
#define PAL_COLOR_MASK 0xff
|
||||
|
||||
#ifdef LOHRES
|
||||
#define TFT_WIDTH 240
|
||||
#define TFT_REALWIDTH 240
|
||||
#else
|
||||
#define TFT_WIDTH 320
|
||||
#define TFT_REALWIDTH 320
|
||||
#endif
|
||||
#define TFT_HEIGHT 192
|
||||
#define TFT_REALHEIGHT 240
|
||||
|
||||
//#define WIDTH 272
|
||||
//#define HEIGHT 228
|
||||
|
||||
#define LINES_PER_BLOCK 64
|
||||
#define NR_OF_BLOCK 4
|
||||
#define SCREEN_DMA_NUM_SETTINGS NR_OF_BLOCK
|
||||
|
||||
|
||||
#ifdef ILI9341
|
||||
|
||||
#define ILI9341_NOP 0x00
|
||||
#define ILI9341_SWRESET 0x01
|
||||
#define ILI9341_RDDID 0x04
|
||||
#define ILI9341_RDDST 0x09
|
||||
|
||||
#define ILI9341_SLPIN 0x10
|
||||
#define ILI9341_SLPOUT 0x11
|
||||
#define ILI9341_PTLON 0x12
|
||||
#define ILI9341_NORON 0x13
|
||||
|
||||
#define ILI9341_RDMODE 0x0A
|
||||
#define ILI9341_RDMADCTL 0x0B
|
||||
#define ILI9341_RDPIXFMT 0x0C
|
||||
#define ILI9341_RDIMGFMT 0x0D
|
||||
#define ILI9341_RDSELFDIAG 0x0F
|
||||
|
||||
#define ILI9341_INVOFF 0x20
|
||||
#define ILI9341_INVON 0x21
|
||||
#define ILI9341_GAMMASET 0x26
|
||||
#define ILI9341_DISPOFF 0x28
|
||||
#define ILI9341_DISPON 0x29
|
||||
|
||||
#define ILI9341_CASET 0x2A
|
||||
#define ILI9341_PASET 0x2B
|
||||
#define ILI9341_RAMWR 0x2C
|
||||
#define ILI9341_RAMRD 0x2E
|
||||
|
||||
#define ILI9341_PTLAR 0x30
|
||||
#define ILI9341_MADCTL 0x36
|
||||
#define ILI9341_VSCRSADD 0x37
|
||||
#define ILI9341_PIXFMT 0x3A
|
||||
|
||||
#define ILI9341_FRMCTR1 0xB1
|
||||
#define ILI9341_FRMCTR2 0xB2
|
||||
#define ILI9341_FRMCTR3 0xB3
|
||||
#define ILI9341_INVCTR 0xB4
|
||||
#define ILI9341_DFUNCTR 0xB6
|
||||
|
||||
#define ILI9341_PWCTR1 0xC0
|
||||
#define ILI9341_PWCTR2 0xC1
|
||||
#define ILI9341_PWCTR3 0xC2
|
||||
#define ILI9341_PWCTR4 0xC3
|
||||
#define ILI9341_PWCTR5 0xC4
|
||||
#define ILI9341_VMCTR1 0xC5
|
||||
#define ILI9341_VMCTR2 0xC7
|
||||
|
||||
#define ILI9341_RDID1 0xDA
|
||||
#define ILI9341_RDID2 0xDB
|
||||
#define ILI9341_RDID3 0xDC
|
||||
#define ILI9341_RDID4 0xDD
|
||||
|
||||
#define ILI9341_GMCTRP1 0xE0
|
||||
#define ILI9341_GMCTRN1 0xE1
|
||||
|
||||
#define ILI9341_MADCTL_MY 0x80
|
||||
#define ILI9341_MADCTL_MX 0x40
|
||||
#define ILI9341_MADCTL_MV 0x20
|
||||
#define ILI9341_MADCTL_ML 0x10
|
||||
#define ILI9341_MADCTL_RGB 0x00
|
||||
#define ILI9341_MADCTL_BGR 0x08
|
||||
#define ILI9341_MADCTL_MH 0x04
|
||||
|
||||
#define TFT_CASET ILI9341_CASET
|
||||
#define TFT_PASET ILI9341_PASET
|
||||
#define TFT_RAMWR ILI9341_RAMWR
|
||||
#define TFT_MADCTL ILI9341_MADCTL
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ST7789
|
||||
|
||||
#define ST7735_NOP 0x00
|
||||
#define ST7735_SWRESET 0x01
|
||||
#define ST7735_RDDID 0x04
|
||||
#define ST7735_RDDST 0x09
|
||||
|
||||
#define ST7735_SLPIN 0x10
|
||||
#define ST7735_SLPOUT 0x11
|
||||
#define ST7735_PTLON 0x12
|
||||
#define ST7735_NORON 0x13
|
||||
|
||||
#define ST7735_INVOFF 0x20
|
||||
#define ST7735_INVON 0x21
|
||||
#define ST7735_DISPOFF 0x28
|
||||
#define ST7735_DISPON 0x29
|
||||
#define ST7735_CASET 0x2A
|
||||
#define ST7735_RASET 0x2B
|
||||
#define ST7735_RAMWR 0x2C
|
||||
#define ST7735_RAMRD 0x2E
|
||||
|
||||
#define ST7735_PTLAR 0x30
|
||||
#define ST7735_COLMOD 0x3A
|
||||
#define ST7735_MADCTL 0x36
|
||||
|
||||
#define ST7735_FRMCTR1 0xB1
|
||||
#define ST7735_FRMCTR2 0xB2
|
||||
#define ST7735_FRMCTR3 0xB3
|
||||
#define ST7735_INVCTR 0xB4
|
||||
#define ST7735_DISSET5 0xB6
|
||||
|
||||
#define ST7735_PWCTR1 0xC0
|
||||
#define ST7735_PWCTR2 0xC1
|
||||
#define ST7735_PWCTR3 0xC2
|
||||
#define ST7735_PWCTR4 0xC3
|
||||
#define ST7735_PWCTR5 0xC4
|
||||
#define ST7735_VMCTR1 0xC5
|
||||
|
||||
#define ST7735_RDID1 0xDA
|
||||
#define ST7735_RDID2 0xDB
|
||||
#define ST7735_RDID3 0xDC
|
||||
#define ST7735_RDID4 0xDD
|
||||
|
||||
#define ST7735_PWCTR6 0xFC
|
||||
|
||||
#define ST7735_GMCTRP1 0xE0
|
||||
#define ST7735_GMCTRN1 0xE1
|
||||
|
||||
#define ST77XX_MADCTL_MY 0x80
|
||||
#define ST77XX_MADCTL_MX 0x40
|
||||
#define ST77XX_MADCTL_MV 0x20
|
||||
#define ST77XX_MADCTL_ML 0x10
|
||||
#define ST77XX_MADCTL_RGB 0x00
|
||||
#define ST77XX_MADCTL_BGR 0x08
|
||||
#define ST77XX_MADCTL_MH 0x04
|
||||
|
||||
#define TFT_CASET ST7735_CASET
|
||||
#define TFT_PASET ST7735_RASET
|
||||
#define TFT_RAMWR ST7735_RAMWR
|
||||
#define TFT_MADCTL ST7735_MADCTL
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
class TFT_T_DMA
|
||||
{
|
||||
public:
|
||||
TFT_T_DMA(uint8_t _CS, uint8_t _DC, uint8_t _RST = 255, uint8_t _MOSI=11, uint8_t _SCLK=13, uint8_t _MISO=12, uint8_t touch_cs=38, uint8_t touch_irq=37);
|
||||
|
||||
void setArea(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2);
|
||||
void begin(void);
|
||||
void flipscreen(bool flip);
|
||||
boolean isflipped(void);
|
||||
void startDMA(void);
|
||||
void stopDMA();
|
||||
int get_frame_buffer_size(int *width, int *height);
|
||||
|
||||
// Touch screen functions
|
||||
#define TOUCH_ENABLED() ((_touch_cs != 255) && (_touch_irq != 255))
|
||||
bool isTouching(void) { return ((!TOUCH_ENABLED())?false:(digitalRead(_touch_irq) == LOW)); }
|
||||
void readRaw(uint16_t * oX, uint16_t * oY, uint16_t * oZ);
|
||||
void readCal(uint16_t * oX, uint16_t * oY, uint16_t * oZ);
|
||||
void callibrateTouch(uint16_t xMin,uint16_t yMin,uint16_t xMax,uint16_t yMax);
|
||||
|
||||
// NoDMA functions
|
||||
void writeScreenNoDma(const uint16_t *pcolors);
|
||||
void fillScreenNoDma(uint16_t color);
|
||||
void drawTextNoDma(int16_t x, int16_t y, const char * text, uint16_t fgcolor, uint16_t bgcolor, bool doublesize);
|
||||
void drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap);
|
||||
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh);
|
||||
|
||||
// DMA functions
|
||||
uint16_t * getLineBuffer(int j);
|
||||
void writeScreen(int width, int height, int stride, uint8_t *buffer, uint16_t *palette16);
|
||||
void writeLine(int width, int height, int stride, uint8_t *buffer, uint16_t *palette16);
|
||||
void writeLine(int width, int height, int y, uint16_t *buf);
|
||||
void fillScreen(uint16_t color);
|
||||
void drawText(int16_t x, int16_t y, const char * text, uint16_t fgcolor, uint16_t bgcolor, bool doublesize);
|
||||
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void drawSprite(int16_t x, int16_t y, const uint16_t *bitmap);
|
||||
void drawSprite(int16_t x, int16_t y, const uint16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh);
|
||||
|
||||
protected:
|
||||
uint8_t _rst, _cs, _dc;
|
||||
uint8_t _miso, _mosi, _sclk;
|
||||
uint8_t _touch_irq=255, _touch_cs=255;
|
||||
bool flipped=false;
|
||||
|
||||
void wait(void);
|
||||
void enableTouchIrq();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
13
MCUME_teensy41/teensyspeccy/tft_t_dma_config.h
Normal file
13
MCUME_teensy41/teensyspeccy/tft_t_dma_config.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#include "platform_config.h"
|
||||
|
||||
//#define ST7789 1
|
||||
//#define ILI9341 1
|
||||
|
||||
#define TFT_LINEARINT 1
|
||||
#define LINEARINT_HACK 1
|
||||
|
||||
//#define FLIP_SCREEN 1
|
||||
//#define TFT_DEBUG 1
|
||||
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
//#define TFT_STATICFB 1
|
||||
#endif
|
||||
53
MCUME_teensy41/teensyspeccy/vga_t_dma.h
Normal file
53
MCUME_teensy41/teensyspeccy/vga_t_dma.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Wrapping class to extend VGA_T4 to TFT_T_DMA
|
||||
*/
|
||||
|
||||
#ifndef _VGA_T_DMAH_
|
||||
#define _VGA_T_DMAH_
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <VGA_t4.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define RGBVAL16(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
|
||||
#define RGBVAL8(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
|
||||
|
||||
|
||||
|
||||
|
||||
#define TFT_WIDTH 320
|
||||
#define TFT_REALWIDTH 320
|
||||
|
||||
#define TFT_HEIGHT 240
|
||||
#define TFT_REALHEIGHT 240
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
class TFT_T_DMA: public VGA_T4
|
||||
{
|
||||
public:
|
||||
// Fake touch screen functions
|
||||
bool isTouching(void) { return false; }
|
||||
void readRaw(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { }
|
||||
void readCal(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { };
|
||||
void callibrateTouch(uint16_t xMin,uint16_t yMin,uint16_t xMax,uint16_t yMax) { }
|
||||
|
||||
// fake DMA functions
|
||||
void startDMA(void) { };
|
||||
void stopDMA(void) { };
|
||||
|
||||
// fake no DMA functions
|
||||
void writeScreenNoDma(const vga_pixel *pcolors) { writeScreen(pcolors); }
|
||||
void fillScreenNoDma(vga_pixel color) { clear(color); }
|
||||
void drawTextNoDma(int16_t x, int16_t y, const char * text, vga_pixel fgcolor, vga_pixel bgcolor, bool doublesize) { drawText(x,y,text,fgcolor,bgcolor,doublesize); }
|
||||
void drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, vga_pixel color) { drawRect(x, y, w, h, color); }
|
||||
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap) { drawSprite(x, y, bitmap); }
|
||||
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); }
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
347
MCUME_teensy41/teensyspeccy/zx_filetyp_z80.c
Normal file
347
MCUME_teensy41/teensyspeccy/zx_filetyp_z80.c
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
//--------------------------------------------------------------
|
||||
// File derived from:
|
||||
// Datum : 27.01.2014
|
||||
// Version : 1.0
|
||||
// Autor : UB
|
||||
// EMail : mc-4u(@)t-online.de
|
||||
// Web : www.mikrocontroller-4u.de
|
||||
//--------------------------------------------------------------
|
||||
#include "zx_filetyp_z80.h"
|
||||
#include "emuapi.h"
|
||||
|
||||
//-------------------------------------------------------------
|
||||
extern uint8_t out_ram;
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// interne Funktionen
|
||||
//--------------------------------------------------------------
|
||||
const uint8_t* p_decompFlashBlock(const uint8_t *block_adr);
|
||||
|
||||
|
||||
void ZX_ReadFromFlash_SNA(Z80 *regs, const char * filename)
|
||||
{
|
||||
uint8_t snafile[27];
|
||||
int f = emu_FileOpen(filename, "r+b");
|
||||
if (f) {
|
||||
if (emu_FileRead(&snafile[0], sizeof(snafile) ,f) == sizeof(snafile)) {
|
||||
// Load Z80 registers from SNA
|
||||
regs->I = snafile[ 0];
|
||||
regs->HL1.B.l = snafile[ 1];
|
||||
regs->HL1.B.h = snafile[ 2];
|
||||
regs->DE1.B.l = snafile[ 3];
|
||||
regs->DE1.B.h = snafile[ 4];
|
||||
regs->BC1.B.l = snafile[ 5];
|
||||
regs->BC1.B.h = snafile[ 6];
|
||||
regs->AF1.B.l = snafile[ 7];
|
||||
regs->AF1.B.h = snafile[ 8];
|
||||
regs->HL.B.l = snafile[ 9];
|
||||
regs->HL.B.h = snafile[10];
|
||||
regs->DE.B.l = snafile[11];
|
||||
regs->DE.B.h = snafile[12];
|
||||
regs->BC.B.l = snafile[13];
|
||||
regs->BC.B.h = snafile[14];
|
||||
regs->IY.B.l = snafile[15];
|
||||
regs->IY.B.h = snafile[16];
|
||||
regs->IX.B.l = snafile[17];
|
||||
regs->IX.B.h = snafile[18];
|
||||
//#define IFF_1 0x01 /* IFF1 flip-flop */
|
||||
//#define IFF_IM1 0x02 /* 1: IM1 mode */
|
||||
//#define IFF_IM2 0x04 /* 1: IM2 mode */
|
||||
//#define IFF_2 0x08 /* IFF2 flip-flop */
|
||||
//#define IFF_EI 0x20 /* 1: EI pending */
|
||||
//#define IFF_HALT 0x80 /* 1: CPU HALTed */
|
||||
regs->R = snafile[20]; //R.W
|
||||
regs->AF.B.l = snafile[21];
|
||||
regs->AF.B.h = snafile[22];
|
||||
regs->SP.B.l =snafile[23];
|
||||
regs->SP.B.h =snafile[24];
|
||||
regs->IFF = 0;
|
||||
regs->IFF |= (((snafile[19]&0x04) >>2)?IFF_1:0); //regs->IFF1 = regs->IFF2 = ...
|
||||
regs->IFF |= (((snafile[19]&0x04) >>2)?IFF_2:0);
|
||||
regs->IFF |= (snafile[25]<< 1); // regs->IM = snafile[25];
|
||||
//regs->BorderColor = snafile[26];
|
||||
|
||||
|
||||
|
||||
// load RAM from SNA
|
||||
int direc;
|
||||
uint8_t b;
|
||||
for (direc=0;direc!=0xbfff;direc++)
|
||||
{
|
||||
emu_FileRead(&b, 1,f);
|
||||
WrZ80(direc+0x4000, b);
|
||||
}
|
||||
emu_FileClose(f);
|
||||
// SP to PC for SNA run
|
||||
regs->PC.B.l = RdZ80(regs->SP.W);
|
||||
regs->SP.W++;
|
||||
regs->PC.B.h = RdZ80(regs->SP.W);
|
||||
regs->SP.W++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Unpack data from a file ( type = * .Z80 ) from flash
|
||||
// And copy them to the memory of the ZX - Spectrum
|
||||
//
|
||||
// Data = pointer to the start of data
|
||||
// Length = number of bytes
|
||||
//--------------------------------------------------------------
|
||||
void ZX_ReadFromFlash_Z80(Z80 *R, const uint8_t *data, uint16_t length)
|
||||
{
|
||||
const uint8_t *ptr;
|
||||
const uint8_t *akt_block,*next_block;
|
||||
uint8_t value1,value2;
|
||||
uint8_t flag_version=0;
|
||||
uint8_t flag_compressed=0;
|
||||
uint16_t header_len;
|
||||
uint16_t cur_addr;
|
||||
|
||||
if(length==0) return;
|
||||
if(length>0xC020) return;
|
||||
|
||||
//----------------------------------
|
||||
// parsing header
|
||||
// Byte : [0...29]
|
||||
//----------------------------------
|
||||
|
||||
// Set pointer to data beginning
|
||||
ptr=data;
|
||||
|
||||
R->AF.B.h=*(ptr++); // A [0]
|
||||
R->AF.B.l=*(ptr++); // F [1]
|
||||
R->BC.B.l=*(ptr++); // C [2]
|
||||
R->BC.B.h=*(ptr++); // B [3]
|
||||
R->HL.B.l=*(ptr++); // L [4]
|
||||
R->HL.B.h=*(ptr++); // H [5]
|
||||
|
||||
// PC [6+7]
|
||||
value1=*(ptr++);
|
||||
value2=*(ptr++);
|
||||
R->PC.W=(value2<<8)|value1;
|
||||
if(R->PC.W==0x0000) {
|
||||
flag_version=1;
|
||||
}
|
||||
else {
|
||||
flag_version=0;
|
||||
}
|
||||
|
||||
// SP [8+9]
|
||||
value1=*(ptr++);
|
||||
value2=*(ptr++);
|
||||
R->SP.W=(value2<<8)|value1;
|
||||
|
||||
R->I=*(ptr++); // I [10]
|
||||
R->R=*(ptr++); // R [11]
|
||||
|
||||
// Comressed-Flag & Border [12]
|
||||
value1=*(ptr++);
|
||||
value2=((value1&0x0E)>>1);
|
||||
OutZ80(0xFE, value2); // BorderColor
|
||||
if((value1&0x20)!=0) {
|
||||
flag_compressed=1;
|
||||
} else {
|
||||
flag_compressed=0;
|
||||
}
|
||||
|
||||
R->DE.B.l=*(ptr++); // E [13]
|
||||
R->DE.B.h=*(ptr++); // D [14]
|
||||
R->BC1.B.l=*(ptr++); // C1 [15]
|
||||
R->BC1.B.h=*(ptr++); // B1 [16]
|
||||
R->DE1.B.l=*(ptr++); // E1 [17]
|
||||
R->DE1.B.h=*(ptr++); // D1 [18]
|
||||
R->HL1.B.l=*(ptr++); // L1 [19]
|
||||
R->HL1.B.h=*(ptr++); // H1 [20]
|
||||
R->AF1.B.h=*(ptr++); // A1 [21]
|
||||
R->AF1.B.l=*(ptr++); // F1 [22]
|
||||
R->IY.B.l=*(ptr++); // Y [23]
|
||||
R->IY.B.h=*(ptr++); // I [24]
|
||||
R->IX.B.l=*(ptr++); // X [25]
|
||||
R->IX.B.h=*(ptr++); // I [26]
|
||||
|
||||
// Interrupt-Flag [27]
|
||||
value1=*(ptr++);
|
||||
if(value1!=0) {
|
||||
// EI
|
||||
R->IFF|=IFF_2|IFF_EI;
|
||||
}
|
||||
else {
|
||||
// DI
|
||||
R->IFF&=~(IFF_1|IFF_2|IFF_EI);
|
||||
}
|
||||
value1=*(ptr++); // nc [28]
|
||||
// Interrupt-Mode [29]
|
||||
value1=*(ptr++);
|
||||
if((value1&0x01)!=0) {
|
||||
R->IFF|=IFF_IM1;
|
||||
}
|
||||
else {
|
||||
R->IFF&=~IFF_IM1;
|
||||
}
|
||||
if((value1&0x02)!=0) {
|
||||
R->IFF|=IFF_IM2;
|
||||
}
|
||||
else {
|
||||
R->IFF&=~IFF_IM2;
|
||||
}
|
||||
|
||||
// restliche Register
|
||||
R->ICount = R->IPeriod;
|
||||
R->IRequest = INT_NONE;
|
||||
R->IBackup = 0;
|
||||
|
||||
//----------------------------------
|
||||
// save the data in RAM
|
||||
// Byte : [30...n]
|
||||
//----------------------------------
|
||||
|
||||
cur_addr=0x4000; // RAM start
|
||||
|
||||
|
||||
if(flag_version==0) {
|
||||
//-----------------------
|
||||
// old Version
|
||||
//-----------------------
|
||||
if(flag_compressed==1) {
|
||||
//-----------------------
|
||||
// compressed
|
||||
//-----------------------
|
||||
while(ptr<(data+length)) {
|
||||
value1=*(ptr++);
|
||||
if(value1!=0xED) {
|
||||
WrZ80(cur_addr++, value1);
|
||||
}
|
||||
else {
|
||||
value2=*(ptr++);
|
||||
if(value2!=0xED) {
|
||||
WrZ80(cur_addr++, value1);
|
||||
WrZ80(cur_addr++, value2);
|
||||
}
|
||||
else {
|
||||
value1=*(ptr++);
|
||||
value2=*(ptr++);
|
||||
while(value1--) {
|
||||
WrZ80(cur_addr++, value2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//-----------------------
|
||||
// raw (uncompressed)
|
||||
//-----------------------
|
||||
while(ptr<(data+length)) {
|
||||
value1=*(ptr++);
|
||||
WrZ80(cur_addr++, value1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//-----------------------
|
||||
// new Version
|
||||
//-----------------------
|
||||
// Header Laenge [30+31]
|
||||
value1=*(ptr++);
|
||||
value2=*(ptr++);
|
||||
header_len=(value2<<8)|value1;
|
||||
akt_block=(uint8_t*)(ptr+header_len);
|
||||
// PC [32+33]
|
||||
value1=*(ptr++);
|
||||
value2=*(ptr++);
|
||||
R->PC.W=(value2<<8)|value1;
|
||||
|
||||
//------------------------
|
||||
// 1st block parsing
|
||||
//------------------------
|
||||
next_block=p_decompFlashBlock(akt_block);
|
||||
//------------------------
|
||||
// all other parsing
|
||||
//------------------------
|
||||
while(next_block<data+length) {
|
||||
akt_block=next_block;
|
||||
next_block=p_decompFlashBlock(akt_block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Internal function
|
||||
// Unpack and store a block of data
|
||||
// ( From flash ) the new version
|
||||
//--------------------------------------------------------------
|
||||
const uint8_t* p_decompFlashBlock(const uint8_t *block_adr)
|
||||
{
|
||||
const uint8_t *ptr;
|
||||
const uint8_t *next_block;
|
||||
uint8_t value1,value2;
|
||||
uint16_t block_len;
|
||||
uint8_t flag_compressed=0;
|
||||
uint8_t flag_page=0;
|
||||
uint16_t cur_addr=0;
|
||||
|
||||
// pointer auf Blockanfang setzen
|
||||
ptr=block_adr;
|
||||
|
||||
// Laenge vom Block
|
||||
value1=*(ptr++);
|
||||
value2=*(ptr++);
|
||||
block_len=(value2<<8)|value1;
|
||||
if(block_len==0xFFFF) {
|
||||
block_len=0x4000;
|
||||
flag_compressed=0;
|
||||
}
|
||||
else {
|
||||
flag_compressed=1;
|
||||
}
|
||||
|
||||
// Page vom Block
|
||||
flag_page=*(ptr++);
|
||||
|
||||
// next Block ausrechnen
|
||||
next_block=(uint8_t*)(ptr+block_len);
|
||||
|
||||
// Startadresse setzen
|
||||
if(flag_page==4) cur_addr=0x8000;
|
||||
if(flag_page==5) cur_addr=0xC000;
|
||||
if(flag_page==8) cur_addr=0x4000;
|
||||
|
||||
if(flag_compressed==1) {
|
||||
//-----------------------
|
||||
// komprimiert
|
||||
//-----------------------
|
||||
while(ptr<(block_adr+3+block_len)) {
|
||||
value1=*(ptr++);
|
||||
if(value1!=0xED) {
|
||||
WrZ80(cur_addr++, value1);
|
||||
}
|
||||
else {
|
||||
value2=*(ptr++);
|
||||
if(value2!=0xED) {
|
||||
WrZ80(cur_addr++, value1);
|
||||
WrZ80(cur_addr++, value2);
|
||||
}
|
||||
else {
|
||||
value1=*(ptr++);
|
||||
value2=*(ptr++);
|
||||
while(value1--) {
|
||||
WrZ80(cur_addr++, value2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//-----------------------
|
||||
// nicht komprimiert
|
||||
//-----------------------
|
||||
while(ptr<(block_adr+3+block_len)) {
|
||||
value1=*(ptr++);
|
||||
WrZ80(cur_addr++, value1);
|
||||
}
|
||||
}
|
||||
|
||||
return(next_block);
|
||||
}
|
||||
6
MCUME_teensy41/teensyspeccy/zx_filetyp_z80.h
Normal file
6
MCUME_teensy41/teensyspeccy/zx_filetyp_z80.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
#include "Z80.h"
|
||||
|
||||
void ZX_ReadFromFlash_SNA(Z80 *R, const char * filename);
|
||||
void ZX_ReadFromFlash_Z80(Z80 *R, const uint8_t *data, uint16_t length);
|
||||
|
||||
Loading…
Reference in a new issue