mirror of
https://github.com/polpo/picogus.git
synced 2026-10-25 21:40:16 +00:00
pgusinit: Update com port and SB blaster parsing
This commit is contained in:
1 parent
ab2b0e2be2
commit
afd68487c1
2 files changed
+196
-94
No files matched your search
+79
-53
@@ -1,20 +1,26 @@
|
||||
# PicoGUSinit v2.1.5
|
||||
# PicoGUS firmware v2.0.0 / PicoGUSinit v3.0.0
|
||||
|
||||
PicoGUSinit (also called pgusinit, after the program's .exe file) detects and
|
||||
initializes a PicoGUS card. In GUS emulation mode, it should be used instead of
|
||||
ULTRINIT.
|
||||
|
||||
For more info on PicoGUS, see https://github.com/polpo/picogus.
|
||||
For more info on PicoGUS, see https://picog.us/.
|
||||
|
||||
The board must be loaded with firmware before using it for the first time. See
|
||||
https://github.com/polpo/picogus/wiki/Building-your-PicoGUS#programming-the-pico
|
||||
for programming instructions.
|
||||
for programming instructions if your card didn't come programmed. The `/flash
|
||||
x` option to pgusinit can be used to upgrade firmware on a running PicoGUS.
|
||||
Firmware file that comes with release:
|
||||
|
||||
* `picogus.uf2` - All modes are now in a single firmware. To switch between
|
||||
modes, use the `/mode x` option in pgusinit.
|
||||
|
||||
pgusinit must be run with firmware it is compatible with. If run with an
|
||||
incompatible firmware, pgusinit will complain. One exception to this is that
|
||||
pgusinit can be used to upgrade an older version of firmware to a more recent
|
||||
version. For example, firmware v0.7.0, which is normally incompatibile with
|
||||
pgusinit v2.0.0, can be upgraded to firmware v1.0.0 with pgusinit v2.0.0.
|
||||
incompatible firmware, pgusinit will complain about a protocol mismatch. One
|
||||
exception to this is that pgusinit can be used to upgrade an older version of
|
||||
firmware to a more recent version. For example, firmware v1.2.0, which is
|
||||
normally incompatibile with pgusinit v3.0.0, can be upgraded to firmware
|
||||
v2.0.0 with pgusinit v3.0.0.
|
||||
|
||||
## Using
|
||||
|
||||
@@ -25,69 +31,89 @@ settings. Options may be given for other settings:
|
||||
|
||||
* `/?` - shows help for PicoGUSinit. Detects the current card mode and only
|
||||
shows options valid for that mode.
|
||||
* `/f firmware.uf2` - uploads firmware in the file named firmware.uf2 to the
|
||||
PicoGUS.
|
||||
* `/j` - enables game port joystick emulation mode (disabled by default).
|
||||
* `/v x` - sets wavetable header volume to x percent (PicoGUS 2.0 boards only).
|
||||
Available in all modes in case you want to use the wavetable header as an aux
|
||||
input (for example for an internal CD-ROM drive).
|
||||
* `/m x [d]` - changes operation mode (reboots card to x firmware, only if
|
||||
pg-multi.uf2 is flashed) for x: (1=gus, 2=sb, 3=mpu, 4=tandy, 5=cms, 6=joy)
|
||||
the optional parameter 'd' makes the selected mode permanent at system boot
|
||||
|
||||
Firmware files that come with the releases:
|
||||
|
||||
* `pg-gus.uf2` - GUS emulation
|
||||
* `pg-sb.uf2` - Sound Blaster/AdLib emulation
|
||||
* `pg-mpu.uf2` - MPU-401 with intelligent mode emulation
|
||||
* `pg-tandy.uf2` - Tandy 3-Voice emulation
|
||||
* `pg-cms.uf2` - CMS/Game Blaster emulation
|
||||
* `pg-joyex.uf2` - Joystick exclusive mode (doesn't emulate any sound cards,
|
||||
just the game port)
|
||||
* `pg-multi.uf2` - Multi-firmware. Contains all 6 firmwares in one. To be used
|
||||
with /m x option in pgusinit to change mode.
|
||||
* `/??` - shows help for PicoGUSinit for all modes.
|
||||
* `/flash picogus.uf2` - uploads firmware in the file named picogus.uf2 to the
|
||||
PicoGUS. Used to upgrade firmware version.
|
||||
* `/wtvol x` - sets wavetable header volume to x percent (PicoGUS 2.0 boards
|
||||
only). Available in all modes in case you want to use the wavetable header
|
||||
as an aux input (for example for an internal CD-ROM drive).
|
||||
* `/mode x` - changes the card to mode specified by x. Options:
|
||||
- `gus`: Gravis Ultrasound
|
||||
- `sb`: Sound Blaster 2.0 & AdLib
|
||||
- `mpu`: MPU-401 with intelligent mode and IRQ support
|
||||
- `tandy`: Tandy 3-voice. Supports USB serial mouse emulation.
|
||||
- `cms`: Creative Music System/Game Blaster. Supports USB serial mouse
|
||||
emulation.
|
||||
- 'adlib`: AdLib only. Supports USB serial mouse emulation.
|
||||
- `usb`: Only emulates game port joystick and serial mouse via USB. Can be
|
||||
used if you don't want to emulate any sound cards.
|
||||
* `/save` - saves current settings to the card. Saved settings persist across
|
||||
reboots, meaning pgusinit does not need to be run. The card mode is also
|
||||
saved.
|
||||
* `/defaults` - restores all card settings to defaults.
|
||||
* `/joy 1|0` - enable USB joystick support with 1, disable with 0.
|
||||
|
||||
### GUS emulation mode
|
||||
|
||||
GUS emulation mode requires the ULTRASND variable to be set, in the format:
|
||||
|
||||
`set ULTRASND=240,1,1,5,5` where 240 is the PicoGUS's port, 1 is the DMA, and 5
|
||||
is the IRQ. The port on the PicoGUS will be programmed to use the port
|
||||
specified in ULTRASND.
|
||||
`set ULTRASND=240,1,1,5,5` where 240 is the PicoGUS's port, 1 is the DMA, and
|
||||
5 is the IRQ. pgusinit will check that the port set on the PicoGUS matches the
|
||||
port specified in ULTRASND.
|
||||
|
||||
* `/a n` - sets the audio buffer size to n samples. Defaults to 4 with a
|
||||
* `/gusport x` - sets the base I/O port of the GUS to x. Defaults to 240.
|
||||
* `/gusbuf n` - sets the audio buffer size to n samples. Defaults to 4 with a
|
||||
minimum of 1 and maximum of 256. Some programs require a different value to
|
||||
run properly. Going lower than 4 is not advisable.
|
||||
* `/d n` - sets the DMA interval to n microseconds. Games that use streaming
|
||||
audio over DMA work better with higher values. Doom, for example, runs well
|
||||
with a value of 10-12. Note that increasing this will slow down sample
|
||||
* `/gusdma n` - sets the DMA interval to n microseconds. Games that use
|
||||
streaming audio over DMA work better with higher values. Doom, for example,
|
||||
runs well with a value of 10-12. Note that increasing this will slow sample
|
||||
loading. Set to 0 to use the GUS's default DMA interval handling, where the
|
||||
DMA interval is set by the program using it.
|
||||
* `/4` - enables fixed 44.1kHz output. Normally the GF1 varies its output
|
||||
sample rate from 44.1kHz at 14 voices to 19.2kHz at 32 voices. Using this
|
||||
option enables 44.1kHz output for all numbers of voices, similar to the
|
||||
Interwave. This will result in stuttering in most games that use streaming DMA
|
||||
for sound effects like Doom, hence it is EXPERIMENTAL.
|
||||
* `/gus44k 1|0` - setting to 1 enables fixed 44.1kHz output. Normally the GF1
|
||||
varies its output sample rate from 44.1kHz at 14 voices to 19.2kHz at 32
|
||||
voices. Using this option enables 44.1kHz output for all numbers of voices,
|
||||
similar to the Interwave. This will result in stuttering in most games that
|
||||
use streaming DMA for sound effects like Doom, hence it is EXPERIMENTAL.
|
||||
|
||||
See the Compatibility List wiki for notes on programs that require these
|
||||
options to be set: https://github.com/polpo/picogus/wiki/Compatibility-list
|
||||
|
||||
### Sound Blaster/AdLib, MPU-401, Tandy, and CMS emulation modes
|
||||
|
||||
* `/p x` - sets the base port of the emulated card to x. Defaults to 220 for
|
||||
Sound Blaster, 330 for MPU-401, 2C0 for Tandy, and 220 for CMS.
|
||||
See the Compatibility List wiki for notes on programs that require special
|
||||
settings for the above options:
|
||||
https://github.com/polpo/picogus/wiki/Compatibility-list
|
||||
|
||||
### Sound Blaster/AdLib mode
|
||||
|
||||
* `/o x` - sets the base port of the OPL/AdLib. Defaults to 388.
|
||||
* `/w` - wait on OPL2 data write. Can fix speed-sensitive early AdLib games on
|
||||
fast systems (example: 688 Attack Sub).
|
||||
* `/sbport x` - sets the base port of the Sound Blaster. Defaults to 220.
|
||||
* `/oplport x` - sets the base port of the OPL/AdLib. Defaults to 388.
|
||||
* `/oplwait` - wait on OPL2 data write. Can fix speed-sensitive early AdLib
|
||||
games on fast systems (example: 688 Attack Sub).
|
||||
|
||||
### MPU-401 emulation mode
|
||||
|
||||
* `/s` - enable sysex delay to prevent buffer overflows on older MPU-401
|
||||
revisions.
|
||||
* `/n` - Fake all-notes-off for the Roland RA-50.
|
||||
* `/mpuport x` - sets the base port of the MPU-401. Defaults to 330.
|
||||
* `/mpudelay` - set to 1 to enable sysex delay to prevent buffer overflows on
|
||||
older MPU-401 revisions.
|
||||
* `/mpufake` - set to 1 to fake all-notes-off for the Roland RA-50.
|
||||
|
||||
### Tandy emulation mode
|
||||
|
||||
* `/tandyport x` - sets the base port of the Tandy 3-voice. Defaults to 2c0.
|
||||
|
||||
### CMS emulation mode
|
||||
|
||||
* `/cmsport x` - sets the base port of the CMS. Defaults to 220.
|
||||
|
||||
### Serial mouse settings
|
||||
|
||||
Since a COM port requires an IRQ, serial mouse emulation is possible in modes
|
||||
that do not require an IRQ: AdLib, CMS, Tandy, and USB.
|
||||
|
||||
* `/mousecom n` - mouse COM port. Default: 0, Choices: 0 (disable), 1, 2, 3, 4
|
||||
* `/mouseproto n` - set mouse protocol. Default: 0 (Microsoft). Choices:
|
||||
0 - Microsoft Mouse 2-button, 1 - Logitech 3-button
|
||||
2 - IntelliMouse 3-button + wheel, 3 - Mouse Systems 3-button
|
||||
* `/mouserate n` - set report rate in Hz. Default: 60, Min: 20, Max: 200.
|
||||
Increase for smoother cursor movement, decrease for lower CPU load
|
||||
* `/mousesen n` - set mouse sensitivity (256 - 100%, 128 - 50%, 512 - 200%)
|
||||
|
||||
## Compiling
|
||||
|
||||
|
||||
+117
-41
@@ -13,17 +13,6 @@ void banner(void) {
|
||||
printf("PicoGUSinit v3.0.0 (c) 2024 Ian Scott - licensed under the GNU GPL v2\n\n");
|
||||
}
|
||||
|
||||
const char* usage_by_card[] = {
|
||||
"[/a n] [/d n] [/4]", // GUS_MODE
|
||||
"[/p x]", // ADLIB_MODE
|
||||
"[/p x] [/v x] [/s] [/n]", // MPU_MODE
|
||||
"[/p x]", // TANDY_MODE
|
||||
"[/p x]", // CMS_MODE
|
||||
"[/p x] [/o x] [/w]", // SB_MODE
|
||||
"", "", "", "", "", "", "", "",
|
||||
"[/p x] [/m n] [/r n] [/s n]", // MOUSE_ONLY_MODE
|
||||
"", // JOYSTICK_ONLY_MODE
|
||||
};
|
||||
|
||||
void usage(char *argv0, card_mode_t mode, bool print_all) {
|
||||
// Max line length @ 80 chars:
|
||||
@@ -33,10 +22,10 @@ void usage(char *argv0, card_mode_t mode, bool print_all) {
|
||||
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(" /mode x - change card mode to x (gus, sb, mpu, tandy, cms, adlib, 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(" /joy 1|0 - enable/disable USB joystick support, Default: 0\n");
|
||||
printf("\n");
|
||||
if (mode == GUS_MODE || print_all) {
|
||||
// "................................................................................\n"
|
||||
@@ -84,8 +73,8 @@ void usage(char *argv0, card_mode_t mode, bool print_all) {
|
||||
if (mode == USB_MODE || mode == CMS_MODE || mode == TANDY_MODE || mode == ADLIB_MODE || print_all) {
|
||||
// "................................................................................\n"
|
||||
printf("Serial Mouse 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(" /mousecom n - mouse COM port. Default: 0, Choices: 0 (disable), 1, 2, 3, 4\n");
|
||||
printf(" /mouseproto n - set mouse protocol. Default: 0 (Microsoft)\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");
|
||||
@@ -113,6 +102,12 @@ void err_ultrasnd(char *argv0) {
|
||||
}
|
||||
|
||||
|
||||
void err_blaster(char *argv0) {
|
||||
fprintf(stderr, "ERROR: no BLASTER variable set or is malformed!\n");
|
||||
usage(argv0, SB_MODE, false);
|
||||
}
|
||||
|
||||
|
||||
void err_pigus(void) {
|
||||
fprintf(stderr, "ERROR: no PicoGUS detected!\n");
|
||||
}
|
||||
@@ -133,19 +128,17 @@ int init_gus(char *argv0) {
|
||||
|
||||
// Parse ULTRASND
|
||||
uint16_t port;
|
||||
uint8_t irq;
|
||||
uint8_t dma;
|
||||
int e;
|
||||
e = sscanf(ultrasnd, "%hx,%hhu,%*hhu,%hhu,%*hhu", &port, &irq, &dma);
|
||||
if (e != 3) {
|
||||
e = sscanf(ultrasnd, "%hx,%*hhu,%*hhu,%*hhu,%*hhu", &port);
|
||||
if (e != 1) {
|
||||
err_ultrasnd(argv0);
|
||||
return 2;
|
||||
}
|
||||
|
||||
outp(CONTROL_PORT, MODE_GUSPORT); // Select port register
|
||||
uint16_t tmp_port = inpw(DATA_PORT_LOW); // Write port
|
||||
uint16_t tmp_port = inpw(DATA_PORT_LOW);
|
||||
if (port != tmp_port) {
|
||||
err_ultrasnd(argv0);
|
||||
err_ultrasnd(argv0);
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -173,6 +166,32 @@ int init_gus(char *argv0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int init_sb(char *argv0) {
|
||||
char* blaster = getenv("BLASTER");
|
||||
if (blaster == NULL) {
|
||||
err_blaster(argv0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Parse BLASTER
|
||||
uint16_t port;
|
||||
int e;
|
||||
e = sscanf(blaster, "A%hx I%*hhu D%*hhu T3", &port);
|
||||
if (e != 1) {
|
||||
err_blaster(argv0);
|
||||
return 2;
|
||||
}
|
||||
|
||||
outp(CONTROL_PORT, MODE_SBPORT); // Select port register
|
||||
uint16_t tmp_port = inpw(DATA_PORT_LOW);
|
||||
if (port != tmp_port) {
|
||||
err_blaster(argv0);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void print_firmware_string(void) {
|
||||
outp(CONTROL_PORT, 0xCC); // Knock on the door...
|
||||
outp(CONTROL_PORT, MODE_FWSTRING); // Select firmware string register
|
||||
@@ -523,8 +542,36 @@ int main(int argc, char* argv[]) {
|
||||
outp(CONTROL_PORT, MODE_CMSPORT); // Select CMS port register
|
||||
outpw(DATA_PORT_LOW, tmp_uint16); // Write port
|
||||
// Mouse options /////////////////////////////////////////////////////////////////
|
||||
} else if (stricmp(argv[i], "/mouseport") == 0) {
|
||||
process_port_opt(tmp_uint16);
|
||||
} else if (stricmp(argv[i], "/mousecom") == 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;
|
||||
}
|
||||
switch (tmp_uint8) {
|
||||
case 0:
|
||||
tmp_uint16 = 0;
|
||||
break;
|
||||
case 1:
|
||||
tmp_uint16 = 0x3f8;
|
||||
break;
|
||||
case 2:
|
||||
tmp_uint16 = 0x2f8;
|
||||
break;
|
||||
case 3:
|
||||
tmp_uint16 = 0x3e8;
|
||||
break;
|
||||
case 4:
|
||||
tmp_uint16 = 0x2e8;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0], mode, false);
|
||||
return 4;
|
||||
}
|
||||
outp(CONTROL_PORT, MODE_MOUSEPORT); // Select mouse port register
|
||||
outpw(DATA_PORT_LOW, tmp_uint16);
|
||||
} else if (stricmp(argv[i], "/mousesen") == 0) {
|
||||
@@ -563,6 +610,10 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
outp(CONTROL_PORT, MODE_MOUSERATE);
|
||||
outp(DATA_PORT_HIGH, tmp_uint8);
|
||||
} else {
|
||||
printf("Unknown option: %s\n", argv[i]);
|
||||
usage(argv[0], mode, false);
|
||||
return 255;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
@@ -606,7 +657,9 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
switch(mode) {
|
||||
case GUS_MODE:
|
||||
init_gus(argv[0]);
|
||||
if (init_gus(argv[0])) {
|
||||
return 1;
|
||||
}
|
||||
printf("GUS mode: ");
|
||||
outp(CONTROL_PORT, MODE_GUSBUF); // Select audio buffer register
|
||||
tmp_uint16 = inp(DATA_PORT_HIGH) + 1;
|
||||
@@ -662,6 +715,9 @@ int main(int argc, char* argv[]) {
|
||||
printf("Running in CMS/Game Blaster mode on port %x\n", tmp_uint16);
|
||||
break;
|
||||
case SB_MODE:
|
||||
if (init_sb(argv[0])) {
|
||||
return 1;
|
||||
}
|
||||
outp(CONTROL_PORT, MODE_SBPORT); // Select port register
|
||||
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
|
||||
printf("Running in Sound Blaster 2.0 mode on port %x ", tmp_uint16);
|
||||
@@ -672,27 +728,47 @@ int main(int argc, char* argv[]) {
|
||||
tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
printf("%s)\n", tmp_uint8 ? ", wait on" : "");
|
||||
break;
|
||||
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, MODE_MOUSERATE);
|
||||
tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
printf("Mouse report rate: %d Hz, ", tmp_uint8);
|
||||
|
||||
outp(CONTROL_PORT, MODE_MOUSEPROTO);
|
||||
tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
printf("protocol: %s\n", mouse_protocol_str[tmp_uint8]);
|
||||
|
||||
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 (maybe upgrade pgusinit?)\n");
|
||||
break;
|
||||
}
|
||||
if (mode == USB_MODE || mode == CMS_MODE || mode == TANDY_MODE || mode == ADLIB_MODE) {
|
||||
outp(CONTROL_PORT, MODE_MOUSEPORT); // Select port register
|
||||
tmp_uint16 = inpw(DATA_PORT_LOW); // Get port
|
||||
printf("Serial Mouse ");
|
||||
switch (tmp_uint16) {
|
||||
case 0:
|
||||
printf("disabled (enable with /mousecom n option)\n");
|
||||
break;
|
||||
case 0x3f8:
|
||||
printf("enabled on COM1\n");
|
||||
break;
|
||||
case 0x2f8:
|
||||
printf("enabled on COM2\n");
|
||||
break;
|
||||
case 0x3e8:
|
||||
printf("enabled on COM3\n");
|
||||
break;
|
||||
case 0x2e8:
|
||||
printf("enabled on COM4\n");
|
||||
break;
|
||||
default:
|
||||
printf("enabled on IO port %x\n", tmp_uint16);
|
||||
}
|
||||
if (tmp_uint16 != 0) {
|
||||
outp(CONTROL_PORT, MODE_MOUSERATE);
|
||||
tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
printf("Mouse report rate: %d Hz, ", tmp_uint8);
|
||||
|
||||
outp(CONTROL_PORT, MODE_MOUSEPROTO);
|
||||
tmp_uint8 = inp(DATA_PORT_HIGH);
|
||||
printf("protocol: %s\n", mouse_protocol_str[tmp_uint8]);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
printf("PicoGUS initialized!\n");
|
||||
|
||||
if (permanent) {
|
||||
|
||||
Reference in new issue
Block a user