fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 291 lines 5.7 kB view raw
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}