|
|
1.1 root 1: // Code for manipulating VGA framebuffers.
2: //
3: // Copyright (C) 2009 Kevin O'Connor <[email protected]>
4: // Copyright (C) 2001-2008 the LGPL VGABios developers Team
5: //
6: // This file may be distributed under the terms of the GNU LGPLv3 license.
7:
1.1.1.2 ! root 8: #include "vgabios.h" // vgafb_scroll
1.1 root 9: #include "biosvar.h" // GET_BDA
10: #include "util.h" // memset_far
1.1.1.2 ! root 11: #include "stdvga.h" // stdvga_planar4_plane
1.1 root 12:
13:
14: /****************************************************************
15: * Screen scrolling
16: ****************************************************************/
17:
18: static inline void *
19: memcpy_stride(u16 seg, void *dst, void *src, int copylen, int stride, int lines)
20: {
21: for (; lines; lines--, dst+=stride, src+=stride)
22: memcpy_far(seg, dst, seg, src, copylen);
23: return dst;
24: }
25:
26: static inline void
27: memset_stride(u16 seg, void *dst, u8 val, int setlen, int stride, int lines)
28: {
29: for (; lines; lines--, dst+=stride)
30: memset_far(seg, dst, val, setlen);
31: }
32:
33: static inline void
34: memset16_stride(u16 seg, void *dst, u16 val, int setlen, int stride, int lines)
35: {
36: for (; lines; lines--, dst+=stride)
37: memset16_far(seg, dst, val, setlen);
38: }
39:
40: static void
41: scroll_pl4(struct vgamode_s *vmode_g, int nblines, int attr
42: , struct cursorpos ul, struct cursorpos lr)
43: {
1.1.1.2 ! root 44: int cheight = GET_GLOBAL(vmode_g->cheight);
! 45: int cwidth = 1;
! 46: int stride = GET_BDA(video_cols) * cwidth;
1.1 root 47: void *src_far, *dest_far;
48: if (nblines >= 0) {
1.1.1.2 ! root 49: dest_far = (void*)(ul.y * cheight * stride + ul.x * cwidth);
1.1 root 50: src_far = dest_far + nblines * cheight * stride;
51: } else {
52: // Scroll down
53: nblines = -nblines;
1.1.1.2 ! root 54: dest_far = (void*)(lr.y * cheight * stride + ul.x * cwidth);
1.1 root 55: src_far = dest_far - nblines * cheight * stride;
56: stride = -stride;
57: }
1.1.1.2 ! root 58: if (attr < 0)
! 59: attr = 0;
1.1 root 60: int cols = lr.x - ul.x + 1;
61: int rows = lr.y - ul.y + 1;
1.1.1.2 ! root 62: int i;
! 63: for (i=0; i<4; i++) {
! 64: stdvga_planar4_plane(i);
! 65: void *dest = dest_far;
! 66: if (nblines < rows)
! 67: dest = memcpy_stride(SEG_GRAPH, dest, src_far, cols * cwidth
! 68: , stride, (rows - nblines) * cheight);
! 69: u8 pixels = (attr & (1<<i)) ? 0xff : 0x00;
! 70: memset_stride(SEG_GRAPH, dest, pixels, cols * cwidth
! 71: , stride, nblines * cheight);
1.1 root 72: }
1.1.1.2 ! root 73: stdvga_planar4_plane(-1);
1.1 root 74: }
75:
76: static void
77: scroll_cga(struct vgamode_s *vmode_g, int nblines, int attr
78: , struct cursorpos ul, struct cursorpos lr)
79: {
1.1.1.2 ! root 80: int cheight = GET_GLOBAL(vmode_g->cheight) / 2;
! 81: int cwidth = GET_GLOBAL(vmode_g->depth);
! 82: int stride = GET_BDA(video_cols) * cwidth;
1.1 root 83: void *src_far, *dest_far;
84: if (nblines >= 0) {
1.1.1.2 ! root 85: dest_far = (void*)(ul.y * cheight * stride + ul.x * cwidth);
1.1 root 86: src_far = dest_far + nblines * cheight * stride;
87: } else {
88: // Scroll down
89: nblines = -nblines;
1.1.1.2 ! root 90: dest_far = (void*)(lr.y * cheight * stride + ul.x * cwidth);
1.1 root 91: src_far = dest_far - nblines * cheight * stride;
92: stride = -stride;
93: }
1.1.1.2 ! root 94: if (attr < 0)
! 95: attr = 0;
! 96: if (cwidth == 1)
! 97: attr = (attr&1) | ((attr&1)<<1);
! 98: attr &= 3;
! 99: attr |= (attr<<2) | (attr<<4) | (attr<<6);
! 100: int cols = lr.x - ul.x + 1;
1.1 root 101: int rows = lr.y - ul.y + 1;
102: if (nblines < rows) {
1.1.1.2 ! root 103: memcpy_stride(SEG_CTEXT, dest_far+0x2000, src_far+0x2000, cols * cwidth
! 104: , stride, (rows - nblines) * cheight);
! 105: dest_far = memcpy_stride(SEG_CTEXT, dest_far, src_far, cols * cwidth
! 106: , stride, (rows - nblines) * cheight);
! 107: }
! 108: memset_stride(SEG_CTEXT, dest_far + 0x2000, attr, cols * cwidth
! 109: , stride, nblines * cheight);
! 110: memset_stride(SEG_CTEXT, dest_far, attr, cols * cwidth
! 111: , stride, nblines * cheight);
! 112: }
! 113:
! 114: static void
! 115: scroll_lin(struct vgamode_s *vmode_g, int nblines, int attr
! 116: , struct cursorpos ul, struct cursorpos lr)
! 117: {
! 118: int cheight = 8;
! 119: int cwidth = 8;
! 120: int stride = GET_BDA(video_cols) * cwidth;
! 121: void *src_far, *dest_far;
! 122: if (nblines >= 0) {
! 123: dest_far = (void*)(ul.y * cheight * stride + ul.x * cwidth);
! 124: src_far = dest_far + nblines * cheight * stride;
! 125: } else {
! 126: // Scroll down
! 127: nblines = -nblines;
! 128: dest_far = (void*)(lr.y * cheight * stride + ul.x * cwidth);
! 129: src_far = dest_far - nblines * cheight * stride;
! 130: stride = -stride;
1.1 root 131: }
132: if (attr < 0)
133: attr = 0;
1.1.1.2 ! root 134: int cols = lr.x - ul.x + 1;
! 135: int rows = lr.y - ul.y + 1;
! 136: if (nblines < rows)
! 137: dest_far = memcpy_stride(SEG_GRAPH, dest_far, src_far, cols * cwidth
! 138: , stride, (rows - nblines) * cheight);
! 139: memset_stride(SEG_GRAPH, dest_far, attr, cols * cwidth
! 140: , stride, nblines * cheight);
1.1 root 141: }
142:
143: static void
144: scroll_text(struct vgamode_s *vmode_g, int nblines, int attr
145: , struct cursorpos ul, struct cursorpos lr)
146: {
1.1.1.2 ! root 147: int cheight = 1;
! 148: int cwidth = 2;
! 149: int stride = GET_BDA(video_cols) * cwidth;
! 150: void *src_far, *dest_far = (void*)(GET_BDA(video_pagesize) * ul.page);
1.1 root 151: if (nblines >= 0) {
1.1.1.2 ! root 152: dest_far += ul.y * cheight * stride + ul.x * cwidth;
! 153: src_far = dest_far + nblines * cheight * stride;
1.1 root 154: } else {
155: // Scroll down
156: nblines = -nblines;
1.1.1.2 ! root 157: dest_far += lr.y * cheight * stride + ul.x * cwidth;
! 158: src_far = dest_far - nblines * cheight * stride;
1.1 root 159: stride = -stride;
160: }
161: if (attr < 0)
162: attr = 0x07;
163: attr = (attr << 8) | ' ';
1.1.1.2 ! root 164: int cols = lr.x - ul.x + 1;
! 165: int rows = lr.y - ul.y + 1;
! 166: u16 seg = GET_GLOBAL(vmode_g->sstart);
! 167: if (nblines < rows)
! 168: dest_far = memcpy_stride(seg, dest_far, src_far, cols * cwidth
! 169: , stride, (rows - nblines) * cheight);
! 170: memset16_stride(seg, dest_far, attr, cols * cwidth
! 171: , stride, nblines * cheight);
1.1 root 172: }
173:
174: void
175: vgafb_scroll(int nblines, int attr, struct cursorpos ul, struct cursorpos lr)
176: {
177: // Get the mode
1.1.1.2 ! root 178: struct vgamode_s *vmode_g = get_current_mode();
1.1 root 179: if (!vmode_g)
180: return;
181:
182: // FIXME gfx mode not complete
183: switch (GET_GLOBAL(vmode_g->memmodel)) {
1.1.1.2 ! root 184: case MM_TEXT:
1.1 root 185: scroll_text(vmode_g, nblines, attr, ul, lr);
186: break;
1.1.1.2 ! root 187: case MM_PLANAR:
1.1 root 188: scroll_pl4(vmode_g, nblines, attr, ul, lr);
189: break;
1.1.1.2 ! root 190: case MM_CGA:
1.1 root 191: scroll_cga(vmode_g, nblines, attr, ul, lr);
192: break;
1.1.1.2 ! root 193: case MM_DIRECT:
! 194: case MM_PACKED:
! 195: scroll_lin(vmode_g, nblines, attr, ul, lr);
1.1 root 196: break;
197: default:
1.1.1.2 ! root 198: break;
1.1 root 199: }
200: }
201:
202:
203: /****************************************************************
204: * Read/write characters to screen
205: ****************************************************************/
206:
207: static void
208: write_gfx_char_pl4(struct vgamode_s *vmode_g
209: , struct cursorpos cp, struct carattr ca)
210: {
211: u16 nbcols = GET_BDA(video_cols);
212: if (cp.x >= nbcols)
213: return;
214:
1.1.1.2 ! root 215: u8 cheight = GET_GLOBAL(vmode_g->cheight);
1.1 root 216: u8 *fdata_g;
217: switch (cheight) {
218: case 14:
219: fdata_g = vgafont14;
220: break;
221: case 16:
222: fdata_g = vgafont16;
223: break;
224: default:
225: fdata_g = vgafont8;
226: }
227: u16 addr = cp.x + cp.y * cheight * nbcols;
228: u16 src = ca.car * cheight;
1.1.1.2 ! root 229: int i;
! 230: for (i=0; i<4; i++) {
! 231: stdvga_planar4_plane(i);
! 232: u8 colors = ((ca.attr & (1<<i)) ? 0xff : 0x00);
! 233: int j;
! 234: for (j = 0; j < cheight; j++) {
! 235: u8 *dest_far = (void*)(addr + j * nbcols);
! 236: u8 pixels = colors & GET_GLOBAL(fdata_g[src + j]);
! 237: if (ca.attr & 0x80)
! 238: pixels ^= GET_FARVAR(SEG_GRAPH, *dest_far);
! 239: SET_FARVAR(SEG_GRAPH, *dest_far, pixels);
1.1 root 240: }
241: }
1.1.1.2 ! root 242: stdvga_planar4_plane(-1);
1.1 root 243: }
244:
245: static void
246: write_gfx_char_cga(struct vgamode_s *vmode_g
247: , struct cursorpos cp, struct carattr ca)
248: {
249: u16 nbcols = GET_BDA(video_cols);
250: if (cp.x >= nbcols)
251: return;
252:
253: u8 *fdata_g = vgafont8;
1.1.1.2 ! root 254: u8 bpp = GET_GLOBAL(vmode_g->depth);
1.1 root 255: u16 addr = (cp.x * bpp) + cp.y * 320;
256: u16 src = ca.car * 8;
257: u8 i;
258: for (i = 0; i < 8; i++) {
259: u8 *dest_far = (void*)(addr + (i >> 1) * 80);
260: if (i & 1)
261: dest_far += 0x2000;
262: if (bpp == 1) {
1.1.1.2 ! root 263: u8 colors = (ca.attr & 0x01) ? 0xff : 0x00;
! 264: u8 pixels = colors & GET_GLOBAL(fdata_g[src + i]);
1.1 root 265: if (ca.attr & 0x80)
1.1.1.2 ! root 266: pixels ^= GET_FARVAR(SEG_GRAPH, *dest_far);
! 267: SET_FARVAR(SEG_CTEXT, *dest_far, pixels);
1.1 root 268: } else {
1.1.1.2 ! root 269: u16 pixels = 0;
! 270: u8 fontline = GET_GLOBAL(fdata_g[src + i]);
! 271: int j;
! 272: for (j = 0; j < 8; j++)
! 273: if (fontline & (1<<j))
! 274: pixels |= (ca.attr & 0x03) << (j*2);
! 275: pixels = htons(pixels);
! 276: if (ca.attr & 0x80)
! 277: pixels ^= GET_FARVAR(SEG_GRAPH, *(u16*)dest_far);
! 278: SET_FARVAR(SEG_CTEXT, *(u16*)dest_far, pixels);
1.1 root 279: }
280: }
281: }
282:
283: static void
284: write_gfx_char_lin(struct vgamode_s *vmode_g
285: , struct cursorpos cp, struct carattr ca)
286: {
287: // Get the dimensions
288: u16 nbcols = GET_BDA(video_cols);
289: if (cp.x >= nbcols)
290: return;
291:
292: u8 *fdata_g = vgafont8;
293: u16 addr = cp.x * 8 + cp.y * nbcols * 64;
294: u16 src = ca.car * 8;
295: u8 i;
296: for (i = 0; i < 8; i++) {
297: u8 *dest_far = (void*)(addr + i * nbcols * 8);
1.1.1.2 ! root 298: u8 fontline = GET_GLOBAL(fdata_g[src + i]);
1.1 root 299: u8 j;
300: for (j = 0; j < 8; j++) {
1.1.1.2 ! root 301: u8 pixel = (fontline & (0x80>>j)) ? ca.attr : 0x00;
! 302: SET_FARVAR(SEG_GRAPH, dest_far[j], pixel);
1.1 root 303: }
304: }
305: }
306:
307: static void
308: write_text_char(struct vgamode_s *vmode_g
309: , struct cursorpos cp, struct carattr ca)
310: {
311: // Compute the address
1.1.1.2 ! root 312: u16 nbcols = GET_BDA(video_cols);
! 313: void *address_far = (void*)(GET_BDA(video_pagesize) * cp.page
1.1 root 314: + (cp.x + cp.y * nbcols) * 2);
315:
316: if (ca.use_attr) {
317: u16 dummy = (ca.attr << 8) | ca.car;
318: SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u16*)address_far, dummy);
319: } else {
320: SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)address_far, ca.car);
321: }
322: }
323:
324: void
325: vgafb_write_char(struct cursorpos cp, struct carattr ca)
326: {
327: // Get the mode
1.1.1.2 ! root 328: struct vgamode_s *vmode_g = get_current_mode();
1.1 root 329: if (!vmode_g)
330: return;
331:
332: // FIXME gfx mode not complete
333: switch (GET_GLOBAL(vmode_g->memmodel)) {
1.1.1.2 ! root 334: case MM_TEXT:
1.1 root 335: write_text_char(vmode_g, cp, ca);
336: break;
1.1.1.2 ! root 337: case MM_PLANAR:
1.1 root 338: write_gfx_char_pl4(vmode_g, cp, ca);
339: break;
1.1.1.2 ! root 340: case MM_CGA:
1.1 root 341: write_gfx_char_cga(vmode_g, cp, ca);
342: break;
1.1.1.2 ! root 343: case MM_DIRECT:
! 344: case MM_PACKED:
1.1 root 345: write_gfx_char_lin(vmode_g, cp, ca);
346: break;
1.1.1.2 ! root 347: default:
! 348: break;
1.1 root 349: }
350: }
351:
352: struct carattr
353: vgafb_read_char(struct cursorpos cp)
354: {
355: // Get the mode
1.1.1.2 ! root 356: struct vgamode_s *vmode_g = get_current_mode();
1.1 root 357: if (!vmode_g)
358: goto fail;
359:
1.1.1.2 ! root 360: if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) {
1.1 root 361: // FIXME gfx mode
362: dprintf(1, "Read char in graphics mode\n");
363: goto fail;
364: }
365:
366: // Compute the address
1.1.1.2 ! root 367: u16 nbcols = GET_BDA(video_cols);
! 368: u16 *address_far = (void*)(GET_BDA(video_pagesize) * cp.page
1.1 root 369: + (cp.x + cp.y * nbcols) * 2);
370: u16 v = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *address_far);
371: struct carattr ca = {v, v>>8, 0};
372: return ca;
373:
374: fail: ;
375: struct carattr ca2 = {0, 0, 0};
376: return ca2;
377: }
378:
379:
380: /****************************************************************
381: * Read/write pixels
382: ****************************************************************/
383:
384: void
385: vgafb_write_pixel(u8 color, u16 x, u16 y)
386: {
387: // Get the mode
1.1.1.2 ! root 388: struct vgamode_s *vmode_g = get_current_mode();
1.1 root 389: if (!vmode_g)
390: return;
391:
1.1.1.2 ! root 392: u8 *addr_far, mask, attr, data, i;
1.1 root 393: switch (GET_GLOBAL(vmode_g->memmodel)) {
1.1.1.2 ! root 394: case MM_PLANAR:
1.1 root 395: addr_far = (void*)(x / 8 + y * GET_BDA(video_cols));
396: mask = 0x80 >> (x & 0x07);
1.1.1.2 ! root 397: for (i=0; i<4; i++) {
! 398: stdvga_planar4_plane(i);
! 399: u8 colors = (color & (1<<i)) ? 0xff : 0x00;
! 400: u8 orig = GET_FARVAR(SEG_GRAPH, *addr_far);
! 401: if (color & 0x80)
! 402: colors ^= orig;
! 403: SET_FARVAR(SEG_GRAPH, *addr_far, (colors & mask) | (orig & ~mask));
! 404: }
! 405: stdvga_planar4_plane(-1);
1.1 root 406: break;
1.1.1.2 ! root 407: case MM_CGA:
! 408: if (GET_GLOBAL(vmode_g->depth) == 2)
1.1 root 409: addr_far = (void*)((x >> 2) + (y >> 1) * 80);
410: else
411: addr_far = (void*)((x >> 3) + (y >> 1) * 80);
412: if (y & 1)
413: addr_far += 0x2000;
414: data = GET_FARVAR(SEG_CTEXT, *addr_far);
1.1.1.2 ! root 415: if (GET_GLOBAL(vmode_g->depth) == 2) {
1.1 root 416: attr = (color & 0x03) << ((3 - (x & 0x03)) * 2);
417: mask = 0x03 << ((3 - (x & 0x03)) * 2);
418: } else {
419: attr = (color & 0x01) << (7 - (x & 0x07));
420: mask = 0x01 << (7 - (x & 0x07));
421: }
422: if (color & 0x80) {
423: data ^= attr;
424: } else {
425: data &= ~mask;
426: data |= attr;
427: }
428: SET_FARVAR(SEG_CTEXT, *addr_far, data);
429: break;
1.1.1.2 ! root 430: case MM_DIRECT:
! 431: case MM_PACKED:
1.1 root 432: addr_far = (void*)(x + y * (GET_BDA(video_cols) * 8));
433: SET_FARVAR(SEG_GRAPH, *addr_far, color);
434: break;
1.1.1.2 ! root 435: default:
! 436: case MM_TEXT:
! 437: return;
1.1 root 438: }
439: }
440:
441: u8
442: vgafb_read_pixel(u16 x, u16 y)
443: {
444: // Get the mode
1.1.1.2 ! root 445: struct vgamode_s *vmode_g = get_current_mode();
1.1 root 446: if (!vmode_g)
447: return 0;
448:
449: u8 *addr_far, mask, attr=0, data, i;
450: switch (GET_GLOBAL(vmode_g->memmodel)) {
1.1.1.2 ! root 451: case MM_PLANAR:
1.1 root 452: addr_far = (void*)(x / 8 + y * GET_BDA(video_cols));
453: mask = 0x80 >> (x & 0x07);
454: attr = 0x00;
455: for (i = 0; i < 4; i++) {
1.1.1.2 ! root 456: stdvga_planar4_plane(i);
1.1 root 457: data = GET_FARVAR(SEG_GRAPH, *addr_far) & mask;
458: if (data > 0)
459: attr |= (0x01 << i);
460: }
1.1.1.2 ! root 461: stdvga_planar4_plane(-1);
1.1 root 462: break;
1.1.1.2 ! root 463: case MM_CGA:
1.1 root 464: addr_far = (void*)((x >> 2) + (y >> 1) * 80);
465: if (y & 1)
466: addr_far += 0x2000;
467: data = GET_FARVAR(SEG_CTEXT, *addr_far);
1.1.1.2 ! root 468: if (GET_GLOBAL(vmode_g->depth) == 2)
1.1 root 469: attr = (data >> ((3 - (x & 0x03)) * 2)) & 0x03;
470: else
471: attr = (data >> (7 - (x & 0x07))) & 0x01;
472: break;
1.1.1.2 ! root 473: case MM_DIRECT:
! 474: case MM_PACKED:
1.1 root 475: addr_far = (void*)(x + y * (GET_BDA(video_cols) * 8));
476: attr = GET_FARVAR(SEG_GRAPH, *addr_far);
477: break;
1.1.1.2 ! root 478: default:
! 479: case MM_TEXT:
! 480: return 0;
1.1 root 481: }
482: return attr;
483: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.