mirror of
https://github.com/buserror/mii_emu.git
synced 2024-11-22 01:30:51 +00:00
Added joystick support
It is limited for now, hard coded to mine. Still need some sort of way to specify which button to map to the emulated joytick. Same with the axis, currently default to 0,1 Signed-off-by: Michel Pollet <buserror@gmail.com>
This commit is contained in:
parent
08e1ff861e
commit
d53b0bceff
@ -32,6 +32,7 @@ I wanted something:
|
||||
* Adds a small 'attack' filter when playing back to soften the often annoying 'click' of typical audio effects from the apple II.
|
||||
* Mouse Card -- mouse isn't captured like in some other emulators.
|
||||
* No Slot Clock
|
||||
* Joystick (in a limited way...)
|
||||
* Smartport DMA 'hard drive' card
|
||||
* "Titan Accelerator //e" simulation, to turn on/off fast mode.
|
||||
* Terence's J Boldt [1MB ROM card](https://github.com/tjboldt/ProDOS-ROM-Drive), also because I own a couple!
|
||||
@ -127,6 +128,7 @@ There are just a few keys that are mapped for anything useful.
|
||||
* A2Desktop PT3 player doesn't see keypresses.
|
||||
* Sometimes the emulator goes in 'slow mode', ie 0.2MHz. Likely the frame scheduler playing up.
|
||||
* Thats' about it really, all the other things I tried work
|
||||
* Joystick support is a bit limited, no 'mapping' I used a (USB) 8bitdo NES30 Pro, and it works, but it's not perfect. But, I can play choplifter with it, so it's good enough for now...
|
||||
|
||||
## What it could do with
|
||||
* Not sure about keeping Nuklear, it does a lot bit it's hard work customizing anything
|
||||
|
@ -86,6 +86,12 @@ show_state:
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!strcmp(argv[1], "analog")) {
|
||||
printf("analog: %3d %3d %3d %3d\n", mii->analog.v[0].value,
|
||||
mii->analog.v[1].value, mii->analog.v[2].value,
|
||||
mii->analog.v[3].value);
|
||||
return;
|
||||
}
|
||||
if (!strcmp(argv[1], "trace")) {
|
||||
mii->trace_cpu = !mii->trace_cpu;
|
||||
printf("trace_cpu %d\n", mii->trace_cpu);
|
||||
|
@ -12,6 +12,15 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// probably should wrap these into a HAVE_JOYSTICK define for non-linux
|
||||
#ifndef HAVE_JOYSTICK
|
||||
#define HAVE_JOYSTICK 1
|
||||
#endif
|
||||
|
||||
#include "mii.h"
|
||||
#include "mii_thread.h"
|
||||
|
||||
@ -31,19 +40,17 @@ mii_get_time()
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
static pthread_t mii_thread;
|
||||
static bool mii_thread_running = false;
|
||||
static float default_fps = 60;
|
||||
mii_th_fifo_t signal_fifo;
|
||||
|
||||
static void *
|
||||
mii_thread_func(
|
||||
mii_thread_cpu_regulator(
|
||||
void *arg)
|
||||
{
|
||||
mii_t *mii = (mii_t *) arg;
|
||||
mii_thread_running = true;
|
||||
__uint128_t last_cycles = mii->cycles;
|
||||
mii_cycles_t last_cycles = mii->cycles;
|
||||
uint32_t running = 1;
|
||||
unsigned long target_fps_us = 1000000 / default_fps;
|
||||
long sleep_time = target_fps_us;
|
||||
@ -117,8 +124,8 @@ mii_thread_func(
|
||||
last_frame_stamp += target_fps_us;
|
||||
|
||||
// calculate the MHz
|
||||
__uint128_t cycles = mii->cycles;
|
||||
__uint128_t delta_cycles = cycles - last_cycles;
|
||||
mii_cycles_t cycles = mii->cycles;
|
||||
mii_cycles_t delta_cycles = cycles - last_cycles;
|
||||
last_cycles = cycles;
|
||||
mii->speed_current = delta_cycles / (float)target_fps_us;
|
||||
}
|
||||
@ -129,13 +136,87 @@ mii_thread_func(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if HAVE_JOYSTICK
|
||||
#include <linux/joystick.h>
|
||||
|
||||
static void *
|
||||
mii_thread_joystick(
|
||||
void *arg)
|
||||
{
|
||||
int fd = open("/dev/input/js0", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
printf("No joystick found\n");
|
||||
return NULL;
|
||||
}
|
||||
uint8_t axes, buttons;
|
||||
if (ioctl(fd, JSIOCGAXES, &axes) == -1 ||
|
||||
ioctl(fd, JSIOCGBUTTONS, &buttons) == -1) {
|
||||
perror(__func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct js_event event;
|
||||
mii_t *mii = (mii_t *)arg;
|
||||
mii->analog.v[0].value = 127;
|
||||
mii->analog.v[1].value = 127;
|
||||
do {
|
||||
ssize_t rd = read(fd, &event, sizeof(event));
|
||||
if (rd != sizeof(event)) {
|
||||
perror(__func__);
|
||||
break;
|
||||
}
|
||||
switch (event.type) {
|
||||
case JS_EVENT_BUTTON:
|
||||
// printf("button %u %s\n", event.number, event.value ? "pressed" : "released");
|
||||
switch (event.number) {
|
||||
case 2 ... 3:
|
||||
mii_bank_poke(&mii->bank[MII_BANK_MAIN],
|
||||
0xc061 + (event.number - 2),
|
||||
event.value ? 0x80 : 0);
|
||||
break;
|
||||
case 4 ... 5:
|
||||
mii_bank_poke(&mii->bank[MII_BANK_MAIN],
|
||||
0xc061 + (event.number - 4),
|
||||
event.value ? 0x80 : 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case JS_EVENT_AXIS:
|
||||
switch (event.number) {
|
||||
case 0 ... 1: {// X
|
||||
uint32_t v = (event.value + 0x8000) / 256;
|
||||
if (v > 255)
|
||||
v = 255;
|
||||
mii->analog.v[event.number ? 1 : 0].value = v;
|
||||
// printf("axis %u %6d %3dx%3d\n"
|
||||
// event.number, event.value,
|
||||
// mii->analog.v[0].value, mii->analog.v[1].value);
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Ignore init events. */
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
close(fd);
|
||||
printf("Joystick thread terminated\n");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
mii_thread_start(
|
||||
mii_t *mii)
|
||||
{
|
||||
const mii_th_fifo_t zero = {};
|
||||
signal_fifo = zero;
|
||||
pthread_create(&mii_thread, NULL, mii_thread_func, mii);
|
||||
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL, mii_thread_cpu_regulator, mii);
|
||||
#if HAVE_JOYSTICK
|
||||
pthread_create(&thread, NULL, mii_thread_joystick, mii);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct mii_th_fifo_t*
|
||||
|
@ -313,6 +313,11 @@ mii_access_soft_switches(
|
||||
res = true;
|
||||
mii_speaker_click(&mii->speaker);
|
||||
break;
|
||||
case 0xc064 ... 0xc067: // Joystick, buttons
|
||||
case 0xc070: // Analog reset
|
||||
res = true;
|
||||
mii_analog_access(mii, &mii->analog, addr, byte, write);
|
||||
break;
|
||||
case 0xc068:
|
||||
res = true;
|
||||
// IIgs register, read by prodos tho
|
||||
|
59
src/mii_analog.c
Normal file
59
src/mii_analog.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* mii_analog.c
|
||||
*
|
||||
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "mii.h"
|
||||
#include "mii_analog.h"
|
||||
|
||||
void
|
||||
mii_analog_init(
|
||||
struct mii_t *mii,
|
||||
mii_analog_t * a )
|
||||
{
|
||||
memset(a, 0, sizeof(*a));
|
||||
}
|
||||
|
||||
/*
|
||||
* https://retrocomputing.stackexchange.com/questions/15093/how-do-i-read-the-position-of-an-apple-ii-joystick
|
||||
*/
|
||||
void
|
||||
mii_analog_access(
|
||||
mii_t *mii,
|
||||
mii_analog_t * a,
|
||||
uint16_t addr,
|
||||
uint8_t * byte,
|
||||
bool write)
|
||||
{
|
||||
if (write)
|
||||
return;
|
||||
switch (addr) {
|
||||
case 0xc070: {
|
||||
// multiplying by mii->speed allows reading joystick in 'fast' mode,
|
||||
// this basically simulate slowing down just for the joystick reading
|
||||
|
||||
/* TODO: According to various artivles, the multiplier ought
|
||||
* to be 11, but we're not making the count here, which means it's
|
||||
* likely the emulated core is missing a cycle for one instruction
|
||||
* somewhere... */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
a->v[i].decay = mii->cycles +
|
||||
((a->v[i].value * 10.10) * mii->speed);
|
||||
// printf("joystick %d: %d\n", i, a->v[i].value);
|
||||
}
|
||||
} break;
|
||||
case 0xc064 ... 0xc067: {
|
||||
addr -= 0xc064;
|
||||
*byte = mii->cycles <= a->v[addr].decay ? 0x80 : 0x00;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
33
src/mii_analog.h
Normal file
33
src/mii_analog.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* mii_analog.h
|
||||
*
|
||||
* Copyright (C) 2023 Michel Pollet <buserror@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "mii_types.h"
|
||||
|
||||
|
||||
typedef struct mii_analog_t {
|
||||
struct {
|
||||
uint8_t value;
|
||||
mii_cycles_t decay;
|
||||
} v[4];
|
||||
} mii_analog_t;
|
||||
|
||||
struct mii_t;
|
||||
|
||||
void
|
||||
mii_analog_init(
|
||||
struct mii_t *mii,
|
||||
mii_analog_t * analog );
|
||||
|
||||
void
|
||||
mii_analog_access(
|
||||
mii_t *mii,
|
||||
mii_analog_t * analog,
|
||||
uint16_t addr,
|
||||
uint8_t * byte,
|
||||
bool write);
|
Loading…
Reference in New Issue
Block a user