1 /*
2 * libtilemcore - Graphing calculator emulation library
3 *
4 * Copyright (C) 2011 Benjamin Moody
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27 #include "tilem.h"
28
tilem_lcd_buffer_new()29 TilemLCDBuffer* tilem_lcd_buffer_new()
30 {
31 return tilem_new0(TilemLCDBuffer, 1);
32 }
33
tilem_lcd_buffer_free(TilemLCDBuffer * buf)34 void tilem_lcd_buffer_free(TilemLCDBuffer *buf)
35 {
36 tilem_free(buf->data);
37 tilem_free(buf->tmpbuf);
38 tilem_free(buf);
39 }
40
tilem_lcd_get_frame(TilemCalc * restrict calc,TilemLCDBuffer * restrict buf)41 void tilem_lcd_get_frame(TilemCalc * restrict calc,
42 TilemLCDBuffer * restrict buf)
43 {
44 byte * restrict bp;
45 byte * restrict op;
46 int dwidth = calc->hw.lcdwidth;
47 int dheight = calc->hw.lcdheight;
48 unsigned int size;
49 int bwidth = ((calc->hw.lcdwidth + 7) / 8);
50 int i, j;
51
52 if (TILEM_UNLIKELY(buf->height != dheight
53 || buf->rowstride != bwidth * 8)) {
54 /* reallocate data buffer */
55 tilem_free(buf->data);
56 buf->data = tilem_new_atomic(byte, dwidth * bwidth * 8);
57 buf->rowstride = bwidth * 8;
58 buf->height = dheight;
59 }
60
61 size = bwidth * dheight * sizeof(byte);
62 if (TILEM_UNLIKELY(buf->tmpbufsize < size)) {
63 /* reallocate temp buffer */
64 tilem_free(buf->tmpbuf);
65 buf->tmpbuf = tilem_malloc_atomic(size);
66 buf->tmpbufsize = size;
67 }
68
69 buf->width = dwidth;
70
71 buf->stamp = calc->z80.lastlcdwrite;
72
73 if (!calc->lcd.active || (calc->z80.halted && !calc->poweronhalt)) {
74 /* screen is turned off */
75 buf->contrast = 0;
76 return;
77 }
78
79 buf->contrast = calc->lcd.contrast;
80
81 bp = buf->tmpbuf;
82 op = buf->data;
83 (*calc->hw.get_lcd)(calc, bp);
84
85 for (i = 0; i < bwidth * dheight; i++) {
86 for (j = 0; j < 8; j++) {
87 *op = (*bp << j) & 0x80;
88 op++;
89 }
90 bp++;
91 }
92 }
93
94 /* Do the same thing as tilem_lcd_get_frame, but output is only 0 and 1 */
tilem_lcd_get_frame1(TilemCalc * restrict calc,TilemLCDBuffer * restrict buf)95 void tilem_lcd_get_frame1(TilemCalc * restrict calc,
96 TilemLCDBuffer * restrict buf)
97 {
98 byte * restrict bp;
99 byte * restrict op;
100 int dwidth = calc->hw.lcdwidth;
101 int dheight = calc->hw.lcdheight;
102 unsigned int size;
103 int bwidth = ((calc->hw.lcdwidth + 7) / 8);
104 int i, j;
105
106 if (TILEM_UNLIKELY(buf->height != dheight
107 || buf->rowstride != bwidth * 8)) {
108 /* reallocate data buffer */
109 tilem_free(buf->data);
110 buf->data = tilem_new_atomic(byte, dwidth * bwidth * 8);
111 buf->rowstride = bwidth * 8;
112 buf->height = dheight;
113 }
114
115 size = bwidth * dheight * sizeof(byte);
116 if (TILEM_UNLIKELY(buf->tmpbufsize < size)) {
117 /* reallocate temp buffer */
118 tilem_free(buf->tmpbuf);
119 buf->tmpbuf = tilem_malloc_atomic(size);
120 buf->tmpbufsize = size;
121 }
122
123 buf->width = dwidth;
124
125 buf->stamp = calc->z80.lastlcdwrite;
126
127 if (!calc->lcd.active || (calc->z80.halted && !calc->poweronhalt)) {
128 /* screen is turned off */
129 buf->contrast = 0;
130 return;
131 }
132
133 buf->contrast = calc->lcd.contrast;
134
135 bp = buf->tmpbuf;
136 op = buf->data;
137 (*calc->hw.get_lcd)(calc, bp);
138
139 for (i = 0; i < bwidth * dheight; i++) {
140 for (j = 0; j < 8; j++) {
141 *op = (*bp << j) & 0x80;
142 if(*op != 0)
143 *op = 1;
144 op++;
145 }
146 bp++;
147 }
148 }
149