summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/decsfb.cpp
blob: 166cc98f62b6e6bbd44fbf35db8dea29cbe41704 (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
171
172
173
174
175
// license:BSD-3-Clause
// copyright-holders:R. Belmont

/*
 * An emulation of the Digital Equipment Corporation SFB "Smart Frame Buffer" chip
 *
 * Used in:
 *
 *   Accelerated TURBOChannel video cards for DECstations and AlphaStations
 *   On-board on some DECstations
 *   On-board on many AlphaStations
 *
 * Sources:
 *
 * http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-93-1.pdf
 *
 */

#include "emu.h"
#include "decsfb.h"

#define MODE_SIMPLE     0
#define MODE_OPAQUESTIPPLE  1
#define MODE_OPAQUELINE     2
#define MODE_TRANSPARENTSTIPPLE 5
#define MODE_TRANSPARENTLINE    6
#define MODE_COPY       7

#define LOG_GENERAL (1U << 0)
#define LOG_REG     (1U << 1)
#define LOG_IRQ     (1U << 2)

//#define VERBOSE (LOG_GENERAL|LOG_REG||LOG_IRQ)

#include "logmacro.h"

DEFINE_DEVICE_TYPE(DECSFB, decsfb_device, "decsfb", "Digital Equipment Corporation Smart Frame Buffer")

decsfb_device::decsfb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, DECSFB, tag, owner, clock),
	m_int_cb(*this)
{
}

void decsfb_device::device_start()
{
	m_int_cb.resolve_safe();

	save_item(NAME(m_vram));
	save_item(NAME(m_regs));
	save_item(NAME(m_copy_src));
}

void decsfb_device::device_reset()
{
	m_copy_src = 1;
}

/*
    0x100000 copy register 0
    0x100004 copy register 1
    0x100008 copy register 2
    0x10000C copy register 3
    0x100010 copy register 4
    0x100014 copy register 5
    0x100018 copy register 6
    0x10001C copy register 7
    0x100020 foreground register
    0x100024 background register
    0x100028 plane mask
    0x10002C pixel mask
    0x100030 cxt mode
    0x100034 boolean operation
    0x100038 pixel shift
    0x10003C line address
    0x100040 bresh 1
    0x100044 bresh 2
    0x100048 bresh 3
    0x10004C bresh continue
    0x100050 deep register
    0x100054 start register
    0x100058 Clear Interrupt
    0x10005C reserved 2
    0x100060 refresh count
    0x100064 video horiz
    0x100068 video vertical
    0x10006C refresh base
    0x100070 video valid
    0x100074 Interrupt Enable
*/

READ32_MEMBER(decsfb_device::read)
{
	return m_regs[offset];
}

WRITE32_MEMBER(decsfb_device::write)
{
	COMBINE_DATA(&m_regs[offset]);

	if ((offset == (0x30/4)) && (data = 7))
	{
		m_copy_src = 1;
	}
}

READ32_MEMBER(decsfb_device::vram_r)
{
	return m_vram[offset];
}

WRITE32_MEMBER(decsfb_device::vram_w)
{
	switch (m_regs[0x30/4])
	{
		case MODE_SIMPLE:   // simple
			COMBINE_DATA(&m_vram[offset]);
			break;

		case MODE_TRANSPARENTSTIPPLE:
			{
				uint8_t *pVRAM = (uint8_t *)&m_vram[offset];
				uint8_t fgs[4];

				fgs[0] = m_regs[0x20/4] >> 24;
				fgs[1] = (m_regs[0x20/4] >> 16) & 0xff;
				fgs[2] = (m_regs[0x20/4] >> 8) & 0xff;
				fgs[3] = m_regs[0x20/4] & 0xff;
				for (int x = 0; x < 32; x++)
				{
					if (data & (1<<(31-x)))
					{
						pVRAM[x] = fgs[x & 3];
					}
				}
			}
			break;

		case MODE_COPY:
			{
				uint8_t *pVRAM = (uint8_t *)&m_vram[offset];
				uint8_t *pBuffer = (uint8_t *)&m_regs[0];    // first 8 32-bit regs are the copy buffer

				if (m_copy_src)
				{
					m_copy_src = 0;

					for (int x = 0; x < 32; x++)
					{
						if (data & (1<<(31-x)))
						{
							pBuffer[x] = pVRAM[x];
						}
					}
				}
				else
				{
					m_copy_src = 1;

					for (int x = 0; x < 32; x++)
					{
						if (data & (1<<(31-x)))
						{
							pVRAM[x] = pBuffer[x];
						}
					}
				}
			}
			break;

		default:
			logerror("SFB: Unsupported VRAM write %08x (mask %08x) at %08x in mode %x\n", data, mem_mask, offset<<2, m_regs[0x30/4]);
			break;
	}
}