summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/video/dgn_beta.c
blob: 421c3aa1563689a8b8a5a521cdedeed9d66e3060 (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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/*
    video/dgn_beta.c

The Dragon Beta uses a 68B45 for it's display generation, this is used in the
conventional wat with a character generator ROM in the two text modes, which are
standard 40x25 and 80x25. In adition to the 6845 there is some TTL logic which
provides colour and attributes. In text modes the video ram is organised as pairs
of character and attribute, in alternate bytes.

The attributes decode as follows :-

    7-6-5-4-3-2-1-0
    f-u-F-F-F-B-B-B

    f=flash
    u=underline

    FFF = foreground colour
    BBB = bakcground colour

        000 black
        001 red
        010 green
        011 yellow
        100 blue
        101 magenta
        110 cyan
        111 white

    If flash is true, foreground and background colours will be exchanged.

It is interesting to note that the 6845 uses 16 bit wide access to the ram, in contrast
to the 8 bit accesses from the CPUs, this allows each increment of the MA lines to move
2 bytes at a time, and therefore feed both the character rom and the attribute decode
circuit simultaniously.

The RAM addresses are made up of two parts, the MA0..13 from the 6845, plus two output
lines from the 6821 PIA, I28, the lines are BP6 and PB7, with PB7 being the most
significant. This effectivly allows the 6845 access to the first 128K of memory, as there
are 16 address lines, accessing a 16 bit wide memory.

The relationship between how the cpu sees the RAM, and the way the 6845 sees it is simply
CPU addr=2x6845 addr. So for the default video address of $1F000, the CPU sees this as
being at $1F000 (after DAT trasnlation). The 6845 is programmed to start it's MA lines
counting at $3800, plus A14 and A15 being supplied by PB6 and PB7 from I28, gives an address
of $F800, which is the same as $1F000 / 2.

I am currently at this time not sure of how any of the graphics modes, work, this will need
further investigation.

However the modes supported are :-

Text Modes
        width   height  colours
        40  25  8
        80  25  8
Graphics modes
        320 256 4
        320 256 16
        640 512 4
        640 256 4**
        640 512 2

Looking at the parts of the circuit sheet that I have seen it looks like the graphics modes
are driven using a combination of the 6845 MA and RA lines to address more than 64K or memory
which is needed for some of the modes above (specifically, 640x512x4, which needs 80K).

2006-11-30, Text mode is almost completely implemented, in both 40 and 80 column modes.
I have made a start on implementing the graphics modes of the beta, drawing from technical
documents, from the project, this is still a work in progress. I have however managed to get
it to display a distorted graphical image, so I know I am going in the correct direction !

** 2006-12-05, this mode is not documented in any of the printed documentation, however it
is supported and displayed by the graphics test rom, it is basically the 640x512x4 mode with
half the number of vertical lines, and in non-interlaced mode.

It seems that the 640x512 modes operate the 6845 in interlaced mode, just how this affects
the access to the video memory is unclear to me at the moment.

*/

#include "emu.h"
#include "includes/dgn_beta.h"

/* GCtrl bitmasks, infered from bits of Beta schematic */
#define GCtrlWI     0x01
#define GCtrlSWChar 0x02    /* Character set select */
#define GCtrlHiLo   0x04    /* Hi/Lo res graphics, Hi=1, Lo=0 */
#define GCtrlChrGfx 0x08    /* Character=1 / Graphics=0 */
#define GCtrlControl    0x10    /* Control bit, sets direct drive mode */
#define GCtrlFS     0x20    /* labeled F/S, not yet sure of function Fast or Slow scan ? */
#define GCtrlAddrLines  0xC0    /* Top two address lines for text mode */

#define IsTextMode  (state->m_GCtrl & GCtrlChrGfx) ? 1 : 0                  // Is this text mode ?
#define IsGfx16     ((~state->m_GCtrl & GCtrlChrGfx) && (~state->m_GCtrl & GCtrlControl)) ? 1 : 0   // is this 320x256x16bpp mode
#define IsGfx2      ((state->m_GCtrl & GCtrlHiLo) && (~state->m_GCtrl & GCtrlFS)) ? 1 : 0       // Is this a 2 colour mode
#define SWChar      (state->m_GCtrl & GCtrlSWChar)>>1                   // Swchar bit

static MC6845_UPDATE_ROW( dgnbeta_update_row )
{
	dgn_beta_state *state = device->machine().driver_data<dgn_beta_state>();
	const rgb_t *palette = palette_entry_list_raw(bitmap.palette());
	UINT8 *videoram = state->m_videoram;
	UINT32  *p = &bitmap.pix32(y);
	int i;
	if(IsTextMode)
	{
		UINT8 *chr_gen = state->memregion("gfx1")->base();
		for ( i = 0; i < x_count; i++ )
		{
			UINT32 offset = ( ( ma + i ) | ((state->m_GCtrl & GCtrlAddrLines)<<8)) << 1;
			UINT8 chr = videoram[ offset ];
			UINT8 attr = videoram[ offset +1 ];

			/* Extract non-colour attributes, in character set 1, undeline is used */
			/* We will extract the colours below, when we have decoded inverse */
			/* to indicate a double height character */
			int UnderLine=(attr & 0x40) >> 6; // Underline active
			int FlashChar=(attr & 0x80) >> 7; // Flashing char

			// underline is active for character set 0, on character row 9
			int ULActive=(UnderLine && (ra==9) && ~SWChar);

			/* Invert forground and background if flashing char and flash acive */
			int Invert=(FlashChar & state->m_FlashBit);

			/* Underline inverts flash */
			if (ULActive)
				Invert=~Invert;

			/* Cursor on also inverts */
			if (i == cursor_x)
				Invert=~Invert;

			UINT16 fg = 0;
			UINT16 bg = 0;

			/* Invert colours if invert is true */
			if(!Invert)
			{
				fg  = (attr & 0x38) >> 3;
				bg  = (attr & 0x07);
			}
			else
			{
				bg  = (attr & 0x38) >> 3;
				fg  = (attr & 0x07);
			}



			UINT8 data = chr_gen[ chr * 16 + ra ];

			*p = palette[( data & 0x80 ) ? fg : bg]; p++;
			*p = palette[( data & 0x80 ) ? fg : bg]; p++;
			*p = palette[( data & 0x40 ) ? fg : bg]; p++;
			*p = palette[( data & 0x40 ) ? fg : bg]; p++;
			*p = palette[( data & 0x20 ) ? fg : bg]; p++;
			*p = palette[( data & 0x20 ) ? fg : bg]; p++;
			*p = palette[( data & 0x10 ) ? fg : bg]; p++;
			*p = palette[( data & 0x10 ) ? fg : bg]; p++;
			*p = palette[( data & 0x08 ) ? fg : bg]; p++;
			*p = palette[( data & 0x08 ) ? fg : bg]; p++;
			*p = palette[( data & 0x04 ) ? fg : bg]; p++;
			*p = palette[( data & 0x04 ) ? fg : bg]; p++;
			*p = palette[( data & 0x02 ) ? fg : bg]; p++;
			*p = palette[( data & 0x02 ) ? fg : bg]; p++;
			*p = palette[( data & 0x01 ) ? fg : bg]; p++;
			*p = palette[( data & 0x01 ) ? fg : bg]; p++;
		}

	}
	else
	{
		for ( i = 0; i < x_count; i++ )
		{
			UINT32 offset = ((((ma + i ) & 0x1FFF) << 3) | (ra & 0x07)) << 1;

			UINT8 Lo = videoram[ offset ];
			UINT8 Hi = videoram[ offset +1 ];
			UINT16 Word = (Hi<<8) | Lo;
			int Red;
			int Green;
			int Blue;
			int Intense;
			int Colour;
			int Dot;

			/* If contol is low then we are plotting 4 bit per pixel, 16 colour mode */
			/* This directly drives the colour output lines, from the pixel value */
			/* If Control is high, then we lookup the colour from the LS670 4x4 bit */
			/* palate register */
			if (IsGfx16)
			{
				Intense =(Lo & 0x0F);
				Red =(Lo & 0xF0)>>4;
				Green   =(Hi & 0x0F);
				Blue    =(Hi & 0xF0)>>4;
				Colour=((Intense&0x08) | (Red&0x08)>>1) | ((Green&0x08)>>2) | ((Blue&0x08)>>3);

				for (Dot=0;Dot<4;Dot++)
				{
					*p = palette[Colour]; p++;
					*p = palette[Colour]; p++;
					*p = palette[Colour]; p++;
					*p = palette[Colour]; p++;

					Intense =Intense<<1;
					Red =Red<<1;
					Green   =Green<<1;
					Blue    =Blue<<1;
				}
			}
			else if (IsGfx2)
			{
				for (Dot=0;Dot<16;Dot=Dot+1)
				{
					Colour=state->m_ColourRAM[((Word&0x8000)>>15)];

					*p = palette[Colour]; p++;

					Hi=(Word&0x8000) >> 15;
					Word=((Word<<1)&0xFFFE) | Hi;
				}
			}
			else
			{
				for (Dot=0;Dot<8;Dot++)
				{
					Colour=state->m_ColourRAM[((Word&0x8000)>>14) | ((Word&0x80)>>7)];
					*p = palette[Colour]; p++;
					*p = palette[Colour]; p++;

					Hi=(Word&0x8000) >> 15;
					Word=((Word<<1)&0xFFFE) | Hi;
				}
			}
		}
	}

}

WRITE_LINE_MEMBER(dgn_beta_state::dgnbeta_vsync_changed)
{
	m_beta_VSync=state;
	if (!m_beta_VSync)
	{
		m_FlashCount++;
		if(m_FlashCount==10)
		{
			m_FlashCount=0;         // Reset counter
			m_FlashBit=(!m_FlashBit) & 0x01;    // Invert flash bit.
		}
	}

	dgn_beta_frame_interrupt(machine(), state);
}

const mc6845_interface dgnbeta_crtc6845_interface =
{
	"screen",
	16 /*?*/,
	NULL,
	dgnbeta_update_row,
	NULL,
	DEVCB_NULL,
	DEVCB_NULL,
	DEVCB_NULL,
	DEVCB_DRIVER_LINE_MEMBER(dgn_beta_state,dgnbeta_vsync_changed),
	NULL
};


/* Set video control register from I28 port B, the control register is laid out as */
/* follows :-                                                                      */
/*  bit function                               */
/*  0   WI, unknown                            */
/*  1   Character set select, drives A12 of character rom in text mode     */
/*  2   High (1) or Low(0) resolution if in graphics mode.         */
/*  3   Text (1) or Graphics(0) mode                       */
/*  4   Control bit, Selects between colour palate and drirect drive       */
/*  5   F/S bit, 1=80 bytes/line, 0=40bytes/line               */
/*  6   Effective A14, to ram, in text mode                    */
/*  7   Effective A15, to ram, in text mode                */
/* the top two address lines for the video ram, are supplied by the BB6 and PB7 on */
/* 6821-I28, this allows the 6845 to access the full 64K address range, however    */
/* since the ram data is addressed as a 16bit wide unit, this allows the 6845      */
/* access to the first 128K or ram.                                                */
void dgnbeta_vid_set_gctrl(running_machine &machine, int data)
{
	dgn_beta_state *state = machine.driver_data<dgn_beta_state>();
	state->m_GCtrl=data;
}


/* Write handler for colour, pallate ram */
WRITE8_MEMBER(dgn_beta_state::dgnbeta_colour_ram_w)
{
	m_ColourRAM[offset]=data&0x0f;          /* Colour ram 4 bit and write only to CPU */
}