Skip to content

Commit

Permalink
Implement shift register mode "disabled"
Browse files Browse the repository at this point in the history
When disabled, the blank signal is controlled by the peripheral control
register. This was partially hooked up already, but was just missing the
last bit of actually tracking whether the shift mode was disabled or
not.

Fixes Sea Pup homebrew game.
  • Loading branch information
amaiorano committed Dec 23, 2023
1 parent 768c0b5 commit d24d4a7
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 21 deletions.
18 changes: 11 additions & 7 deletions libs/emulator/include/emulator/ShiftRegister.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,31 @@

#include "core/Base.h"

enum class ShiftRegisterMode {
// There are actually more modes, but I think Vectrex only uses these ones
Disabled,
ShiftOutUnder02,
};


// The VIA's shift register, mainly responsible for driving the drawing of line patterns. It can be
// loaded with an 8 bit mask that represents the pattern to be drawn, and although it's called a
// "shift" register, it actually rotates its values so the pattern will repeat.
class ShiftRegister {
public:
void SetMode(ShiftRegisterMode mode) { m_mode = mode; }
ShiftRegisterMode Mode() const { return m_mode; }

void SetValue(uint8_t value);
uint8_t ReadValue() const;
bool CB2Active() const { return m_cb2Active; }
bool Enabled() const {
// For now, always return true as it seems the shift register isn't disabled by games on
// Vectrex. Also, am not sure exactly how to control the enabled state of the shift
// register; I believe it may be controlled by bit 4 of the VIA's auxiliary control register
// ($B).
return true;
}
void Update(cycles_t cycles);

void SetInterruptFlag(bool enabled) { m_interruptFlag = enabled; }
bool InterruptFlag() const { return m_interruptFlag; }

private:
ShiftRegisterMode m_mode = ShiftRegisterMode::Disabled;
uint8_t m_value = 0;
mutable int m_shiftCyclesLeft = 0;
bool m_cb2Active = false;
Expand Down
24 changes: 10 additions & 14 deletions libs/emulator/src/Via.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@
#include "emulator/MemoryMap.h"

namespace {
enum class ShiftRegisterMode {
// There are actually many more modes, but I think Vectrex only uses one
ShiftOutUnder02
};

namespace Register {
enum Type {
PortB = 0x0,
Expand Down Expand Up @@ -51,10 +46,14 @@ namespace {
inline ShiftRegisterMode GetShiftRegisterMode(uint8_t auxCntrl) {
uint8_t result =
ReadBitsWithShift(auxCntrl, ShiftRegisterModeMask, ShiftRegisterModeShift);
if (result != 0b110) {
ErrorHandler::Unsupported(
"ShiftRegisterMode expected to only support ShiftOutUnder02\n");
switch (result) {
case 0:
return ShiftRegisterMode::Disabled;
case 0b110:
return ShiftRegisterMode::ShiftOutUnder02;
}
ErrorHandler::Unsupported(
"Unexpected ShiftRegisterMode: 0x%X, forcing to ShiftOutUnder02\n", result);
return ShiftRegisterMode::ShiftOutUnder02;
}

Expand Down Expand Up @@ -209,8 +208,7 @@ void Via::DoSync(cycles_t cycles, const Input& input, RenderContext& renderConte
m_shiftRegister.Update(cycles);

// Shift register's CB2 line drives /BLANK
//@TODO: check some flag on the shift register to know whether it's active
if (m_shiftRegister.Enabled()) {
if (m_shiftRegister.Mode() == ShiftRegisterMode::ShiftOutUnder02) {
m_screen.SetBlankEnabled(m_shiftRegister.CB2Active());
}

Expand Down Expand Up @@ -425,9 +423,7 @@ void Via::Write(uint16_t address, uint8_t value) {
break;

case Register::AuxCntl: {
// For now just read the shift register mode, which will assert if it's invalid/unexpected
auto shiftRegisterMode = AuxCntl::GetShiftRegisterMode(value);
(void)shiftRegisterMode;
m_shiftRegister.SetMode(AuxCntl::GetShiftRegisterMode(value));

ASSERT_MSG(AuxCntl::GetTimer1Mode(value) == TimerMode::OneShot,
"t1 assumed always on one-shot mode");
Expand All @@ -450,7 +446,7 @@ void Via::Write(uint16_t address, uint8_t value) {
"Top 2 bits should always be 1 (right?)");

m_periphCntl = value;
if (!m_shiftRegister.Enabled()) {
if (m_shiftRegister.Mode() == ShiftRegisterMode::Disabled) {
m_screen.SetBlankEnabled(PeriphCntl::IsBlankEnabled(m_periphCntl));
}
} break;
Expand Down

0 comments on commit d24d4a7

Please sign in to comment.