fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/arch/macplus/video.c *
7 * Created: 2007-04-16 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2007-2012 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include "main.h"
24#include "video.h"
25
26#include <stdlib.h>
27#include <string.h>
28
29
30#define MAC_VIDEO_PFREQ 15667200
31
32
33int mac_video_init (mac_video_t *mv, unsigned w, unsigned h)
34{
35 mv->vbuf = NULL;
36 mv->vbuf_addr = 0;
37 mv->vbuf_size = 0;
38 mv->dirty = 1;
39 mv->trm = NULL;
40
41 mv->w = w;
42 mv->h = h;
43
44 mv->hfreq = MAC_VIDEO_PFREQ / (w + 192);
45 mv->vfreq = mv->hfreq / (h + 28);
46 mv->vb1 = ((unsigned long)h * (unsigned long)(w + 192) * 7833600) /
47 MAC_VIDEO_PFREQ;
48 mv->vb2 = ((unsigned long)(h + 28) * (unsigned long)(w + 192) *
49 7833600) / MAC_VIDEO_PFREQ;
50
51 mv->force = 0;
52
53 mv->cmp_cnt = 8;
54
55 mv->vcmp = malloc ((unsigned long) ((mv->w + 7) / 8) * mv->h);
56
57 if (mv->vcmp == NULL) {
58 return (1);
59 }
60
61 mv->rgb = malloc (3UL * (unsigned long) w * mv->cmp_cnt);
62
63 if (mv->rgb == NULL) {
64 return (1);
65 }
66
67 mv->brightness = 255;
68
69 mv->col0[0] = 0;
70 mv->col0[1] = 0;
71 mv->col0[2] = 0;
72
73 mv->col1[0] = 0xff;
74 mv->col1[1] = 0xff;
75 mv->col1[2] = 0xff;
76
77 mv->clk = 0;
78
79 mv->vbi_val = 0;
80 mv->vbi_ext = NULL;
81 mv->set_vbi = NULL;
82
83 return (0);
84}
85
86mac_video_t *mac_video_new (unsigned w, unsigned h)
87{
88 mac_video_t *mv;
89
90 mv = malloc (sizeof (mac_video_t));
91
92 if (mv == NULL) {
93 return (NULL);
94 }
95
96 if (mac_video_init (mv, w, h)) {
97 free (mv);
98 return (NULL);
99 }
100
101 return (mv);
102}
103
104void mac_video_free (mac_video_t *mv)
105{
106}
107
108void mac_video_del (mac_video_t *mv)
109{
110 if (mv != NULL) {
111 mac_video_free (mv);
112 free (mv);
113 }
114}
115
116void mac_video_set_vbi_fct (mac_video_t *mv, void *ext, void *fct)
117{
118 mv->vbi_ext = ext;
119 mv->set_vbi = fct;
120}
121
122void mac_video_set_vbuf (mac_video_t *mv, const unsigned char *vbuf)
123{
124 mv->vbuf = vbuf;
125}
126
127void mac_video_set_vbuf_addr (mac_video_t *mv, unsigned long addr, unsigned long size)
128{
129 mv->vbuf_addr = addr;
130 mv->vbuf_size = size;
131 mv->dirty = 1;
132}
133
134void mac_video_set_dirty (mac_video_t *mv)
135{
136 mv->dirty = 1;
137}
138
139void mac_video_set_terminal (mac_video_t *mv, terminal_t *trm)
140{
141 mv->trm = trm;
142
143 if (mv->trm != NULL) {
144 trm_open (mv->trm, mv->w, mv->h);
145 }
146}
147
148void mac_video_set_color (mac_video_t *mv, unsigned long col0, unsigned long col1)
149{
150 unsigned i;
151
152 for (i = 0; i < 3; i++) {
153 mv->col0[i] = (col0 >> (8 * (2 - i))) & 0xff;
154 mv->col1[i] = (col1 >> (8 * (2 - i))) & 0xff;
155 }
156
157 mv->force = 1;
158}
159
160void mac_video_set_brightness (mac_video_t *mv, unsigned val)
161{
162 if (val > 255) {
163 val = 255;
164 }
165
166 if (mv->brightness != val) {
167 mv->force = 1;
168 mv->brightness = val;
169 }
170}
171
172static
173void mac_video_set_vbi (mac_video_t *mv, unsigned char val)
174{
175 if (mv->vbi_val == val) {
176 return;
177 }
178
179 mv->vbi_val = val;
180
181 if (mv->set_vbi != NULL) {
182 mv->set_vbi (mv->vbi_ext, val);
183 }
184}
185
186static
187void mac_video_update (mac_video_t *mv)
188{
189 unsigned y;
190 unsigned i, j;
191 unsigned k, n;
192 const unsigned char *src;
193 unsigned char *dst, *rgb;
194 unsigned char col0[3], col1[3];
195
196 if (mv->trm == NULL) {
197 return;
198 }
199
200 if (mv->vbuf == NULL) {
201 return;
202 }
203
204 if (!mv->dirty && !mv->force) {
205 return;
206 }
207
208 for (i = 0; i < 3; i++) {
209 col0[i] = (mv->brightness * mv->col0[i]) / 255;
210 col1[i] = (mv->brightness * mv->col1[i]) / 255;
211 }
212
213 trm_set_size (mv->trm, mv->w, mv->h);
214
215 src = mv->vbuf;
216 dst = mv->vcmp;
217 rgb = mv->rgb;
218
219 y = 0;
220 while (y < mv->h) {
221 n = mv->h - y;
222
223 if (n > mv->cmp_cnt) {
224 n = mv->cmp_cnt;
225 }
226
227 k = n * ((mv->w + 7) / 8);
228
229 if (mv->force || (memcmp (dst, src, k) != 0)) {
230 memcpy (dst, src, k);
231
232 j = 0;
233 for (i = 0; i < (8 * k); i++) {
234 if (dst[i >> 3] & (0x80 >> (i & 7))) {
235 rgb[j + 0] = col0[0];
236 rgb[j + 1] = col0[1];
237 rgb[j + 2] = col0[2];
238 }
239 else {
240 rgb[j + 0] = col1[0];
241 rgb[j + 1] = col1[1];
242 rgb[j + 2] = col1[2];
243 }
244
245 j += 3;
246 }
247
248 trm_set_lines (mv->trm, rgb, y, n);
249 }
250
251 src += k;
252 dst += k;
253
254 y += n;
255 }
256
257 mv->force = 0;
258 mv->dirty = 0;
259
260 trm_update (mv->trm);
261}
262
263void mac_video_redraw (mac_video_t *mv)
264{
265 mac_video_update (mv);
266}
267
268void mac_video_clock (mac_video_t *mv, unsigned long n)
269{
270 unsigned long old;
271
272 old = mv->clk;
273
274 mv->clk += n;
275
276 if (mv->clk < mv->vb1) {
277 return;
278 }
279
280 if (old < mv->vb1) {
281 /* vbl start */
282 mac_video_update (mv);
283 mac_video_set_vbi (mv, 1);
284 }
285
286 if (mv->clk >= mv->vb2) {
287 mac_video_set_vbi (mv, 0);
288
289 mv->clk -= mv->vb2;
290 }
291}