cake
/
libp7
Archived
1
0
Fork 1
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libp7/src/usage/getscreen.c

163 lines
4.7 KiB
C

/* *****************************************************************************
* usage/getscreen.c -- receive the streamed screen from the calculator.
* Copyright (C) 2016-2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libp7.
* libp7 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 3.0 of the License,
* or (at your option) any later version.
*
* libp7 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 libp7; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************** */
#include <libp7/internals.h>
#define makepixel(R, G, B) (((R) << 16) | ((G) << 8) | (B))
/**
* p7_getscreen_adapt:
* Adapts the pixels from the received VRAM.
*
* @arg pixels the pixels matrix
* @arg w pointer to the width var
* @arg h pointer to the height var
* @arg scrtype the VRAM type
* @arg vram the VRAM data
*/
static void p7_getscreen_adapt(uint32_t **pixels, p7_packet_t *resp)
{
uint8_t *vram = resp->p7_seven_packet_vram; int msk;
uint32_t prizm_gray_colors[] = {0xFFFFFF, 0xAAAAAA, 0x777777, 0x000000};
switch (resp->p7_seven_packet_pictype) {
/* monochrome */
case p7_pictype_1bit:
msk = 0x80;
for (unsigned int y = 0; y < resp->p7_seven_packet_height; y++)
for (unsigned int x = 0; x < resp->p7_seven_packet_width; x++) {
/* get pixel */
pixels[y][x] = (*vram & msk) ? 0x000000 : 0xFFFFFF;
/* go to next bit */
vram += msk & 1;
msk = (msk >> 1) | ((msk & 1) << 7);
}
break;
/* 2-bit (Prizm's encoding) */
case p7_pictype_2bit:
msk = 0x80; uint8_t *v2 = &vram[resp->p7_seven_packet_height
* resp->p7_seven_packet_width / 8];
for (unsigned int y = 0; y < resp->p7_seven_packet_height; y++)
for (unsigned int x = 0; x < resp->p7_seven_packet_width; x++) {
/* get pixel */
uint32_t val = (!!(*vram & msk) << 1) | !!(*v2 & msk);
pixels[y][x] = prizm_gray_colors[val];
/* go to next */
vram += msk & 1; v2 += msk & 1;
msk = (msk >> 1) | ((msk & 1) << 7);
}
break;
/* 3-bit */
case p7_pictype_3bit:
msk = 0xF0;
for (unsigned int y = resp->p7_seven_packet_height - 1;
y != (unsigned int)-1; y--)
for (unsigned int x = resp->p7_seven_packet_width - 1;
x != (unsigned int)-1; x--) {
/* get pixel */
uint32_t val = *vram & msk; val = val | (val >> 4);
uint32_t px = 0;
if (px & 8) px |= 0xFF0000;
if (px & 4) px |= 0x00FF00;
if (px & 2) px |= 0x0000FF;
pixels[y][x] = px;
/* go to next */
vram += msk & 1;
msk = ~msk & 0xFF;
}
break;
/* 16-bit */
case p7_pictype_16bit:
for (unsigned int y = 0; y < resp->p7_seven_packet_height; y++)
for (unsigned int x = 0; x < resp->p7_seven_packet_width; x++) {
/* get pixel */
uint32_t o = vram[0], t = vram[1];
pixels[y][x] = (o >> 3) << (16 + 3);
pixels[y][x] |= (((o & 7) << 3) | (t >> 5)) << (8 + 2);
pixels[y][x] |= (t & 31) << (0 + 3);
/* go to next */
vram += 2;
}
break;
}
}
/**
* p7_getscreen:
* Get the screen.
*
* @arg handle the libp7 handle
* @arg callback the main callback for the function.
* for each correctly received frame, the function will
* be called with the dimensions (w, h) and the pixels
* matrix.
* if it returns 0, the function stops.
* @return if it worked
*/
p7_define_ufunc(p7_getscreen, p7_attrs_getscreen,
p7_handle_t *handle, p7_screenfunc_t *callback)
{
int err;
/* make checks */
chk_handle(handle);
chk_seven(handle);
chk_passive(handle);
/* allocate pixels */
uint32_t **pixels = malloc(sizeof(uint32_t*) * MAX_VRAM_HEIGHT
+ sizeof(uint32_t) * MAX_VRAM_WIDTH * MAX_VRAM_HEIGHT);
if (!pixels) return (p7_error_alloc);
/* prepare pixels */
int y = MAX_VRAM_HEIGHT;
uint32_t *base = (uint32_t*)(pixels + MAX_VRAM_HEIGHT);
while (y--) pixels[y] = base + y * MAX_VRAM_WIDTH;
/* main loop */
handle->_flags |= p7_intflag_adjscreen;
while (1) {
/* get packet */
if ((err = p7_seven_recv(handle, 0)))
return (err);
if (response.p7_seven_packet_type != p7_seven_type_ohp)
return (p7_error_unknown);
/* convert */
if (response.p7_seven_packet_pictype) {
p7_getscreen_adapt(pixels, &response);
/* then call back the callback */
if (!(*callback)(response.p7_seven_packet_width,
response.p7_seven_packet_height, pixels))
break;
}
}
/* stop */
free(pixels);
return (0);
}