Big overhaul of pgusinit; break out common stuff

This commit is contained in:
Ian Scott committed 2024-07-05 17:16:23 -06:00
1 parent be1ff1b273
commit e216fdc0ad
17 files changed
+811 -693

No files matched your search

+70
View File
@@ -0,0 +1,70 @@
#pragma once
// names, mode numbers, port numbers, etc., that are common between the PicoGUS firmware and pgusinit.exe
// 1D0 chosen as the base port as nothing is listed in Ralf Brown's Port List (http://www.cs.cmu.edu/~ralf/files.html)
#define CONTROL_PORT 0x1D0
#define DATA_PORT_LOW 0x1D1
#define DATA_PORT_HIGH 0x1D2
#define PICOGUS_PROTOCOL_VER 3
typedef enum {
PICO_FIRMWARE_IDLE = 0,
PICO_FIRMWARE_WRITING = 1,
PICO_FIRMWARE_BUSY = 2,
PICO_FIRMWARE_DONE = 0xFE,
PICO_FIRMWARE_ERROR = 0xFF
} pico_firmware_status_t;
typedef enum { PICO_BASED = 0, PICOGUS_2 = 1 } board_type_t;
typedef enum {
INVALID_MODE = 0,
GUS_MODE = 1,
ADLIB_MODE = 2,
MPU_MODE = 3,
TANDY_MODE = 4,
CMS_MODE = 5,
SB_MODE = 6,
USB_MODE = 7
} card_mode_t;
static const char *modenames[8] = {
"INVALID",
"GUS",
"ADLIB",
"MPU",
"TANDY",
"CMS",
"SB",
"USB"
};
#define MODE_MAGIC 0x00 // Magic string
#define MODE_PROTOCOL 0x01 // Protocol version
#define MODE_FWSTRING 0x02 // Firmware string
#define MODE_MODE 0x03 // Mode (GUS, OPL, MPU, etc...)
#define MODE_GUSPORT 0x04 // GUS Base port
#define MODE_OPLPORT 0x05 // Adlib Base port
#define MODE_SBPORT 0x06 // SB Base port
#define MODE_MPUPORT 0x07 // MPU Base port
#define MODE_TANDYPORT 0x08 // Tandy Base port
#define MODE_CMSPORT 0x09 // CMS Base port
#define MODE_JOYEN 0x0f // enable joystick
#define MODE_GUSBUF 0x10 // Audio buffer size
#define MODE_GUSDMA 0x11 // DMA interval
#define MODE_GUS44K 0x12 // Force 44k
#define MODE_WTVOL 0x20 // Wavetable mixer volume
#define MODE_MPUDELAY 0x21 // MPU sysex delay
#define MODE_MPUFAKE 0x22 // MPU fake all notes off
#define MODE_OPLWAIT 0x30 // Adlib speed sensitive fix
#define MODE_MOUSEPORT 0x40 // Mouse Base port
#define MODE_MOUSEPROTO 0x41 // Mouse protocol
#define MODE_MOUSERATE 0x42 // Mouse report rate
#define MODE_MOUSESEN 0x43 // Mouse sensitivity
#define MODE_BOOTMODE 0xE0 // Select firmware boot mode register
#define MODE_SAVE 0xE1 // Select save settings register
#define MODE_REBOOT 0xE2 // Select reboot register
#define MODE_DEFAULTS 0xE3 // Select reset to defaults register
#define MODE_HWTYPE 0xF0 // Hardware type
#define MODE_FLASH 0xFF // Firmware write mode
+1 -1
View File
@@ -1,5 +1,5 @@
CC = wcl
CFLAGS = -bcl=dos -za99
CFLAGS = -bcl=dos -za99 -os
pgusinit.exe: pgusinit.c
$(CC) $(CFLAGS) $<
+339 -319
View File
@@ -7,40 +7,7 @@
#include <stdbool.h>
#include <i86.h>
#define CONTROL_PORT 0x1D0
#define DATA_PORT_LOW 0x1D1
#define DATA_PORT_HIGH 0x1D2
#define PICOGUS_PROTOCOL_VER 2
typedef enum {
PICO_FIRMWARE_IDLE = 0,
PICO_FIRMWARE_WRITING = 1,
PICO_FIRMWARE_DONE = 0xFE,
PICO_FIRMWARE_ERROR = 0xFF
} pico_firmware_status_t;
typedef enum { PICO_BASED = 0, PICOGUS_2 = 1 } board_type_t;
typedef enum {
GUS_MODE = 0,
ADLIB_MODE = 1,
MPU_MODE = 2,
TANDY_MODE = 3,
CMS_MODE = 4,
SB_MODE = 5,
MOUSE_ONLY_MODE = 0x0e,
JOYSTICK_ONLY_MODE = 0x0f
} card_mode_t;
static const char *fwnames[8] = {
"INVALID",
"GUS",
"SB",
"MPU",
"TANDY",
"CMS",
"JOY"
};
#include "../common/picogus.h"
void banner(void) {
printf("PicoGUSinit v3.0.0 (c) 2024 Ian Scott - licensed under the GNU GPL v2\n\n");
@@ -58,62 +25,78 @@ const char* usage_by_card[] = {
"", // JOYSTICK_ONLY_MODE
};
void usage(char *argv0, card_mode_t mode) {
void usage(char *argv0, card_mode_t mode, bool print_all) {
// Max line length @ 80 chars:
// "................................................................................\n"
fprintf(stderr, "Usage:\n");
fprintf(stderr, " %s [/?] | [/f fw.uf2] | [/m x [d]]", argv0);
if (mode <= CMS_MODE) {
fprintf(stderr, " | [/j] %s", usage_by_card[mode]);
// "................................................................................\n"
printf("Usage:\n");
printf(" /? - show this message (/?? to show options for all modes)\n");
printf(" /flash fw.uf2 - program the PicoGUS with the firmware file fw.uf2\n");
printf(" /wtvol x - set volume of wavetable header. Scale 0-100, Default: 100\n");
printf(" (for PicoGUS v2.0 boards only)\n");
printf(" /mode x - change card mode to x (gus, sb, mpu, tandy, cms, usb)\n");
printf(" /defaults - set all settings for all modes to defaults\n");
printf(" /save - save settings to the card to persist on system boot\n");
printf(" /joy 1|0 - enable/disable USB joystick support\n");
printf("\n");
if (mode == GUS_MODE || print_all) {
// "................................................................................\n"
printf("GUS mode settings:\n");
printf(" /gusport x - set the base port of the GUS. Default: 240\n");
printf(" /gusbuf n - set audio buffer to n samples. Default: 4, Min: 1, Max: 256\n");
printf(" (tweaking can help programs that hang or have audio glitches)\n");
printf(" /gusdma n - force DMA interval to n us. Default: 0, Min: 0, Max: 255\n");
printf(" Specifying 0 restores the GUS default behavior.\n");
printf(" (increase to fix games with streaming audio like Doom)\n");
printf(" /gus44k 1|0 - Fixed 44.1kHz output for all active voice #s [EXPERIMENTAL]\n");
printf("\n");
}
fprintf(stderr, "\n\n");
fprintf(stderr, " /? - show this message\n");
fprintf(stderr, " /f fw.uf2 - program the PicoGUS with the firmware file fw.uf2\n");
fprintf(stderr, " /j - enable USB joystick support\n");
fprintf(stderr, " /v x - set volume of the wavetable header. Scale 0-100, Default: 100\n");
fprintf(stderr, " (for PicoGUS v2.0 boards only)\n");
fprintf(stderr, " /m x - change card mode to x (gus, sb, mpu, tandy, cms, joy)\n");
fprintf(stderr, " /s - save settings to the card to persist on system boot\n");
if (mode > GUS_MODE && mode < MOUSE_ONLY_MODE) {
fprintf(stderr, "Sound Blaster/AdLib, MPU-401, Tandy, CMS modes only:\n");
fprintf(stderr, " /p x - set the (hex) base port address of the emulated card. Defaults:\n");
fprintf(stderr, " Sound Blaster: 220; MPU-401: 330; Tandy: 2C0; CMS: 220\n");
// "................................................................................\n"
if (mode == SB_MODE || print_all) {
// "................................................................................\n"
printf("Sound Blaster/AdLib mode settings:\n");
printf(" /sbport x - set the base port of the Sound Blaster. Default: 220\n");
printf(" /oplport x - set the base port of the OPL2/AdLib on the SB. Default: 388\n");
printf(" /oplwait 1|0 - wait on OPL2 write. Can fix speed-sensitive early AdLib games\n");
printf("\n");
}
if (mode == SB_MODE) {
fprintf(stderr, " /o x - set the base address of the OPL2/AdLib on the SB. Default: 388\n");
fprintf(stderr, " /w - wait on OPL2 data write. Can fix speed-sensitive early AdLib games\n");
// "................................................................................\n"
if (mode == MPU_MODE || print_all) {
// "................................................................................\n"
printf("MPU-401 mode settings:\n");
printf(" /mpuport x - set the base port of the MPU-401. Default: 330\n");
printf(" /mpudelay 1|0 - delay SYSEX (for rev.0 Roland MT-32)\n");
printf(" /mpufake 1|0 - fake all notes off (for Roland RA-50)\n");
printf("\n");
}
if (mode == MPU_MODE) {
fprintf(stderr, "MPU-401 mode only:\n");
fprintf(stderr, " /x - delay SYSEX (for rev.0 Roland MT-32)\n");
fprintf(stderr, " /n - fake all notes off (for Roland RA-50)\n");
// "................................................................................\n"
if (mode == TANDY_MODE || print_all) {
// "................................................................................\n"
printf("Tandy mode settings:\n");
printf(" /tandyport x - set the base port of the Tandy 3-voice. Default: 2C0\n");
printf("\n");
}
if (mode == CMS_MODE || print_all) {
// "................................................................................\n"
printf("CMS mode settings:\n");
printf(" /cmsport x - set the base port of the CMS. Default: 220\n");
printf("\n");
}
if (mode == USB_MODE || print_all) {
// "................................................................................\n"
printf("Serial Mouse mode settings:\n");
printf(" /mouseport n - set COM port of the mouse. Default: 2, Choices: 1, 2, 3, 4\n");
printf(" /mouseproto n - set mouse protocol. Default: 2 (IntelliMouse)\n");
printf(" 0 - Microsoft Mouse 2-button, 1 - Logitech 3-button\n");
printf(" 2 - IntelliMouse 3-button + wheel, 3 - Mouse Systems 3-button\n");
printf(" /mouserate n - set report rate in Hz. Default: 60, Min: 20, Max: 200\n");
printf(" (increase for smoother cursor movement, decrease for lower CPU load)\n");
printf(" /mousesen n - set mouse sensitivity (256 - 100%, 128 - 50%, 512 - 200%)\n");
}
/*
if (mode == GUS_MODE) {
fprintf(stderr, "GUS mode only:\n");
fprintf(stderr, " /a n - set audio buffer to n samples. Default: 4, Min: 1, Max: 256\n");
fprintf(stderr, " (tweaking this can help programs that hang or have audio glitches)\n");
fprintf(stderr, " /d n - force DMA interval to n us. Default: 0, Min: 0, Max: 255\n");
fprintf(stderr, " Specifying 0 restores the GUS default behavior.\n");
fprintf(stderr, " (if games with streaming audio like Doom stutter, increase this)\n");
fprintf(stderr, " /4 - Enable fixed 44.1kHz output for all active voice #s [EXPERIMENTAL]\n");
fprintf(stderr, "The ULTRASND environment variable must be set in the following format:\n");
fprintf(stderr, "\tset ULTRASND=xxx,y,n,z,n\n");
fprintf(stderr, "Where xxx = port, y = DMA, z = IRQ. n is ignored.\n");
fprintf(stderr, "Port is set on the card according to ULTRASND; DMA and IRQ configued via jumper.");
// "................................................................................\n"
}
if (mode == MOUSE_ONLY_MODE) {
fprintf(stderr, "Serial Mouse mode only:\n");
fprintf(stderr, " /m n - set mouse protocol. Default: 2 (IntelliMouse)\n");
fprintf(stderr, " 0 - Microsoft Mouse 2-button, 1 - Logitech 3-button\n");
fprintf(stderr, " 2 - IntelliMouse 3-button + wheel, 3 - Mouse Systems 3-button\n");
fprintf(stderr, " /r n - set report rate in Hz. Default: 60, Min: 20, Max: 200\n");
fprintf(stderr, " (increase for smoother cursor movement, decrease for lower CPU load)\n");
fprintf(stderr, " /s n - set mouse sensitivity (256 - 100%, 128 - 50%, 512 - 200%)\n");
}
*/
}
const char* mouse_protocol_str[] = {
@@ -123,7 +106,7 @@ const char* mouse_protocol_str[] = {
void err_ultrasnd(char *argv0) {
fprintf(stderr, "ERROR: no ULTRASND variable set or is malformed!\n");
usage(argv0, GUS_MODE);
usage(argv0, GUS_MODE, false);
}
@@ -156,7 +139,7 @@ int init_gus(char *argv0) {
return 2;
}
outp(CONTROL_PORT, 0x04); // Select port register
outp(CONTROL_PORT, MODE_GUSPORT); // Select port register
outpw(DATA_PORT_LOW, port); // Write port
// Detect if there's something GUS-like...
@@ -185,7 +168,7 @@ int init_gus(char *argv0) {
void print_firmware_string(void) {
outp(CONTROL_PORT, 0xCC); // Knock on the door...
outp(CONTROL_PORT, 0x02); // Select firmware string register
outp(CONTROL_PORT, MODE_FWSTRING); // Select firmware string register
char firmware_string[256] = {0};
for (int i = 0; i < 255; ++i) {
@@ -208,7 +191,7 @@ bool wait_for_read(const uint8_t value) {
}
void write_settings(void) {
outp(CONTROL_PORT, 0xE1); // Select save settings register
outp(CONTROL_PORT, MODE_SAVE); // Select save settings register
outp(DATA_PORT_HIGH, 0xff);
printf("Settings saved to flash.\n");
delay(100);
@@ -218,7 +201,7 @@ void write_settings(void) {
int reboot_to_firmware(const uint8_t value, const bool permanent) {
outp(CONTROL_PORT, 0xCC); // Knock on the door...
outp(CONTROL_PORT, 0xE0); // Select firmware selection register
outp(CONTROL_PORT, MODE_BOOTMODE); // Select firmware selection register
outp(DATA_PORT_HIGH, value); // Send firmware number and permanent flag
delay(100);
@@ -226,8 +209,8 @@ int reboot_to_firmware(const uint8_t value, const bool permanent) {
if (permanent) {
write_settings();
}
printf("Rebooting to fw: %s...\n", fwnames[value]);
outp(CONTROL_PORT, 0xE2); // Select reboot register
printf("Rebooting to fw: %s...\n", modenames[value]);
outp(CONTROL_PORT, MODE_REBOOT); // Select reboot register
outp(DATA_PORT_HIGH, 0xff);
delay(100);
@@ -241,7 +224,7 @@ int reboot_to_firmware(const uint8_t value, const bool permanent) {
return 0;
}
int write_firmware(const char* fw_filename, uint8_t protocol) {
int write_firmware(const char* fw_filename) {
union {
uint8_t buf[512];
struct UF2_Block {
@@ -265,6 +248,12 @@ int write_firmware(const char* fw_filename, uint8_t protocol) {
return 10;
}
outp(CONTROL_PORT, 0x01); // Select protocol version register
uint8_t protocol = inp(DATA_PORT_HIGH);
if (PICOGUS_PROTOCOL_VER != protocol && protocol < 3) {
printf("Older fw protocol version %d detected, upgrading firmware in compatibility mode\n", protocol);
}
uint32_t numBlocks = 1;
for (uint32_t i = 0; i < numBlocks; ++i) {
if (fread(uf2_buf.buf, 1, 512, fp) != 512) {
@@ -282,7 +271,7 @@ int write_firmware(const char* fw_filename, uint8_t protocol) {
// Put card into programming mode
outp(CONTROL_PORT, 0xCC); // Knock on the door...
outp(CONTROL_PORT, 0xFF); // Select firmware programming mode
outp(CONTROL_PORT, MODE_FLASH); // Select firmware programming mode
// Wait a bit for 2nd core on Pico to restart
delay(100);
if (!wait_for_read(PICO_FIRMWARE_IDLE)) {
@@ -316,13 +305,13 @@ int write_firmware(const char* fw_filename, uint8_t protocol) {
fprintf(stderr, "\nERROR: Card is not in firmware writing mode?\n");
return 15;
}
} else if (protocol == 2) {
} else if (protocol > 1) {
if (!wait_for_read(PICO_FIRMWARE_DONE)) {
fprintf(stderr, "\nERROR: Card has written last firmware byte but is not done\n");
return 15;
}
outp(CONTROL_PORT, 0xCC); // Knock on the door...
outp(CONTROL_PORT, 0xFF); // Select firmware programming mode, which will reboot the card in DONE
outp(CONTROL_PORT, MODE_FLASH); // Select firmware programming mode, which will reboot the card in DONE
}
}
fprintf(stderr, ".");
@@ -341,31 +330,44 @@ int write_firmware(const char* fw_filename, uint8_t protocol) {
return 0;
}
#define process_bool_opt(option) \
if (i + 1 >= argc) { \
usage(argv[0], mode, false); \
return 255; \
} \
e = sscanf(argv[++i], "%1[01]", tmp_arg); \
if (e != 1) { \
usage(argv[0], mode, false); \
return 5; \
} \
option = (tmp_arg[0] == 1) ? 1 : 0;
#define process_port_opt(option) \
if (i + 1 >= argc) { \
usage(argv[0], mode, false); \
return 255; \
} \
e = sscanf(argv[++i], "%hx", &option); \
if (e != 1 || option > 0x3ffu) { \
usage(argv[0], mode, false); \
return 4; \
}
int main(int argc, char* argv[]) {
int e;
unsigned short buffer_size = 0;
unsigned short dma_interval = 0;
uint8_t force_44k = 0;
uint16_t port_override = 0;
uint16_t opl_port_override = 0;
uint8_t wt_volume;
uint8_t enable_joystick = 0;
uint8_t wtvol;
char fw_filename[256] = {0};
card_mode_t mode;
uint8_t mpu_delaysysex = 0;
uint8_t mpu_fakeallnotesoff = 0;
uint8_t enable_joystick = 0;
uint8_t adlib_wait = 0;
char mode_name[8] = {0};
int fw_num = 8;
bool permanent = false;
uint8_t mouse_protocol = 255, mouse_report_rate = 0;
int16_t mouse_sensitivity = 0;
banner();
// Get magic value from port on PicoGUS that is not on real GUS
outp(CONTROL_PORT, 0xCC); // Knock on the door...
outp(CONTROL_PORT, 0x00); // Select magic string register
outp(CONTROL_PORT, MODE_MAGIC); // Select magic string register
if (inp(DATA_PORT_HIGH) != 0xDD) {
err_pigus();
return 99;
@@ -373,168 +375,203 @@ int main(int argc, char* argv[]) {
printf("PicoGUS detected: ");
print_firmware_string();
outp(CONTROL_PORT, 0x03); // Select mode register
mode = inp(DATA_PORT_HIGH);
// Default wavetable volume to 100 in MPU mode, 0 otherwise
wt_volume = (mode == MPU_MODE) ? 100 : 0;
int i = 1;
// /flash option is special and can work across protocol versions, so if it's specified, that's all we do
while (i < argc) {
if (stricmp(argv[i], "/?") == 0) {
usage(argv[0], mode);
return 0;
} else if (stricmp(argv[i], "/j") == 0) {
enable_joystick = 1;
} else if (stricmp(argv[i], "/m") == 0) {
if (stricmp(argv[i], "/flash") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode);
return 255;
}
e = sscanf(argv[++i], "%7s", mode_name);
if (e != 1) {
usage(argv[0], mode);
return 5;
}
} else if (stricmp(argv[i], "/4") == 0) {
force_44k = 1;
} else if (stricmp(argv[i], "/a") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode);
return 255;
}
e = sscanf(argv[++i], "%hu", &buffer_size);
if (e != 1 || buffer_size < 1 || buffer_size > 256) {
usage(argv[0], mode);
return 3;
}
} else if (stricmp(argv[i], "/d") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode);
return 255;
}
e = sscanf(argv[++i], "%hu", &dma_interval);
if (e != 1 || dma_interval > 255) {
usage(argv[0], mode);
return 4;
}
} else if (stricmp(argv[i], "/p") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode);
return 255;
}
e = sscanf(argv[++i], "%hx", &port_override);
if (e != 1 || port_override > 0x3ffu) {
usage(argv[0], mode);
return 4;
}
} else if (stricmp(argv[i], "/o") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode);
return 255;
}
e = sscanf(argv[++i], "%hx", &opl_port_override);
if (e != 1 || opl_port_override > 0x3ffu) {
usage(argv[0], mode);
return 4;
}
} else if (stricmp(argv[i], "/w") == 0) {
adlib_wait = 1;
} else if (stricmp(argv[i], "/v") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode);
return 255;
}
e = sscanf(argv[++i], "%hu", &wt_volume);
if (e != 1 || wt_volume > 100) {
usage(argv[0], mode);
return 4;
}
} else if (stricmp(argv[i], "/x") == 0) {
mpu_delaysysex = 1;
} else if (stricmp(argv[i], "/s") == 0) {
if (mode == MPU_MODE) {
mpu_delaysysex = 1;
} else {
if (i + 1 >= argc) {
usage(argv[0], mode);
return 255;
}
e = sscanf(argv[++i], "%hi", &mouse_sensitivity);
if (e != 1) {
usage(argv[0], mode);
return 4;
}
}
} else if (stricmp(argv[i], "/n") == 0) {
mpu_fakeallnotesoff = 1;
} else if (stricmp(argv[i], "/f") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode);
usage(argv[0], INVALID_MODE, false);
return 255;
}
e = sscanf(argv[++i], "%255s", fw_filename);
if (e != 1) {
usage(argv[0], mode);
usage(argv[0], INVALID_MODE, false);
return 5;
}
} else if (stricmp(argv[i], "/s") == 0) {
permanent = true;
} else if (stricmp(argv[i], "/m") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode);
return 255;
}
e = sscanf(argv[++i], "%hu", &mouse_protocol);
if (e != 1 || mouse_protocol > 3) {
usage(argv[0], mode);
return 4;
}
} else if (stricmp(argv[i], "/r") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode);
return 255;
}
e = sscanf(argv[++i], "%hu", &mouse_report_rate);
if (e != 1 || mouse_report_rate < 20 || mouse_report_rate > 200) {
usage(argv[0], mode);
return 4;
}
return write_firmware(fw_filename);
}
++i;
}
outp(CONTROL_PORT, 0x01); // Select protocol version register
uint8_t protocol_got = inp(DATA_PORT_HIGH);
if (PICOGUS_PROTOCOL_VER != protocol_got) {
if (fw_filename[0] && protocol_got == 1) {
printf("Older fw protocol version 1 detected, upgrading firmware in compatibility mode\n");
} else {
err_protocol(PICOGUS_PROTOCOL_VER, protocol_got);
return 97;
}
err_protocol(PICOGUS_PROTOCOL_VER, protocol_got);
return 97;
}
if (fw_filename[0]) {
return write_firmware(fw_filename, protocol_got);
outp(CONTROL_PORT, MODE_MODE); // Select mode register
mode = inp(DATA_PORT_HIGH);
char tmp_arg[2];
uint16_t tmp_uint16;
uint8_t tmp_uint8;
i = 1;
while (i < argc) {
// global options /////////////////////////////////////////////////////////////////
if (stricmp(argv[i], "/?") == 0) {
usage(argv[0], mode, false);
return 0;
} else if (stricmp(argv[i], "/??") == 0) {
usage(argv[0], mode, true);
return 0;
} else if (stricmp(argv[i], "/joy") == 0) {
process_bool_opt(tmp_uint8);
outp(CONTROL_PORT, MODE_JOYEN); // Select joystick enable register
outp(DATA_PORT_HIGH, tmp_uint8);
} else if (stricmp(argv[i], "/mode") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode, false);
return 255;
}
e = sscanf(argv[++i], "%7s", mode_name);
if (e != 1) {
usage(argv[0], mode, false);
return 5;
}
} else if (stricmp(argv[i], "/wtvol") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode, false);
return 255;
}
e = sscanf(argv[++i], "%hhu", &tmp_uint8);
if (e != 1 || tmp_uint8 > 100) {
usage(argv[0], mode, false);
return 4;
}
outp(CONTROL_PORT, MODE_WTVOL); // Select wavetable volume register
outp(DATA_PORT_HIGH, tmp_uint8); // Write volume
} else if (stricmp(argv[i], "/save") == 0) {
permanent = true;
} else if (stricmp(argv[i], "/defaults") == 0) {
outp(CONTROL_PORT, MODE_DEFAULTS); // Select defaults register
outp(DATA_PORT_HIGH, 0xff); // Write volume
// GUS options /////////////////////////////////////////////////////////////////
} else if (stricmp(argv[i], "/gus44k") == 0) {
process_bool_opt(tmp_uint8);
outp(CONTROL_PORT, MODE_GUS44K); // Select force 44k buffer
outp(DATA_PORT_HIGH, tmp_uint8);
} else if (stricmp(argv[i], "/gusbuf") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode, false);
return 255;
}
e = sscanf(argv[++i], "%hhu", &tmp_uint8);
if (e != 1 || tmp_uint8 < 1) {
usage(argv[0], mode, false);
return 3;
}
outp(CONTROL_PORT, MODE_GUSBUF); // Select audio buffer register
outp(DATA_PORT_HIGH, (unsigned char)(tmp_uint8 - 1));
} else if (stricmp(argv[i], "/gusdma") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode, false);
return 255;
}
e = sscanf(argv[++i], "%hhu", &tmp_uint8);
if (e != 1) {
usage(argv[0], mode, false);
return 4;
}
outp(CONTROL_PORT, MODE_GUSDMA); // Select DMA interval register
outp(DATA_PORT_HIGH, tmp_uint8);
} else if (stricmp(argv[i], "/gusport") == 0) {
process_port_opt(tmp_uint16);
outp(CONTROL_PORT, MODE_GUSPORT); // Select GUS port register
outpw(DATA_PORT_LOW, tmp_uint16); // Write port
// SB options /////////////////////////////////////////////////////////////////
} else if (stricmp(argv[i], "/sbport") == 0) {
process_port_opt(tmp_uint16);
outp(CONTROL_PORT, MODE_SBPORT); // Select SB port register
outpw(DATA_PORT_LOW, tmp_uint16); // Write port
} else if (stricmp(argv[i], "/oplport") == 0) {
process_port_opt(tmp_uint16);
outp(CONTROL_PORT, MODE_OPLPORT); // Select OPL port register
outpw(DATA_PORT_LOW, tmp_uint16); // Write port
} else if (stricmp(argv[i], "/oplwait") == 0) {
process_bool_opt(tmp_uint8);
outp(CONTROL_PORT, MODE_OPLWAIT); // Select Adlib wait register
outp(DATA_PORT_HIGH, tmp_uint8); // Write sysex delay and fake all notes off settings
// MPU options /////////////////////////////////////////////////////////////////
} else if (stricmp(argv[i], "/mpuport") == 0) {
process_port_opt(tmp_uint16);
outp(CONTROL_PORT, MODE_MPUPORT); // Select MPU port register
outpw(DATA_PORT_LOW, tmp_uint16); // Write port
} else if (stricmp(argv[i], "/mpudelay") == 0) {
process_bool_opt(tmp_uint8);
outp(CONTROL_PORT, MODE_MPUDELAY); // Select MPU sysex delay register
outp(DATA_PORT_HIGH, tmp_uint8);
} else if (stricmp(argv[i], "/mpufake") == 0) {
process_bool_opt(tmp_uint8);
outp(CONTROL_PORT, MODE_MPUFAKE); // Select MPU fake all notes off register
outp(DATA_PORT_HIGH, tmp_uint8);
// Tandy options /////////////////////////////////////////////////////////////////
} else if (stricmp(argv[i], "/tandyport") == 0) {
process_port_opt(tmp_uint16);
outp(CONTROL_PORT, MODE_TANDYPORT); // Select Tandy port register
outpw(DATA_PORT_LOW, tmp_uint16); // Write port
// CMS options /////////////////////////////////////////////////////////////////
} else if (stricmp(argv[i], "/cmsport") == 0) {
process_port_opt(tmp_uint16);
outp(CONTROL_PORT, MODE_CMSPORT); // Select CMS port register
outpw(DATA_PORT_LOW, tmp_uint16); // Write port
// Mouse options /////////////////////////////////////////////////////////////////
} else if (stricmp(argv[i], "/mousesen") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode, false);
return 255;
}
e = sscanf(argv[++i], "%hi", &tmp_uint16);
if (e != 1) {
usage(argv[0], mode, false);
return 4;
}
outp(CONTROL_PORT, MODE_MOUSESEN); // Select mouse sensitivity register
outpw(DATA_PORT_LOW, tmp_uint16);
} else if (stricmp(argv[i], "/mouseproto") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode, false);
return 255;
}
e = sscanf(argv[++i], "%hhu", &tmp_uint8);
if (e != 1 || tmp_uint8 > 3) {
usage(argv[0], mode, false);
return 4;
}
outp(CONTROL_PORT, MODE_MOUSEPROTO);
outp(DATA_PORT_HIGH, tmp_uint8);
} else if (stricmp(argv[i], "/mouserate") == 0) {
if (i + 1 >= argc) {
usage(argv[0], mode, false);
return 255;
}
e = sscanf(argv[++i], "%hhu", &tmp_uint8);
if (e != 1 || tmp_uint8 < 20 || tmp_uint8 > 200) {
usage(argv[0], mode, false);
return 4;
}
outp(CONTROL_PORT, MODE_MOUSERATE);
outp(DATA_PORT_HIGH, tmp_uint8);
}
++i;
}
if (mode_name[0]) {
int i;
for (i = 1; i < 8; ++i) {
if (strnicmp(fwnames[i], mode_name, 7) == 0) {
if (strnicmp(modenames[i], mode_name, 7) == 0) {
fw_num = i;
break;
}
}
if (i == 8) {
usage(argv[0], mode);
usage(argv[0], mode, false);
return 255;
}
return reboot_to_firmware(fw_num, permanent);
}
outp(CONTROL_PORT, 0xf0); // Select hardware type register
outp(CONTROL_PORT, MODE_HWTYPE); // Select hardware type register
board_type_t board_type = inp(DATA_PORT_HIGH);
if (board_type == PICO_BASED) {
printf("Hardware: PicoGUS v1.x or PicoGUS Femto\n");
@@ -545,121 +582,104 @@ int main(int argc, char* argv[]) {
}
printf("\n");
uint16_t port;
uint16_t opl_port;
if (mode != GUS_MODE && mode != MOUSE_ONLY_MODE) {
if (port_override) {
outp(CONTROL_PORT, 0x04); // Select port register
outpw(DATA_PORT_LOW, port_override); // Write port
}
outp(CONTROL_PORT, MODE_JOYEN); // Select joystick enable register
tmp_uint8 = inp(DATA_PORT_HIGH);
printf("USB joystick support %s\n", tmp_uint8 ? "enabled" : "disabled");
outp(CONTROL_PORT, 0x04); // Select port register
port = inpw(DATA_PORT_LOW); // Get port
if (mode == SB_MODE) {
if (opl_port_override) {
outp(CONTROL_PORT, 0x05); // Select OPL port register
outpw(DATA_PORT_LOW, opl_port_override); // Write port
}
outp(CONTROL_PORT, 0x05); // Select OPL port register
opl_port = inpw(DATA_PORT_LOW); // Get port
}
}
if (mode != MOUSE_ONLY_MODE) {
outp(CONTROL_PORT, 0x0f); // Select joystick enable register
outp(DATA_PORT_HIGH, enable_joystick);
printf("USB joystick support %s\n", enable_joystick ? "enabled" : "disabled");
}
// Get joystick status (connected, joystick type, etc.)
if (board_type == PICOGUS_2) {
outp(CONTROL_PORT, 0x20); // Select wavetable volume register
outp(DATA_PORT_HIGH, wt_volume); // Write volume
printf("Wavetable volume set to %u\n", wt_volume);
outp(CONTROL_PORT, MODE_WTVOL); // Select wavetable volume register
outp(DATA_PORT_HIGH, wtvol); // Write volume
printf("Wavetable volume set to %u\n", wtvol);
}
switch(mode) {
case GUS_MODE:
init_gus(argv[0]);
if (!buffer_size) {
buffer_size = 4;
}
outp(CONTROL_PORT, 0x10); // Select audio buffer register
outp(DATA_PORT_HIGH, (unsigned char)(buffer_size - 1));
printf("Audio buffer size set to %u samples\n", buffer_size);
printf("GUS settings: ");
outp(CONTROL_PORT, MODE_GUSBUF); // Select audio buffer register
tmp_uint16 = inp(DATA_PORT_HIGH) + 1;
printf("Audio buffer: %u samples; ", tmp_uint16);
outp(CONTROL_PORT, 0x11); // Select DMA interval register
outp(DATA_PORT_HIGH, dma_interval);
if (dma_interval == 0) {
printf("DMA interval set to default behavior\n");
outp(CONTROL_PORT, MODE_GUSDMA); // Select DMA interval register
tmp_uint8 = inp(DATA_PORT_HIGH);
if (tmp_uint8 == 0) {
printf("DMA interval: default; ");
} else {
printf("DMA interval forced to %u us\n", dma_interval);
printf("DMA interval: %u us; ", tmp_uint8);
}
outp(CONTROL_PORT, 0x12); // Select force 44k buffer
outp(DATA_PORT_HIGH, force_44k);
if (force_44k) {
printf("Fixed 44.1kHz output enabled (EXPERIMENTAL)\n");
outp(CONTROL_PORT, MODE_GUS44K); // Select force 44k buffer
tmp_uint8 = inp(DATA_PORT_HIGH);
if (tmp_uint8) {
printf("Fixed 44.1kHz rate\n");
} else {
printf("Variable sample rate\n");
}
outp(CONTROL_PORT, 0x04); // Select port register
port = inpw(DATA_PORT_LOW); // Get port
printf("Running in GUS mode on port %x\n", port);
outp(CONTROL_PORT, MODE_GUSPORT); // Select port register
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
printf("Running in GUS mode on port %x\n", tmp_uint16);
break;
/* AdLib mode is coming back...
case ADLIB_MODE:
printf("Running in AdLib/OPL2 mode on port %x\n", port);
outp(CONTROL_PORT, MODE_OPLPORT); // Select port register
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
printf("Running in AdLib/OPL2 mode on port %x\n", tmp_uint16);
break;
*/
case MPU_MODE:
printf("MPU-401 sysex delay: %s, fake all notes off: %s\n", mpu_delaysysex ? "on" : "off", mpu_fakeallnotesoff ? "on" : "off");
outp(CONTROL_PORT, 0x21); // Select MPU settings register
outp(DATA_PORT_HIGH, mpu_delaysysex | (mpu_fakeallnotesoff << 1)); // Write sysex delay and fake all notes off settings
printf("Running in MPU-401 mode on port %x\n", port);
outp(CONTROL_PORT, MODE_MPUDELAY); // Select force 44k buffer
tmp_uint8 = inp(DATA_PORT_HIGH);
printf("MPU-401 sysex delay: %s, ", tmp_uint8 ? "on" : "off");
outp(CONTROL_PORT, MODE_MPUFAKE); // Select force 44k buffer
tmp_uint8 = inp(DATA_PORT_HIGH);
printf("fake all notes off: %s\n", tmp_uint8 ? "on" : "off");
outp(CONTROL_PORT, MODE_MPUPORT); // Select port register
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
printf("Running in MPU-401 mode on port %x\n", tmp_uint16);
break;
case TANDY_MODE:
printf("Running in Tandy 3-voice mode on port %x\n", port);
outp(CONTROL_PORT, MODE_TANDYPORT); // Select port register
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
printf("Running in Tandy 3-voice mode on port %x\n", tmp_uint16);
break;
case CMS_MODE:
printf("Running in CMS/Game Blaster mode on port %x\n", port);
outp(CONTROL_PORT, MODE_CMSPORT); // Select port register
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
printf("Running in CMS/Game Blaster mode on port %x\n", tmp_uint16);
break;
case SB_MODE:
outp(CONTROL_PORT, 0x30); // Select Adlib wait register
outp(DATA_PORT_HIGH, adlib_wait); // Write sysex delay and fake all notes off settings
printf("Running in Sound Blaster 2.0 mode on port %x (AdLib port %x%s)\n",
port, opl_port, adlib_wait ? ", wait on" : "");
outp(CONTROL_PORT, MODE_OPLPORT); // Select port register
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
printf("Running in Sound Blaster 2.0 mode on port %x ", tmp_uint16);
outp(CONTROL_PORT, MODE_OPLPORT); // Select port register
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
printf("(AdLib port %x", tmp_uint16);
outp(CONTROL_PORT, MODE_OPLWAIT); // Select Adlib wait register
tmp_uint8 = inp(DATA_PORT_HIGH);
printf("%s)\n", tmp_uint8 ? ", wait on" : "");
break;
case JOYSTICK_ONLY_MODE:
printf("Running in Joystick exclusive mode on port 201\n");
case MOUSE_ONLY_MODE:
if (port_override) {
outp(CONTROL_PORT, 0x40); // Select port register
outpw(DATA_PORT_LOW, port_override); // Write port
}
outp(CONTROL_PORT, 0x40); // Select port register
port = inpw(DATA_PORT_LOW); // Get port
case USB_MODE:
outp(CONTROL_PORT, MODE_MOUSEPORT); // Select port register
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
printf("Running in Serial Mouse exclusive mode on port %x\n", tmp_uint16);
outp(CONTROL_PORT, 0x41);
if (mouse_protocol != 255)
outp(DATA_PORT_HIGH, mouse_protocol);
else
mouse_protocol = inp(DATA_PORT_HIGH);
outp(CONTROL_PORT, MODE_MOUSERATE);
tmp_uint8 = inp(DATA_PORT_HIGH);
printf("Mouse report rate: %d Hz, ", tmp_uint8);
outp(CONTROL_PORT, 0x42);
if (mouse_report_rate)
outp(DATA_PORT_HIGH, mouse_report_rate);
else
mouse_report_rate = inp(DATA_PORT_HIGH);
outp(CONTROL_PORT, MODE_MOUSEPROTO);
tmp_uint8 = inp(DATA_PORT_HIGH);
printf("protocol: %s\n", mouse_protocol_str[tmp_uint8]);
outp(CONTROL_PORT, 0x43);
if (mouse_sensitivity)
outpw(DATA_PORT_LOW, mouse_sensitivity);
else
mouse_sensitivity = inpw(DATA_PORT_LOW);
printf("Running in Serial Mouse exclusive mode on port %x\n", port);
printf("Mouse report rate: %d Hz, protocol: %s\n", mouse_report_rate, mouse_protocol_str[mouse_protocol]);
printf("Mouse sensitivity: %d (%d.%02d)\n", mouse_sensitivity, (mouse_sensitivity >> 8), ((mouse_sensitivity & 0xFF) * 100) >> 8);
outp(CONTROL_PORT, MODE_MOUSESEN);
tmp_uint16 = inpw(DATA_PORT_LOW);
printf("Mouse sensitivity: %d (%d.%02d)\n", tmp_uint16, (tmp_uint16 >> 8), ((tmp_uint16 & 0xFF) * 100) >> 8);
break;
default:
printf("Running in unknown mode on port %x (maybe upgrade pgusinit?)\n", port);
printf("Running in unknown mode (maybe upgrade pgusinit?)\n");
break;
}
printf("PicoGUS initialized!\n");
+47 -16
View File
@@ -93,9 +93,13 @@ function(config_target TARGET_NAME MULTIFW)
set_linker_script(${TARGET_NAME} ${CMAKE_BINARY_DIR}/${TARGET_NAME}.ld)
endif()
if(USB_JOYSTICK OR USB_MOUSE)
set(USB_STACK TRUE)
endif()
if (USB_STACK)
# USB stack common stuff
target_link_libraries(picogus tinyusb_host)
target_link_libraries(${TARGET_NAME} tinyusb_host)
target_compile_definitions(${TARGET_NAME} PRIVATE USB_STACK=1)
endif()
if(USB_JOYSTICK)
# Joystick stuff
@@ -107,9 +111,9 @@ function(config_target TARGET_NAME MULTIFW)
endif()
if (USB_MOUSE)
# USB Mouse stuff
target_sources(picogus PRIVATE mouse/mouse_hid.c)
target_include_directories(picogus PUBLIC ${CMAKE_CURRENT_LIST_DIR}/mouse)
target_compile_definitions(picogus PRIVATE USB_MOUSE=1)
target_sources(${TARGET_NAME} PRIVATE mouse/mouse_hid.c)
target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/mouse)
target_compile_definitions(${TARGET_NAME} PRIVATE USB_MOUSE=1)
endif()
target_sources(${TARGET_NAME} PRIVATE M62429/M62429.cpp)
@@ -131,10 +135,7 @@ function(config_target TARGET_NAME MULTIFW)
pico_add_extra_outputs(${TARGET_NAME})
endfunction()
if(USB_JOYSTICK)
# Joystick stuff
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/tusb_xinput)
endif()
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/tusb_xinput)
add_subdirectory(rp2040-psram)
add_subdirectory(opl)
@@ -142,6 +143,7 @@ add_subdirectory(opl)
################################################################################
# Build GUS firmware
function(build_gus TARGET_NAME MULTIFW)
set(USB_JOYSTICK 1)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-gus")
target_sources(${TARGET_NAME} PRIVATE gusplay.cpp pico_pic.c isa_dma.c)
@@ -175,13 +177,14 @@ endfunction()
################################################################################
# Build SB firmware
function(build_sb TARGET_NAME MULTIFW)
set(USB_JOYSTICK 1)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-sb")
target_sources(${TARGET_NAME} PRIVATE sbdsp.cpp sbplay.cpp pico_pic.c isa_dma.c)
target_link_libraries(${TARGET_NAME} opl)
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_SB=1
# SOUND_OPL=1
SOUND_OPL=1
SOUND_DSP=1
USE_ALARM=1
USE_EMU8950_OPL=1
@@ -194,9 +197,31 @@ function(build_sb TARGET_NAME MULTIFW)
pico_enable_stdio_semihosting(${TARGET_NAME} 0)
endfunction()
################################################################################
# Build AdLib firmware
function(build_adlib TARGET_NAME MULTIFW)
set(USB_JOYSTICK 1)
set(USB_MOUSE 1)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-sb")
target_sources(${TARGET_NAME} PRIVATE sbplay.cpp)
target_link_libraries(${TARGET_NAME} opl)
target_compile_definitions(${TARGET_NAME} PRIVATE
SOUND_OPL=1
USE_ALARM=1
USE_EMU8950_OPL=1
EMU8950_ASM=1
# PICOW=1
)
pico_enable_stdio_uart(${TARGET_NAME} 1)
pico_enable_stdio_usb(${TARGET_NAME} 0)
pico_enable_stdio_semihosting(${TARGET_NAME} 0)
endfunction()
################################################################################
# Build MPU firmware
function(build_mpu TARGET_NAME MULTIFW)
set(USB_JOYSTICK 1)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-mpu401")
target_compile_definitions(${TARGET_NAME} PRIVATE
@@ -221,6 +246,8 @@ endfunction()
################################################################################
# Build Tandy firmware
function(build_tandy TARGET_NAME MULTIFW)
set(USB_JOYSTICK 1)
set(USB_MOUSE 1)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-tandy")
target_compile_definitions(${TARGET_NAME} PRIVATE
@@ -240,6 +267,8 @@ endfunction()
################################################################################
# Build CMS firmware
function(build_cms TARGET_NAME MULTIFW)
set(USB_JOYSTICK 1)
set(USB_MOUSE 1)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-cms")
target_compile_definitions(${TARGET_NAME} PRIVATE
@@ -258,20 +287,16 @@ endfunction()
################################################################################
# Build USB-only firmware (joystick + mouse support)
function(build_usb TARGET_NAME MULTIFW)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-usb")
set(USB_STACK 1)
set(USB_JOYSTICK 1)
set(USB_MOUSE 1)
config_target(${TARGET_NAME} ${MULTIFW})
pico_set_program_name(${TARGET_NAME} "picogus-usb")
target_compile_definitions(${TARGET_NAME} PRIVATE
USB_JOYSTICK_ONLY=1
USB_MOUSE_ONLY=1
USB_ONLY=1
)
target_sources(${TARGET_NAME} PRIVATE
usbplay.cpp
pico_pic.c
mouseplay.cpp
mouse/8250uart.cpp
mouse/sermouse.cpp
)
@@ -337,6 +362,9 @@ if(PROJECT_TYPE STREQUAL "MULTIFW")
build_sb(pg-sb FALSE)
build_sb(pg-sb-multifw TRUE)
add_dependencies(pg-sb-multifw pg-sb generate_flash_firmware_h)
build_adlib(pg-adlib FALSE)
build_adlib(pg-adlib-multifw TRUE)
add_dependencies(pg-adlib-multifw pg-adlib generate_flash_firmware_h)
build_mpu(pg-mpu FALSE)
build_mpu(pg-mpu-multifw TRUE)
add_dependencies(pg-mpu-multifw pg-mpu generate_flash_firmware_h)
@@ -383,6 +411,9 @@ elseif(PROJECT_TYPE STREQUAL "GUS")
elseif(PROJECT_TYPE STREQUAL "SB")
set(FW_TARGET pg-sb)
build_sb(pg-sb FALSE)
elseif(PROJECT_TYPE STREQUAL "ADLIB")
set(FW_TARGET pg-adlib)
build_sb(pg-adlib FALSE)
elseif(PROJECT_TYPE STREQUAL "MPU")
set(FW_TARGET pg-mpu)
build_mpu(pg-mpu FALSE)
+14 -3
View File
@@ -19,9 +19,13 @@
#include "pico/audio_i2s.h"
#include "pico/flash.h"
#ifdef USB_JOYSTICK
#ifdef USB_STACK
#include "tusb.h"
#endif
#ifdef USB_MOUSE
#include "mouse/8250uart.h"
#include "mouse/sermouse.h"
#endif
#ifdef MAME_CMS
#include "saa1099/saa1099.h"
@@ -80,7 +84,7 @@ void play_cms() {
puts("starting core 1 CMS");
flash_safe_execute_core_init();
#ifdef USB_JOYSTICK
#ifdef USB_STACK
// Init TinyUSB for joystick support
tuh_init(BOARD_TUH_RHPORT);
#endif
@@ -172,9 +176,16 @@ void play_cms() {
buffer->sample_count = buffer->max_sample_count;
give_audio_buffer(ap, buffer);
#ifdef USB_JOYSTICK
#ifdef USB_STACK
// Service TinyUSB events
tuh_task();
#endif
#ifdef USB_MOUSE
// mouse task
sermouse_core1_task();
// uart emulation task
uartemu_core1_task();
#endif
}
}
+8 -2
View File
@@ -38,6 +38,12 @@ static const Settings defaultSettings = {
},
.Tandy = {
.basePort = 0x2c0
},
.Mouse = {
.basePort = 0xffff,
.protocol = 0,
.reportRate = 60,
.sensitivity = 0x100
}
};
@@ -99,7 +105,7 @@ void saveSettings(const Settings* settings)
*/
}
void resetSettings(void)
void getDefaultSettings(Settings* settings)
{
saveSettings(&defaultSettings);
memcpy(settings, &defaultSettings, sizeof(Settings));
}
+8 -2
View File
@@ -12,7 +12,7 @@ extern "C" {
// Settings struct has generous padding for future settings by aligning to 4 bytes
typedef struct Settings {
uint32_t magic; // should be "pgus" in ascii (0x7069636F)
uint32_t magic; // should be "pgus" in ascii (0x70677573)
uint8_t version;
uint8_t startupMode;
struct {
@@ -43,12 +43,18 @@ typedef struct Settings {
struct {
uint16_t basePort;
} Tandy;
struct {
uint16_t basePort;
uint8_t protocol;
uint8_t reportRate;
int16_t sensitivity;
} Mouse;
} Settings;
void loadSettings(Settings* settings);
void saveSettings(const Settings* settings);
void resetSettings(void);
void getDefaultSettings(Settings* settings);
#ifdef __cplusplus
}
+3 -3
View File
@@ -21,7 +21,7 @@
#include "pico_pic.h"
#endif
#ifdef USB_JOYSTICK
#ifdef USB_STACK
#include "tusb.h"
#endif
@@ -121,7 +121,7 @@ void play_gus() {
#endif
#endif
GUS_Setup();
#ifdef USB_JOYSTICK
#ifdef USB_STACK
// Init TinyUSB for joystick support
tuh_init(BOARD_TUH_RHPORT);
#endif
@@ -156,7 +156,7 @@ void play_gus() {
*/
// gpio_xor_mask(1u << PICO_DEFAULT_LED_PIN);
give_audio_buffer(ap, buffer);
#ifdef USB_JOYSTICK
#ifdef USB_STACK
// Service TinyUSB events
tuh_task();
#endif
+5 -6
View File
@@ -95,7 +95,7 @@ static void sermouse_send_id() {
// --------------------------
// inititalization
uint32_t sermouse_init() {
uint32_t sermouse_init(uint8_t protocol, uint8_t report_rate_hz, int16_t sensitivity) {
// clear mouse state
mouse_state.state = SERMOUSE_STATE_RESET;
mouse_state.next_state = SERMOUSE_STATE_NULL;
@@ -107,11 +107,10 @@ uint32_t sermouse_init() {
mouse_state.report_interval_us = 0;
mouse_state.rx_interval_us = 0;
// set default internal values
// TODO: load from persistent storage (like Flash ROM)
sermouse_set_protocol(SERMOUSE_PROTOCOL_INTELLIMOUSE);
sermouse_set_report_rate_hz(SERMOUSE_REPORTRATE_DEFAULT);
sermouse_set_sensitivity(0x100);
// set internal values
sermouse_set_protocol(protocol);
sermouse_set_report_rate_hz(report_rate_hz);
sermouse_set_sensitivity(sensitivity);
// set initialized flag
mouse_state.initialized = 1;
+1 -1
View File
@@ -111,7 +111,7 @@ struct sermouse_state_t {
// --------------------------
// any core
uint32_t sermouse_init();
uint32_t sermouse_init(uint8_t protocol, uint8_t report_rate_hz, int16_t sensitivity);
uint32_t sermouse_attach_uart();
uint32_t sermouse_done();
-37
View File
@@ -1,37 +0,0 @@
#include <stdio.h>
#include "tusb.h"
#include "mouse/8250uart.h"
#include "mouse/sermouse.h"
// #include <string.h>
#ifdef USE_ALARM
#include "pico_pic.h"
#endif
void play_usb() {
puts("starting core 1 USB");
// board_init();
#ifdef USE_ALARM
// Init PIC on this core so it handles timers
PIC_Init();
puts("pic inited on core 1");
#endif
// init host stack on configured roothub port
tuh_init(BOARD_TUH_RHPORT);
for (;;) {
// tinyusb host task
tuh_task();
// mouse task
sermouse_core1_task();
// uart emulation task
uartemu_core1_task();
}
}
+3 -3
View File
@@ -9,7 +9,7 @@ extern Settings settings;
#include "pico_pic.h"
#endif
#ifdef USB_JOYSTICK
#ifdef USB_STACK
#include "tusb.h"
#endif
@@ -19,7 +19,7 @@ void play_mpu() {
puts("starting core 1 MPU");
flash_safe_execute_core_init();
#ifdef USB_JOYSTICK
#ifdef USB_STACK
// Init TinyUSB for joystick support
tuh_init(BOARD_TUH_RHPORT);
#endif
@@ -33,7 +33,7 @@ void play_mpu() {
for (;;) {
send_midi_byte(); // see if we need to send a byte
#ifdef USB_JOYSTICK
#ifdef USB_STACK
// Service TinyUSB events
tuh_task();
#endif
+1 -8
View File
@@ -5,14 +5,7 @@ extern "C" {
#endif
#include <stdint.h>
typedef enum {
PICO_FIRMWARE_IDLE = 0,
PICO_FIRMWARE_WRITING = 1,
PICO_FIRMWARE_BUSY = 2,
PICO_FIRMWARE_DONE = 0xFE,
PICO_FIRMWARE_ERROR = 0xFF
} pico_firmware_status_t;
#include "../common/picogus.h"
void pico_firmware_write(uint8_t data);
void pico_firmware_start();
+254 -283
View File
@@ -15,18 +15,9 @@
#include "hardware/watchdog.h"
#include "hardware/structs/watchdog.h"
enum board_type { PICO_BASED = 0, PICOGUS_2 = 1 } BOARD_TYPE;
#include "../common/picogus.h"
typedef enum {
GUS_MODE = 0,
ADLIB_MODE = 1, // deprecated
MPU_MODE = 2,
TANDY_MODE = 3,
CMS_MODE = 4,
SB_MODE = 5,
MOUSE_ONLY_MODE = 0x0E, // clarify later
JOYSTICK_ONLY_MODE = 0x0f
} card_mode_t;
board_type_t BOARD_TYPE;
#ifdef PSRAM
#include "psram_spi.h"
@@ -49,22 +40,19 @@ uint LED_PIN;
M62429* m62429;
#ifdef SOUND_SB
#include "opl.h"
static uint16_t basePort;
static uint16_t sb_port_test;
extern void sbdsp_write(uint8_t address, uint8_t value);
extern uint8_t sbdsp_read(uint8_t address);
extern void sbdsp_init();
extern void sbdsp_process();
#endif
#ifdef SOUND_OPL
#include "opl.h"
void play_adlib(void);
extern "C" int OPL_Pico_Init(unsigned int);
extern "C" unsigned int OPL_Pico_PortRead(opl_port_t);
#include "cmd_buffers.h"
cms_buffer_t opl_buffer = { {0}, 0, 0 };
extern void sbdsp_write(uint8_t address, uint8_t value);
extern uint8_t sbdsp_read(uint8_t address);
extern void sbdsp_init();
extern void sbdsp_process();
static uint16_t adlib_basePort;
static bool adlib_wait;
#endif
#ifdef SOUND_GUS
@@ -72,7 +60,6 @@ static bool adlib_wait;
#include "isa_dma.h"
dma_inst_t dma_config;
static uint16_t basePort;
static uint16_t gus_port_test;
void play_gus(void);
#endif
@@ -80,13 +67,11 @@ void play_gus(void);
#ifdef SOUND_MPU
#include "mpu401/export.h"
static uint16_t basePort;
void play_mpu(void);
#endif
#ifdef SOUND_TANDY
#include "square/square.h"
static uint16_t basePort;
void play_tandy(void);
#include "cmd_buffers.h"
@@ -94,7 +79,6 @@ tandy_buffer_t tandy_buffer = { {0}, 0, 0 };
#endif
#ifdef SOUND_CMS
static uint16_t basePort;
void play_cms(void);
static uint8_t cms_detect = 0xFF;
@@ -103,31 +87,20 @@ cms_buffer_t cms_buffer = { {0}, 0, 0 };
#endif
#ifdef USB_JOYSTICK
static uint16_t joyPort;
#ifdef USB_JOYSTICK_ONLY
void play_usb(void);
#endif
#include "joy_hid/joy.h"
extern "C" joystate_struct_t joystate_struct;
uint8_t joystate_bin;
#include "hardware/pwm.h"
#endif
#ifdef USB_MOUSE
static uint16_t mousePort = 0x2F8; // emulate at COM2
static uint8_t mouseSensitivity_low;
#include "mouse/8250uart.h"
#include "mouse/sermouse.h"
extern uart_state_t uart_state;
void play_usb(void); // FIXME!!!!
#endif
#ifdef USB_ONLY
void play_usb(void);
#endif
// PicoGUS control and data ports
// 1D0 chosen as the base port as nothing is listed in Ralf Brown's Port List (http://www.cs.cmu.edu/~ralf/files.html)
#define CONTROL_PORT 0x1D0
#define DATA_PORT_LOW 0x1D1
#define DATA_PORT_HIGH 0x1D2
#define PICOGUS_PROTOCOL_VER 2
static bool control_active = false;
static uint8_t sel_reg = 0;
static uint16_t cur_data = 0;
@@ -136,63 +109,64 @@ static bool queueSaveSettings = false;
static bool queueReboot = false;
Settings settings;
void processSettings(void);
#define IOW_PIO_SM 0
#define IOR_PIO_SM 1
const char* firmware_string = PICO_PROGRAM_NAME " v" PICO_PROGRAM_VERSION_STRING;
uint16_t basePort_tmp;
uint16_t multifw_tmp;
static uint8_t basePort_low;
static uint8_t mouseSensitivity_low;
__force_inline void select_picogus(uint8_t value) {
// printf("select picogus %x\n", value);
sel_reg = value;
switch (sel_reg) {
case 0x00: // Magic string
case 0x01: // Protocol version
case MODE_MAGIC: // Magic string
case MODE_PROTOCOL: // Protocol version
break;
case 0x02: // Firmware string
case MODE_FWSTRING: // Firmware string
cur_read = 0;
break;
case 0x03: // Mode (GUS, OPL, MPU, etc...)
case MODE_MODE: // Mode (GUS, OPL, MPU, etc...)
break;
case 0x04: // Base port
case 0x05: // Adlib Base port
basePort_tmp = 0;
case MODE_GUSPORT: // GUS Base port
case MODE_OPLPORT: // Adlib Base port
case MODE_SBPORT: // SB Base port
case MODE_MPUPORT: // MPU Base port
case MODE_TANDYPORT: // Tandy Base port
case MODE_CMSPORT: // CMS Base port
basePort_low = 0;
break;
case 0x0f: // enable joystick
case MODE_JOYEN: // enable joystick
break;
#ifdef SOUND_GUS
case 0x10: // Audio buffer size
case 0x11: // DMA interval
case 0x12: // Force 44k
case MODE_GUSBUF: // Audio buffer size
case MODE_GUSDMA: // DMA interval
case MODE_GUS44K: // Force 44k
break;
#endif
case 0x20: // Wavetable mixer volume
case MODE_WTVOL: // Wavetable mixer volume
break;
#ifdef SOUND_MPU
case 0x21: // MPU init
case MODE_MPUDELAY: // MPU sysex delay
case MODE_MPUFAKE: // MPU fake all notes off
break;
#endif
#ifdef SOUND_SB
case 0x30: // Adlib speed sensitive fix
case MODE_OPLWAIT: // Adlib speed sensitive fix
break;
#ifdef USB_MOUSE
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case MODE_MOUSEPORT:
basePort_low = 0;
break;
#endif
#endif
case 0xE0: // Select firmware boot mode register
case 0xE1: // Select save settings register
case 0xE2: // Select reboot register
case MODE_MOUSEPROTO:
case MODE_MOUSERATE:
case MODE_MOUSESEN:
break;
case 0xF0: // Hardware version
case MODE_BOOTMODE: // Select firmware boot mode register
case MODE_SAVE: // Select save settings register
case MODE_REBOOT: // Select reboot register
case MODE_DEFAULTS: // Select reset to defaults register
break;
case 0xFF: // Firmware write mode
case MODE_HWTYPE: // Hardware version
break;
case MODE_FLASH: // Firmware write mode
pico_firmware_start();
break;
default:
@@ -203,119 +177,129 @@ __force_inline void select_picogus(uint8_t value) {
__force_inline void write_picogus_low(uint8_t value) {
switch (sel_reg) {
case 0x04: // Base port
case 0x05: // Adlib Base port
basePort_tmp = value;
case MODE_GUSPORT: // GUS Base port
case MODE_OPLPORT: // Adlib Base port
case MODE_SBPORT: // SB Base port
case MODE_MPUPORT: // MPU Base port
case MODE_TANDYPORT: // Tandy Base port
case MODE_CMSPORT: // CMS Base port
case MODE_MOUSEPORT: // USB Mouse port (0 - disabled)
basePort_low = value;
break;
#ifdef USB_MOUSE
case 0x30: // USB Mouse port (0 - disabled)
mousePort = value;
break;
case 0x33: // USB Mouse Sensitivity (8.8 fixedpoint)
case MODE_MOUSESEN: // USB Mouse Sensitivity (8.8 fixedpoint)
mouseSensitivity_low = value;
break;
#endif
}
}
__force_inline void write_picogus_high(uint8_t value) {
switch (sel_reg) {
case 0x04: // Base port
#if defined(SOUND_GUS) || defined(SOUND_SB) || defined(SOUND_MPU) || defined(SOUND_TANDY) || defined(SOUND_CMS)
basePort = (value << 8) | basePort_tmp;
#endif
case MODE_GUSPORT: // GUS Base port
settings.GUS.basePort = (value && basePort_low) ? ((value << 8) | (basePort_low & 0xFF)) : 0xFFFF;
#ifdef SOUND_GUS
settings.GUS.basePort = basePort;
gus_port_test = basePort >> 4 | 0x10;
// GUS_SetPort(basePort);
gus_port_test = settings.GUS.basePort >> 4 | 0x10;
#endif
break;
case MODE_OPLPORT: // Adlib Base port
settings.SB.oplBasePort = (value && basePort_low) ? ((value << 8) | (basePort_low & 0xFF)) : 0xFFFF;
break;
case MODE_SBPORT: // SB Base port
settings.SB.basePort = (value && basePort_low) ? ((value << 8) | (basePort_low & 0xFF)) : 0xFFFF;
#ifdef SOUND_SB
settings.SB.basePort = basePort;
sb_port_test = basePort >> 4;
#endif
#ifdef SOUND_MPU
settings.MPU.basePort = basePort;
#endif
#ifdef SOUND_TANDY
settings.Tandy.basePort = basePort;
#endif
#ifdef SOUND_CMS
settings.CMS.basePort = basePort;
sb_port_test = settings.SB.basePort >> 4;
#endif
break;
case 0x05: // Adlib Base port
#ifdef SOUND_SB
adlib_basePort = (value << 8) | basePort_tmp;
settings.SB.oplBasePort = adlib_basePort;
#endif
case MODE_MPUPORT: // MPU Base port
settings.MPU.basePort = (value && basePort_low) ? ((value << 8) | (basePort_low & 0xFF)) : 0xFFFF;
break;
case 0x0f: // enable joystick
#ifdef USB_JOYSTICK
joyPort = value ? 0x201u : 0xffff;
settings.Joy.basePort = joyPort;
#endif
case MODE_TANDYPORT: // Tandy Base port
settings.Tandy.basePort = (value && basePort_low) ? ((value << 8) | (basePort_low & 0xFF)) : 0xFFFF;
break;
#ifdef SOUND_GUS
case 0x10: // Audio buffer size
case MODE_CMSPORT: // CMS Base port
settings.CMS.basePort = (value && basePort_low) ? ((value << 8) | (basePort_low & 0xFF)) : 0xFFFF;
break;
case MODE_JOYEN: // enable joystick
settings.Joy.basePort = value ? 0x201u : 0xffff;
break;
case MODE_GUSBUF: // GUS audio buffer size
// Value is sent by pgusinit as the size - 1, so we need to add 1 back to it
GUS_SetAudioBuffer(value + 1);
settings.GUS.audioBuffer = value + 1;
break;
case 0x11: // DMA interval
GUS_SetDMAInterval(value);
settings.GUS.dmaInterval = value;
break;
case 0x12: // Force 44k output
GUS_SetFixed44k(value);
settings.GUS.force44k = value;
break;
#ifdef SOUND_GUS
GUS_SetAudioBuffer(settings.GUS.audioBuffer);
#endif
case 0x20: // Wavetable mixer volume
break;
case MODE_GUSDMA: // GUS DMA interval
settings.GUS.dmaInterval = value;
#ifdef SOUND_GUS
GUS_SetDMAInterval(settings.GUS.dmaInterval);
#endif
break;
case MODE_GUS44K: // Force 44k output
settings.GUS.force44k = value;
#ifdef SOUND_GUS
GUS_SetFixed44k(settings.GUS.force44k);
#endif
break;
case MODE_WTVOL: // Wavetable mixer volume
settings.Global.waveTableVolume = value;
if (BOARD_TYPE == PICOGUS_2) {
m62429->setVolume(M62429_BOTH, value);
settings.Global.waveTableVolume = value;
m62429->setVolume(M62429_BOTH, settings.Global.waveTableVolume);
}
break;
case MODE_MPUDELAY: // MPU SYSEX delay
settings.MPU.delaySysex = value;
#ifdef SOUND_MPU
case 0x21: // MIDI emulation flags
MPU401_Init(value & 0x1 /* delaysysex */, value & 0x2 /* fakeallnotesoff */);
settings.MPU.delaySysex = value & 0x1;
settings.MPU.fakeAllNotesOff = value & 0x2;
break;
MPU401_Init(settings.MPU.delaySysex, settings.MPU.fakeAllNotesOff);
#endif
#ifdef SOUND_SB
case 0x30: // Adlib speed sensitive fix
adlib_wait = value;
break;
case MODE_MPUFAKE: // MPU fake all notes off
settings.MPU.fakeAllNotesOff = value;
#ifdef SOUND_MPU
MPU401_Init(settings.MPU.delaySysex, settings.MPU.fakeAllNotesOff);
#endif
break;
case MODE_OPLWAIT: // Adlib speed sensitive fix
settings.SB.oplSpeedSensitive = value;
break;
case MODE_MOUSEPORT: // USB Mouse port (0 - disabled)
settings.Mouse.basePort = (value && basePort_low) ? ((value << 8) | (basePort_low & 0xFF)) : 0xFFFF;
break;
case MODE_MOUSEPROTO: // USB Mouse protocol
settings.Mouse.protocol = value;
#ifdef USB_MOUSE
case 0x40: // USB Mouse port (0 - disabled)
uart_state.iobase = value ? ((value << 8) | (mousePort & 0xFF)) : 0xFFFF;
break;
case 0x41: // USB Mouse protocol
sermouse_set_protocol(value);
break;
case 0x42: // USB Mouse Report Rate
sermouse_set_report_rate_hz(value);
break;
case 0x43: // USB Mouse Sensitivity (8.8 fixedpoint)
sermouse_set_sensitivity((value << 8) | (mouseSensitivity_low & 0xFF));
break;
sermouse_set_protocol(settings.Mouse.protocol);
#endif
break;
case MODE_MOUSERATE: // USB Mouse Report Rate
settings.Mouse.reportRate = value;
#ifdef USB_MOUSE
sermouse_set_report_rate_hz(settings.Mouse.reportRate);
#endif
break;
case MODE_MOUSESEN: // USB Mouse Sensitivity (8.8 fixedpoint)
settings.Mouse.sensitivity = (value << 8) | (mouseSensitivity_low & 0xFF);
#ifdef USB_MOUSE
sermouse_set_sensitivity(settings.Mouse.sensitivity);
#endif
break;
// For multifw
case 0xE0:
// set firmware num, perm flag and reboot
case MODE_BOOTMODE:
settings.startupMode = value;
printf("requesting startup mode: %u\n", value);
break;
case 0xE1:
case MODE_SAVE:
queueSaveSettings = true;
break;
case 0xE2:
case MODE_REBOOT:
watchdog_hw->scratch[3] = settings.startupMode;
printf("rebooting into mode: %u\n", settings.startupMode);
watchdog_reboot(0, 0, 0);
case 0xff: // Firmware write
break;
case MODE_DEFAULTS:
getDefaultSettings(&settings);
processSettings();
break;
case MODE_FLASH: // Firmware write
pico_firmware_write(value);
break;
}
@@ -323,25 +307,22 @@ __force_inline void write_picogus_high(uint8_t value) {
__force_inline uint8_t read_picogus_low(void) {
switch (sel_reg) {
case 0x04: // Base port
#if defined(SOUND_GUS) || defined(SOUND_SB) || defined(SOUND_MPU) || defined(SOUND_TANDY) || defined(SOUND_CMS)
return basePort & 0xff;
#else
return 0xff;
#endif
#ifdef USB_MOUSE
case 0x30: // USB Mouse port (0 - disabled)
return uart_state.iobase == 0xFFFF ? 0 : (uart_state.iobase & 0xFF);
case 0x33: // USB Mouse Sensitivity (8.8 fixedpoint)
return (sermouse_get_sensitivity() & 0xFF);
#endif
break;
case 0x05: // Adlib Base port
#if defined(SOUND_SB)
return adlib_basePort & 0xff;
#else
return 0xff;
#endif
case MODE_GUSPORT: // GUS Base port
return settings.GUS.basePort == 0xFFFF ? 0 : (settings.Mouse.basePort & 0xFF);
case MODE_OPLPORT: // Adlib Base port
return settings.SB.oplBasePort == 0xFFFF ? 0 : (settings.Mouse.basePort & 0xFF);
case MODE_SBPORT: // SB Base port
return settings.SB.basePort == 0xFFFF ? 0 : (settings.Mouse.basePort & 0xFF);
case MODE_MPUPORT: // MPU Base port
return settings.MPU.basePort == 0xFFFF ? 0 : (settings.Mouse.basePort & 0xFF);
case MODE_TANDYPORT: // Tandy Base port
return settings.Tandy.basePort == 0xFFFF ? 0 : (settings.Mouse.basePort & 0xFF);
case MODE_CMSPORT: // CMS Base port
return settings.CMS.basePort == 0xFFFF ? 0 : (settings.Mouse.basePort & 0xFF);
case MODE_MOUSEPORT: // USB Mouse port (0 - disabled)
return settings.Mouse.basePort == 0xFFFF ? 0 : (settings.Mouse.basePort & 0xFF);
case MODE_MOUSESEN: // USB Mouse Sensitivity (8.8 fixedpoint)
return settings.Mouse.sensitivity & 0xFF;
default:
return 0x0;
}
@@ -350,20 +331,17 @@ __force_inline uint8_t read_picogus_low(void) {
__force_inline uint8_t read_picogus_high(void) {
uint8_t ret;
switch (sel_reg) {
case 0x00: // PicoGUS magic string
case MODE_MAGIC: // PicoGUS magic string
return 0xdd;
break;
case 0x01: // PicoGUS protocol version
case MODE_PROTOCOL: // PicoGUS protocol version
return PICOGUS_PROTOCOL_VER;
break;
case 0x02: // Firmware string
case MODE_FWSTRING: // Firmware string
ret = firmware_string[cur_read++];
if (ret == 0) { // Null terminated
cur_read = 0;
}
return ret;
break;
case 0x03: // Mode (GUS, OPL, MPU, etc...)
case MODE_MODE: // Mode (GUS, OPL, MPU, etc...)
#if defined(SOUND_GUS)
return GUS_MODE;
#elif defined(SOUND_MPU)
@@ -374,88 +352,78 @@ __force_inline uint8_t read_picogus_high(void) {
return CMS_MODE;
#elif defined(SOUND_SB)
return SB_MODE;
#elif defined(USB_JOYSTICK_ONLY)
return JOYSTICK_ONLY_MODE;
#elif defined(USB_MOUSE_ONLY)
return MOUSE_ONLY_MODE;
#elif defined(SOUND_OPL)
return ADLIB_MODE;
#elif defined(USB_ONLY)
return USB_MODE;
#else
return 0xff;
return INVALID_MODE;
#endif
break;
case 0x04: // Base port
#if defined(SOUND_GUS) || defined(SOUND_SB) || defined(SOUND_MPU) || defined(SOUND_TANDY) || defined(SOUND_CMS)
return basePort >> 8;
#else
return 0xff;
#endif
break;
case 0x05: // Adlib Base port
#if defined(SOUND_SB)
return adlib_basePort >> 8;
#else
return 0xff;
#endif
break;
case 0x0f: // enable joystick
#ifdef USB_JOYSTICK
return joyPort == 0x201u;
#else
return 0;
#endif
case 0x20: // Wavetable mixer volume
if (BOARD_TYPE == PICOGUS_2) {
return m62429->getVolume(0);
} else {
return 0;
}
break;
#ifdef USB_MOUSE
case 0x40: // USB Mouse port (0 - disabled)
return uart_state.iobase == 0xFFFF ? 0 : (uart_state.iobase >> 8);
break;
case 0x41: // USB Mouse protocol
return sermouse_get_protocol();
break;
case 0x42: // USB Mouse Report Rate
return sermouse_get_report_rate_hz();
break;
case 0x43: // USB Mouse Sensitivity (8.8 fixedpoint)
return (sermouse_get_sensitivity() >> 8);
break;
#endif
case 0xF0: // Hardware version
case MODE_GUSPORT: // GUS Base port
return settings.GUS.basePort >> 8;
case MODE_OPLPORT: // Adlib Base port
return settings.SB.oplBasePort >> 8;
case MODE_SBPORT: // SB Base port
return settings.SB.basePort >> 8;
case MODE_MPUPORT: // MPU Base port
return settings.MPU.basePort >> 8;
case MODE_TANDYPORT: // Tandy Base port
return settings.Tandy.basePort >> 8;
case MODE_CMSPORT: // CMS Base port
return settings.CMS.basePort >> 8;
case MODE_JOYEN: // enable joystick
return settings.Joy.basePort == 0x201u;
case MODE_GUSBUF: // GUS audio buffer size
return settings.GUS.audioBuffer - 1;
case MODE_GUSDMA: // GUS DMA interval
return settings.GUS.dmaInterval;
case MODE_GUS44K: // Force 44k output
return settings.GUS.force44k;
case MODE_WTVOL: // Wavetable mixer volume
return (BOARD_TYPE == PICOGUS_2) ? m62429->getVolume(0) : 0;
case MODE_MPUDELAY: // SYSEX delay
return settings.MPU.delaySysex;
case MODE_MPUFAKE: // MPU fake all notes off
return settings.MPU.fakeAllNotesOff;
case MODE_OPLWAIT: // Adlib speed sensitive fix
return settings.SB.oplSpeedSensitive;
case MODE_MOUSEPORT: // USB Mouse port (0 - disabled)
return settings.Mouse.basePort == 0xFFFF ? 0 : (settings.Mouse.basePort >> 8);
case MODE_MOUSEPROTO: // USB Mouse protocol
return settings.Mouse.protocol;
case MODE_MOUSERATE: // USB Mouse Report Rate
return settings.Mouse.reportRate;
case MODE_MOUSESEN: // USB Mouse Sensitivity (8.8 fixedpoint)
return settings.Mouse.sensitivity >> 8;
case MODE_HWTYPE: // Hardware version
return BOARD_TYPE;
case 0xff:
case MODE_FLASH:
// Get status of firmware write
return pico_firmware_getStatus();
break;
default:
return 0xff;
break;
}
}
void processSettings(void) {
#ifdef SOUND_SB
basePort = settings.SB.basePort;
sb_port_test = basePort >> 4;
adlib_basePort = settings.SB.oplBasePort;
adlib_wait = settings.SB.oplSpeedSensitive;
sb_port_test = settings.SB.basePort >> 4;
#endif
#ifdef SOUND_GUS
basePort = settings.GUS.basePort;
gus_port_test = basePort >> 4 | 0x10;
gus_port_test = settings.GUS.basePort >> 4 | 0x10;
GUS_SetFixed44k(settings.GUS.force44k);
GUS_SetAudioBuffer(settings.GUS.audioBuffer);
GUS_SetDMAInterval(settings.GUS.dmaInterval);
#endif
#ifdef SOUND_MPU
basePort = settings.MPU.basePort;
#endif
#ifdef SOUND_CMS
basePort = settings.CMS.basePort;
#endif
#ifdef SOUND_TANDY
basePort = settings.Tandy.basePort;
#ifdef USB_MOUSE
sermouse_set_protocol(settings.Mouse.protocol);
sermouse_set_report_rate_hz(settings.Mouse.reportRate);
sermouse_set_sensitivity(settings.Mouse.sensitivity);
#endif
if (BOARD_TYPE == PICOGUS_2) {
m62429->setVolume(M62429_BOTH, settings.Global.waveTableVolume);
}
}
@@ -471,7 +439,7 @@ __force_inline void handle_iow(void) {
// printf("IOW: %x %x\n", port, iow_read & 0xFF);
#ifdef SOUND_GUS
if ((port >> 4 | 0x10) == gus_port_test) {
port -= basePort;
port -= settings.GUS.basePort;
switch (port) {
case 0x8:
case 0xb:
@@ -498,7 +466,7 @@ __force_inline void handle_iow(void) {
#endif // SOUND_GUS
#ifdef SOUND_SB
if ((port >> 4) == sb_port_test) {
switch (port - basePort) {
switch (port - settings.SB.basePort) {
// OPL ports
case 0x8:
// Fast write
@@ -525,7 +493,10 @@ __force_inline void handle_iow(void) {
sbdsp_process();
break;
}
} else if (port == adlib_basePort) {
} else // if follows down below
#endif // SOUND_SB
#if defined(SOUND_OPL)
if (port == settings.SB.oplBasePort) {
// Fast write
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
opl_buffer.cmds[opl_buffer.head++] = {
@@ -534,9 +505,9 @@ __force_inline void handle_iow(void) {
};
// Fast write - return early as we've already written 0x0u to the PIO
return;
} else if (port == adlib_basePort + 1) {
} else if (port == settings.SB.oplBasePort + 1) {
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
if (adlib_wait) {
if (settings.SB.oplSpeedSensitive) {
busy_wait_us(1); // busy wait for speed sensitive games
}
opl_buffer.cmds[opl_buffer.head++] = {
@@ -544,9 +515,9 @@ __force_inline void handle_iow(void) {
(uint8_t)(iow_read & 0xFF)
};
} else // if follows down below
#endif // SOUND_SB
#endif // SOUND_OPL
#ifdef SOUND_MPU
switch (port - basePort) {
switch (port - settings.MPU.basePort) {
case 0:
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT);
// printf("MPU IOW: port: %x value: %x\n", port, iow_read & 0xFF);
@@ -562,14 +533,14 @@ __force_inline void handle_iow(void) {
}
#endif // SOUND_MPU
#ifdef SOUND_TANDY
if (port == basePort) {
if (port == settings.Tandy.basePort) {
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
tandy_buffer.cmds[tandy_buffer.head++] = iow_read & 0xFF;
return;
} else // if follows down below
#endif // SOUND_TANDY
#ifdef SOUND_CMS
switch (port - basePort) {
switch (port - settings.CMS.basePort) {
// SAA data/address ports
case 0x0:
case 0x1:
@@ -592,7 +563,7 @@ __force_inline void handle_iow(void) {
}
#endif // SOUND_CMS
#ifdef USB_JOYSTICK
if (port == joyPort) {
if (port == settings.Joy.basePort) {
pio_sm_put(pio0, IOW_PIO_SM, IO_END);
// Set times in # of cycles (affected by clkdiv) for each PWM slice to count up and wrap back to 0
// TODO better calibrate this
@@ -618,7 +589,7 @@ __force_inline void handle_iow(void) {
} else // if follows down below
#endif // USB_JOYSTICK
#ifdef USB_MOUSE
if ((port & ~7) == uart_state.iobase) {
if ((port & ~7) == settings.Mouse.basePort) {
pio_sm_put(pio0, IOW_PIO_SM, IO_WAIT); // leave some time for UART logic emualtion
uartemu_write(port & 7, iow_read & 0xFF);
} else // if follows down below
@@ -662,16 +633,17 @@ __force_inline void handle_ior(void) {
if ((port >> 4 | 0x10) == gus_port_test) {
// Tell PIO to wait for data
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
uint32_t value = read_gus(port - basePort) & 0xff;
uint32_t value = read_gus(port - settings.GUS.basePort) & 0xff;
// OR with 0x0000ff00 is required to set pindirs in the PIO
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | value);
// printf("GUS IOR: port: %x value: %x\n", port, value);
// gpio_xor_mask(LED_PIN);
} else // if follows down below
#elif defined(SOUND_SB)
#endif
#if defined(SOUND_SB)
if ((port >> 4) == sb_port_test) {
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
if (port - basePort == 0x8) {
if (port - settings.SB.basePort == 0x8) {
// wait for OPL buffer to process
while (opl_buffer.tail != opl_buffer.head) {
tight_loop_contents();
@@ -682,7 +654,10 @@ __force_inline void handle_ior(void) {
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | sbdsp_read(port & 0xF));
sbdsp_process();
}
} else if (port == adlib_basePort) {
} else // if follows down below
#endif
#if defined(SOUND_OPL)
if (port == settings.SB.oplBasePort) {
// Tell PIO to wait for data
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
// wait for OPL buffer to process
@@ -691,15 +666,16 @@ __force_inline void handle_ior(void) {
}
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | OPL_Pico_PortRead(OPL_REGISTER_PORT));
} else // if follows down below
#elif defined(SOUND_MPU)
if (port == basePort) {
#endif
#if defined(SOUND_MPU)
if (port == settings.MPU.basePort) {
// Tell PIO to wait for data
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
uint32_t value = MPU401_ReadData();
// printf("MPU IOR: port: %x value: %x\n", port, value);
// OR with 0x0000ff00 is required to set pindirs in the PIO
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | value);
} else if (port == basePort + 1) {
} else if (port == settings.MPU.basePort + 1) {
// Tell PIO to wait for data
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
uint32_t value = MPU401_ReadStatus();
@@ -707,8 +683,9 @@ __force_inline void handle_ior(void) {
// OR with 0x0000ff00 is required to set pindirs in the PIO
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | value);
} else // if follows down below
#elif defined(SOUND_CMS)
switch (port - basePort) {
#endif
#if defined(SOUND_CMS)
switch (port - settings.CMS.basePort) {
// CMS autodetect ports
case 0x4:
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
@@ -722,7 +699,7 @@ __force_inline void handle_ior(void) {
}
#endif // SOUND_CMS
#ifdef USB_JOYSTICK
if (port == joyPort) {
if (port == settings.Joy.basePort) {
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
uint8_t value =
// Proportional bits: 1 if counter is still counting, 0 otherwise
@@ -735,7 +712,7 @@ __force_inline void handle_ior(void) {
} else // if follows down below
#endif // USB_JOYSTICK
#ifdef USB_MOUSE
if ((port & ~7) == uart_state.iobase) {
if ((port & ~7) == settings.Mouse.basePort) {
pio_sm_put(pio0, IOR_PIO_SM, IO_WAIT);
uint8_t value = uartemu_read(port & 7);
pio_sm_put(pio0, IOR_PIO_SM, IOR_SET_VALUE | value);
@@ -807,7 +784,6 @@ __force_inline bool ior_has_data() {
#include "hardware/structs/xip_ctrl.h"
int main()
{
hw_clear_bits(&xip_ctrl_hw->ctrl, XIP_CTRL_EN_BITS);
#ifdef ASYNC_UART
stdio_async_uart_init_full(UART_ID, BAUD_RATE, UART_TX_PIN, UART_RX_PIN);
#else
@@ -825,7 +801,7 @@ int main()
// Load settings from flash
loadSettings(&settings);
processSettings();
hw_clear_bits(&xip_ctrl_hw->ctrl, XIP_CTRL_EN_BITS);
// Determine board type. GPIO 29 is grounded on PicoGUS v2.0, and on a Pico, it's VSYS/3 (~1.666V)
// GPIO 25 must be high to read GPIO 29 on the Pico W
@@ -895,8 +871,8 @@ int main()
m62429->begin(24, 25, pio1, -1);
#else
m62429->begin(24, 25);
m62429->setVolume(M62429_BOTH, settings.Global.waveTableVolume);
#endif // SOUND_MPU
// Initial volume is set in processSettings()
#endif // M62429_PIO
}
gpio_init(IRQ_PIN);
@@ -954,17 +930,16 @@ int main()
#ifdef SOUND_SB
puts("Initializing SoundBlaster DSP");
sbdsp_init();
puts("Creating OPL");
OPL_Pico_Init(basePort);
multicore_launch_core1(&play_adlib);
#endif // SOUND_SB
#ifdef SOUND_OPL
puts("Creating OPL");
OPL_Pico_Init(0);
multicore_launch_core1(&play_adlib);
#endif
#ifdef SOUND_GUS
puts("Creating GUS");
GUS_OnReset();
GUS_SetAudioBuffer(settings.GUS.audioBuffer);
GUS_SetDMAInterval(settings.GUS.dmaInterval);
GUS_SetFixed44k(settings.GUS.force44k);
multicore_launch_core1(&play_gus);
#endif // SOUND_GUS
@@ -995,18 +970,16 @@ int main()
pwm_init(1, &pwm_c, true);
pwm_init(2, &pwm_c, true);
pwm_init(3, &pwm_c, true);
#ifdef USB_JOYSTICK_ONLY
multicore_launch_core1(&play_usb);
#endif // USB_JOYSTICK_ONLY
#endif // USB_JOYSTICK
#ifdef USB_MOUSE
puts("Config USB Mouse emulation");
uartemu_init(mousePort);
sermouse_init();
uartemu_init(0);
sermouse_init(settings.Mouse.protocol, settings.Mouse.reportRate, settings.Mouse.sensitivity);
sermouse_attach_uart();
multicore_launch_core1(&play_usb);
#endif // USB_MOUSE
#ifdef USB_ONLY
multicore_launch_core1(&play_usb);
#endif // USBONLY
for(int i=AD0_PIN; i<(AD0_PIN + 10); ++i) {
gpio_disable_pulls(i);
@@ -1061,18 +1034,16 @@ int main()
PIC_Init();
#endif
processSettings();
for (;;) {
#ifndef USE_IRQ
// if (!pio_sm_is_rx_fifo_empty(pio0, IOW_PIO_SM)) {
if (iow_has_data()) {
handle_iow();
// gpio_xor_mask(LED_PIN);
}
// if (!pio_sm_is_rx_fifo_empty(pio0, IOR_PIO_SM)) {
if (ior_has_data()) {
handle_ior();
// gpio_xor_mask(LED_PIN);
}
#endif
#ifndef USE_ALARM
+25 -6
View File
@@ -22,22 +22,28 @@
extern "C" void OPL_Pico_simple(int16_t *buffer, uint32_t nsamples);
extern "C" void OPL_Pico_PortWrite(opl_port_t, unsigned int);
#ifdef SOUND_SB
extern int16_t sbdsp_sample();
#ifdef USE_ALARM
#include "pico_pic.h"
#endif
#endif
#include "clamp.h"
#include "cmd_buffers.h"
extern cms_buffer_t opl_buffer;
#ifdef USB_JOYSTICK
#ifdef USB_STACK
#include "tusb.h"
#endif
#ifdef USB_MOUSE
#include "mouse/8250uart.h"
#include "mouse/sermouse.h"
#endif
extern uint LED_PIN;
#ifdef USE_ALARM
#include "pico_pic.h"
#endif
#if PICO_ON_DEVICE
#include "pico/binary_info.h"
@@ -93,12 +99,14 @@ void play_adlib() {
flash_safe_execute_core_init();
uint32_t start, end;
#ifdef SOUND_SB
#ifdef USE_ALARM
// Init PIC on this core so it handles timers
PIC_Init();
#endif
#endif
#ifdef USB_JOYSTICK
#ifdef USB_STACK
// Init TinyUSB for joystick support
tuh_init(BOARD_TUH_RHPORT);
#endif
@@ -125,13 +133,24 @@ void play_adlib() {
int16_t *samples = (int16_t *) buffer->buffer->bytes;
int16_t opl_sample;
OPL_Pico_simple(&opl_sample, 1);
#ifdef SOUND_SB
samples[0] = samples[1] = clamp16((int32_t)sbdsp_sample() + (int32_t)opl_sample);
#else
samples[0] = samples[1] = opl_sample;
#endif
buffer->sample_count=1;
// putchar((unsigned char)buffer->buffer->bytes[1]);
give_audio_buffer(ap, buffer);
#ifdef USB_JOYSTICK
#ifdef USB_STACK
// Service TinyUSB events
tuh_task();
#endif
#ifdef USB_MOUSE
// mouse task
sermouse_core1_task();
// uart emulation task
uartemu_core1_task();
#endif
}
}
+14 -3
View File
@@ -25,9 +25,13 @@ extern tandy_buffer_t tandy_buffer;
extern uint LED_PIN;
#ifdef USB_JOYSTICK
#ifdef USB_STACK
#include "tusb.h"
#endif
#ifdef USB_MOUSE
#include "mouse/8250uart.h"
#include "mouse/sermouse.h"
#endif
#include <string.h>
@@ -76,7 +80,7 @@ struct audio_buffer_pool *init_audio() {
void play_tandy() {
puts("starting core 1 tandy");
flash_safe_execute_core_init();
#ifdef USB_JOYSTICK
#ifdef USB_STACK
// Init TinyUSB for joystick support
tuh_init(BOARD_TUH_RHPORT);
#endif
@@ -119,9 +123,16 @@ void play_tandy() {
buffer->sample_count = SAMPLES_PER_BUFFER;
give_audio_buffer(ap, buffer);
#ifdef USB_JOYSTICK
#ifdef USB_STACK
// Service TinyUSB events
tuh_task();
#endif
#ifdef USB_MOUSE
// mouse task
sermouse_core1_task();
// uart emulation task
uartemu_core1_task();
#endif
}
}
+18
View File
@@ -1,19 +1,37 @@
#include <stdio.h>
#include "tusb.h"
#include "mouse/8250uart.h"
#include "mouse/sermouse.h"
// #include <string.h>
#ifdef USE_ALARM
#include "pico_pic.h"
#endif
void play_usb() {
puts("starting core 1 USB");
// board_init();
#ifdef USE_ALARM
// Init PIC on this core so it handles timers
PIC_Init();
puts("pic inited on core 1");
#endif
// init host stack on configured roothub port
tuh_init(BOARD_TUH_RHPORT);
for (;;) {
// tinyusb host task
tuh_task();
// mouse task
sermouse_core1_task();
// uart emulation task
uartemu_core1_task();
}
}