Merge branch 'master' of https://github.com/86Box/86Box
This commit is contained in:
5
.github/workflows/cmake.yml
vendored
5
.github/workflows/cmake.yml
vendored
@@ -76,6 +76,7 @@ jobs:
|
|||||||
${{ matrix.environment.prefix }}-zlib
|
${{ matrix.environment.prefix }}-zlib
|
||||||
${{ matrix.environment.prefix }}-libpng
|
${{ matrix.environment.prefix }}-libpng
|
||||||
${{ matrix.environment.prefix }}-libvncserver
|
${{ matrix.environment.prefix }}-libvncserver
|
||||||
|
${{ matrix.environment.prefix }}-openal
|
||||||
${{ matrix.environment.prefix }}-rtmidi
|
${{ matrix.environment.prefix }}-rtmidi
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
@@ -230,7 +231,7 @@ jobs:
|
|||||||
librtmidi-dev
|
librtmidi-dev
|
||||||
qtbase5-dev
|
qtbase5-dev
|
||||||
qttools5-dev
|
qttools5-dev
|
||||||
libfaudio-dev
|
libopenal-dev
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
run: >-
|
run: >-
|
||||||
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
|
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
|
||||||
@@ -271,7 +272,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: brew install freetype sdl2 libpng rtmidi qt@5 faudio ninja
|
run: brew install freetype sdl2 libpng rtmidi qt@5 openal-soft ninja
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
run: >-
|
run: >-
|
||||||
PATH=/usr/local/opt/qt@5/bin:$PATH
|
PATH=/usr/local/opt/qt@5/bin:$PATH
|
||||||
|
@@ -18,12 +18,8 @@ cmake_minimum_required(VERSION 3.16)
|
|||||||
cmake_policy(SET CMP0091 NEW)
|
cmake_policy(SET CMP0091 NEW)
|
||||||
cmake_policy(SET CMP0079 NEW)
|
cmake_policy(SET CMP0079 NEW)
|
||||||
|
|
||||||
# if(HAIKU)
|
|
||||||
# set(OPENAL ON)
|
|
||||||
# set(RTMIDI OFF)
|
|
||||||
# endif()
|
|
||||||
set(OPENAL ON)
|
|
||||||
if(HAIKU)
|
if(HAIKU)
|
||||||
|
set(OPENAL ON)
|
||||||
set(RTMIDI OFF)
|
set(RTMIDI OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -131,7 +127,7 @@ set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
|
|||||||
# ------ ----------- ----
|
# ------ ----------- ----
|
||||||
option(RELEASE "Release build" OFF)
|
option(RELEASE "Release build" OFF)
|
||||||
option(DYNAREC "Dynamic recompiler" ON)
|
option(DYNAREC "Dynamic recompiler" ON)
|
||||||
option(OPENAL "OpenAL" OFF)
|
option(OPENAL "OpenAL" ON)
|
||||||
option(RTMIDI "RtMidi" ON)
|
option(RTMIDI "RtMidi" ON)
|
||||||
option(FLUIDSYNTH "FluidSynth" ON)
|
option(FLUIDSYNTH "FluidSynth" ON)
|
||||||
option(MUNT "MUNT" ON)
|
option(MUNT "MUNT" ON)
|
||||||
|
@@ -96,6 +96,7 @@
|
|||||||
#include <86box/thread.h>
|
#include <86box/thread.h>
|
||||||
#include <86box/version.h>
|
#include <86box/version.h>
|
||||||
#include <86box/gdbstub.h>
|
#include <86box/gdbstub.h>
|
||||||
|
#include <86box/machine_status.h>
|
||||||
|
|
||||||
// Disable c99-designator to avoid the warnings about int ng
|
// Disable c99-designator to avoid the warnings about int ng
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
@@ -891,6 +892,8 @@ pc_init_modules(void)
|
|||||||
|
|
||||||
video_reset_close();
|
video_reset_close();
|
||||||
|
|
||||||
|
machine_status_init();
|
||||||
|
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
add_executable(86Box 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c
|
add_executable(86Box 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c
|
||||||
dma.c ddma.c discord.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c
|
dma.c ddma.c discord.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c
|
||||||
mca.c usb.c fifo8.c device.c nvr.c nvr_at.c nvr_ps2.c)
|
mca.c usb.c fifo8.c device.c nvr.c nvr_at.c nvr_ps2.c machine_status.c)
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||||
add_compile_definitions(_FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE=1 _LARGEFILE64_SOURCE=1)
|
add_compile_definitions(_FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE=1 _LARGEFILE64_SOURCE=1)
|
||||||
|
@@ -1642,9 +1642,6 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
|||||||
disabled, the Read Multiple operation is rejected with an Aborted Com-
|
disabled, the Read Multiple operation is rejected with an Aborted Com-
|
||||||
mand error. */
|
mand error. */
|
||||||
ide->blockcount = 0;
|
ide->blockcount = 0;
|
||||||
/* Turn on the activity indicator *here* so that it gets turned on
|
|
||||||
less times. */
|
|
||||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
|
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
|
|
||||||
case WIN_READ:
|
case WIN_READ:
|
||||||
@@ -1658,6 +1655,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
|||||||
ide->atastat = BSY_STAT;
|
ide->atastat = BSY_STAT;
|
||||||
|
|
||||||
if (ide->type == IDE_HDD) {
|
if (ide->type == IDE_HDD) {
|
||||||
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1);
|
||||||
uint32_t sec_count;
|
uint32_t sec_count;
|
||||||
double wait_time;
|
double wait_time;
|
||||||
if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) {
|
if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) {
|
||||||
@@ -1908,7 +1906,7 @@ ide_read_data(ide_t *ide, int length)
|
|||||||
double xfer_time = ide_get_xfer_time(ide, 512);
|
double xfer_time = ide_get_xfer_time(ide, 512);
|
||||||
ide_set_callback(ide, seek_time + xfer_time);
|
ide_set_callback(ide, seek_time + xfer_time);
|
||||||
}
|
}
|
||||||
} else if (ide->command != WIN_READ_MULTIPLE)
|
} else
|
||||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
src/include/86box/machine_status.h
Normal file
32
src/include/86box/machine_status.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef EMU_MACHINE_STATUS_H
|
||||||
|
#define EMU_MACHINE_STATUS_H
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
atomic_bool_t empty;
|
||||||
|
atomic_bool_t active;
|
||||||
|
} dev_status_empty_active_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
atomic_bool_t active;
|
||||||
|
} dev_status_active_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
atomic_bool_t empty;
|
||||||
|
} dev_status_empty_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
dev_status_empty_active_t fdd[FDD_NUM];
|
||||||
|
dev_status_empty_active_t cdrom[CDROM_NUM];
|
||||||
|
dev_status_empty_active_t zip[ZIP_NUM];
|
||||||
|
dev_status_empty_active_t mo[MO_NUM];
|
||||||
|
dev_status_empty_active_t cassette;
|
||||||
|
dev_status_active_t hdd[HDD_BUS_USB];
|
||||||
|
dev_status_active_t net;
|
||||||
|
dev_status_empty_t cartridge[2];
|
||||||
|
} machine_status_t;
|
||||||
|
|
||||||
|
extern machine_status_t machine_status;
|
||||||
|
|
||||||
|
extern void machine_status_init();
|
||||||
|
|
||||||
|
#endif /*EMU_MACHINE_STATUS_H*/
|
@@ -70,10 +70,12 @@ extern int strnicmp(const char* s1, const char* s2, size_t n);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#define atomic_flag_t std::atomic_flag
|
#define atomic_flag_t std::atomic_flag
|
||||||
|
#define atomic_bool_t std::atomic_bool
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#else
|
#else
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
#define atomic_flag_t atomic_flag
|
#define atomic_flag_t atomic_flag
|
||||||
|
#define atomic_bool_t atomic_bool
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Global variables residing in the platform module. */
|
/* Global variables residing in the platform module. */
|
||||||
|
@@ -70,8 +70,8 @@ extern void ui_sb_update_panes(void);
|
|||||||
extern void ui_sb_update_text(void);
|
extern void ui_sb_update_text(void);
|
||||||
extern void ui_sb_update_tip(int meaning);
|
extern void ui_sb_update_tip(int meaning);
|
||||||
extern void ui_sb_timer_callback(int pane);
|
extern void ui_sb_timer_callback(int pane);
|
||||||
extern void ui_sb_update_icon(int tag, int val);
|
extern void ui_sb_update_icon(int tag, int active);
|
||||||
extern void ui_sb_update_icon_state(int tag, int active);
|
extern void ui_sb_update_icon_state(int tag, int state);
|
||||||
extern void ui_sb_set_text_w(wchar_t *wstr);
|
extern void ui_sb_set_text_w(wchar_t *wstr);
|
||||||
extern void ui_sb_set_text(char *str);
|
extern void ui_sb_set_text(char *str);
|
||||||
extern void ui_sb_bugui(char *str);
|
extern void ui_sb_bugui(char *str);
|
||||||
|
52
src/machine_status.c
Normal file
52
src/machine_status.c
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/plat.h>
|
||||||
|
#include <86box/ui.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
|
#include <86box/device.h>
|
||||||
|
#include <86box/fdd.h>
|
||||||
|
#include <86box/hdc.h>
|
||||||
|
#include <86box/scsi.h>
|
||||||
|
#include <86box/scsi_device.h>
|
||||||
|
#include <86box/cartridge.h>
|
||||||
|
#include <86box/cassette.h>
|
||||||
|
#include <86box/cdrom.h>
|
||||||
|
#include <86box/zip.h>
|
||||||
|
#include <86box/mo.h>
|
||||||
|
#include <86box/hdd.h>
|
||||||
|
#include <86box/machine_status.h>
|
||||||
|
|
||||||
|
machine_status_t machine_status;
|
||||||
|
|
||||||
|
void
|
||||||
|
machine_status_init() {
|
||||||
|
for (size_t i = 0; i < FDD_NUM; ++i) {
|
||||||
|
machine_status.fdd[i].empty = (strlen(floppyfns[i]) == 0);
|
||||||
|
machine_status.fdd[i].active = false;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < CDROM_NUM; ++i) {
|
||||||
|
machine_status.cdrom[i].empty = cdrom[i].host_drive != 200 || (strlen(cdrom[i].image_path) == 0);
|
||||||
|
machine_status.cdrom[i].active = false;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < ZIP_NUM; i++) {
|
||||||
|
machine_status.zip[i].empty = (strlen(zip_drives[i].image_path) == 0);
|
||||||
|
machine_status.zip[i].active = false;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < MO_NUM; i++) {
|
||||||
|
machine_status.mo[i].empty = (strlen(mo_drives[i].image_path) == 0);
|
||||||
|
machine_status.mo[i].active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
machine_status.cassette.empty = (strlen(cassette_fname) == 0);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < HDD_BUS_USB; i++) {
|
||||||
|
machine_status.hdd[i].active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
machine_status.net.active = false;
|
||||||
|
}
|
@@ -39,6 +39,7 @@ extern uint64_t tsc;
|
|||||||
#include <86box/machine.h>
|
#include <86box/machine.h>
|
||||||
#include <86box/network.h>
|
#include <86box/network.h>
|
||||||
#include <86box/ui.h>
|
#include <86box/ui.h>
|
||||||
|
#include <86box/machine_status.h>
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
@@ -92,17 +93,21 @@ namespace {
|
|||||||
|
|
||||||
struct StateActive {
|
struct StateActive {
|
||||||
std::unique_ptr<QLabel> label;
|
std::unique_ptr<QLabel> label;
|
||||||
QTimer timer;
|
|
||||||
PixmapSetActive* pixmaps = nullptr;
|
PixmapSetActive* pixmaps = nullptr;
|
||||||
bool active = false;
|
bool active = false;
|
||||||
|
|
||||||
void setActive(bool b) {
|
void setActive(bool b) {
|
||||||
active = b;
|
if (!label || b == active)
|
||||||
if (! label) {
|
return;
|
||||||
|
active = b;
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
if (!label)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
label->setPixmap(active ? pixmaps->active : pixmaps->normal);
|
label->setPixmap(active ? pixmaps->active : pixmaps->normal);
|
||||||
timer.start(75);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct StateEmpty {
|
struct StateEmpty {
|
||||||
@@ -111,33 +116,42 @@ namespace {
|
|||||||
bool empty = false;
|
bool empty = false;
|
||||||
|
|
||||||
void setEmpty(bool e) {
|
void setEmpty(bool e) {
|
||||||
empty = e;
|
if (!label || e == empty)
|
||||||
if (! label) {
|
return;
|
||||||
|
empty = e;
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
if (!label)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
label->setPixmap(empty ? pixmaps->empty : pixmaps->normal);
|
label->setPixmap(empty ? pixmaps->empty : pixmaps->normal);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct StateEmptyActive {
|
struct StateEmptyActive {
|
||||||
std::unique_ptr<QLabel> label;
|
std::unique_ptr<QLabel> label;
|
||||||
QTimer timer;
|
|
||||||
PixmapSetEmptyActive* pixmaps = nullptr;
|
PixmapSetEmptyActive* pixmaps = nullptr;
|
||||||
bool empty = false;
|
bool empty = false;
|
||||||
bool active = false;
|
bool active = false;
|
||||||
|
|
||||||
void setActive(bool b) {
|
void setActive(bool b) {
|
||||||
|
if (!label || b == active)
|
||||||
|
return;
|
||||||
|
|
||||||
active = b;
|
active = b;
|
||||||
refresh();
|
refresh();
|
||||||
timer.start(75);
|
|
||||||
}
|
}
|
||||||
void setEmpty(bool b) {
|
void setEmpty(bool b) {
|
||||||
|
if (!label || b == empty)
|
||||||
|
return;
|
||||||
|
|
||||||
empty = b;
|
empty = b;
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
void refresh() {
|
void refresh() {
|
||||||
if (! label) {
|
if (!label)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if (empty) {
|
if (empty) {
|
||||||
label->setPixmap(active ? pixmaps->empty_active : pixmaps->empty);
|
label->setPixmap(active ? pixmaps->empty_active : pixmaps->empty);
|
||||||
} else {
|
} else {
|
||||||
@@ -190,26 +204,20 @@ struct MachineStatus::States {
|
|||||||
cartridge[0].pixmaps = &pixmaps.cartridge;
|
cartridge[0].pixmaps = &pixmaps.cartridge;
|
||||||
cartridge[1].pixmaps = &pixmaps.cartridge;
|
cartridge[1].pixmaps = &pixmaps.cartridge;
|
||||||
cassette.pixmaps = &pixmaps.cassette;
|
cassette.pixmaps = &pixmaps.cassette;
|
||||||
QObject::connect(&cassette.timer, &QTimer::timeout, parent, [&]{ cassette.setActive(false); });
|
|
||||||
for (auto& f : fdd) {
|
for (auto& f : fdd) {
|
||||||
f.pixmaps = &pixmaps.floppy_disabled;
|
f.pixmaps = &pixmaps.floppy_disabled;
|
||||||
QObject::connect(&f.timer, &QTimer::timeout, parent, [&]{ f.setActive(false); });
|
|
||||||
}
|
}
|
||||||
for (auto& c : cdrom) {
|
for (auto& c : cdrom) {
|
||||||
c.pixmaps = &pixmaps.cdrom;
|
c.pixmaps = &pixmaps.cdrom;
|
||||||
QObject::connect(&c.timer, &QTimer::timeout, parent, [&]{ c.setActive(false); });
|
|
||||||
}
|
}
|
||||||
for (auto& z : zip) {
|
for (auto& z : zip) {
|
||||||
z.pixmaps = &pixmaps.zip;
|
z.pixmaps = &pixmaps.zip;
|
||||||
QObject::connect(&z.timer, &QTimer::timeout, parent, [&]{ z.setActive(false); });
|
|
||||||
}
|
}
|
||||||
for (auto& m : mo) {
|
for (auto& m : mo) {
|
||||||
m.pixmaps = &pixmaps.mo;
|
m.pixmaps = &pixmaps.mo;
|
||||||
QObject::connect(&m.timer, &QTimer::timeout, parent, [&]{ m.setActive(false); });
|
|
||||||
}
|
}
|
||||||
for (auto& h : hdds) {
|
for (auto& h : hdds) {
|
||||||
h.pixmaps = &pixmaps.hd;
|
h.pixmaps = &pixmaps.hd;
|
||||||
QObject::connect(&h.timer, &QTimer::timeout, parent, [&]{ h.setActive(false); });
|
|
||||||
}
|
}
|
||||||
net.pixmaps = &pixmaps.net;
|
net.pixmaps = &pixmaps.net;
|
||||||
}
|
}
|
||||||
@@ -227,9 +235,12 @@ struct MachineStatus::States {
|
|||||||
};
|
};
|
||||||
|
|
||||||
MachineStatus::MachineStatus(QObject *parent) :
|
MachineStatus::MachineStatus(QObject *parent) :
|
||||||
QObject(parent)
|
QObject(parent),
|
||||||
|
refreshTimer(new QTimer(this))
|
||||||
{
|
{
|
||||||
d = std::make_unique<MachineStatus::States>(this);
|
d = std::make_unique<MachineStatus::States>(this);
|
||||||
|
connect(refreshTimer, &QTimer::timeout, this, &MachineStatus::refreshIcons);
|
||||||
|
refreshTimer->start(75);
|
||||||
}
|
}
|
||||||
|
|
||||||
MachineStatus::~MachineStatus() = default;
|
MachineStatus::~MachineStatus() = default;
|
||||||
@@ -321,6 +332,38 @@ static int hdd_count(int bus) {
|
|||||||
return(c);
|
return(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MachineStatus::refreshIcons() {
|
||||||
|
for (size_t i = 0; i < FDD_NUM; ++i) {
|
||||||
|
d->fdd[i].setActive(machine_status.fdd[i].active);
|
||||||
|
d->fdd[i].setEmpty(machine_status.fdd[i].empty);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < CDROM_NUM; ++i) {
|
||||||
|
d->cdrom[i].setActive(machine_status.cdrom[i].active);
|
||||||
|
d->cdrom[i].setEmpty(machine_status.cdrom[i].empty);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < ZIP_NUM; i++) {
|
||||||
|
d->zip[i].setActive(machine_status.zip[i].active);
|
||||||
|
d->zip[i].setEmpty(machine_status.zip[i].empty);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < MO_NUM; i++) {
|
||||||
|
d->mo[i].setActive(machine_status.mo[i].active);
|
||||||
|
d->mo[i].setEmpty(machine_status.mo[i].empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
d->cassette.setEmpty(machine_status.cassette.empty);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < HDD_BUS_USB; i++) {
|
||||||
|
d->hdds[i].setActive(machine_status.hdd[i].active);
|
||||||
|
}
|
||||||
|
|
||||||
|
d->net.setActive(machine_status.net.active);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
d->cartridge[i].setEmpty(machine_status.cartridge[i].empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void MachineStatus::refresh(QStatusBar* sbar) {
|
void MachineStatus::refresh(QStatusBar* sbar) {
|
||||||
bool has_mfm = machine_has_flags(machine, MACHINE_MFM) > 0;
|
bool has_mfm = machine_has_flags(machine, MACHINE_MFM) > 0;
|
||||||
bool has_xta = machine_has_flags(machine, MACHINE_XTA) > 0;
|
bool has_xta = machine_has_flags(machine, MACHINE_XTA) > 0;
|
||||||
@@ -358,6 +401,7 @@ void MachineStatus::refresh(QStatusBar* sbar) {
|
|||||||
if (cassette_enable) {
|
if (cassette_enable) {
|
||||||
d->cassette.label = std::make_unique<ClickableLabel>();
|
d->cassette.label = std::make_unique<ClickableLabel>();
|
||||||
d->cassette.setEmpty(QString(cassette_fname).isEmpty());
|
d->cassette.setEmpty(QString(cassette_fname).isEmpty());
|
||||||
|
d->cassette.refresh();
|
||||||
connect((ClickableLabel*)d->cassette.label.get(), &ClickableLabel::clicked, [](QPoint pos) {
|
connect((ClickableLabel*)d->cassette.label.get(), &ClickableLabel::clicked, [](QPoint pos) {
|
||||||
MediaMenu::ptr->cassetteMenu->popup(pos - QPoint(0, MediaMenu::ptr->cassetteMenu->sizeHint().height()));
|
MediaMenu::ptr->cassetteMenu->popup(pos - QPoint(0, MediaMenu::ptr->cassetteMenu->sizeHint().height()));
|
||||||
});
|
});
|
||||||
@@ -373,6 +417,7 @@ void MachineStatus::refresh(QStatusBar* sbar) {
|
|||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
d->cartridge[i].label = std::make_unique<ClickableLabel>();
|
d->cartridge[i].label = std::make_unique<ClickableLabel>();
|
||||||
d->cartridge[i].setEmpty(QString(cart_fns[i]).isEmpty());
|
d->cartridge[i].setEmpty(QString(cart_fns[i]).isEmpty());
|
||||||
|
d->cartridge[i].refresh();
|
||||||
connect((ClickableLabel*)d->cartridge[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
|
connect((ClickableLabel*)d->cartridge[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
|
||||||
MediaMenu::ptr->cartridgeMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->cartridgeMenus[i]->sizeHint().height()));
|
MediaMenu::ptr->cartridgeMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->cartridgeMenus[i]->sizeHint().height()));
|
||||||
});
|
});
|
||||||
@@ -397,6 +442,7 @@ void MachineStatus::refresh(QStatusBar* sbar) {
|
|||||||
d->fdd[i].label = std::make_unique<ClickableLabel>();
|
d->fdd[i].label = std::make_unique<ClickableLabel>();
|
||||||
d->fdd[i].setEmpty(QString(floppyfns[i]).isEmpty());
|
d->fdd[i].setEmpty(QString(floppyfns[i]).isEmpty());
|
||||||
d->fdd[i].setActive(false);
|
d->fdd[i].setActive(false);
|
||||||
|
d->fdd[i].refresh();
|
||||||
connect((ClickableLabel*)d->fdd[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
|
connect((ClickableLabel*)d->fdd[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
|
||||||
MediaMenu::ptr->floppyMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->floppyMenus[i]->sizeHint().height()));
|
MediaMenu::ptr->floppyMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->floppyMenus[i]->sizeHint().height()));
|
||||||
});
|
});
|
||||||
@@ -412,6 +458,7 @@ void MachineStatus::refresh(QStatusBar* sbar) {
|
|||||||
d->cdrom[i].label = std::make_unique<ClickableLabel>();
|
d->cdrom[i].label = std::make_unique<ClickableLabel>();
|
||||||
d->cdrom[i].setEmpty(cdrom[i].host_drive != 200 || QString(cdrom[i].image_path).isEmpty());
|
d->cdrom[i].setEmpty(cdrom[i].host_drive != 200 || QString(cdrom[i].image_path).isEmpty());
|
||||||
d->cdrom[i].setActive(false);
|
d->cdrom[i].setActive(false);
|
||||||
|
d->cdrom[i].refresh();
|
||||||
connect((ClickableLabel*)d->cdrom[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
|
connect((ClickableLabel*)d->cdrom[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
|
||||||
MediaMenu::ptr->cdromMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->cdromMenus[i]->sizeHint().height()));
|
MediaMenu::ptr->cdromMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->cdromMenus[i]->sizeHint().height()));
|
||||||
});
|
});
|
||||||
@@ -427,6 +474,7 @@ void MachineStatus::refresh(QStatusBar* sbar) {
|
|||||||
d->zip[i].label = std::make_unique<ClickableLabel>();
|
d->zip[i].label = std::make_unique<ClickableLabel>();
|
||||||
d->zip[i].setEmpty(QString(zip_drives[i].image_path).isEmpty());
|
d->zip[i].setEmpty(QString(zip_drives[i].image_path).isEmpty());
|
||||||
d->zip[i].setActive(false);
|
d->zip[i].setActive(false);
|
||||||
|
d->zip[i].refresh();
|
||||||
connect((ClickableLabel*)d->zip[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
|
connect((ClickableLabel*)d->zip[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
|
||||||
MediaMenu::ptr->zipMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->zipMenus[i]->sizeHint().height()));
|
MediaMenu::ptr->zipMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->zipMenus[i]->sizeHint().height()));
|
||||||
});
|
});
|
||||||
@@ -442,6 +490,7 @@ void MachineStatus::refresh(QStatusBar* sbar) {
|
|||||||
d->mo[i].label = std::make_unique<ClickableLabel>();
|
d->mo[i].label = std::make_unique<ClickableLabel>();
|
||||||
d->mo[i].setEmpty(QString(mo_drives[i].image_path).isEmpty());
|
d->mo[i].setEmpty(QString(mo_drives[i].image_path).isEmpty());
|
||||||
d->mo[i].setActive(false);
|
d->mo[i].setActive(false);
|
||||||
|
d->mo[i].refresh();
|
||||||
connect((ClickableLabel*)d->mo[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
|
connect((ClickableLabel*)d->mo[i].label.get(), &ClickableLabel::clicked, [i](QPoint pos) {
|
||||||
MediaMenu::ptr->moMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->moMenus[i]->sizeHint().height()));
|
MediaMenu::ptr->moMenus[i]->popup(pos - QPoint(0, MediaMenu::ptr->moMenus[i]->sizeHint().height()));
|
||||||
});
|
});
|
||||||
@@ -457,24 +506,28 @@ void MachineStatus::refresh(QStatusBar* sbar) {
|
|||||||
if ((has_mfm || hdc_name.left(5) == QStringLiteral("st506")) && c_mfm > 0) {
|
if ((has_mfm || hdc_name.left(5) == QStringLiteral("st506")) && c_mfm > 0) {
|
||||||
d->hdds[HDD_BUS_MFM].label = std::make_unique<QLabel>();
|
d->hdds[HDD_BUS_MFM].label = std::make_unique<QLabel>();
|
||||||
d->hdds[HDD_BUS_MFM].setActive(false);
|
d->hdds[HDD_BUS_MFM].setActive(false);
|
||||||
|
d->hdds[HDD_BUS_MFM].refresh();
|
||||||
d->hdds[HDD_BUS_MFM].label->setToolTip(tr("Hard disk (%s)").replace("%s", "MFM/RLL"));
|
d->hdds[HDD_BUS_MFM].label->setToolTip(tr("Hard disk (%s)").replace("%s", "MFM/RLL"));
|
||||||
sbar->addWidget(d->hdds[HDD_BUS_MFM].label.get());
|
sbar->addWidget(d->hdds[HDD_BUS_MFM].label.get());
|
||||||
}
|
}
|
||||||
if ((has_esdi || hdc_name.left(4) == QStringLiteral("esdi")) && c_esdi > 0) {
|
if ((has_esdi || hdc_name.left(4) == QStringLiteral("esdi")) && c_esdi > 0) {
|
||||||
d->hdds[HDD_BUS_ESDI].label = std::make_unique<QLabel>();
|
d->hdds[HDD_BUS_ESDI].label = std::make_unique<QLabel>();
|
||||||
d->hdds[HDD_BUS_ESDI].setActive(false);
|
d->hdds[HDD_BUS_ESDI].setActive(false);
|
||||||
|
d->hdds[HDD_BUS_ESDI].refresh();
|
||||||
d->hdds[HDD_BUS_ESDI].label->setToolTip(tr("Hard disk (%s)").replace("%s", "ESDI"));
|
d->hdds[HDD_BUS_ESDI].label->setToolTip(tr("Hard disk (%s)").replace("%s", "ESDI"));
|
||||||
sbar->addWidget(d->hdds[HDD_BUS_ESDI].label.get());
|
sbar->addWidget(d->hdds[HDD_BUS_ESDI].label.get());
|
||||||
}
|
}
|
||||||
if ((has_xta || hdc_name.left(3) == QStringLiteral("xta")) && c_xta > 0) {
|
if ((has_xta || hdc_name.left(3) == QStringLiteral("xta")) && c_xta > 0) {
|
||||||
d->hdds[HDD_BUS_XTA].label = std::make_unique<QLabel>();
|
d->hdds[HDD_BUS_XTA].label = std::make_unique<QLabel>();
|
||||||
d->hdds[HDD_BUS_XTA].setActive(false);
|
d->hdds[HDD_BUS_XTA].setActive(false);
|
||||||
|
d->hdds[HDD_BUS_XTA].refresh();
|
||||||
d->hdds[HDD_BUS_XTA].label->setToolTip(tr("Hard disk (%s)").replace("%s", "XTA"));
|
d->hdds[HDD_BUS_XTA].label->setToolTip(tr("Hard disk (%s)").replace("%s", "XTA"));
|
||||||
sbar->addWidget(d->hdds[HDD_BUS_XTA].label.get());
|
sbar->addWidget(d->hdds[HDD_BUS_XTA].label.get());
|
||||||
}
|
}
|
||||||
if ((hasIDE() || hdc_name.left(5) == QStringLiteral("xtide") || hdc_name.left(3) == QStringLiteral("ide")) && c_ide > 0) {
|
if ((hasIDE() || hdc_name.left(5) == QStringLiteral("xtide") || hdc_name.left(3) == QStringLiteral("ide")) && c_ide > 0) {
|
||||||
d->hdds[HDD_BUS_IDE].label = std::make_unique<QLabel>();
|
d->hdds[HDD_BUS_IDE].label = std::make_unique<QLabel>();
|
||||||
d->hdds[HDD_BUS_IDE].setActive(false);
|
d->hdds[HDD_BUS_IDE].setActive(false);
|
||||||
|
d->hdds[HDD_BUS_IDE].refresh();
|
||||||
d->hdds[HDD_BUS_IDE].label->setToolTip(tr("Hard disk (%s)").replace("%s", "IDE"));
|
d->hdds[HDD_BUS_IDE].label->setToolTip(tr("Hard disk (%s)").replace("%s", "IDE"));
|
||||||
sbar->addWidget(d->hdds[HDD_BUS_IDE].label.get());
|
sbar->addWidget(d->hdds[HDD_BUS_IDE].label.get());
|
||||||
}
|
}
|
||||||
@@ -482,6 +535,7 @@ void MachineStatus::refresh(QStatusBar* sbar) {
|
|||||||
(scsi_card_current[2] != 0) || (scsi_card_current[3] != 0)) && c_scsi > 0) {
|
(scsi_card_current[2] != 0) || (scsi_card_current[3] != 0)) && c_scsi > 0) {
|
||||||
d->hdds[HDD_BUS_SCSI].label = std::make_unique<QLabel>();
|
d->hdds[HDD_BUS_SCSI].label = std::make_unique<QLabel>();
|
||||||
d->hdds[HDD_BUS_SCSI].setActive(false);
|
d->hdds[HDD_BUS_SCSI].setActive(false);
|
||||||
|
d->hdds[HDD_BUS_SCSI].refresh();
|
||||||
d->hdds[HDD_BUS_SCSI].label->setToolTip(tr("Hard disk (%s)").replace("%s", "SCSI"));
|
d->hdds[HDD_BUS_SCSI].label->setToolTip(tr("Hard disk (%s)").replace("%s", "SCSI"));
|
||||||
sbar->addWidget(d->hdds[HDD_BUS_SCSI].label.get());
|
sbar->addWidget(d->hdds[HDD_BUS_SCSI].label.get());
|
||||||
}
|
}
|
||||||
@@ -489,6 +543,7 @@ void MachineStatus::refresh(QStatusBar* sbar) {
|
|||||||
if (do_net) {
|
if (do_net) {
|
||||||
d->net.label = std::make_unique<QLabel>();
|
d->net.label = std::make_unique<QLabel>();
|
||||||
d->net.setActive(false);
|
d->net.setActive(false);
|
||||||
|
d->net.refresh();
|
||||||
d->net.label->setToolTip(tr("Network"));
|
d->net.label->setToolTip(tr("Network"));
|
||||||
sbar->addWidget(d->net.label.get());
|
sbar->addWidget(d->net.label.get());
|
||||||
}
|
}
|
||||||
@@ -505,72 +560,6 @@ void MachineStatus::refresh(QStatusBar* sbar) {
|
|||||||
sbar->addWidget(d->text.get());
|
sbar->addWidget(d->text.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MachineStatus::setActivity(int tag, bool active) {
|
|
||||||
int category = tag & 0xfffffff0;
|
|
||||||
int item = tag & 0xf;
|
|
||||||
switch (category) {
|
|
||||||
case SB_CASSETTE:
|
|
||||||
break;
|
|
||||||
case SB_CARTRIDGE:
|
|
||||||
break;
|
|
||||||
case SB_FLOPPY:
|
|
||||||
d->fdd[item].setActive(active);
|
|
||||||
break;
|
|
||||||
case SB_CDROM:
|
|
||||||
d->cdrom[item].setActive(active);
|
|
||||||
break;
|
|
||||||
case SB_ZIP:
|
|
||||||
d->zip[item].setActive(active);
|
|
||||||
break;
|
|
||||||
case SB_MO:
|
|
||||||
d->mo[item].setActive(active);
|
|
||||||
break;
|
|
||||||
case SB_HDD:
|
|
||||||
d->hdds[item].setActive(active);
|
|
||||||
break;
|
|
||||||
case SB_NETWORK:
|
|
||||||
d->net.setActive(active);
|
|
||||||
break;
|
|
||||||
case SB_SOUND:
|
|
||||||
break;
|
|
||||||
case SB_TEXT:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MachineStatus::setEmpty(int tag, bool empty) {
|
|
||||||
int category = tag & 0xfffffff0;
|
|
||||||
int item = tag & 0xf;
|
|
||||||
switch (category) {
|
|
||||||
case SB_CASSETTE:
|
|
||||||
d->cassette.setEmpty(empty);
|
|
||||||
break;
|
|
||||||
case SB_CARTRIDGE:
|
|
||||||
d->cartridge[item].setEmpty(empty);
|
|
||||||
break;
|
|
||||||
case SB_FLOPPY:
|
|
||||||
d->fdd[item].setEmpty(empty);
|
|
||||||
break;
|
|
||||||
case SB_CDROM:
|
|
||||||
d->cdrom[item].setEmpty(empty);
|
|
||||||
break;
|
|
||||||
case SB_ZIP:
|
|
||||||
d->zip[item].setEmpty(empty);
|
|
||||||
break;
|
|
||||||
case SB_MO:
|
|
||||||
d->mo[item].setEmpty(empty);
|
|
||||||
break;
|
|
||||||
case SB_HDD:
|
|
||||||
break;
|
|
||||||
case SB_NETWORK:
|
|
||||||
break;
|
|
||||||
case SB_SOUND:
|
|
||||||
break;
|
|
||||||
case SB_TEXT:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MachineStatus::message(const QString &msg) {
|
void MachineStatus::message(const QString &msg) {
|
||||||
d->text->setText(msg);
|
d->text->setText(msg);
|
||||||
}
|
}
|
||||||
|
@@ -70,14 +70,14 @@ public:
|
|||||||
QString getMessage();
|
QString getMessage();
|
||||||
public slots:
|
public slots:
|
||||||
void refresh(QStatusBar* sbar);
|
void refresh(QStatusBar* sbar);
|
||||||
void setActivity(int tag, bool active);
|
|
||||||
void setEmpty(int tag, bool active);
|
|
||||||
void message(const QString& msg);
|
void message(const QString& msg);
|
||||||
void updateTip(int tag);
|
void updateTip(int tag);
|
||||||
|
void refreshIcons();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct States;
|
struct States;
|
||||||
std::unique_ptr<States> d;
|
std::unique_ptr<States> d;
|
||||||
|
QTimer *refreshTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QT_MACHINESTATUS_HPP
|
#endif // QT_MACHINESTATUS_HPP
|
||||||
|
@@ -268,8 +268,6 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
});
|
});
|
||||||
connect(this, &MainWindow::updateStatusBarPanes, this, &MainWindow::refreshMediaMenu);
|
connect(this, &MainWindow::updateStatusBarPanes, this, &MainWindow::refreshMediaMenu);
|
||||||
connect(this, &MainWindow::updateStatusBarTip, status.get(), &MachineStatus::updateTip);
|
connect(this, &MainWindow::updateStatusBarTip, status.get(), &MachineStatus::updateTip);
|
||||||
connect(this, &MainWindow::updateStatusBarActivity, status.get(), &MachineStatus::setActivity);
|
|
||||||
connect(this, &MainWindow::updateStatusBarEmpty, status.get(), &MachineStatus::setEmpty);
|
|
||||||
connect(this, &MainWindow::statusBarMessage, status.get(), &MachineStatus::message, Qt::QueuedConnection);
|
connect(this, &MainWindow::statusBarMessage, status.get(), &MachineStatus::message, Qt::QueuedConnection);
|
||||||
|
|
||||||
ui->actionKeyboard_requires_capture->setChecked(kbd_req_capture);
|
ui->actionKeyboard_requires_capture->setChecked(kbd_req_capture);
|
||||||
|
@@ -132,8 +132,6 @@ void ProgSettings::accept()
|
|||||||
main_window->refreshMediaMenu();
|
main_window->refreshMediaMenu();
|
||||||
main_window->status->message(msg);
|
main_window->status->message(msg);
|
||||||
connect(main_window, &MainWindow::updateStatusBarTip, main_window->status.get(), &MachineStatus::updateTip);
|
connect(main_window, &MainWindow::updateStatusBarTip, main_window->status.get(), &MachineStatus::updateTip);
|
||||||
connect(main_window, &MainWindow::updateStatusBarActivity, main_window->status.get(), &MachineStatus::setActivity);
|
|
||||||
connect(main_window, &MainWindow::updateStatusBarEmpty, main_window->status.get(), &MachineStatus::setEmpty);
|
|
||||||
connect(main_window, &MainWindow::statusBarMessage, main_window->status.get(), &MachineStatus::message, Qt::QueuedConnection);
|
connect(main_window, &MainWindow::statusBarMessage, main_window->status.get(), &MachineStatus::message, Qt::QueuedConnection);
|
||||||
mouse_sensitivity = mouseSensitivity;
|
mouse_sensitivity = mouseSensitivity;
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#include <QStatusBar>
|
#include <QStatusBar>
|
||||||
|
|
||||||
#include "qt_mainwindow.hpp"
|
#include "qt_mainwindow.hpp"
|
||||||
|
#include "qt_machinestatus.hpp"
|
||||||
|
|
||||||
MainWindow* main_window = nullptr;
|
MainWindow* main_window = nullptr;
|
||||||
|
|
||||||
@@ -36,6 +37,20 @@ extern "C" {
|
|||||||
#include <86box/plat.h>
|
#include <86box/plat.h>
|
||||||
#include <86box/ui.h>
|
#include <86box/ui.h>
|
||||||
#include <86box/mouse.h>
|
#include <86box/mouse.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/device.h>
|
||||||
|
#include <86box/fdd.h>
|
||||||
|
#include <86box/hdc.h>
|
||||||
|
#include <86box/scsi.h>
|
||||||
|
#include <86box/scsi_device.h>
|
||||||
|
#include <86box/cartridge.h>
|
||||||
|
#include <86box/cassette.h>
|
||||||
|
#include <86box/cdrom.h>
|
||||||
|
#include <86box/zip.h>
|
||||||
|
#include <86box/mo.h>
|
||||||
|
#include <86box/hdd.h>
|
||||||
|
#include <86box/machine_status.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
plat_delay_ms(uint32_t count)
|
plat_delay_ms(uint32_t count)
|
||||||
@@ -174,16 +189,70 @@ void ui_sb_set_ready(int ready) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
ui_sb_update_icon_state(int tag, int state) {
|
ui_sb_update_icon_state(int tag, int state) {
|
||||||
if (main_window == nullptr) {
|
int category = tag & 0xfffffff0;
|
||||||
return;
|
int item = tag & 0xf;
|
||||||
|
switch (category) {
|
||||||
|
case SB_CASSETTE:
|
||||||
|
machine_status.cassette.empty = state > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_CARTRIDGE:
|
||||||
|
machine_status.cartridge[item].empty = state > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_FLOPPY:
|
||||||
|
machine_status.fdd[item].empty = state > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_CDROM:
|
||||||
|
machine_status.cdrom[item].empty = state > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_ZIP:
|
||||||
|
machine_status.zip[item].empty = state > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_MO:
|
||||||
|
machine_status.mo[item].empty = state > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_HDD:
|
||||||
|
break;
|
||||||
|
case SB_NETWORK:
|
||||||
|
break;
|
||||||
|
case SB_SOUND:
|
||||||
|
break;
|
||||||
|
case SB_TEXT:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
main_window->updateStatusBarEmpty(tag, state > 0 ? true : false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ui_sb_update_icon(int tag, int active) {
|
ui_sb_update_icon(int tag, int active) {
|
||||||
if (!update_icons) return;
|
int category = tag & 0xfffffff0;
|
||||||
main_window->updateStatusBarActivity(tag, active > 0 ? true : false);
|
int item = tag & 0xf;
|
||||||
|
switch (category) {
|
||||||
|
case SB_CASSETTE:
|
||||||
|
break;
|
||||||
|
case SB_CARTRIDGE:
|
||||||
|
break;
|
||||||
|
case SB_FLOPPY:
|
||||||
|
machine_status.fdd[item].active = active > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_CDROM:
|
||||||
|
machine_status.cdrom[item].active = active > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_ZIP:
|
||||||
|
machine_status.zip[item].active = active > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_MO:
|
||||||
|
machine_status.mo[item].active = active > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_HDD:
|
||||||
|
machine_status.hdd[item].active = active > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_NETWORK:
|
||||||
|
machine_status.net.active = active > 0 ? true : false;
|
||||||
|
break;
|
||||||
|
case SB_SOUND:
|
||||||
|
break;
|
||||||
|
case SB_TEXT:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
903
src/upi42.c
Normal file
903
src/upi42.c
Normal file
@@ -0,0 +1,903 @@
|
|||||||
|
/*
|
||||||
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||||
|
* running old operating systems and software designed for IBM
|
||||||
|
* PC systems and compatibles from 1981 through fairly recent
|
||||||
|
* system designs based on the PCI bus.
|
||||||
|
*
|
||||||
|
* This file is part of the 86Box distribution.
|
||||||
|
*
|
||||||
|
* Intel UPI-42/MCS-48 microcontroller emulation.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Authors: RichardG, <richardg867@gmail.com>
|
||||||
|
*
|
||||||
|
* Copyright 2022 RichardG.
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#define fatal printf
|
||||||
|
#define pclog printf
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UPI42_8042 = 0,
|
||||||
|
UPI42_80C42
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _upi42_ {
|
||||||
|
int (*ops[256])(struct _upi42_ *upi42, uint32_t fetchdat);
|
||||||
|
uint8_t ram[256], rom[4096], /* memory */
|
||||||
|
ports[7], /* I/O ports */
|
||||||
|
dbb_in, dbb_out; /* UPI-42 data buffer */
|
||||||
|
|
||||||
|
uint8_t rammask,
|
||||||
|
a, /* accumulator */
|
||||||
|
t, /* timer counter */
|
||||||
|
psw, /* program status word */
|
||||||
|
sts; /* UPI-42 status */
|
||||||
|
|
||||||
|
uint16_t pc; /* program counter */
|
||||||
|
|
||||||
|
unsigned int prescaler : 5, tf : 1, tcnti : 1, run_timer : 1, run_counter : 1, skip_timer_inc : 1, /* timer/counter */
|
||||||
|
i : 1, i_asserted : 1, tcnti_asserted : 1, irq_mask : 1, /* interrupts */
|
||||||
|
dbf : 1, /* ROM bank */
|
||||||
|
t0 : 1, t1 : 1, /* T0/T1 signals */
|
||||||
|
flags : 1, /* buffer flag pins */
|
||||||
|
suspend : 1; /* 80C42 suspend flag */
|
||||||
|
|
||||||
|
int cycs; /* cycle counter */
|
||||||
|
} upi42_t;
|
||||||
|
|
||||||
|
#define UPI42_REG_READ(upi42, r) ((upi42->psw & 0x10) ? (upi42->ram[24 + ((r) &7)]) : (upi42->ram[(r) &7]))
|
||||||
|
#define UPI42_REG_WRITE(upi42, r, op) ((upi42->psw & 0x10) ? (upi42->ram[24 + ((r) &7)] op) : (upi42->ram[(r) &7] op))
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
upi42_mirror_f0(upi42_t *upi42)
|
||||||
|
{
|
||||||
|
/* Update status register F0 flag to match PSW F0 flag. */
|
||||||
|
upi42->sts = ((upi42->psw & 0x20) >> 3) | (upi42->sts & ~0x04);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_A_Rr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = UPI42_REG_READ(upi42, fetchdat);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_Rr_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
UPI42_REG_WRITE(upi42, fetchdat, = upi42->a);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_A_indRr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_indRr_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask] = upi42->a;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_Rr_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
UPI42_REG_WRITE(upi42, fetchdat, = fetchdat >> 8);
|
||||||
|
upi42->cycs--;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_indRr_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask] = fetchdat >> 8;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_A_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = fetchdat >> 8;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_A_PSW(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = upi42->psw;
|
||||||
|
upi42_mirror_f0(upi42);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_PSW_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->psw = upi42->a;
|
||||||
|
upi42_mirror_f0(upi42);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_A_T(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = upi42->t;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_T_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->t = upi42->a;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOV_STS_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->sts = (upi42->a & 0xf0) | (upi42->sts & 0x0f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOVP_A_indA(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = upi42->rom[(upi42->pc & 0xff00) | upi42->a];
|
||||||
|
upi42->cycs--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOVP3_A_indA(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = upi42->rom[0x300 | upi42->a];
|
||||||
|
upi42->cycs--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_XCH_A_Rr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
uint8_t temp = upi42->a;
|
||||||
|
upi42->a = UPI42_REG_READ(upi42, fetchdat);
|
||||||
|
UPI42_REG_WRITE(upi42, fetchdat, = temp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_XCH_A_indRr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
uint8_t temp = upi42->a, addr = upi42->ram[fetchdat & 1] & upi42->rammask;
|
||||||
|
upi42->a = upi42->ram[addr];
|
||||||
|
upi42->ram[addr] = temp;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_XCHD_A_indRr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
uint8_t temp = upi42->a, addr = upi42->ram[fetchdat & 1] & upi42->rammask;
|
||||||
|
upi42->a = (upi42->a & 0xf0) | (upi42->ram[addr] & 0x0f);
|
||||||
|
upi42->ram[addr] = (upi42->ram[addr] & 0xf0) | (temp & 0x0f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_SWAP_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = (upi42->a << 4) | (upi42->a >> 4);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_IN_A_Pp(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = upi42->ports[fetchdat & 3];
|
||||||
|
upi42->cycs--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_IN_A_DBB(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = upi42->dbb_in;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_OUTL_Pp_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->ports[fetchdat & 3] = upi42->a;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_OUT_DBB_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->dbb_out = upi42->a;
|
||||||
|
upi42->sts |= 0x01;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOVD_A_Pp(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = upi42->ports[4 | (fetchdat & 3)] & 0x0f;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_MOVD_Pp_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->ports[4 | (fetchdat & 3)] = upi42->a & 0x0f;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ANL_A_Rr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a &= UPI42_REG_READ(upi42, fetchdat);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ORL_A_Rr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a |= UPI42_REG_READ(upi42, fetchdat);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_XRL_A_Rr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a ^= UPI42_REG_READ(upi42, fetchdat);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ANL_A_indRr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a &= upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ORL_A_indRr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a |= upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_XRL_A_indRr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a ^= upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ANL_A_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a &= fetchdat >> 8;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ORL_A_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a |= fetchdat >> 8;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_XRL_A_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a ^= fetchdat >> 8;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ANL_Pp_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->ports[fetchdat & 3] &= fetchdat >> 8;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ORL_Pp_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->ports[fetchdat & 3] |= fetchdat >> 8;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ANLD_Pp_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->ports[4 | (fetchdat & 3)] &= upi42->a;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ORLD_Pp_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->ports[4 | (fetchdat & 3)] |= upi42->a;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_RR_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = (upi42->a << 7) | (upi42->a >> 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_RL_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = (upi42->a >> 7) | (upi42->a << 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_RRC_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
uint8_t temp = upi42->a;
|
||||||
|
upi42->a = (upi42->psw & 0x80) | (temp >> 1);
|
||||||
|
upi42->psw = (temp << 7) | (upi42->psw & ~0x80);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_RLC_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
uint8_t temp = upi42->a;
|
||||||
|
upi42->a = (temp << 1) | (upi42->psw >> 7);
|
||||||
|
upi42->psw = (temp & 0x80) | (upi42->psw & ~0x80);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_INC_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_INC_Rr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
UPI42_REG_WRITE(upi42, fetchdat, ++);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_INC_indRr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->ram[upi42->ram[fetchdat & 1] & upi42->rammask]++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_DEC_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_DEC_Rr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
UPI42_REG_WRITE(upi42, fetchdat, --);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_DJNZ_Rr_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
UPI42_REG_WRITE(upi42, fetchdat, --);
|
||||||
|
if (UPI42_REG_READ(upi42, fetchdat)) {
|
||||||
|
upi42->pc = (upi42->pc & 0xff00) | ((fetchdat >> 8) & 0xff);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ADD_A_Rr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
int res = upi42->a + UPI42_REG_READ(upi42, fetchdat);
|
||||||
|
upi42->a = res;
|
||||||
|
upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ADDC_A_Rr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
int res = upi42->a + (upi42->psw >> 7) + UPI42_REG_READ(upi42, fetchdat);
|
||||||
|
upi42->a = res;
|
||||||
|
upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ADD_A_indRr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
int res = upi42->a + upi42->ram[UPI42_REG_READ(upi42, fetchdat) & upi42->rammask];
|
||||||
|
upi42->a = res;
|
||||||
|
upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ADDC_A_indRr(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
int res = upi42->a + (upi42->psw >> 7) + upi42->ram[UPI42_REG_READ(upi42, fetchdat) & upi42->rammask];
|
||||||
|
upi42->a = res;
|
||||||
|
upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ADD_A_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
int res = upi42->a + (fetchdat >> 8);
|
||||||
|
upi42->a = res;
|
||||||
|
upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80);
|
||||||
|
upi42->cycs--;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_ADDC_A_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
int res = upi42->a + (upi42->psw >> 7) + (fetchdat >> 8);
|
||||||
|
upi42->a = res;
|
||||||
|
upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80);
|
||||||
|
upi42->cycs--;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_CLR_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_CPL_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->a = ~upi42->a;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_DA_A(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
if (((upi42->a & 0x0f) > 9) || (upi42->psw & 0x40))
|
||||||
|
upi42->a += 6;
|
||||||
|
if (((upi42->a >> 4) > 9) || (upi42->psw & 0x80)) {
|
||||||
|
int res = upi42->a + (6 << 4);
|
||||||
|
upi42->a = res;
|
||||||
|
upi42->psw = ((res >> 1) & 0x80) | (upi42->psw & ~0x80);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_CLR_C(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->psw &= ~0x80;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_CPL_C(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->psw ^= 0x80;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_CLR_F0(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->psw &= ~0x20;
|
||||||
|
upi42_mirror_f0(upi42);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_CPL_F0(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->psw ^= 0x20;
|
||||||
|
upi42_mirror_f0(upi42);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_CLR_F1(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->sts &= ~0x08;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_CPL_F1(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->sts ^= 0x08;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_EN_I(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->i = 1;
|
||||||
|
upi42->skip_timer_inc = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_DIS_I(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->i = 0;
|
||||||
|
upi42->skip_timer_inc = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_EN_TCNTI(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->tcnti = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_DIS_TCNTI(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->tcnti = upi42->tcnti_asserted = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_STRT_T(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->run_timer = 1;
|
||||||
|
upi42->prescaler = 0;
|
||||||
|
upi42->skip_timer_inc = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_STRT_CNT(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->run_counter = 1;
|
||||||
|
upi42->skip_timer_inc = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_STOP_TCNT(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->run_timer = upi42->run_counter = 0;
|
||||||
|
upi42->skip_timer_inc = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_SEL_PMB0(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->dbf = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_SEL_PMB1(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->dbf = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_SEL_RB0(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->psw &= ~0x10;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_SEL_RB1(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->psw |= 0x10;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_NOP(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_CALL_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
/* Push new frame onto stack. */
|
||||||
|
uint8_t sp = (upi42->psw & 0x07) << 1;
|
||||||
|
upi42->ram[8 + sp++] = upi42->pc; /* stack frame format is undocumented! */
|
||||||
|
upi42->ram[8 + sp++] = (upi42->psw & 0xf0) | ((upi42->pc >> 8) & 0x07);
|
||||||
|
upi42->psw = (upi42->psw & 0xf8) | (sp >> 1);
|
||||||
|
|
||||||
|
/* Load new program counter. */
|
||||||
|
upi42->pc = (upi42->dbf << 11) | ((fetchdat << 3) & 0x0700) | ((fetchdat >> 8) & 0x00ff);
|
||||||
|
|
||||||
|
/* Don't decrease cycle counter if this is an interrupt call. */
|
||||||
|
if (fetchdat & 0xff)
|
||||||
|
upi42->cycs--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_RET(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
/* Pop frame off the stack. */
|
||||||
|
uint8_t sp = (upi42->psw & 0x07) << 1;
|
||||||
|
uint8_t frame1 = upi42->ram[8 + --sp];
|
||||||
|
uint8_t frame0 = upi42->ram[8 + --sp];
|
||||||
|
upi42->psw = (upi42->psw & 0xf8) | (sp >> 1);
|
||||||
|
|
||||||
|
/* Load new program counter. */
|
||||||
|
upi42->pc = ((frame1 & 0x0f) << 8) | frame0;
|
||||||
|
|
||||||
|
/* Load new Program Status Word and unmask interrupts if this is RETR. */
|
||||||
|
if (fetchdat & 0x10) {
|
||||||
|
upi42->psw = (frame1 & 0xf0) | (upi42->psw & 0x0f);
|
||||||
|
upi42_mirror_f0(upi42);
|
||||||
|
|
||||||
|
upi42->irq_mask = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
upi42->cycs--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_JMP_imm(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->pc = (upi42->dbf << 11) | ((fetchdat << 3) & 0x0700) | ((fetchdat >> 8) & 0x00ff);
|
||||||
|
upi42->cycs--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_JMPP_indA(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
upi42->pc = (upi42->pc & 0xff00) | upi42->a;
|
||||||
|
upi42->cycs--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UPI42_COND_JMP_IMM(insn, cond, post) \
|
||||||
|
static int \
|
||||||
|
upi42_op_##insn##_imm(upi42_t *upi42, uint32_t fetchdat) \
|
||||||
|
{ \
|
||||||
|
if (cond) \
|
||||||
|
upi42->pc = (upi42->pc & 0xff00) | ((fetchdat >> 8) & 0x00ff); \
|
||||||
|
post \
|
||||||
|
upi42->cycs--; \
|
||||||
|
return 2 * !(cond); \
|
||||||
|
}
|
||||||
|
UPI42_COND_JMP_IMM(JC, upi42->psw & 0x80, ;)
|
||||||
|
UPI42_COND_JMP_IMM(JNC, !(upi42->psw & 0x80), ;)
|
||||||
|
UPI42_COND_JMP_IMM(JZ, !upi42->a, ;)
|
||||||
|
UPI42_COND_JMP_IMM(JNZ, upi42->a, ;)
|
||||||
|
UPI42_COND_JMP_IMM(JT0, upi42->t0, ;)
|
||||||
|
UPI42_COND_JMP_IMM(JNT0, !upi42->t0, ;)
|
||||||
|
UPI42_COND_JMP_IMM(JT1, upi42->t1, ;)
|
||||||
|
UPI42_COND_JMP_IMM(JNT1, !upi42->t1, ;)
|
||||||
|
UPI42_COND_JMP_IMM(JF0, upi42->psw & 0x20, ;)
|
||||||
|
UPI42_COND_JMP_IMM(JF1, upi42->sts & 0x08, ;)
|
||||||
|
UPI42_COND_JMP_IMM(JTF, !upi42->tf, upi42->tf = 0;)
|
||||||
|
UPI42_COND_JMP_IMM(JBb, upi42->a &(1 << ((fetchdat >> 5) & 7)), ;)
|
||||||
|
UPI42_COND_JMP_IMM(JNIBF, !(upi42->sts & 0x02), ;)
|
||||||
|
UPI42_COND_JMP_IMM(JOBF, upi42->sts & 0x01, ;)
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_EN_A20(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
/* Enable fast A20 until reset. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_EN_DMA(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_EN_FLAGS(upi42_t *upi42, uint32_t fetchdat)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
upi42_op_SUSPEND(upi42_t *upi42, uint32_t fetchdatr)
|
||||||
|
{
|
||||||
|
/* Inhibit execution until reset. */
|
||||||
|
upi42->suspend = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
upi42_exec(void *priv)
|
||||||
|
{
|
||||||
|
upi42_t *upi42 = (upi42_t *) priv;
|
||||||
|
|
||||||
|
/* Skip interrupt handling and code execution if we're suspended or in a multi-cycle instruction. */
|
||||||
|
if (upi42->suspend || ++upi42->cycs < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Trigger interrupt if requested. */
|
||||||
|
if (upi42->irq_mask) {
|
||||||
|
/* Masked, we're currently in an ISR. */
|
||||||
|
} else if (upi42->i_asserted) {
|
||||||
|
/* External interrupt. Higher priority than the timer interrupt. */
|
||||||
|
upi42->irq_mask = 1;
|
||||||
|
upi42->i_asserted = 0;
|
||||||
|
upi42_op_CALL_imm(upi42, 3 << 8);
|
||||||
|
return;
|
||||||
|
} else if (upi42->tcnti_asserted) {
|
||||||
|
/* Timer interrupt. */
|
||||||
|
upi42->irq_mask = 1;
|
||||||
|
upi42->tcnti_asserted = 0;
|
||||||
|
upi42_op_CALL_imm(upi42, 7 << 8);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch instruction. */
|
||||||
|
uint32_t fetchdat = *((uint32_t *) &upi42->rom[upi42->pc]);
|
||||||
|
pclog("%04X @ %04X R0=%02X", fetchdat & 0xffff, upi42->pc, upi42->ram[0]);
|
||||||
|
|
||||||
|
/* Decode instruction. */
|
||||||
|
uint8_t insn = fetchdat & 0xff;
|
||||||
|
if (upi42->ops[insn]) {
|
||||||
|
/* Execute instruction and increment program counter. */
|
||||||
|
upi42->pc += upi42->ops[insn](upi42, fetchdat);
|
||||||
|
|
||||||
|
/* Decrement cycle counter. Multi-cycle instructions also decrement within their code. */
|
||||||
|
upi42->cycs--;
|
||||||
|
} else {
|
||||||
|
fatal("UPI42: Unknown opcode %02X (%08X)\n", insn, fetchdat);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some instructions don't increment the timer. */
|
||||||
|
if (upi42->skip_timer_inc) {
|
||||||
|
upi42->skip_timer_inc = 0;
|
||||||
|
} else {
|
||||||
|
/* Increment counter once the prescaler overflows,
|
||||||
|
and set timer flag once the main value overflows. */
|
||||||
|
if ((++upi42->prescaler == 0) && (++upi42->t == 0)) {
|
||||||
|
upi42->tf = 1;
|
||||||
|
|
||||||
|
/* Fire counter interrupt if enabled. */
|
||||||
|
if (upi42->tcnti)
|
||||||
|
upi42->tcnti_asserted = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int (*ops_80c42[256])(upi42_t *upi42, uint32_t fetchdat) = {
|
||||||
|
// clang-format off
|
||||||
|
/* 0 / 8 */ /* 1 / 9 */ /* 2 / a */ /* 3 / b */ /* 4 / c */ /* 5 / d */ /* 6 / e */ /* 7 / f */
|
||||||
|
/* 00 */ upi42_op_NOP, NULL, upi42_op_OUT_DBB_A, upi42_op_ADD_A_imm, upi42_op_JMP_imm, upi42_op_EN_I, NULL, upi42_op_DEC_A,
|
||||||
|
/* 08 */ upi42_op_IN_A_Pp, upi42_op_IN_A_Pp, upi42_op_IN_A_Pp, NULL, upi42_op_MOVD_A_Pp, upi42_op_MOVD_A_Pp, upi42_op_MOVD_A_Pp, upi42_op_MOVD_A_Pp,
|
||||||
|
/* 10 */ upi42_op_INC_indRr, upi42_op_INC_indRr, upi42_op_JBb_imm, upi42_op_ADDC_A_imm, upi42_op_CALL_imm, upi42_op_DIS_I, upi42_op_JTF_imm, upi42_op_INC_A,
|
||||||
|
/* 18 */ upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr, upi42_op_INC_Rr,
|
||||||
|
/* 20 */ upi42_op_XCH_A_indRr, upi42_op_XCH_A_indRr, upi42_op_IN_A_DBB, upi42_op_MOV_A_imm, upi42_op_JMP_imm, upi42_op_EN_TCNTI, upi42_op_JNT0_imm, upi42_op_CLR_A,
|
||||||
|
/* 28 */ upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr, upi42_op_XCH_A_Rr,
|
||||||
|
/* 30 */ upi42_op_XCHD_A_indRr, upi42_op_XCHD_A_indRr, upi42_op_JBb_imm, upi42_op_EN_A20, upi42_op_CALL_imm, upi42_op_DIS_TCNTI, upi42_op_JT0_imm, upi42_op_CPL_A,
|
||||||
|
/* 38 */ upi42_op_OUTL_Pp_A, upi42_op_OUTL_Pp_A, upi42_op_OUTL_Pp_A, upi42_op_OUTL_Pp_A, upi42_op_MOVD_Pp_A, upi42_op_MOVD_Pp_A, upi42_op_MOVD_Pp_A, upi42_op_MOVD_Pp_A,
|
||||||
|
/* 40 */ upi42_op_ORL_A_indRr, upi42_op_ORL_A_indRr, upi42_op_MOV_A_T, upi42_op_ORL_A_imm, upi42_op_JMP_imm, upi42_op_STRT_CNT, upi42_op_JNT1_imm, upi42_op_SWAP_A,
|
||||||
|
/* 48 */ upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr, upi42_op_ORL_A_Rr,
|
||||||
|
/* 50 */ upi42_op_ANL_A_indRr, upi42_op_ANL_A_indRr, upi42_op_JBb_imm, upi42_op_ANL_A_imm, upi42_op_CALL_imm, upi42_op_STRT_T, upi42_op_JT1_imm, upi42_op_DA_A,
|
||||||
|
/* 58 */ upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr, upi42_op_ANL_A_Rr,
|
||||||
|
/* 60 */ upi42_op_ADD_A_indRr, upi42_op_ADD_A_indRr, upi42_op_MOV_T_A, NULL, upi42_op_JMP_imm, upi42_op_STOP_TCNT, NULL, upi42_op_RRC_A,
|
||||||
|
/* 68 */ upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr, upi42_op_ADD_A_Rr,
|
||||||
|
/* 70 */ upi42_op_ADDC_A_indRr, upi42_op_ADDC_A_indRr, upi42_op_JBb_imm, NULL, upi42_op_CALL_imm, NULL, upi42_op_JF1_imm, upi42_op_RR_A,
|
||||||
|
/* 78 */ upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr, upi42_op_ADDC_A_Rr,
|
||||||
|
/* 80 */ NULL, NULL, upi42_op_SUSPEND, upi42_op_RET, upi42_op_JMP_imm, upi42_op_CLR_F0, upi42_op_JOBF_imm, NULL,
|
||||||
|
/* 88 */ upi42_op_ORL_Pp_imm, upi42_op_ORL_Pp_imm, upi42_op_ORL_Pp_imm, upi42_op_ORL_Pp_imm, upi42_op_ORLD_Pp_A, upi42_op_ORLD_Pp_A, upi42_op_ORLD_Pp_A, upi42_op_ORLD_Pp_A,
|
||||||
|
/* 90 */ upi42_op_MOV_STS_A, NULL, upi42_op_JBb_imm, upi42_op_RET, upi42_op_CALL_imm, upi42_op_CPL_F0, upi42_op_JNZ_imm, upi42_op_CLR_C,
|
||||||
|
/* 98 */ upi42_op_ANL_Pp_imm, upi42_op_ANL_Pp_imm, upi42_op_ANL_Pp_imm, upi42_op_ANL_Pp_imm, upi42_op_ANLD_Pp_A, upi42_op_ANLD_Pp_A, upi42_op_ANLD_Pp_A, upi42_op_ANLD_Pp_A,
|
||||||
|
/* a0 */ upi42_op_MOV_indRr_A, upi42_op_MOV_indRr_A, NULL, upi42_op_MOVP_A_indA, upi42_op_JMP_imm, upi42_op_CLR_F1, NULL, upi42_op_CPL_C,
|
||||||
|
/* a8 */ upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A, upi42_op_MOV_Rr_A,
|
||||||
|
/* b0 */ upi42_op_MOV_indRr_imm,upi42_op_MOV_indRr_imm,upi42_op_JBb_imm, upi42_op_JMPP_indA, upi42_op_CALL_imm, upi42_op_CPL_F1, upi42_op_JF0_imm, NULL,
|
||||||
|
/* b8 */ upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm, upi42_op_MOV_Rr_imm,
|
||||||
|
/* c0 */ NULL, NULL, NULL, NULL, upi42_op_JMP_imm, NULL, upi42_op_JZ_imm, upi42_op_MOV_A_PSW,
|
||||||
|
/* c8 */ upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr, upi42_op_DEC_Rr,
|
||||||
|
/* d0 */ upi42_op_XRL_A_indRr, upi42_op_XRL_A_indRr, upi42_op_JBb_imm, upi42_op_XRL_A_imm, upi42_op_CALL_imm, NULL, upi42_op_JNIBF_imm, upi42_op_MOV_PSW_A,
|
||||||
|
/* d8 */ upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr, upi42_op_XRL_A_Rr,
|
||||||
|
/* e0 */ NULL, NULL, upi42_op_SUSPEND, upi42_op_MOVP3_A_indA, upi42_op_JMP_imm, upi42_op_EN_DMA, upi42_op_JNC_imm, upi42_op_RL_A,
|
||||||
|
/* e8 */ upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm, upi42_op_DJNZ_Rr_imm,
|
||||||
|
/* f0 */ upi42_op_MOV_A_indRr, upi42_op_MOV_A_indRr, upi42_op_JBb_imm, NULL, upi42_op_CALL_imm, upi42_op_EN_FLAGS, upi42_op_JC_imm, upi42_op_RLC_A,
|
||||||
|
/* f8 */ upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr, upi42_op_MOV_A_Rr
|
||||||
|
// clang-format on
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
upi42_reset(upi42_t *upi42)
|
||||||
|
{
|
||||||
|
upi42->pc = 0; /* program counter */
|
||||||
|
upi42->psw = 0; /* stack pointer, register bank and F0 */
|
||||||
|
upi42->dbf = 0; /* memory bank */
|
||||||
|
upi42->i = upi42->tcnti = 0; /* both interrupts */
|
||||||
|
upi42->tf = 0; /* timer flag */
|
||||||
|
upi42->sts = 0; /* F1 */
|
||||||
|
upi42->suspend = 0; /* 80C42 suspend flag */
|
||||||
|
}
|
||||||
|
|
||||||
|
static upi42_t *
|
||||||
|
upi42_init(int type)
|
||||||
|
{
|
||||||
|
/* Allocate state structure. */
|
||||||
|
upi42_t *upi42 = (upi42_t *) malloc(sizeof(upi42_t));
|
||||||
|
memset(upi42, 0, sizeof(upi42_t));
|
||||||
|
|
||||||
|
/* Build instruction table. */
|
||||||
|
memcpy(upi42->ops, ops_80c42, sizeof(ops_80c42));
|
||||||
|
if (type < UPI42_80C42) {
|
||||||
|
/* Remove 80C42-only instructions. */
|
||||||
|
upi42->ops[0x33] = NULL; /* EN A20 */
|
||||||
|
upi42->ops[0x63] = NULL; /* SEL PMB0 */
|
||||||
|
upi42->ops[0x73] = NULL; /* SEL PMB1 */
|
||||||
|
upi42->ops[0x42] = NULL; /* SUSPEND */
|
||||||
|
upi42->ops[0xe2] = NULL; /* SUSPEND */
|
||||||
|
}
|
||||||
|
|
||||||
|
return upi42;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
upi42_t *upi42 = upi42_init(UPI42_8042);
|
||||||
|
|
||||||
|
/* Load ROM. */
|
||||||
|
FILE *f = fopen("1503033.bin", "rb");
|
||||||
|
fread(upi42->rom, 1, sizeof(upi42->rom), f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
/* Start execution. */
|
||||||
|
char buf[256];
|
||||||
|
while (1) {
|
||||||
|
upi42->sts |= 0x02;
|
||||||
|
upi42->sts |= 0x08;
|
||||||
|
upi42->dbb_in = 0xaa;
|
||||||
|
upi42->cycs = 0;
|
||||||
|
|
||||||
|
upi42_exec(upi42);
|
||||||
|
fgets(buf, 256, stdin);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user