/*
* libtilemcore - Graphing calculator emulation library
*
* Copyright (C) 2011 Benjamin Moody
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see
* .
*/
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include "tilem.h"
TilemLCDBuffer* tilem_lcd_buffer_new()
{
return tilem_new0(TilemLCDBuffer, 1);
}
void tilem_lcd_buffer_free(TilemLCDBuffer *buf)
{
tilem_free(buf->data);
tilem_free(buf->tmpbuf);
tilem_free(buf);
}
void tilem_lcd_get_frame(TilemCalc * restrict calc,
TilemLCDBuffer * restrict buf)
{
byte * restrict bp;
byte * restrict op;
int dwidth = calc->hw.lcdwidth;
int dheight = calc->hw.lcdheight;
unsigned int size;
int bwidth = ((calc->hw.lcdwidth + 7) / 8);
int i, j;
if (TILEM_UNLIKELY(buf->height != dheight
|| buf->rowstride != bwidth * 8)) {
/* reallocate data buffer */
tilem_free(buf->data);
buf->data = tilem_new_atomic(byte, dwidth * bwidth * 8);
buf->rowstride = bwidth * 8;
buf->height = dheight;
}
size = bwidth * dheight * sizeof(byte);
if (TILEM_UNLIKELY(buf->tmpbufsize < size)) {
/* reallocate temp buffer */
tilem_free(buf->tmpbuf);
buf->tmpbuf = tilem_malloc_atomic(size);
buf->tmpbufsize = size;
}
buf->width = dwidth;
buf->stamp = calc->z80.lastlcdwrite;
if (!calc->lcd.active || (calc->z80.halted && !calc->poweronhalt)) {
/* screen is turned off */
buf->contrast = 0;
return;
}
buf->contrast = calc->lcd.contrast;
bp = buf->tmpbuf;
op = buf->data;
(*calc->hw.get_lcd)(calc, bp);
for (i = 0; i < bwidth * dheight; i++) {
for (j = 0; j < 8; j++) {
*op = (*bp << j) & 0x80;
op++;
}
bp++;
}
}
/* Do the same thing as tilem_lcd_get_frame, but output is only 0 and 1 */
void tilem_lcd_get_frame1(TilemCalc * restrict calc,
TilemLCDBuffer * restrict buf)
{
byte * restrict bp;
byte * restrict op;
int dwidth = calc->hw.lcdwidth;
int dheight = calc->hw.lcdheight;
unsigned int size;
int bwidth = ((calc->hw.lcdwidth + 7) / 8);
int i, j;
if (TILEM_UNLIKELY(buf->height != dheight
|| buf->rowstride != bwidth * 8)) {
/* reallocate data buffer */
tilem_free(buf->data);
buf->data = tilem_new_atomic(byte, dwidth * bwidth * 8);
buf->rowstride = bwidth * 8;
buf->height = dheight;
}
size = bwidth * dheight * sizeof(byte);
if (TILEM_UNLIKELY(buf->tmpbufsize < size)) {
/* reallocate temp buffer */
tilem_free(buf->tmpbuf);
buf->tmpbuf = tilem_malloc_atomic(size);
buf->tmpbufsize = size;
}
buf->width = dwidth;
buf->stamp = calc->z80.lastlcdwrite;
if (!calc->lcd.active || (calc->z80.halted && !calc->poweronhalt)) {
/* screen is turned off */
buf->contrast = 0;
return;
}
buf->contrast = calc->lcd.contrast;
bp = buf->tmpbuf;
op = buf->data;
(*calc->hw.get_lcd)(calc, bp);
for (i = 0; i < bwidth * dheight; i++) {
for (j = 0; j < 8; j++) {
*op = (*bp << j) & 0x80;
if(*op != 0)
*op = 1;
op++;
}
bp++;
}
}