summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nubus/nubus_vikbw.cpp
blob: 89ac560752fa9fc270e3cc5f2dd000a3a57c4234 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// license:BSD-3-Clause
// copyright-holders:R. Belmont
/***************************************************************************

  Moniterm MacViking II 1024x768 fixed-resolution monochrome board

  https://wiki.preterhuman.net/Moniterm_MACVIKING_II

  VRAM from Fs040000 to Fs05FFFF (RAM test goes up to Fs065800 for some reason)
  Read from Fs000000 enables VBL, write to Fs000000 disables VBL
  Write to Fs080000 acks VBL

  Crystal (pixel clock) is 72 MHz.

  TODO: Actual raster parameters are unknown.  We've gone with the Apple 19"
  1024x768 monitor's htotal/vtotal but this used a custom monitor.  There are
  no register writes other than the IRQ enable/ack so the CRTC is a fixed
  state machine.

***************************************************************************/

#include "emu.h"
#include "emupal.h"
#include "nubus_vikbw.h"
#include "screen.h"

namespace {

static constexpr u32 VRAM_SIZE = 0x20000;       // 4x HM53461 VRAMs (64K x 4 bit)

class nubus_vikbw_device : public device_t,
						   public device_nubus_card_interface
{
public:
	// construction/destruction
	nubus_vikbw_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);

protected:
	nubus_vikbw_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);

	// device-level overrides
	virtual void device_start() override ATTR_COLD;
	virtual void device_reset() override ATTR_COLD;

	// optional information overrides
	virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
	virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;

private:
	u32 viking_ack_r();
	void viking_ack_w(u32 data);
	u32 viking_enable_r();
	void viking_disable_w(u32 data);

	u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);

	std::unique_ptr<u32[]> m_vram;
	u32 m_vbl_disable;
};

ROM_START( vikbw )
	ROM_REGION(0x2000, "vikingrom", 0)
	ROM_LOAD( "viking.bin",   0x000000, 0x002000, CRC(92cf04d1) SHA1(d08349edfc82a0bd5ea848e053e1712092308f74) )
ROM_END

void nubus_vikbw_device::device_add_mconfig(machine_config &config)
{
	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
	screen.set_screen_update(FUNC(nubus_vikbw_device::screen_update));
	screen.set_raw(72000000, 1324, 0, 1024, 803, 0, 768);
	screen.set_palette("palette");

	PALETTE(config, "palette", palette_device::MONOCHROME_INVERTED);
}

const tiny_rom_entry *nubus_vikbw_device::device_rom_region() const
{
	return ROM_NAME( vikbw );
}

nubus_vikbw_device::nubus_vikbw_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
	nubus_vikbw_device(mconfig, NUBUS_VIKBW, tag, owner, clock)
{
}

nubus_vikbw_device::nubus_vikbw_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
	device_t(mconfig, type, tag, owner, clock),
	device_nubus_card_interface(mconfig, *this),
	m_vbl_disable(0)
{
}

void nubus_vikbw_device::device_start()
{
	u32 slotspace;

	install_declaration_rom("vikingrom", true);

	slotspace = get_slotspace();

	m_vram = std::make_unique<u32[]>(VRAM_SIZE / sizeof(u32));
	install_bank(slotspace + 0x40000, slotspace + 0x40000 + VRAM_SIZE - 1, &m_vram[0]);
	install_bank(slotspace+0x940000, slotspace+0x940000+VRAM_SIZE-1, &m_vram[0]);

	nubus().install_device(slotspace, slotspace+3, read32smo_delegate(*this, FUNC(nubus_vikbw_device::viking_enable_r)), write32smo_delegate(*this, FUNC(nubus_vikbw_device::viking_disable_w)));
	nubus().install_device(slotspace+0x80000, slotspace+0x80000+3, read32smo_delegate(*this, FUNC(nubus_vikbw_device::viking_ack_r)), write32smo_delegate(*this, FUNC(nubus_vikbw_device::viking_ack_w)));

	save_item(NAME(m_vbl_disable));
	save_pointer(NAME(m_vram), VRAM_SIZE / sizeof(u32));
}

void nubus_vikbw_device::device_reset()
{
	m_vbl_disable = 1;
	std::fill_n(&m_vram[0], VRAM_SIZE / sizeof(u32), 0);
}

u32 nubus_vikbw_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
	if (!m_vbl_disable)
	{
		raise_slot_irq();
	}

	auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]);
	for (int y = 0; y < 768; y++)
	{
		u16 *scanline = &bitmap.pix(y);
		for (int x = 0; x < 1024/8; x++)
		{
			u8 const pixels = vram8[(y * 128) + x];

			*scanline++ = BIT(pixels, 7);
			*scanline++ = BIT(pixels, 6);
			*scanline++ = BIT(pixels, 5);
			*scanline++ = BIT(pixels, 4);
			*scanline++ = BIT(pixels, 3);
			*scanline++ = BIT(pixels, 2);
			*scanline++ = BIT(pixels, 1);
			*scanline++ = BIT(pixels, 0);
		}
	}

	return 0;
}

void nubus_vikbw_device::viking_ack_w(u32 data)
{
	lower_slot_irq();
}

u32 nubus_vikbw_device::viking_ack_r()
{
	return 0;
}

void nubus_vikbw_device::viking_disable_w(u32 data)
{
	m_vbl_disable = 1;
}

u32 nubus_vikbw_device::viking_enable_r()
{
	m_vbl_disable = 0;
	return 0;
}

}   // anonymous namespace

DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_VIKBW, device_nubus_card_interface, nubus_vikbw_device, "nb_vikbw", "Moniterm MacViking II video card")