add coloco and oddysey emu to T-COMPUTER

pull/16/head
jean-marcharvengt 2022-03-07 21:34:33 +01:00
rodzic d35010f31d
commit 51e82c6482
69 zmienionych plików z 57017 dodań i 11046 usunięć

Wyświetl plik

@ -33,8 +33,8 @@ typedef struct
// global variables
EXTMEM static unsigned char MemPool[8*1024*1024];
unsigned char * memory=&MemPool[0];
//EXTMEM static unsigned char MemPool[8*1024*1024];
unsigned char * memory=NULL; //&MemPool[0];
int tv_mode = TV_PAL;
UBYTE INPUT_key_consol;

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1,378 @@
/** 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-1998 **/
/** 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=RdZ80(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=RdZ80(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=RdZ80(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=RdZ80(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=RdZ80(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=RdZ80(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=RdZ80(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=RdZ80(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;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) { 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: OutZ80(RdZ80(R->PC.W++),R->AF.B.h);break;
case INA: R->AF.B.h=InZ80(RdZ80(R->PC.W++));break;
case HALT: R->PC.W--;R->IFF|=0x80;R->ICount=0;break;
case DI:
R->IFF&=0xFE;
break;
case EI:
R->IFF|=0x01;
if(R->IRequest!=INT_NONE)
{
R->IFF|=0x20;
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=RdZ80(R->PC.W++);break;
case LD_C_BYTE: R->BC.B.l=RdZ80(R->PC.W++);break;
case LD_D_BYTE: R->DE.B.h=RdZ80(R->PC.W++);break;
case LD_E_BYTE: R->DE.B.l=RdZ80(R->PC.W++);break;
case LD_H_BYTE: R->HL.B.h=RdZ80(R->PC.W++);break;
case LD_L_BYTE: R->HL.B.l=RdZ80(R->PC.W++);break;
case LD_A_BYTE: R->AF.B.h=RdZ80(R->PC.W++);break;
case LD_xHL_BYTE: WrZ80(R->HL.W,RdZ80(R->PC.W++));break;
case LD_xWORD_HL:
J.B.l=RdZ80(R->PC.W++);
J.B.h=RdZ80(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=RdZ80(R->PC.W++);
J.B.h=RdZ80(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=RdZ80(R->PC.W++);
J.B.h=RdZ80(R->PC.W++);
R->AF.B.h=RdZ80(J.W);
break;
case LD_xWORD_A:
J.B.l=RdZ80(R->PC.W++);
J.B.h=RdZ80(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,RdZ80(R->PC.W-1),R->PC.W-1
);
break;

Wyświetl plik

@ -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-1998 **/
/** 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;

Wyświetl plik

@ -0,0 +1,282 @@
/** 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-1998 **/
/** 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=RdZ80(R->PC.W++);
J.B.h=RdZ80(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=RdZ80(R->PC.W++);
J.B.h=RdZ80(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=RdZ80(R->PC.W++);
J.B.h=RdZ80(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=RdZ80(R->PC.W++);
J.B.h=RdZ80(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=RdZ80(R->PC.W++);
J.B.h=RdZ80(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=RdZ80(R->PC.W++);
J.B.h=RdZ80(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=RdZ80(R->PC.W++);
J.B.h=RdZ80(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=RdZ80(R->PC.W++);
J.B.h=RdZ80(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&1? 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&1? 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&=0xF9;break;
case IM_1: R->IFF=(R->IFF&0xF9)|2;break;
case IM_2: R->IFF=(R->IFF&0xF9)|4;break;
case RETI: M_RET;break;
case RETN: if(R->IFF&0x40) R->IFF|=0x01; else R->IFF&=0xFE;
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.B.l,R->BC.B.h);break;
case OUT_xC_C: OutZ80(R->BC.B.l,R->BC.B.l);break;
case OUT_xC_D: OutZ80(R->BC.B.l,R->DE.B.h);break;
case OUT_xC_E: OutZ80(R->BC.B.l,R->DE.B.l);break;
case OUT_xC_H: OutZ80(R->BC.B.l,R->HL.B.h);break;
case OUT_xC_L: OutZ80(R->BC.B.l,R->HL.B.l);break;
case OUT_xC_A: OutZ80(R->BC.B.l,R->AF.B.h);break;
case INI:
WrZ80(R->HL.W++,InZ80(R->BC.B.l));
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.B.l));
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.B.l));
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.B.l));
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:
OutZ80(R->BC.B.l,RdZ80(R->HL.W++));
R->BC.B.h--;
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);
break;
case OTIR:
do
{
OutZ80(R->BC.B.l,RdZ80(R->HL.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 OUTD:
OutZ80(R->BC.B.l,RdZ80(R->HL.W--));
R->BC.B.h--;
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG);
break;
case OTDR:
do
{
OutZ80(R->BC.B.l,RdZ80(R->HL.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 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;

Wyświetl plik

@ -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-1998 **/
/** 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;

Wyświetl plik

@ -0,0 +1,388 @@
/** 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-1998 **/
/** 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 { M_JR; } break;
case JR_NC: if(R->AF.B.l&C_FLAG) R->PC.W++; else { M_JR; } break;
case JR_Z: if(R->AF.B.l&Z_FLAG) { M_JR; } else R->PC.W++; break;
case JR_C: if(R->AF.B.l&C_FLAG) { 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)) { M_RET; } break;
case RET_NC: if(!(R->AF.B.l&C_FLAG)) { M_RET; } break;
case RET_PO: if(!(R->AF.B.l&P_FLAG)) { M_RET; } break;
case RET_P: if(!(R->AF.B.l&S_FLAG)) { M_RET; } break;
case RET_Z: if(R->AF.B.l&Z_FLAG) { M_RET; } break;
case RET_C: if(R->AF.B.l&C_FLAG) { M_RET; } break;
case RET_PE: if(R->AF.B.l&P_FLAG) { M_RET; } break;
case RET_M: if(R->AF.B.l&S_FLAG) { M_RET; } break;
case CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_CALL; } break;
case CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_CALL; } break;
case CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_CALL; } break;
case CALL_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_CALL; } break;
case CALL_Z: if(R->AF.B.l&Z_FLAG) { M_CALL; } else R->PC.W+=2; break;
case CALL_C: if(R->AF.B.l&C_FLAG) { M_CALL; } else R->PC.W+=2; break;
case CALL_PE: if(R->AF.B.l&P_FLAG) { M_CALL; } else R->PC.W+=2; break;
case CALL_M: if(R->AF.B.l&S_FLAG) { 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)RdZ80(R->PC.W++));
M_ADD(I);break;
case ADD_BYTE: I=RdZ80(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)RdZ80(R->PC.W++));
M_SUB(I);break;
case SUB_BYTE: I=RdZ80(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)RdZ80(R->PC.W++));
M_AND(I);break;
case AND_BYTE: I=RdZ80(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)RdZ80(R->PC.W++));
M_OR(I);break;
case OR_BYTE: I=RdZ80(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)RdZ80(R->PC.W++));
M_ADC(I);break;
case ADC_BYTE: I=RdZ80(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)RdZ80(R->PC.W++));
M_SBC(I);break;
case SBC_BYTE: I=RdZ80(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)RdZ80(R->PC.W++));
M_XOR(I);break;
case XOR_BYTE: I=RdZ80(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)RdZ80(R->PC.W++));
M_CP(I);break;
case CP_BYTE: I=RdZ80(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;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)RdZ80(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)RdZ80(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) { 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: OutZ80(RdZ80(R->PC.W++),R->AF.B.h);break;
case INA: R->AF.B.h=InZ80(RdZ80(R->PC.W++));break;
case DI:
R->IFF&=0xFE;
break;
case EI:
R->IFF|=0x01;
if(R->IRequest!=INT_NONE)
{
R->IFF|=0x20;
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)RdZ80(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)RdZ80(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)RdZ80(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)RdZ80(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)RdZ80(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)RdZ80(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)RdZ80(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)RdZ80(R->PC.W++));break;
case LD_C_xHL: R->BC.B.l=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
case LD_D_xHL: R->DE.B.h=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
case LD_E_xHL: R->DE.B.l=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
case LD_H_xHL: R->HL.B.h=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
case LD_L_xHL: R->HL.B.l=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
case LD_A_xHL: R->AF.B.h=RdZ80(R->XX.W+(offset)RdZ80(R->PC.W++));break;
case LD_B_BYTE: R->BC.B.h=RdZ80(R->PC.W++);break;
case LD_C_BYTE: R->BC.B.l=RdZ80(R->PC.W++);break;
case LD_D_BYTE: R->DE.B.h=RdZ80(R->PC.W++);break;
case LD_E_BYTE: R->DE.B.l=RdZ80(R->PC.W++);break;
case LD_H_BYTE: R->XX.B.h=RdZ80(R->PC.W++);break;
case LD_L_BYTE: R->XX.B.l=RdZ80(R->PC.W++);break;
case LD_A_BYTE: R->AF.B.h=RdZ80(R->PC.W++);break;
case LD_xHL_BYTE: J.W=R->XX.W+(offset)RdZ80(R->PC.W++);
WrZ80(J.W,RdZ80(R->PC.W++));break;
case LD_xWORD_HL:
J.B.l=RdZ80(R->PC.W++);
J.B.h=RdZ80(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=RdZ80(R->PC.W++);
J.B.h=RdZ80(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=RdZ80(R->PC.W++);
J.B.h=RdZ80(R->PC.W++);
R->AF.B.h=RdZ80(J.W);
break;
case LD_xWORD_A:
J.B.l=RdZ80(R->PC.W++);
J.B.h=RdZ80(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;

Wyświetl plik

@ -0,0 +1,969 @@
#include "options.h"
#include "Z80.h" /* Z80 CPU emulation */
#include "SN76489.h" /* SN76489 PSG emulation */
#include <stdlib.h>
#include <ctype.h>
#include "emuapi.h"
/**************************************
* Local macros/typedef
**************************************/
#define WIDTH 256
#define HEIGHT 192
#define MAXSCREEN 3 /* Highest screen mode supported */
#define NORAM 0xFF /* Byte to be returned from */
/* non-existing pages and ports */
/***** Following are macros to be used in screen drivers *****/
#define BigSprites (VDP[1]&0x01) /* Zoomed sprites */
#define Sprites16x16 (VDP[1]&0x02) /* 16x16/8x8 sprites */
#define ScreenON (VDP[1]&0x40) /* Show screen */
/***************************************
* Local procedures definition
***************************************/
static void snd_Reset(void);
static void snd_Sound(int C, int F, int V);
static void SetColor(byte N,byte R,byte G,byte B);
static void RefreshSprites(byte Y);
static void RefreshBorder(byte Y);
static void RefreshLine0(byte Y);
static void RefreshLine1(byte Y);
static void RefreshLine2(byte Y);
static void RefreshLine3(byte Y);
static void RefreshScreen(void);
static void VDPOut(byte Reg,byte Value); /* Write value into VDP */
static void CheckSprites(void); /* Collisions/5th spr. */
static void Play(int C,int F,int V); /* Log and play sound */
/***************************************
* Local data
***************************************/
static byte * XBuf=0; // = (byte *)XBuf32;
static byte XPal[16],XPal0;
/*** TMS9918/9928 Palette *******************************************/
struct { byte R,G,B; } Palette[16] =
{
{0x00,0x00,0x00},{0x00,0x00,0x00},{0x20,0xC0,0x20},{0x60,0xE0,0x60},
{0x20,0x20,0xE0},{0x40,0x60,0xE0},{0xA0,0x20,0x20},{0x40,0xC0,0xE0},
{0xE0,0x20,0x20},{0xE0,0x60,0x60},{0xC0,0xC0,0x20},{0xC0,0xC0,0x80},
{0x20,0x80,0x20},{0xC0,0x40,0xA0},{0xA0,0xA0,0xA0},{0xE0,0xE0,0xE0}
};
byte Verbose = 1; /* Debug msgs ON/OFF */
byte UPeriod = 2; /* Interrupts/scr. update */
int VPeriod = 60000; /* Number of cycles per VBlank */
int HPeriod = 215; /* Number of cycles per HBlank */
byte AutoA=0,AutoB=0; /* 1: Autofire for A,B buttons */
byte Adam = 0; /* 1: Emulate Coleco Adam */
#define MEMRELOC -0x4000
#define VRAMSIZE 0x4000
#define RAMSIZE 0xC000
/* Main and Video RAMs */
static byte * VRAM=0; //[VRAMSIZE];
static byte * RAM=0; //RAM[RAMSIZE];
//static byte VRAM[VRAMSIZE];
//static byte RAM[RAMSIZE];
Z80 ccpu; /* Z80 CPU registers and state */
SN76489 PSG; /* SN76489 PSG state */
byte *ChrGen,*ChrTab,*ColTab; /* VDP tables (screens) */
byte *SprGen,*SprTab; /* VDP tables (sprites) */
pair WVAddr,RVAddr; /* Storage for VRAM addresses */
byte VKey; /* VDP address latch key */
byte FGColor,BGColor; /* Colors */
byte ScrMode; /* Current screen mode */
byte CurLine; /* Current scanline */
byte VDP[8],VDPStatus; /* VDP registers */
byte JoyMode; /* Joystick controller mode */
word JoyState[2]; /* Joystick states */
/*** Screen handlers and masks for VDP table address registers ******/
struct
{
void (*Refresh)(byte Y);
byte R2,R3,R4,R5;
} SCR[MAXSCREEN+1] =
{
{ RefreshLine0,0x7F,0x00,0x3F,0x00 }, /* SCREEN 0:TEXT 40x24 */
{ RefreshLine1,0x7F,0xFF,0x3F,0xFF }, /* SCREEN 1:TEXT 32x24 */
{ RefreshLine2,0x7F,0x80,0x3C,0xFF }, /* SCREEN 2:BLOCK 256x192 */
{ RefreshLine3,0x7F,0x00,0x3F,0xFF } /* SCREEN 3:GFX 64x48x16 */
};
/***************************************
* Global data
***************************************/
/***************************************
* Exported procedures
***************************************/
static int ik; // joypad key
static int ihk; // I2C keyboard key
static int iusbhk; // USB keyboard key
static int prevhk; // previous keyboard key
void emu_KeyboardOnDown(int keymodifer, int key) {
int keyCode = -1; //INV_KEY;
if ((key >=0xc0) && (key <=0xdf)) {
keyCode = ((key-0xc0) & 0x1f) + 0x7f;
}
else {
keyCode = key & 0x7f;
}
//Serial.println(keyCode);
if (keyCode != -1) {
iusbhk = keyCode;
}
}
void emu_KeyboardOnUp(int keymodifer, int key) {
iusbhk = 0;
}
void coc_Input(int click) {
ik = emu_GetPad();
ihk = emu_ReadI2CKeyboard();
}
void coc_Init(void)
{
int J;
/* Set up the palette */
for(J=0;J<16;J++)
SetColor(J,Palette[J].R,Palette[J].G,Palette[J].B);
if (VRAM == 0) VRAM = (byte *)emu_Malloc(VRAMSIZE);
if (RAM == 0) RAM = (byte *)emu_Malloc(RAMSIZE);
#if SINGLELINE_RENDERING
if (XBuf == 0) XBuf = (byte *)emu_Malloc(WIDTH);
#else
if (XBuf == 0) XBuf = (byte *)emu_Malloc(WIDTH*HEIGHT);
#endif
}
int coc_Start(char * Cartridge)
{
int *T,I,J;
char *P;
/*** VDP control register states: ***/
static byte VDPInit[8] =
{ 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00 };
/*** STARTUP CODE starts here: ***/
T=(int *)"\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
#ifdef LSB_FIRST
if(*T!=1)
{
emu_printf("********** This machine is high-endian. **********\n");
emu_printf("Take #define LSB_FIRST out and compile ColEm again.\n");
return(0);
}
#else
if(*T==1)
{
emu_printf("********** This machine is low-endian. **********\n");
emu_printf("Insert #define LSB_FIRST and compile ColEm again.\n");
return(0);
}
#endif
/* Calculate IPeriod from VPeriod */
if(UPeriod<1) UPeriod=1;
if(VPeriod/HPeriod<256) VPeriod=256*HPeriod;
ccpu.IPeriod=HPeriod;
ccpu.TrapBadOps=Verbose&0x04;
ccpu.IAutoReset=0;
memset(RAM,NORAM,RAMSIZE);
memset(VRAM,NORAM,VRAMSIZE);
if(Verbose) emu_printf("OK\nLoading ROMs:\nOpening COLECO.ROM...");
P=NULL;
if (emu_LoadFile(ROMSDIR "/" "coleco.rom", (unsigned char *)RAM, 0x2000) != 0x2000)
P="NOT FOUND OR SHORT FILE";
//if(P) { if(Verbose) puts(P);return(0); }
if(Verbose) emu_printf("OK\nOpening ROM");
if(Verbose) emu_printf(Cartridge);
P=NULL;
J= emu_LoadFile(Cartridge, (unsigned char *)RAM+0x8000+MEMRELOC, 0x8000);
if(J<0x1000) P="SHORT FILE";
I=RAM[0x8000+MEMRELOC];J=RAM[0x8001+MEMRELOC];
if( !( ((I==0x55)&&(J==0xAA))||((I==0xAA)&&(J==0x55)) ) )
P="INVALID IMAGE";
//if(P) { if(Verbose) puts(P);return(0); }
if(Verbose) emu_printf("bytes loaded\n");
if(Verbose)
{
emu_printf("Initializing CPU and System Hardware:\n");
//emu_printf(" VBlank = %d cycles\n HBlank = %d cycles\n",VPeriod,HPeriod);
}
#ifdef HAS_SND
snd_Reset();
#endif
#ifdef SOUND_PRESENT
snd_Open(44100/*22050*/, 2, 4096/*16384*/,(void*)snd_Mixer);
#endif
/* Initialize VDP registers */
memcpy(VDP,VDPInit,sizeof(VDP));
/* Initialize internal variables */
VKey=1; /* VDP address latch key */
VDPStatus=0x9F; /* VDP status register */
FGColor=BGColor=0; /* Fore/Background color */
ScrMode=0; /* Current screenmode */
CurLine=0; /* Current scanline */
ChrTab=ColTab=ChrGen=VRAM; /* VDP tables (screen) */
SprTab=SprGen=VRAM; /* VDP tables (sprites) */
JoyMode=0; /* Joystick mode key */
JoyState[0]=JoyState[1]=0xFFFF; /* Joystick states */
Reset76489(&PSG,Play); /* Reset SN76489 PSG */
Sync76489(&PSG,PSG_SYNC); /* Make it synchronous */
ResetZ80(&ccpu); /* Reset Z80 registers */
if(Verbose) emu_printf("RUNNING ROM CODE...\n");
return(1);
}
void coc_Step(void)
{
//emu_printf("s");
RunZ80(&ccpu);
RunZ80(&ccpu);
}
void coc_Stop(void)
{
}
#ifdef HAS_SND
static void snd_Reset(void)
{
emu_sndInit();
}
static void snd_Sound(int C, int F, int V)
{
emu_sndPlaySound(C, V, F);
}
#endif
/** Joysticks ************************************************/
/** Check for keyboard events, parse them, and modify **/
/** joystick controller status **/
/*************************************************************/
void SetColor(byte N,byte R,byte G,byte B)
{
unsigned char val = R;
XPal[N] = N; //(R&0xe0) | ((G>>3) & 0x1c) | ((B>>6) & 0x3); // RGBVAL(R,G,B); //(byte)lld_SetPaletteEntry(-1, R,G,B,0);
emu_SetPaletteEntry(R,G,B,N);
}
void Joysticks(void)
{
int N=0;
word JS[2] = { 0xFFFF,0xFFFF };
int k = ik & 0x7fff;
int hk = ihk;
if (iusbhk) hk = iusbhk;
//if (k & 0x8000) N = 1;
//else N = 0;
if(k)
JS[N]=(JS[N]&0xFFF0)|(k-1);
switch(hk) {
case 'q':
case '1':
hk = 2;
break;
case 'w':
case '2':
hk = 3;
break;
case 'e':
case '3':
hk = 4;
break;
case 'r':
case '4':
hk = 5;
break;
case 't':
case '5':
hk = 6;
break;
case 'y':
case '6':
hk = 7;
break;
case 'u':
case '7':
hk = 8;
break;
case 'i':
case '8':
hk = 9;
break;
case 'o':
case '9':
hk = 10;
case 'p':
case '0':
hk = 1;
break;
default:
hk = 0;
break;
};
if(hk)
JS[N]=(JS[N]&0xFFF0)|(hk-1);
if (k & MASK_JOY2_BTN)
{
JS[N]&=0xBFFF; //Fire 1
}
if (k & MASK_KEY_USER1)
{
JS[N]&=0xFFBF; //Fire 2
}
if (k & MASK_KEY_USER2)
{
JS[0]=(JS[0]&0xFFF0)|(2); //1
}
// JS[0]=(JS[0]&0xFFF0)|(12);
// JS[0]=(JS[0]&0xFFF0)|(13);
if (k & MASK_JOY2_DOWN)
JS[N]&=0xFBFF; //Down
if (k & MASK_JOY2_UP)
JS[N]&=0xFEFF; //Up
if (k & MASK_JOY2_RIGHT)
JS[N]&=0xF7FF; //Right
if (k & MASK_JOY2_LEFT)
JS[N]&=0xFDFF; //Left
JoyState[0]=JS[0];JoyState[1]=JS[1];
}
/** WrZ80() **************************************************/
/** Z80 emulation calls this function to write byte V to **/
/** address A of Z80 address space. **/
/*************************************************************/
void WrZ80(register word A,register byte V)
{
if((A>0x5FFF)&&(A<0x8000))
{
A&=0x03FF;
RAM[0x6000+A+MEMRELOC]=RAM[0x6400+A+MEMRELOC]=RAM[0x6800+A+MEMRELOC]=RAM[0x6C00+A+MEMRELOC]=
RAM[0x7000+A+MEMRELOC]=RAM[0x7400+A+MEMRELOC]=RAM[0x7800+A+MEMRELOC]=RAM[0x7C00+A+MEMRELOC]=V;
}
}
/** RdZ80() **************************************************/
/** Z80 emulation calls this function to read a byte from **/
/** address A of Z80 address space. Now moved to z80.c and **/
/** made inlined to speed things up. **/
/*************************************************************/
byte RdZ80(register word A) {
if ( (A>=0x6000) && (A<0x10000) )
return(RAM[A+MEMRELOC]);
else
return(RAM[A]);
}
/** PatchZ80() ***********************************************/
/** Z80 emulation calls this function when it encounters a **/
/** special patch command (ED FE) provided for user needs. **/
/*************************************************************/
void PatchZ80(Z80 *R) {}
/** InZ80() **************************************************/
/** Z80 emulation calls this function to read a byte from **/
/** a given I/O port. **/
/*************************************************************/
byte InZ80(register word Port)
{
static byte KeyCodes[16] =
{
0x0A,0x0D,0x07,0x0C,0x02,0x03,0x0E,0x05,
0x01,0x0B,0x06,0x09,0x08,0x04,0x0F,0x0F,
};
switch(Port&0xE0)
{
case 0x40: /* Printer Status */
if(Adam&&(Port==0x40)) return(0xFF);
break;
case 0xE0: /* Joysticks Data */
Port=(Port>>1)&0x01;
Port=JoyMode?
(JoyState[Port]>>8):
(JoyState[Port]&0xF0)|KeyCodes[JoyState[Port]&0x0F];
return((Port|0xB0)&0x7F);
case 0xA0: /* VDP Status/Data */
if(Port&0x01) { Port=VDPStatus;VDPStatus&=0x5F;VKey=1; }
else { Port=VRAM[RVAddr.W];RVAddr.W=(RVAddr.W+1)&0x3FFF; }
return(Port);
}
/* No such port */
return(NORAM);
}
/** OutZ80() *************************************************/
/** Z80 emulation calls this function to write a byte to a **/
/** given I/O port. **/
/*************************************************************/
void OutZ80(register word Port,register byte Value)
{
static byte SR,VR; /* Sound and VDP register storage */
switch(Port&0xE0)
{
case 0x80: JoyMode=0;return;
case 0xC0: JoyMode=1;return;
case 0xE0: Write76489(&PSG,Value);return;
case 0x40:
// if(Adam&&(Port==0x40)) fputc(Value,PrnStream);
return;
case 0xA0:
if(Port&0x01)
if(VKey) { VR=Value;VKey--; }
else
{
VKey++;
switch(Value&0xC0)
{
case 0x80: VDPOut(Value&0x07,VR);break;
case 0x40: WVAddr.B.l=VR;WVAddr.B.h=Value&0x3F;break;
case 0x00: RVAddr.B.l=VR;RVAddr.B.h=Value;
}
}
else
if(VKey)
{ VRAM[WVAddr.W]=Value;WVAddr.W=(WVAddr.W+1)&0x3FFF; }
return;
}
}
/** LoopZ80() ************************************************/
/** Z80 emulation calls this function periodically to check **/
/** if the system hardware requires any interrupts. **/
/*************************************************************/
word LoopZ80(Z80 *R, int * ras)
{
static byte UCount=0;
static byte ACount=0;
/* Next scanline */
CurLine=(CurLine+1)%193;
/* Refresh scanline if needed */
if(CurLine<192)
{
if(!UCount) {
(SCR[ScrMode].Refresh)(CurLine);
#if SINGLELINE_RENDERING
emu_DrawLine(XBuf, WIDTH, HEIGHT, CurLine);
#else
#endif
}
R->IPeriod=HPeriod;
return(INT_NONE);
}
/* End of screen reached... */
/* Set IPeriod to the beginning of next screen */
R->IPeriod=VPeriod-HPeriod*192;
/* Check joysticks */
Joysticks();
/* Autofire emulation */
ACount=(ACount+1)&0x07;
if(ACount>3)
{
if(AutoA) { JoyState[0]|=0x0040;JoyState[1]|=0x0040; }
if(AutoB) { JoyState[0]|=0x4000;JoyState[1]|=0x4000; }
}
/* Flush any accumulated sound changes */
Sync76489(&PSG,PSG_FLUSH);
/* Refresh screen if needed */
if(UCount)
UCount--;
else
{
UCount=UPeriod-1;
RefreshScreen();
}
/* Setting VDPStatus flags */
VDPStatus=(VDPStatus&0xDF)|0x80;
/* Checking sprites: */
if(ScrMode) CheckSprites();
/* If exit requested, return INT_QUIT */
// if(ExitNow) return(INT_QUIT);
*ras = 1;
/* Generate VDP interrupt */
return(VKey&&(VDP[1]&0x20)? INT_NMI:INT_NONE);
}
/** VDPOut() *************************************************/
/** Emulator calls this function to write byte V into a VDP **/
/** register R. **/
/*************************************************************/
void VDPOut(register byte R,register byte V)
{
register byte J;
switch(R)
{
case 0: switch(((V&0x0E)>>1)|(VDP[1]&0x18))
{
case 0x10: J=0;break;
case 0x00: J=1;break;
case 0x01: J=2;break;
case 0x08: J=3;break;
default: J=ScrMode;
}
if(J!=ScrMode)
{
ChrTab=VRAM+((long)(VDP[2]&SCR[J].R2)<<10);
ChrGen=VRAM+((long)(VDP[4]&SCR[J].R4)<<11);
ColTab=VRAM+((long)(VDP[3]&SCR[J].R3)<<6);
SprTab=VRAM+((long)(VDP[5]&SCR[J].R5)<<7);
SprGen=VRAM+((long)VDP[6]<<11);
ScrMode=J;
}
break;
case 1: switch(((VDP[0]&0x0E)>>1)|(V&0x18))
{
case 0x10: J=0;break;
case 0x00: J=1;break;
case 0x01: J=2;break;
case 0x08: J=3;break;
default: J=ScrMode;
}
if(J!=ScrMode)
{
ChrTab=VRAM+((long)(VDP[2]&SCR[J].R2)<<10);
ChrGen=VRAM+((long)(VDP[4]&SCR[J].R4)<<11);
ColTab=VRAM+((long)(VDP[3]&SCR[J].R3)<<6);
SprTab=VRAM+((long)(VDP[5]&SCR[J].R5)<<7);
SprGen=VRAM+((long)VDP[6]<<11);
ScrMode=J;
}
break;
case 2: ChrTab=VRAM+((long)(V&SCR[ScrMode].R2)<<10);break;
case 3: ColTab=VRAM+((long)(V&SCR[ScrMode].R3)<<6);break;
case 4: ChrGen=VRAM+((long)(V&SCR[ScrMode].R4)<<11);break;
case 5: SprTab=VRAM+((long)(V&SCR[ScrMode].R5)<<7);break;
case 6: V&=0x3F;SprGen=VRAM+((long)V<<11);break;
case 7: FGColor=V>>4;BGColor=V&0x0F;break;
}
VDP[R]=V;return;
}
/** CheckSprites() *******************************************/
/** This function is periodically called to check for the **/
/** sprite collisions and 5th sprite, and set appropriate **/
/** bits in the VDP status register. **/
/*************************************************************/
void CheckSprites(void)
{
register word LS,LD;
register byte DH,DV,*PS,*PD,*T;
byte I,J,N,*S,*D;
VDPStatus=(VDPStatus&0x9F)|0x1F;
for(N=0,S=SprTab;(N<32)&&(S[0]!=208);N++,S+=4);
if(Sprites16x16)
{
for(J=0,S=SprTab;J<N;J++,S+=4)
if(S[3]&0x0F)
for(I=J+1,D=S+4;I<N;I++,D+=4)
if(D[3]&0x0F)
{
DV=S[0]-D[0];
if((DV<16)||(DV>240))
{
DH=S[1]-D[1];
if((DH<16)||(DH>240))
{
PS=SprGen+((long)(S[2]&0xFC)<<3);
PD=SprGen+((long)(D[2]&0xFC)<<3);
if(DV<16) PD+=DV; else { DV=256-DV;PS+=DV; }
if(DH>240) { DH=256-DH;T=PS;PS=PD;PD=T; }
while(DV<16)
{
LS=((word)*PS<<8)+*(PS+16);
LD=((word)*PD<<8)+*(PD+16);
if(LD&(LS>>DH)) break;
else { DV++;PS++;PD++; }
}
if(DV<16) { VDPStatus|=0x20;return; }
}
}
}
}
else
{
for(J=0,S=SprTab;J<N;J++,S+=4)
if(S[3]&0x0F)
for(I=J+1,D=S+4;I<N;I++,D+=4)
if(D[3]&0x0F)
{
DV=S[0]-D[0];
if((DV<8)||(DV>248))
{
DH=S[1]-D[1];
if((DH<8)||(DH>248))
{
PS=SprGen+((long)S[2]<<3);
PD=SprGen+((long)D[2]<<3);
if(DV<8) PD+=DV; else { DV=256-DV;PS+=DV; }
if(DH>248) { DH=256-DH;T=PS;PS=PD;PD=T; }
while((DV<8)&&!(*PD&(*PS>>DH))) { DV++;PS++;PD++; }
if(DV<8) { VDPStatus|=0x20;return; }
}
}
}
}
}
/** Play() ***************************************************/
/** Log and play sound of given frequency (Hz) and volume **/
/** (0..255) via given channel (0..3). **/
/*************************************************************/
void Play(int C,int F,int V)
{
/* Play actual sound */
#ifdef HAS_SND
snd_Sound(C,F,V);
#endif
}
/** RefreshScreen() ******************************************/
/** Refresh screen. This function is called in the end of **/
/** refresh cycle to show the entire screen. **/
/*************************************************************/
void RefreshScreen(void)
{
#if SINGLELINE_RENDERING
#else
emu_DrawScreen(XBuf, WIDTH, HEIGHT, WIDTH);
#endif
emu_DrawVsync();
}
/** RefreshBorder() ******************************************/
/** This function is called from RefreshLine#() to refresh **/
/** the screen border. **/
/*************************************************************/
void RefreshBorder(register byte Y)
{
// if(!Y)
// memset(XBuf,XPal[BGColor],WIDTH*(HEIGHT-192)/2);
// if(Y==191)
// memset(XBuf+WIDTH*(HEIGHT+192)/2,XPal[BGColor],WIDTH*(HEIGHT-192)/2);
}
/** RefreshSprites() *****************************************/
/** This function is called from RefreshLine#() to refresh **/
/** sprites. **/
/*************************************************************/
void RefreshSprites(register byte Y)
{
register byte C,H;
register byte *P,*PT,*AT;
register int L,K;
register unsigned int M;
H=Sprites16x16? 16:8;
C=0;M=0;L=0;AT=SprTab-4;
do
{
M<<=1;AT+=4;L++; /* Iterating through SprTab */
K=AT[0]; /* K = sprite Y coordinate */
if(K==208) break; /* Iteration terminates if Y=208 */
if(K>256-H) K-=256; /* Y coordinate may be negative */
/* Mark all valid sprites with 1s, break at 4 sprites */
if((Y>K)&&(Y<=K+H)) { M|=1;if(++C==4) break; }
}
while(L<32);
for(;M;M>>=1,AT-=4)
if(M&1)
{
C=AT[3]; /* C = sprite attributes */
L=C&0x80? AT[1]-32:AT[1]; /* Sprite may be shifted left by 32 */
C&=0x0F; /* C = sprite color */
if((L<256)&&(L>-H)&&C)
{
K=AT[0]; /* K = sprite Y coordinate */
if(K>256-H) K-=256; /* Y coordinate may be negative */
#if SINGLELINE_RENDERING
P=XBuf+L;
#else
P=XBuf+WIDTH*(HEIGHT-192)/2+(WIDTH-256)/2+WIDTH*Y+L;
#endif
PT=SprGen+((int)(H>8? AT[2]&0xFC:AT[2])<<3)+Y-K-1;
C=XPal[C];
/* Mask 1: clip left sprite boundary */
K=L>=0? 0x0FFFF:(0x10000>>-L)-1;
/* Mask 2: clip right sprite boundary */
if(L>256-H) K^=((0x00200>>(H-8))<<(L-257+H))-1;
/* Get and clip the sprite data */
K&=((int)PT[0]<<8)|(H>8? PT[16]:0x00);
/* Draw left 8 pixels of the sprite */
if(K&0xFF00)
{
if(K&0x8000) P[0]=C;if(K&0x4000) P[1]=C;
if(K&0x2000) P[2]=C;if(K&0x1000) P[3]=C;
if(K&0x0800) P[4]=C;if(K&0x0400) P[5]=C;
if(K&0x0200) P[6]=C;if(K&0x0100) P[7]=C;
}
/* Draw right 8 pixels of the sprite */
if(K&0x00FF)
{
if(K&0x0080) P[8]=C; if(K&0x0040) P[9]=C;
if(K&0x0020) P[10]=C;if(K&0x0010) P[11]=C;
if(K&0x0008) P[12]=C;if(K&0x0004) P[13]=C;
if(K&0x0002) P[14]=C;if(K&0x0001) P[15]=C;
}
}
}
}
/** RefreshLine0() *******************************************/
/** Refresh line Y (0..191) of SCREEN0, including sprites **/
/** in this line. **/
/*************************************************************/
void RefreshLine0(register byte Y)
{
register byte X,K,Offset,FC,BC;
register byte *P,*T;
#if SINGLELINE_RENDERING
P=XBuf;
#else
P=XBuf+WIDTH*(HEIGHT-192)/2+WIDTH*Y;
#endif
XPal[0]=BGColor? XPal[BGColor]:XPal0;
if(!ScreenON) memset(P,XPal[BGColor],WIDTH);
else
{
BC=XPal[BGColor];
FC=XPal[FGColor];
T=ChrTab+(Y>>3)*40;
Offset=Y&0x07;
//memset(P,BC,(WIDTH-240)/2);
//P+=(WIDTH-240)/2;
for(X=0;X<40;X++)
{
K=ChrGen[((int)*T<<3)+Offset];
P[0]=K&0x80? FC:BC;P[1]=K&0x40? FC:BC;
P[2]=K&0x20? FC:BC;P[3]=K&0x10? FC:BC;
P[4]=K&0x08? FC:BC;P[5]=K&0x04? FC:BC;
P+=6;T++;
}
//memset(P,BC,(WIDTH-240)/2);
}
//RefreshBorder(Y);
}
/** RefreshLine1() *******************************************/
/** Refresh line Y (0..191) of SCREEN1, including sprites **/
/** in this line. **/
/*************************************************************/
void RefreshLine1(register byte Y)
{
register byte X,K,Offset,FC,BC;
register byte *P,*T;
#if SINGLELINE_RENDERING
P=XBuf;
#else
P=XBuf+WIDTH*(HEIGHT-192)/2+WIDTH*Y;
#endif
XPal[0]=BGColor? XPal[BGColor]:XPal0;
if(!ScreenON) memset(P,XPal[BGColor],WIDTH);
else
{
T=ChrTab+(Y>>3)*32;
Offset=Y&0x07;
//memset(P,XPal[BGColor],(WIDTH-256)/2);
//P+=(WIDTH-256)/2;
for(X=0;X<32;X++)
{
K=*T;
BC=ColTab[K>>3];
K=ChrGen[((int)K<<3)+Offset];
FC=XPal[BC>>4];
BC=XPal[BC&0x0F];
P[0]=K&0x80? FC:BC;P[1]=K&0x40? FC:BC;
P[2]=K&0x20? FC:BC;P[3]=K&0x10? FC:BC;
P[4]=K&0x08? FC:BC;P[5]=K&0x04? FC:BC;
P[6]=K&0x02? FC:BC;P[7]=K&0x01? FC:BC;
P+=8;T++;
}
//memset(P,XPal[BGColor],(WIDTH-256)/2);
RefreshSprites(Y);
}
RefreshBorder(Y);
}
/** RefreshLine2() *******************************************/
/** Refresh line Y (0..191) of SCREEN2, including sprites **/
/** in this line. **/
/*************************************************************/
void RefreshLine2(register byte Y)
{
register byte X,K,FC,BC,Offset;
register byte *P,*T,*PGT,*CLT;
register int I;
#if SINGLELINE_RENDERING
P=XBuf;
#else
P=XBuf+WIDTH*(HEIGHT-192)/2+WIDTH*Y;
#endif
XPal[0]=BGColor? XPal[BGColor]:XPal0;
if(!ScreenON) memset(P,XPal[BGColor],WIDTH);
else
{
I=(int)(Y&0xC0)<<5;
PGT=ChrGen+I;
CLT=ColTab+I;
T=ChrTab+(Y>>3)*32;
Offset=Y&0x07;
//memset(P,XPal[BGColor],(WIDTH-256)/2);
//P+=(WIDTH-256)/2;
for(X=0;X<32;X++)
{
I=((int)*T<<3)+Offset;
K=PGT[I];
BC=CLT[I];
FC=XPal[BC>>4];
BC=XPal[BC&0x0F];
P[0]=K&0x80? FC:BC;P[1]=K&0x40? FC:BC;
P[2]=K&0x20? FC:BC;P[3]=K&0x10? FC:BC;
P[4]=K&0x08? FC:BC;P[5]=K&0x04? FC:BC;
P[6]=K&0x02? FC:BC;P[7]=K&0x01? FC:BC;
P+=8;T++;
}
//memset(P,XPal[BGColor],(WIDTH-256)/2);
RefreshSprites(Y);
}
RefreshBorder(Y);
}
/** RefreshLine3() *******************************************/
/** Refresh line Y (0..191) of SCREEN3, including sprites **/
/** in this line. **/
/*************************************************************/
void RefreshLine3(register byte Y)
{
register byte X,K,Offset;
register byte *P,*T;
#if SINGLELINE_RENDERING
P=XBuf;
#else
P=XBuf+WIDTH*(HEIGHT-192)/2+WIDTH*Y;
#endif
XPal[0]=BGColor? XPal[BGColor]:XPal0;
if(!ScreenON) memset(P,XPal[BGColor],WIDTH);
else
{
T=ChrTab+(Y>>3)*32;
Offset=(Y&0x1C)>>2;
//memset(P,XPal[BGColor],(WIDTH-256)/2);
//P+=(WIDTH-256)/2;
for(X=0;X<32;X++)
{
K=ChrGen[((int)*T<<3)+Offset];
P[0]=P[1]=P[2]=P[3]=XPal[K>>4];
P[4]=P[5]=P[6]=P[7]=XPal[K&0x0F];
P+=8;T++;
}
//memset(P,XPal[BGColor],(WIDTH-256)/2);
RefreshSprites(Y);
}
RefreshBorder(Y);
}

Wyświetl plik

@ -0,0 +1,5 @@
extern void coc_Init(void);
extern void coc_Start(char * CartName);
extern void coc_Step(void);
extern void coc_Stop(void);
extern void coc_Input(int click);

Wyświetl plik

@ -0,0 +1,98 @@
/** EMULib Emulation Library *********************************/
/** **/
/** SN76489.c **/
/** **/
/** This file contains emulation for the SN76489 sound chip **/
/** produced by Intel. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-1998 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "SN76489.h"
/** Reset76489() *********************************************/
/** Reset the sound chip. The user has to provide a pointer **/
/** to a function Sound(Channel,Freq,Volume) used to make **/
/** actual sound. **/
/*************************************************************/
void Reset76489(SN76489 *D,void (*Sound)(int,int,int))
{
register int J;
for(J=0;J<4;J++) D->Volume[J]=D->Freq[J]=0;
D->NoiseMode=D->Buf=D->Changed=0x00;
D->Sync=PSG_ASYNC;D->Sound=Sound;
}
/** Sync76489() **********************************************/
/** Flush all accumulated changes by issuing Sound() calls, **/
/** and set the synchronization on/off. The second argument **/
/** should be PSG_SYNC, PSG_ASYNC to set/reset sync, or **/
/** PSG_FLUSH to leave sync mode as it is. **/
/*************************************************************/
void Sync76489(SN76489 *D,unsigned char Sync)
{
register int J,I;
if(D->Sync&&D->Changed)
{
for(J=0,I=1;J<4;J++,I<<=1)
if(D->Changed&I)
D->Sound(J,D->Freq[J],D->Volume[J]);
}
D->Changed=0x00;
if(Sync!=PSG_FLUSH) D->Sync=Sync;
}
/** Write76489() *********************************************/
/** Call this function to output a value V into the sound **/
/** chip. **/
/*************************************************************/
void Write76489(SN76489 *D,unsigned char V)
{
register unsigned char N,J;
register long L;
switch(V&0xF0)
{
case 0xE0:
J=V&0x03;
if(J==D->NoiseMode) return;
switch(J)
{
case 0: D->Freq[3]=20000;break;
case 1: D->Freq[3]=10000;break;
case 2: D->Freq[3]=5000;break;
case 3: D->Freq[3]=D->Freq[2];break;
}
N=3;break;
case 0x80: case 0xA0: case 0xC0:
D->Buf=V;return;
case 0x90: case 0xB0: case 0xD0: case 0xF0:
N=(V-0x90)>>5;
J=(~V&0x0F)*16;
if(J==D->Volume[N]) return;
D->Volume[N]=J;
break;
default:
if(!(D->Buf&0xC0)) return;
N=(D->Buf-0x80)>>5;
L=PSG_BASE/((V&0x3F)*16+(D->Buf&0x0F)+1);
if(L>15000) L=0;
if(L==D->Freq[N]) return;
if((N==2)&&(D->NoiseMode==3))
{
D->Freq[3]=L;
if(D->Sync) D->Changed|=0x08;
else D->Sound(3,D->Freq[3],D->Volume[3]);
}
D->Freq[N]=L;
break;
}
if(D->Sync) D->Changed|=1<<N;
else D->Sound(N,D->Freq[N],D->Volume[N]);
}

Wyświetl plik

@ -0,0 +1,50 @@
/** EMULib Emulation Library *********************************/
/** **/
/** SN76489.c **/
/** **/
/** This file contains emulation for the SN76489 sound chip **/
/** produced by Intel. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-1998 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef SN76489_H
#define SN76489_H
#define PSG_BASE 131072 /* Base frequency for SN76489 */
#define PSG_ASYNC 0 /* Asynchronous emulation */
#define PSG_SYNC 1 /* Synchronous emulation mode */
#define PSG_FLUSH 2 /* Flush buffers only */
typedef struct
{
int Channel,Freq[4],Volume[4],Sync;
unsigned char NoiseMode,Buf,Changed;
void (*Sound)(int,int,int);
} SN76489;
/** Reset76489() *********************************************/
/** Reset the sound chip. The user has to provide a pointer **/
/** to a function Sound(Channel,Freq,Volume) used to make **/
/** actual sound. **/
/*************************************************************/
void Reset76489(register SN76489 *D,void (*Sound)(int,int,int));
/** Sync76489() **********************************************/
/** Flush all accumulated changes by issuing Sound() calls, **/
/** and set the synchronization on/off. The second argument **/
/** should be PSG_SYNC, PSG_ASYNC to set/reset sync, or **/
/** PSG_FLUSH to leave sync mode as it is. **/
/*************************************************************/
void Sync76489(register SN76489 *D,register unsigned char Sync);
/** Write76489() *********************************************/
/** Call this function to output a value V into the sound **/
/** chip. **/
/*************************************************************/
void Write76489(register SN76489 *D,register unsigned char V);
#endif /* SN76489_H */

Wyświetl plik

@ -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-1998 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
static 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 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 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 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, 9, 9, 9, 9, 9, 9, 9, 9, 9, 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 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 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 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 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
};

Wyświetl plik

@ -0,0 +1,583 @@
/** 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-1998 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "options.h"
#include "Z80.h"
#include "Tables.h"
//#include <stdio.h>
#define printf(...)
/** INLINE ***************************************************/
/** Different compilers inline C functions differently. **/
/*************************************************************/
#ifdef __GNUC__
#define INLINE inline
#else
#define INLINE static
#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
extern byte *RAM;
INLINE byte RdZ80(word A) { return(RAM[A]); }
#endif
#ifdef MG
extern byte *Page[];
INLINE byte RdZ80(word A) { return(Page[A>>13][A&0x1FFF]); }
#endif
#ifdef FMSX
extern byte *RAM[],PSL[],SSLReg;
INLINE byte RdZ80(word A)
{
if(A!=0xFFFF) return(RAM[A>>13][A&0x1FFF]);
else return((PSL[3]==3)? ~SSLReg:RAM[7][0x1FFF]);
}
#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&~(N_FLAG|Z_FLAG))|H_FLAG|(Rg&(1<<Bit)? 0:Z_FLAG)
#define M_SET(Bit,Rg) Rg|=1<<Bit
#define M_RES(Bit,Rg) Rg&=~(1<<Bit)
#define M_POP(Rg) \
R->Rg.B.l=RdZ80(R->SP.W++);R->Rg.B.h=RdZ80(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=RdZ80(R->PC.W++);J.B.h=RdZ80(R->PC.W++); \
WrZ80(--R->SP.W,R->PC.B.h);WrZ80(--R->SP.W,R->PC.B.l); \
R->PC.W=J.W
#define M_JP J.B.l=RdZ80(R->PC.W++);J.B.h=RdZ80(R->PC.W);R->PC.W=J.W
#define M_JR R->PC.W+=(offset)RdZ80(R->PC.W)+1
#define M_RET R->PC.B.l=RdZ80(R->SP.W++);R->PC.B.h=RdZ80(R->SP.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
#define M_LDWORD(Rg) \
R->Rg.B.l=RdZ80(R->PC.W++);R->Rg.B.h=RdZ80(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.B.l);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=RdZ80(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),RdZ80(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)RdZ80(R->PC.W++);
I=RdZ80(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),RdZ80(R->PC.W-2),RdZ80(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)RdZ80(R->PC.W++);
I=RdZ80(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,RdZ80(R->PC.W-2),RdZ80(R->PC.W-1),R->PC.W-4
);
}
#undef XX
}
static void CodesED(register Z80 *R)
{
register byte I;
register pair J;
I=RdZ80(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,RdZ80(R->PC.W-1),R->PC.W-2
);
}
}
static void CodesDD(register Z80 *R)
{
register byte I;
register pair J;
#define XX IX
I=RdZ80(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;
case HALT:
R->PC.W--;R->IFF|=0x80;R->ICount=0;break;
default:
if(R->TrapBadOps)
printf
(
"[Z80 %lX] Unrecognized instruction: DD %02X at PC=%04X\n",
(long)R->User,RdZ80(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=RdZ80(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;
case HALT:
R->PC.W--;R->IFF|=0x80;R->ICount=0;break;
default:
printf
(
"Unrecognized instruction: FD %02X at PC=%04X\n",
RdZ80(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)
{
R->PC.W=0x0000;R->SP.W=0xF000;
R->AF.W=R->BC.W=R->DE.W=R->HL.W=0x0000;
R->AF1.W=R->BC1.W=R->DE1.W=R->HL1.W=0x0000;
R->IX.W=R->IY.W=0x0000;
R->I=0x00;R->IFF=0x00;
R->ICount=R->IPeriod;
R->IRequest=INT_NONE;
}
/** ExecZ80() ************************************************/
/** This function will execute a single Z80 opcode. It will **/
/** then return next PC, and current register values in R. **/
/*************************************************************/
word ExecZ80(Z80 *R)
{
register byte I;
register pair J;
I=RdZ80(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;
}
/* We are done */
return(R->PC.W);
}
/** IntZ80() *************************************************/
/** This function will generate interrupt of given vector. **/
/*************************************************************/
void IntZ80(Z80 *R,word Vector)
{
if((R->IFF&0x01)||(Vector==INT_NMI))
{
/* Experimental V Shouldn't disable all interrupts? */
R->IFF=(R->IFF&0x9E)|((R->IFF&0x01)<<6);
if(R->IFF&0x80) { R->PC.W++;R->IFF&=0x7F; }
M_PUSH(PC);
/* Automatically reset IRequest if needed */
if(R->IAutoReset&&(Vector==R->IRequest)) R->IRequest=INT_NONE;
if(Vector==INT_NMI) R->PC.W=INT_NMI;
else
if(R->IFF&0x04)
{
Vector=(Vector&0xFF)|((word)(R->I)<<8);
R->PC.B.l=RdZ80(Vector++);
R->PC.B.h=RdZ80(Vector);
}
else
if(R->IFF&0x02) R->PC.W=INT_IRQ;
else R->PC.W=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. **/
/*************************************************************/
static byte I;
static pair J;
word RunZ80(Z80 *R)
{
// register byte I;
// register pair J;
int ras=0;
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=RdZ80(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&0x20)
{
J.W=R->IRequest; /* Get pending interrupt */
R->ICount+=R->IBackup-1; /* Restore the ICount */
R->IFF&=0xDF; /* Done with AfterEI state */
}
else
{
J.W=LoopZ80(R, &ras); /* Call periodic handler */
R->ICount=R->IPeriod; /* Reset the cycle counter */
if(J.W==INT_NONE) I=R->IRequest; /* Pending int-rupt */
}
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 */
}
if (ras == 1) break;
}
/* Execution stopped */
return(R->PC.W);
}

Wyświetl plik

@ -0,0 +1,141 @@
/** Z80: portable Z80 emulator *******************************/
/** **/
/** Z80.h **/
/** **/
/** This file contains declarations relevant to emulation **/
/** of Z80 CPU. **/
/** **/
/** Copyright (C) Marat Fayzullin 1994-1998 **/
/** 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
/* 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_IRQ 0x0038 /* Standard RST 38h interrupt */
#define INT_NMI 0x0066 /* 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 */
/** Simple Datatypes *****************************************/
/** NOTICE: sizeof(byte)=1 and sizeof(word)=2 **/
/*************************************************************/
typedef unsigned char byte;
typedef unsigned short word;
typedef signed char 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);
/** ExecZ80() ************************************************/
/** This function will execute a single Z80 opcode. It will **/
/** then return next PC, and current register values in R. **/
/*************************************************************/
word ExecZ80(register Z80 *R);
/** 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. **/
/*************************************************************/
word RunZ80(register Z80 *R);
/** 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. **/
/*************************************************************/
byte DebugZ80(register Z80 *R);
/** 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, int * ras);
#endif /* Z80_H */

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,214 @@
#ifndef EMUAPI_H
#define EMUAPI_H
#include "platform_config.h"
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
// Title: < >
#define TITLE " Coleco Emulator"
#define ROMSDIR "coleco"
#define emu_Init(ROM) {coc_Init();coc_Start(ROM);}
#define emu_Step() {coc_Step();}
#define emu_Input(x) {coc_Input(x);}
#define MAX_FILENAME_PATH 64
#define NB_FILE_HANDLER 4
#define PALETTE_SIZE 16
#define VID_FRAME_SKIP 0x0
#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',157, //lowecase
0,'a','s','d','f','g','h','j','k','l',0x0D,
0,'z','x','c','v','b','n','m',',','.',';','/',
145,157,29,17,
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',0x0D,
0,'Z','X','C','V','B','N','M','<','>',':','?',
145,157,29,17,
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,'=',' ','_'
};
#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,
0,0,0,0,
0,0,' ',0
};
#define keylables_map4_0 (char *)"\x11\x12\x13\x14\x15\x16\x17\x18 "
#define keylables_map4_1 (char *)" "
#define keylables_map4_2 (char *)" "
#define keylables_map4_3 (char *)" "
const unsigned short key_map4[] = {
133,134,135,136,137,138,139,140,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,
0,0,0,0,
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,
0,0,0,0,
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

Wyświetl plik

@ -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
};

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1,132 @@
/****************************************************************************
* Purpose : Keyboard input driver.
* Module : Keyboard
* Author : J-M Harvengt
* History : 10/08/97 Creation
****************************************************************************/
#ifndef _KEYBOARD
#define _KEYBOARD
/****************************************************************************
* Macros / typedefs
****************************************************************************/
#define SOURCE_REM 0x01
#define SOURCE_PAD 0x02
#define SOURCE_KEYB 0x03
/* keys id */
#define KEY_UNKNOWN 0x00
#define KEY_LEFT 0x01
#define KEY_RIGHT 0x02
#define KEY_UP 0x03
#define KEY_DOWN 0x04
#define KEY_SPACE 0x05
#define KEY_FONE 0x06
#define KEY_FTWO 0x07
#define KEY_FTHREE 0x08
#define KEY_FFOUR 0x09
#define KEY_FFIVE 0x0a
#define KEY_FSIX 0x0b
#define KEY_FSEVEN 0x0c
#define KEY_FEIGHT 0x0d
#define KEY_FNINE 0x0e
#define KEY_FZERO 0x0f
#define KEY_ONE 0x10
#define KEY_TWO 0x11
#define KEY_THREE 0x12
#define KEY_FOUR 0x13
#define KEY_FIVE 0x14
#define KEY_SIX 0x15
#define KEY_SEVEN 0x16
#define KEY_EIGHT 0x17
#define KEY_NINE 0x18
#define KEY_ZERO 0x19
#define KEY_OK KEY_SPACE
#define KEY_BUT KEY_SPACE
#define KEY_BACK KEY_FONE
#define KEY_MENU KEY_FTWO
#define KEY_TELEWEB KEY_FTHREE
#define KEY_TELETEXT KEY_FFOUR
#define KEY_COIN KEY_FTHREE
#define KEY_ONEUP KEY_FFOUR
/* Bit mask for pad keys */
#define JKEY_PLEFT 0x0001
#define JKEY_PRIGHT 0x0002
#define JKEY_PUP 0x0004
#define JKEY_PDOWN 0x0008
#define JKEY_PSPACE 0x0010
#define JKEY_PONE 0x0020
#define JKEY_PTWO 0x0040
#define JKEY_PTHREE 0x0080
#define JKEY_PFOUR 0x0100
#define JKEY_PFIVE 0x0200
#define JKEY_PSIX 0x0400
#define JKEY_PSEVEN 0x0800
#define JKEY_PEIGHT 0x1000
#define JKEY_PNINE 0x2000
#define JKEY_PZERO 0x4000
#define JKEY_LEFT 0x00010000
#define JKEY_RIGHT 0x00020000
#define JKEY_UP 0x00040000
#define JKEY_DOWN 0x00080000
#define JKEY_SPACE 0x00100000
#define JKEY_ONE 0x00200000
#define JKEY_TWO 0x00400000
#define JKEY_THREE 0x00800000
#define JKEY_FOUR 0x01000000
#define JKEY_FIVE 0x02000000
#define JKEY_SIX 0x04000000
#define JKEY_SEVEN 0x08000000
#define JKEY_EIGHT 0x10000000
#define JKEY_NINE 0x20000000
#define JKEY_ZERO 0x40000000
#define JKEY_OK JKEY_SPACE
#define JKEY_BUT JKEY_SPACE
#define JKEY_BACK JKEY_ONE
#define JKEY_MENU JKEY_TWO
#define JKEY_TELEWEB JKEY_THREE
#define JKEY_TELETEXT JKEY_FOUR
#define JKEY_COIN JKEY_THREE
#define JKEY_ONEUP JKEY_FOUR
#define JKEY_PPLUS JKEY_EIGHT
#define JKEY_PMINUS JKEY_NINE
#define JKEY_POK JKEY_PSPACE
#define JKEY_PBUT JKEY_PSPACE
#define JKEY_PBACK JKEY_PONE
#define JKEY_PMENU JKEY_PTWO
#define JKEY_PTELEWEB JKEY_PTHREE
#define JKEY_PTELETEXT JKEY_PFOUR
#define JKEY_PEPG JKEY_PFIVE
#define JKEY_PCOIN JKEY_PTHREE
#define JKEY_PONEUP JKEY_PFOUR
#define JKEY_PPPLUS JKEY_PEIGHT
#define JKEY_PPMINUS JKEY_PNINE
/* Bit mask for mouse button */
#define LMOUSEDOWN 0x40
#define LMOUSEUP 0x80
/****************************************************************************
* Exported procedures
****************************************************************************/
extern void key_Init(void);
extern void key_TurnOn(void);
extern void key_TurnOff(void);
extern void key_OnKeyDown(int aSource, int aKey);
extern void key_OnKeyUp(int aSource, int aKey);
extern void key_SubscribeKeyUp(void * callback);
extern void key_SubscribeKeyDown(void * callback);
extern void key_OnKeyTimer(void);
extern int key_GetKeyPad(void);
extern void key_OnMouseMove(int x, int y, int b);
extern void key_GetMouseMove(int *x, int *y, int *b);
#endif

Wyświetl plik

@ -0,0 +1 @@
#define LSB_FIRST 1

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1,205 @@
extern "C" {
#include "iopins.h"
#include "emuapi.h"
}
extern "C" {
#include "Colem.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, 20000); //to run every 20ms
myTimer.begin(vblCount, 16666); //to run every 16.6666ms
}
delay(20);
}
else {
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
emu_Step();
//delay(20);
delay(16);
}
}
#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

Wyświetl plik

@ -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 256
#define TFT_REALWIDTH 320
#endif
#define TFT_HEIGHT 240
#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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -146,7 +146,7 @@ void loop(void)
emu_Init(filename);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
myTimer.begin(vblCount, 20000); //to run every 20ms
myTimer.begin(vblCount, 16666); //to run every 16.6666ms
}
delay(20);
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1,202 @@
/****************************************************************************
* Module name : oddemu
* Description : Library SMSEMU
* Author : J-M Harvengt
* History : 14-07-97 Creation
****************************************************************************/
#include "vmachine.h"
#include "vdc.h"
#include "oddemu.h"
#include "emuapi.h"
/****************************************************************************
* Local macros / typedefs
****************************************************************************/
#define MAX_ROM_SIZE 8192 //16384
/****************************************************************************
* Local procedures definition
****************************************************************************/
/****************************************************************************
* Local data
****************************************************************************/
#define MAXC 1024
static char * bios=0; //[MAXC];
static char * scshot=0; //[MAXC];
static char * lorom=0; //[MAX_ROM_SIZE];
/****************************************************************************
* Global data
****************************************************************************/
/****************************************************************************
* Local procedures
****************************************************************************/
/****************************************************************************
* Exported procedures
****************************************************************************/
void odd_Init(void)
{
if (bios == 0) bios = (char *)emu_Malloc(MAXC);
if (scshot == 0) scshot = (char *)emu_Malloc(MAXC);
if (lorom == 0) lorom = (char *)emu_Malloc(MAX_ROM_SIZE);
app_data.debug = 0;
app_data.stick[0] = 0;
app_data.stick[1] = 1;
app_data.bank = 0;
app_data.limit = 1;
app_data.sound_en = 1;
app_data.speed = 100;
app_data.wsize = 1;
app_data.fullscreen = 1;
app_data.scanlines = 0;
app_data.voice = 1;
app_data.window_title = "O2EM v";
app_data.svolume = 200;
app_data.vvolume = 100;
app_data.filter = 0;
app_data.exrom = 0;
app_data.crc = 0;
app_data.scshot = scshot;
app_data.euro = 1;
app_data.openb = 0;
}
static void load_bios( char *biosname)
{
static char s[MAXC+10];
unsigned long crc;
emu_LoadFile(biosname,&rom1[0],1024);
memcpy(&rom2[0],&rom1[0],1024);
memcpy(&rom3[0],&rom1[0],1024);
memcpy(&rom4[0],&rom1[0],1024);
crc = crc32_buf(rom1,1024);
if (crc==0x8016A315)
emu_printf("Odyssey2 bios ROM loaded\n");
else if (crc==0xE20A9F41)
emu_printf("Videopac+ G7400 bios ROM loaded\n");
else
emu_printf("Bios ROM loaded (unknown version)\n");
}
static void load_cart(char *file)
{
long l;
l = emu_LoadFile(file,&lorom[0],MAX_ROM_SIZE);
app_data.crc = crc32_buf(lorom, l); // crc32_file(file);
if (app_data.crc == 0xAFB23F89) app_data.exrom = 1; /* Musician */
if (app_data.crc == 0x3BFEF56B) app_data.exrom = 1; /* Four in 1 Row! */
if (((app_data.crc == 0x975AB8DA) || (app_data.crc == 0xE246A812)) && (!app_data.debug)) {
emu_printf("Error: file is an incomplete ROM dump\n");
}
if (l < 2049) {
app_data.bank=1;
memcpy(&rom1[1024],&lorom[0],l);
memcpy(&rom1[3072],&rom1[2048],1024); /* simulate missing A10 */
rom=rom1;
emu_printf("2K");
} else if (l == 3072) {
app_data.bank=1;
memcpy(&rom1[1024],&lorom[0],3072);
rom=rom1;
emu_printf("3K");
} else if (l == 4096) {
if (app_data.exrom) {
app_data.bank=1;
memcpy(&extROM[0],&lorom[0],1024);
memcpy(&rom1[1024],&lorom[1024],3072);
rom=rom1;
emu_printf("3K EXROM");
} else {
app_data.bank=2;
memcpy(&rom1[1024],&lorom[0],2048);
memcpy(&rom2[1024],&lorom[2048],2048);
memcpy(&rom1[3072],&rom1[2048],1024); /* simulate missing A10 */
memcpy(&rom2[3072],&rom2[2048],1024); /* simulate missing A10 */
rom=rom2;
emu_printf("4K");
}
} else if (l == 6144) {
app_data.bank=2;
memcpy(&rom1[1024],&lorom[0],3072);
memcpy(&rom2[1024],&lorom[3072],3072);
rom=rom2;
emu_printf("6K");
} else if (l == 8192) {
app_data.bank=3;
memcpy(&rom1[1024],&lorom[0],2048);
memcpy(&rom2[1024],&lorom[2048],2048);
memcpy(&rom3[1024],&lorom[2*2048],2048);
memcpy(&rom4[1024],&lorom[3*2048],2048);
memcpy(&rom1[3072],&rom1[2048],1024); /* simulate missing A10 */
memcpy(&rom2[3072],&rom2[2048],1024); /* simulate missing A10 */
memcpy(&rom3[3072],&rom3[2048],1024); /* simulate missing A10 */
memcpy(&rom4[3072],&rom4[2048],1024); /* simulate missing A10 */
rom=rom4;
emu_printf("8K");
} else if (l == 12288) {
app_data.bank=3;
memcpy(&rom1[1024],&lorom[0],3072);
memcpy(&rom2[1024],&lorom[3072],3072);
memcpy(&rom3[1024],&lorom[2*3072],3072);
memcpy(&rom4[1024],&lorom[3*3072],3072);
rom=rom4;
emu_printf("12K");
} else {
emu_printf("Invalid ROM size");
}
if ((rom1[1024+12]=='O') && (rom1[1024+13]=='P') && (rom1[1024+14]=='N') && (rom1[1024+15]=='B')) app_data.openb=1;
orom=rom;
//printf("CRC: %08lX\n",app_data.crc);
}
void odd_Start(char * filename)
{
load_bios(ROMSDIR "/" "o2rom.bin");
load_cart(filename);
init_display();
init_cpu();
init_system();
}
//static void snd_Mixer(short * stream, int len )
//{
// audio_process(stream, len>>2);
//}
void odd_Stop(void)
{
close_audio();
close_display();
}
void odd_Step(void)
{
run();
//emu_printf("s");
emu_DrawScreen((unsigned char *)getGBuf()+BORDERW/2, BMPW-BORDERW, BMPH, BMPW);
emu_DrawVsync();
}

Wyświetl plik

@ -0,0 +1,5 @@
extern void odd_Init(void);
extern void odd_Start(char * filename);
extern void odd_Stop(void);
extern void odd_Step(void);
extern void odd_Input(int click);

Wyświetl plik

@ -0,0 +1,183 @@
/*
* O2EM Freeware Odyssey2 / Videopac+ Emulator
*
* Created by Daniel Boris <dboris@comcast.net> (c) 1997,1998
*
* Developed by Andre de la Rocha <adlroc@users.sourceforge.net>
*
* http://o2em.sourceforge.net
*
*
*
* O2 audio emulation
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cpu.h"
#include "types.h"
#include "config.h"
#include "vmachine.h"
#include "audio.h"
//#define SAMPLE_RATE 44100
#define PERIOD1 11 //11
#define PERIOD2 44 //44
#define SOUND_BUFFER_LEN 1056
#define AUD_CTRL 0xAA
#define AUD_D0 0xA7
#define AUD_D1 0xA8
#define AUD_D2 0xA9
int sound_IRQ;
//static short *stream=NULL;
//static AUDIOSTREAM *stream=NULL;
//FILE *sndlog=NULL;
static double flt_a=0.0, flt_b=0.0;
static unsigned char flt_prv = 0;
static void filter(unsigned char *buf, unsigned long len);
//void audio_process(unsigned char *buffer){
#ifdef GP32
void audio_process(unsigned short *buffer, int len)
#else
void audio_process(short *buffer, int len)
#endif
{
unsigned long aud_data;
#ifdef GP32
unsigned short s;
#else
short s;
#endif
int volume, re_circ, noise, enabled, intena, period, pnt, cnt, rndbit, pos;
aud_data = (VDCwrite[AUD_D2] | (VDCwrite[AUD_D1] << 8) | (VDCwrite[AUD_D0] << 16));
intena = VDCwrite[0xA0] & 0x04;
pnt = cnt = 0;
noise = VDCwrite[AUD_CTRL] & 0x10;
enabled = VDCwrite[AUD_CTRL] & 0x80;
rndbit = (enabled && noise) ? (rand()%2) : 0;
while (pnt < len/*SOUND_BUFFER_LEN*/) {
pos = (tweakedaudio) ? (pnt/3) : (MAXLINES-1);
volume = AudioVector[pos] & 0x0F;
enabled = AudioVector[pos] & 0x80;
period = (AudioVector[pos] & 0x20) ? PERIOD1 : PERIOD2;
re_circ = AudioVector[pos] & 0x40;
#ifdef GP32
s= ( (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0) << 8;
#else
s= (( (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0) - 128) << 8 ;
#endif
*buffer++ = s;
*buffer++ = s;
pnt++;
cnt++;
if (cnt >= period) {
cnt=0;
aud_data = (re_circ) ? ((aud_data >> 1) | ((aud_data & 1) << 23)) : (aud_data >>= 1);
rndbit = (enabled && noise) ? (rand()%2) : 0;
if (enabled && intena && (!sound_IRQ)) {
sound_IRQ = 1;
ext_IRQ();
}
}
}
// if (app_data.filter) filter(buffer, SOUND_BUFFER_LEN);
}
void update_audio(void) {
// unsigned char *p;
if (app_data.sound_en) {
// p = (unsigned char *)get_audio_stream_buffer(stream);
// if (p) {
// audio_process(p);
// if (sndlog) fwrite(p,1,SOUND_BUFFER_LEN,sndlog);
// free_audio_stream_buffer(stream);
// }
}
}
void init_audio(void) {
// int i;
sound_IRQ=0;
// set_volume(255,255);
init_sound_stream();
// sndlog = NULL;
}
void init_sound_stream(void){
int vol;
if (app_data.sound_en){
if (app_data.filter)
vol = (255*app_data.svolume)/100;
else
vol = (255*app_data.svolume)/200;
// stream = play_audio_stream(SOUND_BUFFER_LEN,8,0,SAMPLE_RATE,vol,128);
// if (!stream) {
// printf("Error creating audio stream!\n");
// app_data.sound_en=0;
// }
flt_a = flt_b = 0.0;
flt_prv = 0;
}
}
void mute_audio(void){
if (app_data.sound_en /*&& stream*/){
// stop_audio_stream(stream);
// stream=NULL;
}
}
void close_audio(void) {
if (app_data.sound_en /*&& stream*/) {
// stop_audio_stream(stream);
}
app_data.sound_en=0;
}
static void filter(unsigned char *buffer, unsigned long len){
static unsigned char buf[SOUND_BUFFER_LEN];
int t;
unsigned long i;
if (len>SOUND_BUFFER_LEN) return;
memcpy(buf,buffer,len);
for (i=0; i<len; i++){
t = (i==0)?(buf[0]-flt_prv):(buf[i]-buf[i-1]);
if (t) flt_b = (double)t;
flt_a += flt_b/4.0 - flt_a/80.0;
flt_b -= flt_b/4.0;
if ((flt_a>255.0)||(flt_a<-255.0)) flt_a=0.0;
buffer[i] = (unsigned char)((flt_a+255.0)/2.0);
}
flt_prv = buf[len-1];
}

Wyświetl plik

@ -0,0 +1,18 @@
#ifndef __AUDIO_H
#define __AUDIO_H
void update_audio(void);
void init_audio(void);
void close_audio(void);
void init_sound_stream(void);
void mute_audio(void);
#ifdef GP32
void audio_process(unsigned short *buffer, int len);
#else
void audio_process(short *buffer, int len);
#endif
extern int sound_IRQ;
#endif

Wyświetl plik

@ -0,0 +1,8 @@
#ifndef __CONFIG_H
#define __CONFIG_H
#define O2EM_VERSION "1.01"
#define RELEASE_DATE "(October/2002)"
#endif

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,34 @@
#ifndef CPU_H
#define CPU_H
#include "types.h"
extern Byte acc; /* Accumulator */
extern ADDRESS pc; /* Program counter */
extern long clk; /* clock */
extern Byte itimer; /* Internal timer */
extern Byte reg_pnt; /* pointer to register bank */
extern Byte timer_on; /* 0=timer off/1=timer on */
extern Byte count_on; /* 0=count off/1=count on */
extern Byte t_flag; /* Timer flag */
extern Byte psw; /* Processor status word */
extern Byte sp; /* Stack pointer (part of psw) */
extern Byte p1; /* I/O port 1 */
extern Byte p2; /* I/O port 2 */
extern Byte xirq_pend;
extern Byte tirq_pend;
void init_cpu(void);
void cpu_exec(void);
void ext_IRQ(void);
void tim_IRQ(void);
void make_psw_debug(void);
#endif /* CPU_H */

Wyświetl plik

@ -0,0 +1,111 @@
/*
* O2EM Freeware Odyssey2 / Videopac+ Emulator
*
* Created by Daniel Boris <dboris@comcast.net> (c) 1997,1998
*
* Developed by Andre de la Rocha <adlroc@users.sourceforge.net>
*
* http://o2em.sourceforge.net
*
*
*
* CRC32 functions used to identify files
*/
#include <stdio.h>
#include <stdlib.h>
#include "crc32.h"
//#include "pgmspace.h"
static const unsigned long crc32tab[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
unsigned long crc32_buf(const void *buf, long len){
unsigned long crc = ~0;
unsigned char *p = (unsigned char*)buf;
while (len--) crc = (crc >> 8) ^ crc32tab[(crc ^ (*p++)) & 0xff];
return ~crc;
}
unsigned long crc32_file(const char *filename){
unsigned long crc = ~0;
FILE *f;
int c;
f = fopen(filename,"rb");
if (f){
while ((c=fgetc(f)) != EOF) crc = (crc >> 8) ^ crc32tab[(crc ^ c) & 0xff];
fclose(f);
}
return ~crc;
}

Wyświetl plik

@ -0,0 +1,7 @@
#ifndef __CRC32_H
#define __CRC32_H
unsigned long crc32_buf(const void *buf, long len);
unsigned long crc32_file(const char *filename);
#endif

Wyświetl plik

@ -0,0 +1,86 @@
/*
* O2EM Freeware Odyssey2 / Videopac+ Emulator
*
* Created by Daniel Boris <dboris@comcast.net> (c) 1997,1998
*
* Developed by Andre de la Rocha <adlroc@users.sourceforge.net>
*
* http://o2em.sourceforge.net
*
*
*
* O2 character table
*/
#include "types.h"
#include "cset.h"
const Byte cset[512]= {
0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
0x18,0x38,0x18,0x18,0x18,0x18,0x3C,0x00,
0x3C,0x66,0x0C,0x18,0x30,0x60,0x7E,0x00,
0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00,
0xCC,0xCC,0xCC,0xFE,0x0C,0x0C,0x0C,0x00,
0xFE,0xC0,0xC0,0x7C,0x06,0xC6,0x7C,0x00,
0x7C,0xC6,0xC0,0xFC,0xC6,0xC6,0x7C,0x00,
0xFE,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,
0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00,
0x7C,0xC6,0xC6,0x7E,0x06,0xC6,0x7C,0x00,
0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00,
0x18,0x7E,0x58,0x7E,0x1A,0x7E,0x18,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x3C,0x66,0x0C,0x18,0x18,0x00,0x18,0x00,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0x00,
0xFC,0xC6,0xC6,0xFC,0xC0,0xC0,0xC0,0x00,
0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,
0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00,
0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xFE,0x00,
0xFC,0xC6,0xC6,0xFC,0xD8,0xCC,0xC6,0x00,
0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,
0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,
0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x76,0x00,
0x7C,0xC6,0xC0,0x7C,0x06,0xC6,0x7C,0x00,
0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0xFC,0x00,
0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00,
0x7C,0xC6,0xC0,0xC0,0xCE,0xC6,0x7E,0x00,
0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,
0x06,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,
0xC6,0xCC,0xD8,0xF0,0xD8,0xCC,0xC6,0x00,
0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00,
0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00,
0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00,
0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,
0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,
0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00,
0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00,
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,
0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,
0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,0x00,
0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00,
0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00,
0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00,
0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00,
0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,
0xCE,0xDB,0xDB,0xDB,0xDB,0xDB,0xCE,0x00,
0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x3C,0x00,
0x1C,0x1C,0x18,0x1E,0x18,0x18,0x1C,0x00,
0x1C,0x1C,0x18,0x1E,0x18,0x34,0x26,0x00,
0x38,0x38,0x18,0x78,0x18,0x2C,0x64,0x00,
0x38,0x38,0x18,0x78,0x18,0x18,0x38,0x00,
0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,
0x18,0x3C,0x7E,0xFF,0xFF,0x18,0x18,0x00,
0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0x00,
0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0x00,
0x38,0x38,0x12,0xFE,0xB8,0x28,0x6C,0x00,
0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x00,
0x00,0x00,0x0C,0x08,0x08,0x7F,0x3E,0x00,
0x00,0x03,0x63,0xFF,0xFF,0x18,0x08,0x00,
0x00,0x00,0x00,0x10,0x38,0xFF,0x7E,0x00,
0x00,0x00,0x00,0x06,0x6E,0xFF,0x7E,0x00};

Wyświetl plik

@ -0,0 +1,6 @@
#ifndef __CSET_H
#define __CSET_H
extern const Byte cset[512];
#endif

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,214 @@
#ifndef EMUAPI_H
#define EMUAPI_H
#include "platform_config.h"
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
// Title: < >
#define TITLE " Oddysey Emulator"
#define ROMSDIR "o2em"
#define emu_Init(ROM) {odd_Init();odd_Start(ROM);}
#define emu_Step() {odd_Step();}
#define emu_Input(x) {odd_Input(x);}
#define MAX_FILENAME_PATH 64
#define NB_FILE_HANDLER 4
#define VID_FRAME_SKIP 0x0
#define PALETTE_SIZE 256
#define TFT_VBUFFER_YCROP 20
#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',157, //lowecase
0,'a','s','d','f','g','h','j','k','l',0x0D,
0,'z','x','c','v','b','n','m',',','.',';','/',
145,157,29,17,
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',0x0D,
0,'Z','X','C','V','B','N','M','<','>',':','?',
145,157,29,17,
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,'=',' ','_'
};
#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,
0,0,0,0,
0,0,' ',0
};
#define keylables_map4_0 (char *)"\x11\x12\x13\x14\x15\x16\x17\x18 "
#define keylables_map4_1 (char *)" "
#define keylables_map4_2 (char *)" "
#define keylables_map4_3 (char *)" "
const unsigned short key_map4[] = {
133,134,135,136,137,138,139,140,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,
0,0,0,0,
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,
0,0,0,0,
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

Wyświetl plik

@ -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
};

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1,341 @@
/*
* O2EM Freeware Odyssey2 / Videopac+ Emulator
*
* Created by Daniel Boris <dboris@comcast.net> (c) 1997,1998
*
* Developed by Andre de la Rocha <adlroc@users.sourceforge.net>
*
* http://o2em.sourceforge.net
*
*
*
* 8048 Mnemonics
*/
#include "cpu.h"
#include "table.h"
struct lookup_tag lookup[] = {
/* 00 */ {"NOP",1,0},
/* 01 */ {"ILL",1,0},
/* 02 */ {"OUTL BUS,A",1,0},
/* 03 */ {"ADD A,",2,1},
/* 04 */ {"JMP",2,2},
/* 05 */ {"EN I",1,0},
/* 06 */ {"ILL",1,0},
/* 07 */ {"DEC A",1,0},
/* 08 */ {"INS A,BUS",1,0},
/* 09 */ {"IN A,P1",1,0},
/* 0A */ {"IN A,P2",1,0},
/* 0B */ {"ILL",1,0},
/* 0C */ {"MOVD A,P4",1,0},
/* 0D */ {"MOVD A,P5",1,0},
/* 0E */ {"MOVD A,P6",1,0},
/* 0F */ {"MOVD A,P7",1,0},
/* 10 */ {"INC @R0",1,0},
/* 11 */ {"INC @R1",1,0},
/* 12 */ {"JB0",2,3},
/* 13 */ {"ADDC A,",2,1},
/* 14 */ {"CALL",2,2},
/* 15 */ {"DIS I",1,0},
/* 16 */ {"JTF",2,3},
/* 17 */ {"INC A",1,0},
/* 18 */ {"INC R0",1,0},
/* 19 */ {"INC R1",1,0},
/* 1A */ {"INC R2",1,0},
/* 1B */ {"INC R3",1,0},
/* 1C */ {"INC R4",1,0},
/* 1D */ {"INC R5",1,0},
/* 1E */ {"INC R6",1,0},
/* 1F */ {"INC R7",1,0},
/* 20 */ {"XCH A,@R0",1,0},
/* 21 */ {"XCH A,@R1",1,0},
/* 22 */ {"ILL",1,0},
/* 23 */ {"MOV A,",2,1},
/* 24 */ {"JMP",2,2},
/* 25 */ {"EN TCNTI",1,0},
/* 26 */ {"JNT0",2,3},
/* 27 */ {"CLR A",1,0},
/* 28 */ {"XCH A,R0",1,0},
/* 29 */ {"XCH A,R1",1,0},
/* 2A */ {"XCH A,R2",1,0},
/* 2B */ {"XCH A,R3",1,0},
/* 2C */ {"XCH A,R4",1,0},
/* 2D */ {"XCH A,R5",1,0},
/* 2E */ {"XCH A,R6",1,0},
/* 2F */ {"XCH A,R7",1,0},
/* 30 */ {"XCHD A,@R0",1,0},
/* 31 */ {"XCHD A,@R1",1,0},
/* 32 */ {"JB1",2,3},
/* 33 */ {"ILL",1,0},
/* 34 */ {"CALL",2,2},
/* 35 */ {"DIS TCNTI",1,0},
/* 36 */ {"JT0",2,3},
/* 37 */ {"CPL A",1,0},
/* 38 */ {"ILL",1,0},
/* 39 */ {"OUTL P1,A",1,0},
/* 3A */ {"OUTL P2,A",1,0},
/* 3B */ {"ILL",1,0},
/* 3C */ {"MOVD P4,A",1,0},
/* 3D */ {"MOVD P5,A",1,0},
/* 3E */ {"MOVD P6,A",1,0},
/* 3F */ {"MOVD P7,A",1,0},
/* 40 */ {"ORL A,@R0",1,0},
/* 41 */ {"ORL A,@R1",1,0},
/* 42 */ {"MOV A,T",1,0},
/* 43 */ {"ORL A,",2,1},
/* 44 */ {"JMP",2,2},
/* 45 */ {"STRT CNT",1,0},
/* 46 */ {"JNT1",2,3},
/* 47 */ {"SWAP",1,0},
/* 48 */ {"ORL A,R0",1,0},
/* 49 */ {"ORL A,R1",1,0},
/* 4A */ {"ORL A,R2",1,0},
/* 4B */ {"ORL A,R3",1,0},
/* 4C */ {"ORL A,R4",1,0},
/* 4D */ {"ORL A,R5",1,0},
/* 4E */ {"ORL A,R6",1,0},
/* 4F */ {"ORL A,R7",1,0},
/* 50 */ {"ANL A,@R0",1,0},
/* 51 */ {"ANL A,@R1",1,0},
/* 52 */ {"JB2",2,3},
/* 53 */ {"ANL A,",2,1},
/* 54 */ {"CALL",2,2},
/* 55 */ {"STRT T",1,0},
/* 56 */ {"JT1",2,3},
/* 57 */ {"ILL",1,0},
/* 58 */ {"ANL A,R0",1,0},
/* 59 */ {"ANL A,R1",1,0},
/* 5A */ {"ANL A,R2",1,0},
/* 5B */ {"ANL A,R3",1,0},
/* 5C */ {"ANL A,R4",1,0},
/* 5D */ {"ANL A,R5",1,0},
/* 5E */ {"ANL A,R6",1,0},
/* 5F */ {"ANL A,R7",1,0},
/* 60 */ {"ADD A,@R0",1,0},
/* 61 */ {"ADD A,@R1",1,0},
/* 62 */ {"MOV T,A",1,0},
/* 63 */ {"ILL",1,0},
/* 64 */ {"JMP",2,2},
/* 65 */ {"STOP TCNT",1,0},
/* 66 */ {"ILL",1,0},
/* 67 */ {"RRC A",1,0},
/* 68 */ {"ADD A,R0",1,0},
/* 69 */ {"ADD A,R1",1,0},
/* 6A */ {"ADD A,R2",1,0},
/* 6B */ {"ADD A,R3",1,0},
/* 6C */ {"ADD A,R4",1,0},
/* 6D */ {"ADD A,R5",1,0},
/* 6E */ {"ADD A,R6",1,0},
/* 6F */ {"ADD A,R7",1,0},
/* 70 */ {"ADDC A,@R0",1,0},
/* 71 */ {"ADDC A,@R1",1,0},
/* 72 */ {"JB3",2,3},
/* 73 */ {"ILL",1,0},
/* 74 */ {"CALL",2,2},
/* 75 */ {"ENT0 CLK",1,0},
/* 76 */ {"JF1",2,3},
/* 77 */ {"RR A",1,0},
/* 78 */ {"ADDC A,R0",1,0},
/* 79 */ {"ADDC A,R1",1,0},
/* 7A */ {"ADDC A,R2",1,0},
/* 7B */ {"ADDC A,R3",1,0},
/* 7C */ {"ADDC A,R4",1,0},
/* 7D */ {"ADDC A,R5",1,0},
/* 7E */ {"ADDC A,R6",1,0},
/* 7F */ {"ADDC A,R7",1,0},
/* 80 */ {"MOVX A,@R0",1,0},
/* 81 */ {"MOVX A,@R1",1,0},
/* 82 */ {"ILL",1,0},
/* 83 */ {"RET",1,0},
/* 84 */ {"JMP",2,2},
/* 85 */ {"CLR F0",1,0},
/* 86 */ {"JNI",2,3},
/* 87 */ {"ILL",1,0},
/* 88 */ {"ORL BUS,",2,1},
/* 89 */ {"ORL P1,",2,1},
/* 8A */ {"ORL P2,",2,1},
/* 8B */ {"ILL",1,0},
/* 8C */ {"ORLD P4,A",1,0},
/* 8D */ {"ORLD P5,A",1,0},
/* 8E */ {"ORLD P6,A",1,0},
/* 8F */ {"ORLD P7,A",1,0},
/* 90 */ {"MOVX @R0,A",1,0},
/* 91 */ {"MOVX @R1,A",1,0},
/* 92 */ {"JB4",2,3},
/* 93 */ {"RETR",1,0},
/* 94 */ {"CALL",2,2},
/* 95 */ {"CPL F0",1,0},
/* 96 */ {"JNZ",2,3},
/* 97 */ {"CLR C",1,0},
/* 98 */ {"ANL BUS,",2,1},
/* 99 */ {"ANL P1,",2,1},
/* 9A */ {"ANL P2,",2,1},
/* 9B */ {"ILL",1,0},
/* 9C */ {"ANLD P4,A",1,0},
/* 9D */ {"ANLD P5,A",1,0},
/* 9E */ {"ANLD P6,A",1,0},
/* 9F */ {"ANLD P7,A",1,0},
/* A0 */ {"MOV @R0,A",1,0},
/* A1 */ {"MOV @R1,A",1,0},
/* A2 */ {"ILL",1,0},
/* A3 */ {"MOVP A,@A",1,0},
/* A4 */ {"JMP",2,2},
/* A5 */ {"CLR F1",1,0},
/* A6 */ {"ILL",1,0},
/* A7 */ {"CPL C",1,0},
/* A8 */ {"MOV R0,A",1,0},
/* A9 */ {"MOV R1,A",1,0},
/* AA */ {"MOV R2,A",1,0},
/* AB */ {"MOV R3,A",1,0},
/* AC */ {"MOV R4,A",1,0},
/* AD */ {"MOV R5,A",1,0},
/* AE */ {"MOV R6,A",1,0},
/* AF */ {"MOV R7,A",1,0},
/* B0 */ {"MOV @R0,",2,1},
/* B1 */ {"MOV @R1,",2,1},
/* B2 */ {"JB5",2,3},
/* B3 */ {"JMPP @A",1,0},
/* B4 */ {"CALL",2,2},
/* B5 */ {"CPL F1",1,0},
/* B6 */ {"JF0",2,3},
/* B7 */ {"ILL",1,0},
/* B8 */ {"MOV R0,",2,1},
/* B9 */ {"MOV R1,",2,1},
/* BA */ {"MOV R2,",2,1},
/* BB */ {"MOV R3,",2,1},
/* BC */ {"MOV R4,",2,1},
/* BD */ {"MOV R5,",2,1},
/* BE */ {"MOV R6,",2,1},
/* BF */ {"MOV R7,",2,1},
/* C0 */ {"ILL",1,0},
/* C1 */ {"ILL",1,0},
/* C2 */ {"ILL",1,0},
/* C3 */ {"ILL",1,0},
/* C4 */ {"JMP",2,2},
/* C5 */ {"SEL RB0",1,0},
/* C6 */ {"JZ",2,3},
/* C7 */ {"MOV A,PSW",1,0},
/* C8 */ {"DEC R0",1,0},
/* C9 */ {"DEC R1",1,0},
/* CA */ {"DEC R2",1,0},
/* CB */ {"DEC R3",1,0},
/* CC */ {"DEC R4",1,0},
/* CD */ {"DEC R5",1,0},
/* CE */ {"DEC R6",1,0},
/* CF */ {"DEC R7",1,0},
/* D0 */ {"XRL A,@R0",1,0},
/* D1 */ {"XRL A,@R1",1,0},
/* D2 */ {"JB6",2,3},
/* D3 */ {"XRL A,",2,1},
/* D4 */ {"CALL",2,2},
/* D5 */ {"SEL RB1",1,0},
/* D6 */ {"ILL",1,0},
/* D7 */ {"MOV PSW,A",1,0},
/* D8 */ {"XRL A,R0",1,0},
/* D9 */ {"XRL A,R1",1,0},
/* DA */ {"XRL A,R2",1,0},
/* DB */ {"XRL A,R3",1,0},
/* DC */ {"XRL A,R4",1,0},
/* DD */ {"XRL A,R5",1,0},
/* DE */ {"XRL A,R6",1,0},
/* DF */ {"XRL A,R7",1,0},
/* E0 */ {"ILL",1,0},
/* E1 */ {"ILL",1,0},
/* E2 */ {"ILL",1,0},
/* E3 */ {"MOVP3 A,@A",1,0},
/* E4 */ {"JMP",2,2},
/* E5 */ {"SEL MB0",1,0},
/* E6 */ {"JNC",2,3},
/* E7 */ {"RL A",1,0},
/* E8 */ {"DJNZ R0,",2,3},
/* E9 */ {"DJNZ R1,",2,3},
/* EA */ {"DJNZ R2,",2,3},
/* EB */ {"DJNZ R3,",2,3},
/* EC */ {"DJNZ R4,",2,3},
/* ED */ {"DJNZ R5,",2,3},
/* EE */ {"DJNZ R6,",2,3},
/* EF */ {"DJNZ R7,",2,3},
/* F0 */ {"MOV A,@R0",1,0},
/* F1 */ {"MOV A,@R1",1,0},
/* F2 */ {"JB7",2,3},
/* F3 */ {"ILL",1,0},
/* F4 */ {"CALL",2,2},
/* F5 */ {"SEL MB1",1,0},
/* F6 */ {"JC",2,3},
/* F7 */ {"RLC A",1,0},
/* F8 */ {"MOV A,R0",1,0},
/* F9 */ {"MOV A,R1",1,0},
/* FA */ {"MOV A,R2",1,0},
/* FB */ {"MOV A,R3",1,0},
/* FC */ {"MOV A,R4",1,0},
/* FD */ {"MOV A,R5",1,0},
/* FE */ {"MOV A,R6",1,0},
/* FF */ {"MOV A,R7",1,0}
};

Wyświetl plik

@ -0,0 +1,10 @@
#ifndef __TABLE_H
#define __TABLE_H
extern struct lookup_tag {
signed char *mnemonic; //JMH
unsigned char bytes;
unsigned char type;
} lookup[];
#endif

Wyświetl plik

@ -0,0 +1,204 @@
extern "C" {
#include "iopins.h"
#include "emuapi.h"
}
extern "C" {
#include "Oddemu.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, 20000); //to run every 20ms
myTimer.begin(vblCount, 16666); //to run every 16.6666ms
}
delay(20);
}
else {
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
emu_Step();
//delay(20);
//delay(16);
}
}
#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

Wyświetl plik

@ -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 240
#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

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1,9 @@
#ifndef TYPES_H
#define TYPES_H
typedef unsigned char Byte;
typedef unsigned short ADDRESS;
#define INLINE
#endif /* TYPES_H */

Wyświetl plik

@ -0,0 +1,468 @@
/*
* O2EM Freeware Odyssey2 / Videopac+ Emulator
*
* Created by Daniel Boris <dboris@comcast.net> (c) 1997,1998
*
* Developed by Andre de la Rocha <adlroc@users.sourceforge.net>
*
* http://o2em.sourceforge.net
*
*
*
* O2 Video Display Controller emulation
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "types.h"
#include "vmachine.h"
#include "config.h"
#include "cset.h"
#include "cpu.h"
#include "vpp.h"
#include "vdc.h"
#include "emuapi.h"
typedef struct
{
unsigned char r;
unsigned char g;
unsigned char b;
} PALETTE_ENTRY;
#define COL_SP0 0x01
#define COL_SP1 0x02
#define COL_SP2 0x04
#define COL_SP3 0x08
#define COL_VGRID 0x10
#define COL_HGRID 0x20
#define COL_VPP 0x40
#define COL_CHAR 0x80
#define X_START 8
#define Y_START 24
static const long colortable[16]={
0x000000,
0x0e3dd4,
0x00981b,
0x00bbd9,
0xc70008,
0xcc16b3,
0x9d8710,
0xe1dee1,
0x5f6e6b,
0x6aa1ff,
0x3df07a,
0x31ffff,
0xff4255,
0xff98ff,
0xd9ad5d,
0xffffff
};
/* The pointer to the graphics buffer And palette */
static PALETTE_ENTRY colors[256];
static Byte * vscreen=0; //[BMPW*BMPH];
/* Collision buffer */
static Byte * colbuf=0; //[BMPW*BMPH];
Byte coltab[256];
long clip_low;
long clip_high;
static void create_cmap(void);
static void draw_char(Byte ypos,Byte xpos,Byte chr,Byte col);
static void draw_grid(void);
INLINE extern void mputvid(unsigned int ad, unsigned int len, Byte d, Byte c);
unsigned char * getGBuf(void)
{
return(vscreen);
}
void draw_region(void){
int i;
//emu_printi(last_line);
if (regionoff == 0xffff)
i = master_clk/(LINECNT-1)-5;
else
i = master_clk/22+regionoff;
//i = snapline(i, VDCwrite[0xA0], 0);
if (i<0) i=0;
#ifdef HALFHEIGHT
i = i>>1;
#else
#endif
clip_low = last_line * (long)BMPW;
clip_high = i * (long)BMPW;
if (clip_high > BMPW*BMPH) clip_high = BMPW*BMPH;
if (clip_low < 0) clip_low=0;
if (clip_low < clip_high) draw_display();
last_line=i;
}
#define fastmputvid1(ad,d,c) if ((ad > (unsigned long)clip_low) && (ad < (unsigned long)clip_high)) { vscreen[ad]=d; colbuf[ad] |= c; coltab[c] |= colbuf[ad];}
#define fastmputvid2(ad,d,c) if ((ad > (unsigned long)clip_low) && (ad < (unsigned long)clip_high)) { vscreen[ad]=d; colbuf[ad] |= c; coltab[c] |= colbuf[ad];vscreen[ad+1]=d; colbuf[ad+1] |= c; coltab[c] |= colbuf[ad+1];}
//#define fastmputvid1(ad,d,c) mputvid(ad,1,d,c);
//#define fastmputvid2(ad,d,c) mputvid(ad,2,d,c);
INLINE void mputvid(unsigned int ad, unsigned int len, Byte d, Byte c){
if ((ad > (unsigned long)clip_low) && (ad < (unsigned long)clip_high)) {
unsigned int i;
// JMH
Byte d1;
d1 = d;
if ( ((len & 3)==0) && (sizeof(unsigned long) == 4) && ((ad & 3) == 0) )
{
unsigned long dddd = (((unsigned long)d1) & 0xff) | ((((unsigned long)d1) & 0xff) << 8) | ((((unsigned long)d1) & 0xff) << 16) | ((((unsigned long)d1) & 0xff) << 24);
unsigned long cccc = (((unsigned long)c) & 0xff) | ((((unsigned long)c) & 0xff) << 8) | ((((unsigned long)c) & 0xff) << 16) | ((((unsigned long)c) & 0xff) << 24);
for (i=0; i<len>>2; i++) {
*((unsigned long*)(vscreen+ad)) = dddd;
cccc |= *((unsigned long*)(colbuf+ad));
*((unsigned long*)(colbuf+ad)) = cccc;
coltab[c] |= ((cccc | (cccc >> 8) | (cccc >> 16) | (cccc >> 24)) & 0xff);
ad += 4;
}
} else
{
for (i=0; i<len; i++) {
vscreen[ad]=d1;
colbuf[ad] |= c;
coltab[c] |= colbuf[ad++];
}
}
}
}
static void create_cmap(void){
int i;
/* Initialise parts of the colors array */
for (i = 0; i < 16; i++) {
/* Use the color values from the color table */
colors[i+32].r = colors[i].r = (colortable[i] & 0xff0000) >> 16; //18;
colors[i+32].g = colors[i].g = (colortable[i] & 0x00ff00) >> 8; //10;
colors[i+32].b = colors[i].b = (colortable[i] & 0x0000ff) >> 0; //2;
}
for (i = 16; i < 32; i++) {
/* Half-bright colors for the 50% scanlines */
colors[i+32].r = colors[i].r = colors[i-16].r/2;
colors[i+32].g = colors[i].g = colors[i-16].g/2;
colors[i+32].b = colors[i].b = colors[i-16].b/2;
}
for (i = 64; i < 256; i++) colors[i].r = colors[i].g = colors[i].b = 0;
for (i=0;i<256;i++)
{
emu_SetPaletteEntry(colors[i].r, colors[i].g, colors[i].b, i);
}
}
static void draw_char(Byte ypos,Byte xpos,Byte chr,Byte col){
int j,c;
Byte cl,d1;
int y,b,n;
unsigned int pnt;
#ifdef HALFHEIGHT
y = ypos>>1;
#else
y=(ypos & 0xFE);
#endif
pnt = y * BMPW + (xpos-8)+BORDERW;
ypos = ypos >> 1;
n = 8 - (ypos % 8) - (chr % 8);
if (n < 3) n = n + 7;
#ifdef HALFHEIGHT
if ((pnt+BMPW*n >= (unsigned long)clip_low) && (pnt <= (unsigned long)clip_high)) {
#else
if ((pnt+BMPW*2*n >= (unsigned long)clip_low) && (pnt <= (unsigned long)clip_high)) {
#endif
c=(int)chr + ypos;
if (col & 0x01) c+=256;
if (c > 511) c=c-512;
cl = ((col & 0x0E) >> 1);
cl = ((cl&2) | ((cl&1)<<2) | ((cl&4)>>2)) + 8;
#ifdef HALFHEIGHT
if ((y>0) && (y<112) && (xpos<157)) {
#else
if ((y>0) && (y<232) && (xpos<157)) {
#endif
for (j=0; j<n; j++) {
d1 = cset[c+j];
for (b=0; b<8; b++) {
if (d1 & 0x80) {
#ifdef HALFHEIGHT
if ((xpos-8+b < 160) && (y+j < 120)) {
#else
if ((xpos-8+b < 160) && (y+j < 240)) {
#endif
fastmputvid1(pnt,cl,COL_CHAR);
#ifdef HALFHEIGHT
#else
fastmputvid1(pnt+BMPW,cl,COL_CHAR);
#endif
}
}
pnt+=1;
d1 = d1 << 1;
}
#ifdef HALFHEIGHT
pnt += BMPW-8;
#else
pnt += BMPW*2-8;
#endif
}
}
}
}
static void draw_grid(void){
unsigned int pnt, pn1;
Byte mask,d;
int j,i,x,w;
Byte color;
if (VDCwrite[0xA0] & 0x40) {
for(j=0; j<9; j++) {
#ifdef HALFHEIGHT
pnt = (((j*12)+12) * BMPW);
#else
pnt = (((j*24)+24) * BMPW);
#endif
for (i=0; i<9; i++) {
pn1 = pnt + (i * 16) + BORDERW;
color = ColorVector[j*24+24];
fastmputvid2(pn1, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_HGRID);
color = ColorVector[j*24+25];
fastmputvid2(pn1+BMPW, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_HGRID);
#ifdef HALFHEIGHT
#else
color = ColorVector[j*24+26];
fastmputvid2(pn1+BMPW*2, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_HGRID);
#endif
}
}
}
// horizontal
mask=0x01;
for(j=0; j<9; j++) {
#ifdef HALFHEIGHT
pnt = (((j*12)+12) * BMPW);
#else
pnt = (((j*24)+24) * BMPW);
#endif
for (i=0; i<9; i++) {
pn1 = pnt + (i * 16) + BORDERW;
#ifdef HALFHEIGHT
if ((pn1+BMPW*2 >= (unsigned long)clip_low) && (pn1 <= (unsigned long)clip_high)) {
#else
if ((pn1+BMPW*3 >= (unsigned long)clip_low) && (pn1 <= (unsigned long)clip_high)) {
#endif
d=VDCwrite[0xC0 + i];
if (j == 8) {
d=VDCwrite[0xD0+i];
mask=1;
}
if (d & mask) {
color = ColorVector[j*24+24];
mputvid(pn1, 18, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_HGRID);
color = ColorVector[j*24+25];
mputvid(pn1+BMPW, 18, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_HGRID);
#ifdef HALFHEIGHT
#else
color = ColorVector[j*24+26];
mputvid(pn1+BMPW*2, 18, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_HGRID);
#endif
}
}
}
mask = mask << 1;
}
// vertical
mask=0x01;
w=2;
if (VDCwrite[0xA0] & 0x80) w=16;
for(j=0; j<10; j++) {
pnt=(j*16);
mask=0x01;
d=VDCwrite[0xE0+j];
for (x=0; x<8; x++) {
#ifdef HALFHEIGHT
pn1 = pnt + (((x*12)+12) * BMPW) + BORDERW;
#else
pn1 = pnt + (((x*24)+24) * BMPW) + BORDERW;
#endif
if (d & mask) {
#ifdef HALFHEIGHT
for(i=0; i<12; i++) {
#else
for(i=0; i<24; i++) {
#endif
if ((pn1 >= (unsigned long)clip_low) && (pn1 <= (unsigned long)clip_high)) {
color = ColorVector[x*24+24+i];
mputvid(pn1, w, (color & 0x07) | ((color & 0x40) >> 3) | (color & 0x80 ? 0 : 8), COL_VGRID);
}
pn1+=BMPW;
}
}
mask = mask << 1;
}
}
}
void finish_display(void){
vpp_finish_bmp(vscreen, 9, 5, BMPW-9, BMPH-5, BMPW, BMPH);
}
void clear_collision(void){
load_colplus(colbuf);
coltab[0x01]=coltab[0x02]=0;
coltab[0x04]=coltab[0x08]=0;
coltab[0x10]=coltab[0x20]=0;
coltab[0x40]=coltab[0x80]=0;
}
void draw_display(void){
int i,j,x,sm,t;
Byte y,xt,yt,b,d1,cl,c;
unsigned int pnt,pnt2;
#ifdef HALFHEIGHT
for (i=clip_low/BMPW; i<clip_high/BMPW; i++) {
memset(vscreen+i*BMPW, ((ColorVector[i<<1] & 0x38) >> 3) | (ColorVector[i<<1] & 0x80 ? 0 : 8), BMPW);
}
#else
for (i=clip_low/BMPW; i<clip_high/BMPW; i++) {
memset(vscreen+i*BMPW, ((ColorVector[i] & 0x38) >> 3) | (ColorVector[i] & 0x80 ? 0 : 8), BMPW);
}
#endif
if (VDCwrite[0xA0] & 0x08) draw_grid();
if (useforen && (!(VDCwrite[0xA0] & 0x20))) return;
for(i=0x10; i<0x40; i+=4) draw_char(VDCwrite[i],VDCwrite[i+1],VDCwrite[i+2],VDCwrite[i+3]);
pnt=0x40;
for(i=0; i<4; i++) {
x=y=248;
for (j=0; j<4; j++){
xt = VDCwrite[pnt+j*4+1];
yt = VDCwrite[pnt+j*4];
if ((xt<240) && (yt<240)){
x=xt;
y=yt;
break;
}
}
for(j=0; j<4; j++) {
draw_char(y,x,VDCwrite[pnt+2],VDCwrite[pnt+3]);
x+=16;
pnt+=4;
}
}
c=8;
for (i=12; i>=0; i -=4) {
pnt2 = 0x80 + (i * 2);
#ifdef HALFHEIGHT
y = VDCwrite[i]>>1;
#else
y = VDCwrite[i];
#endif
x = VDCwrite[i+1]-8;
t = VDCwrite[i+2];
cl = ((t & 0x38) >> 3);
cl = ((cl&2) | ((cl&1)<<2) | ((cl&4)>>2)) + 8;
//#ifdef HALFHEIGHT
// if ((x<164) && (y>0) && (y<112)) {
//#else
if ((x<164) && (y>0) && (y<232)) {
//#endif
pnt = y * BMPW + x + BORDERW + sproff;
if ((pnt+BMPW*16 >= (unsigned long)clip_low) && (pnt <= (unsigned long)clip_high)) {
for (j=0; j<8; j++) {
sm = (((j%2==0) && (((t>>1) & 1) != (t & 1))) || ((j%2==1) && (t & 1))) ? 1 : 0;
d1 = VDCwrite[pnt2++];
for (b=0; b<8; b++) {
if (d1 & 0x01) {
#ifdef HALFHEIGHT
if ((x+b+sm<160) && (y+j<129)) {
#else
if ((x+b+sm<160) && (y+j<249)) {
#endif
fastmputvid1(sm+pnt,cl,c);
#ifdef HALFHEIGHT
#else
fastmputvid1(sm+pnt+BMPW,cl,c);
#endif
}
}
pnt += 1;
d1 = d1 >> 1;
}
#ifdef HALFHEIGHT
pnt += BMPW-8;
#else
pnt += BMPW*2-8;
#endif
}
}
}
c = c >> 1;
}
}
void close_display(void)
{
}
void init_display(void)
{
if (vscreen==0) vscreen = (Byte *)emu_Malloc(BMPW*BMPH);
if (colbuf == 0) colbuf = (Byte *)emu_Malloc(BMPW*BMPH);
create_cmap();
memset(colbuf,0,BMPW*BMPH);
}

Wyświetl plik

@ -0,0 +1,28 @@
#ifndef __VDC_H
#define __VDC_H
//#define HALFHEIGHT 1
#define BORDERW 8
#define BMPW (160+BORDERW) // 320
#ifdef HALFHEIGHT
#define BMPH 120
#else
#define BMPH 240
#endif
extern Byte coltab[];
extern long clip_low;
extern long clip_high;
extern unsigned char * getGBuf(void);
void init_display(void);
void draw_display(void);
void draw_region(void);
void finish_display();
void close_display(void);
void clear_collision(void);
#endif

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1,680 @@
/*
* O2EM Freeware Odyssey2 / Videopac+ Emulator
*
* Created by Daniel Boris <dboris@comcast.net> (c) 1997,1998
*
* Developed by Andre de la Rocha <adlroc@users.sourceforge.net>
*
* http://o2em.sourceforge.net
*
*
*
* Main O2 machine emulation
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "audio.h"
#include "types.h"
#include "cpu.h"
#include "config.h"
#include "vdc.h"
//#include "vpp.h"
#include "vmachine.h"
#include "emuapi.h"
static Byte x_latch,y_latch;
static Byte line_count;
static int fps=FPS_NTSC;
//static Byte snapedlines[MAXLINES+2*MAXSNAP][256][2]; //500+2*50 *256*2 600*512
int evblclk=EVBLCLK_NTSC;
struct resource app_data;
int frame=0;
Byte dbstick1,dbstick2;
int int_clk; /* counter for length of /INT pulses */
int master_clk; /* Master clock */
int h_clk; /* horizontal clock */
unsigned long clk_counter;
int last_line;
int key2vcnt=0;
int mstate;
int ccolflag=0;
int pendirq=0;
int enahirq=1;
int useforen=0;
long regionoff=0xffff;
int mxsnap=2;
int sproff=0;
int tweakedaudio=0;
Byte rom1[5120];
Byte rom2[5120];
Byte rom3[5120];
Byte rom4[5120];
Byte intRAM[64];
Byte extRAM[256];
Byte extROM[1024];
Byte VDCwrite[256];
Byte ColorVector[MAXLINES];
Byte AudioVector[MAXLINES];
Byte *rom, *orom;
int key2[128];
#define KEY_0 0
#define KEY_1 1
#define KEY_2 2
#define KEY_3 3
#define KEY_4 4
#define KEY_5 5
#define KEY_6 6
#define KEY_7 7
#define KEY_8 8
#define KEY_9 9
#define KEY_A 10
#define KEY_B 11
#define KEY_C 12
#define KEY_D 13
#define KEY_E 14
#define KEY_F 15
#define KEY_G 16
#define KEY_H 17
#define KEY_I 18
#define KEY_J 19
#define KEY_K 20
#define KEY_L 21
#define KEY_M 22
#define KEY_N 23
#define KEY_O 24
#define KEY_P 25
#define KEY_Q 26
#define KEY_R 27
#define KEY_S 28
#define KEY_T 29
#define KEY_U 30
#define KEY_V 31
#define KEY_W 32
#define KEY_X 33
#define KEY_Y 34
#define KEY_Z 35
#define KEY_PLUS 35
#define KEY_MINUS 36
#define KEY_SLASH 38
#define KEY_ASTERISK 39
#define KEY_SPACE 40
#define KEY_EQUALS 41
#define KEY_DEL 42
#define KEY_ENTER 43
#define KEY_STOP 44
#define KEY_SLASH_PAD 45
#define KEY_PLUS_PAD 46
static unsigned int key_map[6][8]= {
{KEY_0,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6,KEY_7},
{KEY_8,KEY_9,0,0,KEY_SPACE,KEY_SLASH,KEY_L,KEY_P},
{KEY_PLUS_PAD,KEY_W,KEY_E,KEY_R,KEY_T,KEY_U,KEY_I,KEY_O},
{KEY_Q,KEY_S,KEY_D,KEY_F,KEY_G,KEY_H,KEY_J,KEY_K},
{KEY_A,KEY_Z,KEY_X,KEY_C,KEY_V,KEY_B,KEY_M,KEY_STOP},
{KEY_MINUS,KEY_ASTERISK,KEY_SLASH_PAD,KEY_EQUALS,KEY_Y,KEY_N,KEY_DEL,KEY_ENTER}
};
static void do_kluges(void);
static void setvideomode(int t);
void run(void){
cpu_exec();
}
static int ik; // joypad key
static int ihk; // I2C keyboard key
static int iusbhk; // USB keyboard key
static int prevhk; // previous keyboard key
void emu_KeyboardOnDown(int keymodifer, int key) {
int keyCode = -1; //INV_KEY;
if ((key >=0xc0) && (key <=0xdf)) {
keyCode = ((key-0xc0) & 0x1f) + 0x7f;
}
else {
keyCode = key & 0x7f;
}
//Serial.println(keyCode);
if (keyCode != -1) {
iusbhk = keyCode;
}
}
void emu_KeyboardOnUp(int keymodifer, int key) {
iusbhk = 0;
}
void odd_Input(int click) {
ik = emu_GetPad();
ihk = emu_ReadI2CKeyboard();
}
void handle_vbl(void){
update_audio();
// update_voice();
// }
if (!ccolflag) {
clear_collision();
ccolflag=1;
}
draw_region();
ext_IRQ();
mstate = 1;
}
void handle_evbl(void){
static long last=0;
static int rest_cnt=0;
int i;
i = (15*app_data.speed/100);
rest_cnt = (rest_cnt+1)%(i<5?5:i);
last_line=0;
master_clk -= evblclk;
frame++;
ccolflag=0;
if (!app_data.debug) {
finish_display();
}
for (i=0; i<MAXLINES; i++) {
ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (p1 & 0x80);
AudioVector[i] = VDCwrite[0xAA];
}
if (key2vcnt++ > 10) {
key2vcnt=0;
for (i=0; i<128; i++) key2[i] = 0;
dbstick1 = dbstick2 = 0;
}
mstate=0;
}
void init_system(void){
int i,j,k;
last_line=0;
dbstick1=0x00;
dbstick2=0x00;
mstate=0;
master_clk=0;
h_clk=0;
line_count=0;
itimer=0;
clk_counter=0;
for(i=0; i<256; i++) {
VDCwrite[i]=0;
extRAM[i]=0;
}
for(i=0; i<64; i++) {
intRAM[i]=0;
}
for (i=0; i<MAXLINES; i++) AudioVector[i] = ColorVector[i] = 0;
ccolflag=0;
/*
for (i=0; i<MAXLINES+2*MAXSNAP; i++)
for (j=0; j<256; j++)
for (k=0; k<2; k++)
snapedlines[i][j][k]=0;
*/
for (i=0; i<128; i++) key2[i] = 0;
key2vcnt=0;
if (app_data.euro)
setvideomode(1);
else
setvideomode(0);
do_kluges();
//init_vpp();
}
Byte read_t1(void){
if ((h_clk > 16) || (master_clk > VBLCLK))
return 1;
else
return 0;
}
void write_p1(Byte d){
if ((d & 0x80) != (p1 & 0x80)) {
int i,l;
//l = snapline((int)((float)master_clk/22.0+0.5), VDCwrite[0xA3], 1);
for (i=l; i<MAXLINES; i++) ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (d & 0x80);
}
p1 = d;
if (app_data.bank == 2) {
if (p1 & 0x01)
rom=rom2;
else
rom=rom1;
}
if (app_data.bank == 3) {
switch(p1 & 0x03) {
case 0:
rom=rom1;
break;
case 1:
rom=rom2;
break;
case 2:
rom=rom3;
break;
case 3:
rom=rom4;
break;
}
}
}
Byte read_P2(void){
int i,si,so,km;
int k=ik&0x7f;
int hk = ihk; //&0x7f;
if (iusbhk) hk = iusbhk;
if (k & MASK_KEY_USER1) { // 1
k = 1;
}
switch(hk) {
case 'q':
case '1':
hk = 2;
break;
case 'w':
case '2':
hk = 3;
break;
case 'e':
case '3':
hk = 4;
break;
case 'r':
case '4':
hk = 5;
break;
case 't':
case '5':
hk = 6;
break;
case 'y':
case '6':
hk = 7;
break;
case 'u':
case '7':
hk = 8;
break;
case 'i':
case '8':
hk = 9;
break;
case 'o':
case '9':
hk = 10;
case 'p':
case '0':
hk = 1;
break;
default:
hk = 0;
break;
};
if (!(p1 & 0x04)) {
si = (p2 & 7);
so=0xff;
if (si<6) {
for (i=0; i<8; i++) {
km = key_map[si][i];
if ( (km == (k-1)) && (k) )
{
so = i ^ 0x07;
}
else if ( (km == (hk-1)) && (hk) )
{
so = i ^ 0x07;
}
// if ((key[km] && ((!joykeystab[km]) || (key_shifts & KB_CAPSLOCK_FLAG))) || (key2[km])) {
// so = i ^ 0x07;
// }
}
}
if (so != 0xff) {
p2 = p2 & 0x0F;
p2 = p2 | (so << 5);
} else {
p2 = p2 | 0xF0;
}
} else {
p2 = p2 | 0xF0;
}
return(p2);
}
Byte ext_read(ADDRESS adr){
Byte d;
Byte si;
Byte m;
int i;
if (!(p1 & 0x08) && !(p1 & 0x40)) {
/* Handle VDC Read */
switch(adr) {
case 0xA1:
d = VDCwrite[0xA0] & 0x02;
if (master_clk > VBLCLK) d = d | 0x08;
if (h_clk < (LINECNT-7)) d = d | 0x01;
if (sound_IRQ) d = d | 0x04;
sound_IRQ=0;
return d;
case 0xA2:
si = VDCwrite[0xA2];
m=0x01;
d=0;
for(i=0; i<8; i++) {
if (si & m) {
if (coltab[1] & m) d = d | (coltab[1] & (m ^ 0xFF));
if (coltab[2] & m) d = d | (coltab[2] & (m ^ 0xFF));
if (coltab[4] & m) d = d | (coltab[4] & (m ^ 0xFF));
if (coltab[8] & m) d = d | (coltab[8] & (m ^ 0xFF));
if (coltab[0x10] & m) d = d | (coltab[0x10] & (m ^ 0xFF));
if (coltab[0x20] & m) d = d | (coltab[0x20] & (m ^ 0xFF));
if (coltab[0x80] & m) d = d | (coltab[0x80] & (m ^ 0xFF));
}
m = m << 1;
}
return d;
case 0xA5:
if (!(VDCwrite[0xA0] & 0x02)) {
return x_latch;
}
else {
x_latch = h_clk * 12;
return x_latch;
}
case 0xA4:
if (!(VDCwrite[0xA0] & 0x02)) {
return y_latch;
}
else {
y_latch = master_clk/22;
if (y_latch > 241) y_latch=0xFF;
return y_latch;
}
default:
return VDCwrite[adr];
}
} else if (!(p1 & 0x10)) {
/* Handle ext RAM Read */
return extRAM[adr & 0xFF];
//} else if (!(p1 & 0x20)) {
// /* Read a Videopac+ register */
// return vpp_read(adr);
} else if (app_data.exrom && (p1 & 0x02)) {
/* Handle read from exrom */
return extROM[(p2 << 8) | (adr & 0xFF)];
}
return 0;
}
Byte in_bus(void){
Byte si=0,d=0,mode=0,jn=0;
int key;
if ((p1 & 0x08) && (p1 & 0x10)) {
/* Handle joystick read */
if (!(p1 & 0x04)) {
si = (p2 & 7);
}
d=0xFF;
/* Get current input */
key = ik;
app_data.stick[0]=0;
app_data.stick[1]=1;
/*
if ( emu_GetPad() & 0x80 )
{
app_data.stick[0]=1;
app_data.stick[1]=0;
}
else
{
app_data.stick[0]=0;
app_data.stick[1]=1;
}
if (si == 1) {
mode = app_data.stick[0];
jn = 0;
} else {
mode = app_data.stick[1];
jn = 1;
}
*/
mode=1;
//if (key & 0x8000) jn=1;
//else jn=0;
switch(mode) {
case 1:
if (key & MASK_JOY2_RIGHT) d &= 0xF7;
if (key & MASK_JOY2_LEFT) d &= 0xFD;
if (key & MASK_JOY2_UP) d &= 0xFE;
if (key & MASK_JOY2_DOWN) d &= 0xFB;
if (key & MASK_JOY2_BTN) d &= 0xEF;
break;
case 2:
/* Get current input */
// key = emu_GetPad();
// if (key & JKEY_PLEFT) d &= 0xF7;
// if (key & JKEY_PRIGHT) d &= 0xFD;
// if (key & JKEY_PUP) d &= 0xFE;
// if (key & JKEY_PDOWN) d &= 0xFB;
// if (key & JKEY_PSPACE) d &= 0xEF;
break;
}
if (si == 1) {
if (dbstick1) d = dbstick1;
} else {
if (dbstick2) d = dbstick2;
}
}
return d;
}
void ext_write(Byte dat, ADDRESS adr){
int i;
if (!(p1 & 0x08)) {
/* Handle VDC Write */
if (adr == 0xA0){
if ((VDCwrite[0xA0] & 0x02) && !(dat & 0x02)) {
y_latch = master_clk/22;
x_latch = h_clk * 12;
if (y_latch > 241) y_latch=0xFF;
}
if ((master_clk <= VBLCLK) && (VDCwrite[0xA0] != dat)) {
if (!ccolflag) {
clear_collision();
ccolflag=1;
}
draw_region();
}
} else if (adr == 0xA2) {
clear_collision();
ccolflag=1;
} else if (adr == 0xA3){
int l;
//l = snapline((int)((float)master_clk/22.0+0.5), dat, 1);
for (i=l; i<MAXLINES; i++) ColorVector[i] = (dat & 0x7f) | (p1 & 0x80);
} else if (adr == 0xAA) {
for (i=master_clk/22; i<MAXLINES; i++) AudioVector[i]=dat;
}
VDCwrite[adr]=dat;
} else if (!(p1 & 0x10) && !(p1 & 0x40)) {
adr = adr & 0xFF;
if (adr < 0x80) {
/* Handle ext RAM Write */
extRAM[adr] = dat;
} else {
/* Handle The Voice */
if (!(dat & 0x20))
{
//JMH reset_voice();
}
else {
//JMH
// if (adr == 0xE4)
// set_voice_bank(0);
// else if ((adr >= 0xE8) && (adr <= 0xEF))
// set_voice_bank(adr-0xE7);
// else if (((adr >= 0x80) && (adr <= 0xDF)) || ((adr >= 0xF0) && (adr <= 0xFF)))
// trigger_voice(adr);
}
}
//} else if (!(p1 & 0x20)) {
// /* Write to a Videopac+ register */
// vpp_write(dat,adr);
}
}
static void do_kluges(void){
if (app_data.crc == 0xA7344D1F) pendirq=1; /* Atlantis */
if (app_data.crc == 0xFB83171E) pendirq=1; /* Blockout*/
if (app_data.crc == 0x881CEAE4) pendirq=1; /* Wall Street */
if (app_data.crc == 0x9E42E766) useforen=1; /* Turtles */
if (app_data.crc == 0x1C750349) useforen=1; /* Turtles (European version) */
if (app_data.crc == 0x202F2749) useforen=1; /* Q*bert */
if (app_data.crc == 0xFB83171E) enahirq=0; /* Blockout*/
if (app_data.crc == 0xFB83171E) regionoff=1; /* Blockout*/
if (app_data.crc == 0x202F2749) regionoff=1; /* Q*bert */
if (app_data.crc == 0x5216771A) regionoff=1; /* Popeye */
if (app_data.crc == 0x0C2E4811) regionoff=12; /* Out of this World! / Helicopter Rescue! */
if (app_data.crc == 0x67069924) regionoff=11; /* Smithereens! */
if (app_data.crc == 0x44D1A8A5) regionoff=11; /* Smithereens! (European version) */
if (app_data.crc == 0xB936BD78) regionoff=12; /* Type & Tell */
if (app_data.crc == 0xDC30AD3D) regionoff=10; /* Dynasty! */
if (app_data.crc == 0x7810BAD5) regionoff=10; /* Dynasty! (European) */
if (app_data.crc == 0xA7344D1F) regionoff=0; /* Atlantis */
if (app_data.crc == 0xD0BC4EE6) regionoff=12; /* Frogger */
if (app_data.crc == 0x825976A9) regionoff=0; /* Mousing Cat 8kb */
if (app_data.crc == 0xF390BFEC) regionoff=0; /* Mousing Cat 4kb */
if (app_data.crc == 0x3BFEF56B) regionoff=1; /* Four in 1 Row! */
if (app_data.crc == 0x9BFC3E01) regionoff=10; /* Demon Attack */
if (app_data.crc == 0x6CEBAB74) regionoff=12; /* P.T. Barnum's Acrobats! (European version) */
if (app_data.crc == 0xE7B26A56) regionoff=12; /* P.T. Barnum's Acrobats! (European version - Extra keys) */
if (app_data.crc == 0xFB83171E) mxsnap=3; /* Blockout*/
if (app_data.crc == 0xA57E1724) mxsnap=12; /* Catch the Ball / Noughts and Crosses */
if (app_data.crc == 0xFD179F6D) mxsnap=3; /* Clay Pigeon! */
if (app_data.crc == 0x9BFC3E01) mxsnap=0; /* Demon Attack */
if (app_data.crc == 0x9C9DDDF9) mxsnap=3; /* Verkehr */
if (app_data.crc == 0x95936B07) mxsnap=3; /* Super Cobra */
if (app_data.crc == 0x881CEAE4) mxsnap=3; /* Wall Street */
if (app_data.crc == 0x9E42E766) mxsnap=0; /* Turtles */
if (app_data.crc == 0x1C750349) mxsnap=0; /* Turtles (European version) */
if (app_data.crc == 0xD0BC4EE6) mxsnap=3; /* Frogger */
if (app_data.crc == 0x3BFEF56B) mxsnap=6; /* Four in 1 Row! */
if (app_data.crc == 0xA7344D1F) setvideomode(1); /* Atlantis */
if (app_data.crc == 0x39E31BF0) setvideomode(1); /* Jake */
if (app_data.crc == 0x3351FEDA) setvideomode(1); /* Power Lords */
if (app_data.crc == 0x40AE062D) setvideomode(1); /* Power Lords (alternate) */
if (app_data.crc == 0xD158EEBA) setvideomode(1); /* Labirinth */
if (app_data.crc == 0x26B0FF5B) setvideomode(1); /* Nightmare */
if (app_data.crc == 0xDF36683F) setvideomode(1); /* Shark Hunter */
if (app_data.crc == 0xAF307559) setvideomode(1); /* Super Bee 8Kb */
if (app_data.crc == 0x9585D511) setvideomode(1); /* Super Bee 4Kb */
if (app_data.crc == 0x58FA6766) setvideomode(1); /* War of the Nerves */
if (app_data.crc == 0x58FA6766) setvideomode(1); /* War of the Nerves */
if (app_data.crc == 0x39989464) setvideomode(1); /* Hockey! / Soccer! */
if (app_data.crc == 0xB47F3E0B) setvideomode(1); /* Kill the Attacking Aliens Demo */
if (app_data.crc == 0x3BFEF56B) setvideomode(1); /* Four in 1 Row! */
if (app_data.crc == 0x68560DC7) setvideomode(1); /* Jopac Moto Crash */
if (app_data.crc == 0x202F2749) setvideomode(0); /* Q*bert */
if (app_data.crc == 0xFB83171E) setvideomode(0); /* Blockout*/
if (app_data.crc == 0x9BFC3E01) setvideomode(0); /* Demon Attack */
if (app_data.crc == 0x239DF97D) setvideomode(0); /* Pachinko! */
if ((app_data.crc == 0xF390BFEC) || (app_data.crc == 0x825976A9)){ /* Mousing Cat */
setvideomode(1);
evblclk=7642;
}
if (app_data.crc == 0xD0BC4EE6) { /* Frogger */
setvideomode(1);
evblclk=7642;
}
if ((app_data.crc == 0x2DCB77F0) || (app_data.crc == 0xF6882734)) { /* Depth Charge / Marksman */
setvideomode(1);
evblclk=9000;
}
if (app_data.crc == 0x881CEAE4) { /* Wall Street */
setvideomode(1);
evblclk=6100;
}
if (app_data.crc == 0xD0BC4EE6) tweakedaudio=1; /* Frogger */
if (app_data.crc == 0x5216771A) tweakedaudio=1; /* Popeye */
if (app_data.crc == 0xAFB23F89) tweakedaudio=1; /* Musician */
if (app_data.crc == 0xD3B09FEC) sproff=1; /* Volleyball! */
}
/*
int snapline(int pos, Byte reg, int t){
int i;
for (i=0; i<mxsnap; i++){
if (snapedlines[pos+MAXSNAP-i][reg][t]) return pos-i;
if (snapedlines[pos+MAXSNAP+i][reg][t]) return pos+i;
}
snapedlines[pos+MAXSNAP][reg][t]=1;
return pos;
}
*/
static void setvideomode(int t){
if (t) {
evblclk = EVBLCLK_PAL;
fps = FPS_PAL;
} else {
evblclk = EVBLCLK_NTSC;
fps = FPS_NTSC;
}
}

Wyświetl plik

@ -0,0 +1,91 @@
#ifndef VMACHINE_H
#define VMACHINE_H
#include "types.h"
#define LINECNT 21
#define MAXLINES 500
#define MAXSNAP 50
#define VBLCLK 5493
#define EVBLCLK_NTSC 5964
#define EVBLCLK_PAL 7259
#define FPS_NTSC 60
#define FPS_PAL 50
extern Byte dbstick1, dbstick2;
extern int last_line;
extern int evblclk;
extern int master_clk; /* Master clock */
extern int int_clk; /* counter for length of /INT pulses for JNI */
extern int h_clk; /* horizontal clock */
extern int mstate;
extern Byte rom1[];
extern Byte rom2[];
extern Byte rom3[];
extern Byte rom4[];
extern Byte intRAM[];
extern Byte extRAM[];
extern Byte extROM[];
extern Byte VDCwrite[256];
extern Byte ColorVector[MAXLINES];
extern Byte AudioVector[MAXLINES];
extern Byte *rom;
extern Byte *orom;
extern int frame;
extern int key2[128];
extern int key2vcnt;
extern unsigned long clk_counter;
extern int ccolflag;
extern int enahirq;
extern int pendirq;
extern int useforen;
extern long regionoff;
extern int sproff;
extern int tweakedaudio;
Byte read_P2(void);
int snapline(int pos, Byte reg, int t);
void ext_write(Byte dat, ADDRESS adr);
Byte ext_read(ADDRESS adr);
void handle_vbl(void);
void handle_evbl(void);
Byte in_bus(void);
void write_p1(Byte d);
Byte read_t1(void);
void init_system(void);
void run(void);
extern struct resource {
int bank;
int debug;
int stick[2];
int limit;
int sound_en;
int speed;
int wsize;
int fullscreen;
int scanlines;
int voice;
int svolume;
int vvolume;
int exrom;
int filter;
int euro;
int openb;
unsigned long crc;
char *window_title;
char *scshot;
} app_data;
#endif /* VMACHINE_H */

Wyświetl plik

@ -0,0 +1,488 @@
/*
* O2EM Freeware Odyssey2 / Videopac+ Emulator
*
* Created by Daniel Boris <dboris@comcast.net> (c) 1997,1998
*
* Developed by Andre de la Rocha <adlroc@users.sourceforge.net>
*
* http://o2em.sourceforge.net
*
*
*
* Videopac+ G7400 emulation
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "types.h"
#include "vmachine.h"
#include "vdc.h"
#include "vpp_cset.h"
#include "vpp.h"
#include "emuapi.h"
typedef struct
{
int w;
int h;
unsigned char * line;
// unsigned char line[320][250];
} BITMAP;
static void clear(BITMAP * bmp)
{
int i,j;
bmp->line = (unsigned char *)emu_Malloc(BMPW*(BMPH+10));
for(i=0;i<bmp->h;i++)
for(j=0;j<bmp->w;j++)
//bmp->line[i][j] = 0;
*bmp->line++ = 0;
}
static void vpp_draw_char(int x, int y, Byte ch, Byte c0, Byte c1, Byte ext, Byte dw, Byte dh, Byte ul);
static void vpp_update_screen(void);
static Byte LumReg = 0xff, TraReg = 0xff;
static BITMAP svppbmp;
static BITMAP * vppbmp = &svppbmp;
//static Byte *colplus = NULL;
//static Byte colplus[BMPW*BMPH];
static int vppon = 1;
static int vpp_cx = 0;
static int vpp_cy = 0;
static Byte vpp_data = 0;
static int inc_curs=1;
static int slice=0;
static int vpp_y0=0;
static Byte vpp_r=0;
static Byte dchars[2][960];
static Byte vpp_mem[40][32][4];
static int frame_cnt=0;
static int blink_st=0;
static int slicemode=0;
static int need_update=0;
Byte read_PB(Byte p){
p &= 0x3;
switch (p) {
case 0:
return LumReg >> 4;
break;
case 1:
return LumReg & 0xf;
break;
case 2:
return TraReg >> 4;
break;
case 3:
return TraReg & 0xf;
break;
}
return 0;
}
void write_PB(Byte p, Byte val){
p &= 0x3;
val &= 0xf;
switch (p) {
case 0:
LumReg = (val<<4) | (LumReg & 0xf);
break;
case 1:
LumReg = (LumReg & 0xf0) | val;
break;
case 2:
TraReg = (val<<4) | (TraReg & 0xf);
break;
case 3:
TraReg = (TraReg & 0xf0) | val;
break;
}
need_update = 1;
}
Byte vpp_read(ADDRESS adr){
Byte t;
switch (adr){
case 4:
return vpp_mem[vpp_cx][vpp_cy][1];
case 5:
if (slicemode) {
Byte ext, chr;
chr = vpp_mem[vpp_cx][vpp_cy][0];
ext = (vpp_mem[vpp_cx][vpp_cy][1] & 0x80) ? 1 : 0;
if (chr < 0xA0)
t = 0;
else {
t = dchars[ext][(chr-0xA0)*10+slice];
t = ((t&0x80)>>7) | ((t&0x40)>>5) | ((t&0x20)>>3) | ((t&0x10)>>1) | ((t&0x08)<<1) | ((t&0x04)<<3) | ((t&0x02)<<5) | ((t&0x01)<<7);
}
slice = (slice+1) % 10;
} else {
t = vpp_mem[vpp_cx][vpp_cy][0];
if (inc_curs) {
vpp_cx++;
if (vpp_cx >= 40) {
vpp_cx = 0;
vpp_cy++;
if (vpp_cy >= 24) vpp_cy = 0;
}
}
}
return t;
case 6:
return 0;
default:
return 0;
}
}
void vpp_write(Byte dat, ADDRESS adr){
switch (adr) {
case 0:
if (!slicemode) vpp_mem[vpp_cx][vpp_cy][1] = dat;
break;
case 1:
if (slicemode) {
Byte ext, chr;
chr = vpp_mem[vpp_cx][vpp_cy][0];
ext = (vpp_mem[vpp_cx][vpp_cy][1] & 0x80) ? 1 : 0;
if (chr >= 0xA0) dchars[ext][(chr-0xA0)*10+slice] = ((dat&0x80)>>7) | ((dat&0x40)>>5) | ((dat&0x20)>>3) | ((dat&0x10)>>1) | ((dat&0x08)<<1) | ((dat&0x04)<<3) | ((dat&0x02)<<5) | ((dat&0x01)<<7);
slice = (slice+1) % 10;
} else {
vpp_mem[vpp_cx][vpp_cy][0] = dat;
if ((dat>0x7f) && (dat<0xa0) && (!(vpp_mem[vpp_cx][vpp_cy][1] & 0x80))) {
vpp_mem[vpp_cx][vpp_cy][2] = dat;
vpp_mem[vpp_cx][vpp_cy][3] = vpp_mem[vpp_cx][vpp_cy][1];
} else {
vpp_mem[vpp_cx][vpp_cy][2] = vpp_mem[vpp_cx][vpp_cy][3] = 0;
}
if (inc_curs) {
vpp_cx++;
if (vpp_cx >= 40) {
vpp_cx = 0;
vpp_cy++;
if (vpp_cy >= 24) vpp_cy = 0;
}
}
}
break;
case 2:
vpp_data = dat;
break;
case 3:
switch (dat & 0xe0) {
case 0x00: /* plus_cmd_brow */
vpp_cy = vpp_data & 0x1f;
vpp_cx = 0;
break;
case 0x20: /* plus_cmd_loady */
vpp_cy = vpp_data & 0x1f;
break;
case 0x40: /* plus_cmd_loadx */
vpp_cx = vpp_data % 40;
break;
case 0x60: /* plus_cmd_incc */
vpp_cx++;
if (vpp_cx >= 40) {
vpp_cx = 0;
vpp_cy++;
if (vpp_cy >= 24) vpp_cy = 0;
}
break;
case 0x80: /* plus_cmd_loadm */
slicemode = 0;
slice = (vpp_data & 0x1f) % 10;
switch (vpp_data & 0xe0) {
case 0x00: /* plus_loadm_wr */
inc_curs = 1;
break;
case 0x20: /* plus_loadm_rd */
inc_curs = 1;
break;
case 0x40: /* plus_loadm_wrni */
inc_curs = 0;
break;
case 0x60: /* plus_loadm_rdni */
inc_curs = 0;
break;
case 0x80: /* plus_loadm_wrsl */
slicemode = 1;
break;
case 0xA0: /* plus_loadm_rdsl */
slicemode = 1;
break;
default:
break;
}
break;
case 0xA0: /* plus_cmd_loadr */
vpp_r = vpp_data;
break;
case 0xC0: /* plus_cmd_loady0 */
vpp_y0 = (vpp_data & 0x1f) % 24;
break;
default:
break;
}
break;
default:
break;
}
need_update = 1;
}
void vpp_finish_bmp(Byte *vmem, int offx, int offy, int w, int h, int totw, int toth){
int i, x, y, t, c, nc, clrx, clry;
int tcol[16], m[8] = {0x01, 0x10, 0x04, 0x40, 0x02, 0x20, 0x08, 0x80};
Byte *pnt, *pnt2, *pnt3;
if (vppon) {
//memset(colplus,0,BMPW*BMPH);
vppon=0;
}
if (TraReg == 0xff) return;
vppon=1;
frame_cnt--;
if (frame_cnt<=0) {
frame_cnt = 100;
blink_st = 1-blink_st;
need_update = 1;
}
if (need_update) vpp_update_screen();
for (i=0; i<8; i++) tcol[i] = tcol[i+8] = !(TraReg & m[i]);
if (w > totw-offx) w = totw-offx;
if (h > toth-offy) h = toth-offy;
if (w > vppbmp->w) w = vppbmp->w;
if (h > vppbmp->h) h = vppbmp->h;
clrx = clry = 0;
for (i=0; (!clrx) && (i<totw); i++) if (tcol[vmem[offy*totw+i]&7]) clrx=1;
for (i=0; (!clry) && (i<toth); i++) if (tcol[vmem[i*totw+offx]&7]) clry=1;
if (clrx) for (y=0; y<offy; y++) for (x=0; x<totw; x++) vmem[y*totw+x]=0;
if (clry) for (y=0; y<toth; y++) for (x=0; x<offx; x++) vmem[y*totw+x]=0;
for (y=0; y<h; y++){
pnt = vmem+(offy+y)*totw + offx;
// pnt2 = (Byte *)vppbmp->line[y];
pnt2 = (Byte *)&vppbmp->line[y*320];
x=0;
while (x < w) {
pnt3 = pnt;
c = *pnt++;
t = x++;
if ((((x+offx) & 3) == 0) && (sizeof(unsigned long)==4)) {
unsigned long cccc, dddd, *p = (unsigned long*) pnt;
int t2=x, w2=w-4;
cccc = (((unsigned long)c) & 0xff) | ((((unsigned long)c) & 0xff) << 8) | ((((unsigned long)c) & 0xff) << 16) | ((((unsigned long)c) & 0xff) << 24);
dddd = *p++;
while ((x<w2) && (dddd == cccc)) {
x += 4;
dddd = *p++;
}
pnt += x-t2;
}
if (c<16) {
if (tcol[c]){
if (app_data.openb)
for (i=0; i<x-t; i++) *pnt3++ = *pnt2++ & 0xf;
else {
memcpy(pnt3, pnt2, x-t);
pnt2 += x-t;
}
} else {
for (i=0; i<x-t; i++) {
nc = *pnt2++;
if ((nc & 0x10) && app_data.openb) {
*pnt3++ = nc & 0xf;
} else if (nc & 8) {
//colplus[pnt3++ - vmem] = 0x40;
} else {
pnt3++;
}
}
}
}
}
}
}
static void vpp_draw_char(int x, int y, Byte ch, Byte c0, Byte c1, Byte ext, Byte dw, Byte dh, Byte ul){
int xx, yy, d, m, k;
if ((x>39) || (y>24) || (ext>1)) return;
d = (dh==2) ? 5 : 0;
for (yy=0; yy<10; yy++) {
if (ul && (d==9))
k = 255;
else if (ch >= 0xA0)
k = dchars[ext][(ch-0xA0)*10 + d];
else if (ch >= 0x80)
k = 255;
else
k = vpp_cset[ext][ch * 10 + d];
m = (dw==2) ? 0x08 : 0x80;
for (xx=0; xx<8; xx++) {
//vppbmp->line[y*10+yy][x*8+xx] = (k & m) ? c1 : c0;
vppbmp->line[(y*10+yy)*320+ x*8+xx] = (k & m) ? c1 : c0;
if ((xx%2) || (dw==0)) m >>= 1;
}
if ((yy%2) || (dh==0)) d++;
}
}
static void vpp_update_screen(void){
int i,x,y,l,chr,attr,ext,c0,c1,dw,dh,hpar,vpar,lvd,lhd,ser_chr,ser_atr,ul,conc,box;
int tlum[8], m[8] = {0x01, 0x10, 0x04, 0x40, 0x02, 0x20, 0x08, 0x80};
clear(vppbmp);
for (i=0; i<8; i++) tlum[i] = (LumReg & m[i]) ? 0 : 8;
vpar = lvd = 0;
for (y=0; y<25; y++) {
vpar = (lvd==0) ? 0 : 1-vpar;
l = (y==0) ? 31 : (y-1+vpp_y0)%24;
c0 = ul = conc = box = 0;
hpar = lhd = 0;
for (x=0; x<40; x++) {
hpar = (lhd==0) ? 0 : 1-hpar;
chr = vpp_mem[x][l][0];
attr = vpp_mem[x][l][1];
c1 = attr & 0x7;
c1 = ((c1&2) | ((c1&1)<<2) | ((c1&4)>>2));
ext = (attr & 0x80) ? 1 : 0;
ser_chr = vpp_mem[x][l][2];
ser_atr = vpp_mem[x][l][3];
if (ser_chr) {
c0 = (ser_atr>>4) & 0x7;
c0 = ((c0&2) | ((c0&1)<<2) | ((c0&4)>>2));
ul = ser_chr & 4;
conc = ser_chr & 1;
box = ser_chr & 2;
}
if (ext) {
c0 = (attr>>4) & 0x7;
c0 = ((c0&2) | ((c0&1)<<2) | ((c0&4)>>2));
dw = dh = 0;
} else {
dw = (attr & 0x20) ? (hpar ? 2 : 1) : 0;
dh = (attr & 0x10) ? (vpar ? 2 : 1) : 0;
if (dw) lhd=1;
if (dh) lvd=1;
}
if ((vpp_r & 0x80) && (!(attr & 8)) && (!blink_st)) c1=c0;
if (((y == 0) && (vpp_r & 8)) || ((y != 0) && (vpp_r & 1))) {
if ((!conc) || (!(vpp_r & 4))) {
if (box || (!(vpp_r & 2))) {
if ((!ext) && (attr & 0x40))
vpp_draw_char(x, y, chr, c1|tlum[c1], c0|tlum[c0], ext, dw, dh, ul);
else
vpp_draw_char(x, y, chr, c0|tlum[c0], c1|tlum[c1], ext, dw, dh, ul);
} else {
vpp_draw_char(x, y, 255, (app_data.openb) ? 16 : 0, 0, 0, 0, 0, 0);
}
}
}
}
}
if (vpp_r & 0x20) {
for (y = vppbmp->h-1; y >= 10; y--)
// for (x = 0; x < vppbmp->w; x++) vppbmp->line[y][x] = vppbmp->line[(y-10)/2+10][x];
for (x = 0; x < vppbmp->w; x++) vppbmp->line[y*320+x] = vppbmp->line[((y-10)/2+10)*320 + x];
}
need_update=0;
}
void load_colplus(Byte *col){
if (vppon) {
//memcpy(col,colplus,BMPW*BMPH);
}
else
memset(col,0,BMPW*BMPH);
}
void init_vpp(void){
int i,j,k;
vppbmp->w = 320;
vppbmp->h = 250;
// if ((!vppbmp) || (!colplus)) {
// fprintf(stderr,"Could not allocate memory for Videopac+ screen buffer.\n");
// exit(EXIT_FAILURE);
// }
clear(vppbmp);
//memset(colplus,0,BMPW*BMPH);
LumReg = TraReg = 0xff;
vpp_cx = 0;
vpp_cy = 0;
vpp_y0 = 0;
vpp_r = 0;
inc_curs = 1;
vpp_data = 0;
frame_cnt=0;
blink_st=0;
slice = 0;
slicemode=0;
need_update = 1;
vppon = 1;
for (i=0; i<2; i++)
for (j=0; j<960; j++) dchars[i][j] = 0;
for (i=0; i<40; i++)
for (j=0; j<32; j++)
for (k=0; k<4; k++) vpp_mem[i][j][k] = 0;
}

Wyświetl plik

@ -0,0 +1,12 @@
#ifndef __VPP_H
#define __VPP_H
Byte read_PB(Byte p);
void write_PB(Byte p, Byte val);
Byte vpp_read(ADDRESS adr);
void vpp_write(Byte dat, ADDRESS adr);
void vpp_finish_bmp(Byte *vmem, int offx, int offy, int w, int h, int totw, int toth);
void init_vpp(void);
void load_colplus(Byte *col);
#endif

Wyświetl plik

@ -0,0 +1,284 @@
/*
* O2EM Freeware Odyssey2 / Videopac+ Emulator
*
* Created by Daniel Boris <dboris@comcast.net> (c) 1997,1998
*
* Developed by Andre de la Rocha <adlroc@users.sourceforge.net>
*
* http://o2em.sourceforge.net
*
*
*
* Videopac+ character table
*/
#include "types.h"
#include "vpp_cset.h"
const Byte vpp_cset[2][1280] = {
{
/* Alphanumeric */
0x00,0x38,0x44,0x40,0x20,0x10,0x00,0x10,0x00,0x00,
0x00,0x10,0x28,0x00,0x38,0x44,0x7c,0x44,0x00,0x00,
0x00,0x08,0x10,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00,
0x00,0x08,0x14,0x10,0x38,0x10,0x24,0x3c,0x00,0x00,
0x00,0x10,0x38,0x50,0x38,0x14,0x54,0x38,0x10,0x00,
0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x10,0x20,
0x00,0x28,0x28,0x7c,0x28,0x7c,0x28,0x28,0x00,0x00,
0x00,0x20,0x18,0x00,0x38,0x44,0x7c,0x44,0x00,0x00,
0x00,0x20,0x18,0x00,0x44,0x44,0x44,0x38,0x00,0x00,
0x00,0x10,0x08,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00,
0x00,0x3c,0x50,0x50,0x58,0x50,0x50,0x3c,0x00,0x00,
0x00,0x08,0x14,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00,
0x00,0x00,0x10,0x20,0x7f,0x20,0x10,0x00,0x00,0x00,
0x00,0x10,0x38,0x54,0x10,0x10,0x10,0x10,0x10,0x10,
0x00,0x00,0x08,0x04,0xfe,0x04,0x08,0x00,0x00,0x00,
0x10,0x10,0x10,0x10,0x10,0x10,0x54,0x38,0x10,0x00,
0x00,0x18,0x24,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x10,0x10,0x7c,0x10,0x10,0x00,0x7c,0x00,0x00,
0x00,0x08,0x10,0x38,0x44,0x7c,0x40,0x38,0x00,0x00,
0x00,0x28,0x00,0x38,0x44,0x7c,0x40,0x38,0x00,0x00,
0x00,0x28,0x00,0x30,0x10,0x10,0x10,0x38,0x00,0x00,
0x00,0x00,0x00,0x38,0x40,0x40,0x40,0x38,0x10,0x20,
0x00,0x10,0x28,0x00,0x44,0x44,0x4c,0x34,0x00,0x00,
0x00,0x20,0x10,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00,
0x00,0x00,0x10,0x00,0x7c,0x00,0x10,0x00,0x00,0x00,
0x00,0x20,0x10,0x38,0x44,0x7c,0x40,0x38,0x00,0x00,
0x00,0x00,0x00,0x3c,0x52,0x5e,0x50,0x3e,0x00,0x00,
0x00,0x10,0x28,0x38,0x44,0x7c,0x40,0x38,0x00,0x00,
0x00,0x40,0xc0,0x40,0x44,0x4c,0x14,0x3e,0x04,0x00,
0x00,0x40,0xc0,0x40,0x4c,0x52,0x04,0x08,0x1e,0x00,
0x00,0xe0,0x20,0x40,0x24,0xcc,0x14,0x3e,0x04,0x00,
0x00,0x10,0x28,0x00,0x38,0x44,0x44,0x38,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00,
0x00,0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x28,0x00,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00,
0x00,0x10,0x28,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00,
0x00,0x60,0x64,0x08,0x10,0x20,0x4c,0x0c,0x00,0x00,
0x00,0x20,0x50,0x50,0x20,0x54,0x48,0x34,0x00,0x00,
0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x08,0x10,0x20,0x20,0x20,0x10,0x08,0x00,0x00,
0x00,0x20,0x10,0x08,0x08,0x08,0x10,0x20,0x00,0x00,
0x00,0x10,0x54,0x38,0x10,0x38,0x54,0x10,0x00,0x00,
0x00,0x00,0x10,0x10,0x7c,0x10,0x10,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x40,0x00,
0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,
0x01,0x02,0x02,0x04,0x08,0x10,0x20,0x20,0x40,0x80,
0x00,0x10,0x28,0x44,0x44,0x44,0x28,0x10,0x00,0x00,
0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x00,0x00,
0x00,0x38,0x44,0x04,0x18,0x20,0x40,0x7c,0x00,0x00,
0x00,0x7c,0x04,0x08,0x18,0x04,0x44,0x38,0x00,0x00,
0x00,0x08,0x18,0x28,0x48,0x7c,0x08,0x08,0x00,0x00,
0x00,0x7c,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00,
0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x38,0x00,0x00,
0x00,0x7c,0x04,0x08,0x10,0x20,0x20,0x20,0x00,0x00,
0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00,0x00,
0x00,0x38,0x44,0x44,0x3c,0x04,0x04,0x38,0x00,0x00,
0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,
0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x20,0x40,0x00,
0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x00,0x00,
0x00,0x00,0x00,0x7c,0x00,0x7c,0x00,0x00,0x00,0x00,
0x00,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00,0x00,
0x00,0x38,0x44,0x04,0x08,0x10,0x00,0x10,0x00,0x00,
0x00,0x38,0x44,0x5c,0x54,0x5c,0x40,0x38,0x00,0x00,
0x00,0x38,0x44,0x44,0x44,0x7c,0x44,0x44,0x00,0x00,
0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x78,0x00,0x00,
0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00,
0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00,
0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x7c,0x00,0x00,
0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x40,0x00,0x00,
0x00,0x38,0x44,0x40,0x40,0x4c,0x44,0x3c,0x00,0x00,
0x00,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x00,0x00,
0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,
0x00,0x1c,0x08,0x08,0x08,0x08,0x48,0x30,0x00,0x00,
0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00,
0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7c,0x00,0x00,
0x00,0x44,0x6c,0x54,0x44,0x44,0x44,0x44,0x00,0x00,
0x00,0x44,0x44,0x64,0x54,0x4c,0x44,0x44,0x00,0x00,
0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,
0x00,0x78,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00,
0x00,0x38,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00,
0x00,0x78,0x44,0x44,0x78,0x50,0x48,0x44,0x00,0x00,
0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00,
0x00,0x7c,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,
0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,
0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,
0x00,0x44,0x44,0x44,0x54,0x54,0x54,0x28,0x00,0x00,
0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00,
0x00,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00,
0x00,0x7c,0x04,0x08,0x10,0x20,0x40,0x7c,0x00,0x00,
0x00,0x1c,0x10,0x10,0x10,0x10,0x10,0x1c,0x00,0x00,
0x80,0x40,0x40,0x20,0x10,0x08,0x04,0x04,0x02,0x01,
0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x38,0x00,0x00,
0x00,0x10,0x28,0x00,0x30,0x10,0x10,0x38,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00,
0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x78,0x00,0x00,
0x00,0x00,0x00,0x38,0x40,0x40,0x40,0x38,0x00,0x00,
0x00,0x04,0x04,0x3c,0x44,0x44,0x44,0x3c,0x00,0x00,
0x00,0x00,0x00,0x38,0x44,0x7c,0x40,0x38,0x00,0x00,
0x00,0x18,0x24,0x20,0x70,0x20,0x20,0x20,0x00,0x00,
0x00,0x00,0x00,0x3c,0x44,0x44,0x3c,0x04,0x24,0x18,
0x00,0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x00,0x00,
0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x38,0x00,0x00,
0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x48,0x30,
0x00,0x20,0x20,0x24,0x28,0x30,0x28,0x24,0x00,0x00,
0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,
0x00,0x00,0x00,0x68,0x54,0x54,0x54,0x54,0x00,0x00,
0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x00,0x00,
0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x00,0x00,
0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,
0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x3c,0x04,0x04,
0x00,0x00,0x00,0x58,0x64,0x40,0x40,0x40,0x00,0x00,
0x00,0x00,0x00,0x38,0x40,0x38,0x04,0x78,0x00,0x00,
0x00,0x20,0x20,0x38,0x20,0x20,0x20,0x18,0x00,0x00,
0x00,0x00,0x00,0x44,0x44,0x44,0x4c,0x34,0x00,0x00,
0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x00,0x00,
0x00,0x00,0x00,0x44,0x44,0x54,0x54,0x28,0x00,0x00,
0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00,
0x00,0x00,0x00,0x44,0x44,0x4c,0x34,0x04,0x44,0x38,
0x00,0x00,0x00,0x7c,0x08,0x10,0x20,0x7c,0x00,0x00,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},
{
/* Separated semi-graphic */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,
0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,
0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,
0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00,
0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00,
0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00,
0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00,
0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00,
0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00,
0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00,
0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00,
0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00,
0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00,
0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00,
0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00,
0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00,
0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00,
0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00,
0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00,
0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00,
0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00,
0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00,
0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00,
0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00,
0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00,
0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00,
0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00,
0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00,
0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00,
0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00,
0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00,
0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00,
0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00,
0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00,
0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00,
0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00,
0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00,
0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00,
0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00,
0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00,
0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00,
0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00,
0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00,
0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00,
/* Mosaic semi-graphic */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,
0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,
0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,
0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,
0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,
0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,
0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,
0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,
0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,
0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,
0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,
0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,
0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,
0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,
0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,
0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,
0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0,
0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0,
0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,
0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,
0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,
0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,
0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,
0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,
0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,
0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,
0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,
0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,
0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,
0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,
0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0xff,0xff,0xff,
0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,
0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,
0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,
0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,
0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,
0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff,
0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff,
0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff,
0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff,
0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}
};

Wyświetl plik

@ -0,0 +1,6 @@
#ifndef __VPP_CSET_H
#define __VPP_CSET_H
extern const Byte vpp_cset[2][1280];
#endif

Wyświetl plik

@ -5,7 +5,6 @@ extern "C" {
#include "emu.h"
#include "emu.h"
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
TFT_T_DMA tft;