fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 366 lines 6.8 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/chipset/e6845.c * 7 * Created: 2017-08-07 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2017-2022 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 <stdlib.h> 24#include <stdio.h> 25 26#include "e6845.h" 27 28 29#ifndef DEBUG_CRTC 30#define DEBUG_CRTC 0 31#endif 32 33 34void e6845_init (e6845_t *crt) 35{ 36 unsigned i; 37 38 crt->ccol = 0; 39 crt->crow = 0; 40 crt->frame = 0; 41 crt->ma = 0; 42 crt->ra = 0; 43 crt->vsync_cnt = 0; 44 crt->index = 0; 45 46 for (i = 0; i < E6845_REG_CNT; i++) { 47 crt->reg[i] = 0; 48 } 49 50 crt->hsync_ext = NULL; 51 crt->hsync_fct = NULL; 52 53 crt->vsync_ext = NULL; 54 crt->vsync_fct = NULL; 55} 56 57void e6845_free (e6845_t *crt) 58{ 59} 60 61void e6845_set_hsync_fct (e6845_t *crt, void *ext, void *fct) 62{ 63 crt->hsync_ext = ext; 64 crt->hsync_fct = fct; 65} 66 67void e6845_set_vsync_fct (e6845_t *crt, void *ext, void *fct) 68{ 69 crt->vsync_ext = ext; 70 crt->vsync_fct = fct; 71} 72 73unsigned e6845_get_start_address (const e6845_t *crt) 74{ 75 unsigned val; 76 77 val = crt->reg[E6845_REG_AH]; 78 val = (val << 8) | crt->reg[E6845_REG_AL]; 79 80 return (val & 0x3fff); 81} 82 83unsigned e6845_get_cursor_address (const e6845_t *crt) 84{ 85 unsigned val; 86 87 val = crt->reg[E6845_REG_CH]; 88 val = (val << 8) | crt->reg[E6845_REG_CL]; 89 90 return (val & 0x3fff); 91} 92 93unsigned e6845_get_cursor_mask (e6845_t *crt, int blink) 94{ 95 unsigned mask; 96 97 mask = 0; 98 99 switch ((crt->reg[E6845_REG_CS] >> 5) & 3) { 100 case 0: 101 /* non-blink */ 102 blink = 0; 103 break; 104 105 case 1: 106 /* non-display */ 107 return (0); 108 109 case 2: 110 /* blink at 1/16 field rate */ 111 mask = 16; 112 break; 113 114 case 3: 115 /* blink 1/32 field rate */ 116 mask = 32; 117 break; 118 } 119 120 if (blink) { 121 if (crt->frame & mask) { 122 return (0); 123 } 124 } 125 126 if (crt->ra < (crt->reg[E6845_REG_CS] & 0x1f)) { 127 return (0); 128 } 129 130 if (crt->ra > (crt->reg[E6845_REG_CE] & 0x1f)) { 131 return (0); 132 } 133 134 return (~0U); 135} 136 137unsigned e6845_get_vtl (const e6845_t *crt) 138{ 139 unsigned val; 140 141 val = (crt->reg[E6845_REG_ML] & 0x1f) + 1; 142 val *= (crt->reg[E6845_REG_VT] & 0x7f) + 1; 143 val += crt->reg[E6845_REG_VA] & 0x1f; 144 145 return (val); 146} 147 148unsigned e6845_get_vdl (const e6845_t *crt) 149{ 150 unsigned val; 151 152 val = (crt->reg[E6845_REG_ML] & 0x1f) + 1; 153 val *= crt->reg[E6845_REG_VD] & 0x7f; 154 155 return (val); 156} 157 158unsigned e6845_get_vsl (const e6845_t *crt) 159{ 160 unsigned val; 161 162 val = (crt->reg[E6845_REG_ML] & 0x1f) + 1; 163 val *= crt->reg[E6845_REG_VS] & 0x7f; 164 165 return (val); 166} 167 168int e6845_get_hde (const e6845_t *crt) 169{ 170 if (crt->ccol < crt->reg[E6845_REG_HD]) { 171 return (1); 172 } 173 174 return (0); 175} 176 177int e6845_get_vde (const e6845_t *crt) 178{ 179 if (crt->crow < (crt->reg[E6845_REG_VD] & 0x7f)) { 180 return (1); 181 } 182 183 return (0); 184} 185 186int e6845_get_de (const e6845_t *crt) 187{ 188 if (crt->crow >= (crt->reg[E6845_REG_VD] & 0x7f)) { 189 return (0); 190 } 191 192 if (crt->ccol >= crt->reg[E6845_REG_HD]) { 193 return (0); 194 } 195 196 return (1); 197} 198 199void e6845_set_pen (e6845_t *crt) 200{ 201 unsigned addr; 202 203 addr = (crt->ma + crt->ccol) & 0x3fff; 204 205 crt->reg[E6845_REG_LH] = (addr >> 8) & 0xff; 206 crt->reg[E6845_REG_LL] = addr & 0xff; 207} 208 209unsigned char e6845_get_index (const e6845_t *crt) 210{ 211 return (crt->index); 212} 213 214unsigned char e6845_get_data (e6845_t *crt) 215{ 216 if ((crt->index >= 12) && (crt->index <= 17)) { 217 return (crt->reg[crt->index]); 218 } 219 220 return (0); 221} 222 223unsigned char e6845_get_uint8 (e6845_t *crt, unsigned long addr) 224{ 225 switch (addr) { 226 case 0: 227 return (e6845_get_index (crt)); 228 229 case 1: 230 return (e6845_get_data (crt)); 231 } 232 233 return (0); 234} 235 236unsigned short e6845_get_uint16 (e6845_t *crt, unsigned long addr) 237{ 238 return (0); 239} 240 241void e6845_set_index (e6845_t *crt, unsigned char val) 242{ 243 crt->index = val & 0x1f; 244} 245 246void e6845_set_data (e6845_t *crt, unsigned char val) 247{ 248 if (crt->index >= E6845_REG_CNT) { 249 return; 250 } 251 252 crt->reg[crt->index] = val; 253} 254 255void e6845_set_uint8 (e6845_t *crt, unsigned long addr, unsigned char val) 256{ 257 switch (addr) { 258 case 0: 259 e6845_set_index (crt, val); 260 break; 261 262 case 1: 263 e6845_set_data (crt, val); 264 break; 265 } 266} 267 268void e6850_set_uint16 (e6845_t *crt, unsigned long addr, unsigned short val) 269{ 270} 271 272void e6845_reset (e6845_t *crt) 273{ 274 unsigned i; 275 276 crt->ccol = 0; 277 crt->crow = 0; 278 crt->frame = 0; 279 crt->ma = 0; 280 crt->ra = 0; 281 crt->vsync_cnt = 0; 282 crt->index = 0; 283 284 for (i = 0; i < E6845_REG_CNT; i++) { 285 crt->reg[i] = 0; 286 } 287} 288 289static 290void e6845_hsync (e6845_t *crt) 291{ 292 if (crt->hsync_fct == NULL) { 293 return; 294 } 295 296 crt->hsync_fct (crt->hsync_ext); 297} 298 299static 300void e6845_vsync (e6845_t *crt) 301{ 302 if (crt->vsync_fct == NULL) { 303 return; 304 } 305 306 crt->vsync_fct (crt->vsync_ext); 307} 308 309void e6845_clock (e6845_t *crt, unsigned cnt) 310{ 311 unsigned char hs, ht, vs, vt, va; 312 313 hs = crt->reg[E6845_REG_HS]; 314 ht = crt->reg[E6845_REG_HT] + 1; 315 316 vs = crt->reg[E6845_REG_VS]; 317 vt = crt->reg[E6845_REG_VT] + 1; 318 va = crt->reg[E6845_REG_VA]; 319 320 while (cnt > 0) { 321 crt->ccol += 1; 322 cnt -= 1; 323 324 if (crt->ccol == hs) { 325 crt->hsync_cnt = crt->reg[E6845_REG_SW] & 15; 326 e6845_hsync (crt); 327 } 328 else if (crt->hsync_cnt > 0) { 329 crt->hsync_cnt -= 1; 330 } 331 332 333 if (crt->ccol >= ht) { 334 crt->ccol = 0; 335 336 if (crt->vsync_cnt > 0) { 337 crt->vsync_cnt -= 1; 338 } 339 340 crt->ra += 1; 341 342 if (crt->ra > crt->reg[E6845_REG_ML]) { 343 if (crt->crow < vt) { 344 crt->ma += crt->reg[E6845_REG_HD]; 345 crt->ra = 0; 346 crt->crow += 1; 347 } 348 } 349 350 if ((crt->crow == vs) && (crt->ra == 0)) { 351 crt->vsync_cnt = 16; 352 353 e6845_vsync (crt); 354 355 crt->frame += 1; 356 crt->ma = e6845_get_start_address (crt); 357 } 358 359 if (((crt->crow == vt) && (crt->ra >= va)) || (crt->crow > vt)) { 360 crt->crow = 0; 361 crt->ma = e6845_get_start_address (crt); 362 crt->ra = 0; 363 } 364 } 365 } 366}