1
0
mirror of https://github.com/samstyle/Xpeccy.git synced 2025-04-19 00:04:05 +03:00

build 20170426

[+] Virtual keyboard: LMB = press+release, RMB = trigger, MMB = release
all keys
[+] Virtual keyboard: indicate all ZX keys state
[+] CMakeLists.txt fixes for MacOSX. Bundle icon is now available!
[+] internal: cpu->exec makes a decision: to exec opcode or to handle
interrupt. no more cpu->intr there
This commit is contained in:
samstyle 2017-04-26 16:31:43 +03:00
parent fa83c135eb
commit 0914907c84
37 changed files with 357 additions and 303 deletions

View File

@ -87,11 +87,17 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CPACK_DMG_NAME ${PROJECT_NAME})
set(CPACK_DMG_FORMAT UDZO)
set(CPACK_BUNDLE_NAME ${PROJECT_NAME}.app)
set(CPACK_BUNDLE_ICON ${CMAKE_SOURCE_DIR}/images/xpeccy.icns)
set(MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME}.app)
set(MACOSX_BUNDLE_ICON_FILE ${PROJECT_NAME}.icns)
set(MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/Info.plist)
set(MACOSX_BUNDLE_BUNDLE_VERSION ${XVER})
set_source_files_properties(${CMAKE_BINARY_DIR}/${PROJECT_NAME} PROPERTIES MACOS_PACKAGE_LOCATION MacOSX)
set_source_files_properties(${CPACK_BUNDLE_ICON} PROPERTIES MACOS_PACKAGE_LOCATION Resources)
set(BUNDLE_ICON_PATH ${CMAKE_SOURCE_DIR}/images/${MACOSX_BUNDLE_ICON_FILE})
set(BUNDLE_PATH ${CMAKE_BINARY_DIR}/${MACOSX_BUNDLE_BUNDLE_NAME})
set_source_files_properties(${CMAKE_BINARY_DIR}/${PROJECT_NAME} PROPERTIES MACOSX_PACKAGE_LOCATION MacOSX)
set_source_files_properties(${BUNDLE_ICON_PATH} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
@ -143,6 +149,7 @@ set(MOCFILES
./src/dbg_finder.h
./src/watcher.h
./src/setupwin.h
./src/vkeyboard.h
./src/xgui/xgui.h
)
@ -232,14 +239,20 @@ include_directories(${INCLUDIRS})
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS} ${UIHEADERS} ${RESOURCES} ${MOCHEADERS})
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SOURCES} ${HEADERS} ${UIHEADERS} ${RESOURCES} ${MOCHEADERS})
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SOURCES} ${HEADERS} ${UIHEADERS} ${RESOURCES} ${MOCHEADERS} ${BUNDLE_ICON_PATH})
find_program(MACDEPLOYQTEXE macdeployqt)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND mkdir ARGS -p ${CMAKE_BINARY_DIR}/${CPACK_BUNDLE_NAME}/Contents/Frameworks
COMMAND cp ARGS -R /Library/Frameworks/SDL.framework ${CMAKE_BINARY_DIR}/${CPACK_BUNDLE_NAME}/Contents/Frameworks
COMMAND ${MACDEPLOYQTEXE} ARGS ${CMAKE_BINARY_DIR}/${CPACK_BUNDLE_NAME} -always-overwrite
COMMAND ${MACDEPLOYQTEXE} ARGS ${BUNDLE_PATH} -always-overwrite
# COMMAND mkdir ARGS -p ${BUNDLE_PATH}/Contents/Frameworks
COMMAND cp ARGS -R /Library/Frameworks/SDL.framework ${BUNDLE_PATH}/Contents/Frameworks
)
set(CMAKE_INSTALL_PREFIX "/Applications")
# install(CODE "
# include(BundleUtilities)
# fixup_bundle(${BUNDLE_PATH} \"\" ${LIBDIRS})
# find_program(MACDEPLOYQTEXE macdeployqt)
# execute_process(COMMAND ${MACDEPLOYQTEXE} ARGS ${BUNDLE_PATH} -always-overwrite)
# " COMPONENT Runtime)
install(TARGETS ${PROJECT_NAME} BUNDLE DESTINATION .)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
add_executable(${PROJECT_NAME} WIN32 ${SOURCES} ${HEADERS} ${UIHEADERS} ${RESOURCES} ${MOCHEADERS})

30
Info.plist Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>Russian</string>
<key>CFBundleDisplayName</key>
<string>xpeccy</string>
<key>CFBundleExecutable</key>
<string>xpeccy</string>
<key>CFBundleIconFile</key>
<string>xpeccy.icns</string>
<key>CFBundleIdentifier</key>
<string>ru.samstyle.xpeccy</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>xpeccy</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.6</string>
<key>CFBundleSignature</key>
<string>iddqd</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.productivity</string>
</dict>
</plist>

View File

@ -1 +1 @@
0.6.20170419
0.6.20170426

BIN
images/cartrige.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

BIN
images/keyboardzx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

BIN
images/objective.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 B

BIN
images/pixels.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -41,7 +41,7 @@ void DebugWin::start(Computer* c) {
updateScreen();
if (!comp->vid->tail)
vidDarkTail(comp->vid);
ui.tabsPanel->setTabEnabled(ui.tabsPanel->indexOf(ui.gbTab), comp->hw->type == HW_GBC);
ui.tabsPanel->setTabEnabled(ui.tabsPanel->indexOf(ui.gbTab), comp->hw->id == HW_GBC);
ui.dasmTable->comp = comp;
move(winPos);
@ -369,7 +369,7 @@ void DebugWin::doStep() {
disasmAdr = comp->cpu->pc;
fillDisasm();
}
if ((traceType == DBG_TRACE_INT) && (comp->cpu->inth))
if ((traceType == DBG_TRACE_INT) && (comp->cpu->intrq & comp->cpu->inten))
trace = 0;
if ((traceType == DBG_TRACE_HERE) && (comp->cpu->pc == traceAdr))
trace = 0;
@ -646,7 +646,7 @@ bool DebugWin::fillAll() {
setSignal(ui.labCPM, comp->cpm);
//setSignal(ui.labHBlank, comp->vid->hblank);
//setSignal(ui.labVBlank, comp->vid->vblank);
setSignal(ui.labINT, comp->cpu->inth);
setSignal(ui.labINT, comp->cpu->intrq & comp->cpu->inten);
if (memViewer->isVisible())
memViewer->fillImage();
return fillDisasm();

View File

@ -33,83 +33,13 @@
// main
unsigned char screen[2048 * 2048 * 3]; // scaled image (up to fullscreen)
unsigned char screen[4096 * 2048 * 3]; // scaled image (up to fullscreen)
unsigned char scrn[1024 * 512 * 3]; // 2:1 image
unsigned char prvScr[1024 * 512 * 3]; // copy of last 2:1 image (for noflic)
// temp emulation
unsigned short pc,af,de,ix;
// onscreen keyboard
unsigned char kwMap[4][10] = {
{'1','2','3','4','5','6','7','8','9','0'},
{'q','w','e','r','t','y','u','i','o','p'},
{'a','s','d','f','g','h','j','k','l','E'},
{'C','z','x','c','v','b','n','m','S',' '}
};
keyWindow::keyWindow(QWidget* p):QLabel(p) {
kb = NULL;
xk.key1 = 0;
xk.key2 = 0;
}
void keyWindow::paintEvent(QPaintEvent*) {
QPainter pnt;
int wid = width() / 10 + 1;
int hig = height() / 4;
pnt.begin(this);
pnt.fillRect(QRectF(0,0,1,1), qRgba(0,0,0,0));
if (~kb->map[0] & 2) { // SS
pnt.fillRect(8 * wid, 3 * hig, wid, hig, qRgba(64, 160, 160, 100));
}
if (~kb->map[7] & 1) { // CS
pnt.fillRect(0, 3 * hig, wid, hig, qRgba(64, 160, 160, 100));
}
pnt.drawPixmap(0, 0, QPixmap(":/images/keymap.png"));
pnt.end();
}
void keyWindow::mousePressEvent(QMouseEvent* ev) {
if (!kb) return;
int row;
int col;
if (ev->button() == Qt::RightButton) {
keyReleaseAll(kb);
xk.key1 = 0;
} else {
row = ev->y() * 4 / height();
col = ev->x() * 10 / width();
xk.key1 = kwMap[row][col];
if ((xk.key1 == 'S') || (xk.key1 == 'C')) {
keyTrigger(kb, xk, 0);
update();
} else {
keyPress(kb, xk, 0);
}
}
}
void keyWindow::mouseReleaseEvent(QMouseEvent* ev) {
if (!kb) return;
switch(xk.key1) {
case 'C':
if (kb->map[0] & 2) break;
keyRelease(kb, xk, 0);
update();
break;
case 'S':
if (kb->map[7] & 1) break;
keyRelease(kb, xk, 0);
update();
break;
default:
keyRelease(kb, xk, 0);
break;
}
}
// mainwin
void MainWin::updateHead() {
@ -236,8 +166,6 @@ MainWin::MainWin() {
rzxWin = new RZXWin(this);
connect(rzxWin,SIGNAL(stateChanged(int)),this,SLOT(rzxStateChanged(int)));
initUserMenu();
keywin = new keyWindow();
QPixmap pxm(":/images/keymap.png");
keywin->setPixmap(pxm);
@ -245,6 +173,8 @@ MainWin::MainWin() {
keywin->setWindowIcon(QIcon(":/images/keyboard.png"));
keywin->setWindowTitle("ZX Keyboard");
initUserMenu();
cmosTimer.start(1000);
timer.setInterval(20);
connect(&cmosTimer,SIGNAL(timeout()),this,SLOT(cmosTick()));
@ -554,8 +484,8 @@ void MainWin::keyPressEvent(QKeyEvent *ev) {
keywin->close();
} else {
keywin->show();
activateWindow();
raise();
// activateWindow();
// raise();
}
break;
case Qt::Key_N:
@ -572,7 +502,7 @@ void MainWin::keyPressEvent(QKeyEvent *ev) {
break;
}
} else {
if (comp->hw->type == HW_GBC)
if (comp->hw->id == HW_GBC)
gbPress(comp, kent.name);
keyPress(comp->keyb, kent.zxKey, 0);
if (kent.msxKey.key1) keyPress(comp->keyb,kent.msxKey,2);
@ -664,6 +594,7 @@ void MainWin::keyPressEvent(QKeyEvent *ev) {
break;
}
}
if (keywin->isVisible()) keywin->update();
}
void MainWin::keyReleaseEvent(QKeyEvent *ev) {
@ -680,6 +611,7 @@ void MainWin::keyReleaseEvent(QKeyEvent *ev) {
keyRelease(comp->keyb, kent.zxKey, 0);
if (kent.msxKey.key1) keyRelease(comp->keyb,kent.msxKey,2);
}
if (keywin->isVisible()) keywin->update();
}
void MainWin::mousePressEvent(QMouseEvent *ev){
@ -1031,7 +963,8 @@ void MainWin::initUserMenu() {
userMenu->addSeparator();
pckAct = userMenu->addAction(QIcon(":/images/keyboard.png"),"PC keyboard");
pckAct->setCheckable(true);
userMenu->addAction(QIcon(),"Watcher",watcher,SLOT(show()));
userMenu->addAction(QIcon(":/images/keyboardzx.png"),"ZX Keyboard",keywin,SLOT(show()));
userMenu->addAction(QIcon(":/images/objective.png"),"Watcher",watcher,SLOT(show()));
userMenu->addAction(QIcon(":/images/other.png"),"Options",this,SLOT(doOptions()));
connect(bookmarkMenu,SIGNAL(triggered(QAction*)),this,SLOT(bookmarkSelected(QAction*)));
@ -1044,7 +977,7 @@ void MainWin::initUserMenu() {
fileMenu->addAction(QIcon(":/images/memory.png"),"Snapshot")->setData(FT_SNAP | FT_SPG);
fileMenu->addAction(QIcon(":/images/tape.png"),"Tape")->setData(FT_TAPE);
fileMenu->addAction(QIcon(":/images/floppy.png"),"Floppy")->setData(FT_DISK);
fileMenu->addAction(QIcon(),"Slot")->setData(FT_SLOT);
fileMenu->addAction(QIcon(":/images/cartrige.png"),"Slot")->setData(FT_SLOT);
nsAct = vmodeMenu->addAction("No screen");
nsAct->setData(-1);

View File

@ -11,6 +11,7 @@
#include "setupwin.h"
#include "debuger.h"
#include "watcher.h"
#include "vkeyboard.h"
#include "xcore/xcore.h"
#include "xgui/xgui.h"
#include "ethread.h"
@ -35,19 +36,6 @@ typedef struct {
QString imgName;
} xLed;
class keyWindow : public QLabel {
Q_OBJECT
public:
keyWindow(QWidget* = NULL);
Keyboard* kb;
private:
xKey xk;
protected:
void paintEvent(QPaintEvent*);
void mousePressEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*);
};
class MainWin : public QWidget {
Q_OBJECT
public:

View File

@ -4,7 +4,7 @@
#include "xgui/xgui.h"
#include "xcore/sound.h"
std::mutex emutex;
QMutex emutex;
unsigned char* blkData = NULL;
extern unsigned char scrn[1024 * 512 * 3];

View File

@ -2,7 +2,7 @@
#define _ETHREAD_H
#include <QThread>
#include <mutex>
#include <QMutex>
#include "xcore/xcore.h"
@ -29,6 +29,6 @@ class xThread : public QThread {
void tapeSignal(int,int);
};
extern std::mutex emutex;
extern QMutex emutex;
#endif

View File

@ -93,7 +93,7 @@ int getFileType(QString path) {
int testSlotOn(Computer* comp) {
int res = 0;
switch (comp->hw->type) {
switch (comp->hw->id) {
case HW_MSX:
case HW_MSX2:
case HW_GBC:

View File

@ -27,23 +27,6 @@ void lr_reset(CPU* cpu) {
cpu->i = cpu->r = cpu->r7 = 0xff;
}
int lr_exec(CPU* cpu) {
if (cpu->lock) return 1;
cpu->t = 0;
cpu->opTab = lrTab;
do {
cpu->tmp = cpu->mrd(cpu->pc++, 1, cpu->data);
cpu->op = &cpu->opTab[cpu->tmp];
cpu->t += cpu->op->t;
cpu->op->exec(cpu);
} while (cpu->op->prefix);
if (cpu->dihalt) { // LR35902 bug (?) : repeat opcode after HALT with disabled interrupts (DI)
cpu->dihalt = 0;
cpu->pc = cpu->tmpw;
}
return cpu->t;
}
typedef struct {
unsigned char mask;
unsigned short inta;
@ -77,6 +60,30 @@ int lr_int(CPU* cpu) {
return res;
}
int lr_exec(CPU* cpu) {
int res = 0;
if ((cpu->intrq & cpu->inten) && cpu->iff1) {
res = lr_int(cpu);
} else if (cpu->lock) {
res = 1;
} else {
cpu->t = 0;
cpu->opTab = lrTab;
do {
cpu->tmp = cpu->mrd(cpu->pc++, 1, cpu->data);
cpu->op = &cpu->opTab[cpu->tmp];
cpu->t += cpu->op->t;
cpu->op->exec(cpu);
} while (cpu->op->prefix);
if (cpu->dihalt) { // LR35902 bug (?) : repeat opcode after HALT with disabled interrupts (DI)
cpu->dihalt = 0;
cpu->pc = cpu->tmpw;
}
res = cpu->t;
}
return res;
}
// disasm
xAsmScan lr_asm(const char* cbuf, char* buf) {

View File

@ -26,16 +26,23 @@ int m6502_int(CPU* cpu) {
m6502_push_int(cpu);
cpu->pc = 0xfffe;
}
cpu->inth = cpu->intrq ? 1 : 0; // if both INT happened in one time
// cpu->inth = cpu->intrq ? 1 : 0; // if both INT happened in one time
return 7;
}
int m6502_exec(CPU* cpu) {
unsigned char com = cpu->mrd(cpu->pc++, 1, cpu->data);
opCode* op = &mosTab[com];
cpu->t = op->t; // 2T fetch
op->exec(cpu);
return cpu->t;
int res = 0;
unsigned char com;
if (cpu->intrq & cpu->inten) {
res = m6502_int(cpu);
} else {
com = cpu->mrd(cpu->pc++, 1, cpu->data);
opCode* op = &mosTab[com];
cpu->t = op->t; // 2T fetch
op->exec(cpu);
res = cpu->t;
}
return res;
}
xMnem m6502_mnem(CPU* cpu, unsigned short adr, cbdmr mrd, void* data) {

View File

@ -92,7 +92,7 @@ void mosGetINDY(CPU* cpu) {
// brk : 7T
void mosop00(CPU* cpu) {
cpu->intrq |= 1; // request for user interrupt
cpu->inth = 1;
// cpu->inth = 1;
}
// 01:ora indx n : 6T

View File

@ -26,24 +26,10 @@ void z80_reset(CPU* cpu) {
cpu->i = cpu->r = cpu->r7 = 0;
cpu->halt = 0;
cpu->intrq = 0;
cpu->inten = 2; // NMI allways enabled, INT is controlled by ei/di
cpu->wait = 0;
}
int z80_exec(CPU* cpu) {
if (cpu->wait) return 1;
cpu->t = 0;
cpu->noint = 0;
cpu->opTab = npTab;
do {
cpu->com = cpu->mrd(cpu->pc++,1,cpu->data);
cpu->op = &cpu->opTab[cpu->com];
cpu->r++;
cpu->t += cpu->op->t;
cpu->op->exec(cpu);
} while (cpu->op->prefix);
return cpu->t;
}
int z80_int(CPU* cpu) {
int res = 0;
if (cpu->wait) return 0;
@ -108,6 +94,28 @@ int z80_int(CPU* cpu) {
return res;
}
int z80_exec(CPU* cpu) {
int res = 0;
if (cpu->wait) {
res = 1;
} else if (cpu->intrq & cpu->inten) {
res = z80_int(cpu);
} else {
cpu->t = 0;
cpu->noint = 0;
cpu->opTab = npTab;
do {
cpu->com = cpu->mrd(cpu->pc++,1,cpu->data);
cpu->op = &cpu->opTab[cpu->com];
cpu->r++;
cpu->t += cpu->op->t;
cpu->op->exec(cpu);
} while (cpu->op->prefix);
res = cpu->t;
}
return res;
}
// disasm
unsigned char z80_cnd[4] = {FZ, FC, FP, FS};

View File

@ -845,6 +845,7 @@ void nprF2(CPU* cpu) {
void nprF3(CPU* cpu) {
cpu->iff1 = 0;
cpu->iff2 = 0;
cpu->inten &= ~1;
}
// f4 call p,nn 4 3rd 3rd[+1] [3wr 3wr] memptr = nn
@ -897,6 +898,7 @@ void nprFB(CPU* cpu) {
cpu->iff1 = 1;
cpu->iff2 = 1;
cpu->noint = 1;
cpu->inten |= 1;
}
// fc call m,nn 4 3rd 3rd[+1] [3wr 3wr] mptr = nn

View File

@ -28,9 +28,9 @@ extern opCode npTab[256];
extern opCode lrTab[256];
cpuCore cpuTab[] = {
{CPU_Z80, "Z80", npTab, z80_reset, z80_exec, z80_int, z80_asm, z80_mnem},
{CPU_LR35902, "LR35902", lrTab, lr_reset, lr_exec, lr_int, lr_asm, lr_mnem},
{CPU_NONE, "none", NULL, nil_reset, nil_exec, nil_int, nil_asm, nil_mnem}
{CPU_Z80, "Z80", npTab, z80_reset, z80_exec, /*z80_int,*/ z80_asm, z80_mnem},
{CPU_LR35902, "LR35902", lrTab, lr_reset, lr_exec, /*lr_int,*/ lr_asm, lr_mnem},
{CPU_NONE, "none", NULL, nil_reset, nil_exec, /*nil_int,*/ nil_asm, nil_mnem}
};
cpuCore* findCore(int type) {
@ -59,7 +59,7 @@ void cpuSetType(CPU* cpu, int type) {
cpu->type = core->type;
cpu->reset = core->reset;
cpu->exec = core->exec;
cpu->intr = core->intr;
// cpu->intr = core->intr;
cpu->asmbl = core->asmbl;
cpu->mnem = core->mnem;
cpu->tab = core->tab;

View File

@ -10,11 +10,17 @@ typedef struct {
const char* mnem;
} xMnem;
// memrq rd
typedef unsigned char(*cbmr)(unsigned short,int,void*);
// memrq wr
typedef void(*cbmw)(unsigned short,unsigned char,void*);
// iorq rd
typedef unsigned char(*cbir)(unsigned short,void*);
// iorq wr
typedef void(*cbiw)(unsigned short,unsigned char,void*);
// iorq int : interrupt vector request
typedef unsigned char(*cbirq)(void*);
// memrd external
typedef unsigned char(*cbdmr)(unsigned short,void*);
#ifdef WORDS_BIG_ENDIAN
@ -55,7 +61,7 @@ enum {
struct CPU {
unsigned halt:1; // cpu halted, undo on interrput
unsigned inth:1; // next step is 1:handle interrupt, 0: exec opcode
// unsigned inth:1; // next step is 1:handle interrupt, 0: exec opcode
unsigned resPV:1; // Z80: reset PV flag on INT
unsigned noint:1; // Z80: don't handle INT after EI
unsigned wait:1; // Z80: WAIT signal
@ -106,7 +112,7 @@ struct CPU {
void (*reset)(CPU*);
int (*exec)(CPU*);
int (*intr)(CPU*); // handle interrupt. intrq = requested INT types
// int (*intr)(CPU*); // handle interrupt. intrq = requested INT types
xAsmScan (*asmbl)(const char*, char*);
xMnem (*mnem)(CPU*, unsigned short, cbdmr, void*);
@ -123,7 +129,7 @@ typedef struct {
opCode* tab; // start opcode tab;
void (*reset)(CPU*); // reset
int (*exec)(CPU*); // exec opcode, return T
int (*intr)(CPU*); // handle interrupt, return T
// int (*intr)(CPU*); // handle interrupt, return T
xAsmScan (*asmbl)(const char*, char*); // compile mnemonic
xMnem (*mnem)(CPU*, unsigned short, cbdmr, void*);
} cpuCore;

View File

@ -30,17 +30,17 @@ void zx_sync(Computer* comp, long ns) {
if (!comp->cpu->iff1 || comp->cpu->noint) return;
if (comp->vid->intFRAME && (comp->vid->intMask & 1)) {
comp->intVector = 0xff;
comp->cpu->inth = 1;
// comp->cpu->inth = 1;
comp->cpu->intrq |= 1;
comp->vid->intFRAME = 0;
} else if (comp->vid->intLINE) {
comp->intVector = 0xfd;
comp->cpu->inth = 1;
// comp->cpu->inth = 1;
comp->cpu->intrq |= 1;
comp->vid->intLINE = 0;
} else if (comp->vid->intDMA) {
comp->intVector = 0xfb;
comp->cpu->inth = 1;
// comp->cpu->inth = 1;
comp->cpu->intrq |= 1;
comp->vid->intDMA = 0;
}

View File

@ -732,8 +732,8 @@ void gbc_sync(Computer* comp, long ns) {
req |= 16;
}
comp->cpu->intrq |= req; // cpu int req
if (comp->cpu->iff1 && (comp->cpu->intrq & 0x1f)) //comp->cpu->inten))
comp->cpu->inth = 1;
// if (comp->cpu->iff1 && (comp->cpu->intrq & 0x1f)) //comp->cpu->inten))
// comp->cpu->inth = 1;
}
// keypress

View File

@ -4,55 +4,55 @@
HardWare hwTab[] = {
{
"ZX48K","ZX 48K",HW_ZX48,50,MEM_48,
HW_ZX48,"ZX48K","ZX 48K",50,MEM_48,
&speMapMem,&speOut,&speIn,&stdMRd,&stdMWr,&speReset,&zx_sync
},{
"Pentagon","Pentagon",HW_PENT,50,MEM_128 | MEM_512,
HW_PENT,"Pentagon","Pentagon",50,MEM_128 | MEM_512,
&penMapMem,&penOut,&penIn,&stdMRd,&stdMWr,NULL,&zx_sync
},{
"Pentagon1024SL","Pentagon 1024 SL",HW_P1024,50,MEM_1M,
HW_P1024,"Pentagon1024SL","Pentagon 1024 SL",50,MEM_1M,
&p1mMapMem,&p1mOut,&p1mIn,&stdMRd,&stdMWr,NULL,&zx_sync
},{
"Scorpion","ZS Scorpion",HW_SCORP,50,MEM_256 | MEM_1M,
HW_SCORP,"Scorpion","ZS Scorpion",50,MEM_256 | MEM_1M,
&scoMapMem,&scoOut,&scoIn,&scoMRd,&stdMWr,NULL,&zx_sync
},{
"ATM2","ATM Turbo 2+",HW_ATM2,50,MEM_128 | MEM_256 | MEM_512 | MEM_1M,
HW_ATM2,"ATM2","ATM Turbo 2+",50,MEM_128 | MEM_256 | MEM_512 | MEM_1M,
&atm2MapMem,&atm2Out,&atm2In,&stdMRd,&stdMWr,&atm2Reset,&zx_sync
},{
"Profi","Profi",HW_PROFI,50,MEM_512 | MEM_1M,
HW_PROFI,"Profi","Profi",50,MEM_512 | MEM_1M,
&prfMapMem,&prfOut,&prfIn,&stdMRd,&stdMWr,&prfReset,&zx_sync
},{
"Phoenix","ZXM Phoenix",HW_PHOENIX,50,MEM_2M,
HW_PHOENIX,"Phoenix","ZXM Phoenix",50,MEM_2M,
&phxMapMem,&phxOut,&phxIn,&stdMRd,&stdMWr,&phxReset,&zx_sync
},{
"PentEvo","Evo Baseconf",HW_PENTEVO,50,MEM_4M,
HW_PENTEVO,"PentEvo","Evo Baseconf",50,MEM_4M,
&evoMapMem,&evoOut,&evoIn,&evoMRd,&evoMWr,&evoReset,&zx_sync
},{
"TSLab","Evo TSConf",HW_TSLAB,50,MEM_4M,
HW_TSLAB,"TSLab","Evo TSConf",50,MEM_4M,
&tslMapMem,&tslOut,&tslIn,&tslMRd,&tslMWr,&tslReset,&zx_sync
},{
"","",HW_NULL,50,0,NULL,NULL,NULL,NULL,NULL,NULL // separator
HW_NULL,"","",50,0,NULL,NULL,NULL,NULL,NULL,NULL // separator
},{
"Spectrum +2","Spectrum +2",HW_PLUS2,50,MEM_128,
HW_PLUS2,"Spectrum +2","Spectrum +2",50,MEM_128,
&pl2MapMem,&pl2Out,&pl2In,&stdMRd,&stdMWr,NULL,&zx_sync
},{
"Spectrum +3","Spectrum +3",HW_PLUS3,50,MEM_128,
HW_PLUS3,"Spectrum +3","Spectrum +3",50,MEM_128,
&pl2MapMem,&pl3Out,&pl3In,&stdMRd,&stdMWr,NULL,&zx_sync
},{
"","",HW_NULL,50,0,NULL,NULL,NULL,NULL,NULL,NULL // separator
HW_NULL,"","",50,0,NULL,NULL,NULL,NULL,NULL,NULL // separator
},{
"MSX","MSX-1",HW_MSX,60,MEM_128,
HW_MSX,"MSX","MSX-1",60,MEM_128,
&msxMapMem,&msxOut,&msxIn,&stdMRd,&stdMWr,&msxReset,&msx_sync
},{
"MSX2","MSX-2 (alfa)",HW_MSX2,60,MEM_128,
HW_MSX2,"MSX2","MSX-2 (alfa)",60,MEM_128,
&msx2mapper,&msx2Out,&msx2In,&msx2mrd,&msx2mwr,&msx2Reset,&msx_sync
},{
"","",HW_NULL,50,0,NULL,NULL,NULL,NULL,NULL,NULL // separator
HW_NULL,"","",50,0,NULL,NULL,NULL,NULL,NULL,NULL // separator
},{
"GameBoy", "Game Boy", HW_GBC, 60, MEM_48,
&gbMaper, NULL, NULL, &gbMemRd, &gbMemWr, &gbReset, &gbc_sync
HW_GBC,"GameBoy","Game Boy",60,MEM_48,
&gbMaper,NULL,NULL,&gbMemRd,&gbMemWr,&gbReset,&gbc_sync
},{
NULL,NULL,HW_NULL,50,0,NULL,NULL,NULL,NULL,NULL,NULL // eot
HW_NULL,NULL,NULL,50,0,NULL,NULL,NULL,NULL,NULL,NULL // eot
}
};
@ -60,7 +60,7 @@ HardWare* findHardware(const char* name) {
HardWare* hw = NULL;
int idx = 0;
while (hwTab[idx].name != NULL) {
if ((hwTab[idx].type != HW_NULL) && !strcmp(hwTab[idx].name,name)) {
if ((hwTab[idx].id != HW_NULL) && !strcmp(hwTab[idx].name,name)) {
hw = &hwTab[idx];
break;
}

View File

@ -37,12 +37,37 @@ enum {
#define MEM_2M (1<<4)
#define MEM_4M (1<<5)
// Hardware callbacks
// reset
typedef void(*cbHwRes)(Computer*);
// map memory
typedef void(*cbHwMap)(Computer*);
// sync: calls after every CPU command
typedef void(*cbHwSnc)(Computer*, long);
// memory read
typedef unsigned char(*cbHwMrd)(Computer*, unsigned short, int);
// memory write
typedef void(*cbHwMwr)(Computer*, unsigned short, unsigned char);
// io read; TODO:remove last argument (bdi activity)
typedef unsigned char(*cbHwIrd)(Computer*, unsigned short, int);
// io write
typedef void(*cbHwIwr)(Computer*, unsigned short, unsigned char, int);
struct HardWare {
int id; // id
const char* name; // name used for conf file
const char* optName; // name used for setup window
int type; // id
int fps;
int mask; // mem size bits (b0:128, b1:256, b2:512, b3:1M, b4:2M, b5:4M); =0 for 48K
cbHwMap mapMem;
cbHwIwr out;
cbHwIrd in;
cbHwMrd mrd;
cbHwMwr mwr;
cbHwRes reset;
cbHwSnc sync;
/*
void (*mapMem)(Computer*);
void (*out)(Computer*,unsigned short,unsigned char,int);
unsigned char (*in)(Computer*,unsigned short,int);
@ -50,6 +75,7 @@ struct HardWare {
void (*mwr)(Computer*,unsigned short,unsigned char);
void (*reset)(Computer*);
void (*sync)(Computer*, long); // callback after each command. control request/handle interrupt bit
*/
};
typedef struct {

View File

@ -249,7 +249,8 @@ void msxOut(Computer* comp, unsigned short port, unsigned char val, int dos) {
// int zxINT(Computer*, unsigned char);
void msx_sync(Computer* comp, long ns) {
if ((comp->vid->v9938.reg[1] & 0x40) && comp->vid->newFrame && comp->cpu->iff1) {
comp->cpu->inth = 1;
// comp->cpu->inth = 1;
comp->cpu->intrq |= 1;
comp->intVector = 0xff;
}
}

View File

@ -1,7 +1,7 @@
#include "../spectrum.h"
void speReset(Computer* comp) {
comp->p7FFD = 0x10;
}
void speMapMem(Computer* comp) {

View File

@ -130,18 +130,12 @@ void gsSync(GSound* gs) {
int res;
gs->counter += gs->sync * GS_FRQ / 980; // ticks to emulate
while (gs->counter > 0) {
if (gs->cpu->inth) {
gs->cpu->inth = 0;
gs->cpu->intrq = 1;
res = gs->cpu->intr(gs->cpu);
} else {
res = gs->cpu->exec(gs->cpu);
}
res = gs->cpu->exec(gs->cpu);
gs->counter -= res;
gs->cnt += res;
if (gs->cnt > 320) { // 12MHz CLK, 37.5KHz INT -> int in each 320 ticks
gs->cnt -= 320;
gs->cpu->inth = 1;
gs->cpu->intrq |= 1;
}
}
gs->sync = 0;

View File

@ -246,7 +246,6 @@ void compReset(Computer* comp,int res) {
if (comp->rzx.play) rzxStop(comp);
zxInitPalete(comp);
comp->vid->ula->active = 0;
comp->rzx.play = 0;
comp->prt2 = 0;
comp->p1FFD = 0;
comp->pEFF7 = 0;
@ -285,7 +284,7 @@ void compUpdateTimings(Computer* comp) {
long perNoTurbo = 1e3 / comp->cpuFrq;
if (perNoTurbo & 1) perNoTurbo++;
comp->nsPerTick = perNoTurbo / comp->frqMul;
int type = comp->hw ? comp->hw->type : HW_NULL;
int type = comp->hw ? comp->hw->id : HW_NULL;
switch (type) {
case HW_MSX:
case HW_MSX2:
@ -324,25 +323,23 @@ void compSetHardware(Computer* comp, const char* name) {
HardWare* hw = findHardware(name);
if (hw == NULL) return;
comp->hw = hw;
comp->vid->istsconf = (hw->type == HW_TSLAB) ? 1 : 0;
comp->vid->ismsx = ((hw->type == HW_MSX) || (hw->type == HW_MSX2)) ? 1 : 0;
comp->vid->isgb = (hw->type == HW_GBC) ? 1 : 0;
comp->vid->istsconf = (hw->id == HW_TSLAB) ? 1 : 0;
comp->vid->ismsx = ((hw->id == HW_MSX) || (hw->id == HW_MSX2)) ? 1 : 0;
comp->vid->isgb = (hw->id == HW_GBC) ? 1 : 0;
compUpdateTimings(comp);
}
// interrupts
// exec 1 opcode, sync devices, return eated ns
// IDEA : let video system to accumulate TIME value, not like (cpu->t * comp->nsPerTick);
void vidTSRender(Video*, unsigned char*);
int compExec(Computer* comp) {
res4 = 0;
res2 = 0;
if (comp->cpu->inth) { // 1:handle interrupt
comp->cpu->inth = 0;
res2 = comp->cpu->intr(comp->cpu);
}
if (res2 == 0)
res2 = comp->cpu->exec(comp->cpu);
// exec cpu opcode OR handle interrupt. get T states back
res2 = comp->cpu->exec(comp->cpu);
// scorpion WAIT: add 1T to odd-T command
if (comp->evenM1 && (res2 & 1))
res2++;
@ -368,10 +365,9 @@ int compExec(Computer* comp) {
// ...
res1 = res2;
pcreg = comp->cpu->pc;
// NMI TODO: remake as another INT
// NMI
if ((pcreg > 0x3fff) && comp->nmiRequest && !comp->rzx.play) {
comp->cpu->intrq |= 2; // request nmi
comp->cpu->inth = 1;
comp->dos = 1; // set dos page
comp->rom = 1;
comp->hw->mapMem(comp);
@ -383,7 +379,7 @@ int compExec(Computer* comp) {
if (comp->rzx.play) {
if (comp->rzx.frm.fetches < 1) {
comp->intVector = 0xff;
comp->cpu->inth = 1;
comp->cpu->intrq |= 1;
comp->rzx.fCurrent++;
comp->rzx.fCount--;
rzxGetFrame(comp);
@ -399,7 +395,6 @@ int compExec(Computer* comp) {
// TSConf : update 'next-line' registers TODO:move to TSConf hw->sync
if (comp->vid->nextrow && comp->vid->istsconf) {
tslUpdatePorts(comp);
// vidTSRender(comp->vid, comp->vid->linptr);
comp->vid->nextrow = 0;
}
// breakpoints
@ -419,7 +414,7 @@ int compExec(Computer* comp) {
difSync(comp->dif, nsTime);
// tsSync(comp->ts, nsTime);
if (comp->hw->type == HW_GBC) {
if (comp->hw->id == HW_GBC) {
// sound
gbsSync(comp->gbsnd, nsTime);
// timer

View File

@ -59,7 +59,7 @@ SetupWin::SetupWin(QWidget* par):QDialog(par) {
// machine
i = 0;
while (hwTab[i].name != NULL) {
if (hwTab[i].type != HW_NULL) {
if (hwTab[i].id != HW_NULL) {
ui.machbox->addItem(trUtf8(hwTab[i].optName),QString::fromLocal8Bit(hwTab[i].name));
} else {
ui.machbox->insertSeparator(i);

View File

@ -1 +1 @@
#define VERSION 0.6.20170419
#define VERSION 0.6.20170426

103
src/vkeyboard.cpp Normal file
View File

@ -0,0 +1,103 @@
// virtual keyboard
#include "vkeyboard.h"
#include "xcore/xcore.h"
#include <QPainter>
unsigned char kwMap[4][10] = {
{'1','2','3','4','5','6','7','8','9','0'},
{'q','w','e','r','t','y','u','i','o','p'},
{'a','s','d','f','g','h','j','k','l','E'},
{'C','z','x','c','v','b','n','m','S',' '}
};
keyWindow::keyWindow(QWidget* p):QLabel(p) {
kb = NULL;
xk.key1 = 0;
xk.key2 = 0;
// setWindowModality(Qt::WindowModal);
}
void keyWindow::paintEvent(QPaintEvent*) {
QPainter pnt;
int wid = width() / 10 + 1;
int hig = (height() - 10) / 4;
unsigned char val;
int row, pos;
pnt.begin(this);
pnt.fillRect(QRectF(0,0,1,1), qRgba(0,0,0,0));
// pnt.setPen(qRgb(0, 200, 255));
// pnt.setBrush(QBrush(qRgb(0, 180, 235)));
for(int i = 0; i < 8; i++) {
pos = (i & 4) ? 0 : 9;
row = (i & 4) ? (i & 3) : (~i & 3);
val = ~kb->map[i] & 0x1f;
while(val) {
if (val & 1) {
pnt.fillRect(pos * wid, 10 + row * hig, wid, hig, qRgb(0, 200, 255));
//pnt.drawRoundRect(pos * wid, row * hig, wid, hig);
}
val >>= 1;
pos += (i & 4) ? 1 : -1;
}
}
pnt.drawPixmap(0, 0, QPixmap(":/images/keymap.png"));
pnt.end();
}
void keyWindow::mousePressEvent(QMouseEvent* ev) {
if (!kb) return;
int row;
int col;
row = ev->y() * 4 / height();
col = ev->x() * 10 / width();
xk.key1 = kwMap[row][col];
switch(ev->button()) {
case Qt::LeftButton:
keyPress(kb, xk, 0);
update();
break;
case Qt::RightButton:
keyTrigger(kb, xk, 0);
update();
break;
case Qt::MiddleButton:
keyReleaseAll(kb);
xk.key1 = 0;
update();
break;
default:
break;
}
}
void keyWindow::mouseReleaseEvent(QMouseEvent* ev) {
if (!kb) return;
if (ev->button() == Qt::LeftButton) {
keyRelease(kb, xk, 0);
}
update();
}
void keyWindow::keyPressEvent(QKeyEvent* ev) {
int keyid = qKey2id(ev->key());
keyEntry kent = getKeyEntry(keyid);
if (ev->modifiers() & Qt::AltModifier) {
if (ev->key() == Qt::Key_K)
close();
} else {
keyPress(kb, kent.zxKey, 0);
if (kent.msxKey.key1)
keyPress(kb,kent.msxKey,2);
update();
}
}
void keyWindow::keyReleaseEvent(QKeyEvent* ev) {
int keyid = qKey2id(ev->key());
keyEntry kent = getKeyEntry(keyid);
keyRelease(kb, kent.zxKey, 0);
if (kent.msxKey.key1) keyRelease(kb,kent.msxKey,2);
update();
}

27
src/vkeyboard.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef _VKEYBOARD_H
#define _VKEYBOARD_H
#include <QWidget>
#include <QLabel>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QKeyEvent>
#include "libxpeccy/input.h"
class keyWindow : public QLabel {
Q_OBJECT
public:
keyWindow(QWidget* = NULL);
Keyboard* kb;
private:
xKey xk;
protected:
void paintEvent(QPaintEvent*);
void mousePressEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*);
void keyPressEvent(QKeyEvent*);
void keyReleaseEvent(QKeyEvent*);
};
#endif

View File

@ -2,8 +2,6 @@
#include "xcore.h"
// #if __linux
#define XKEY_1 10
#define XKEY_2 11
#define XKEY_3 12
@ -90,94 +88,6 @@
#define XKEY_RBRACK 257 // }
#define XKEY_QUEST 258
/*
#elif _WIN32
#define XKEY_1 2
#define XKEY_2 3
#define XKEY_3 4
#define XKEY_4 5
#define XKEY_5 6
#define XKEY_6 7
#define XKEY_7 8
#define XKEY_8 9
#define XKEY_9 10
#define XKEY_0 11
#define XKEY_MINUS 12
#define XKEY_PLUS 13
#define XKEY_BSP 14
#define XKEY_TAB 15
#define XKEY_Q 16
#define XKEY_W 17
#define XKEY_E 18
#define XKEY_R 19
#define XKEY_T 20
#define XKEY_Y 21
#define XKEY_U 22
#define XKEY_I 23
#define XKEY_O 24
#define XKEY_P 25
#define XKEY_LBRACE 26
#define XKEY_RBRACE 27
#define XKEY_ENTER 28
#define XKEY_LCTRL 29
#define XKEY_A 30
#define XKEY_S 31
#define XKEY_D 32
#define XKEY_F 33
#define XKEY_G 34
#define XKEY_H 35
#define XKEY_J 36
#define XKEY_K 37
#define XKEY_L 38
#define XKEY_DOTCOM 39 // ;
#define XKEY_QUOTE 40 // "
#define XKEY_TILDA 41 // ~
#define XKEY_LSHIFT 42
#define XKEY_SLASH 43
#define XKEY_Z 44
#define XKEY_X 45
#define XKEY_C 46
#define XKEY_V 47
#define XKEY_B 48
#define XKEY_N 49
#define XKEY_M 50
#define XKEY_PERIOD 51
#define XKEY_COMMA 52
#define XKEY_BSLASH 53 // /
#define XKEY_RSHIFT 54
#define XKEY_SPACE 57
#define XKEY_CAPS 58
#define XKEY_RCTRL XKEY_LCTRL
#define XKEY_RALT 312
#define XKEY_LALT 56
#define XKEY_HOME 327
#define XKEY_UP 328
#define XKEY_PGUP 329
#define XKEY_LEFT 331
#define XKEY_RIGHT 333
#define XKEY_END 335
#define XKEY_DOWN 336
#define XKEY_PGDN 337
#define XKEY_INS 338
#define XKEY_DEL 339
#define XKEY_MENU 349
#define XKEY_ESC 1
#define XKEY_F1 59
#define XKEY_F2 60
#define XKEY_F3 61
#define XKEY_F4 62
#define XKEY_F5 63
#define XKEY_F6 64
#define XKEY_F7 65
#define XKEY_F8 66
#define XKEY_F9 67
#define XKEY_F10 68
#define XKEY_F11 87
#endif
*/
#define ENDKEY 0
// KEYMAPS
@ -240,7 +150,7 @@ keyEntry keyMapInit[] = {
{"[",XKEY_LBRACK,{'S','8'},{'S','y'},{'[',0},0x54},
{"]",XKEY_RBRACK,{'S','9'},{'S','u'},{']',0},0x5b},
{"`",XKEY_TILDA,{'C','S'},{'S','x'},{'`',0},0x0e},
{"\\",XKEY_SLASH,{'S','c'},{'S','d'},{'\\',0},0x5d},
{"\\",XKEY_SLASH,{'S','C'},{0,0},{'\\',0},0x5d},
{"PGDN",XKEY_PGUP,{'C','3'},{'m'|0x80,0},{MSXK_CODE,0},0x7de0},
{"PGUP",XKEY_PGDN,{'C','4'},{'n'|0x80,0},{MSXK_SEL,0},0x7ae0},
@ -354,7 +264,7 @@ keyTrans ktTab[] = {
{Qt::Key_BracketRight, 1066, XKEY_RBRACK}, // ]
// {Qt::Key_BraceLeft, 1061, XKEY_LBRACE}, // { == Shift + [
// {Qt::Key_BraceRight, 1066, XKEY_LBRACE}, // } == Shift + ]
{Qt::Key_Slash, Qt::Key_Slash, XKEY_BSLASH}, // ?
{Qt::Key_Backslash, Qt::Key_Backslash, XKEY_SLASH}, // |
{Qt::Key_CapsLock, Qt::Key_CapsLock, XKEY_CAPS},
{Qt::Key_A, 1060, XKEY_A},
@ -380,6 +290,7 @@ keyTrans ktTab[] = {
{Qt::Key_M, 1068, XKEY_M},
{Qt::Key_Period, 1041, XKEY_PERIOD},
{Qt::Key_Comma, Qt::Key_Comma, XKEY_COMMA},
{Qt::Key_Slash, Qt::Key_Slash, XKEY_BSLASH}, // ?
{Qt::Key_Control, Qt::Key_Control, XKEY_LCTRL},
{Qt::Key_Alt, Qt::Key_Alt, XKEY_LALT},

View File

@ -4,12 +4,12 @@
#include "xcore.h"
#include <iostream>
#include <mutex>
#include <QMutex>
#include <SDL.h>
#undef main
extern std::mutex emutex; // unlock to start emulation cycle
extern QMutex emutex; // unlock to start emulation cycle
typedef struct {
unsigned char data[0x1000];

View File

@ -2220,7 +2220,7 @@
<action name="actSprScan">
<property name="icon">
<iconset resource="../xpeccy.qrc">
<normaloff>:/images/eye.png</normaloff>:/images/eye.png</iconset>
<normaloff>:/images/pixels.png</normaloff>:/images/pixels.png</iconset>
</property>
<property name="text">
<string>Sprite scanner</string>

View File

@ -48,7 +48,6 @@
<file>images/msx.png</file>
<file>images/stop.png</file>
<file>images/floppyRed.png</file>
<file>images/eye.png</file>
<file>images/gameboy.png</file>
<file>font.bin</file>
<file>images/label.png</file>
@ -61,5 +60,9 @@
<file>images/search.png</file>
<file>DejaVuSansMono.ttf</file>
<file>images/note.png</file>
<file>images/keyboardzx.png</file>
<file>images/objective.png</file>
<file>images/pixels.png</file>
<file>images/cartrige.png</file>
</qresource>
</RCC>