add T41 VGA supprt for all emus except st and amiga

This commit is contained in:
jean-marcharvengt 2020-09-28 21:11:50 +02:00
parent b11ae4b91b
commit cb094fe973
342 changed files with 19766 additions and 232327 deletions

View file

@ -195,4 +195,3 @@ void AudioPlaySystem::sound(int C, int F, int V) {
void AudioPlaySystem::step(void) {
}
#endif

View file

@ -455,6 +455,13 @@ static void Initialise(void)
cont2.analog_v = POT_CENTRE;
}
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
void at5_Init(void)
{
int i;
@ -593,9 +600,3 @@ void at5_Start(char * cartname)
emu_printf("init done");
}

View file

@ -5,8 +5,17 @@ extern "C" {
#include "iopins.h"
}
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
const uint16_t deflogo[] = {
0,0
};
static const uint16_t * logo = deflogo;
#else
#include "tft_t_dma.h"
#include "logo.h"
#endif
#include "bmpjoy.h"
#include "bmpvbar.h"
#ifdef OLD_LAYOUT
@ -19,6 +28,13 @@ extern "C" {
#include <Wire.h>
#endif
#ifdef HAS_USBKEY
#include "USBHost_t36.h" // Read this header first for key info
USBHost myusb;
KeyboardController keyboard1(myusb);
#endif
static uint8_t usbnavpad=0;
#ifdef USE_SDFS
#include "uSDFS.h"
static FATFS fatfs;
@ -84,7 +100,7 @@ static File file;
#define MKEY_TFT 23
#define MKEY_VGA 24
#define MAX_FILES 32
#define MAX_FILES 64
#define MAX_FILENAME_SIZE 24
#define MAX_MENULINES (MKEY_L9)
#define TEXT_HEIGHT 16
@ -93,7 +109,7 @@ static File file;
#define MENU_FILE_YOFFSET (2*TEXT_HEIGHT)
#define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH)
#define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x20)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40)
#define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT)
#define MENU_VBAR_XOFFSET (0*TEXT_WIDTH)
#define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET)
@ -113,13 +129,10 @@ static char selection[MAX_FILENAME_SIZE+1]="";
static char files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
static int16_t calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static bool i2cKeyboardPresent = false;
//const uint16_t deflogo[] = {
// 0x0000,0x0000
//};
//static const uint16_t * logo = deflogo;
static unsigned short * keys;
static int keyMap;
const unsigned short menutouchareas[] = {
TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET,
@ -245,7 +258,7 @@ void emu_printf(int val)
void emu_printi(int val)
{
Serial.println(val);
Serial.println(val,HEX);
}
void emu_printh(int val)
@ -272,13 +285,29 @@ void * emu_Malloc(int size)
}
}
else {
emu_printf("could allocate ");
emu_printf("could allocate dynamic ");
emu_printf(size);
}
return retval;
}
void * emu_MallocI(int size)
{
void * retval = NULL;
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
emu_printf("could allocate static ");
emu_printf(size);
}
else {
emu_printf("failure to allocate");
}
return retval;
}
void emu_Free(void * pt)
{
free(pt);
@ -400,6 +429,12 @@ int emu_ReadKeys(void)
retval = ((j2 << 8) | j1);
}
if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
#ifdef PIN_KEY_USER1
if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1;
#endif
@ -575,7 +610,7 @@ bool virtualkeyboardIsActive(void) {
void toggleVirtualkeyboard(bool keepOn) {
if (keepOn) {
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbKeepOn = true;
vkbActive = true;
@ -592,7 +627,7 @@ void toggleVirtualkeyboard(bool keepOn) {
}
else {
tft.stopDMA();
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbActive = true;
exitVkbd = false;
@ -637,7 +672,7 @@ void handleVirtualkeyboard() {
if (vkeyRefresh) {
vkeyRefresh = false;
tft.drawSpriteNoDma(0,0,(uint16_t*)logo, rx, ry, rw, rh);
tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh);
}
if ( (exitVkbd) && (vkbActive) ) {
@ -651,10 +686,6 @@ void handleVirtualkeyboard() {
}
int emu_setKeymap(int index) {
if (index) {
}
else {
}
}
@ -726,10 +757,12 @@ void backgroundMenu(void) {
menuRedraw=true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,(uint16_t*)bmpvbar);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,bmpvbar);
#endif
#ifdef OLD_LAYOUT
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,(uint16_t*)bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,(uint16_t*)bmpvga);
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,bmpvga);
#endif
}
@ -839,7 +872,7 @@ int handleMenu(uint16_t bClick)
strcpy(selection,filename);
}
else {
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, 0xFFFF, 0x0000, true);
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true);
}
}
i++;
@ -847,8 +880,10 @@ int handleMenu(uint16_t bClick)
fileIndex++;
}
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0xff,0x00,0x00), false);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
#endif
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false);
menuRedraw=false;
}
@ -1338,11 +1373,138 @@ void emu_FileTempWrite(int addr, unsigned char val)
#endif
}
#ifdef HAS_USBKEY
void OnPress(auto key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad |= MASK_JOY2_DOWN;
break;
case 218:
usbnavpad |= MASK_JOY2_UP;
break;
case 216:
usbnavpad |= MASK_JOY2_LEFT;
break;
case 215:
usbnavpad |= MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad |= MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnDown(keymodifier, key);
}
}
void OnRelease(int key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad &= ~MASK_JOY2_DOWN;
break;
case 218:
usbnavpad &= ~MASK_JOY2_UP;
break;
case 216:
usbnavpad &= ~MASK_JOY2_LEFT;
break;
case 215:
usbnavpad &= ~MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad &= ~MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnUp(keymodifier, key);
}
}
#endif
void emu_init(void)
{
Serial.begin(115200);
#ifdef HAS_USBKEY
myusb.begin();
keyboard1.attachPress(OnPress);
keyboard1.attachRelease(OnRelease);
#endif
#ifdef USE_SDFS
strcpy(romspath,SDFSDEV);
strcat(romspath,ROMSDIR);
@ -1387,7 +1549,11 @@ void emu_init(void)
{
toggleMenu(true);
}
}
void emu_start(void)
{
#ifdef HAS_I2CKBD
byte msg[7]={0,0,0,0,0,0,0};
Wire.begin(); // join i2c bus SDA2/SCL2
@ -1413,5 +1579,9 @@ void emu_init(void)
Serial.println("i2C keyboard found");
}
#endif
}
usbnavpad = 0;
keys = key_map1;
keyMap = 0;
}

View file

@ -1,13 +1,10 @@
#ifndef EMUAPI_H
#define EMUAPI_H
#define INVX 1
//#define INVY 1
#define HAS_SND 1
#define CUSTOM_SND 1
//#define HAS_I2CKBD 1
//#define TIMER_REND 1
#include "platform_config.h"
#define CUSTOM_SND 1
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
// Title: < >
@ -68,7 +65,7 @@ const unsigned short keysw[] = {
// [START] 12 [ 3 ] 13 [ 2 ] 14 [ 1 ] 15
const unsigned short keys[] = {
const unsigned short key_map1[] = {
12+1,8+1,4+1,
0,
15+1,14+1,13+1,
@ -108,6 +105,9 @@ const unsigned short i2ckeys[] = {
extern void emu_init(void);
extern void emu_start(void);
extern void emu_resetSD(void);
extern void emu_printf(char * text);
extern void emu_printi(int val);
extern void * emu_Malloc(int size);
@ -128,6 +128,7 @@ extern void emu_FileTempWrite(int addr, unsigned char val);
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_DrawLine8(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_DrawVsync(void);
extern int emu_FrameSkip(void);
@ -141,6 +142,9 @@ extern int emu_GetPad(void);
extern int emu_ReadAnalogJoyX(int min, int max);
extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
extern void emu_KeyboardOnUp(int keymodifer, int key);
extern void emu_KeyboardOnDown(int keymodifer, int key);
extern void emu_sndPlaySound(int chan, int volume, int freq);
extern void emu_sndPlayBuzz(int size, int val);
extern void emu_sndInit();
@ -149,9 +153,11 @@ extern int emu_us(void);
extern int emu_setKeymap(int index);
extern void emu_FileTempInit(void);
extern void emu_FileTempRead(int addr, unsigned char * val, int n);
extern void emu_FileTempWrite(int addr, unsigned char val);
extern void emu_printh(int val);
#endif

View file

@ -35,13 +35,26 @@
#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 38 // UP
#define PIN_JOY1_2 36 // DOWN
#define PIN_JOY1_3 35 // 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
//#define PIN_KEY_USER3 33
//#define PIN_KEY_USER4 39
// Second joystick
#define PIN_JOY1_BTN 2
@ -49,6 +62,7 @@
#define PIN_JOY1_2 7 // DOWN
#define PIN_JOY1_3 6 // RIGHT
#define PIN_JOY1_4 5 // LEFT
#endif
#else
// OLD LAYOUT!!!!
@ -87,7 +101,3 @@
#endif
#endif

View file

@ -2,15 +2,21 @@
#define _PLATFORM_CONFIG_H_
//#define OLD_LAYOUT 1
#define HAS_T4_VGA 1
#define ILI9341 1
#define HAS_SND 1
//#define INVX 1
//#define INVY 1
#define HAS_USBKEY 1
//#define ILI9341 1
//#define ST7789 1
//#define SWAP_JOYSTICK 1
//#define LOHRES 1
//#define ROTATE_SCREEN 1
#define EXTERNAL_SD 1
//#define EXTERNAL_SD 1
#define HAS_PSRAM 1
//#define HAS_PSRAM 1
//#define USE_SDFAT 1
//#define SD_FAT_TYPE 1

View file

@ -3,7 +3,6 @@ extern "C" {
#include "emuapi.h"
}
#include "keyboard_osd.h"
#include "tft_t_dma.h"
extern "C" {
#include "atari5200.h"
@ -36,7 +35,14 @@ uVGA uvga;
uint8_t * VGA_frame_buffer;
#endif
#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;
@ -60,7 +66,7 @@ void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int
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);
palette16[index] = RGBVAL16(r,g,b);
}
}
@ -70,7 +76,11 @@ void emu_DrawVsync(void)
skip += 1;
skip &= VID_FRAME_SKIP;
if (!vgaMode) {
#ifdef HAS_T4_VGA
tft.waitSync();
#else
while (vbl==vb) {};
#endif
}
#ifdef HAS_VGA
else {
@ -82,7 +92,11 @@ void emu_DrawVsync(void)
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
}
#ifdef HAS_VGA
else {
@ -100,11 +114,43 @@ void emu_DrawLine(unsigned char * VBuf, int width, int height, int line)
#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
}
}
#ifdef HAS_VGA
#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
}
}
#ifdef HAS_VGA
#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
}
}
#ifdef HAS_VGA
@ -154,8 +200,13 @@ void * emu_LineBuffer(int line)
// the setup() method runs once, when the sketch starts
// ****************************************************
void setup() {
tft.begin();
#ifdef HAS_T4_VGA
tft.begin(VGA_MODE_352x240);
// NVIC_SET_PRIORITY(IRQ_QTIMER3, 0);
#else
tft.begin();
#endif
emu_init();
myTimer.begin(vblCount, 20000); //to run every 20ms
@ -169,15 +220,16 @@ void loop(void)
if (menuActive()) {
uint16_t bClick = emu_DebounceLocalKeys();
int action = handleMenu(bClick);
char * filename = menuSelection();
char * filename = menuSelection();
if (action == ACTION_RUNTFT) {
toggleMenu(false);
vgaMode = false;
vgaMode = false;
emu_start();
emu_Init(filename);
//digitalWrite(TFT_CS, 1);
//digitalWrite(SD_CS, 1);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
tft.startDMA();
}
else if (action == ACTION_RUNVGA) {
#ifdef HAS_VGA
@ -185,6 +237,7 @@ void loop(void)
vgaMode = true;
VGA_frame_buffer = (uint8_t *)malloc((UVGA_YRES*(UVGA_XRES+UVGA_XRES_EXTRA))*sizeof(uint8_t));
uvga.set_static_framebuffer(VGA_frame_buffer);
emu_start();
emu_Init(filename);
int retvga = uvga.begin(&modeline);
Serial.println(retvga);
@ -225,8 +278,15 @@ void loop(void)
AudioPlaySystem mymixer;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#ifdef HAS_T4_VGA
AudioOutputI2S i2s1;
AudioConnection patchCord8(mymixer, 0, i2s1, 0);
AudioConnection patchCord9(mymixer, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
#else
AudioOutputMQS mqs;
AudioConnection patchCord9(mymixer, 0, mqs, 1);
#endif
#else
AudioOutputAnalog dac1;
AudioConnection patchCord1(mymixer, dac1);
@ -234,6 +294,10 @@ AudioConnection patchCord1(mymixer, dac1);
void emu_sndInit() {
Serial.println("sound init");
#ifdef HAS_T4_VGA
sgtl5000_1.enable();
sgtl5000_1.volume(0.6);
#endif
AudioMemory(16);
mymixer.start();
}

View file

@ -3,6 +3,9 @@
*/
#include "TFT_T_DMA.h"
#ifndef HAS_T4_VGA
#include "font8x8.h"
@ -1231,7 +1234,7 @@ void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap, uint16_
l++;
}
}
#endif

View file

@ -16,8 +16,8 @@
#define TFT_WIDTH 320 //640 //320
#define TFT_REALWIDTH 320 //640 //320
#define TFT_WIDTH 320
#define TFT_REALWIDTH 320
#define TFT_HEIGHT 240
#define TFT_REALHEIGHT 240
@ -44,8 +44,8 @@ class TFT_T_DMA: public VGA_T4
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 vga_pixel *bitmap) { drawSprite(x, y, bitmap); }
void drawSpriteNoDma(int16_t x, int16_t y, const vga_pixel *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); }
void drawSpriteNoDma(int16_t x, int16_t y, const int16_t *bitmap) { drawSprite(x, y, bitmap); }
void drawSpriteNoDma(int16_t x, int16_t y, const int16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); }
};

View file

@ -50,13 +50,18 @@
#define USBHOST (!PS2KEYBOARD)
#include "tft_t_dma.h"
extern TFT_T_DMA tft;
extern "C" {
#include "emuapi.h"
}
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
extern TFT_T_DMA tft;
void initMachine();
void resetMachine() __attribute__ ((noreturn));
void resetExternal();

View file

@ -1,7 +1,9 @@
extern "C" {
#include "emuapi.h"
#include "platform_config.h"
}
#include "Teensy64.h"
#include <string.h>
@ -251,7 +253,9 @@ void c64_Init(void)
resetCia2();
resetVic();
cpu_reset();
#ifdef HAS_SND
emu_sndInit();
#endif
}
@ -307,6 +311,12 @@ void c64_Input(int bClick) {
}
}
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
#ifdef HAS_SND
void SND_Process( void * stream, int len )
{

View file

@ -5,8 +5,17 @@ extern "C" {
#include "iopins.h"
}
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
const uint16_t deflogo[] = {
0,0
};
static const uint16_t * logo = deflogo;
#else
#include "tft_t_dma.h"
#include "logo.h"
#endif
#include "bmpjoy.h"
#include "bmpvbar.h"
#ifdef OLD_LAYOUT
@ -19,6 +28,13 @@ extern "C" {
#include <Wire.h>
#endif
#ifdef HAS_USBKEY
#include "USBHost_t36.h" // Read this header first for key info
USBHost myusb;
KeyboardController keyboard1(myusb);
#endif
static uint8_t usbnavpad=0;
#ifdef USE_SDFS
#include "uSDFS.h"
static FATFS fatfs;
@ -84,7 +100,7 @@ static File file;
#define MKEY_TFT 23
#define MKEY_VGA 24
#define MAX_FILES 32
#define MAX_FILES 64
#define MAX_FILENAME_SIZE 24
#define MAX_MENULINES (MKEY_L9)
#define TEXT_HEIGHT 16
@ -93,7 +109,7 @@ static File file;
#define MENU_FILE_YOFFSET (2*TEXT_HEIGHT)
#define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH)
#define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x20)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40)
#define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT)
#define MENU_VBAR_XOFFSET (0*TEXT_WIDTH)
#define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET)
@ -113,13 +129,10 @@ static char selection[MAX_FILENAME_SIZE+1]="";
static char files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
static int16_t calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static bool i2cKeyboardPresent = false;
//const uint16_t deflogo[] = {
// 0x0000,0x0000
//};
//static const uint16_t * logo = deflogo;
static unsigned short * keys;
static int keyMap;
const unsigned short menutouchareas[] = {
TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET,
@ -245,7 +258,7 @@ void emu_printf(int val)
void emu_printi(int val)
{
Serial.println(val);
Serial.println(val,HEX);
}
void emu_printh(int val)
@ -272,13 +285,29 @@ void * emu_Malloc(int size)
}
}
else {
emu_printf("could allocate ");
emu_printf("could allocate dynamic ");
emu_printf(size);
}
return retval;
}
void * emu_MallocI(int size)
{
void * retval = NULL;
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
emu_printf("could allocate static ");
emu_printf(size);
}
else {
emu_printf("failure to allocate");
}
return retval;
}
void emu_Free(void * pt)
{
free(pt);
@ -400,6 +429,12 @@ int emu_ReadKeys(void)
retval = ((j2 << 8) | j1);
}
if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
#ifdef PIN_KEY_USER1
if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1;
#endif
@ -454,6 +489,7 @@ int emu_ReadKeys(void)
}
#endif
}
return (retval);
}
@ -479,9 +515,9 @@ int emu_ReadI2CKeyboard(void) {
if (b != 0xff) hitindex=i;
msg[i++] = b;
}
if (hitindex >=0 ) {
/*
/*
Serial.println(msg[0], BIN);
Serial.println(msg[1], BIN);
Serial.println(msg[2], BIN);
@ -491,7 +527,7 @@ int emu_ReadI2CKeyboard(void) {
Serial.println(msg[6], BIN);
*/
unsigned short match = (~msg[hitindex])&0x00FF | (hitindex<<8);
Serial.println(match,HEX);
//Serial.println(match,HEX);
for (i=0; i<sizeof(i2ckeys); i++) {
if (match == i2ckeys[i]) {
//Serial.println((int)keys[i]);
@ -574,7 +610,7 @@ bool virtualkeyboardIsActive(void) {
void toggleVirtualkeyboard(bool keepOn) {
if (keepOn) {
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbKeepOn = true;
vkbActive = true;
@ -591,7 +627,7 @@ void toggleVirtualkeyboard(bool keepOn) {
}
else {
tft.stopDMA();
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbActive = true;
exitVkbd = false;
@ -636,7 +672,7 @@ void handleVirtualkeyboard() {
if (vkeyRefresh) {
vkeyRefresh = false;
tft.drawSpriteNoDma(0,0,(uint16_t*)logo, rx, ry, rw, rh);
tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh);
}
if ( (exitVkbd) && (vkbActive) ) {
@ -650,10 +686,6 @@ void handleVirtualkeyboard() {
}
int emu_setKeymap(int index) {
if (index) {
}
else {
}
}
@ -725,10 +757,12 @@ void backgroundMenu(void) {
menuRedraw=true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,(uint16_t*)bmpvbar);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,bmpvbar);
#endif
#ifdef OLD_LAYOUT
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,(uint16_t*)bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,(uint16_t*)bmpvga);
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,bmpvga);
#endif
}
@ -838,7 +872,7 @@ int handleMenu(uint16_t bClick)
strcpy(selection,filename);
}
else {
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, 0xFFFF, 0x0000, true);
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true);
}
}
i++;
@ -846,8 +880,10 @@ int handleMenu(uint16_t bClick)
fileIndex++;
}
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0xff,0x00,0x00), false);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
#endif
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false);
menuRedraw=false;
}
@ -1337,11 +1373,138 @@ void emu_FileTempWrite(int addr, unsigned char val)
#endif
}
#ifdef HAS_USBKEY
void OnPress(auto key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad |= MASK_JOY2_DOWN;
break;
case 218:
usbnavpad |= MASK_JOY2_UP;
break;
case 216:
usbnavpad |= MASK_JOY2_LEFT;
break;
case 215:
usbnavpad |= MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad |= MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnDown(keymodifier, key);
}
}
void OnRelease(int key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad &= ~MASK_JOY2_DOWN;
break;
case 218:
usbnavpad &= ~MASK_JOY2_UP;
break;
case 216:
usbnavpad &= ~MASK_JOY2_LEFT;
break;
case 215:
usbnavpad &= ~MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad &= ~MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnUp(keymodifier, key);
}
}
#endif
void emu_init(void)
{
Serial.begin(115200);
#ifdef HAS_USBKEY
myusb.begin();
keyboard1.attachPress(OnPress);
keyboard1.attachRelease(OnRelease);
#endif
#ifdef USE_SDFS
strcpy(romspath,SDFSDEV);
strcat(romspath,ROMSDIR);
@ -1386,7 +1549,11 @@ void emu_init(void)
{
toggleMenu(true);
}
}
void emu_start(void)
{
#ifdef HAS_I2CKBD
byte msg[7]={0,0,0,0,0,0,0};
Wire.begin(); // join i2c bus SDA2/SCL2
@ -1412,5 +1579,9 @@ void emu_init(void)
Serial.println("i2C keyboard found");
}
#endif
}
usbnavpad = 0;
keys = key_map1;
keyMap = 0;
}

View file

@ -1,17 +1,15 @@
#ifndef EMUAPI_H
#define EMUAPI_H
#define INVX 1
//#define INVY 1
#define HAS_SND 1
#include "platform_config.h"
#define CUSTOM_SND 1
#define HAS_I2CKBD 1
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
// Title: < >
#define TITLE " NES Emulator "
#define TITLE " C64 Emulator "
#define ROMSDIR "c64"
#define emu_Init(ROM) {c64_Start(ROM); c64_Init(); }
@ -51,7 +49,7 @@ const unsigned short keysw[] = {
TAREA_NEW_ROW,40,40,
TAREA_END};
const unsigned short keys[] = {
const unsigned short key_map1[] = {
2,3};
#ifdef HAS_I2CKBD
@ -80,6 +78,7 @@ const unsigned short i2ckeys[] = {
extern void emu_init(void);
extern void emu_start(void);
extern void emu_resetSD(void);
extern void emu_printf(char * text);
@ -102,6 +101,7 @@ extern void emu_FileTempWrite(int addr, unsigned char val);
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_DrawLine8(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_DrawVsync(void);
extern int emu_FrameSkip(void);
@ -115,6 +115,9 @@ extern int emu_GetPad(void);
extern int emu_ReadAnalogJoyX(int min, int max);
extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
extern void emu_KeyboardOnUp(int keymodifer, int key);
extern void emu_KeyboardOnDown(int keymodifer, int key);
extern void emu_sndPlaySound(int chan, int volume, int freq);
extern void emu_sndPlayBuzz(int size, int val);
extern void emu_sndInit();
@ -123,9 +126,10 @@ extern int emu_us(void);
extern int emu_setKeymap(int index);
extern void emu_FileTempInit(void);
extern void emu_FileTempRead(int addr, unsigned char * val, int n);
extern void emu_FileTempWrite(int addr, unsigned char val);
extern void emu_printh(int val);
#endif

View file

@ -35,13 +35,26 @@
#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 38 // UP
#define PIN_JOY1_2 36 // DOWN
#define PIN_JOY1_3 35 // 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
//#define PIN_KEY_USER3 33
//#define PIN_KEY_USER4 39
// Second joystick
#define PIN_JOY1_BTN 2
@ -49,6 +62,7 @@
#define PIN_JOY1_2 7 // DOWN
#define PIN_JOY1_3 6 // RIGHT
#define PIN_JOY1_4 5 // LEFT
#endif
#else
// OLD LAYOUT!!!!
@ -87,7 +101,3 @@
#endif
#endif

View file

@ -35,6 +35,7 @@
#include "patches.h"
#include "emuapi.h"
#include "platform_config.h"
#define DIRECTORY ROMSDIR + "/\0"
@ -191,13 +192,17 @@ uint16_t addr,size;
Serial.println("loading");
//printf("%s,%d,%d:", filename, device, secondaryAddress);
#ifdef EXTERNAL_SD
tft.stopDMA();
//emu_resetSD();
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
#endif
if (emu_FileOpen(filename) == 0) {
//Serial.println("not found");
cpu.pc = 0xf530; //Jump to $F530
#ifdef EXTERNAL_SD
tft.startDMA();
#endif
return;
}
@ -214,8 +219,9 @@ uint16_t addr,size;
cpu.y = 0x49; //Offset for "LOADING"
cpu.pc = 0xF12B; //Print and return
emu_printf("loaded");
#ifdef EXTERNAL_SD
tft.startDMA();
#endif
return;
}

View file

@ -3,14 +3,22 @@
//#define OLD_LAYOUT 1
#define ILI9341 1
#define HAS_T4_VGA 1
//#define INVX 1
#define INVY 1
#define HAS_SND 1
#define HAS_USBKEY 1
//#define HAS_I2CKBD 1
//#define ILI9341 1
//#define ST7789 1
//#define SWAP_JOYSTICK 1
//#define LOHRES 1
//#define ROTATE_SCREEN 1
#define EXTERNAL_SD 1
//#define EXTERNAL_SD 1
#define HAS_PSRAM 1
//#define HAS_PSRAM 1
//#define USE_SDFAT 1
//#define SD_FAT_TYPE 1

View file

@ -2,12 +2,10 @@ extern "C" {
#include "iopins.h"
#include "emuapi.h"
}
#include "keyboard_osd.h"
#include "tft_t_dma.h"
//extern "C" {
#include "keyboard_osd.h"
#include "c64.h"
//}
#ifdef HAS_VGA
#include <uVGA.h>
@ -36,7 +34,13 @@ uVGA uvga;
uint8_t * VGA_frame_buffer;
#endif
#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;
@ -47,17 +51,12 @@ volatile boolean vbl=true;
static int skip=0;
static elapsedMicros tius;
volatile int16_t mClick=0;
static void vblCount() {
if (vbl) {
vbl = false;
} else {
vbl = true;
}
emu_Input(mClick);
if (mClick) {
mClick = 0;
}
}
}
void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int index)
@ -75,19 +74,29 @@ void emu_DrawVsync(void)
skip += 1;
skip &= VID_FRAME_SKIP;
if (!vgaMode) {
#ifdef HAS_T4_VGA
tft.waitSync();
#else
while (vbl==vb) {};
#endif
}
#ifdef HAS_VGA
else {
while (vbl==vb) {};
}
#endif
#endif
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
}
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
}
#ifdef HAS_VGA
else {
@ -105,12 +114,29 @@ void emu_DrawLine(unsigned char * VBuf, int width, int height, int line)
#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
}
}
#ifdef HAS_VGA
#endif
}
void emu_DrawLine16(unsigned short * VBuf, int width, int height, int line)
{
if (!vgaMode) {
//if (skip==0) {
if (skip==0) {
#ifdef HAS_T4_VGA
tft.writeLine16(width,height,line, VBuf);
#else
tft.writeLine(width,height,line, VBuf);
//}
#endif
}
}
#ifdef HAS_VGA
#endif
@ -120,7 +146,11 @@ 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
}
}
#ifdef HAS_VGA
@ -166,15 +196,23 @@ void * emu_LineBuffer(int line)
#endif
}
// ****************************************************
// the setup() method runs once, when the sketch starts
// ****************************************************
void setup() {
tft.begin();
#ifdef HAS_T4_VGA
tft.begin(VGA_MODE_320x240);
NVIC_SET_PRIORITY(IRQ_QTIMER3, 0);
#else
tft.begin();
#endif
emu_init();
emu_init();
}
// ****************************************************
// the loop() method runs continuously
// ****************************************************
@ -187,6 +225,7 @@ void loop(void)
if (action == ACTION_RUNTFT) {
toggleMenu(false);
vgaMode = false;
emu_start();
emu_Init(filename);
//digitalWrite(TFT_CS, 1);
//digitalWrite(SD_CS, 1);
@ -200,6 +239,7 @@ void loop(void)
vgaMode = true;
VGA_frame_buffer = (uint8_t *)malloc((UVGA_YRES*(UVGA_XRES+UVGA_XRES_EXTRA))*sizeof(uint8_t));
uvga.set_static_framebuffer(VGA_frame_buffer);
emu_start();
emu_Init(filename);
int retvga = uvga.begin(&modeline);
Serial.println(retvga);
@ -226,11 +266,11 @@ void loop(void)
#endif
if ( (!virtualkeyboardIsActive()) || (vgaMode) ) {
emu_Step();
uint16_t bClick = emu_DebounceLocalKeys();
if (bClick & MASK_KEY_USER1) {
emu_Input(bClick);
mClick = 1;
}
//delay(20);
//uint16_t bClick = emu_DebounceLocalKeys();
//if (bClick & MASK_KEY_USER1) {
// emu_Input(bClick);
//}
}
}
}
@ -243,8 +283,15 @@ void loop(void)
AudioPlaySystem mymixer;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#ifdef HAS_T4_VGA
AudioOutputI2S i2s1;
AudioConnection patchCord8(mymixer, 0, i2s1, 0);
AudioConnection patchCord9(mymixer, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
#else
AudioOutputMQS mqs;
AudioConnection patchCord9(mymixer, 0, mqs, 1);
#endif
#else
AudioOutputAnalog dac1;
AudioConnection patchCord1(mymixer, dac1);
@ -277,5 +324,3 @@ void emu_sndPlayBuzz(int size, int val) {
//Serial.println(size);
}
#endif

View file

@ -3,6 +3,9 @@
*/
#include "TFT_T_DMA.h"
#ifndef HAS_T4_VGA
#include "font8x8.h"
@ -1231,7 +1234,7 @@ void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap, uint16_
l++;
}
}
#endif

View file

@ -0,0 +1,53 @@
/*
Wrapping class to extend VGA_T4 to TFT_T_DMA
*/
#ifndef _VGA_T_DMAH_
#define _VGA_T_DMAH_
#ifdef __cplusplus
#include <VGA_t4.h>
#endif
#define RGBVAL16(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define RGBVAL8(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define TFT_WIDTH 320
#define TFT_REALWIDTH 320
#define TFT_HEIGHT 240
#define TFT_REALHEIGHT 240
#ifdef __cplusplus
class TFT_T_DMA: public VGA_T4
{
public:
// Fake touch screen functions
bool isTouching(void) { return false; }
void readRaw(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { }
void readCal(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { };
void callibrateTouch(uint16_t xMin,uint16_t yMin,uint16_t xMax,uint16_t yMax) { }
// fake DMA functions
void startDMA(void) { };
void stopDMA(void) { };
// fake no DMA functions
void writeScreenNoDma(const vga_pixel *pcolors) { writeScreen(pcolors); }
void fillScreenNoDma(vga_pixel color) { clear(color); }
void drawTextNoDma(int16_t x, int16_t y, const char * text, vga_pixel fgcolor, vga_pixel bgcolor, bool doublesize) { drawText(x,y,text,fgcolor,bgcolor,doublesize); }
void drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, vga_pixel color) { drawRect(x, y, w, h, color); }
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap) { drawSprite(x, y, bitmap); }
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); }
};
#endif
#endif

View file

@ -69,7 +69,11 @@
#define BORDER_LEFT 0
#define BORDER_RIGHT 0
#ifdef HAS_T4_VGA
typedef uint8_t tpixel;
#else
typedef uint16_t tpixel;
#endif
#define MAXCYCLESSPRITES0_2 3
#define MAXCYCLESSPRITES3_7 5
@ -1270,7 +1274,8 @@ void mode7 (tpixel *p, const tpixel *pe, uint16_t *spl, const uint16_t vc) {
typedef void (*modes_t)( tpixel *p, const tpixel *pe, uint16_t *spl, const uint16_t vc ); //Funktionspointer
const modes_t modes[8] = {mode0, mode1, mode2, mode3, mode4, mode5, mode6, mode7};
static uint16_t linebuffer[SCREEN_WIDTH];
static tpixel linebuffer[SCREEN_WIDTH];
void vic_do(void) {
@ -1304,7 +1309,7 @@ void vic_do(void) {
cpu.vic.denLatch = 0;
//if (cpu.vic.rasterLine == LINECNT)
//delay(50);
//emu_DrawVsync();
emu_DrawVsync();
} else cpu.vic.rasterLine++;
@ -1602,7 +1607,13 @@ g-Zugriff
}
emu_DrawLine16(&linebuffer[0], SCREEN_WIDTH, SCREEN_HEIGHT, (r - FIRSTDISPLAYLINE));
#ifdef HAS_T4_VGA
emu_DrawLine8(&linebuffer[0], SCREEN_WIDTH, SCREEN_HEIGHT, (r - FIRSTDISPLAYLINE));
#else
emu_DrawLine16(&linebuffer[0], SCREEN_WIDTH, SCREEN_HEIGHT, (r - FIRSTDISPLAYLINE));
#endif
//Rechter Rand nach CSEL, im Textbereich
cpu_clock(5);

View file

@ -267,6 +267,11 @@ void at8_Init(void)
Initialise();
}
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
void at8_Step(void)
{
@ -371,9 +376,3 @@ void at8_Start(char * cartname)
emu_printf("init done");
}

View file

@ -5,8 +5,17 @@ extern "C" {
#include "iopins.h"
}
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
const uint16_t deflogo[] = {
0,0
};
static const uint16_t * logo = deflogo;
#else
#include "tft_t_dma.h"
#include "logo.h"
#endif
#include "bmpjoy.h"
#include "bmpvbar.h"
#ifdef OLD_LAYOUT
@ -19,6 +28,13 @@ extern "C" {
#include <Wire.h>
#endif
#ifdef HAS_USBKEY
#include "USBHost_t36.h" // Read this header first for key info
USBHost myusb;
KeyboardController keyboard1(myusb);
#endif
static uint8_t usbnavpad=0;
#ifdef USE_SDFS
#include "uSDFS.h"
static FATFS fatfs;
@ -84,7 +100,7 @@ static File file;
#define MKEY_TFT 23
#define MKEY_VGA 24
#define MAX_FILES 32
#define MAX_FILES 64
#define MAX_FILENAME_SIZE 24
#define MAX_MENULINES (MKEY_L9)
#define TEXT_HEIGHT 16
@ -93,7 +109,7 @@ static File file;
#define MENU_FILE_YOFFSET (2*TEXT_HEIGHT)
#define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH)
#define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x20)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40)
#define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT)
#define MENU_VBAR_XOFFSET (0*TEXT_WIDTH)
#define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET)
@ -113,13 +129,10 @@ static char selection[MAX_FILENAME_SIZE+1]="";
static char files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
static int16_t calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static bool i2cKeyboardPresent = false;
//const uint16_t deflogo[] = {
// 0x0000,0x0000
//};
//static const uint16_t * logo = deflogo;
static unsigned short * keys;
static int keyMap;
const unsigned short menutouchareas[] = {
TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET,
@ -245,7 +258,7 @@ void emu_printf(int val)
void emu_printi(int val)
{
Serial.println(val);
Serial.println(val,HEX);
}
void emu_printh(int val)
@ -272,13 +285,29 @@ void * emu_Malloc(int size)
}
}
else {
emu_printf("could allocate ");
emu_printf("could allocate dynamic ");
emu_printf(size);
}
return retval;
}
void * emu_MallocI(int size)
{
void * retval = NULL;
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
emu_printf("could allocate static ");
emu_printf(size);
}
else {
emu_printf("failure to allocate");
}
return retval;
}
void emu_Free(void * pt)
{
free(pt);
@ -400,6 +429,12 @@ int emu_ReadKeys(void)
retval = ((j2 << 8) | j1);
}
if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
#ifdef PIN_KEY_USER1
if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1;
#endif
@ -575,7 +610,7 @@ bool virtualkeyboardIsActive(void) {
void toggleVirtualkeyboard(bool keepOn) {
if (keepOn) {
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbKeepOn = true;
vkbActive = true;
@ -592,7 +627,7 @@ void toggleVirtualkeyboard(bool keepOn) {
}
else {
tft.stopDMA();
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbActive = true;
exitVkbd = false;
@ -637,7 +672,7 @@ void handleVirtualkeyboard() {
if (vkeyRefresh) {
vkeyRefresh = false;
tft.drawSpriteNoDma(0,0,(uint16_t*)logo, rx, ry, rw, rh);
tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh);
}
if ( (exitVkbd) && (vkbActive) ) {
@ -651,10 +686,6 @@ void handleVirtualkeyboard() {
}
int emu_setKeymap(int index) {
if (index) {
}
else {
}
}
@ -726,10 +757,12 @@ void backgroundMenu(void) {
menuRedraw=true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,(uint16_t*)bmpvbar);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,bmpvbar);
#endif
#ifdef OLD_LAYOUT
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,(uint16_t*)bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,(uint16_t*)bmpvga);
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,bmpvga);
#endif
}
@ -839,7 +872,7 @@ int handleMenu(uint16_t bClick)
strcpy(selection,filename);
}
else {
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, 0xFFFF, 0x0000, true);
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true);
}
}
i++;
@ -847,8 +880,10 @@ int handleMenu(uint16_t bClick)
fileIndex++;
}
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0xff,0x00,0x00), false);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
#endif
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false);
menuRedraw=false;
}
@ -1338,11 +1373,138 @@ void emu_FileTempWrite(int addr, unsigned char val)
#endif
}
#ifdef HAS_USBKEY
void OnPress(auto key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad |= MASK_JOY2_DOWN;
break;
case 218:
usbnavpad |= MASK_JOY2_UP;
break;
case 216:
usbnavpad |= MASK_JOY2_LEFT;
break;
case 215:
usbnavpad |= MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad |= MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnDown(keymodifier, key);
}
}
void OnRelease(int key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad &= ~MASK_JOY2_DOWN;
break;
case 218:
usbnavpad &= ~MASK_JOY2_UP;
break;
case 216:
usbnavpad &= ~MASK_JOY2_LEFT;
break;
case 215:
usbnavpad &= ~MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad &= ~MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnUp(keymodifier, key);
}
}
#endif
void emu_init(void)
{
Serial.begin(115200);
#ifdef HAS_USBKEY
myusb.begin();
keyboard1.attachPress(OnPress);
keyboard1.attachRelease(OnRelease);
#endif
#ifdef USE_SDFS
strcpy(romspath,SDFSDEV);
strcat(romspath,ROMSDIR);
@ -1387,7 +1549,11 @@ void emu_init(void)
{
toggleMenu(true);
}
}
void emu_start(void)
{
#ifdef HAS_I2CKBD
byte msg[7]={0,0,0,0,0,0,0};
Wire.begin(); // join i2c bus SDA2/SCL2
@ -1413,5 +1579,9 @@ void emu_init(void)
Serial.println("i2C keyboard found");
}
#endif
}
usbnavpad = 0;
keys = key_map1;
keyMap = 0;
}

View file

@ -1,11 +1,9 @@
#ifndef EMUAPI_H
#define EMUAPI_H
#define INVX 1
//#define INVY 1
#define HAS_SND 1
#include "platform_config.h"
#define CUSTOM_SND 1
#define HAS_I2CKBD 1
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
@ -18,7 +16,7 @@
#define emu_Input(x) {}
#define PALETTE_SIZE 256
#define VID_FRAME_SKIP 0x3
#define VID_FRAME_SKIP 0x0
#define TFT_VBUFFER_YCROP 0
#define SINGLELINE_RENDERING 1
@ -60,7 +58,7 @@ const unsigned short keysw[] = {
TAREA_END};
const unsigned short keys[] = {
const unsigned short key_map1[] = {
0x1C+1,0x1F+1,0x1F ,0x1A+1,0x18+1,0x1D+1,0x1B+1,0x33+1,0x35+1,0x30+1,0x32+1,0x36+1,0x37+1,0,0,
0x2C+1,0x2F+1,0x2F ,0x2A+1,0x28+1,0x2D+1,0x2B+1,0x0B+1,0x0D+1,0x08+1,0x0A+1,0x0E,0x0F+1,0x0C+1,
0, 0x3F+1,0x3F ,0x3A+1,0x38+1,0x3D+1,0x39+1,0x01+1,0x05+1,0x00+1,0x02+1,0x06+1,0x07+1,0,
@ -97,6 +95,9 @@ const unsigned short i2ckeys[] = {
extern void emu_init(void);
extern void emu_start(void);
extern void emu_resetSD(void);
extern void emu_printf(char * text);
extern void emu_printi(int val);
extern void * emu_Malloc(int size);
@ -117,6 +118,7 @@ extern void emu_FileTempWrite(int addr, unsigned char val);
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_DrawLine8(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_DrawVsync(void);
extern int emu_FrameSkip(void);
@ -130,6 +132,9 @@ extern int emu_GetPad(void);
extern int emu_ReadAnalogJoyX(int min, int max);
extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
extern void emu_KeyboardOnUp(int keymodifer, int key);
extern void emu_KeyboardOnDown(int keymodifer, int key);
extern void emu_sndPlaySound(int chan, int volume, int freq);
extern void emu_sndPlayBuzz(int size, int val);
extern void emu_sndInit();
@ -138,8 +143,10 @@ extern int emu_us(void);
extern int emu_setKeymap(int index);
extern void emu_FileTempInit(void);
extern void emu_FileTempRead(int addr, unsigned char * val, int n);
extern void emu_FileTempWrite(int addr, unsigned char val);
extern void emu_printh(int val);
#endif

View file

@ -35,13 +35,26 @@
#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 38 // UP
#define PIN_JOY1_2 36 // DOWN
#define PIN_JOY1_3 35 // 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
//#define PIN_KEY_USER3 33
//#define PIN_KEY_USER4 39
// Second joystick
#define PIN_JOY1_BTN 2
@ -49,6 +62,7 @@
#define PIN_JOY1_2 7 // DOWN
#define PIN_JOY1_3 6 // RIGHT
#define PIN_JOY1_4 5 // LEFT
#endif
#else
// OLD LAYOUT!!!!
@ -87,7 +101,3 @@
#endif
#endif

View file

@ -2,15 +2,22 @@
#define _PLATFORM_CONFIG_H_
//#define OLD_LAYOUT 1
#define HAS_T4_VGA 1
#define ILI9341 1
#define HAS_SND 1
//#define INVX 1
//#define INVY 1
#define HAS_USBKEY 1
//#define HAS_I2CKBD 1
//#define ILI9341 1
//#define ST7789 1
//#define SWAP_JOYSTICK 1
//#define LOHRES 1
//#define ROTATE_SCREEN 1
#define EXTERNAL_SD 1
//#define EXTERNAL_SD 1
#define HAS_PSRAM 1
//#define HAS_PSRAM 1
//#define USE_SDFAT 1
//#define SD_FAT_TYPE 1

View file

@ -3,7 +3,6 @@ extern "C" {
#include "emuapi.h"
}
#include "keyboard_osd.h"
#include "tft_t_dma.h"
extern "C" {
#include "atari800.h"
@ -36,7 +35,14 @@ uVGA uvga;
uint8_t * VGA_frame_buffer;
#endif
#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;
@ -60,7 +66,7 @@ void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int
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);
palette16[index] = RGBVAL16(r,g,b);
}
}
@ -70,7 +76,11 @@ void emu_DrawVsync(void)
skip += 1;
skip &= VID_FRAME_SKIP;
if (!vgaMode) {
#ifdef HAS_T4_VGA
tft.waitSync();
#else
while (vbl==vb) {};
#endif
}
#ifdef HAS_VGA
else {
@ -82,7 +92,11 @@ void emu_DrawVsync(void)
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
}
#ifdef HAS_VGA
else {
@ -100,11 +114,43 @@ void emu_DrawLine(unsigned char * VBuf, int width, int height, int line)
#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
}
}
#ifdef HAS_VGA
#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
}
}
#ifdef HAS_VGA
#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
}
}
#ifdef HAS_VGA
@ -154,8 +200,13 @@ void * emu_LineBuffer(int line)
// the setup() method runs once, when the sketch starts
// ****************************************************
void setup() {
tft.begin();
#ifdef HAS_T4_VGA
tft.begin(VGA_MODE_352x240);
// NVIC_SET_PRIORITY(IRQ_QTIMER3, 255);
#else
tft.begin();
#endif
emu_init();
myTimer.begin(vblCount, 20000); //to run every 20ms
@ -169,15 +220,16 @@ void loop(void)
if (menuActive()) {
uint16_t bClick = emu_DebounceLocalKeys();
int action = handleMenu(bClick);
char * filename = menuSelection();
char * filename = menuSelection();
if (action == ACTION_RUNTFT) {
toggleMenu(false);
vgaMode = false;
vgaMode = false;
emu_start();
emu_Init(filename);
//digitalWrite(TFT_CS, 1);
//digitalWrite(SD_CS, 1);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
tft.startDMA();
}
else if (action == ACTION_RUNVGA) {
#ifdef HAS_VGA
@ -185,6 +237,7 @@ void loop(void)
vgaMode = true;
VGA_frame_buffer = (uint8_t *)malloc((UVGA_YRES*(UVGA_XRES+UVGA_XRES_EXTRA))*sizeof(uint8_t));
uvga.set_static_framebuffer(VGA_frame_buffer);
emu_start();
emu_Init(filename);
int retvga = uvga.begin(&modeline);
Serial.println(retvga);
@ -217,6 +270,7 @@ void loop(void)
}
#ifdef HAS_SND
#include <Audio.h>
@ -224,8 +278,15 @@ void loop(void)
AudioPlaySystem mymixer;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#ifdef HAS_T4_VGA
AudioOutputI2S i2s1;
AudioConnection patchCord8(mymixer, 0, i2s1, 0);
AudioConnection patchCord9(mymixer, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
#else
AudioOutputMQS mqs;
AudioConnection patchCord9(mymixer, 0, mqs, 1);
#endif
#else
AudioOutputAnalog dac1;
AudioConnection patchCord1(mymixer, dac1);
@ -233,6 +294,10 @@ AudioConnection patchCord1(mymixer, dac1);
void emu_sndInit() {
Serial.println("sound init");
#ifdef HAS_T4_VGA
// sgtl5000_1.enable();
// sgtl5000_1.volume(0.6);
#endif
AudioMemory(16);
mymixer.start();
}
@ -258,7 +323,3 @@ void emu_sndPlayBuzz(int size, int val) {
//Serial.println(size);
}
#endif

View file

@ -3,6 +3,9 @@
*/
#include "TFT_T_DMA.h"
#ifndef HAS_T4_VGA
#include "font8x8.h"
@ -1231,7 +1234,7 @@ void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap, uint16_
l++;
}
}
#endif

View file

@ -0,0 +1,53 @@
/*
Wrapping class to extend VGA_T4 to TFT_T_DMA
*/
#ifndef _VGA_T_DMAH_
#define _VGA_T_DMAH_
#ifdef __cplusplus
#include <VGA_t4.h>
#endif
#define RGBVAL16(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define RGBVAL8(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define TFT_WIDTH 320
#define TFT_REALWIDTH 320
#define TFT_HEIGHT 240
#define TFT_REALHEIGHT 240
#ifdef __cplusplus
class TFT_T_DMA: public VGA_T4
{
public:
// Fake touch screen functions
bool isTouching(void) { return false; }
void readRaw(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { }
void readCal(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { };
void callibrateTouch(uint16_t xMin,uint16_t yMin,uint16_t xMax,uint16_t yMax) { }
// fake DMA functions
void startDMA(void) { };
void stopDMA(void) { };
// fake no DMA functions
void writeScreenNoDma(const vga_pixel *pcolors) { writeScreen(pcolors); }
void fillScreenNoDma(vga_pixel color) { clear(color); }
void drawTextNoDma(int16_t x, int16_t y, const char * text, vga_pixel fgcolor, vga_pixel bgcolor, bool doublesize) { drawText(x,y,text,fgcolor,bgcolor,doublesize); }
void drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, vga_pixel color) { drawRect(x, y, w, h, color); }
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap) { drawSprite(x, y, bitmap); }
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); }
};
#endif
#endif

View file

@ -4,13 +4,15 @@
// #define RAM_SIZE 0xF8000 // 512k //655360UL
// #define NATIVE_RAM (0X28000) // 128k+32768 //231424UL
#define RAM_SIZE 0x78000 // 512k //655360UL
#define NATIVE_RAM (0X28000) // 128k+32768 //231424UL
#define NATIVE_START 0UL
#define RAM_SIZE 0x78000 // 512k //655360UL
#define NATIVE_RAM (0X28000) // 128k+32768 //231424UL
#define NATIVE_START 0UL
#define ROM_READ(a,b) a[b]
#define ROM_READ(a,b) a[b]
//#define INCLUDE_ROM_BASIC
@ -152,4 +154,3 @@ union _bytewordregs_{
uint16_t wordregs[8];
uint8_t byteregs[8];
} ;

View file

@ -1,12 +1,21 @@
#define KEYMAP_PRESENT 1
//extern "C" {
extern "C" {
#include "emuapi.h"
#include "iopins.h"
//}
}
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
const uint16_t deflogo[] = {
0,0
};
static const uint16_t * logo = deflogo;
#else
#include "tft_t_dma.h"
#include "logo.h"
#endif
#include "bmpjoy.h"
#include "bmpvbar.h"
#ifdef OLD_LAYOUT
@ -19,6 +28,13 @@
#include <Wire.h>
#endif
#ifdef HAS_USBKEY
#include "USBHost_t36.h" // Read this header first for key info
USBHost myusb;
KeyboardController keyboard1(myusb);
#endif
static uint8_t usbnavpad=0;
#ifdef USE_SDFS
#include "uSDFS.h"
static FATFS fatfs;
@ -84,7 +100,7 @@ static File file;
#define MKEY_TFT 23
#define MKEY_VGA 24
#define MAX_FILES 32
#define MAX_FILES 64
#define MAX_FILENAME_SIZE 24
#define MAX_MENULINES (MKEY_L9)
#define TEXT_HEIGHT 16
@ -93,7 +109,7 @@ static File file;
#define MENU_FILE_YOFFSET (2*TEXT_HEIGHT)
#define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH)
#define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x20)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40)
#define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT)
#define MENU_VBAR_XOFFSET (0*TEXT_WIDTH)
#define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET)
@ -113,13 +129,10 @@ static char selection[MAX_FILENAME_SIZE+1]="";
static char files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
static int16_t calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static bool i2cKeyboardPresent = false;
//const uint16_t deflogo[] = {
// 0x0000,0x0000
//};
//static const uint16_t * logo = deflogo;
static unsigned short * keys;
static int keyMap;
const unsigned short menutouchareas[] = {
TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET,
@ -245,7 +258,7 @@ void emu_printf(int val)
void emu_printi(int val)
{
Serial.println(val);
Serial.println(val,HEX);
}
void emu_printh(int val)
@ -272,13 +285,29 @@ void * emu_Malloc(int size)
}
}
else {
emu_printf("could allocate ");
emu_printf("could allocate dynamic ");
emu_printf(size);
}
return retval;
}
void * emu_MallocI(int size)
{
void * retval = NULL;
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
emu_printf("could allocate static ");
emu_printf(size);
}
else {
emu_printf("failure to allocate");
}
return retval;
}
void emu_Free(void * pt)
{
free(pt);
@ -400,6 +429,12 @@ int emu_ReadKeys(void)
retval = ((j2 << 8) | j1);
}
if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
#ifdef PIN_KEY_USER1
if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1;
#endif
@ -575,7 +610,7 @@ bool virtualkeyboardIsActive(void) {
void toggleVirtualkeyboard(bool keepOn) {
if (keepOn) {
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbKeepOn = true;
vkbActive = true;
@ -592,7 +627,7 @@ void toggleVirtualkeyboard(bool keepOn) {
}
else {
tft.stopDMA();
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbActive = true;
exitVkbd = false;
@ -637,7 +672,7 @@ void handleVirtualkeyboard() {
if (vkeyRefresh) {
vkeyRefresh = false;
tft.drawSpriteNoDma(0,0,(uint16_t*)logo, rx, ry, rw, rh);
tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh);
}
if ( (exitVkbd) && (vkbActive) ) {
@ -651,10 +686,6 @@ void handleVirtualkeyboard() {
}
int emu_setKeymap(int index) {
if (index) {
}
else {
}
}
@ -726,10 +757,12 @@ void backgroundMenu(void) {
menuRedraw=true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,(uint16_t*)bmpvbar);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,bmpvbar);
#endif
#ifdef OLD_LAYOUT
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,(uint16_t*)bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,(uint16_t*)bmpvga);
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,bmpvga);
#endif
}
@ -839,7 +872,7 @@ int handleMenu(uint16_t bClick)
strcpy(selection,filename);
}
else {
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, 0xFFFF, 0x0000, true);
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true);
}
}
i++;
@ -847,8 +880,10 @@ int handleMenu(uint16_t bClick)
fileIndex++;
}
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0xff,0x00,0x00), false);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
#endif
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false);
menuRedraw=false;
}
@ -1338,11 +1373,138 @@ void emu_FileTempWrite(int addr, unsigned char val)
#endif
}
#ifdef HAS_USBKEY
void OnPress(auto key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad |= MASK_JOY2_DOWN;
break;
case 218:
usbnavpad |= MASK_JOY2_UP;
break;
case 216:
usbnavpad |= MASK_JOY2_LEFT;
break;
case 215:
usbnavpad |= MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad |= MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnDown(keymodifier, key);
}
}
void OnRelease(int key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad &= ~MASK_JOY2_DOWN;
break;
case 218:
usbnavpad &= ~MASK_JOY2_UP;
break;
case 216:
usbnavpad &= ~MASK_JOY2_LEFT;
break;
case 215:
usbnavpad &= ~MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad &= ~MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnUp(keymodifier, key);
}
}
#endif
void emu_init(void)
{
Serial.begin(115200);
#ifdef HAS_USBKEY
myusb.begin();
keyboard1.attachPress(OnPress);
keyboard1.attachRelease(OnRelease);
#endif
#ifdef USE_SDFS
strcpy(romspath,SDFSDEV);
strcat(romspath,ROMSDIR);
@ -1387,7 +1549,11 @@ void emu_init(void)
{
toggleMenu(true);
}
}
void emu_start(void)
{
#ifdef HAS_I2CKBD
byte msg[7]={0,0,0,0,0,0,0};
Wire.begin(); // join i2c bus SDA2/SCL2
@ -1413,5 +1579,9 @@ void emu_init(void)
Serial.println("i2C keyboard found");
}
#endif
}
usbnavpad = 0;
keys = key_map1;
keyMap = 0;
}

View file

@ -1,14 +1,9 @@
#ifndef EMUAPI_H
#define EMUAPI_H
//#define INVX 1
//#define INVY 1
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#else
#endif
//#define HAS_SND 1
#include "platform_config.h"
//#define CUSTOM_SND 1
#define HAS_I2CKBD 1
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
@ -60,7 +55,7 @@ const unsigned short keysw[]=
//TAREA_NEW_ROW,18,18,18,18,18,18,18,18,18,18,
TAREA_END};
const unsigned short keys[]={
const unsigned short key_map1[]={
59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
109,110,111,112,106,107,108,17,18,19,
@ -99,10 +94,16 @@ const unsigned short i2ckeys[] = {
#define MASK_KEY_USER4 0x2000
#ifdef __cplusplus
extern "C" {
#endif
extern void emu_init(void);
extern void emu_start(void);
extern void emu_printf(char * text);
extern void emu_printi(int val);
extern void * emu_Malloc(int size);
extern void emu_Free(void * pt);
@ -121,6 +122,7 @@ extern void emu_FileTempWrite(int addr, unsigned char val);
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_DrawLine8(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_DrawVsync(void);
extern int emu_FrameSkip(void);
@ -134,6 +136,9 @@ extern int emu_GetPad(void);
extern int emu_ReadAnalogJoyX(int min, int max);
extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
extern void emu_KeyboardOnUp(int keymodifer, int key);
extern void emu_KeyboardOnDown(int keymodifer, int key);
extern void emu_sndPlaySound(int chan, int volume, int freq);
extern void emu_sndPlayBuzz(int size, int val);
extern void emu_sndInit();
@ -142,9 +147,14 @@ extern int emu_us(void);
extern int emu_setKeymap(int index);
extern void emu_FileTempInit(void);
extern void emu_FileTempRead(int addr, unsigned char * val, int n);
extern void emu_FileTempWrite(int addr, unsigned char val);
extern void emu_printh(int val);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -35,13 +35,26 @@
#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 38 // UP
#define PIN_JOY1_2 36 // DOWN
#define PIN_JOY1_3 35 // 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
//#define PIN_KEY_USER3 33
//#define PIN_KEY_USER4 39
// Second joystick
#define PIN_JOY1_BTN 2
@ -49,6 +62,7 @@
#define PIN_JOY1_2 7 // DOWN
#define PIN_JOY1_3 6 // RIGHT
#define PIN_JOY1_4 5 // LEFT
#endif
#else
// OLD LAYOUT!!!!
@ -87,7 +101,3 @@
#endif
#endif

View file

@ -2,15 +2,22 @@
#define _PLATFORM_CONFIG_H_
//#define OLD_LAYOUT 1
#define HAS_T41 1
#define HAS_T4_VGA 1
//#define HAS_SND 1
//#define INVX 1
//#define INVY 1
#define HAS_USBKEY 1
//#define ILI9341 1
#define ST7789 1
#define SWAP_JOYSTICK 1
//#define ST7789 1
//#define SWAP_JOYSTICK 1
//#define LOHRES 1
//#define ROTATE_SCREEN 1
#define EXTERNAL_SD 1
//#define EXTERNAL_SD 1
#define HAS_PSRAM 1
//#define HAS_PSRAM 1
//#define USE_SDFAT 1
//#define SD_FAT_TYPE 1

View file

@ -1,8 +1,8 @@
#include "iopins.h"
#include "emuapi.h"
extern "C" {
#include "iopins.h"
#include "emuapi.h"
}
#include "keyboard_osd.h"
#include "tft_t_dma.h"
#include "test.h"
@ -33,7 +33,14 @@ uVGA uvga;
uint8_t * VGA_frame_buffer;
#endif
#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;
@ -55,9 +62,8 @@ static void vblCount() {
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);
palette16[index] = RGBVAL16(r,g,b);
}
}
@ -67,7 +73,11 @@ void emu_DrawVsync(void)
skip += 1;
skip &= VID_FRAME_SKIP;
if (!vgaMode) {
#ifdef HAS_T4_VGA
tft.waitSync();
#else
while (vbl==vb) {};
#endif
}
#ifdef HAS_VGA
else {
@ -79,7 +89,11 @@ void emu_DrawVsync(void)
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
}
#ifdef HAS_VGA
else {
@ -97,11 +111,28 @@ void emu_DrawLine(unsigned char * VBuf, int width, int height, int line)
#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
}
}
#ifdef HAS_VGA
#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
}
}
#ifdef HAS_VGA
@ -112,7 +143,11 @@ 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
}
}
#ifdef HAS_VGA
@ -162,13 +197,18 @@ void * emu_LineBuffer(int line)
// the setup() method runs once, when the sketch starts
// ****************************************************
void setup() {
tft.begin();
#ifdef HAS_T4_VGA
tft.begin(VGA_MODE_640x240);
// NVIC_SET_PRIORITY(IRQ_QTIMER3, 0);
#else
tft.begin();
#endif
emu_init();
myTimer.begin(vblCount, 20000); //to run every 20ms
}
static unsigned char col=0;
// ****************************************************
// the loop() method runs continuously
// ****************************************************
@ -177,13 +217,16 @@ void loop(void)
if (menuActive()) {
uint16_t bClick = emu_DebounceLocalKeys();
int action = handleMenu(bClick);
char * filename = menuSelection();
char * filename = menuSelection();
if (action == ACTION_RUNTFT) {
toggleMenu(false);
vgaMode = false;
emu_Init(filename);
vgaMode = false;
emu_start();
emu_Init(filename);
//digitalWrite(TFT_CS, 1);
//digitalWrite(SD_CS, 1);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
tft.startDMA();
}
else if (action == ACTION_RUNVGA) {
#ifdef HAS_VGA
@ -191,6 +234,7 @@ void loop(void)
vgaMode = true;
VGA_frame_buffer = (uint8_t *)malloc((UVGA_YRES*(UVGA_XRES+UVGA_XRES_EXTRA))*sizeof(uint8_t));
uvga.set_static_framebuffer(VGA_frame_buffer);
emu_start();
emu_Init(filename);
int retvga = uvga.begin(&modeline);
Serial.println(retvga);
@ -215,29 +259,42 @@ void loop(void)
handleVirtualkeyboard();
#endif
if ( (!virtualkeyboardIsActive()) || (vgaMode) ) {
emu_Step();
//delay(20);
//tft.fillScreen( RGBVAL16(0xff,col,0x00) );
//if ((uint32_t)_pfbtft >= 0x20200000u) arm_dcache_flush(_pfbtft, CBALLOC);
//col++;
emu_Step();
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
}
}
}
#ifdef HAS_SND
#include <Audio.h>
#include "AudioPlaySystem.h"
AudioPlaySystem mymixer;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#ifdef HAS_T4_VGA
AudioOutputI2S i2s1;
AudioConnection patchCord8(mymixer, 0, i2s1, 0);
AudioConnection patchCord9(mymixer, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
#else
AudioOutputMQS mqs;
AudioConnection patchCord9(mymixer, 0, mqs, 1);
#endif
#else
AudioOutputAnalog dac1;
AudioConnection patchCord1(mymixer, dac1);
#endif
void emu_sndInit() {
Serial.println("sound init");
#ifdef HAS_T4_VGA
sgtl5000_1.enable();
sgtl5000_1.volume(0.6);
#endif
AudioMemory(16);
mymixer.start();
}
@ -247,7 +304,6 @@ void emu_sndPlaySound(int chan, int volume, int freq)
if (chan < 6) {
mymixer.sound(chan, freq, volume);
}
/*
Serial.print(chan);
Serial.print(":" );

View file

@ -4,7 +4,13 @@
#include "emu.h"
#include "ps2.h"
#ifdef HAS_T41
EXTMEM static unsigned char MemPool[8*1024*1024];
#else
static uint8_t LOMEM[NATIVE_RAM];
#endif
uint8_t * RAM;
uint8_t * LORAM;
@ -333,14 +339,15 @@ void installPalette(void) {
extern uint8_t vidmode, portram[0x400];
#define XRES 320
#define YRES 200
#define XRES_MAX 640
#define XRES_HI 640
#define XRES_LO 320
#define YRES 200
#include "font.h"
static unsigned short line[XRES];
static unsigned short line[XRES_MAX];
void drawscreentext80(void) {
uint16_t row, col, y, x, xpos;
@ -360,23 +367,23 @@ void drawscreentext80(void) {
fg = attrib & 0x0F;
//if (y == 0) {printf("0x%02X",cc);}
fontdata = ROM_READ(font, ((uint32_t)cc << 3) + (y&0x7));
for (x=0; x<4; x++)
for (x=0; x<8; x++)
//for (x=0; x<4; x++)
{
if (fontdata & 1) {
line[xpos++] = palettecga[fg];
} else {
line[xpos++] = palettecga[bg];
}
fontdata >>= 2;
fontdata >>= 1;
//fontdata >>= 2;
}
}
emu_DrawLine16(&line[0], XRES, YRES, y);
emu_DrawLine16(&line[0], XRES_HI, YRES, y);
}
}
void drawscreenlorescga(void) {
//uint16_t row;
uint16_t y, x, xpos;
uint8_t intensity, usepal;
uint16_t color;
@ -385,10 +392,8 @@ void drawscreenlorescga(void) {
for (y=0; y<(25*8); y++)
{
//row = y>>3;
//uint8_t * vrampt=&VRAM[160*row];
xpos = 0;
for (x=0; x<XRES; x++)
for (x=0; x<XRES_LO; x++)
{
int ychar = y;// >> 1;
int xchar = x;// >> 1;
@ -403,8 +408,7 @@ void drawscreenlorescga(void) {
if (color == (usepal + intensity)) color = 0;
line[xpos++] = palettecga[color];
}
emu_DrawLine16(&line[0], XRES, YRES, y);
emu_DrawLine16(&line[0], XRES_LO, YRES, y);
}
}
@ -415,7 +419,7 @@ void drawscreenhirescga(void) {
for (y=0; y<(25*8); y++)
{
xpos = 0;
for (x=0; x<XRES; x++)
for (x=0; x<XRES_HI; x++)
{
int ychar = y >> 1;
int xchar = x;
@ -423,8 +427,7 @@ void drawscreenhirescga(void) {
color = ((curchar >> (7-(x&7))) & 1) ? 15 : 0;
line[xpos++] = palettecga[color];
}
emu_DrawLine16(&line[0], XRES, YRES, y);
emu_DrawLine16(&line[0], XRES_HI, YRES, y);
}
}
@ -457,9 +460,10 @@ static uint8_t nbkeys=0;
static uint8_t kcnt=0;
static int toggle=1;
//static char * seq="DIR\r";
//static char * seq="CAT.EXE\r";
static char * seq="PRINCE.BAT\r";
static char * seq;
static char * seq1="PRINCE.BAT\r";
static char * seq2="CAT.EXE\r";
static char * seq3="DIR\r";
static int mouse_x = 160;
static int mouse_y = 100;
@ -480,7 +484,6 @@ static void keyevent(int keysym, int isdown)
if (!isdown) portram[0x60] |= 0x80;
portram[0x64] |= 2;
doirq(1);
//vTaskDelay(50 / portTICK_PERIOD_MS);
}
}
@ -490,7 +493,13 @@ extern void apc_Input(int bClick) {
if (nbkeys == 0) {
if (bClick & MASK_JOY2_BTN) {
nbkeys = strlen(seq);
nbkeys = strlen(seq1);
seq=seq1;
kcnt=0;
}
if (bClick & MASK_KEY_USER1) {
nbkeys = strlen(seq2);
seq=seq2;
kcnt=0;
}
}
@ -554,35 +563,23 @@ static void do_events(void)
}
else {
if (( k & MASK_JOY1_RIGHT) || ( k & MASK_JOY2_RIGHT)) {
if ( mouse_x < XRES ) {
if ( mouse_x < XRES_HI ) {
mouse_x += 1;
//Serial.print("r");
//IkbdMouseMotion ( mouse_x, mouse_y );
//IkbdLoop();
}
}
else if (( k & MASK_JOY1_LEFT) || ( k & MASK_JOY2_LEFT)) {
if ( mouse_x > 1 ) {
mouse_x -= 1;
//Serial.print("l");
//IkbdMouseMotion ( mouse_x, mouse_y );
//IkbdLoop();
mouse_x -= 1;
}
}
else if (( k & MASK_JOY1_UP) || ( k & MASK_JOY2_UP)) {
if ( mouse_y > 1 ) {
mouse_y -= 1;
//Serial.print("u");
//IkbdMouseMotion ( mouse_x, mouse_y );
//IkbdLoop();
mouse_y -= 1;
}
}
else if (( k & MASK_JOY1_DOWN) || ( k & MASK_JOY2_DOWN)) {
if ( mouse_y < YRES ) {
mouse_y += 1;
//Serial.print("d");
//IkbdMouseMotion ( mouse_x, mouse_y );
//IkbdLoop();
mouse_y += 1;
}
}
@ -591,15 +588,17 @@ static void do_events(void)
mouseb=1;
}
if ( (mouseb != prev_mouseb) ){
//if (mouseb) IkbdMousePress(2);
//else IkbdMouseRelease(2);
//Serial.println("btoggle");
//IkbdLoop();
prev_mouseb = mouseb;
}
}
}
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
void apc_Step(void)
{
exec86(8000);
@ -612,12 +611,18 @@ void apc_Step(void)
void apc_Init(void)
{
#ifdef HAS_T41
LORAM = MemPool;
RAM = MemPool + NATIVE_RAM;
#else
RAM = (uint8_t*) malloc(RAM_SIZE);
if (!RAM) emu_printf("SPI RAM malloc failed");
if (!RAM) emu_printf("RAM malloc failed");
LORAM = &LOMEM[0];
//LORAM = (uint8_t*)malloc(NATIVE_RAM);
//if (!LORAM) emu_printf("LORAM malloc failed");
#endif
installPalette();
init8253();
reset86();
@ -630,9 +635,3 @@ void apc_Start(char * filename)
initDisk(filename);
emu_printf("init done");
}

View file

@ -3,6 +3,9 @@
*/
#include "TFT_T_DMA.h"
#ifndef HAS_T4_VGA
#include "font8x8.h"
@ -1231,7 +1234,7 @@ void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap, uint16_
l++;
}
}
#endif

View file

@ -0,0 +1,53 @@
/*
Wrapping class to extend VGA_T4 to TFT_T_DMA
*/
#ifndef _VGA_T_DMAH_
#define _VGA_T_DMAH_
#ifdef __cplusplus
#include <VGA_t4.h>
#endif
#define RGBVAL16(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define RGBVAL8(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define TFT_WIDTH 640
#define TFT_REALWIDTH 640
#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 int16_t *bitmap) { drawSprite(x, y, bitmap); }
void drawSpriteNoDma(int16_t x, int16_t y, const int16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); }
};
#endif
#endif

View file

@ -5,10 +5,20 @@ extern "C" {
#include "iopins.h"
}
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
const uint16_t deflogo[] = {
0,0
};
static const uint16_t * logo = deflogo;
#else
#include "tft_t_dma.h"
//#include "logo.h"
#include "logozx80kbd.h"
#include "logozx81kbd.h"
static const uint16_t * logo = logozx80kbd;
#endif
static const unsigned short * keysw = keyswzx80;
#include "bmpjoy.h"
#include "bmpvbar.h"
#ifdef OLD_LAYOUT
@ -21,6 +31,13 @@ extern "C" {
#include <Wire.h>
#endif
#ifdef HAS_USBKEY
#include "USBHost_t36.h" // Read this header first for key info
USBHost myusb;
KeyboardController keyboard1(myusb);
#endif
static uint8_t usbnavpad=0;
#ifdef USE_SDFS
#include "uSDFS.h"
static FATFS fatfs;
@ -86,7 +103,7 @@ static File file;
#define MKEY_TFT 23
#define MKEY_VGA 24
#define MAX_FILES 32
#define MAX_FILES 64
#define MAX_FILENAME_SIZE 24
#define MAX_MENULINES (MKEY_L9)
#define TEXT_HEIGHT 16
@ -95,7 +112,7 @@ static File file;
#define MENU_FILE_YOFFSET (2*TEXT_HEIGHT)
#define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH)
#define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x20)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40)
#define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT)
#define MENU_VBAR_XOFFSET (0*TEXT_WIDTH)
#define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET)
@ -115,14 +132,10 @@ static char selection[MAX_FILENAME_SIZE+1]="";
static char files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
static int16_t calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static bool i2cKeyboardPresent = false;
//const uint16_t deflogo[] = {
// 0x0000,0x0000
//};
//static const uint16_t * logo = deflogo;
static const uint16_t * logo = logozx80kbd;
static const unsigned short * keysw = keyswzx80;
static unsigned short * keys;
static int keyMap;
const unsigned short menutouchareas[] = {
TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET,
@ -248,7 +261,7 @@ void emu_printf(int val)
void emu_printi(int val)
{
Serial.println(val);
Serial.println(val,HEX);
}
void emu_printh(int val)
@ -275,13 +288,29 @@ void * emu_Malloc(int size)
}
}
else {
emu_printf("could allocate ");
emu_printf("could allocate dynamic ");
emu_printf(size);
}
return retval;
}
void * emu_MallocI(int size)
{
void * retval = NULL;
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
emu_printf("could allocate static ");
emu_printf(size);
}
else {
emu_printf("failure to allocate");
}
return retval;
}
void emu_Free(void * pt)
{
free(pt);
@ -403,6 +432,12 @@ int emu_ReadKeys(void)
retval = ((j2 << 8) | j1);
}
if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
#ifdef PIN_KEY_USER1
if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1;
#endif
@ -578,7 +613,7 @@ bool virtualkeyboardIsActive(void) {
void toggleVirtualkeyboard(bool keepOn) {
if (keepOn) {
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbKeepOn = true;
vkbActive = true;
@ -595,7 +630,7 @@ void toggleVirtualkeyboard(bool keepOn) {
}
else {
tft.stopDMA();
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbActive = true;
exitVkbd = false;
@ -640,7 +675,7 @@ void handleVirtualkeyboard() {
if (vkeyRefresh) {
vkeyRefresh = false;
tft.drawSpriteNoDma(0,0,(uint16_t*)logo, rx, ry, rw, rh);
tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh);
}
if ( (exitVkbd) && (vkbActive) ) {
@ -655,11 +690,15 @@ void handleVirtualkeyboard() {
int emu_setKeymap(int index) {
if (index) {
#ifndef HAS_T4_VGA
logo = logozx81kbd;
#endif
keysw = keyswzx81;
}
else {
#ifndef HAS_T4_VGA
logo = logozx80kbd;
#endif
keysw = keyswzx80;
}
}
@ -733,10 +772,12 @@ void backgroundMenu(void) {
menuRedraw=true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,(uint16_t*)bmpvbar);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,bmpvbar);
#endif
#ifdef OLD_LAYOUT
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,(uint16_t*)bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,(uint16_t*)bmpvga);
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,bmpvga);
#endif
}
@ -846,7 +887,7 @@ int handleMenu(uint16_t bClick)
strcpy(selection,filename);
}
else {
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, 0xFFFF, 0x0000, true);
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true);
}
}
i++;
@ -854,8 +895,10 @@ int handleMenu(uint16_t bClick)
fileIndex++;
}
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0xff,0x00,0x00), false);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
#endif
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false);
menuRedraw=false;
}
@ -1345,11 +1388,138 @@ void emu_FileTempWrite(int addr, unsigned char val)
#endif
}
#ifdef HAS_USBKEY
void OnPress(auto key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad |= MASK_JOY2_DOWN;
break;
case 218:
usbnavpad |= MASK_JOY2_UP;
break;
case 216:
usbnavpad |= MASK_JOY2_LEFT;
break;
case 215:
usbnavpad |= MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad |= MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnDown(keymodifier, key);
}
}
void OnRelease(int key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad &= ~MASK_JOY2_DOWN;
break;
case 218:
usbnavpad &= ~MASK_JOY2_UP;
break;
case 216:
usbnavpad &= ~MASK_JOY2_LEFT;
break;
case 215:
usbnavpad &= ~MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad &= ~MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnUp(keymodifier, key);
}
}
#endif
void emu_init(void)
{
Serial.begin(115200);
#ifdef HAS_USBKEY
myusb.begin();
keyboard1.attachPress(OnPress);
keyboard1.attachRelease(OnRelease);
#endif
#ifdef USE_SDFS
strcpy(romspath,SDFSDEV);
strcat(romspath,ROMSDIR);
@ -1394,7 +1564,11 @@ void emu_init(void)
{
toggleMenu(true);
}
}
void emu_start(void)
{
#ifdef HAS_I2CKBD
byte msg[7]={0,0,0,0,0,0,0};
Wire.begin(); // join i2c bus SDA2/SCL2
@ -1420,5 +1594,9 @@ void emu_init(void)
Serial.println("i2C keyboard found");
}
#endif
}
usbnavpad = 0;
keys = key_map1;
keyMap = 0;
}

View file

@ -1,12 +1,9 @@
#ifndef EMUAPI_H
#define EMUAPI_H
#define INVX 1
//#define INVY 1
#define HAS_SND 1
#define HAS_I2CKBD 1
//#define TIMER_REND 1
#include "platform_config.h"
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
// Title: < >
@ -62,7 +59,7 @@ const unsigned short keyswzx81[] = {
TAREA_NEW_ROW,30,30,30,30,30,30,30,30,30,30,
TAREA_END};
const unsigned short keys[] = {
const unsigned short key_map1[] = {
30,31,32,33,34,35,36,37,38,39,
20,26, 8,21,23,28,25,12,18,19,
4, 9, 7,22, 4,11,13,14,15,40,
@ -96,8 +93,10 @@ const unsigned short i2ckeys[] = {
#define MASK_KEY_USER4 0x2000
extern void emu_init(void);
extern void emu_start(void);
extern void emu_resetSD(void);
extern void emu_printf(char * text);
extern void emu_printi(int val);
extern void * emu_Malloc(int size);
@ -118,6 +117,7 @@ extern void emu_FileTempWrite(int addr, unsigned char val);
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_DrawLine8(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_DrawVsync(void);
extern int emu_FrameSkip(void);
@ -131,6 +131,9 @@ extern int emu_GetPad(void);
extern int emu_ReadAnalogJoyX(int min, int max);
extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
extern void emu_KeyboardOnUp(int keymodifer, int key);
extern void emu_KeyboardOnDown(int keymodifer, int key);
extern void emu_sndPlaySound(int chan, int volume, int freq);
extern void emu_sndPlayBuzz(int size, int val);
extern void emu_sndInit();
@ -139,10 +142,10 @@ extern int emu_us(void);
extern int emu_setKeymap(int index);
extern void emu_FileTempInit(void);
extern void emu_FileTempRead(int addr, unsigned char * val, int n);
extern void emu_FileTempWrite(int addr, unsigned char val);
extern void emu_printh(int val);
#endif

View file

@ -35,13 +35,26 @@
#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 38 // UP
#define PIN_JOY1_2 36 // DOWN
#define PIN_JOY1_3 35 // 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
//#define PIN_KEY_USER3 33
//#define PIN_KEY_USER4 39
// Second joystick
#define PIN_JOY1_BTN 2
@ -49,6 +62,7 @@
#define PIN_JOY1_2 7 // DOWN
#define PIN_JOY1_3 6 // RIGHT
#define PIN_JOY1_4 5 // LEFT
#endif
#else
// OLD LAYOUT!!!!
@ -87,7 +101,3 @@
#endif
#endif

View file

@ -2,15 +2,22 @@
#define _PLATFORM_CONFIG_H_
//#define OLD_LAYOUT 1
#define HAS_T4_VGA 1
#define ILI9341 1
//#define HAS_SND 1
//#define INVX 1
//#define INVY 1
#define HAS_USBKEY 1
//#define HAS_I2CKBD 1
//#define ILI9341 1
//#define ST7789 1
//#define SWAP_JOYSTICK 1
//#define LOHRES 1
//#define ROTATE_SCREEN 1
#define EXTERNAL_SD 1
//#define EXTERNAL_SD 1
#define HAS_PSRAM 1
//#define HAS_PSRAM 1
//#define USE_SDFAT 1
//#define SD_FAT_TYPE 1

View file

@ -3,12 +3,12 @@ extern "C" {
#include "emuapi.h"
}
#include "keyboard_osd.h"
#include "tft_t_dma.h"
extern "C" {
#include "zx81.h"
}
#ifdef HAS_VGA
#include <uVGA.h>
uVGA uvga;
@ -36,7 +36,14 @@ uVGA uvga;
uint8_t * VGA_frame_buffer;
#endif
#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;
@ -60,7 +67,7 @@ void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int
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);
palette16[index] = RGBVAL16(r,g,b);
}
}
@ -70,7 +77,11 @@ void emu_DrawVsync(void)
skip += 1;
skip &= VID_FRAME_SKIP;
if (!vgaMode) {
#ifdef HAS_T4_VGA
tft.waitSync();
#else
while (vbl==vb) {};
#endif
}
#ifdef HAS_VGA
else {
@ -82,7 +93,11 @@ void emu_DrawVsync(void)
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
}
#ifdef HAS_VGA
else {
@ -100,11 +115,43 @@ void emu_DrawLine(unsigned char * VBuf, int width, int height, int line)
#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
}
}
#ifdef HAS_VGA
#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
}
}
#ifdef HAS_VGA
#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
}
}
#ifdef HAS_VGA
@ -154,8 +201,13 @@ void * emu_LineBuffer(int line)
// the setup() method runs once, when the sketch starts
// ****************************************************
void setup() {
tft.begin();
#ifdef HAS_T4_VGA
tft.begin(VGA_MODE_352x240);
// NVIC_SET_PRIORITY(IRQ_QTIMER3, 0);
#else
tft.begin();
#endif
emu_init();
myTimer.begin(vblCount, 20000); //to run every 20ms
@ -169,15 +221,16 @@ void loop(void)
if (menuActive()) {
uint16_t bClick = emu_DebounceLocalKeys();
int action = handleMenu(bClick);
char * filename = menuSelection();
char * filename = menuSelection();
if (action == ACTION_RUNTFT) {
toggleMenu(false);
vgaMode = false;
vgaMode = false;
emu_start();
emu_Init(filename);
//digitalWrite(TFT_CS, 1);
//digitalWrite(SD_CS, 1);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
tft.startDMA();
}
else if (action == ACTION_RUNVGA) {
#ifdef HAS_VGA
@ -185,6 +238,7 @@ void loop(void)
vgaMode = true;
VGA_frame_buffer = (uint8_t *)malloc((UVGA_YRES*(UVGA_XRES+UVGA_XRES_EXTRA))*sizeof(uint8_t));
uvga.set_static_framebuffer(VGA_frame_buffer);
emu_start();
emu_Init(filename);
int retvga = uvga.begin(&modeline);
Serial.println(retvga);
@ -217,6 +271,7 @@ void loop(void)
}
#ifdef HAS_SND
#include <Audio.h>
@ -224,8 +279,15 @@ void loop(void)
AudioPlaySystem mymixer;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#ifdef HAS_T4_VGA
AudioOutputI2S i2s1;
AudioConnection patchCord8(mymixer, 0, i2s1, 0);
AudioConnection patchCord9(mymixer, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
#else
AudioOutputMQS mqs;
AudioConnection patchCord9(mymixer, 0, mqs, 1);
#endif
#else
AudioOutputAnalog dac1;
AudioConnection patchCord1(mymixer, dac1);
@ -233,6 +295,10 @@ AudioConnection patchCord1(mymixer, dac1);
void emu_sndInit() {
Serial.println("sound init");
#ifdef HAS_T4_VGA
sgtl5000_1.enable();
sgtl5000_1.volume(0.6);
#endif
AudioMemory(16);
mymixer.start();
}
@ -258,6 +324,3 @@ void emu_sndPlayBuzz(int size, int val) {
//Serial.println(size);
}
#endif

View file

@ -3,6 +3,9 @@
*/
#include "TFT_T_DMA.h"
#ifndef HAS_T4_VGA
#include "font8x8.h"
@ -443,7 +446,7 @@ void TFT_T_DMA::startDMA(void) {
digitalWrite(_cs, HIGH);
SPI.begin();
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#ifdef TFT_DEBUG
PRREG(LPSPI4_CCR);
@ -1231,7 +1234,7 @@ void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap, uint16_
l++;
}
}
#endif

View file

@ -0,0 +1,53 @@
/*
Wrapping class to extend VGA_T4 to TFT_T_DMA
*/
#ifndef _VGA_T_DMAH_
#define _VGA_T_DMAH_
#ifdef __cplusplus
#include <VGA_t4.h>
#endif
#define RGBVAL16(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define RGBVAL8(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define TFT_WIDTH 320
#define TFT_REALWIDTH 320
#define TFT_HEIGHT 240
#define TFT_REALHEIGHT 240
#ifdef __cplusplus
class TFT_T_DMA: public VGA_T4
{
public:
// Fake touch screen functions
bool isTouching(void) { return false; }
void readRaw(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { }
void readCal(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { };
void callibrateTouch(uint16_t xMin,uint16_t yMin,uint16_t xMax,uint16_t yMax) { }
// fake DMA functions
void startDMA(void) { };
void stopDMA(void) { };
// fake no DMA functions
void writeScreenNoDma(const vga_pixel *pcolors) { writeScreen(pcolors); }
void fillScreenNoDma(vga_pixel color) { clear(color); }
void drawTextNoDma(int16_t x, int16_t y, const char * text, vga_pixel fgcolor, vga_pixel bgcolor, bool doublesize) { drawText(x,y,text,fgcolor,bgcolor,doublesize); }
void drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, vga_pixel color) { drawRect(x, y, w, h, color); }
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap) { drawSprite(x, y, bitmap); }
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); }
};
#endif
#endif

View file

@ -200,6 +200,7 @@ void do_interrupt()
void bitbufBlit(unsigned char * buf)
{
emu_DrawVsync();
memset( XBuf, 1, WIDTH*8 );
buf = buf + (ZX_VID_MARGIN*(ZX_VID_FULLWIDTH/8));
int y,x,i;
@ -472,6 +473,13 @@ static void initmem()
}
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
void z81_Init(void)
{
#if HAS_SND
@ -516,8 +524,7 @@ void z81_Step(void)
{
ExecZ80();
sighandler(0);
//if (strlen(tapename)) handleKeyBuf();
emu_DrawVsync();
//if (strlen(tapename)) handleKeyBuf();
updateKeyboard();
Loop8910(&ay,20);
}
@ -558,4 +565,3 @@ void z81_Start(char * filename)
ramsize = 56;
}
}

View file

@ -10,7 +10,7 @@
//#define ROTATE_SCREEN 1
#define EXTERNAL_SD 1
#define HAS_PSRAM 1
//#define HAS_PSRAM 1
//#define USE_SDFAT 1
//#define SD_FAT_TYPE 1

View file

@ -192,7 +192,7 @@ static void do_events(void)
if (hk != prev_hk) {
prev_hk == hk;
prev_hk = hk;
if ( (hk != 0) && (hk != prev_key) ) {
prev_key = hk;
IkbdKeyPress ( hk );

View file

@ -110,6 +110,12 @@ struct
/***************************************
* Exported procedures
***************************************/
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
void coc_Init(void)
{
int J;
@ -894,5 +900,3 @@ void RefreshLine3(register byte Y)
RefreshBorder(Y);
}

View file

@ -5,8 +5,17 @@ extern "C" {
#include "iopins.h"
}
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
const int16_t deflogo[] = {
0,0
};
static const int16_t * logo = deflogo;
#else
#include "tft_t_dma.h"
#include "logo.h"
#endif
#include "bmpjoy.h"
#include "bmpvbar.h"
#ifdef OLD_LAYOUT
@ -19,6 +28,13 @@ extern "C" {
#include <Wire.h>
#endif
#ifdef HAS_USBKEY
#include "USBHost_t36.h" // Read this header first for key info
USBHost myusb;
KeyboardController keyboard1(myusb);
#endif
static uint8_t usbnavpad=0;
#ifdef USE_SDFS
#include "uSDFS.h"
static FATFS fatfs;
@ -84,7 +100,7 @@ static File file;
#define MKEY_TFT 23
#define MKEY_VGA 24
#define MAX_FILES 32
#define MAX_FILES 64
#define MAX_FILENAME_SIZE 24
#define MAX_MENULINES (MKEY_L9)
#define TEXT_HEIGHT 16
@ -93,7 +109,7 @@ static File file;
#define MENU_FILE_YOFFSET (2*TEXT_HEIGHT)
#define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH)
#define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x20)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40)
#define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT)
#define MENU_VBAR_XOFFSET (0*TEXT_WIDTH)
#define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET)
@ -113,13 +129,10 @@ static char selection[MAX_FILENAME_SIZE+1]="";
static char files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
static int16_t calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static bool i2cKeyboardPresent = false;
//const uint16_t deflogo[] = {
// 0x0000,0x0000
//};
//static const uint16_t * logo = deflogo;
static unsigned short * keys;
static int keyMap;
const unsigned short menutouchareas[] = {
TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET,
@ -245,7 +258,7 @@ void emu_printf(int val)
void emu_printi(int val)
{
Serial.println(val);
Serial.println(val,HEX);
}
void emu_printh(int val)
@ -272,13 +285,29 @@ void * emu_Malloc(int size)
}
}
else {
emu_printf("could allocate ");
emu_printf("could allocate dynamic ");
emu_printf(size);
}
return retval;
}
void * emu_MallocI(int size)
{
void * retval = NULL;
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
emu_printf("could allocate static ");
emu_printf(size);
}
else {
emu_printf("failure to allocate");
}
return retval;
}
void emu_Free(void * pt)
{
free(pt);
@ -400,6 +429,12 @@ int emu_ReadKeys(void)
retval = ((j2 << 8) | j1);
}
if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
#ifdef PIN_KEY_USER1
if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1;
#endif
@ -575,7 +610,7 @@ bool virtualkeyboardIsActive(void) {
void toggleVirtualkeyboard(bool keepOn) {
if (keepOn) {
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbKeepOn = true;
vkbActive = true;
@ -592,7 +627,7 @@ void toggleVirtualkeyboard(bool keepOn) {
}
else {
tft.stopDMA();
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbActive = true;
exitVkbd = false;
@ -637,7 +672,7 @@ void handleVirtualkeyboard() {
if (vkeyRefresh) {
vkeyRefresh = false;
tft.drawSpriteNoDma(0,0,(uint16_t*)logo, rx, ry, rw, rh);
tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh);
}
if ( (exitVkbd) && (vkbActive) ) {
@ -651,10 +686,6 @@ void handleVirtualkeyboard() {
}
int emu_setKeymap(int index) {
if (index) {
}
else {
}
}
@ -726,10 +757,12 @@ void backgroundMenu(void) {
menuRedraw=true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,(uint16_t*)bmpvbar);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,bmpvbar);
#endif
#ifdef OLD_LAYOUT
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,(uint16_t*)bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,(uint16_t*)bmpvga);
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,bmpvga);
#endif
}
@ -839,7 +872,7 @@ int handleMenu(uint16_t bClick)
strcpy(selection,filename);
}
else {
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, 0xFFFF, 0x0000, true);
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true);
}
}
i++;
@ -847,8 +880,10 @@ int handleMenu(uint16_t bClick)
fileIndex++;
}
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0xff,0x00,0x00), false);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
#endif
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false);
menuRedraw=false;
}
@ -1338,11 +1373,138 @@ void emu_FileTempWrite(int addr, unsigned char val)
#endif
}
#ifdef HAS_USBKEY
void OnPress(auto key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad |= MASK_JOY2_DOWN;
break;
case 218:
usbnavpad |= MASK_JOY2_UP;
break;
case 216:
usbnavpad |= MASK_JOY2_LEFT;
break;
case 215:
usbnavpad |= MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad |= MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnDown(keymodifier, key);
}
}
void OnRelease(int key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad &= ~MASK_JOY2_DOWN;
break;
case 218:
usbnavpad &= ~MASK_JOY2_UP;
break;
case 216:
usbnavpad &= ~MASK_JOY2_LEFT;
break;
case 215:
usbnavpad &= ~MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad &= ~MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnUp(keymodifier, key);
}
}
#endif
void emu_init(void)
{
Serial.begin(115200);
#ifdef HAS_USBKEY
myusb.begin();
keyboard1.attachPress(OnPress);
keyboard1.attachRelease(OnRelease);
#endif
#ifdef USE_SDFS
strcpy(romspath,SDFSDEV);
strcat(romspath,ROMSDIR);
@ -1387,7 +1549,11 @@ void emu_init(void)
{
toggleMenu(true);
}
}
void emu_start(void)
{
#ifdef HAS_I2CKBD
byte msg[7]={0,0,0,0,0,0,0};
Wire.begin(); // join i2c bus SDA2/SCL2
@ -1413,5 +1579,9 @@ void emu_init(void)
Serial.println("i2C keyboard found");
}
#endif
}
usbnavpad = 0;
keys = key_map1;
keyMap = 0;
}

View file

@ -1,12 +1,9 @@
#ifndef EMUAPI_H
#define EMUAPI_H
#define INVX 1
//#define INVY 1
#define HAS_SND 1
#define HAS_I2CKBD 1
//#define TIMER_REND 1
#include "platform_config.h"
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
// Title: < >
@ -53,7 +50,7 @@ const unsigned short keysw[] = {
TAREA_NEW_ROW,20,20,20,
TAREA_END};
const unsigned short keys[] = {
const unsigned short key_map1[] = {
2,3,4,
5,6,7,
8,9,10,
@ -86,8 +83,10 @@ const unsigned short i2ckeys[] = {
#define MASK_KEY_USER4 0x2000
extern void emu_init(void);
extern void emu_start(void);
extern void emu_resetSD(void);
extern void emu_printf(char * text);
extern void emu_printi(int val);
extern void * emu_Malloc(int size);
@ -108,6 +107,7 @@ extern void emu_FileTempWrite(int addr, unsigned char val);
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_DrawLine8(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_DrawVsync(void);
extern int emu_FrameSkip(void);
@ -121,6 +121,9 @@ extern int emu_GetPad(void);
extern int emu_ReadAnalogJoyX(int min, int max);
extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
extern void emu_KeyboardOnUp(int keymodifer, int key);
extern void emu_KeyboardOnDown(int keymodifer, int key);
extern void emu_sndPlaySound(int chan, int volume, int freq);
extern void emu_sndPlayBuzz(int size, int val);
extern void emu_sndInit();
@ -129,9 +132,11 @@ extern int emu_us(void);
extern int emu_setKeymap(int index);
extern void emu_FileTempInit(void);
extern void emu_FileTempRead(int addr, unsigned char * val, int n);
extern void emu_FileTempWrite(int addr, unsigned char val);
extern void emu_printh(int val);
#endif

View file

@ -35,13 +35,26 @@
#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 38 // UP
#define PIN_JOY1_2 36 // DOWN
#define PIN_JOY1_3 35 // 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
//#define PIN_KEY_USER3 33
//#define PIN_KEY_USER4 39
// Second joystick
#define PIN_JOY1_BTN 2
@ -49,6 +62,7 @@
#define PIN_JOY1_2 7 // DOWN
#define PIN_JOY1_3 6 // RIGHT
#define PIN_JOY1_4 5 // LEFT
#endif
#else
// OLD LAYOUT!!!!
@ -87,7 +101,3 @@
#endif
#endif

View file

@ -2,15 +2,21 @@
#define _PLATFORM_CONFIG_H_
//#define OLD_LAYOUT 1
#define HAS_T4_VGA 1
#define ILI9341 1
//#define HAS_SND 1
//#define INVX 1
//#define INVY 1
#define HAS_USBKEY 1
//#define ILI9341 1
//#define ST7789 1
//#define SWAP_JOYSTICK 1
//#define LOHRES 1
//#define ROTATE_SCREEN 1
#define EXTERNAL_SD 1
//#define EXTERNAL_SD 1
#define HAS_PSRAM 1
//#define HAS_PSRAM 1
//#define USE_SDFAT 1
//#define SD_FAT_TYPE 1

View file

@ -3,7 +3,6 @@ extern "C" {
#include "emuapi.h"
}
#include "keyboard_osd.h"
#include "tft_t_dma.h"
extern "C" {
#include "Colem.h"
@ -36,7 +35,14 @@ uVGA uvga;
uint8_t * VGA_frame_buffer;
#endif
#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;
@ -60,7 +66,7 @@ void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int
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);
palette16[index] = RGBVAL16(r,g,b);
}
}
@ -70,7 +76,11 @@ void emu_DrawVsync(void)
skip += 1;
skip &= VID_FRAME_SKIP;
if (!vgaMode) {
#ifdef HAS_T4_VGA
tft.waitSync();
#else
while (vbl==vb) {};
#endif
}
#ifdef HAS_VGA
else {
@ -82,7 +92,11 @@ void emu_DrawVsync(void)
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
}
#ifdef HAS_VGA
else {
@ -100,11 +114,43 @@ void emu_DrawLine(unsigned char * VBuf, int width, int height, int line)
#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
}
}
#ifdef HAS_VGA
#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
}
}
#ifdef HAS_VGA
#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
}
}
#ifdef HAS_VGA
@ -154,8 +200,13 @@ void * emu_LineBuffer(int line)
// the setup() method runs once, when the sketch starts
// ****************************************************
void setup() {
tft.begin();
#ifdef HAS_T4_VGA
tft.begin(VGA_MODE_352x240);
// NVIC_SET_PRIORITY(IRQ_QTIMER3, 0);
#else
tft.begin();
#endif
emu_init();
myTimer.begin(vblCount, 20000); //to run every 20ms
@ -169,15 +220,16 @@ void loop(void)
if (menuActive()) {
uint16_t bClick = emu_DebounceLocalKeys();
int action = handleMenu(bClick);
char * filename = menuSelection();
char * filename = menuSelection();
if (action == ACTION_RUNTFT) {
toggleMenu(false);
vgaMode = false;
vgaMode = false;
emu_start();
emu_Init(filename);
//digitalWrite(TFT_CS, 1);
//digitalWrite(SD_CS, 1);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
tft.startDMA();
}
else if (action == ACTION_RUNVGA) {
#ifdef HAS_VGA
@ -185,6 +237,7 @@ void loop(void)
vgaMode = true;
VGA_frame_buffer = (uint8_t *)malloc((UVGA_YRES*(UVGA_XRES+UVGA_XRES_EXTRA))*sizeof(uint8_t));
uvga.set_static_framebuffer(VGA_frame_buffer);
emu_start();
emu_Init(filename);
int retvga = uvga.begin(&modeline);
Serial.println(retvga);
@ -209,14 +262,15 @@ void loop(void)
handleVirtualkeyboard();
#endif
if ( (!virtualkeyboardIsActive()) || (vgaMode) ) {
emu_Step();
delay(20);
emu_Step();
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
}
}
}
#ifdef HAS_SND
#include <Audio.h>
@ -224,8 +278,15 @@ void loop(void)
AudioPlaySystem mymixer;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#ifdef HAS_T4_VGA
AudioOutputI2S i2s1;
AudioConnection patchCord8(mymixer, 0, i2s1, 0);
AudioConnection patchCord9(mymixer, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
#else
AudioOutputMQS mqs;
AudioConnection patchCord9(mymixer, 0, mqs, 1);
#endif
#else
AudioOutputAnalog dac1;
AudioConnection patchCord1(mymixer, dac1);
@ -233,6 +294,10 @@ AudioConnection patchCord1(mymixer, dac1);
void emu_sndInit() {
Serial.println("sound init");
#ifdef HAS_T4_VGA
sgtl5000_1.enable();
sgtl5000_1.volume(0.6);
#endif
AudioMemory(16);
mymixer.start();
}

View file

@ -3,6 +3,9 @@
*/
#include "TFT_T_DMA.h"
#ifndef HAS_T4_VGA
#include "font8x8.h"
@ -1231,7 +1234,7 @@ void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap, uint16_
l++;
}
}
#endif

View file

@ -0,0 +1,50 @@
/*
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 256
#define TFT_REALWIDTH 320
#define TFT_HEIGHT 192
#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 int16_t *bitmap) { drawSprite(x, y, bitmap); }
void drawSpriteNoDma(int16_t x, int16_t y, const int16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); }
};
#endif
#endif

View file

@ -2,7 +2,6 @@
#include "emuapi.h"
#include "tft_t_dma.h"
#include "psram_t.h"
#include "iopins.h"
extern "C" {
@ -10,6 +9,29 @@ extern "C" {
#include "system.h"
}
#ifdef HAS_T41
EXTMEM static unsigned char MemPool[8*1024*1024];
extern "C" uint8 read_rom(int address) {
return (MemPool[address]);
}
extern "C" uint8 readb_swap_rom(int address) {
return (MemPool[address^1]);
}
extern "C" uint16 readw_swap_rom(int address) {
return ((MemPool[address+1]<<8) + MemPool[address]);
}
extern "C" void write_rom(int address, uint8 val) {
MemPool[address]=val;
}
#else
#include "psram_t.h"
PSRAM_T psram = PSRAM_T(PSRAM_CS, PSRAM_MOSI, PSRAM_SCLK, PSRAM_MISO);
extern "C" uint8 read_rom(int address) {
@ -27,6 +49,8 @@ extern "C" void write_rom(int address, uint8 val) {
psram.pswrite(address,val);
}
#endif
static uint8 romversion;
extern "C" uint8 rom_version(void) {
return romversion;
@ -47,11 +71,18 @@ static deinterleave_block(int offset, int srcoffset)
}
}
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
void gen_Init(void)
{
emu_printf("Allocating MEM");
#ifndef HAS_T41
psram.begin();
#endif
mem_init();
emu_printf("Allocating MEM done");
}
@ -167,7 +198,3 @@ audio_play_sample(stream, 0, len);
#endif
#endif
}

View file

@ -5,8 +5,17 @@ extern "C" {
#include "iopins.h"
}
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
const uint16_t deflogo[] = {
0,0
};
static const uint16_t * logo = deflogo;
#else
#include "tft_t_dma.h"
#include "logo.h"
#endif
#include "bmpjoy.h"
#include "bmpvbar.h"
#ifdef OLD_LAYOUT
@ -19,6 +28,13 @@ extern "C" {
#include <Wire.h>
#endif
#ifdef HAS_USBKEY
#include "USBHost_t36.h" // Read this header first for key info
USBHost myusb;
KeyboardController keyboard1(myusb);
#endif
static uint8_t usbnavpad=0;
#ifdef USE_SDFS
#include "uSDFS.h"
static FATFS fatfs;
@ -84,7 +100,7 @@ static File file;
#define MKEY_TFT 23
#define MKEY_VGA 24
#define MAX_FILES 32
#define MAX_FILES 64
#define MAX_FILENAME_SIZE 24
#define MAX_MENULINES (MKEY_L9)
#define TEXT_HEIGHT 16
@ -93,7 +109,7 @@ static File file;
#define MENU_FILE_YOFFSET (2*TEXT_HEIGHT)
#define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH)
#define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x20)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40)
#define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT)
#define MENU_VBAR_XOFFSET (0*TEXT_WIDTH)
#define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET)
@ -113,13 +129,10 @@ static char selection[MAX_FILENAME_SIZE+1]="";
static char files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
static int16_t calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static bool i2cKeyboardPresent = false;
//const uint16_t deflogo[] = {
// 0x0000,0x0000
//};
//static const uint16_t * logo = deflogo;
static unsigned short * keys;
static int keyMap;
const unsigned short menutouchareas[] = {
TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET,
@ -245,7 +258,7 @@ void emu_printf(int val)
void emu_printi(int val)
{
Serial.println(val);
Serial.println(val,HEX);
}
void emu_printh(int val)
@ -272,13 +285,29 @@ void * emu_Malloc(int size)
}
}
else {
emu_printf("could allocate ");
emu_printf("could allocate dynamic ");
emu_printf(size);
}
return retval;
}
void * emu_MallocI(int size)
{
void * retval = NULL;
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
emu_printf("could allocate static ");
emu_printf(size);
}
else {
emu_printf("failure to allocate");
}
return retval;
}
void emu_Free(void * pt)
{
free(pt);
@ -400,6 +429,12 @@ int emu_ReadKeys(void)
retval = ((j2 << 8) | j1);
}
if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
#ifdef PIN_KEY_USER1
if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1;
#endif
@ -575,7 +610,7 @@ bool virtualkeyboardIsActive(void) {
void toggleVirtualkeyboard(bool keepOn) {
if (keepOn) {
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbKeepOn = true;
vkbActive = true;
@ -592,7 +627,7 @@ void toggleVirtualkeyboard(bool keepOn) {
}
else {
tft.stopDMA();
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbActive = true;
exitVkbd = false;
@ -637,7 +672,7 @@ void handleVirtualkeyboard() {
if (vkeyRefresh) {
vkeyRefresh = false;
tft.drawSpriteNoDma(0,0,(uint16_t*)logo, rx, ry, rw, rh);
tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh);
}
if ( (exitVkbd) && (vkbActive) ) {
@ -651,10 +686,6 @@ void handleVirtualkeyboard() {
}
int emu_setKeymap(int index) {
if (index) {
}
else {
}
}
@ -726,10 +757,12 @@ void backgroundMenu(void) {
menuRedraw=true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,(uint16_t*)bmpvbar);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,bmpvbar);
#endif
#ifdef OLD_LAYOUT
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,(uint16_t*)bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,(uint16_t*)bmpvga);
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,bmpvga);
#endif
}
@ -839,7 +872,7 @@ int handleMenu(uint16_t bClick)
strcpy(selection,filename);
}
else {
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, 0xFFFF, 0x0000, true);
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true);
}
}
i++;
@ -847,8 +880,10 @@ int handleMenu(uint16_t bClick)
fileIndex++;
}
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0xff,0x00,0x00), false);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
#endif
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false);
menuRedraw=false;
}
@ -1338,11 +1373,138 @@ void emu_FileTempWrite(int addr, unsigned char val)
#endif
}
#ifdef HAS_USBKEY
void OnPress(auto key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad |= MASK_JOY2_DOWN;
break;
case 218:
usbnavpad |= MASK_JOY2_UP;
break;
case 216:
usbnavpad |= MASK_JOY2_LEFT;
break;
case 215:
usbnavpad |= MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad |= MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnDown(keymodifier, key);
}
}
void OnRelease(int key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad &= ~MASK_JOY2_DOWN;
break;
case 218:
usbnavpad &= ~MASK_JOY2_UP;
break;
case 216:
usbnavpad &= ~MASK_JOY2_LEFT;
break;
case 215:
usbnavpad &= ~MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad &= ~MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnUp(keymodifier, key);
}
}
#endif
void emu_init(void)
{
Serial.begin(115200);
#ifdef HAS_USBKEY
myusb.begin();
keyboard1.attachPress(OnPress);
keyboard1.attachRelease(OnRelease);
#endif
#ifdef USE_SDFS
strcpy(romspath,SDFSDEV);
strcat(romspath,ROMSDIR);
@ -1387,7 +1549,11 @@ void emu_init(void)
{
toggleMenu(true);
}
}
void emu_start(void)
{
#ifdef HAS_I2CKBD
byte msg[7]={0,0,0,0,0,0,0};
Wire.begin(); // join i2c bus SDA2/SCL2
@ -1413,5 +1579,9 @@ void emu_init(void)
Serial.println("i2C keyboard found");
}
#endif
}
usbnavpad = 0;
keys = key_map1;
keyMap = 0;
}

View file

@ -1,14 +1,16 @@
#ifndef EMUAPI_H
#define EMUAPI_H
//#define INVX 1
//#define INVY 1
#define HAS_SND 1
#include "platform_config.h"
#define CUSTOM_SND 1
//#define HAS_I2CKBD 1
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10 //0x9000
#ifdef HAS_T4_VGA
#define EXTRA_HEAP 0x10000
#else
#define EXTRA_HEAP 0x10
#endif
// Title: < >
#define TITLE " Genesis Emulator "
@ -18,7 +20,7 @@
#define emu_Step(x) {gen_Step();}
#define emu_Input(x) {gen_Input(x);}
#define PALETTE_SIZE 2
#define PALETTE_SIZE 1
#define VID_FRAME_SKIP 0x0
#define TFT_VBUFFER_YCROP 0
#define SINGLELINE_RENDERING 1
@ -57,7 +59,7 @@ const unsigned short keysw[]=
//TAREA_NEW_ROW,18,18,18,18,18,18,18,18,18,18,
TAREA_END};
const unsigned short keys[]={
const unsigned short key_map1[]={
59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
109,110,111,112,106,107,108,17,18,19,
@ -101,17 +103,17 @@ const unsigned short i2ckeys[] = {
extern "C" {
#endif
extern void emu_init(void);
extern void emu_start(void);
extern void emu_printf(char * text);
extern void emu_printi(int val);
extern void emu_printh(int val);
extern void * emu_Malloc(int size);
extern void emu_Free(void * pt);
extern int emu_FileOpen(char * filename);
extern int emu_FileRead(char * buf, int size);
extern unsigned char emu_FileGetc(void);
extern int emu_FileTell(void);
extern int emu_FileSeek(int seek);
extern void emu_FileClose(void);
extern int emu_FileSize(char * filename);
@ -124,6 +126,7 @@ extern void emu_FileTempWrite(int addr, unsigned char val);
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_DrawLine8(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_DrawVsync(void);
extern int emu_FrameSkip(void);
@ -137,6 +140,9 @@ extern int emu_GetPad(void);
extern int emu_ReadAnalogJoyX(int min, int max);
extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
extern void emu_KeyboardOnUp(int keymodifer, int key);
extern void emu_KeyboardOnDown(int keymodifer, int key);
extern void emu_sndPlaySound(int chan, int volume, int freq);
extern void emu_sndPlayBuzz(int size, int val);
extern void emu_sndInit();
@ -145,12 +151,14 @@ extern int emu_us(void);
extern int emu_setKeymap(int index);
extern void emu_FileTempInit(void);
extern void emu_FileTempRead(int addr, unsigned char * val, int n);
extern void emu_FileTempWrite(int addr, unsigned char val);
extern void emu_printh(int val);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -35,13 +35,26 @@
#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 38 // UP
#define PIN_JOY1_2 36 // DOWN
#define PIN_JOY1_3 35 // 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
//#define PIN_KEY_USER3 33
//#define PIN_KEY_USER4 39
// Second joystick
#define PIN_JOY1_BTN 2
@ -49,6 +62,7 @@
#define PIN_JOY1_2 7 // DOWN
#define PIN_JOY1_3 6 // RIGHT
#define PIN_JOY1_4 5 // LEFT
#endif
#else
// OLD LAYOUT!!!!
@ -87,7 +101,3 @@
#endif
#endif

View file

@ -2,15 +2,22 @@
#define _PLATFORM_CONFIG_H_
//#define OLD_LAYOUT 1
#define HAS_T41 1
#define HAS_T4_VGA 1
#define ILI9341 1
//#define HAS_SND 1
//#define INVX 1
//#define INVY 1
#define HAS_USBKEY 1
//#define ILI9341 1
//#define ST7789 1
//#define SWAP_JOYSTICK 1
//#define LOHRES 1
//#define ROTATE_SCREEN 1
#define EXTERNAL_SD 1
//#define EXTERNAL_SD 1
#define HAS_PSRAM 1
//#define HAS_PSRAM 1
//#define USE_SDFAT 1
//#define SD_FAT_TYPE 1

View file

@ -240,7 +240,6 @@ Serial.printf("D") ; Serial.flush();
#include "emuapi.h"
PSRAM_T::PSRAM_T(uint8_t cs, uint8_t mosi, uint8_t sclk, uint8_t miso)
{
}
@ -386,4 +385,3 @@ uint16_t PSRAM_T::psread_w(uint32_t addr)
psram_read_n(curPage,&(pages[top].page[0]),PAGE_SIZE);
return (pages[top].page[offs+1]<<8) + pages[top].page[offs];
}

View file

@ -7,6 +7,14 @@
#include "shared.h"
#include "platform_config.h"
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
#endif
extern void emu_DrawLine16(unsigned short *src, int width , int height, int line);
extern void emu_printf(char * text);
#ifdef ALIGN_LONG
@ -14,6 +22,27 @@
#undef READ_LONG
#undef WRITE_LONG
if(reg[12] & 8)
{
int j;
for(j = 0; j < 3; j += 1)
{
color = &vdp_palette[j][data];
set_color((j << 6), color);
}
}
else
{
color = &vdp_palette[1][data];
set_color(0x00, color);
set_color(0x40, color);
set_color(0x80, color);
}
static __inline__ uint32 READ_LONG(void *address)
{
if ((uint32)address & 3)
@ -155,6 +184,9 @@ static __inline__ void WRITE_LONG(void *address, uint32 data)
/* Pixel creation macros, input is four bits each */
/* 3:3:2 RGB */
#define MAKE_PIXEL_8(r,g,b) ((r) << 5 | (g) << 2 | ((b) >> 1))
/* 5:6:5 RGB */
#define MAKE_PIXEL_16(r,g,b) ((r) << 12 | (g) << 7 | (b) << 1)
@ -229,6 +261,7 @@ int render_init(void)
pixel_16_lut[2][i] = MAKE_PIXEL_16(r|8,g|8,b|8);
}
/* Set up color update function */
color_update = color_update_16;
@ -283,6 +316,7 @@ void render_reset(void)
memset(ntb_buf, 0, sizeof(ntb_buf));
memset(obj_buf, 0, sizeof(obj_buf));
//memset(&pixel_8, 0, sizeof(pixel_8));
memset(&pixel_16, 0, sizeof(pixel_16));
}
@ -363,12 +397,8 @@ void render_line(int line)
int width = (reg[12] & 1) ? 320 : 256;
remap_16(lb+0x20, line_buf, pixel_16, width);
emu_DrawLine16(line_buf, width ,256, line);
//remap_16(lb+0x20, emu_LineBuffer(line), pixel_16, width);
}
/*--------------------------------------------------------------------------*/
/* Window rendering */
@ -770,18 +800,6 @@ void window_clip(int line)
/*--------------------------------------------------------------------------*/
/* Remap functions */
/*--------------------------------------------------------------------------*/
/*
void remap_8(uint8 *src, uint8 *dst, uint8 *table, int length)
{
int count;
for(count = 0; count < length; count += 1)
{
*dst++ = table[*src++];
}
}
*/
void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length)
{
int count;
@ -808,6 +826,7 @@ void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width)
}
}
void color_update_16(int index, uint16 data)
{
if(reg[12] & 8)
@ -1044,4 +1063,3 @@ void render_obj_im2(int line, uint8 *buf, uint8 *table)
}
}
}

View file

@ -1,40 +1,39 @@
#ifndef _RENDER_H_
#define _RENDER_H_
/* Look-up pixel table information */
#define LUT_MAX (5)
#define LUT_SIZE (0x10000)
/* Clip structure */
typedef struct
{
uint8 left;
uint8 right;
uint8 enable;
}clip_t;
/* Function prototypes */
int render_init(void);
void render_reset(void);
void render_shutdown(void);
void render_line(int line);
void render_obj(int line, uint8 *buf, uint8 *table);
void render_obj_im2(int line, uint8 *buf, uint8 *table);
void render_ntw(int line, uint8 *buf);
void render_ntw_im2(int line, uint8 *buf);
void render_ntx(int which, int line, uint8 *buf);
void render_ntx_im2(int which, int line, uint8 *buf);
void render_ntx_vs(int which, int line, uint8 *buf);
void update_bg_pattern_cache(void);
void get_hscroll(int line, uint16 *scrolla, uint16 *scrollb);
void window_clip(int line);
void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length);
void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width);
void color_update_16(int index, uint16 data);
void make_name_lut(void);
void parse_satb(int line);
#endif /* _RENDER_H_ */
#ifndef _RENDER_H_
#define _RENDER_H_
/* Look-up pixel table information */
#define LUT_MAX (5)
#define LUT_SIZE (0x10000)
/* Clip structure */
typedef struct
{
uint8 left;
uint8 right;
uint8 enable;
}clip_t;
/* Function prototypes */
int render_init(void);
void render_reset(void);
void render_shutdown(void);
void render_line(int line);
void render_obj(int line, uint8 *buf, uint8 *table);
void render_obj_im2(int line, uint8 *buf, uint8 *table);
void render_ntw(int line, uint8 *buf);
void render_ntw_im2(int line, uint8 *buf);
void render_ntx(int which, int line, uint8 *buf);
void render_ntx_im2(int which, int line, uint8 *buf);
void render_ntx_vs(int which, int line, uint8 *buf);
void update_bg_pattern_cache(void);
void get_hscroll(int line, uint16 *scrolla, uint16 *scrollb);
void window_clip(int line);
void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length);
void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width);
void color_update_16(int index, uint16 data);
void make_name_lut(void);
void parse_satb(int line);
#endif /* _RENDER_H_ */

View file

@ -1,8 +1,9 @@
#include "iopins.h"
#include "emuapi.h"
extern "C" {
#include "iopins.h"
#include "emuapi.h"
}
#include "keyboard_osd.h"
#include "tft_t_dma.h"
#include "emu.h"
@ -33,7 +34,14 @@ uVGA uvga;
uint8_t * VGA_frame_buffer;
#endif
#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;
@ -55,9 +63,8 @@ static void vblCount() {
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);
palette16[index] = RGBVAL16(r,g,b);
}
}
@ -67,7 +74,11 @@ void emu_DrawVsync(void)
skip += 1;
skip &= VID_FRAME_SKIP;
if (!vgaMode) {
#ifdef HAS_T4_VGA
tft.waitSync();
#else
while (vbl==vb) {};
#endif
}
#ifdef HAS_VGA
else {
@ -79,7 +90,11 @@ void emu_DrawVsync(void)
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
}
#ifdef HAS_VGA
else {
@ -97,11 +112,28 @@ void emu_DrawLine(unsigned char * VBuf, int width, int height, int line)
#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
}
}
#ifdef HAS_VGA
#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
}
}
#ifdef HAS_VGA
@ -112,7 +144,11 @@ 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
}
}
#ifdef HAS_VGA
@ -162,14 +198,18 @@ void * emu_LineBuffer(int line)
// the setup() method runs once, when the sketch starts
// ****************************************************
void setup() {
tft.begin();
#ifdef HAS_T4_VGA
tft.begin(VGA_MODE_320x240);
// NVIC_SET_PRIORITY(IRQ_QTIMER3, 0);
#else
tft.begin();
#endif
emu_init();
myTimer.begin(vblCount, 20000); //to run every 20ms
myTimer.begin(vblCount, 20000); //to run every 20ms
}
// ****************************************************
// the loop() method runs continuously
// ****************************************************
@ -178,13 +218,16 @@ void loop(void)
if (menuActive()) {
uint16_t bClick = emu_DebounceLocalKeys();
int action = handleMenu(bClick);
char * filename = menuSelection();
char * filename = menuSelection();
if (action == ACTION_RUNTFT) {
toggleMenu(false);
vgaMode = false;
emu_Init(filename);
vgaMode = false;
emu_start();
emu_Init(filename);
//digitalWrite(TFT_CS, 1);
//digitalWrite(SD_CS, 1);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
tft.startDMA();
}
else if (action == ACTION_RUNVGA) {
#ifdef HAS_VGA
@ -192,6 +235,7 @@ void loop(void)
vgaMode = true;
VGA_frame_buffer = (uint8_t *)malloc((UVGA_YRES*(UVGA_XRES+UVGA_XRES_EXTRA))*sizeof(uint8_t));
uvga.set_static_framebuffer(VGA_frame_buffer);
emu_start();
emu_Init(filename);
int retvga = uvga.begin(&modeline);
Serial.println(retvga);
@ -216,13 +260,15 @@ void loop(void)
handleVirtualkeyboard();
#endif
if ( (!virtualkeyboardIsActive()) || (vgaMode) ) {
emu_Step();
uint16_t bClick = 0; //emu_DebounceLocalKeys();
emu_Step();
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
}
}
}
#ifdef HAS_SND
#include <Audio.h>
@ -230,8 +276,15 @@ void loop(void)
AudioPlaySystem mymixer;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#ifdef HAS_T4_VGA
AudioOutputI2S i2s1;
AudioConnection patchCord8(mymixer, 0, i2s1, 0);
AudioConnection patchCord9(mymixer, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
#else
AudioOutputMQS mqs;
AudioConnection patchCord9(mymixer, 0, mqs, 1);
#endif
#else
AudioOutputAnalog dac1;
AudioConnection patchCord1(mymixer, dac1);
@ -239,6 +292,10 @@ AudioConnection patchCord1(mymixer, dac1);
void emu_sndInit() {
Serial.println("sound init");
#ifdef HAS_T4_VGA
sgtl5000_1.enable();
sgtl5000_1.volume(0.6);
#endif
AudioMemory(16);
mymixer.start();
}

View file

@ -3,6 +3,9 @@
*/
#include "TFT_T_DMA.h"
#ifndef HAS_T4_VGA
#include "font8x8.h"
@ -1231,7 +1234,7 @@ void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap, uint16_
l++;
}
}
#endif

View file

@ -0,0 +1,53 @@
/*
Wrapping class to extend VGA_T4 to TFT_T_DMA
*/
#ifndef _VGA_T_DMAH_
#define _VGA_T_DMAH_
#ifdef __cplusplus
#include <VGA_t4.h>
#endif
#define RGBVAL16(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define RGBVAL8(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define TFT_WIDTH 320
#define TFT_REALWIDTH 320
#define TFT_HEIGHT 240
#define TFT_REALHEIGHT 240
#ifdef __cplusplus
class TFT_T_DMA: public VGA_T4
{
public:
// Fake touch screen functions
bool isTouching(void) { return false; }
void readRaw(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { }
void readCal(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { };
void callibrateTouch(uint16_t xMin,uint16_t yMin,uint16_t xMax,uint16_t yMax) { }
// fake DMA functions
void startDMA(void) { };
void stopDMA(void) { };
// fake no DMA functions
void writeScreenNoDma(const vga_pixel *pcolors) { writeScreen(pcolors); }
void fillScreenNoDma(vga_pixel color) { clear(color); }
void drawTextNoDma(int16_t x, int16_t y, const char * text, vga_pixel fgcolor, vga_pixel bgcolor, bool doublesize) { drawText(x,y,text,fgcolor,bgcolor,doublesize); }
void drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, vga_pixel color) { drawRect(x, y, w, h, color); }
void drawSpriteNoDma(int16_t x, int16_t y, const int16_t *bitmap) { drawSprite(x, y, bitmap); }
void drawSpriteNoDma(int16_t x, int16_t y, const int16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); }
};
#endif
#endif

View file

@ -1,7 +1,6 @@
#include <string.h>
#include "emuapi.h"
#include "tft_t_dma.h"
#include "psram_t.h"
#include "iopins.h"
@ -21,27 +20,39 @@ extern "C" {
#include "loader.h"
}
static int rom_offset = 0;
PSRAM_T psram = PSRAM_T(PSRAM_CS, PSRAM_MOSI, PSRAM_SCLK, PSRAM_MISO);
#ifdef HAS_T41
EXTMEM static unsigned char MemPool[8*1024*1024];
extern "C" uint8 read_rom(int address) {
return (MemPool[address+rom_offset]);
}
extern "C" void write_rom(int address, uint8 val) {
MemPool[address]=val;
}
#else
#include "psram_t.h"
PSRAM_T psram = PSRAM_T(PSRAM_CS, PSRAM_MOSI, PSRAM_SCLK, PSRAM_MISO);
extern "C" uint8 read_rom(int address) {
return (psram.psread(address+rom_offset));
}
//extern "C" uint8 readb_swap_rom(int address) {
// return(psram.psread(address^1));
//}
//extern "C" uint16 readw_swap_rom(int address) {
// return psram.psread_w(address);
//}
extern "C" void write_rom(int address, uint8 val) {
psram.pswrite(address,val);
}
#endif
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
@ -49,7 +60,9 @@ extern "C" void write_rom(int address, uint8 val) {
void gbe_Init(void)
{
emu_printf("Allocating MEM");
#ifndef HAS_T41
psram.begin();
#endif
mem_init();
emu_printf("Allocating MEM done");
}
@ -98,8 +111,10 @@ void gbe_Start(char * Cartridge)
cpu_reset();
mbc_reset();
#ifdef SOUND_PRESENT
#ifdef HAS_SND
sound_reset(22050);
emu_sndInit();
emu_sndInit();
#endif
#endif
lcd_begin();
emu_printf("init done");
@ -151,7 +166,3 @@ void SND_Process(void *stream, int len) {
#endif
#endif
}

View file

@ -5,8 +5,17 @@ extern "C" {
#include "iopins.h"
}
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
const uint16_t deflogo[] = {
0,0
};
static const uint16_t * logo = deflogo;
#else
#include "tft_t_dma.h"
#include "logo.h"
#endif
#include "bmpjoy.h"
#include "bmpvbar.h"
#ifdef OLD_LAYOUT
@ -19,6 +28,13 @@ extern "C" {
#include <Wire.h>
#endif
#ifdef HAS_USBKEY
#include "USBHost_t36.h" // Read this header first for key info
USBHost myusb;
KeyboardController keyboard1(myusb);
#endif
static uint8_t usbnavpad=0;
#ifdef USE_SDFS
#include "uSDFS.h"
static FATFS fatfs;
@ -84,7 +100,7 @@ static File file;
#define MKEY_TFT 23
#define MKEY_VGA 24
#define MAX_FILES 32
#define MAX_FILES 64
#define MAX_FILENAME_SIZE 24
#define MAX_MENULINES (MKEY_L9)
#define TEXT_HEIGHT 16
@ -93,7 +109,7 @@ static File file;
#define MENU_FILE_YOFFSET (2*TEXT_HEIGHT)
#define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH)
#define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x20)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40)
#define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT)
#define MENU_VBAR_XOFFSET (0*TEXT_WIDTH)
#define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET)
@ -113,13 +129,10 @@ static char selection[MAX_FILENAME_SIZE+1]="";
static char files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
static int16_t calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static bool i2cKeyboardPresent = false;
//const uint16_t deflogo[] = {
// 0x0000,0x0000
//};
//static const uint16_t * logo = deflogo;
static unsigned short * keys;
static int keyMap;
const unsigned short menutouchareas[] = {
TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET,
@ -245,7 +258,7 @@ void emu_printf(int val)
void emu_printi(int val)
{
Serial.println(val);
Serial.println(val,HEX);
}
void emu_printh(int val)
@ -272,13 +285,29 @@ void * emu_Malloc(int size)
}
}
else {
emu_printf("could allocate ");
emu_printf("could allocate dynamic ");
emu_printf(size);
}
return retval;
}
void * emu_MallocI(int size)
{
void * retval = NULL;
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
emu_printf("could allocate static ");
emu_printf(size);
}
else {
emu_printf("failure to allocate");
}
return retval;
}
void emu_Free(void * pt)
{
free(pt);
@ -400,6 +429,12 @@ int emu_ReadKeys(void)
retval = ((j2 << 8) | j1);
}
if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
#ifdef PIN_KEY_USER1
if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1;
#endif
@ -413,7 +448,7 @@ int emu_ReadKeys(void)
if ( digitalRead(PIN_KEY_USER4) == LOW ) retval |= MASK_KEY_USER4;
#endif
//Serial.println(retval,HEX);
// Serial.println(retval,HEX);
if ( ((retval & (MASK_KEY_USER1+MASK_KEY_USER2)) == (MASK_KEY_USER1+MASK_KEY_USER2))
|| (retval & MASK_KEY_USER4 ) )
@ -575,7 +610,7 @@ bool virtualkeyboardIsActive(void) {
void toggleVirtualkeyboard(bool keepOn) {
if (keepOn) {
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbKeepOn = true;
vkbActive = true;
@ -592,7 +627,7 @@ void toggleVirtualkeyboard(bool keepOn) {
}
else {
tft.stopDMA();
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbActive = true;
exitVkbd = false;
@ -637,7 +672,7 @@ void handleVirtualkeyboard() {
if (vkeyRefresh) {
vkeyRefresh = false;
tft.drawSpriteNoDma(0,0,(uint16_t*)logo, rx, ry, rw, rh);
tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh);
}
if ( (exitVkbd) && (vkbActive) ) {
@ -651,10 +686,6 @@ void handleVirtualkeyboard() {
}
int emu_setKeymap(int index) {
if (index) {
}
else {
}
}
@ -726,10 +757,12 @@ void backgroundMenu(void) {
menuRedraw=true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,(uint16_t*)bmpvbar);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,bmpvbar);
#endif
#ifdef OLD_LAYOUT
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,(uint16_t*)bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,(uint16_t*)bmpvga);
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,bmpvga);
#endif
}
@ -839,7 +872,7 @@ int handleMenu(uint16_t bClick)
strcpy(selection,filename);
}
else {
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, 0xFFFF, 0x0000, true);
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true);
}
}
i++;
@ -847,8 +880,10 @@ int handleMenu(uint16_t bClick)
fileIndex++;
}
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0xff,0x00,0x00), false);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
#endif
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false);
menuRedraw=false;
}
@ -1338,11 +1373,138 @@ void emu_FileTempWrite(int addr, unsigned char val)
#endif
}
#ifdef HAS_USBKEY
void OnPress(auto key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad |= MASK_JOY2_DOWN;
break;
case 218:
usbnavpad |= MASK_JOY2_UP;
break;
case 216:
usbnavpad |= MASK_JOY2_LEFT;
break;
case 215:
usbnavpad |= MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad |= MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnDown(keymodifier, key);
}
}
void OnRelease(int key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad &= ~MASK_JOY2_DOWN;
break;
case 218:
usbnavpad &= ~MASK_JOY2_UP;
break;
case 216:
usbnavpad &= ~MASK_JOY2_LEFT;
break;
case 215:
usbnavpad &= ~MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad &= ~MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnUp(keymodifier, key);
}
}
#endif
void emu_init(void)
{
Serial.begin(115200);
#ifdef HAS_USBKEY
myusb.begin();
keyboard1.attachPress(OnPress);
keyboard1.attachRelease(OnRelease);
#endif
#ifdef USE_SDFS
strcpy(romspath,SDFSDEV);
strcat(romspath,ROMSDIR);
@ -1387,7 +1549,11 @@ void emu_init(void)
{
toggleMenu(true);
}
}
void emu_start(void)
{
#ifdef HAS_I2CKBD
byte msg[7]={0,0,0,0,0,0,0};
Wire.begin(); // join i2c bus SDA2/SCL2
@ -1413,5 +1579,9 @@ void emu_init(void)
Serial.println("i2C keyboard found");
}
#endif
}
usbnavpad = 0;
keys = key_map1;
keyMap = 0;
}

View file

@ -1,11 +1,9 @@
#ifndef EMUAPI_H
#define EMUAPI_H
//#define INVX 1
//#define INVY 1
#define HAS_SND 1
#include "platform_config.h"
#define CUSTOM_SND 1
//#define HAS_I2CKBD 1
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10 //0x9000
@ -57,7 +55,7 @@ const unsigned short keysw[]=
//TAREA_NEW_ROW,18,18,18,18,18,18,18,18,18,18,
TAREA_END};
const unsigned short keys[]={
const unsigned short key_map1[]={
59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
109,110,111,112,106,107,108,17,18,19,
@ -101,17 +99,17 @@ const unsigned short i2ckeys[] = {
extern "C" {
#endif
extern void emu_init(void);
extern void emu_start(void);
extern void emu_resetSD(void);
extern void emu_printf(char * text);
extern void emu_printi(int val);
extern void emu_printh(int val);
extern void * emu_Malloc(int size);
extern void emu_Free(void * pt);
extern int emu_FileOpen(char * filename);
extern int emu_FileRead(char * buf, int size);
extern unsigned char emu_FileGetc(void);
extern int emu_FileTell(void);
extern int emu_FileSeek(int seek);
extern void emu_FileClose(void);
extern int emu_FileSize(char * filename);
@ -124,6 +122,7 @@ extern void emu_FileTempWrite(int addr, unsigned char val);
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_DrawLine8(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_DrawVsync(void);
extern int emu_FrameSkip(void);
@ -137,6 +136,9 @@ extern int emu_GetPad(void);
extern int emu_ReadAnalogJoyX(int min, int max);
extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
extern void emu_KeyboardOnUp(int keymodifer, int key);
extern void emu_KeyboardOnDown(int keymodifer, int key);
extern void emu_sndPlaySound(int chan, int volume, int freq);
extern void emu_sndPlayBuzz(int size, int val);
extern void emu_sndInit();
@ -145,12 +147,14 @@ extern int emu_us(void);
extern int emu_setKeymap(int index);
extern void emu_FileTempInit(void);
extern void emu_FileTempRead(int addr, unsigned char * val, int n);
extern void emu_FileTempWrite(int addr, unsigned char val);
extern void emu_printh(int val);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -35,13 +35,26 @@
#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 38 // UP
#define PIN_JOY1_2 36 // DOWN
#define PIN_JOY1_3 35 // 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
//#define PIN_KEY_USER3 33
//#define PIN_KEY_USER4 39
// Second joystick
#define PIN_JOY1_BTN 2
@ -49,6 +62,7 @@
#define PIN_JOY1_2 7 // DOWN
#define PIN_JOY1_3 6 // RIGHT
#define PIN_JOY1_4 5 // LEFT
#endif
#else
// OLD LAYOUT!!!!
@ -87,7 +101,3 @@
#endif
#endif

View file

@ -2,15 +2,22 @@
#define _PLATFORM_CONFIG_H_
//#define OLD_LAYOUT 1
#define HAS_T41 1
#define HAS_T4_VGA 1
#define ILI9341 1
#define HAS_SND 1
//#define INVX 1
//#define INVY 1
#define HAS_USBKEY 1
//#define ILI9341 1
//#define ST7789 1
//#define SWAP_JOYSTICK 1
//#define LOHRES 1
//#define ROTATE_SCREEN 1
#define EXTERNAL_SD 1
//#define EXTERNAL_SD 1
#define HAS_PSRAM 1
//#define HAS_PSRAM 1
//#define USE_SDFAT 1
//#define SD_FAT_TYPE 1

View file

@ -1,8 +1,9 @@
#include "iopins.h"
#include "emuapi.h"
extern "C" {
#include "iopins.h"
#include "emuapi.h"
}
#include "keyboard_osd.h"
#include "tft_t_dma.h"
#include "emu.h"
@ -33,7 +34,13 @@ uVGA uvga;
uint8_t * VGA_frame_buffer;
#endif
#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;
@ -43,6 +50,9 @@ static IntervalTimer myTimer;
volatile boolean vbl=true;
static int skip=0;
static elapsedMicros tius;
volatile int16_t mClick=0;
static void vblCount() {
if (vbl) {
@ -67,7 +77,11 @@ void emu_DrawVsync(void)
skip += 1;
skip &= VID_FRAME_SKIP;
if (!vgaMode) {
#ifdef HAS_T4_VGA
tft.waitSync();
#else
while (vbl==vb) {};
#endif
}
#ifdef HAS_VGA
else {
@ -79,7 +93,11 @@ void emu_DrawVsync(void)
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
}
#ifdef HAS_VGA
else {
@ -97,11 +115,28 @@ void emu_DrawLine(unsigned char * VBuf, int width, int height, int line)
#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
}
}
#ifdef HAS_VGA
#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
}
}
#ifdef HAS_VGA
@ -112,7 +147,11 @@ 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
}
}
#ifdef HAS_VGA
@ -158,15 +197,20 @@ void * emu_LineBuffer(int line)
#endif
}
// ****************************************************
// the setup() method runs once, when the sketch starts
// ****************************************************
void setup() {
tft.begin();
emu_init();
myTimer.begin(vblCount, 20000); //to run every 20ms
#ifdef HAS_T4_VGA
tft.begin(VGA_MODE_320x240);
NVIC_SET_PRIORITY(IRQ_QTIMER3, 0);
#else
tft.begin();
#endif
emu_init();
}
@ -181,10 +225,14 @@ void loop(void)
char * filename = menuSelection();
if (action == ACTION_RUNTFT) {
toggleMenu(false);
vgaMode = false;
emu_Init(filename);
vgaMode = false;
emu_start();
emu_Init(filename);
//digitalWrite(TFT_CS, 1);
//digitalWrite(SD_CS, 1);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
myTimer.begin(vblCount, 40000); //to run every 40ms
}
else if (action == ACTION_RUNVGA) {
#ifdef HAS_VGA
@ -192,6 +240,7 @@ void loop(void)
vgaMode = true;
VGA_frame_buffer = (uint8_t *)malloc((UVGA_YRES*(UVGA_XRES+UVGA_XRES_EXTRA))*sizeof(uint8_t));
uvga.set_static_framebuffer(VGA_frame_buffer);
emu_start();
emu_Init(filename);
int retvga = uvga.begin(&modeline);
Serial.println(retvga);
@ -202,6 +251,7 @@ void loop(void)
// In VGA mode, we show the keyboard on TFT
toggleVirtualkeyboard(true); // keepOn
Serial.println("Starting");
myTimer.begin(vblCount, 40000); //to run every 20ms
#endif
}
delay(20);
@ -216,13 +266,18 @@ void loop(void)
handleVirtualkeyboard();
#endif
if ( (!virtualkeyboardIsActive()) || (vgaMode) ) {
emu_Step();
uint16_t bClick = 0; //emu_DebounceLocalKeys();
emu_Input(bClick);
emu_Step();
//delay(20);
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
if (bClick & MASK_KEY_USER1) {
mClick = 1;
}
}
}
}
#ifdef HAS_SND
#include <Audio.h>
@ -230,8 +285,15 @@ void loop(void)
AudioPlaySystem mymixer;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#ifdef HAS_T4_VGA
AudioOutputI2S i2s1;
AudioConnection patchCord8(mymixer, 0, i2s1, 0);
AudioConnection patchCord9(mymixer, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
#else
AudioOutputMQS mqs;
AudioConnection patchCord9(mymixer, 0, mqs, 1);
#endif
#else
AudioOutputAnalog dac1;
AudioConnection patchCord1(mymixer, dac1);

View file

@ -3,6 +3,9 @@
*/
#include "TFT_T_DMA.h"
#ifndef HAS_T4_VGA
#include "font8x8.h"
@ -1231,7 +1234,7 @@ void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap, uint16_
l++;
}
}
#endif

View file

@ -0,0 +1,53 @@
/*
Wrapping class to extend VGA_T4 to TFT_T_DMA
*/
#ifndef _VGA_T_DMAH_
#define _VGA_T_DMAH_
#ifdef __cplusplus
#include <VGA_t4.h>
#endif
#define RGBVAL16(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define RGBVAL8(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define TFT_WIDTH 320
#define TFT_REALWIDTH 320
#define TFT_HEIGHT 240
#define TFT_REALHEIGHT 240
#ifdef __cplusplus
class TFT_T_DMA: public VGA_T4
{
public:
// Fake touch screen functions
bool isTouching(void) { return false; }
void readRaw(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { }
void readCal(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { };
void callibrateTouch(uint16_t xMin,uint16_t yMin,uint16_t xMax,uint16_t yMax) { }
// fake DMA functions
void startDMA(void) { };
void stopDMA(void) { };
// fake no DMA functions
void writeScreenNoDma(const vga_pixel *pcolors) { writeScreen(pcolors); }
void fillScreenNoDma(vga_pixel color) { clear(color); }
void drawTextNoDma(int16_t x, int16_t y, const char * text, vga_pixel fgcolor, vga_pixel bgcolor, bool doublesize) { drawText(x,y,text,fgcolor,bgcolor,doublesize); }
void drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, vga_pixel color) { drawRect(x, y, w, h, color); }
void drawSpriteNoDma(int16_t x, int16_t y, const int16_t *bitmap) { drawSprite(x, y, bitmap); }
void drawSpriteNoDma(int16_t x, int16_t y, const int16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); }
};
#endif
#endif

View file

@ -5,8 +5,17 @@ extern "C" {
#include "iopins.h"
}
#ifdef HAS_T4_VGA
#include "vga_t_dma.h"
const uint16_t deflogo[] = {
0,0
};
static const uint16_t * logo = deflogo;
#else
#include "tft_t_dma.h"
#include "logo.h"
#endif
#include "bmpjoy.h"
#include "bmpvbar.h"
#ifdef OLD_LAYOUT
@ -19,6 +28,13 @@ extern "C" {
#include <Wire.h>
#endif
#ifdef HAS_USBKEY
#include "USBHost_t36.h" // Read this header first for key info
USBHost myusb;
KeyboardController keyboard1(myusb);
#endif
static uint8_t usbnavpad=0;
#ifdef USE_SDFS
#include "uSDFS.h"
static FATFS fatfs;
@ -84,7 +100,7 @@ static File file;
#define MKEY_TFT 23
#define MKEY_VGA 24
#define MAX_FILES 32
#define MAX_FILES 64
#define MAX_FILENAME_SIZE 24
#define MAX_MENULINES (MKEY_L9)
#define TEXT_HEIGHT 16
@ -93,7 +109,7 @@ static File file;
#define MENU_FILE_YOFFSET (2*TEXT_HEIGHT)
#define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH)
#define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x20)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40)
#define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT)
#define MENU_VBAR_XOFFSET (0*TEXT_WIDTH)
#define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET)
@ -113,13 +129,10 @@ static char selection[MAX_FILENAME_SIZE+1]="";
static char files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
static int16_t calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static bool i2cKeyboardPresent = false;
//const uint16_t deflogo[] = {
// 0x0000,0x0000
//};
//static const uint16_t * logo = deflogo;
static unsigned short * keys;
static int keyMap;
const unsigned short menutouchareas[] = {
TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET,
@ -245,7 +258,7 @@ void emu_printf(int val)
void emu_printi(int val)
{
Serial.println(val);
Serial.println(val,HEX);
}
void emu_printh(int val)
@ -272,13 +285,29 @@ void * emu_Malloc(int size)
}
}
else {
emu_printf("could allocate ");
emu_printf("could allocate dynamic ");
emu_printf(size);
}
return retval;
}
void * emu_MallocI(int size)
{
void * retval = NULL;
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
emu_printf("could allocate static ");
emu_printf(size);
}
else {
emu_printf("failure to allocate");
}
return retval;
}
void emu_Free(void * pt)
{
free(pt);
@ -400,6 +429,12 @@ int emu_ReadKeys(void)
retval = ((j2 << 8) | j1);
}
if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
#ifdef PIN_KEY_USER1
if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1;
#endif
@ -575,7 +610,7 @@ bool virtualkeyboardIsActive(void) {
void toggleVirtualkeyboard(bool keepOn) {
if (keepOn) {
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbKeepOn = true;
vkbActive = true;
@ -592,7 +627,7 @@ void toggleVirtualkeyboard(bool keepOn) {
}
else {
tft.stopDMA();
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
tft.drawSpriteNoDma(0,0,logo);
//prev_zt = 0;
vkbActive = true;
exitVkbd = false;
@ -637,7 +672,7 @@ void handleVirtualkeyboard() {
if (vkeyRefresh) {
vkeyRefresh = false;
tft.drawSpriteNoDma(0,0,(uint16_t*)logo, rx, ry, rw, rh);
tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh);
}
if ( (exitVkbd) && (vkbActive) ) {
@ -651,10 +686,6 @@ void handleVirtualkeyboard() {
}
int emu_setKeymap(int index) {
if (index) {
}
else {
}
}
@ -726,10 +757,12 @@ void backgroundMenu(void) {
menuRedraw=true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,(uint16_t*)bmpvbar);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,bmpvbar);
#endif
#ifdef OLD_LAYOUT
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,(uint16_t*)bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,(uint16_t*)bmpvga);
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,bmpvga);
#endif
}
@ -839,7 +872,7 @@ int handleMenu(uint16_t bClick)
strcpy(selection,filename);
}
else {
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, 0xFFFF, 0x0000, true);
tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true);
}
}
i++;
@ -847,8 +880,10 @@ int handleMenu(uint16_t bClick)
fileIndex++;
}
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0xff,0x00,0x00), false);
#ifndef HAS_T4_VGA
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
#endif
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false);
menuRedraw=false;
}
@ -910,7 +945,7 @@ static void readCallibration(void)
#else
File file = SD.open(CALIBRATION_FILE, O_READ);
if (file) {
if ( file.read(fileBuffer, 64) ) {
if ( file.read(fileBuffer, 64) ) {
sscanf(fileBuffer,"%d %d %d %d", &calMinX,&calMinY,&calMaxX,&calMaxY);
}
file.close();
@ -924,7 +959,7 @@ static void readCallibration(void)
else {
Serial.println("Callibration read error");
}
tft.callibrateTouch(calMinX,calMinY,calMaxX,calMaxY);
tft.callibrateTouch(calMinX,calMinY,calMaxX,calMaxY);
}
static void writeCallibration(void)
@ -1338,11 +1373,138 @@ void emu_FileTempWrite(int addr, unsigned char val)
#endif
}
#ifdef HAS_USBKEY
void OnPress(auto key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad |= MASK_JOY2_DOWN;
break;
case 218:
usbnavpad |= MASK_JOY2_UP;
break;
case 216:
usbnavpad |= MASK_JOY2_LEFT;
break;
case 215:
usbnavpad |= MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad |= MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnDown(keymodifier, key);
}
}
void OnRelease(int key)
{
uint8_t keymodifier = keyboard1.getModifiers();
if(keymodifier == 0x40){
// ALTGR Key modifier FR Keyboard
switch (key) {
#ifdef LAYOUT_FRENCH
case 233 : key = '~' ; break;
case 34 : key = '#' ; break;
case 39 : key = '{' ; break;
case 40 : key = '[' ; break;
case 45 : key = '|' ; break;
case 232 : key = '`' ; break;
case 95 : key = 92 ; break;
case 231 : key = '^' ; break;
case 224 : key = '@' ; break;
case 41 : key = ']' ; break;
case 61 : key = '}' ; break;
#endif
#ifdef LAYOUT_FRENCH_BELGIAN
case 38 : key = '|' ; break; //1
case 233 : key = '@' ; break; //2
case 34 : key = '#' ; break; //3
case 167 : key = '^' ; break; //6
case 231 : key = '{' ; break; //9
case 224 : key = '}' ; break; //0
case 36 : key = ']' ; break; //$
case 61 : key = '~' ; break; //=
#endif
}
}
if (menuActive())
{
switch (key)
{
case 217:
usbnavpad &= ~MASK_JOY2_DOWN;
break;
case 218:
usbnavpad &= ~MASK_JOY2_UP;
break;
case 216:
usbnavpad &= ~MASK_JOY2_LEFT;
break;
case 215:
usbnavpad &= ~MASK_JOY2_RIGHT;
break;
case 10:
usbnavpad &= ~MASK_JOY2_BTN;
break;
}
}
else
{
emu_KeyboardOnUp(keymodifier, key);
}
}
#endif
void emu_init(void)
{
Serial.begin(115200);
#ifdef HAS_USBKEY
myusb.begin();
keyboard1.attachPress(OnPress);
keyboard1.attachRelease(OnRelease);
#endif
#ifdef USE_SDFS
strcpy(romspath,SDFSDEV);
strcat(romspath,ROMSDIR);
@ -1355,9 +1517,9 @@ void emu_init(void)
}
#else
#ifdef USE_SDFAT
if (!SD.begin(SD_CONFIG))
while (!SD.begin(SD_CONFIG))
#else
if (!SD.begin(SD_CS))
while (!SD.begin(SD_CS))
#endif
{
Serial.println("SD begin failed, retrying...");
@ -1370,7 +1532,6 @@ void emu_init(void)
Serial.print("SD initialized, files found: ");
Serial.println(nbFiles);
emu_InitJoysticks();
#ifdef SWAP_JOYSTICK
@ -1387,7 +1548,11 @@ void emu_init(void)
{
toggleMenu(true);
}
}
void emu_start(void)
{
#ifdef HAS_I2CKBD
byte msg[7]={0,0,0,0,0,0,0};
Wire.begin(); // join i2c bus SDA2/SCL2
@ -1413,5 +1578,9 @@ void emu_init(void)
Serial.println("i2C keyboard found");
}
#endif
}
usbnavpad = 0;
keys = key_map1;
keyMap = 0;
}

View file

@ -1,12 +1,9 @@
#ifndef EMUAPI_H
#define EMUAPI_H
//#define INVX 1
//#define INVY 1
#define HAS_SND 1
//#define HAS_I2CKBD 1
//#define TIMER_REND 1
#include "platform_config.h"
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
// Title: < >
@ -52,7 +49,7 @@ const unsigned short keysw[] = {
TAREA_NEW_ROW,30,30,30,30,30,30,30,30,30,30,
TAREA_END};
const unsigned short keys[] = {
const unsigned short key_map1[] = {
30,31,32,33,34,35,36,37,38,39,
20,26, 8,21,23,28,25,12,18,19,
4, 9, 7,22, 4,11,13,14,15,40,
@ -87,8 +84,10 @@ const unsigned short i2ckeys[] = {
#define MASK_KEY_USER4 0x2000
extern void emu_init(void);
extern void emu_start(void);
extern void emu_resetSD(void);
extern void emu_printf(char * text);
extern void emu_printi(int val);
extern void * emu_Malloc(int size);
@ -109,8 +108,11 @@ extern void emu_FileTempWrite(int addr, unsigned char val);
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_DrawLine8(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_DrawVsync(void);
extern int emu_FrameSkip(void);
extern void * emu_LineBuffer(int line);
extern void emu_InitJoysticks(void);
extern int emu_SwapJoysticks(int statusOnly);
@ -120,6 +122,9 @@ extern int emu_GetPad(void);
extern int emu_ReadAnalogJoyX(int min, int max);
extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
extern void emu_KeyboardOnUp(int keymodifer, int key);
extern void emu_KeyboardOnDown(int keymodifer, int key);
extern void emu_sndPlaySound(int chan, int volume, int freq);
extern void emu_sndPlayBuzz(int size, int val);
extern void emu_sndInit();
@ -128,8 +133,9 @@ extern int emu_us(void);
extern int emu_setKeymap(int index);
extern void emu_FileTempInit(void);
extern void emu_FileTempRead(int addr, unsigned char * val, int n);
extern void emu_FileTempWrite(int addr, unsigned char val);
extern void emu_printh(int val);
#endif

View file

@ -35,13 +35,26 @@
#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 38 // UP
#define PIN_JOY1_2 36 // DOWN
#define PIN_JOY1_3 35 // 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
//#define PIN_KEY_USER3 33
//#define PIN_KEY_USER4 39
// Second joystick
#define PIN_JOY1_BTN 2
@ -49,6 +62,7 @@
#define PIN_JOY1_2 7 // DOWN
#define PIN_JOY1_3 6 // RIGHT
#define PIN_JOY1_4 5 // LEFT
#endif
#else
// OLD LAYOUT!!!!
@ -87,7 +101,3 @@
#endif
#endif

View file

@ -2,15 +2,21 @@
#define _PLATFORM_CONFIG_H_
//#define OLD_LAYOUT 1
#define HAS_T4_VGA 1
#define ILI9341 1
//#define HAS_SND 1
//#define INVX 1
//#define INVY 1
#define HAS_USBKEY 1
//#define ILI9341 1
//#define ST7789 1
//#define SWAP_JOYSTICK 1
//#define LOHRES 1
//#define ROTATE_SCREEN 1
#define EXTERNAL_SD 1
//#define EXTERNAL_SD 1
#define HAS_PSRAM 1
//#define HAS_PSRAM 1
//#define USE_SDFAT 1
//#define SD_FAT_TYPE 1

View file

@ -2,31 +2,39 @@ extern "C" {
#include "iopins.h"
#include "emuapi.h"
}
#include "tft_t_dma.h"
#include "keyboard_osd.h"
#include <math.h>
#include "mcume.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
static int xOffLogo=0;
static int swipeAngle=0;
void setup() {
//emu_sndInit();
#ifdef HAS_T4_VGA
tft.begin(VGA_MODE_320x240);
// NVIC_SET_PRIORITY(IRQ_QTIMER3, 0);
#else
tft.begin();
//emu_sndPlaySound(0, 255, 4000);
emu_init();
//delay(5000);
//toggleMenu(false);
//tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
//tft.startDMA();
#endif
emu_init();
}
static uint8_t col=0x00;
void loop(void)
{
uint16_t bClick = emu_DebounceLocalKeys();
if (menuActive()) {
int action = handleMenu(bClick);
@ -62,10 +70,9 @@ void loop(void)
#endif
if ( (!virtualkeyboardIsActive()) ) {
delay(20);
//emu_printf("step");
xOffLogo = 16*sin((2*3.14*swipeAngle)/256)+30;
swipeAngle = (swipeAngle + 4)&0xff;
tft.drawSprite(xOffLogo,10,(uint16_t*)logo);
swipeAngle = (swipeAngle + 4)&0xff;
tft.drawSprite(xOffLogo,10,(uint16_t*)logo);
if (bClick & MASK_JOY2_BTN) {
tft.stopDMA();
emu_init();
@ -75,6 +82,12 @@ void loop(void)
}
}
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
#ifdef HAS_SND
#include <Audio.h>
@ -82,8 +95,15 @@ void loop(void)
AudioPlaySystem mymixer;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
#ifdef HAS_T4_VGA
AudioOutputI2S i2s1;
AudioConnection patchCord8(mymixer, 0, i2s1, 0);
AudioConnection patchCord9(mymixer, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
#else
AudioOutputMQS mqs;
AudioConnection patchCord9(mymixer, 0, mqs, 1);
#endif
#else
AudioOutputAnalog dac1;
AudioConnection patchCord1(mymixer, dac1);
@ -91,6 +111,10 @@ AudioConnection patchCord1(mymixer, dac1);
void emu_sndInit() {
Serial.println("sound init");
#ifdef HAS_T4_VGA
sgtl5000_1.enable();
sgtl5000_1.volume(0.6);
#endif
AudioMemory(16);
mymixer.start();
}

View file

@ -3,6 +3,9 @@
*/
#include "TFT_T_DMA.h"
#ifndef HAS_T4_VGA
#include "font8x8.h"
@ -1231,7 +1234,7 @@ void TFT_T_DMA::drawSprite(int16_t x, int16_t y, const uint16_t *bitmap, uint16_
l++;
}
}
#endif

View file

@ -0,0 +1,53 @@
/*
Wrapping class to extend VGA_T4 to TFT_T_DMA
*/
#ifndef _VGA_T_DMAH_
#define _VGA_T_DMAH_
#ifdef __cplusplus
#include <VGA_t4.h>
#endif
#define RGBVAL16(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define RGBVAL8(r,g,b) ( (((r>>5)&0x07)<<5) | (((g>>5)&0x07)<<2) | (((b>>6)&0x3)<<0) )
#define TFT_WIDTH 320
#define TFT_REALWIDTH 320
#define TFT_HEIGHT 240
#define TFT_REALHEIGHT 240
#ifdef __cplusplus
class TFT_T_DMA: public VGA_T4
{
public:
// Fake touch screen functions
bool isTouching(void) { return false; }
void readRaw(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { }
void readCal(uint16_t * oX, uint16_t * oY, uint16_t * oZ) { };
void callibrateTouch(uint16_t xMin,uint16_t yMin,uint16_t xMax,uint16_t yMax) { }
// fake DMA functions
void startDMA(void) { };
void stopDMA(void) { };
// fake no DMA functions
void writeScreenNoDma(const vga_pixel *pcolors) { writeScreen(pcolors); }
void fillScreenNoDma(vga_pixel color) { clear(color); }
void drawTextNoDma(int16_t x, int16_t y, const char * text, vga_pixel fgcolor, vga_pixel bgcolor, bool doublesize) { drawText(x,y,text,fgcolor,bgcolor,doublesize); }
void drawRectNoDma(int16_t x, int16_t y, int16_t w, int16_t h, vga_pixel color) { drawRect(x, y, w, h, color); }
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap) { drawSprite(x, y, bitmap); }
void drawSpriteNoDma(int16_t x, int16_t y, const uint16_t *bitmap, uint16_t croparx, uint16_t cropary, uint16_t croparw, uint16_t croparh) { drawSprite(x, y, bitmap, croparx, cropary, croparw, croparh); }
};
#endif
#endif

Binary file not shown.

View file

@ -1,317 +1,320 @@
/** EMULib Emulation Library *********************************/
/** **/
/** AY8910.c **/
/** **/
/** This file contains emulation for the AY8910 sound chip **/
/** produced by General Instruments, Yamaha, etc. See **/
/** AY8910.h for declarations. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-2003 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "AY8910.h"
#include "Sound.h"
#include <string.h>
/** Reset8910() **********************************************/
/** Reset the sound chip and use sound channels from the **/
/** one given in First. **/
/*************************************************************/
void Reset8910(register AY8910 *D,int First)
{
static byte RegInit[16] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFD,
0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00
};
int J;
for(J=0;J<AY8910_CHANNELS;J++) D->Freq[J]=D->Volume[J]=0;
memcpy(D->R,RegInit,sizeof(D->R));
D->Phase[0]=D->Phase[1]=D->Phase[2]=0;
D->First = First;
D->Sync = AY8910_ASYNC;
D->Changed = 0x00;
D->EPeriod = 0;
D->ECount = 0;
D->Latch = 0x00;
/* Set sound types */
SetSound(0+First,SND_MELODIC);
SetSound(1+First,SND_MELODIC);
SetSound(2+First,SND_MELODIC);
SetSound(3+First,SND_NOISE);
SetSound(4+First,SND_NOISE);
SetSound(5+First,SND_NOISE);
}
/** WrCtrl8910() *********************************************/
/** Write a value V to the PSG Control Port. **/
/*************************************************************/
void WrCtrl8910(AY8910 *D,byte V)
{
D->Latch=V&0x0F;
}
/** WrData8910() *********************************************/
/** Write a value V to the PSG Data Port. **/
/*************************************************************/
void WrData8910(AY8910 *D,byte V)
{
Write8910(D,D->Latch,V);
}
/** RdData8910() *********************************************/
/** Read a value from the PSG Data Port. **/
/*************************************************************/
byte RdData8910(AY8910 *D)
{
return(D->R[D->Latch]);
}
/** Write8910() **********************************************/
/** Call this function to output a value V into the sound **/
/** chip. **/
/*************************************************************/
void Write8910(register AY8910 *D,register byte R,register byte V)
{
register int J,I;
/* Exit if no change */
if((R>15)||((V==D->R[R])&&(R<8)&&(R>10))) return;
switch(R)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
/* Write value */
D->R[R]=V;
/* Exit if the channel is silenced */
if(D->R[7]&(1<<(R>>1))) return;
/* Go to the first register in the pair */
R&=0xFE;
/* Compute frequency */
J=((int)(D->R[R+1]&0x0F)<<8)+D->R[R];
/* Compute channel number */
R>>=1;
/* Assign frequency */
D->Freq[R]=AY8910_BASE/(J+1);
/* Compute changed channels mask */
D->Changed|=1<<R;
break;
case 6:
/* Write value */
D->R[6]=V;
/* Exit if noise channels are silenced */
if(!(~D->R[7]&0x38)) return;
/* Compute and assign noise frequency */
J=AY8910_BASE/((V&0x1F)+1);
if(!(D->R[7]&0x08)) D->Freq[3]=J;
if(!(D->R[7]&0x10)) D->Freq[4]=J;
if(!(D->R[7]&0x20)) D->Freq[5]=J;
/* Compute changed channels mask */
D->Changed|=0x38&~D->R[7];
break;
case 7:
/* Find changed channels */
R=(V^D->R[7])&0x3F;
D->Changed|=R;
/* Write value */
D->R[7]=V;
/* Update frequencies */
for(J=0;R&&(J<AY8910_CHANNELS);J++,R>>=1,V>>=1)
if(R&1)
{
if(V&1) D->Freq[J]=0;
else
{
I=J<3? (((int)(D->R[J*2+1]&0x0F)<<8)+D->R[J*2]):(D->R[6]&0x1F);
D->Freq[J]=AY8910_BASE/(I+1);
}
}
break;
case 8:
case 9:
case 10:
/* Write value */
D->R[R]=V;
/* Compute channel number */
R-=8;
/* Compute and assign new volume */
D->Volume[R+3]=D->Volume[R]=255*(V&0x0F)/15;
/* Start/stop envelope */
D->Phase[R]=V&0x10? 1:0;
/* Compute changed channels mask */
D->Changed|=(0x09<<R)&~D->R[7];
break;
case 11:
case 12:
/* Write value */
D->R[R]=V;
/* Compute frequency */
J=((int)D->R[12]<<8)+D->R[11];
D->EPeriod=1000*J/AY8910_BASE/16;
D->ECount=0;
/* No channels changed */
return;
case 13:
case 14:
case 15:
/* Write value */
D->R[R]=V;
/* No channels changed */
return;
default:
/* Wrong register, do nothing */
return;
}
/* For asynchronous mode, make Sound() calls right away */
if(!D->Sync&&D->Changed) Sync8910(D,AY8910_FLUSH);
}
/** Loop8910() ***********************************************/
/** Call this function periodically to update volume **/
/** envelopes. Use mS to pass the time since the last call **/
/** of Loop8910() in milliseconds. **/
/*************************************************************/
void Loop8910(register AY8910 *D,int mS)
{
register int J,I,Step;
/* Exit if no envelope running */
if(!D->EPeriod) return;
/* Count milliseconds */
D->ECount+=mS;
if(D->ECount<D->EPeriod) return;
D->ECount-=D->EPeriod;
/* By how much do we change volume? */
Step=mS>=D->EPeriod? mS/D->EPeriod:1;
for(J=0;J<3;J++)
if(D->Phase[J]&&(D->R[J+8]&0x10))
switch(D->R[13]&0x0F)
{
case 0:
case 1:
case 2:
case 3:
case 9:
I=D->Volume[J]-Step;
D->Volume[J+3]=D->Volume[J]=I=I>=0? I:0;
if(!I) D->Phase[J]=0;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 4:
case 5:
case 6:
case 7:
I=D->Volume[J]+Step;
D->Volume[J+3]=D->Volume[J]=I=I<256? I:0;
if(!I) D->Phase[J]=0;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 8:
I=D->Volume[J]-Step;
D->Volume[J+3]=D->Volume[J]=I>=0? I:255;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 10:
if(D->Phase[J]==2)
{
I=D->Volume[J]+Step;
D->Volume[J+3]=D->Volume[J]=I=I<256? I:255;
if(I==255) D->Phase[J]=1;
}
else
{
I=D->Volume[J]-Step;
D->Volume[J+3]=D->Volume[J]=I=I>=0? I:0;
if(!I) D->Phase[J]=2;
}
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 11:
I=D->Volume[J]-Step;
D->Volume[J+3]=D->Volume[J]=I=I>=0? I:255;
if(I==255) D->Phase[J]=0;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 12:
I=D->Volume[J]+Step;
D->Volume[J+3]=D->Volume[J]=I<256? I:0;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 13:
case 15:
I=D->Volume[J]+Step;
D->Volume[J+3]=D->Volume[J]=I<256? I:255;
if(I==255) D->Phase[J]=0;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 14:
if(D->Phase[J]==2)
{
I=D->Volume[J]-Step;
D->Volume[J+3]=D->Volume[J]=I=I>=0? I:0;
if(!I) D->Phase[J]=1;
}
else
{
I=D->Volume[J]+Step;
D->Volume[J+3]=D->Volume[J]=I=I<256? I:255;
if(I==255) D->Phase[J]=2;
}
D->Changed|=(0x09<<J)&~D->R[7];
break;
}
/* For asynchronous mode, make Sound() calls right away */
if(!D->Sync&&D->Changed) Sync8910(D,AY8910_FLUSH);
}
/** Sync8910() ***********************************************/
/** Flush all accumulated changes by issuing Sound() calls **/
/** and set the synchronization on/off. The second argument **/
/** should be AY8910_SYNC/AY8910_ASYNC to set/reset sync, **/
/** or AY8910_FLUSH to leave sync mode as it is. To emulate **/
/** noise channels with MIDI drums, OR second argument with **/
/** AY8910_DRUMS. **/
/*************************************************************/
void Sync8910(register AY8910 *D,register byte Sync)
{
register int J,I;
/* Hit MIDI drums for noise channels, if requested */
if(Sync&AY8910_DRUMS)
{
Sync&=~AY8910_DRUMS;
J=0;
if(D->Volume[3]&&D->Freq[3]) J+=D->Volume[3];
if(D->Volume[4]&&D->Freq[4]) J+=D->Volume[4];
if(D->Volume[5]&&D->Freq[5]) J+=D->Volume[5];
if(J) Drum(DRM_MIDI|28,(J+2)/3);
}
if(Sync!=AY8910_FLUSH) D->Sync=Sync;
for(J=0,I=D->Changed;I&&(J<AY8910_CHANNELS);J++,I>>=1)
if(I&1) Sound(J+D->First,D->Freq[J],D->Volume[J]);
D->Changed=0x00;
}
/** EMULib Emulation Library *********************************/
/** **/
/** AY8910.c **/
/** **/
/** This file contains emulation for the AY8910 sound chip **/
/** produced by General Instruments, Yamaha, etc. See **/
/** AY8910.h for declarations. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-2005 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "AY8910.h"
#include "Sound.h"
#include <string.h>
/** Reset8910() **********************************************/
/** Reset the sound chip and use sound channels from the **/
/** one given in First. **/
/*************************************************************/
void Reset8910(register AY8910 *D,int First)
{
static byte RegInit[16] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFD,
0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00
};
int J;
for(J=0;J<AY8910_CHANNELS;J++) D->Freq[J]=D->Volume[J]=0;
memcpy(D->R,RegInit,sizeof(D->R));
D->Phase[0]=D->Phase[1]=D->Phase[2]=0;
D->First = First;
D->Sync = AY8910_ASYNC;
D->Changed = 0x00;
D->EPeriod = 0;
D->ECount = 0;
D->Latch = 0x00;
/* Set sound types */
SetSound(0+First,SND_MELODIC);
SetSound(1+First,SND_MELODIC);
SetSound(2+First,SND_MELODIC);
SetSound(3+First,SND_NOISE);
SetSound(4+First,SND_NOISE);
SetSound(5+First,SND_NOISE);
}
/** WrCtrl8910() *********************************************/
/** Write a value V to the PSG Control Port. **/
/*************************************************************/
void WrCtrl8910(AY8910 *D,byte V)
{
D->Latch=V&0x0F;
}
/** WrData8910() *********************************************/
/** Write a value V to the PSG Data Port. **/
/*************************************************************/
void WrData8910(AY8910 *D,byte V)
{
Write8910(D,D->Latch,V);
}
/** RdData8910() *********************************************/
/** Read a value from the PSG Data Port. **/
/*************************************************************/
byte RdData8910(AY8910 *D)
{
return(D->R[D->Latch]);
}
/** Write8910() **********************************************/
/** Call this function to output a value V into the sound **/
/** chip. **/
/*************************************************************/
void Write8910(register AY8910 *D,register byte R,register byte V)
{
register int J,I;
/* Exit if no change */
if((R>15)||((V==D->R[R])&&(R<8)&&(R>10))) return;
switch(R)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
/* Write value */
D->R[R]=V;
/* Exit if the channel is silenced */
if(D->R[7]&(1<<(R>>1))) return;
/* Go to the first register in the pair */
R&=0xFE;
/* Compute frequency */
J=((int)(D->R[R+1]&0x0F)<<8)+D->R[R];
/* Compute channel number */
R>>=1;
/* Assign frequency */
D->Freq[R]=AY8910_BASE/(J+1);
/* Compute changed channels mask */
D->Changed|=1<<R;
break;
case 6:
/* Write value */
D->R[6]=V;
/* Exit if noise channels are silenced */
if(!(~D->R[7]&0x38)) return;
/* Compute and assign noise frequency */
J=AY8910_BASE/((V&0x1F)+1);
if(!(D->R[7]&0x08)) D->Freq[3]=J;
if(!(D->R[7]&0x10)) D->Freq[4]=J;
if(!(D->R[7]&0x20)) D->Freq[5]=J;
/* Compute changed channels mask */
D->Changed|=0x38&~D->R[7];
break;
case 7:
/* Find changed channels */
R=(V^D->R[7])&0x3F;
D->Changed|=R;
/* Write value */
D->R[7]=V;
/* Update frequencies */
for(J=0;R&&(J<AY8910_CHANNELS);J++,R>>=1,V>>=1)
if(R&1)
{
if(V&1) D->Freq[J]=0;
else
{
I=J<3? (((int)(D->R[J*2+1]&0x0F)<<8)+D->R[J*2]):(D->R[6]&0x1F);
D->Freq[J]=AY8910_BASE/(I+1);
}
}
break;
case 8:
case 9:
case 10:
/* Write value */
D->R[R]=V;
/* Compute channel number */
R-=8;
/* Compute and assign new volume */
D->Volume[R+3]=D->Volume[R]=
V&0x10? (V&0x04? 0:255):255*(V&0x0F)/15;
/* Start/stop envelope */
D->Phase[R]=V&0x10? 1:0;
/* Compute changed channels mask */
D->Changed|=(0x09<<R)&~D->R[7];
break;
case 11:
case 12:
/* Write value */
D->R[R]=V;
/* Compute frequency */
J=((int)D->R[12]<<8)+D->R[11]+1;
D->EPeriod=1000*(J<<4)/AY8910_BASE;
D->ECount=0;
/* No channels changed */
return;
case 13:
case 14:
case 15:
/* Write value */
D->R[R]=V;
/* No channels changed */
return;
default:
/* Wrong register, do nothing */
return;
}
/* For asynchronous mode, make Sound() calls right away */
if(!D->Sync&&D->Changed) Sync8910(D,AY8910_FLUSH);
}
/** Loop8910() ***********************************************/
/** Call this function periodically to update volume **/
/** envelopes. Use mS to pass the time since the last call **/
/** of Loop8910() in milliseconds. **/
/*************************************************************/
void Loop8910(register AY8910 *D,int mS)
{
register int J,I,Step;
/* Exit if no envelope running */
if(!D->EPeriod) return;
/* Count milliseconds */
D->ECount+=mS;
if(D->ECount<D->EPeriod) return;
/* By how much do we change volume? */
Step=(D->ECount<<8)/D->EPeriod;
/* Count the remaining milliseconds */
D->ECount%=D->EPeriod;
for(J=0;J<3;J++)
if(D->Phase[J]&&(D->R[J+8]&0x10))
switch(D->R[13]&0x0F)
{
case 0:
case 1:
case 2:
case 3:
case 9:
I=D->Volume[J]-Step;
D->Volume[J+3]=D->Volume[J]=I=I>=0? I:0;
if(!I) D->Phase[J]=0;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 4:
case 5:
case 6:
case 7:
I=D->Volume[J]+Step;
D->Volume[J+3]=D->Volume[J]=I=I<256? I:0;
if(!I) D->Phase[J]=0;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 8:
I=D->Volume[J]-Step;
D->Volume[J+3]=D->Volume[J]=I>=0? I:255;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 10:
if(D->Phase[J]==2)
{
I=D->Volume[J]+Step;
D->Volume[J+3]=D->Volume[J]=I=I<256? I:255;
if(I==255) D->Phase[J]=1;
}
else
{
I=D->Volume[J]-Step;
D->Volume[J+3]=D->Volume[J]=I=I>=0? I:0;
if(!I) D->Phase[J]=2;
}
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 11:
I=D->Volume[J]-Step;
D->Volume[J+3]=D->Volume[J]=I=I>=0? I:255;
if(I==255) D->Phase[J]=0;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 12:
I=D->Volume[J]+Step;
D->Volume[J+3]=D->Volume[J]=I<256? I:0;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 13:
case 15:
I=D->Volume[J]+Step;
D->Volume[J+3]=D->Volume[J]=I<256? I:255;
if(I==255) D->Phase[J]=0;
D->Changed|=(0x09<<J)&~D->R[7];
break;
case 14:
if(D->Phase[J]==2)
{
I=D->Volume[J]-Step;
D->Volume[J+3]=D->Volume[J]=I=I>=0? I:0;
if(!I) D->Phase[J]=1;
}
else
{
I=D->Volume[J]+Step;
D->Volume[J+3]=D->Volume[J]=I=I<256? I:255;
if(I==255) D->Phase[J]=2;
}
D->Changed|=(0x09<<J)&~D->R[7];
break;
}
/* For asynchronous mode, make Sound() calls right away */
if(!D->Sync&&D->Changed) Sync8910(D,AY8910_FLUSH);
}
/** Sync8910() ***********************************************/
/** Flush all accumulated changes by issuing Sound() calls **/
/** and set the synchronization on/off. The second argument **/
/** should be AY8910_SYNC/AY8910_ASYNC to set/reset sync, **/
/** or AY8910_FLUSH to leave sync mode as it is. To emulate **/
/** noise channels with MIDI drums, OR second argument with **/
/** AY8910_DRUMS. **/
/*************************************************************/
void Sync8910(register AY8910 *D,register byte Sync)
{
register int J,I;
/* Hit MIDI drums for noise channels, if requested */
if(Sync&AY8910_DRUMS)
{
Sync&=~AY8910_DRUMS;
J=0;
if(D->Volume[3]&&D->Freq[3]) J+=D->Volume[3];
if(D->Volume[4]&&D->Freq[4]) J+=D->Volume[4];
if(D->Volume[5]&&D->Freq[5]) J+=D->Volume[5];
if(J) Drum(DRM_MIDI|28,(J+2)/3);
}
if(Sync!=AY8910_FLUSH) D->Sync=Sync;
for(J=0,I=D->Changed;I&&(J<AY8910_CHANNELS);J++,I>>=1)
if(I&1) Sound(J+D->First,D->Freq[J],D->Volume[J]);
D->Changed=0x00;
}

View file

@ -1,91 +1,91 @@
/** EMULib Emulation Library *********************************/
/** **/
/** AY8910.h **/
/** **/
/** This file contains emulation for the AY8910 sound chip **/
/** produced by General Instruments, Yamaha, etc. See **/
/** AY8910.c for the actual code. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-2003 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef AY8910_H
#define AY8910_H
#define AY8910_BASE 111861 /* Base frequency for AY8910 */
#define AY8910_CHANNELS 6 /* 3 melodic + 3 noise chanls */
#define AY8910_ASYNC 0 /* Asynchronous emulation */
#define AY8910_SYNC 1 /* Synchronous emulation */
#define AY8910_FLUSH 2 /* Flush buffers only */
#define AY8910_DRUMS 0x80 /* Hit drums for noise chnls */
#ifndef BYTE_TYPE_DEFINED
#define BYTE_TYPE_DEFINED
typedef unsigned char byte;
#endif
/** AY8910 ***************************************************/
/** This data structure stores AY8910 state. **/
/*************************************************************/
typedef struct
{
byte R[16]; /* PSG registers contents */
int Freq[AY8910_CHANNELS]; /* Frequencies (0 for off) */
int Volume[AY8910_CHANNELS]; /* Volumes (0..255) */
int First; /* First used Sound() channel */
byte Changed; /* Bitmap of changed channels */
byte Sync; /* AY8910_SYNC/AY8910_ASYNC */
byte Latch; /* Latch for the register num */
int EPeriod; /* Envelope step in msecs */
int ECount; /* Envelope step counter */
byte Phase[3]; /* Envelope phase (0 for off) */
} AY8910;
/** Reset8910() **********************************************/
/** Reset the sound chip and use sound channels from the **/
/** one given in First. **/
/*************************************************************/
void Reset8910(register AY8910 *D,int First);
/** Write8910() **********************************************/
/** Call this function to output a value V into the sound **/
/** chip. **/
/*************************************************************/
void Write8910(register AY8910 *D,register byte R,register byte V);
/** WrCtrl8910() *********************************************/
/** Write a value V to the PSG Control Port. **/
/*************************************************************/
void WrCtrl8910(AY8910 *D,byte V);
/** WrData8910() *********************************************/
/** Write a value V to the PSG Data Port. **/
/*************************************************************/
void WrData8910(AY8910 *D,byte V);
/** RdData8910() *********************************************/
/** Read a value from the PSG Data Port. **/
/*************************************************************/
byte RdData8910(AY8910 *D);
/** Sync8910() ***********************************************/
/** Flush all accumulated changes by issuing Sound() calls **/
/** and set the synchronization on/off. The second argument **/
/** should be AY8910_SYNC/AY8910_ASYNC to set/reset sync, **/
/** or AY8910_FLUSH to leave sync mode as it is. To emulate **/
/** noise channels with MIDI drums, OR second argument with **/
/** AY8910_DRUMS. **/
/*************************************************************/
void Sync8910(register AY8910 *D,register byte Sync);
/** Loop8910() ***********************************************/
/** Call this function periodically to update volume **/
/** envelopes. Use mS to pass the time since the last call **/
/** of Loop8910() in milliseconds. **/
/*************************************************************/
void Loop8910(register AY8910 *D,int mS);
#endif /* AY8910_H */
/** EMULib Emulation Library *********************************/
/** **/
/** AY8910.h **/
/** **/
/** This file contains emulation for the AY8910 sound chip **/
/** produced by General Instruments, Yamaha, etc. See **/
/** AY8910.c for the actual code. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-2005 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef AY8910_H
#define AY8910_H
#define AY8910_BASE 111861 /* Base frequency for AY8910 */
#define AY8910_CHANNELS 6 /* 3 melodic + 3 noise chanls */
#define AY8910_ASYNC 0 /* Asynchronous emulation */
#define AY8910_SYNC 1 /* Synchronous emulation */
#define AY8910_FLUSH 2 /* Flush buffers only */
#define AY8910_DRUMS 0x80 /* Hit drums for noise chnls */
#ifndef BYTE_TYPE_DEFINED
#define BYTE_TYPE_DEFINED
typedef unsigned char byte;
#endif
/** AY8910 ***************************************************/
/** This data structure stores AY8910 state. **/
/*************************************************************/
typedef struct
{
byte R[16]; /* PSG registers contents */
int Freq[AY8910_CHANNELS]; /* Frequencies (0 for off) */
int Volume[AY8910_CHANNELS]; /* Volumes (0..255) */
int First; /* First used Sound() channel */
byte Changed; /* Bitmap of changed channels */
byte Sync; /* AY8910_SYNC/AY8910_ASYNC */
byte Latch; /* Latch for the register num */
int EPeriod; /* Envelope step in msecs */
int ECount; /* Envelope step counter */
byte Phase[3]; /* Envelope phase (0 for off) */
} AY8910;
/** Reset8910() **********************************************/
/** Reset the sound chip and use sound channels from the **/
/** one given in First. **/
/*************************************************************/
void Reset8910(register AY8910 *D,int First);
/** Write8910() **********************************************/
/** Call this function to output a value V into the sound **/
/** chip. **/
/*************************************************************/
void Write8910(register AY8910 *D,register byte R,register byte V);
/** WrCtrl8910() *********************************************/
/** Write a value V to the PSG Control Port. **/
/*************************************************************/
void WrCtrl8910(AY8910 *D,byte V);
/** WrData8910() *********************************************/
/** Write a value V to the PSG Data Port. **/
/*************************************************************/
void WrData8910(AY8910 *D,byte V);
/** RdData8910() *********************************************/
/** Read a value from the PSG Data Port. **/
/*************************************************************/
byte RdData8910(AY8910 *D);
/** Sync8910() ***********************************************/
/** Flush all accumulated changes by issuing Sound() calls **/
/** and set the synchronization on/off. The second argument **/
/** should be AY8910_SYNC/AY8910_ASYNC to set/reset sync, **/
/** or AY8910_FLUSH to leave sync mode as it is. To emulate **/
/** noise channels with MIDI drums, OR second argument with **/
/** AY8910_DRUMS. **/
/*************************************************************/
void Sync8910(register AY8910 *D,register byte Sync);
/** Loop8910() ***********************************************/
/** Call this function periodically to update volume **/
/** envelopes. Use mS to pass the time since the last call **/
/** of Loop8910() in milliseconds. **/
/*************************************************************/
void Loop8910(register AY8910 *D,int mS);
#endif /* AY8910_H */

View file

@ -1,378 +1,385 @@
/** Z80: portable Z80 emulator *******************************/
/** **/
/** Codes.h **/
/** **/
/** This file contains implementation for the main table of **/
/** Z80 commands. It is included from Z80.c. **/
/** **/
/** Copyright (C) Marat Fayzullin 1994-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;
/** 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-2005 **/
/** 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) { R->ICount-=5;M_JR; } else R->PC.W++;break;
case JP: M_JP;break;
case JR: M_JR;break;
case CALL: M_CALL;break;
case RET: M_RET;break;
case SCF: S(C_FLAG);R(N_FLAG|H_FLAG);break;
case CPL: R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break;
case NOP: break;
case OUTA: I=RdZ80(R->PC.W++);OutZ80(I,R->AF.B.h);break;
case INA: I=RdZ80(R->PC.W++);R->AF.B.h=InZ80(I);break;
case HALT:
R->PC.W--;
R->IFF|=IFF_HALT;
R->IBackup=0;
R->ICount=0;
break;
case DI:
if(R->IFF&IFF_EI) R->ICount+=R->IBackup-1;
R->IFF&=~(IFF_1|IFF_2|IFF_EI);
break;
case EI:
if(!(R->IFF&(IFF_1|IFF_EI)))
{
R->IFF|=IFF_2|IFF_EI;
R->IBackup=R->ICount;
R->ICount=1;
}
break;
case CCF:
R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG);
R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG;
break;
case EXX:
J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W;
J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W;
J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W;
break;
case EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break;
case EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break;
case LD_B_B: R->BC.B.h=R->BC.B.h;break;
case LD_C_B: R->BC.B.l=R->BC.B.h;break;
case LD_D_B: R->DE.B.h=R->BC.B.h;break;
case LD_E_B: R->DE.B.l=R->BC.B.h;break;
case LD_H_B: R->HL.B.h=R->BC.B.h;break;
case LD_L_B: R->HL.B.l=R->BC.B.h;break;
case LD_A_B: R->AF.B.h=R->BC.B.h;break;
case LD_xHL_B: WrZ80(R->HL.W,R->BC.B.h);break;
case LD_B_C: R->BC.B.h=R->BC.B.l;break;
case LD_C_C: R->BC.B.l=R->BC.B.l;break;
case LD_D_C: R->DE.B.h=R->BC.B.l;break;
case LD_E_C: R->DE.B.l=R->BC.B.l;break;
case LD_H_C: R->HL.B.h=R->BC.B.l;break;
case LD_L_C: R->HL.B.l=R->BC.B.l;break;
case LD_A_C: R->AF.B.h=R->BC.B.l;break;
case LD_xHL_C: WrZ80(R->HL.W,R->BC.B.l);break;
case LD_B_D: R->BC.B.h=R->DE.B.h;break;
case LD_C_D: R->BC.B.l=R->DE.B.h;break;
case LD_D_D: R->DE.B.h=R->DE.B.h;break;
case LD_E_D: R->DE.B.l=R->DE.B.h;break;
case LD_H_D: R->HL.B.h=R->DE.B.h;break;
case LD_L_D: R->HL.B.l=R->DE.B.h;break;
case LD_A_D: R->AF.B.h=R->DE.B.h;break;
case LD_xHL_D: WrZ80(R->HL.W,R->DE.B.h);break;
case LD_B_E: R->BC.B.h=R->DE.B.l;break;
case LD_C_E: R->BC.B.l=R->DE.B.l;break;
case LD_D_E: R->DE.B.h=R->DE.B.l;break;
case LD_E_E: R->DE.B.l=R->DE.B.l;break;
case LD_H_E: R->HL.B.h=R->DE.B.l;break;
case LD_L_E: R->HL.B.l=R->DE.B.l;break;
case LD_A_E: R->AF.B.h=R->DE.B.l;break;
case LD_xHL_E: WrZ80(R->HL.W,R->DE.B.l);break;
case LD_B_H: R->BC.B.h=R->HL.B.h;break;
case LD_C_H: R->BC.B.l=R->HL.B.h;break;
case LD_D_H: R->DE.B.h=R->HL.B.h;break;
case LD_E_H: R->DE.B.l=R->HL.B.h;break;
case LD_H_H: R->HL.B.h=R->HL.B.h;break;
case LD_L_H: R->HL.B.l=R->HL.B.h;break;
case LD_A_H: R->AF.B.h=R->HL.B.h;break;
case LD_xHL_H: WrZ80(R->HL.W,R->HL.B.h);break;
case LD_B_L: R->BC.B.h=R->HL.B.l;break;
case LD_C_L: R->BC.B.l=R->HL.B.l;break;
case LD_D_L: R->DE.B.h=R->HL.B.l;break;
case LD_E_L: R->DE.B.l=R->HL.B.l;break;
case LD_H_L: R->HL.B.h=R->HL.B.l;break;
case LD_L_L: R->HL.B.l=R->HL.B.l;break;
case LD_A_L: R->AF.B.h=R->HL.B.l;break;
case LD_xHL_L: WrZ80(R->HL.W,R->HL.B.l);break;
case LD_B_A: R->BC.B.h=R->AF.B.h;break;
case LD_C_A: R->BC.B.l=R->AF.B.h;break;
case LD_D_A: R->DE.B.h=R->AF.B.h;break;
case LD_E_A: R->DE.B.l=R->AF.B.h;break;
case LD_H_A: R->HL.B.h=R->AF.B.h;break;
case LD_L_A: R->HL.B.l=R->AF.B.h;break;
case LD_A_A: R->AF.B.h=R->AF.B.h;break;
case LD_xHL_A: WrZ80(R->HL.W,R->AF.B.h);break;
case LD_xBC_A: WrZ80(R->BC.W,R->AF.B.h);break;
case LD_xDE_A: WrZ80(R->DE.W,R->AF.B.h);break;
case LD_B_xHL: R->BC.B.h=RdZ80(R->HL.W);break;
case LD_C_xHL: R->BC.B.l=RdZ80(R->HL.W);break;
case LD_D_xHL: R->DE.B.h=RdZ80(R->HL.W);break;
case LD_E_xHL: R->DE.B.l=RdZ80(R->HL.W);break;
case LD_H_xHL: R->HL.B.h=RdZ80(R->HL.W);break;
case LD_L_xHL: R->HL.B.l=RdZ80(R->HL.W);break;
case LD_A_xHL: R->AF.B.h=RdZ80(R->HL.W);break;
case LD_B_BYTE: R->BC.B.h=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;

View file

@ -1,204 +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;
/** 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-2005 **/
/** 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;

View file

@ -1,282 +1,304 @@
/** Z80: portable Z80 emulator *******************************/
/** **/
/** CodesED.h **/
/** **/
/** This file contains implementation for the ED table of **/
/** Z80 commands. It is included from Z80.c. **/
/** **/
/** Copyright (C) Marat Fayzullin 1994-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;
/** 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-2005 **/
/** 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&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h];
break;
case LD_A_R:
R->R++;
R->AF.B.h=(byte)(R->R-R->ICount);
R->AF.B.l=(R->AF.B.l&C_FLAG)|(R->IFF&IFF_2? P_FLAG:0)|ZSTable[R->AF.B.h];
break;
case LD_I_A: R->I=R->AF.B.h;break;
case LD_R_A: break;
case IM_0: R->IFF&=~(IFF_IM1|IFF_IM2);break;
case IM_1: R->IFF=(R->IFF&~IFF_IM2)|IFF_IM1;break;
case IM_2: R->IFF=(R->IFF&~IFF_IM1)|IFF_IM2;break;
case RETI: M_RET;break;
case RETN: if(R->IFF&IFF_2) R->IFF|=IFF_1; else R->IFF&=~IFF_1;
M_RET;break;
case NEG: I=R->AF.B.h;R->AF.B.h=0;M_SUB(I);break;
case IN_B_xC: M_IN(R->BC.B.h);break;
case IN_C_xC: M_IN(R->BC.B.l);break;
case IN_D_xC: M_IN(R->DE.B.h);break;
case IN_E_xC: M_IN(R->DE.B.l);break;
case IN_H_xC: M_IN(R->HL.B.h);break;
case IN_L_xC: M_IN(R->HL.B.l);break;
case IN_A_xC: M_IN(R->AF.B.h);break;
case IN_F_xC: M_IN(J.B.l);break;
case OUT_xC_B: OutZ80(R->BC.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:
I=RdZ80(R->HL.W++);
OutZ80(R->BC.B.l,I);
R->BC.B.h--;
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
break;
case OTIR:
do
{
I=RdZ80(R->HL.W++);
OutZ80(R->BC.B.l,I);
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->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
R->PC.W-=2;
}
else
{
R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
R->ICount+=5;
}
break;
case OUTD:
I=RdZ80(R->HL.W--);
OutZ80(R->BC.B.l,I);
R->BC.B.h--;
R->AF.B.l=N_FLAG|(R->BC.B.h? 0:Z_FLAG)|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
break;
case OTDR:
do
{
I=RdZ80(R->HL.W--);
OutZ80(R->BC.B.l,I);
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->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
R->PC.W-=2;
}
else
{
R->AF.B.l=Z_FLAG|N_FLAG|(R->HL.B.l+I>255? (C_FLAG|H_FLAG):0);
R->ICount+=5;
}
break;
case LDI:
WrZ80(R->DE.W++,RdZ80(R->HL.W++));
R->BC.W--;
R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0);
break;
case LDIR:
do
{
WrZ80(R->DE.W++,RdZ80(R->HL.W++));
R->BC.W--;R->ICount-=21;
}
while(R->BC.W&&(R->ICount>0));
R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG);
if(R->BC.W) { R->AF.B.l|=N_FLAG;R->PC.W-=2; }
else R->ICount+=5;
break;
case LDD:
WrZ80(R->DE.W--,RdZ80(R->HL.W--));
R->BC.W--;
R->AF.B.l=(R->AF.B.l&~(N_FLAG|H_FLAG|P_FLAG))|(R->BC.W? P_FLAG:0);
break;
case LDDR:
do
{
WrZ80(R->DE.W--,RdZ80(R->HL.W--));
R->BC.W--;R->ICount-=21;
}
while(R->BC.W&&(R->ICount>0));
R->AF.B.l&=~(N_FLAG|H_FLAG|P_FLAG);
if(R->BC.W) { R->AF.B.l|=N_FLAG;R->PC.W-=2; }
else R->ICount+=5;
break;
case CPI:
I=RdZ80(R->HL.W++);
J.B.l=R->AF.B.h-I;
R->BC.W--;
R->AF.B.l =
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
break;
case CPIR:
do
{
I=RdZ80(R->HL.W++);
J.B.l=R->AF.B.h-I;
R->BC.W--;R->ICount-=21;
}
while(R->BC.W&&J.B.l&&(R->ICount>0));
R->AF.B.l =
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5;
break;
case CPD:
I=RdZ80(R->HL.W--);
J.B.l=R->AF.B.h-I;
R->BC.W--;
R->AF.B.l =
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
break;
case CPDR:
do
{
I=RdZ80(R->HL.W--);
J.B.l=R->AF.B.h-I;
R->BC.W--;R->ICount-=21;
}
while(R->BC.W&&J.B.l);
R->AF.B.l =
N_FLAG|(R->AF.B.l&C_FLAG)|ZSTable[J.B.l]|
((R->AF.B.h^I^J.B.l)&H_FLAG)|(R->BC.W? P_FLAG:0);
if(R->BC.W&&J.B.l) R->PC.W-=2; else R->ICount+=5;
break;

View file

@ -1,64 +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;
/** 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-2005 **/
/** 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;

View file

@ -1,388 +1,396 @@
/** Z80: portable Z80 emulator *******************************/
/** **/
/** CodesXX.h **/
/** **/
/** This file contains implementation for FD/DD tables of **/
/** Z80 commands. It is included from Z80.c. **/
/** **/
/** Copyright (C) Marat Fayzullin 1994-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;
/** 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-2005 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
case JR_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
case JR_NC: if(R->AF.B.l&C_FLAG) R->PC.W++; else { R->ICount-=5;M_JR; } break;
case JR_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
case JR_C: if(R->AF.B.l&C_FLAG) { R->ICount-=5;M_JR; } else R->PC.W++; break;
case JP_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { M_JP; } break;
case JP_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { M_JP; } break;
case JP_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { M_JP; } break;
case JP_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { M_JP; } break;
case JP_Z: if(R->AF.B.l&Z_FLAG) { M_JP; } else R->PC.W+=2; break;
case JP_C: if(R->AF.B.l&C_FLAG) { M_JP; } else R->PC.W+=2; break;
case JP_PE: if(R->AF.B.l&P_FLAG) { M_JP; } else R->PC.W+=2; break;
case JP_M: if(R->AF.B.l&S_FLAG) { M_JP; } else R->PC.W+=2; break;
case RET_NZ: if(!(R->AF.B.l&Z_FLAG)) { R->ICount-=6;M_RET; } break;
case RET_NC: if(!(R->AF.B.l&C_FLAG)) { R->ICount-=6;M_RET; } break;
case RET_PO: if(!(R->AF.B.l&P_FLAG)) { R->ICount-=6;M_RET; } break;
case RET_P: if(!(R->AF.B.l&S_FLAG)) { R->ICount-=6;M_RET; } break;
case RET_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=6;M_RET; } break;
case RET_C: if(R->AF.B.l&C_FLAG) { R->ICount-=6;M_RET; } break;
case RET_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=6;M_RET; } break;
case RET_M: if(R->AF.B.l&S_FLAG) { R->ICount-=6;M_RET; } break;
case CALL_NZ: if(R->AF.B.l&Z_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
case CALL_NC: if(R->AF.B.l&C_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
case CALL_PO: if(R->AF.B.l&P_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
case CALL_P: if(R->AF.B.l&S_FLAG) R->PC.W+=2; else { R->ICount-=7;M_CALL; } break;
case CALL_Z: if(R->AF.B.l&Z_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
case CALL_C: if(R->AF.B.l&C_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
case CALL_PE: if(R->AF.B.l&P_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
case CALL_M: if(R->AF.B.l&S_FLAG) { R->ICount-=7;M_CALL; } else R->PC.W+=2; break;
case ADD_B: M_ADD(R->BC.B.h);break;
case ADD_C: M_ADD(R->BC.B.l);break;
case ADD_D: M_ADD(R->DE.B.h);break;
case ADD_E: M_ADD(R->DE.B.l);break;
case ADD_H: M_ADD(R->XX.B.h);break;
case ADD_L: M_ADD(R->XX.B.l);break;
case ADD_A: M_ADD(R->AF.B.h);break;
case ADD_xHL: I=RdZ80(R->XX.W+(offset)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) { R->ICount-=5;M_JR; } else R->PC.W++;break;
case JP: M_JP;break;
case JR: M_JR;break;
case CALL: M_CALL;break;
case RET: M_RET;break;
case SCF: S(C_FLAG);R(N_FLAG|H_FLAG);break;
case CPL: R->AF.B.h=~R->AF.B.h;S(N_FLAG|H_FLAG);break;
case NOP: break;
case OUTA: 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|=IFF_HALT;
R->IBackup=0;
R->ICount=0;
break;
case DI:
if(R->IFF&IFF_EI) R->ICount+=R->IBackup-1;
R->IFF&=~(IFF_1|IFF_2|IFF_EI);
break;
case EI:
if(!(R->IFF&(IFF_1|IFF_EI)))
{
R->IFF|=IFF_2|IFF_EI;
R->IBackup=R->ICount;
R->ICount=1;
}
break;
case CCF:
R->AF.B.l^=C_FLAG;R(N_FLAG|H_FLAG);
R->AF.B.l|=R->AF.B.l&C_FLAG? 0:H_FLAG;
break;
case EXX:
J.W=R->BC.W;R->BC.W=R->BC1.W;R->BC1.W=J.W;
J.W=R->DE.W;R->DE.W=R->DE1.W;R->DE1.W=J.W;
J.W=R->HL.W;R->HL.W=R->HL1.W;R->HL1.W=J.W;
break;
case EX_DE_HL: J.W=R->DE.W;R->DE.W=R->HL.W;R->HL.W=J.W;break;
case EX_AF_AF: J.W=R->AF.W;R->AF.W=R->AF1.W;R->AF1.W=J.W;break;
case LD_B_B: R->BC.B.h=R->BC.B.h;break;
case LD_C_B: R->BC.B.l=R->BC.B.h;break;
case LD_D_B: R->DE.B.h=R->BC.B.h;break;
case LD_E_B: R->DE.B.l=R->BC.B.h;break;
case LD_H_B: R->XX.B.h=R->BC.B.h;break;
case LD_L_B: R->XX.B.l=R->BC.B.h;break;
case LD_A_B: R->AF.B.h=R->BC.B.h;break;
case LD_xHL_B: J.W=R->XX.W+(offset)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;

View file

@ -1,95 +1,95 @@
/*************************************************************/
/** **/
/** diskwork.h **/
/** **/
/** Common definitions for programs working with **/
/** disk-images that can be used with fMSX **/
/** **/
/** **/
/** Copyright (c) Arnold Metselaar 1996 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define usint unsigned short int
#define byte unsigned char
#define EOF_FAT 0xFFF /* signals EOF in FAT */
typedef struct de {
char d_fname[8];
char d_ext[3];
char d_attrib;
char d_reserv[10]; /* unused */
byte d_time[2]; /* byte-ordering of ints is machine-dependent */
byte d_date[2];
byte d_first[2];
byte d_size[4];
} DirEntry;
/* macros to change DirEntries */
#define setsh(x,y) {x[0]=y;x[1]=y>>8;}
#define setlg(x,y) {x[0]=y;x[1]=y>>8;x[2]=y>>16;x[3]=y>>24;}
/* macros to read DirEntries */
#define rdsh(x) (x[0]+(x[1]<<8))
#define rdlg(x) (x[0]+(x[1]<<8)+(x[2]<<16)+(x[3]<<24))
#define PError(x) { fprintf(stderr,"%s: ",progname); perror(x); }
#define seclen 512 /* length of sector */
#define cluslen 1024 /* length of cluster */
void *xalloc(size_t len)
{
void *p;
if (!(p=malloc(len)))
{
puts("Out of memory\n"); exit(2);
}
return p;
}
extern byte *FAT;
/* read FAT-entry from FAT in memory */
usint ReadFAT(usint clnr)
{ register byte *P;
P=FAT+(clnr*3)/2;
return (clnr&1)? (P[0]>>4)+(P[1]<<4) : P[0]+((P[1]&0x0F)<<8);
}
/* write an entry to FAT in memory */
void WriteFAT(usint clnr, usint val)
{ register byte *P;
P=FAT+(clnr*3)/2;
if (clnr&1)
{
P[0]=(P[0]&0x0F)+(val<<4);
P[1]=val>>4;
}
else
{
P[0]=val;
P[1]=(P[1]&0xF0)+((val>>8)&0x0F);
}
}
/*************************************************************/
/** **/
/** diskwork.h **/
/** **/
/** Common definitions for programs working with **/
/** disk-images that can be used with fMSX **/
/** **/
/** **/
/** Copyright (c) Arnold Metselaar 1996 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define usint unsigned short int
#define byte unsigned char
#define EOF_FAT 0xFFF /* signals EOF in FAT */
typedef struct de {
char d_fname[8];
char d_ext[3];
char d_attrib;
char d_reserv[10]; /* unused */
byte d_time[2]; /* byte-ordering of ints is machine-dependent */
byte d_date[2];
byte d_first[2];
byte d_size[4];
} DirEntry;
/* macros to change DirEntries */
#define setsh(x,y) {x[0]=y;x[1]=y>>8;}
#define setlg(x,y) {x[0]=y;x[1]=y>>8;x[2]=y>>16;x[3]=y>>24;}
/* macros to read DirEntries */
#define rdsh(x) (x[0]+(x[1]<<8))
#define rdlg(x) (x[0]+(x[1]<<8)+(x[2]<<16)+(x[3]<<24))
#define PError(x) { fprintf(stderr,"%s: ",progname); perror(x); }
#define seclen 512 /* length of sector */
#define cluslen 1024 /* length of cluster */
void *xalloc(size_t len)
{
void *p;
if (!(p=malloc(len)))
{
puts("Out of memory\n"); exit(2);
}
return p;
}
extern byte *FAT;
/* read FAT-entry from FAT in memory */
usint ReadFAT(usint clnr)
{ register byte *P;
P=FAT+(clnr*3)/2;
return (clnr&1)? (P[0]>>4)+(P[1]<<4) : P[0]+((P[1]&0x0F)<<8);
}
/* write an entry to FAT in memory */
void WriteFAT(usint clnr, usint val)
{ register byte *P;
P=FAT+(clnr*3)/2;
if (clnr&1)
{
P[0]=(P[0]&0x0F)+(val<<4);
P[1]=val>>4;
}
else
{
P[0]=val;
P[1]=(P[1]&0xF0)+((val>>8)&0x0F);
}
}

View file

@ -1,196 +1,196 @@
/** EMULib Emulation Library *********************************/
/** **/
/** I8251.c **/
/** **/
/** This file contains emulation for the Intel 8251 UART **/
/** chip and the 8253 timer chip implementing a generic **/
/** RS232 interface. **/
/** **/
/** Copyright (C) Marat Fayzullin 2003 **/
/** Maarten ter Huurne 2000 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "I8251.h"
/** Reset8251 ************************************************/
/** Reset 8251 chip, assigning In and Out to the input and **/
/** output streams. **/
/*************************************************************/
void Reset8251(register I8251 *D,FILE *In,FILE *Out)
{
D->IRQMask = 0x0F; /* All interrupts on */
D->IRQs = 0x00; /* No interrupts yet */
D->Mode = 1; /* Setting mode next */
D->Flow = 0x00; /* Flow control off */
D->NextChr = -1; /* No data yet */
/* Assign input and output streams */
D->In = In? In:stdin;
D->Out = Out? Out:stdout;
}
/** Rd8251 ***************************************************/
/** Read a byte from a given 8251 register. All values of R **/
/** will be truncated to 3 bits as there are only 8 regs. **/
/*************************************************************/
byte Rd8251(register I8251 *D,register byte R)
{
register int J;
/* We only have 8 addressable ports */
R&=0x07;
switch(R)
{
case 0: /* Data */
if(D->Flow)
{
if(D->NextChr<0) D->NextChr=fgetc(D->In);
J=D->NextChr;
D->NextChr=-1;
return((J<0? 0xFF:J)&((0x20<<((D->Control&0x0C)>>2))-1));
}
return(0xFF);
case 1: /* Status */
if(D->NextChr<0) D->NextChr=fgetc(D->In);
return(D->Flow&&(D->NextChr>=0)? 0x87:0x85);
/*
76543210
1....... data set ready (dsr)
.1...... sync detect, sync only
..1..... framing error (fe), async only
...1.... overrun error (oe)
....1... parity error (pe)
.....1.. transmitter empty
......1. receiver ready
.......1 transmitter ready
D->Flow is checked first, so that stdin input doesn't block
fMSX until it's actually being read by the emulated MSX.
*/
case 0x82: /* Status of CTS, timer/counter 2, RI and CD */
return(0x7F);
/*
76543210
1....... CTS (Clear To Send) 0=asserted
.1...... timer/counter output-2 from 8253
..XXXX.. reserved
......1. RI (Ring Indicator) 0=asserted
.......1 CD (Carrier Detect) 0=asserted
RI and CD are optional. If only one of them is implemented,
it must be CD. Implemented like this:
- CTS always returns 0 (asserted)
- Everything else is not implemented
*/
}
/* Other RS232 ports:
3: not standardised - unused
4: 8253 counter 0 - not implemented
5: 8253 counter 1 - not implemented
6: 8253 counter 2 - not implemented
7: 8253 mode register - write only
*/
return(0xFF);
}
/** Wr8251 ***************************************************/
/** Write a byte to a given 8251 register. All values of R **/
/** will be truncated to 3 bits as there are only 8 regs. **/
/*************************************************************/
void Wr8251(register I8251 *D,register byte R,register byte V)
{
/* We only have 8 addressable ports */
R&=0x07;
switch(R)
{
case 0: /* Data */
fputc(V&((0x20<<((D->Control&0x0C)>>2))-1),D->Out);
fflush(D->Out);
return;
/*
TODO: Flush the stream at appropriate intervals, instead of
flushing for every single character. If flushing after every
character remains, make the stream unbuffered.
*/
case 1: /* Command */
if(D->Mode)
{
D->Control=V;
D->Mode=0;
/* Set mode:
......00 sync mode
......01 async, baud rate factor is 1
......10 async, baud rate factor is 16
......11 async, baud rate factor is 64
....00.. character length is 5 bits
....01.. character length is 6 bits
....10.. character length is 7 bits
....11.. character length is 8 bits
...1.... parity enable
..1..... even/odd parity
.1...... sync: external sync detect (syndet) is an input/output
1....... sync: single/double character sync
00...... async: invalid
01...... async: 1 stop bit
10...... async: 1.5 stop bits
11...... async: 2 stop bits
*/
}
else
{
D->Mode=V&0x40;
D->Flow=(V>>4)&0x02;
/* Execute command:
76543210
1....... enter hunt mode (enable search for sync characters)
.1...... internal reset
..1..... request to send (rts)
...1.... reset error flags (pe,oe,fe)
....1... send break character
.....1.. receive enable
......1. data terminal ready (dtr)
.......1 transmit enable
Only RESET (bit6) and DTR (bit2) are implemented.
*/
}
return;
case 2: /* Interrupt mask register */
D->IRQMask=V;
return;
/*
76543210
XXXX.... reserved
....1... timer interrupt from 8253 channel-2 (0=enable int)
.....1.. sync character detect/break detect (0=enable int)
......1. transmit data ready (TxReady) (0=enable int)
.......1 receive data ready (RxReady) (0=enable int)
Initially all interrupts are disabled. RxReady interrupt must be
implemented, the others are optional.
However, currently no interrupt at all is implemented. The result
is that only one character is read per VDP interrupt, so serial
communication is 50/60 baud.
*/
}
/* Other RS232 ports:
3: not standardised - unused
4: 8253 counter 0 - not implemented
5: 8253 counter 1 - not implemented
6: 8253 counter 2 - not implemented
7: 8253 mode register - not implemented
*/
/** EMULib Emulation Library *********************************/
/** **/
/** I8251.c **/
/** **/
/** This file contains emulation for the Intel 8251 UART **/
/** chip and the 8253 timer chip implementing a generic **/
/** RS232 interface. **/
/** **/
/** Copyright (C) Marat Fayzullin 2004-2005 **/
/** Maarten ter Huurne 2000 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "I8251.h"
/** Reset8251 ************************************************/
/** Reset 8251 chip, assigning In and Out to the input and **/
/** output streams. **/
/*************************************************************/
void Reset8251(register I8251 *D,FILE *In,FILE *Out)
{
D->IRQMask = 0x0F; /* All interrupts on */
D->IRQs = 0x00; /* No interrupts yet */
D->Mode = 1; /* Setting mode next */
D->Flow = 0x00; /* Flow control off */
D->NextChr = -1; /* No data yet */
/* Assign input and output streams */
D->In = In? In:stdin;
D->Out = Out? Out:stdout;
}
/** Rd8251 ***************************************************/
/** Read a byte from a given 8251 register. All values of R **/
/** will be truncated to 3 bits as there are only 8 regs. **/
/*************************************************************/
byte Rd8251(register I8251 *D,register byte R)
{
register int J;
/* We only have 8 addressable ports */
R&=0x07;
switch(R)
{
case 0: /* Data */
if(D->Flow)
{
if(D->NextChr<0) D->NextChr=fgetc(D->In);
J=D->NextChr;
D->NextChr=-1;
return((J<0? 0xFF:J)&((0x20<<((D->Control&0x0C)>>2))-1));
}
return(0xFF);
case 1: /* Status */
if(D->NextChr<0) D->NextChr=fgetc(D->In);
return(D->Flow&&(D->NextChr>=0)? 0x87:0x85);
/*
76543210
1....... data set ready (dsr)
.1...... sync detect, sync only
..1..... framing error (fe), async only
...1.... overrun error (oe)
....1... parity error (pe)
.....1.. transmitter empty
......1. receiver ready
.......1 transmitter ready
D->Flow is checked first, so that stdin input doesn't block
fMSX until it's actually being read by the emulated MSX.
*/
case 0x82: /* Status of CTS, timer/counter 2, RI and CD */
return(0x7F);
/*
76543210
1....... CTS (Clear To Send) 0=asserted
.1...... timer/counter output-2 from 8253
..XXXX.. reserved
......1. RI (Ring Indicator) 0=asserted
.......1 CD (Carrier Detect) 0=asserted
RI and CD are optional. If only one of them is implemented,
it must be CD. Implemented like this:
- CTS always returns 0 (asserted)
- Everything else is not implemented
*/
}
/* Other RS232 ports:
3: not standardised - unused
4: 8253 counter 0 - not implemented
5: 8253 counter 1 - not implemented
6: 8253 counter 2 - not implemented
7: 8253 mode register - write only
*/
return(0xFF);
}
/** Wr8251 ***************************************************/
/** Write a byte to a given 8251 register. All values of R **/
/** will be truncated to 3 bits as there are only 8 regs. **/
/*************************************************************/
void Wr8251(register I8251 *D,register byte R,register byte V)
{
/* We only have 8 addressable ports */
R&=0x07;
switch(R)
{
case 0: /* Data */
fputc(V&((0x20<<((D->Control&0x0C)>>2))-1),D->Out);
fflush(D->Out);
return;
/*
TODO: Flush the stream at appropriate intervals, instead of
flushing for every single character. If flushing after every
character remains, make the stream unbuffered.
*/
case 1: /* Command */
if(D->Mode)
{
D->Control=V;
D->Mode=0;
/* Set mode:
......00 sync mode
......01 async, baud rate factor is 1
......10 async, baud rate factor is 16
......11 async, baud rate factor is 64
....00.. character length is 5 bits
....01.. character length is 6 bits
....10.. character length is 7 bits
....11.. character length is 8 bits
...1.... parity enable
..1..... even/odd parity
.1...... sync: external sync detect (syndet) is an input/output
1....... sync: single/double character sync
00...... async: invalid
01...... async: 1 stop bit
10...... async: 1.5 stop bits
11...... async: 2 stop bits
*/
}
else
{
D->Mode=V&0x40;
D->Flow=(V>>4)&0x02;
/* Execute command:
76543210
1....... enter hunt mode (enable search for sync characters)
.1...... internal reset
..1..... request to send (rts)
...1.... reset error flags (pe,oe,fe)
....1... send break character
.....1.. receive enable
......1. data terminal ready (dtr)
.......1 transmit enable
Only RESET (bit6) and DTR (bit2) are implemented.
*/
}
return;
case 2: /* Interrupt mask register */
D->IRQMask=V;
return;
/*
76543210
XXXX.... reserved
....1... timer interrupt from 8253 channel-2 (0=enable int)
.....1.. sync character detect/break detect (0=enable int)
......1. transmit data ready (TxReady) (0=enable int)
.......1 receive data ready (RxReady) (0=enable int)
Initially all interrupts are disabled. RxReady interrupt must be
implemented, the others are optional.
However, currently no interrupt at all is implemented. The result
is that only one character is read per VDP interrupt, so serial
communication is 50/60 baud.
*/
}
/* Other RS232 ports:
3: not standardised - unused
4: 8253 counter 0 - not implemented
5: 8253 counter 1 - not implemented
6: 8253 counter 2 - not implemented
7: 8253 mode register - not implemented
*/
}

View file

@ -1,57 +1,57 @@
/** EMULib Emulation Library *********************************/
/** **/
/** I8251.h **/
/** **/
/** This file contains definitions and declarations for **/
/** routines in I8251.c. **/
/** **/
/** Copyright (C) Marat Fayzullin 2003 **/
/** Maarten ter Huurne 2000 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef I8251_H
#define I8251_H
#include <stdio.h>
#ifndef BYTE_TYPE_DEFINED
#define BYTE_TYPE_DEFINED
typedef unsigned char byte;
#endif
/** I8251 ****************************************************/
/** This data structure stores I8251 state. **/
/*************************************************************/
typedef struct
{
byte Control; /* 8251 ACIA control reg. */
byte IRQMask; /* RS232 interrupt mask */
byte IRQs; /* RS232 interrupts */
byte Mode; /* 8251 mode/cmd select */
byte Flow; /* Flow control state */
int NextChr; /* Next char or -1 */
FILE *In; /* Input stream */
FILE *Out; /* Output stream */
} I8251;
/** Reset8251 ************************************************/
/** Reset 8251 chip, assigning In and Out to the input and **/
/** output streams. **/
/*************************************************************/
void Reset8251(register I8251 *D,FILE *In,FILE *Out);
/** Rd8251 ***************************************************/
/** Read a byte from a given 8251 register. All values of R **/
/** will be truncated to 3 bits as there are only 8 regs. **/
/*************************************************************/
byte Rd8251(register I8251 *D,register byte R);
/** Wr8251 ***************************************************/
/** Write a byte to a given 8251 register. All values of R **/
/** will be truncated to 3 bits as there are only 8 regs. **/
/*************************************************************/
void Wr8251(register I8251 *D,register byte R,register byte V);
#endif /* I8251_H */
/** EMULib Emulation Library *********************************/
/** **/
/** I8251.h **/
/** **/
/** This file contains definitions and declarations for **/
/** routines in I8251.c. **/
/** **/
/** Copyright (C) Marat Fayzullin 2004-2005 **/
/** Maarten ter Huurne 2000 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef I8251_H
#define I8251_H
#include <stdio.h>
#ifndef BYTE_TYPE_DEFINED
#define BYTE_TYPE_DEFINED
typedef unsigned char byte;
#endif
/** I8251 ****************************************************/
/** This data structure stores I8251 state. **/
/*************************************************************/
typedef struct
{
byte Control; /* 8251 ACIA control reg. */
byte IRQMask; /* RS232 interrupt mask */
byte IRQs; /* RS232 interrupts */
byte Mode; /* 8251 mode/cmd select */
byte Flow; /* Flow control state */
int NextChr; /* Next char or -1 */
FILE *In; /* Input stream */
FILE *Out; /* Output stream */
} I8251;
/** Reset8251 ************************************************/
/** Reset 8251 chip, assigning In and Out to the input and **/
/** output streams. **/
/*************************************************************/
void Reset8251(register I8251 *D,FILE *In,FILE *Out);
/** Rd8251 ***************************************************/
/** Read a byte from a given 8251 register. All values of R **/
/** will be truncated to 3 bits as there are only 8 regs. **/
/*************************************************************/
byte Rd8251(register I8251 *D,register byte R);
/** Wr8251 ***************************************************/
/** Write a byte to a given 8251 register. All values of R **/
/** will be truncated to 3 bits as there are only 8 regs. **/
/*************************************************************/
void Wr8251(register I8251 *D,register byte R,register byte V);
#endif /* I8251_H */

View file

@ -1,88 +1,88 @@
/** EMULib Emulation Library *********************************/
/** **/
/** I8255.c **/
/** **/
/** This file contains emulation for the i8255 parallel **/
/** port interface (PPI) chip from Intel. See I8255.h for **/
/** declarations. **/
/** **/
/** Copyright (C) Marat Fayzullin 2001-2003 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "I8255.h"
/** Reset8255 ************************************************/
/** Reset the chip. Set all data to 0x00. Set all ports to **/
/** "input" mode. **/
/*************************************************************/
void Reset8255(register I8255 *D)
{
/* Initialize all registers and ports */
D->R[0]=D->Rout[0]=D->Rin[0]=0x00;
D->R[1]=D->Rout[1]=D->Rin[1]=0x00;
D->R[2]=D->Rout[2]=D->Rin[2]=0x00;
D->R[3]=0x9B;
}
/** Write8255 ************************************************/
/** Write value V into i8255 register A. Returns 0 when A **/
/** is out of range, 1 otherwise. **/
/*************************************************************/
byte Write8255(register I8255 *D,register byte A,register byte V)
{
switch(A)
{
case 0:
case 1:
case 2:
/* Data registers */
D->R[A]=V;
break;
case 3:
/* Control register */
if(V&0x80) D->R[A]=V;
else
{
A=1<<((V&0x0E)>>1);
if(V&0x01) D->R[2]|=A; else D->R[2]&=~A;
}
break;
default:
/* Invalid register */
return(0);
}
/* Set output ports */
V=D->R[3];
D->Rout[0] = V&0x10? 0x00:D->R[0];
D->Rout[1] = V&0x02? 0x00:D->R[1];
D->Rout[2] = ((V&0x01? 0x00:D->R[2])&0x0F)
| ((V&0x08? 0x00:D->R[2])&0xF0);
/* Done */
return(1);
}
/** Read8255 *************************************************/
/** Read value from an i8255 register A. Returns 0 when A **/
/** is out of range. **/
/*************************************************************/
byte Read8255(register I8255 *D,register byte A)
{
switch(A)
{
case 0: return(D->R[3]&0x10? D->Rin[0]:D->R[0]);
case 1: return(D->R[3]&0x02? D->Rin[1]:D->R[1]);
case 2: return
(
((D->R[3]&0x01? D->Rin[2]:D->R[2])&0x0F)|
((D->R[3]&0x08? D->Rin[2]:D->R[2])&0xF0)
);
case 3: return(D->R[3]);
}
/* Invalid address */
return(0x00);
}
/** EMULib Emulation Library *********************************/
/** **/
/** I8255.c **/
/** **/
/** This file contains emulation for the i8255 parallel **/
/** port interface (PPI) chip from Intel. See I8255.h for **/
/** declarations. **/
/** **/
/** Copyright (C) Marat Fayzullin 2001-2005 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "I8255.h"
/** Reset8255 ************************************************/
/** Reset the chip. Set all data to 0x00. Set all ports to **/
/** "input" mode. **/
/*************************************************************/
void Reset8255(register I8255 *D)
{
/* Initialize all registers and ports */
D->R[0]=D->Rout[0]=D->Rin[0]=0x00;
D->R[1]=D->Rout[1]=D->Rin[1]=0x00;
D->R[2]=D->Rout[2]=D->Rin[2]=0x00;
D->R[3]=0x9B;
}
/** Write8255 ************************************************/
/** Write value V into i8255 register A. Returns 0 when A **/
/** is out of range, 1 otherwise. **/
/*************************************************************/
byte Write8255(register I8255 *D,register byte A,register byte V)
{
switch(A)
{
case 0:
case 1:
case 2:
/* Data registers */
D->R[A]=V;
break;
case 3:
/* Control register */
if(V&0x80) D->R[A]=V;
else
{
A=1<<((V&0x0E)>>1);
if(V&0x01) D->R[2]|=A; else D->R[2]&=~A;
}
break;
default:
/* Invalid register */
return(0);
}
/* Set output ports */
V=D->R[3];
D->Rout[0] = V&0x10? 0x00:D->R[0];
D->Rout[1] = V&0x02? 0x00:D->R[1];
D->Rout[2] = ((V&0x01? 0x00:D->R[2])&0x0F)
| ((V&0x08? 0x00:D->R[2])&0xF0);
/* Done */
return(1);
}
/** Read8255 *************************************************/
/** Read value from an i8255 register A. Returns 0 when A **/
/** is out of range. **/
/*************************************************************/
byte Read8255(register I8255 *D,register byte A)
{
switch(A)
{
case 0: return(D->R[3]&0x10? D->Rin[0]:D->R[0]);
case 1: return(D->R[3]&0x02? D->Rin[1]:D->R[1]);
case 2: return
(
((D->R[3]&0x01? D->Rin[2]:D->R[2])&0x0F)|
((D->R[3]&0x08? D->Rin[2]:D->R[2])&0xF0)
);
case 3: return(D->R[3]);
}
/* Invalid address */
return(0x00);
}

View file

@ -1,50 +1,50 @@
/** EMULib Emulation Library *********************************/
/** **/
/** I8255.h **/
/** **/
/** This file contains emulation for the i8255 parallel **/
/** port interface (PPI) chip from Intel. See I8255.h for **/
/** the actual code. **/
/** **/
/** Copyright (C) Marat Fayzullin 2001-2003 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef I8255_H
#define I8255_H
#ifndef BYTE_TYPE_DEFINED
#define BYTE_TYPE_DEFINED
typedef unsigned char byte;
#endif
/** I8255 ****************************************************/
/** This data structure stores i8255 state and port values. **/
/*************************************************************/
typedef struct
{
byte R[4]; /* Registers */
byte Rout[3]; /* Output ports */
byte Rin[3]; /* Input ports */
} I8255;
/** Reset8255 ************************************************/
/** Reset the i8255 chip. Set all data to 0x00. Set all **/
/** ports to "input" mode. **/
/*************************************************************/
void Reset8255(register I8255 *D);
/** Write8255 ************************************************/
/** Write value V into i8255 register A. Returns 0 when A **/
/** is out of range, 1 otherwise. **/
/*************************************************************/
byte Write8255(register I8255 *D,register byte A,register byte V);
/** Read8255 *************************************************/
/** Read value from an i8255 register A. Returns 0 when A **/
/** is out of range. **/
/*************************************************************/
byte Read8255(register I8255 *D,register byte A);
#endif /* I8255_H */
/** EMULib Emulation Library *********************************/
/** **/
/** I8255.h **/
/** **/
/** This file contains emulation for the i8255 parallel **/
/** port interface (PPI) chip from Intel. See I8255.h for **/
/** the actual code. **/
/** **/
/** Copyright (C) Marat Fayzullin 2001-2005 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#ifndef I8255_H
#define I8255_H
#ifndef BYTE_TYPE_DEFINED
#define BYTE_TYPE_DEFINED
typedef unsigned char byte;
#endif
/** I8255 ****************************************************/
/** This data structure stores i8255 state and port values. **/
/*************************************************************/
typedef struct
{
byte R[4]; /* Registers */
byte Rout[3]; /* Output ports */
byte Rin[3]; /* Input ports */
} I8255;
/** Reset8255 ************************************************/
/** Reset the i8255 chip. Set all data to 0x00. Set all **/
/** ports to "input" mode. **/
/*************************************************************/
void Reset8255(register I8255 *D);
/** Write8255 ************************************************/
/** Write value V into i8255 register A. Returns 0 when A **/
/** is out of range, 1 otherwise. **/
/*************************************************************/
byte Write8255(register I8255 *D,register byte A,register byte V);
/** Read8255 *************************************************/
/** Read value from an i8255 register A. Returns 0 when A **/
/** is out of range. **/
/*************************************************************/
byte Read8255(register I8255 *D,register byte A);
#endif /* I8255_H */

File diff suppressed because it is too large Load diff

View file

@ -5,11 +5,12 @@
/** This file contains implementation for the PatchZ80() **/
/** function necessary for emulating MSX disk and tape IO. **/
/** **/
/** Copyright (C) Marat Fayzullin 1994-2003 **/
/** Copyright (C) Marat Fayzullin 1994-2005 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "MSX.h"
#include "Boot.h"
#include <stdio.h>
@ -351,6 +352,7 @@ case 0x00E1:
rewind(CasStream);
}
if(Verbose&0x04) puts("FAILED");
#endif
return;
@ -373,6 +375,7 @@ case 0x00E4:
return;
}
case 0x00E7:
/** TAPIOF: *****************************************************
****************************************************************/

View file

@ -1,187 +1,187 @@
/** EMULib Emulation Library *********************************/
/** **/
/** SCC.c **/
/** **/
/** This file contains emulation for the SCC sound chip **/
/** produced by Konami. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-2003 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "SCC.h"
#include "Sound.h"
#include <string.h>
/** ResetSCC() ***********************************************/
/** Reset the sound chip and use sound channels from the **/
/** one given in First. **/
/*************************************************************/
void ResetSCC(register SCC *D,int First)
{
int J;
/* Reset registers */
memset(D->R,0x00,sizeof(D->R));
/* Set instruments, frequencies, volumes */
for(J=0;J<SCC_CHANNELS;J++)
{
SetSound(0+First,SND_MELODIC);
D->Freq[J]=D->Volume[J]=0;
}
D->First = First;
D->Sync = SCC_ASYNC;
D->Changed = 0x00;
D->WChanged = 0x00;
}
/** ReadSCC() ************************************************/
/** Call this function to read contents of the generic SCC **/
/** sound chip registers. **/
/*************************************************************/
byte ReadSCC(register SCC *D,register byte R)
{
return(R<0x80? D->R[R]:0xFF);
}
/** ReadSCCP() ***********************************************/
/** Call this function to read contents of the newer SCC+ **/
/** sound chip registers. **/
/*************************************************************/
byte ReadSCCP(register SCC *D,register byte R)
{
return(R<0xA0? D->R[R]:0xFF);
}
/** WriteSCC() ***********************************************/
/** Call this function to output a value V into the generic **/
/** SCC sound chip. **/
/*************************************************************/
void WriteSCC(register SCC *D,register byte R,register byte V)
{
/* Prevent rollover */
if(R>=0xE0) return;
/* Generic SCC has one waveform less than SCC+ */
if(R>=0x80) { WriteSCCP(D,R+0x20,V);return; }
/* The last waveform applies to both channels 3 and 4 */
if(R>=0x60) { WriteSCCP(D,R,V);WriteSCCP(D,R+0x20,V);return; }
/* Other waveforms are the same */
WriteSCCP(D,R,V);
}
/** WriteSCCP() **********************************************/
/** Call this function to output a value V into the newer **/
/** SCC+ sound chip. **/
/*************************************************************/
void WriteSCCP(register SCC *D,register byte R,register byte V)
{
register int J;
register byte I;
/* Exit if no change */
if(V==D->R[R]) return;
if((R&0xE0)==0xA0)
{
/* Emulate melodic features */
/* Save active channel mask in I */
I=D->R[0xAF];
/* Write to a register */
R&=0xEF;
D->R[R]=D->R[R+0x10]=V;
/* Melodic register number 0..15 */
R&=0x0F;
switch(R)
{
case 0: case 1: case 2: case 3: case 4:
case 5: case 6: case 7: case 8: case 9:
/* Exit if the channel is silenced */
if(!(I&(1<<(R>>1)))) return;
/* Go to the first register of the pair */
R=(R&0xFE)+0xA0;
/* Compute frequency */
J=((int)(D->R[R+1]&0x0F)<<8)+D->R[R];
/* Compute channel number */
R=(R&0x0F)>>1;
/* Assign frequency */
D->Freq[R]=J? SCC_BASE/J:0;
/* Compute changed channels mask */
D->Changed|=1<<R;
break;
case 10: case 11: case 12: case 13: case 14:
/* Compute channel number */
R-=10;
/* Compute and assign new volume */
D->Volume[R]=255*(V&0x0F)/15;
/* Compute changed channels mask */
D->Changed|=(1<<R)&I;
break;
case 15:
/* Find changed channels */
R=(V^I)&0x1F;
D->Changed|=R;
/* Update frequencies */
for(I=0;R&&(I<SCC_CHANNELS);I++,R>>=1,V>>=1)
if(R&1)
{
if(!(V&1)) D->Freq[I]=0;
else
{
J=I*2+0xA0;
J=((int)(D->R[J+1]&0x0F)<<8)+D->R[J];
D->Freq[I]=J? SCC_BASE/J:0;
}
}
break;
default:
/* Wrong register, do nothing */
return;
}
}
else
{
/* Emulate wave table features */
/* Write data to SCC */
D->R[R]=V;
/* Wrong register, do nothing */
if(R>=0xA0) return;
/* Mark channel waveform as changed */
D->WChanged|=1<<(R>>5);
}
/* For asynchronous mode, make Sound() calls right away */
if(!D->Sync&&(D->Changed||D->WChanged)) SyncSCC(D,SCC_FLUSH);
}
/** SyncSCC() ************************************************/
/** Flush all accumulated changes by issuing Sound() calls **/
/** and set the synchronization on/off. The second argument **/
/** should be SCC_SYNC/SCC_ASYNC to set/reset sync, or **/
/** SCC_FLUSH to leave sync mode as it is. **/
/*************************************************************/
void SyncSCC(register SCC *D,register byte Sync)
{
register int J,I;
if(Sync!=SCC_FLUSH) D->Sync=Sync;
/* Modify waveforms */
for(J=0,I=D->WChanged;I&&(J<SCC_CHANNELS);J++,I>>=1)
if(I&1) SetWave(J+D->First,(signed char *)(D->R+(J<<5)),32,0);
/* Modify frequencies and volumes */
for(J=0,I=D->Changed;I&&(J<SCC_CHANNELS);J++,I>>=1)
if(I&1) Sound(J+D->First,D->Freq[J],D->Volume[J]);
D->Changed=D->WChanged=0x00;
}
/** EMULib Emulation Library *********************************/
/** **/
/** SCC.c **/
/** **/
/** This file contains emulation for the SCC sound chip **/
/** produced by Konami. **/
/** **/
/** Copyright (C) Marat Fayzullin 1996-2005 **/
/** You are not allowed to distribute this software **/
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "SCC.h"
#include "Sound.h"
#include <string.h>
/** ResetSCC() ***********************************************/
/** Reset the sound chip and use sound channels from the **/
/** one given in First. **/
/*************************************************************/
void ResetSCC(register SCC *D,int First)
{
int J;
/* Reset registers */
memset(D->R,0x00,sizeof(D->R));
/* Set instruments, frequencies, volumes */
for(J=0;J<SCC_CHANNELS;J++)
{
SetSound(0+First,SND_MELODIC);
D->Freq[J]=D->Volume[J]=0;
}
D->First = First;
D->Sync = SCC_ASYNC;
D->Changed = 0x00;
D->WChanged = 0x00;
}
/** ReadSCC() ************************************************/
/** Call this function to read contents of the generic SCC **/
/** sound chip registers. **/
/*************************************************************/
byte ReadSCC(register SCC *D,register byte R)
{
return(R<0x80? D->R[R]:0xFF);
}
/** ReadSCCP() ***********************************************/
/** Call this function to read contents of the newer SCC+ **/
/** sound chip registers. **/
/*************************************************************/
byte ReadSCCP(register SCC *D,register byte R)
{
return(R<0xA0? D->R[R]:0xFF);
}
/** WriteSCC() ***********************************************/
/** Call this function to output a value V into the generic **/
/** SCC sound chip. **/
/*************************************************************/
void WriteSCC(register SCC *D,register byte R,register byte V)
{
/* Prevent rollover */
if(R>=0xE0) return;
/* Generic SCC has one waveform less than SCC+ */
if(R>=0x80) { WriteSCCP(D,R+0x20,V);return; }
/* The last waveform applies to both channels 3 and 4 */
if(R>=0x60) { WriteSCCP(D,R,V);WriteSCCP(D,R+0x20,V);return; }
/* Other waveforms are the same */
WriteSCCP(D,R,V);
}
/** WriteSCCP() **********************************************/
/** Call this function to output a value V into the newer **/
/** SCC+ sound chip. **/
/*************************************************************/
void WriteSCCP(register SCC *D,register byte R,register byte V)
{
register int J;
register byte I;
/* Exit if no change */
if(V==D->R[R]) return;
if((R&0xE0)==0xA0)
{
/* Emulate melodic features */
/* Save active channel mask in I */
I=D->R[0xAF];
/* Write to a register */
R&=0xEF;
D->R[R]=D->R[R+0x10]=V;
/* Melodic register number 0..15 */
R&=0x0F;
switch(R)
{
case 0: case 1: case 2: case 3: case 4:
case 5: case 6: case 7: case 8: case 9:
/* Exit if the channel is silenced */
if(!(I&(1<<(R>>1)))) return;
/* Go to the first register of the pair */
R=(R&0xFE)+0xA0;
/* Compute frequency */
J=((int)(D->R[R+1]&0x0F)<<8)+D->R[R];
/* Compute channel number */
R=(R&0x0F)>>1;
/* Assign frequency */
D->Freq[R]=J? SCC_BASE/J:0;
/* Compute changed channels mask */
D->Changed|=1<<R;
break;
case 10: case 11: case 12: case 13: case 14:
/* Compute channel number */
R-=10;
/* Compute and assign new volume */
D->Volume[R]=255*(V&0x0F)/15;
/* Compute changed channels mask */
D->Changed|=(1<<R)&I;
break;
case 15:
/* Find changed channels */
R=(V^I)&0x1F;
D->Changed|=R;
/* Update frequencies */
for(I=0;R&&(I<SCC_CHANNELS);I++,R>>=1,V>>=1)
if(R&1)
{
if(!(V&1)) D->Freq[I]=0;
else
{
J=I*2+0xA0;
J=((int)(D->R[J+1]&0x0F)<<8)+D->R[J];
D->Freq[I]=J? SCC_BASE/J:0;
}
}
break;
default:
/* Wrong register, do nothing */
return;
}
}
else
{
/* Emulate wave table features */
/* Write data to SCC */
D->R[R]=V;
/* Wrong register, do nothing */
if(R>=0xA0) return;
/* Mark channel waveform as changed */
D->WChanged|=1<<(R>>5);
}
/* For asynchronous mode, make Sound() calls right away */
if(!D->Sync&&(D->Changed||D->WChanged)) SyncSCC(D,SCC_FLUSH);
}
/** SyncSCC() ************************************************/
/** Flush all accumulated changes by issuing Sound() calls **/
/** and set the synchronization on/off. The second argument **/
/** should be SCC_SYNC/SCC_ASYNC to set/reset sync, or **/
/** SCC_FLUSH to leave sync mode as it is. **/
/*************************************************************/
void SyncSCC(register SCC *D,register byte Sync)
{
register int J,I;
if(Sync!=SCC_FLUSH) D->Sync=Sync;
/* Modify waveforms */
for(J=0,I=D->WChanged;I&&(J<SCC_CHANNELS);J++,I>>=1)
if(I&1) SetWave(J+D->First,(signed char *)(D->R+(J<<5)),32,0);
/* Modify frequencies and volumes */
for(J=0,I=D->Changed;I&&(J<SCC_CHANNELS);J++,I>>=1)
if(I&1) Sound(J+D->First,D->Freq[J],D->Volume[J]);
D->Changed=D->WChanged=0x00;
}

Some files were not shown because too many files have changed in this diff Show more