/** ** Supermodel ** A Sega Model 3 Arcade Emulator. ** Copyright 2011 Bart Trzynadlowski, Nik Henson ** ** This file is part of Supermodel. ** ** Supermodel is free software: you can redistribute it and/or modify it under ** the terms of the GNU General Public License as published by the Free ** Software Foundation, either version 3 of the License, or (at your option) ** any later version. ** ** Supermodel is distributed in the hope that it will be useful, but WITHOUT ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ** more details. ** ** You should have received a copy of the GNU General Public License along ** with Supermodel. If not, see . **/ /* * DriveBoard.h * * Header for the CDriveBoard (force feedback emulation) class. */ #ifndef INCLUDED_DRIVEBOARD_H #define INCLUDED_DRIVEBOARD_H #include "Util/NewConfig.h" /* * CDriveBoard */ class CDriveBoard : public IBus { public: enum BoardType { Wheel=0, Joystick, SkiPad }; BoardType m_boardType; /* * IsAttached(void): * * Returns: * True if the drive board is "attached" and should be emulated, * otherwise false. */ bool IsAttached(void); /* * IsSimulated(void): * * Returns: * True if the drive board is being simulated rather than actually * emulated, otherwise false. */ bool IsSimulated(void); /* * GetDIPSwitches(dip1, dip2): * * Reads the two sets of DIP switches on the drive board. * * Parameters: * dip1 Reference of variable to store DIP switch 1 to. * dip2 DIP switch 2. */ void GetDIPSwitches(UINT8 &dip1, UINT8 &dip2); /* * SetDIPSwitches(dip1, dip2): * * Sets the DIP switches. * * Parameters: * dip1 DIP switch 1 value. * dip2 DIP switch 2 value. */ void SetDIPSwitches(UINT8 dip1, UINT8 dip2); /* * GetSteeringStrength(void): * * Returns: * Strength of the steering based on drive board DIP switches (1-8). */ unsigned GetSteeringStrength(void); /* * SetSteeringStrength(steeringStrength): * * Sets the steering strength (modifies the DIP switch setting). * * Parameters: * steeringStrength A value ranging from 1 to 8. */ void SetSteeringStrength(unsigned steeringStrength); /* * Get7SegDisplays(seg1Digit1, seg1Digit2, seg2Digit1, seg2Digit2): * * Reads the 7-segment displays. * * Parameters: * seg1Digit1 Reference of variable to store digit 1 of the first 7- * segment display to. * seg1Digit2 First display, second digit. * seg2Digit1 Second display, first digit. * seg2Digit2 Second display, second digit. */ void Get7SegDisplays(UINT8 &seg1Digit, UINT8 &seg1Digit2, UINT8 &seg2Digit1, UINT8 &seg2Digit2); /* * GetZ80(void): * * Returns: * The Z80 object. */ CZ80 *GetZ80(void); /* * SaveState(SaveState): * * Saves the drive board state. * * Parameters: * SaveState Block file to save state information to. */ void SaveState(CBlockFile *SaveState); /* * LoadState(SaveState): * * Restores the drive board state. * * Parameters: * SaveState Block file to load save state information from. */ void LoadState(CBlockFile *SaveState); /* * Init(romPtr): * * Initializes (and "attaches") the drive board. This should be called * before other members. * * Parameters: * romPtr Pointer to the drive board ROM (Z80 program). If this * is NULL, then the drive board will not be emulated. * * Returns: * FAIL if the drive board could not be initialized (prints own error * message), otherwise OKAY. If the drive board is not attached * because no ROM was passed to it, no error is generated and the * drive board is silently disabled (detached). */ bool Init(const UINT8 *romPtr); /* * AttachInputs(InputsPtr, gameInputFlags): * * Attaches inputs to the drive board (for access to the steering wheel * position). * * Parameters: * inputs Pointer to the input object. * gameInputFlags The current game's input flags. */ void AttachInputs(CInputs *inputs, unsigned gameInputFlags); void AttachOutputs(COutputs *outputs); /* * Reset(void): * * Resets the drive board. */ void Reset(void); /* * Read(): * * Reads data from the drive board. * * Returns: * Data read. */ UINT8 Read(void); /* * Write(data): * * Writes data to the drive board. * * Parameters: * data Data to send. */ void Write(UINT8 data); /* * RunFrame(void): * * Emulates a single frame's worth of time on the drive board. */ void RunFrame(void); /* * CDriveBoard(config): * ~CDriveBoard(): * * Constructor and destructor. Memory is freed by destructor. * * Paramters: * config Run-time configuration. The reference should be held because * this changes at run-time. */ CDriveBoard(const Util::Config::Node &config); ~CDriveBoard(void); /* * Read8(addr): * IORead8(portNum): * * Methods for reading from Z80's memory and IO space. Required by CBus. * * Parameters: * addr Address in memory (0-0xFFFF). * portNum Port address (0-255). * * Returns: * A byte of data from the address or port. */ UINT8 Read8(UINT32 addr); UINT8 IORead8(UINT32 portNum); /* * Write8(addr, data): * IORead8(portNum, data): * * Methods for writing to Z80's memory and IO space. Required by CBus. * * Parameters: * addr Address in memory (0-0xFFFF). * portNum Port address (0-255). * data Byte to write. */ void Write8(UINT32 addr, UINT8 data); void IOWrite8(UINT32 portNum, UINT8 data); private: const Util::Config::Node &m_config; bool m_attached; // True if drive board is attached bool m_tmpDisabled; // True if temporarily disabled by loading an incompatible save state bool m_simulated; // True if drive board should be simulated rather than emulated UINT8 m_dip1; // Value of DIP switch 1 UINT8 m_dip2; // Value of DIP switch 2 const UINT8* m_rom; // 32k ROM UINT8* m_ram; // 8k RAM CZ80 m_z80; // Z80 CPU @ 4MHz CInputs *m_inputs; unsigned m_inputFlags; COutputs *m_outputs; // Emulation state bool m_initialized; // True if drive board has finished initialization bool m_allowInterrupts; // True if drive board has enabled NMI interrupts UINT8 m_seg1Digit1; // Current value of left digit on 7-segment display 1 UINT8 m_seg1Digit2; // Current value of right digit on 7-segment display 1 UINT8 m_seg2Digit1; // Current value of left digit on 7-segment display 2 UINT8 m_seg2Digit2; // Current value of right digit on 7-segment display 2 UINT8 m_dataSent; // Last command sent by main board UINT8 m_dataReceived; // Data to send back to main board UINT16 m_adcPortRead; // ADC port currently reading from UINT8 m_adcPortBit; // Bit number currently reading on ADC port UINT8 m_port42Out; // Last value sent to Z80 I/O port 42 (encoder motor data) UINT8 m_port46Out; // Last value sent to Z80 I/O port 46 (encoder motor control) UINT8 m_port45Out; // Last value sent to Z80 I/O port 42 (up-down motor data) UINT8 m_prev42Out; // Previous value sent to Z80 I/O port 42 UINT8 m_prev46Out; // Previous value sent to Z80 I/O port 46 UINT8 m_prev45Out; // Previous value sent to Z80 I/O port 45 (up-down) UINT8 m_uncenterVal1; // First part of pending uncenter command UINT8 m_uncenterVal2; // Second part of pending uncenter command // Simulation state UINT8 m_initState; UINT8 m_statusFlags; UINT8 m_boardMode; UINT8 m_readMode; UINT8 m_wheelCenter; UINT8 m_cockpitCenter; UINT8 m_echoVal; // Feedback state INT8 m_lastConstForce; // Last constant force command sent INT8 m_lastConstForceY; // Last constant force command sent y axis UINT8 m_lastSelfCenter; // Last self center command sent UINT8 m_lastFriction; // Last friction command sent UINT8 m_lastVibrate; // Last vibrate command sent UINT8 SimulateRead(void); void SimulateWrite(UINT8 data); void SimulateFrame(void); void EmulateFrame(void); void ProcessEncoderCmd(void); void ProcessEncoderCmdJoystick(void); void SendStopAll(void); void SendConstantForce(INT8 val); void SendConstantForceY(INT8 val); void SendSelfCenter(UINT8 val); void SendFriction(UINT8 val); void SendVibrate(UINT8 val); uint8_t ReadADCChannel1(); uint8_t ReadADCChannel2(); uint8_t ReadADCChannel3(); uint8_t ReadADCChannel4(); }; #endif // INCLUDED_DRIVEBOARD_H