diff options
| author | spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> | 2022-02-27 23:54:39 +0100 |
|---|---|---|
| committer | spicyjpeg <88942473+spicyjpeg@users.noreply.github.com> | 2022-02-28 00:17:26 +0100 |
| commit | 6174931fe58b1dc0fc64029dbe3abefc81aa67d5 (patch) | |
| tree | 0119a8b41608c84c88981efd8362a15f01602491 /examples | |
| parent | c297c02652575e2affccbba16be0176d30d5ff06 (diff) | |
| download | psn00bsdk-6174931fe58b1dc0fc64029dbe3abefc81aa67d5.tar.gz | |
Refactor io/system573, switch to MSVC for CI builds
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/io/system573/iso.xml | 20 | ||||
| -rw-r--r-- | examples/io/system573/k573io.c | 123 | ||||
| -rw-r--r-- | examples/io/system573/k573io.h | 258 | ||||
| -rw-r--r-- | examples/io/system573/main.c | 264 |
4 files changed, 461 insertions, 204 deletions
diff --git a/examples/io/system573/iso.xml b/examples/io/system573/iso.xml index 09b4d85..0bb84d5 100644 --- a/examples/io/system573/iso.xml +++ b/examples/io/system573/iso.xml @@ -16,16 +16,26 @@ <directory_tree> <!-- - The System 573 BIOS does not parse SYSTEM.CNF, it always looks - for an executable named PSX.EXE. Note that this behavior can be - abused to make multi-system CDs with different executables for - PS1 and 573 (i.e. have both PSX.EXE and SYSTEM.CNF pointing to - a different executable). + The System 573 BIOS does not parse SYSTEM.CNF, it's instead + hardcoded to look for an executable named PSX.EXE. Some modded + or hacked BIOS variants may instead look for slightly altered + file names (QSY.DXD, SSW.BXF, TSV.AXG) as an obfuscation + measure, so it's recommended to have multiple copies of the + executable on the disc. + + Note that this behavior can be abused to make multi-system CDs + with different executables for PS1 and 573 (i.e. have both + PSX.EXE as the 573 executable and SYSTEM.CNF pointing to the + PS1 executable). --> <!--<file name="SYSTEM.CNF" type="data" source="${PROJECT_SOURCE_DIR}/system.cnf" />--> <file name="PSX.EXE" type="data" source="system573.exe" /> <file name="PSX.MAP" type="data" source="system573.map" /> + <file name="QSY.DXD" type="data" source="system573.exe" /> + <file name="SSW.BXF" type="data" source="system573.exe" /> + <file name="TSV.AXG" type="data" source="system573.exe" /> + <dummy sectors="1024"/> </directory_tree> </track> diff --git a/examples/io/system573/k573io.c b/examples/io/system573/k573io.c new file mode 100644 index 0000000..a8748d6 --- /dev/null +++ b/examples/io/system573/k573io.c @@ -0,0 +1,123 @@ +/* + * PSn00bSDK Konami System 573 example (I/O driver) + * (C) 2022 spicyjpeg - MPL licensed + * + * Note that this is far from being a complete driver. It currently lacks: + * - ATAPI driver + * - Flash erasing/writing APIs + * - JVS bus APIs + * - Functions for accessing the digital I/O board's MP3 decoder + */ + +#include <stdint.h> +#include <psxgpu.h> + +#include "k573io.h" + +K573_IOBoardType _board_type = IO_TYPE_ANALOG; + +/* I/O board light control */ + +static void _k573_set_lights_analog(uint32_t lights) { + uint32_t bits = 0xffffffff; + + bits ^= (lights & 0x01010101) << 7; // Lamp n*8+0 -> bit n*8+7 + bits ^= (lights & 0x02020202) << 5; // Lamp n*8+1 -> bit n*8+6 + bits ^= (lights & 0x04040404) >> 1; // Lamp n*8+2 -> bit n*8+1 + bits ^= (lights & 0x08080808) >> 3; // Lamp n*8+3 -> bit n*8+0 + bits ^= (lights & 0x10101010) << 1; // Lamp n*8+4 -> bit n*8+5 + bits ^= (lights & 0x20202020) >> 1; // Lamp n*8+5 -> bit n*8+4 + bits ^= (lights & 0x40404040) >> 3; // Lamp n*8+6 -> bit n*8+3 + bits ^= (lights & 0x80808080) >> 5; // Lamp n*8+7 -> bit n*8+2 + + K573_IO_BOARD[ANALOG_IO_REG_LIGHTS0] = (bits) & 0xff; + K573_IO_BOARD[ANALOG_IO_REG_LIGHTS1] = (bits >> 8) & 0xff; + K573_IO_BOARD[ANALOG_IO_REG_LIGHTS2] = (bits >> 16) & 0xff; + K573_IO_BOARD[ANALOG_IO_REG_LIGHTS3] = (bits >> 24) & 0xff; +} + +// This function controls light outputs on digital I/O boards (i.e. the ones +// that also include MP3 playback hardware, used by most Bemani games). +// TODO: test this on real hardware -- it might not work if lights are handled +// by the board's FPGA, which requires a binary blob... +static void _k573_set_lights_digital(uint32_t lights) { + uint32_t bits = 0xffffffff; + + bits ^= (lights & 0x11111111); // Lamp n*4+0 -> bit n*4+0 + bits ^= (lights & 0x22222222) << 1; // Lamp n*4+1 -> bit n*4+2 + bits ^= (lights & 0x44444444) << 1; // Lamp n*4+2 -> bit n*4+3 + bits ^= (lights & 0x88888888) >> 2; // Lamp n*4+3 -> bit n*4+1 + + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS0] = ((bits) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS1] = ((bits >> 4) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS2] = ((bits >> 8) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS3] = ((bits >> 12) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS4] = ((bits >> 16) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS5] = ((bits >> 20) & 0xf) << 12; + //K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS6] = ((bits >> 24) & 0xf) << 12; + K573_IO_BOARD[DIGITAL_IO_REG_LIGHTS7] = ((bits >> 28) & 0xf) << 12; +} + +static const void (*_k573_set_lights[])(uint32_t) = { + &_k573_set_lights_analog, + &_k573_set_lights_digital +}; + +/* Public API */ + +uint32_t K573_GetJAMMAInputs(void) { + uint32_t inputs; + + inputs = K573_IO_CHIP[IO_REG_IN2]; + inputs |= ((K573_IO_CHIP[IO_REG_IN3_LOW] >> 8) & 0x0f) << 16; + inputs |= ((K573_IO_CHIP[IO_REG_IN3_HIGH] >> 8) & 0x0f) << 20; + inputs |= ((K573_IO_CHIP[IO_REG_IN1_HIGH] >> 8) & 0x1f) << 24; + inputs |= (K573_IO_CHIP[IO_REG_IN1_LOW] & 0x07) << 29; + + return inputs; +} + +void K573_SetLights(uint32_t lights) { + if (_board_type > IO_TYPE_DIGITAL) + return; + + _k573_set_lights[_board_type](lights); +} + +void K573_SetBoardType(K573_IOBoardType type) { + _k573_set_lights[_board_type](0); + _board_type = type; +} + +/*void K573_DDRStageCommand(uint32_t value, uint32_t length) { + uint32_t last_bit = 0; + uint32_t mask = 1; + + for (uint32_t i = 0; i < length; i++) { + uint32_t bit = DDR_LIGHT_P1_MUX_DATA | DDR_LIGHT_P2_MUX_DATA; + if (value & mask) + bit = 0; + + K573_SetLights(last_bit | DDR_LIGHT_P1_MUX_CLK | DDR_LIGHT_P2_MUX_CLK); + _k573_delay_hblanks(20); + K573_SetLights(bit | DDR_LIGHT_P1_MUX_CLK | DDR_LIGHT_P2_MUX_CLK); + _k573_delay_hblanks(20); + K573_SetLights(bit); + _k573_delay_hblanks(20); + + last_bit = bit; + mask <<= 1; + } + + K573_SetLights(0); +}*/ + +//K573_DDRStageCommand(0x000c90, 13); +//K573_DDRStageCommand(0x000001, 22); + +void K573_Init(void) { + EXP1_ADDR = 0x1f000000; + EXP1_CTRL = 0x24173f47; // 573 BIOS uses this value + + K573_RESET_WATCHDOG(); +} diff --git a/examples/io/system573/k573io.h b/examples/io/system573/k573io.h new file mode 100644 index 0000000..cf125e2 --- /dev/null +++ b/examples/io/system573/k573io.h @@ -0,0 +1,258 @@ +/* + * PSn00bSDK Konami System 573 example (I/O driver) + * (C) 2022 spicyjpeg - MPL licensed + */ + +#ifndef __K573IO_H +#define __K573IO_H + +#include <stdint.h> + +/* Register definitions */ + +#define EXP1_ADDR *((volatile uint32_t *) 0x1f801000) +#define EXP1_CTRL *((volatile uint32_t *) 0x1f801008) + +#define K573_BANK_SWITCH *((volatile uint16_t *) 0x1f500000) +#define K573_IDE_RESET *((volatile uint16_t *) 0x1f560000) +#define K573_WATCHDOG *((volatile uint16_t *) 0x1f5c0000) +#define K573_EXT_OUT *((volatile uint16_t *) 0x1f600000) +#define K573_JVS_INPUT *((volatile uint16_t *) 0x1f680000) +#define K573_SECURITY_OUT *((volatile uint16_t *) 0x1f6a0000) + +#define K573_FLASH ((volatile uint16_t *) 0x1f000000) +#define K573_IO_CHIP ((volatile uint16_t *) 0x1f400000) +#define K573_IDE_CS0 ((volatile uint16_t *) 0x1f480000) +#define K573_IDE_CS1 ((volatile uint16_t *) 0x1f4c0000) +#define K573_RTC ((volatile uint16_t *) 0x1f620000) +#define K573_IO_BOARD ((volatile uint16_t *) 0x1f640000) + +typedef enum _K573_IOChipRegister { + IO_REG_IN0 = 0x0, + IO_REG_IN1_LOW = 0x2, + IO_REG_IN1_HIGH = 0x3, + IO_REG_IN2 = 0x4, + IO_REG_IN3_LOW = 0x6, + IO_REG_IN3_HIGH = 0x7 +} K573_IOChipRegister; + +typedef enum _K573_IOBoardRegister { + ANALOG_IO_REG_LIGHTS0 = 0x40, + ANALOG_IO_REG_LIGHTS1 = 0x44, + ANALOG_IO_REG_LIGHTS2 = 0x48, + ANALOG_IO_REG_LIGHTS3 = 0x4c, + + // The digital I/O board has a lot more registers than these, but there + // seems to be no DIGITAL_IO_LIGHTS6 register. WTF + DIGITAL_IO_REG_LIGHTS1 = 0x70, + DIGITAL_IO_REG_LIGHTS0 = 0x71, + DIGITAL_IO_REG_LIGHTS3 = 0x72, + DIGITAL_IO_REG_LIGHTS7 = 0x73, + DIGITAL_IO_REG_LIGHTS4 = 0x7d, + DIGITAL_IO_REG_LIGHTS5 = 0x7e, + DIGITAL_IO_REG_LIGHTS2 = 0x7f, + + FISHBAIT_IO_REG_UNKNOWN = 0x08, + FISHBAIT_IO_REG_MOTOR = 0x40, + FISHBAIT_IO_REG_BRAKE = 0x44, + FISHBAIT_IO_REG_ENCODER = 0x4c, + FISHBAIT_IO_REG_RESET_Y = 0x50 +} K573_IOBoardRegister; + +// The 573's real-time clock chip is an M48T58, which behaves like a standard +// 8 KB battery-backed SRAM with a bunch of special registers. Official games +// store highscores and settings in RTC RAM. +typedef enum _K573_RTCRegister { + RTC_REG_CTRL = 0x1ff8, + RTC_REG_SECONDS = 0x1ff9, + RTC_REG_MINUTES = 0x1ffa, + RTC_REG_HOURS = 0x1ffb, + RTC_REG_DAY_OF_WEEK = 0x1ffc, + RTC_REG_DAY_OF_MONTH = 0x1ffd, + RTC_REG_MONTH = 0x1ffe, + RTC_REG_YEAR = 0x1fff +} K573_RTCRegister; + +/* Inputs and lights bitfields */ + +typedef enum _K573_JAMMAInputs { + // IO_REG_IN2 bits 0-15 + JAMMA_P2_LEFT = 1 << 0, + JAMMA_P2_RIGHT = 1 << 1, + JAMMA_P2_UP = 1 << 2, + JAMMA_P2_DOWN = 1 << 3, + JAMMA_P2_BUTTON1 = 1 << 4, + JAMMA_P2_BUTTON2 = 1 << 5, + JAMMA_P2_BUTTON3 = 1 << 6, + JAMMA_P2_START = 1 << 7, + JAMMA_P1_LEFT = 1 << 8, + JAMMA_P1_RIGHT = 1 << 9, + JAMMA_P1_UP = 1 << 10, + JAMMA_P1_DOWN = 1 << 11, + JAMMA_P1_BUTTON1 = 1 << 12, + JAMMA_P1_BUTTON2 = 1 << 13, + JAMMA_P1_BUTTON3 = 1 << 14, + JAMMA_P1_START = 1 << 15, + + // IO_REG_IN3_LOW bits 8-11 + JAMMA_P1_BUTTON4 = 1 << 16, + JAMMA_P1_BUTTON5 = 1 << 17, + JAMMA_TEST = 1 << 18, + JAMMA_P1_BUTTON6 = 1 << 19, + + // IO_REG_IN3_HIGH bits 8-11 + JAMMA_P2_BUTTON4 = 1 << 20, + JAMMA_P2_BUTTON5 = 1 << 21, + JAMMA_UNKNOWN = 1 << 22, + JAMMA_P2_BUTTON6 = 1 << 23, + + // IO_REG_IN1_HIGH bits 8-12 + JAMMA_COIN1 = 1 << 24, + JAMMA_COIN2 = 1 << 25, + JAMMA_PCMCIA1 = 1 << 26, + JAMMA_PCMCIA2 = 1 << 27, + JAMMA_SERVICE = 1 << 28, + + // IO_REG_IN1_LOW bits 0-2 + JAMMA_DIP1 = 1 << 29, + JAMMA_DIP2 = 1 << 30, + JAMMA_DIP3 = 1 << 31 +} K573_JAMMAInputs; + +typedef enum _K573_Light { + // Dance Dance Revolution (2-player) + DDR_LIGHT_P1_UP = 1 << 0, + DDR_LIGHT_P1_LEFT = 1 << 1, + DDR_LIGHT_P1_RIGHT = 1 << 2, + DDR_LIGHT_P1_DOWN = 1 << 3, + DDR_LIGHT_P1_MUX_DATA = 1 << 4, // Used for stage commands + DDR_LIGHT_P1_MUX_CLK = 1 << 7, // Used for stage commands + DDR_LIGHT_P2_UP = 1 << 8, + DDR_LIGHT_P2_LEFT = 1 << 9, + DDR_LIGHT_P2_RIGHT = 1 << 10, + DDR_LIGHT_P2_DOWN = 1 << 11, + DDR_LIGHT_P2_MUX_DATA = 1 << 12, // Used for stage commands + DDR_LIGHT_P2_MUX_CLK = 1 << 15, // Used for stage commands + DDR_LIGHT_P1_BUTTONS = 1 << 17, + DDR_LIGHT_P2_BUTTONS = 1 << 18, + DDR_LIGHT_MARQUEE_BR = 1 << 20, + DDR_LIGHT_MARQUEE_BL = 1 << 21, + DDR_LIGHT_MARQUEE_TL = 1 << 22, + DDR_LIGHT_MARQUEE_TR = 1 << 23, + DDR_LIGHT_SPEAKER_DIGITAL = 1 << 28, // Speaker neon on digital I/O boards + DDR_LIGHT_SPEARKER_ANALOG = 1 << 30, // Speaker neon on analog I/O boards + + // Dance Dance Revolution Solo + DDRSOLO_LIGHT_EXTRA4 = 1 << 8, + DDRSOLO_LIGHT_EXTRA2 = 1 << 9, + DDRSOLO_LIGHT_EXTRA1 = 1 << 10, + DDRSOLO_LIGHT_EXTRA3 = 1 << 11, + DDRSOLO_LIGHT_SPEAKER = 1 << 16, + DDRSOLO_LIGHT_BUTTONS = 1 << 20, + DDRSOLO_LIGHT_BODY_CENTER = 1 << 21, + DDRSOLO_LIGHT_BODY_RIGHT = 1 << 22, + DDRSOLO_LIGHT_BODY_LEFT = 1 << 23, + + // DrumMania 1st Mix + DM_LIGHT_HIHAT = 1 << 16, + DM_LIGHT_HIGH_TOM = 1 << 17, + DM_LIGHT_LOW_TOM = 1 << 18, + DM_LIGHT_SNARE = 1 << 19, + DM_LIGHT_CYMBAL = 1 << 20, + DM_LIGHT_START_BUTTON = 1 << 21, + DM_LIGHT_SELECT_BUTTON = 1 << 22, + DM_LIGHT_NEON_BOTTOM = 1 << 27, + DM_LIGHT_SPOT = 1 << 30, + DM_LIGHT_NEON_TOP = 1 << 31, + + // DrumMania 2nd Mix and later + DM2_LIGHT_HIHAT = 1 << 0, + DM2_LIGHT_HIGH_TOM = 1 << 1, + DM2_LIGHT_LOW_TOM = 1 << 2, + DM2_LIGHT_SNARE = 1 << 3, + DM2_LIGHT_SPOT = 1 << 8, + DM2_LIGHT_NEON_TOP = 1 << 9, + DM2_LIGHT_NEON_BOTTOM = 1 << 11, + DM2_LIGHT_CYMBAL = 1 << 12, + DM2_LIGHT_START_BUTTON = 1 << 13, + DM2_LIGHT_SELECT_BUTTON = 1 << 14 +} K573_Light; + +/* System information structures */ + +typedef enum _K573_IOBoardType { + IO_TYPE_ANALOG = 0, // Light control board (early Bemani) + IO_TYPE_DIGITAL = 1, // Light control + MP3 playback board (late Bemani) + IO_TYPE_FISHBAIT = 2, // Fishing reel controls interface (Fisherman's Bait) + IO_TYPE_GUNMANIA = 3, // Gun control board (Gun Mania) + IO_TYPE_KARAOKE = 4, // Karaoke I/O + video mux board (DDR Karaoke Mix) + IO_TYPE_SERIAL = 5 // Serial port (debug?) board (Great Bishi Bashi Champ) + // TODO: does PunchMania have its own board? +} K573_IOBoardType; + +typedef enum _K573_DDRStageType { + DDR_TYPE_NONE = 0, + DDR_TYPE_2PLAYER = 1, + DDR_TYPE_SOLO = 2 +} K573_DDRStageType; + +/* Public API */ + +#define K573_RESET_WATCHDOG() { \ + K573_WATCHDOG = 0; \ +} + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Returns a bitfield containing the state of all JAMMA inputs and DIP + * switches. All bits are inverted as they represent the actual signal levels + * on the JAMMA pins (i.e. normally pulled up by resistors, shorted to ground + * when a button is pressed). + * + * @return Inverted logical OR of K573_JAMMAInputs flags + */ +uint32_t K573_GetJAMMAInputs(void); + +/** + * @brief Sets the 32 light outputs provided by the the analog and digital I/O + * boards to match the provided bitfield. K573_SetBoardType(IO_TYPE_ANALOG) or + * K573_SetBoardType(IO_TYPE_DIGITAL) must be called beforehand to set the I/O + * board type. + * + * @param lights Non-inverted logical OR of K573_Light flags + */ +void K573_SetLights(uint32_t lights); + +/** + * @brief Sets the installed I/O board type. Currently only IO_TYPE_ANALOG and + * IO_TYPE_DIGITAL are supported. + * + * @param type + */ +void K573_SetBoardType(K573_IOBoardType type); + +/** + * @brief Sends a command to the multiplexer PCB embedded into DDR stage units + * (if the system is a DDR cabinet) by bitbanging it through the light outputs. + * K573_SetBoardType(IO_TYPE_ANALOG) or K573_SetBoardType(IO_TYPE_DIGITAL) must + * be called beforehand to set the I/O board type. + * + * @param value + * @param length Number of bits to send (1-32) + */ +//void K573_DDRStageCommand(uint32_t value, uint32_t length); + +/** + * @brief Initializes the expansion port registers to enable System 573 I/O + * access. + */ +void K573_Init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/io/system573/main.c b/examples/io/system573/main.c index a06c4e5..64722d7 100644 --- a/examples/io/system573/main.c +++ b/examples/io/system573/main.c @@ -1,15 +1,14 @@ /* * PSn00bSDK Konami System 573 example - * (C) 2021 spicyjpeg - MPL licensed + * (C) 2022 spicyjpeg - MPL licensed * * This is a minimal example demonstrating how to target the Konami System 573 * using PSn00bSDK. The System 573 is a PS1-based arcade motherboard that * powered various Konami arcade games throughout the late 1990s, most notably * Dance Dance Revolution and other Bemani rhythm games. It came in several * configurations, with slightly different I/O connectors depending on the game - * and two optional add-on modules (known as the "analog I/O" and "digital I/O" - * boards respectively) providing light control outputs and, in the case of the - * digital I/O board, MP3 audio playback. + * and optional add-on boards providing extra features such as light control + * outputs or MP3 audio playback. * * Unlike other arcade systems based on PS1 hardware, the 573 is mostly * identical to a regular PS1, with almost all custom extensions mapped into @@ -62,60 +61,15 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <psxetc.h> #include <psxapi.h> #include <psxgpu.h> -#include <psxpad.h> - -/* Register definitions */ - -#define EXP1_ADDR *((volatile uint32_t *) 0x1f801000) -#define EXP1_CTRL *((volatile uint32_t *) 0x1f801008) - -#define K573_IN0 *((volatile uint16_t *) 0x1f400000) -#define K573_IN1_L *((volatile uint16_t *) 0x1f400004) -#define K573_IN1_H *((volatile uint16_t *) 0x1f400006) -#define K573_IN2 *((volatile uint16_t *) 0x1f400008) -#define K573_IN3_L *((volatile uint16_t *) 0x1f40000c) -#define K573_IN3_H *((volatile uint16_t *) 0x1f40000e) -#define K573_BANK *((volatile uint16_t *) 0x1f500000) -#define K573_WATCHDOG *((volatile uint16_t *) 0x1f5c0000) - -#define K573_IDE_CS0 ((volatile uint16_t *) 0x1f480000) -#define K573_IDE_CS1 ((volatile uint16_t *) 0x1f4c0000) -#define K573_RTC ((volatile uint16_t *) 0x1f620000) -#define K573_IO_BOARD ((volatile uint16_t *) 0x1f640000) - -typedef enum { - ANALOG_IO_LIGHTS0 = 0x20, - ANALOG_IO_LIGHTS1 = 0x22, - ANALOG_IO_LIGHTS2 = 0x24, - ANALOG_IO_LIGHTS3 = 0x26, - - // The digital I/O board has a lot more registers than these, but there - // seems to be no DIGITAL_IO_LIGHTS6 register. WTF - DIGITAL_IO_LIGHTS1 = 0x70, - DIGITAL_IO_LIGHTS0 = 0x71, - DIGITAL_IO_LIGHTS3 = 0x72, - DIGITAL_IO_LIGHTS7 = 0x73, - DIGITAL_IO_LIGHTS4 = 0x7d, - DIGITAL_IO_LIGHTS5 = 0x7e, - DIGITAL_IO_LIGHTS2 = 0x7f -} IO_BOARD_REG; - -// The 573's real-time clock chip is an M48T58, which behaves like a standard -// 8 KB battery-backed SRAM with a bunch of special registers. Official games -// store highscores and settings in RTC RAM. -typedef enum { - RTC_CTRL = 0x1ff8, - RTC_SECONDS = 0x1ff9, - RTC_MINUTES = 0x1ffa, - RTC_HOURS = 0x1ffb, - RTC_DAY_OF_WEEK = 0x1ffc, - RTC_DAY_OF_MONTH = 0x1ffd, - RTC_MONTH = 0x1ffe, - RTC_YEAR = 0x1fff -} RTC_REG; + +#include "k573io.h" + +const char *const IO_BOARD_TYPES[] = { + "ANALOG", + "DIGITAL" +}; #define btoi(x) ((((x) >> 4) & 0xf) * 10 + ((x) & 0xf)) @@ -179,89 +133,6 @@ void display(CONTEXT *ctx) { SetDispMask(1); } -/* Input polling utilities */ - -typedef struct { - uint8_t p1_joy, p1_btn; - uint8_t p2_joy, p2_btn; - uint8_t coin, dip_sw; -} JAMMAInputs; - -void get_jamma_inputs(JAMMAInputs *output) { - uint16_t in1l = K573_IN1_L; - uint16_t in1h = K573_IN1_H; - uint16_t in2 = K573_IN2; - uint16_t in3l = K573_IN3_L; - uint16_t in3h = K573_IN3_H; - uint8_t p1_btn, p2_btn, coin; - - // Rearrange the bits read from the input register into something that's - // easier to parse and display. Refer to MAME for information on what each - // bit in the IN* registers does. - p1_btn = ((in2 >> 15) & 0x0001); // Bit 0 = start button - p1_btn |= ((in2 >> 8) & 0x0007) << 1; // Bit 1-3 = buttons 1-3 - p1_btn |= ((in3l >> 8) & 0x0003) << 4; // Bit 4-5 = buttons 4-5 - p1_btn |= ((in3l >> 11) & 0x0001) << 6; // Bit 6 = button 6 - p2_btn = ((in2 >> 7) & 0x0001); // Bit 0 = start button - p2_btn |= ((in2 >> 4) & 0x0007) << 1; // Bit 1-3 = buttons 1-3 - p2_btn |= ((in3h >> 8) & 0x0003) << 4; // Bit 4-5 = buttons 4-5 - p2_btn |= ((in3h >> 11) & 0x0001) << 6; // Bit 6 = button 6 - coin = ((in1h >> 8) & 0x0003); // Bit 0-1 = coin switches - coin |= ((in1h >> 12) & 0x0001) << 2; // Bit 2 = service button - coin |= ((in3l >> 10) & 0x0001) << 3; // Bit 3 = test button - coin |= ((in1h >> 10) & 0x0003) << 4; // Bit 4-5 = PCMCIA cards - - output->p1_joy = (in2 >> 8) & 0x000f; - output->p1_btn = p1_btn; - output->p2_joy = in2 & 0x000f; - output->p2_btn = p2_btn; - output->coin = coin; - output->dip_sw = in1l & 0x000f; -} - -/* I/O board (light control) utilities */ - -// This function controls light outputs on analog I/O boards. -void set_lights_analog(uint32_t lights) { - uint32_t bits; - - bits = (lights & 0x01010101) << 7; // Lamp n*8+0 -> bit n*8+7 - bits |= (lights & 0x02020202) << 5; // Lamp n*8+1 -> bit n*8+6 - bits |= (lights & 0x04040404) >> 1; // Lamp n*8+2 -> bit n*8+1 - bits |= (lights & 0x08080808) >> 3; // Lamp n*8+3 -> bit n*8+0 - bits |= (lights & 0x10101010) << 1; // Lamp n*8+4 -> bit n*8+5 - bits |= (lights & 0x20202020) >> 1; // Lamp n*8+5 -> bit n*8+4 - bits |= (lights & 0x40404040) >> 3; // Lamp n*8+6 -> bit n*8+3 - bits |= (lights & 0x80808080) >> 5; // Lamp n*8+7 -> bit n*8+2 - - K573_IO_BOARD[ANALOG_IO_LIGHTS0] = (bits) & 0xff; - K573_IO_BOARD[ANALOG_IO_LIGHTS1] = (bits >> 8) & 0xff; - K573_IO_BOARD[ANALOG_IO_LIGHTS2] = (bits >> 16) & 0xff; - K573_IO_BOARD[ANALOG_IO_LIGHTS3] = (bits >> 24) & 0xff; -} - -// This function controls light outputs on digital I/O boards (i.e. the ones -// that include MP3 playback hardware in addition to the light control). -// TODO: test this on real hardware -- it might not work if lights are handled -// by the board's FPGA, which requires a binary blob... -void set_lights_digital(uint32_t lights) { - uint32_t bits; - - bits = (lights & 0x11111111); // Lamp n*4+0 -> bit n*4+0 - bits |= (lights & 0x22222222) << 1; // Lamp n*4+1 -> bit n*4+2 - bits |= (lights & 0x44444444) << 1; // Lamp n*4+2 -> bit n*4+3 - bits |= (lights & 0x88888888) >> 2; // Lamp n*4+3 -> bit n*4+1 - - K573_IO_BOARD[DIGITAL_IO_LIGHTS0] = ((bits) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS1] = ((bits >> 4) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS2] = ((bits >> 8) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS3] = ((bits >> 12) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS4] = ((bits >> 16) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS5] = ((bits >> 20) & 0xf) << 12; - //K573_IO_BOARD[DIGITAL_IO_LIGHTS6] = ((bits >> 24) & 0xf) << 12; - K573_IO_BOARD[DIGITAL_IO_LIGHTS7] = ((bits >> 28) & 0xf) << 12; -} - /* Main */ static CONTEXT ctx; @@ -270,101 +141,96 @@ static CONTEXT ctx; #define SHOW_ERROR(...) { SHOW_STATUS(__VA_ARGS__); while (1) __asm__("nop"); } int main(int argc, const char* argv[]) { - // Reinitialize the heap and relocate the stack to allow the 573's full 4 - // MB of RAM to be used. This isn't strictly required; executables designed - // for 2 MB of RAM will also run fine on the 573 (obviously). - // FIXME: this seems to be broken currently - //__asm__ volatile("li $sp, 0x803fffe0"); - //_mem_init(0x400000, 0x20000); - - EXP1_ADDR = 0x1f000000; - EXP1_CTRL = 0x24173f47; // 573 BIOS uses this value - K573_WATCHDOG = 0; - init_context(&ctx); + K573_Init(); - // Determine whether we are running on a 573 by fetching the version string - // from the BIOS. const char *const version = (const char *const) GetSystemInfo(0x02); //if (strncmp(version, "Konami OS", 9)) //SHOW_ERROR("ERROR: NOT RUNNING ON A SYSTEM 573!\n\n[%s]\n", version); uint32_t counter = 0; - uint8_t last_joystick = 0xff; - uint8_t last_buttons = 0xff; + uint32_t inputs = K573_GetJAMMAInputs(); + uint32_t last_inputs = 0xff; uint32_t current_light = 0; - uint32_t is_digital = 0; + + // DIP switch 1 is used to determine if an analog or digital I/O board is + // installed. + K573_IOBoardType io_type = (inputs & JAMMA_DIP1) + ? IO_TYPE_ANALOG + : IO_TYPE_DIGITAL; + + K573_SetBoardType(io_type); + K573_SetLights(1); while (1) { - FntPrint(-1, "COUNTER=%d\n", counter++); + inputs = K573_GetJAMMAInputs(); - JAMMAInputs inputs; - get_jamma_inputs(&inputs); + FntPrint(-1, "COUNTER=%d\n", counter++); FntPrint(-1, "\nJAMMA INPUTS:\n"); - FntPrint(-1, " P1 JOYSTICK =%04@\n", inputs.p1_joy); - FntPrint(-1, " P1 BUTTONS =%07@\n", inputs.p1_btn); - FntPrint(-1, " P2 JOYSTICK =%04@\n", inputs.p2_joy); - FntPrint(-1, " P2 BUTTONS =%07@\n", inputs.p2_btn); - FntPrint(-1, " COIN/SERVICE=%04@\n", inputs.coin & 0xf); - FntPrint(-1, " DIP SWITCHES=%04@\n", inputs.dip_sw); + FntPrint(-1, " IN2 =%016@\n", inputs & 0xffff); + FntPrint(-1, " IN3_L=%04@\n", (inputs >> 16) & 0x0f); + FntPrint(-1, " IN3_H=%04@\n", (inputs >> 20) & 0x0f); + FntPrint(-1, " IN1_H=%05@\n", (inputs >> 24) & 0x1f); FntPrint(-1, "\nCABINET LIGHTS:\n"); - FntPrint(-1, " BOARD=%s I/O\n", is_digital ? "DIGITAL" : "ANALOG"); - FntPrint(-1, " LIGHT=%d\n\n", current_light); - FntPrint(-1, " [START] CHANGE BOARD TYPE\n"); - FntPrint(-1, " [LEFT/RIGHT] SELECT LIGHT TO TEST\n"); + FntPrint(-1, " BOARD=%s\n", IO_BOARD_TYPES[io_type]); + FntPrint(-1, " LIGHT=%d\n", current_light); + FntPrint(-1, "\n [DIP SW1] CHANGE BOARD TYPE\n"); + FntPrint(-1, "\n [TEST SW] CHANGE ACTIVE LIGHT\n"); // Request the current date/time from the RTC and display it. - K573_RTC[RTC_CTRL] |= 0x40; + K573_RTC[RTC_REG_CTRL] |= 0x40; FntPrint(-1, "\nRTC:\n"); FntPrint( -1, " %02d-%02d-%02d %02d:%02d:%02d\n", - btoi(K573_RTC[RTC_YEAR]), - btoi(K573_RTC[RTC_MONTH]), - btoi(K573_RTC[RTC_DAY_OF_MONTH] & 0x3f), - btoi(K573_RTC[RTC_HOURS]), - btoi(K573_RTC[RTC_MINUTES]), - btoi(K573_RTC[RTC_SECONDS] & 0x7f) + btoi(K573_RTC[RTC_REG_YEAR]), + btoi(K573_RTC[RTC_REG_MONTH]), + btoi(K573_RTC[RTC_REG_DAY_OF_MONTH] & 0x3f), + btoi(K573_RTC[RTC_REG_HOURS]), + btoi(K573_RTC[RTC_REG_MINUTES]), + btoi(K573_RTC[RTC_REG_SECONDS] & 0x7f) ); FntPrint(-1, "\nSYSTEM:\n"); FntPrint(-1, " KERNEL=%s\n", version); - FntPrint(-1, " PCMCIA=%02@\n", inputs.coin >> 4); + FntPrint(-1, " DIP SW=%03@\n", inputs >> 29); + FntPrint(-1, " PCMCIA=%02@\n", (inputs >> 26) & 0x3); FntFlush(-1); display(&ctx); // Reset the watchdog. This must be done at least once per frame to // prevent the 573 from rebooting. - K573_WATCHDOG = 0; + K573_RESET_WATCHDOG(); - if (is_digital) - set_lights_digital(1 << current_light); - else - set_lights_analog(1 << current_light); - - // Handle inputs. - if ((last_joystick & 0x01) && !(inputs.p1_joy & 0x01)) // Left - current_light--; - if ((last_joystick & 0x02) && !(inputs.p1_joy & 0x02)) // Right - current_light++; - if ((last_buttons & 0x02) && !(inputs.p1_btn & 0x02)) // Button 1 - current_light--; - if ((last_buttons & 0x04) && !(inputs.p1_btn & 0x04)) // Button 2 + // Change the currently active light if the test button on the 573's + // front panel is pressed. DDR non-light outputs are skipped. + if ((last_inputs & JAMMA_TEST) && !(inputs & JAMMA_TEST)) { current_light++; - if ((last_buttons & 0x01) && !(inputs.p1_btn & 0x01)) { // Start - is_digital = !is_digital; - if (is_digital) - set_lights_analog(0); - else - set_lights_digital(0); + if ( + (current_light == 4) || // DDR_LIGHT_P1_MUX_DATA + (current_light == 7) || // DDR_LIGHT_P1_MUX_CLK + (current_light == 12) || // DDR_LIGHT_P2_MUX_DATA + (current_light == 15) // DDR_LIGHT_P2_MUX_CLK + ) current_light++; + + current_light %= 32; + K573_SetLights(1 << current_light); + } + + // if DIP switch 1 is toggled, change the I/O board type. + if ((last_inputs & JAMMA_DIP1) != (inputs & JAMMA_DIP1)) { + io_type = (inputs & JAMMA_DIP1) + ? IO_TYPE_ANALOG + : IO_TYPE_DIGITAL; + + K573_SetBoardType(io_type); + K573_SetLights(1 << current_light); } - current_light %= 32; - last_joystick = inputs.p1_joy; - last_buttons = inputs.p1_btn; + last_inputs = inputs; } return 0; |
