Compare commits
3 commits
831a115881
...
d44474c24e
| Author | SHA1 | Date | |
|---|---|---|---|
| d44474c24e | |||
| d86ebf1bb8 | |||
| d7d30c5608 |
6 changed files with 114 additions and 87 deletions
|
|
@ -35,6 +35,8 @@ void scc_write(unsigned int address, uint8_t data);
|
|||
uint8_t scc_read(unsigned int address);
|
||||
/* Set a new state for the DCD pins: */
|
||||
void scc_set_dcd(int a, int b);
|
||||
/* check if scc master interrupt is enabled */
|
||||
int scc_get_mie();
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ int umac_loop(void);
|
|||
void umac_reset(void);
|
||||
void umac_opt_disassemble(int enable);
|
||||
void umac_mouse(int deltax, int deltay, int button);
|
||||
void umac_absmouse(int x, int y, int button);
|
||||
void umac_kbd_event(uint8_t scancode, int down);
|
||||
|
||||
static inline void umac_vsync_event(void)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "m68k.h"
|
||||
#include "machw.h"
|
||||
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DDBG(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
|
|
|
|||
128
src/main.c
128
src/main.c
|
|
@ -82,6 +82,8 @@ static int disassemble = 0;
|
|||
|
||||
static void update_overlay_layout(void);
|
||||
|
||||
extern int pv_uart_read();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int m68k_dump_regs(char *buf, int len)
|
||||
|
|
@ -246,7 +248,6 @@ static void kbd_rx(uint8_t data)
|
|||
int evt = KBD_RSP_NULL;
|
||||
if (ringbuf_avail(&kbd_pending_evt)) {
|
||||
evt = ringbuf_get(&kbd_pending_evt);
|
||||
printf("via sr rx %s %02x\n", data == KBD_CMD_INSTANT ? "INSTANT" : "inquiry", evt);
|
||||
}
|
||||
via_sr_rx(evt);
|
||||
}
|
||||
|
|
@ -401,6 +402,10 @@ unsigned int FAST_FUNC(cpu_read_word)(unsigned int address)
|
|||
if (IS_ROM(address))
|
||||
return ROM_RD16(address & (ROM_SIZE - 1));
|
||||
|
||||
if (address == PV_UART_ADDR) {
|
||||
return pv_uart_read();
|
||||
}
|
||||
|
||||
if (IS_TESTSW(address))
|
||||
return 0;
|
||||
|
||||
|
|
@ -476,11 +481,7 @@ void FAST_FUNC(cpu_write_byte)(unsigned int address, unsigned int value)
|
|||
return;
|
||||
}
|
||||
if (address == PV_UART_ADDR) {
|
||||
if(value < 32 && value != '\r' && value != '\n') {
|
||||
printf("0x%02x", value);
|
||||
} else {
|
||||
putchar(value);
|
||||
}
|
||||
putchar(value);
|
||||
fflush(stdout);
|
||||
return;
|
||||
}
|
||||
|
|
@ -614,10 +615,35 @@ void umac_opt_disassemble(int enable)
|
|||
disassemble = enable;
|
||||
}
|
||||
|
||||
#define MOUSE_MAX_PENDING_PIX 30
|
||||
/* Provide mouse input (movement, button) data.
|
||||
*
|
||||
* X is positive going right; Y is positive going upwards.
|
||||
*/
|
||||
void umac_absmouse(int x, int y, int button)
|
||||
{
|
||||
if (!scc_get_mie()) return;
|
||||
#define MTemp_h 0x82a
|
||||
#define MTemp_v 0x828
|
||||
#define CrsrNew 0x8ce
|
||||
#define CrsrCouple 0x8cf
|
||||
|
||||
static int pending_mouse_deltax = 0;
|
||||
static int pending_mouse_deltay = 0;
|
||||
int oldx = RAM_RD16(MTemp_h);
|
||||
int oldy = RAM_RD16(MTemp_v);
|
||||
|
||||
if(x != oldx) {
|
||||
RAM_WR16(MTemp_h, x);
|
||||
}
|
||||
|
||||
if (y != oldy) {
|
||||
RAM_WR16(MTemp_v, y);
|
||||
}
|
||||
|
||||
if(x != oldx || y != oldy) {
|
||||
RAM_WR8(CrsrNew, RAM_RD8(CrsrCouple));
|
||||
}
|
||||
|
||||
via_mouse_pressed = button;
|
||||
}
|
||||
|
||||
/* Provide mouse input (movement, button) data.
|
||||
*
|
||||
|
|
@ -625,83 +651,22 @@ static int pending_mouse_deltay = 0;
|
|||
*/
|
||||
void umac_mouse(int deltax, int deltay, int button)
|
||||
{
|
||||
pending_mouse_deltax += deltax;
|
||||
pending_mouse_deltay += deltay;
|
||||
|
||||
/* Clamp if the UI has flooded with lots and lots of steps!
|
||||
*/
|
||||
if (pending_mouse_deltax > MOUSE_MAX_PENDING_PIX)
|
||||
pending_mouse_deltax = MOUSE_MAX_PENDING_PIX;
|
||||
if (pending_mouse_deltax < -MOUSE_MAX_PENDING_PIX)
|
||||
pending_mouse_deltax = -MOUSE_MAX_PENDING_PIX;
|
||||
if (pending_mouse_deltay > MOUSE_MAX_PENDING_PIX)
|
||||
pending_mouse_deltay = MOUSE_MAX_PENDING_PIX;
|
||||
if (pending_mouse_deltay < -MOUSE_MAX_PENDING_PIX)
|
||||
pending_mouse_deltay = -MOUSE_MAX_PENDING_PIX;
|
||||
|
||||
/* FIXME: The movement might take a little time, but this
|
||||
* posts the button status immediately. Probably OK, but the
|
||||
* mismatch might be perceptible.
|
||||
*/
|
||||
via_mouse_pressed = button;
|
||||
}
|
||||
|
||||
static void mouse_tick(void)
|
||||
{
|
||||
/* Periodically, check if the mouse X/Y deltas are non-zero.
|
||||
* If a movement is required, encode one step in X and/or Y
|
||||
* and deduct from the pending delta.
|
||||
*
|
||||
* The step ultimately posts an SCC IRQ, so we _don't_ try to
|
||||
* make any more steps while an IRQ is currently pending.
|
||||
* (Currently, that means a previous step's DCD IRQ event
|
||||
* hasn't yet been consumed by the OS handler. In future, if
|
||||
* SCC is extended with other IRQ types, then just checking
|
||||
* the IRQ status is technically too crude, but should still
|
||||
* be fine given the timeframes.)
|
||||
*/
|
||||
if (pending_mouse_deltax == 0 && pending_mouse_deltay == 0)
|
||||
return;
|
||||
|
||||
if (scc_irq_state == 1)
|
||||
return;
|
||||
|
||||
static int old_dcd_a = 0;
|
||||
static int old_dcd_b = 0;
|
||||
|
||||
/* Mouse X/Y quadrature signals are wired to:
|
||||
* VIA Port B[4] & SCC DCD_A for X
|
||||
* VIA Port B[5] & SCC DCD_B for Y
|
||||
*
|
||||
* As VIA mouse signals aren't sampled until IRQ, can do this
|
||||
* in one step, toggling existing DCD states and setting VIA
|
||||
* either equal or opposite to DCD:
|
||||
*/
|
||||
int dcd_a = old_dcd_a;
|
||||
int dcd_b = old_dcd_b;
|
||||
int deltax = pending_mouse_deltax;
|
||||
int deltay = pending_mouse_deltay;
|
||||
uint8_t qb = via_quadbits;
|
||||
|
||||
if (deltax) {
|
||||
dcd_a = !dcd_a;
|
||||
qb = (qb & ~0x10) | ((deltax < 0) == dcd_a ? 0x10 : 0);
|
||||
pending_mouse_deltax += (deltax > 0) ? -1 : 1;
|
||||
MDBG(" px %d, oldpx %d", pending_mouse_deltax, deltax);
|
||||
if (!scc_get_mie()) return;
|
||||
if(deltax) {
|
||||
int16_t temp_h = RAM_RD16(MTemp_h) + deltax;
|
||||
RAM_WR16(MTemp_h, temp_h);
|
||||
}
|
||||
|
||||
if (deltay) {
|
||||
dcd_b = !dcd_b;
|
||||
qb = (qb & ~0x20) | ((deltay < 0) == dcd_b ? 0x20 : 0);
|
||||
pending_mouse_deltay += (deltay > 0) ? -1 : 1;
|
||||
MDBG(" py %d, oldpy %d", pending_mouse_deltay, deltay);
|
||||
int16_t temp_v = RAM_RD16(MTemp_v) - deltay;
|
||||
RAM_WR16(MTemp_v, temp_v);
|
||||
}
|
||||
MDBG("\n");
|
||||
|
||||
via_quadbits = qb;
|
||||
old_dcd_a = dcd_a;
|
||||
old_dcd_b = dcd_b;
|
||||
scc_set_dcd(dcd_a, dcd_b);
|
||||
if(deltax || deltay) {
|
||||
RAM_WR8(CrsrNew, RAM_RD8(CrsrCouple));
|
||||
}
|
||||
|
||||
via_mouse_pressed = button;
|
||||
}
|
||||
|
||||
void umac_reset(void)
|
||||
|
|
@ -733,7 +698,6 @@ int umac_loop(void)
|
|||
|
||||
// Device polling
|
||||
via_tick(global_time_us);
|
||||
mouse_tick();
|
||||
disc_tick();
|
||||
kbd_check_work();
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,8 @@ static void scc_wr3(int AnB, uint8_t data)
|
|||
}
|
||||
}
|
||||
|
||||
int scc_get_mie() { return scc_mie; }
|
||||
|
||||
// WR9: Master Interrupt control and reset commands
|
||||
static void scc_wr9(uint8_t data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -196,6 +196,43 @@ static int open_disc(unix_disc_descr_t *desc, int slot, int opt_write, const cha
|
|||
}
|
||||
}
|
||||
|
||||
// from micropython
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
static struct termios orig_termios;
|
||||
|
||||
static void stdio_mode_raw(void) {
|
||||
// save and set terminal settings
|
||||
tcgetattr(0, &orig_termios);
|
||||
static struct termios termios;
|
||||
termios = orig_termios;
|
||||
termios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||
termios.c_cflag = (termios.c_cflag & ~(CSIZE | PARENB)) | CS8;
|
||||
termios.c_lflag = 0;
|
||||
termios.c_cc[VMIN] = 1;
|
||||
termios.c_cc[VTIME] = 0;
|
||||
tcsetattr(0, TCSAFLUSH, &termios);
|
||||
}
|
||||
|
||||
static void stdio_mode_orig(void) {
|
||||
// restore terminal settings
|
||||
tcsetattr(0, TCSAFLUSH, &orig_termios);
|
||||
}
|
||||
|
||||
int pv_uart_read() {
|
||||
|
||||
struct pollfd p = { .fd = 0, .events = POLLIN };
|
||||
int r = poll(&p, 1, 0);
|
||||
if (r > 0) {
|
||||
unsigned char result;
|
||||
r = read(0, &result, 1);
|
||||
if (r == 1) return result;
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/* The emulator core expects to be given ROM and RAM pointers,
|
||||
|
|
@ -346,8 +383,14 @@ int main(int argc, char *argv[])
|
|||
perror("SDL window");
|
||||
return 1;
|
||||
}
|
||||
SDL_SetWindowGrab(window, SDL_TRUE);
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
|
||||
static const int absmouse = 1;
|
||||
if (!absmouse) {
|
||||
SDL_SetWindowGrab(window, SDL_TRUE);
|
||||
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
} else {
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
}
|
||||
|
||||
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||
|
|
@ -371,10 +414,12 @@ int main(int argc, char *argv[])
|
|||
|
||||
umac_init(ram_base, rom_base, discs);
|
||||
umac_opt_disassemble(opt_disassemble);
|
||||
stdio_mode_raw();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Main loop
|
||||
|
||||
|
||||
int done = 0;
|
||||
int mouse_button = 0;
|
||||
uint64_t last_vsync = 0;
|
||||
|
|
@ -384,7 +429,8 @@ int main(int argc, char *argv[])
|
|||
SDL_Event event;
|
||||
int mousex = 0;
|
||||
int mousey = 0;
|
||||
|
||||
int send_mouse = 0;
|
||||
static int absmousex, absmousey;
|
||||
if (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
|
|
@ -395,27 +441,37 @@ int main(int argc, char *argv[])
|
|||
case SDL_KEYUP: {
|
||||
int c = SDLScan2MacKeyCode(event.key.keysym.scancode);
|
||||
c = (c << 1) | 1;
|
||||
printf("Key 0x%x -> 0x%x\n", event.key.keysym.scancode, c);
|
||||
if (c != MKC_None)
|
||||
umac_kbd_event(c, (event.type == SDL_KEYDOWN));
|
||||
} break;
|
||||
|
||||
case SDL_MOUSEMOTION:
|
||||
send_mouse = 1;
|
||||
absmousex = event.motion.x / DISP_SCALE;
|
||||
absmousey = event.motion.y / DISP_SCALE;
|
||||
mousex = event.motion.xrel;
|
||||
mousey = -event.motion.yrel;
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
send_mouse = 1;
|
||||
mouse_button = 1;
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
send_mouse = 1;
|
||||
mouse_button = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
umac_mouse(mousex, mousey, mouse_button);
|
||||
if (send_mouse) {
|
||||
if(absmouse) {
|
||||
umac_absmouse(absmousex, absmousey, mouse_button);
|
||||
} else {
|
||||
umac_mouse(mousex, mousey, mouse_button);
|
||||
}
|
||||
}
|
||||
|
||||
done |= umac_loop();
|
||||
|
||||
|
|
@ -441,5 +497,6 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
} while (!done);
|
||||
|
||||
stdio_mode_orig();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue