2017-02-23 19:17:39 +01:00
|
|
|
/* *****************************************************************************
|
2017-03-25 13:43:44 +01:00
|
|
|
* usage/getscreen.c -- receive the streamed screen from the calculator.
|
2017-02-23 19:17:39 +01:00
|
|
|
* 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/>.
|
|
|
|
* ************************************************************************** */
|
2016-09-06 19:01:37 +02:00
|
|
|
#include <libp7/internals.h>
|
2017-03-10 19:05:39 +01:00
|
|
|
#define makepixel(R, G, B) (((R) << 16) | ((G) << 8) | (B))
|
2016-09-06 19:01:37 +02:00
|
|
|
|
2016-09-17 19:12:27 +02:00
|
|
|
/**
|
|
|
|
* 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
|
2017-01-04 13:38:20 +01:00
|
|
|
* @arg scrtype the VRAM type
|
|
|
|
* @arg vram the VRAM data
|
2016-09-17 19:12:27 +02:00
|
|
|
*/
|
|
|
|
|
2017-03-10 00:02:37 +01:00
|
|
|
static void p7_getscreen_adapt(uint32_t **pixels, p7_packet_t *resp)
|
2016-09-17 19:12:27 +02:00
|
|
|
{
|
2017-04-12 17:39:38 +02:00
|
|
|
uint8_t *vram = resp->p7_seven_packet_vram; int msk;
|
2017-03-10 22:13:38 +01:00
|
|
|
uint32_t prizm_gray_colors[] = {0xFFFFFF, 0xAAAAAA, 0x777777, 0x000000};
|
2017-03-10 00:02:37 +01:00
|
|
|
|
2017-04-12 17:39:38 +02:00
|
|
|
switch (resp->p7_seven_packet_pictype) {
|
2017-03-10 00:02:37 +01:00
|
|
|
/* monochrome */
|
|
|
|
case p7_pictype_1bit:
|
2017-03-10 11:36:34 +01:00
|
|
|
msk = 0x80;
|
2017-04-12 17:39:38 +02:00
|
|
|
for (unsigned int y = 0; y < resp->p7_seven_packet_height; y++)
|
|
|
|
for (unsigned int x = 0; x < resp->p7_seven_packet_width; x++) {
|
2017-03-10 00:02:37 +01:00
|
|
|
/* get pixel */
|
2017-03-10 11:36:34 +01:00
|
|
|
pixels[y][x] = (*vram & msk) ? 0x000000 : 0xFFFFFF;
|
2016-09-17 19:12:27 +02:00
|
|
|
|
|
|
|
/* go to next bit */
|
2017-03-10 11:36:34 +01:00
|
|
|
vram += msk & 1;
|
|
|
|
msk = (msk >> 1) | ((msk & 1) << 7);
|
2016-09-17 19:12:27 +02:00
|
|
|
}
|
|
|
|
break;
|
2017-03-10 00:02:37 +01:00
|
|
|
|
2017-03-10 21:35:19 +01:00
|
|
|
/* 2-bit (Prizm's encoding) */
|
2017-03-10 20:03:28 +01:00
|
|
|
case p7_pictype_2bit:
|
2017-04-12 17:39:38 +02:00
|
|
|
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++) {
|
2017-03-10 20:03:28 +01:00
|
|
|
/* get pixel */
|
2017-03-10 22:07:57 +01:00
|
|
|
uint32_t val = (!!(*vram & msk) << 1) | !!(*v2 & msk);
|
|
|
|
pixels[y][x] = prizm_gray_colors[val];
|
2017-03-10 20:03:28 +01:00
|
|
|
|
|
|
|
/* go to next */
|
2017-03-10 21:54:38 +01:00
|
|
|
vram += msk & 1; v2 += msk & 1;
|
2017-03-10 21:35:19 +01:00
|
|
|
msk = (msk >> 1) | ((msk & 1) << 7);
|
2017-03-10 20:03:28 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2017-03-10 00:02:37 +01:00
|
|
|
/* 3-bit */
|
|
|
|
case p7_pictype_3bit:
|
|
|
|
msk = 0xF0;
|
2017-04-12 17:39:38 +02:00
|
|
|
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--) {
|
2017-03-10 00:02:37 +01:00
|
|
|
/* get pixel */
|
2017-03-10 11:36:34 +01:00
|
|
|
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;
|
2017-03-10 00:02:37 +01:00
|
|
|
|
|
|
|
/* go to next */
|
|
|
|
vram += msk & 1;
|
|
|
|
msk = ~msk & 0xFF;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* 16-bit */
|
|
|
|
case p7_pictype_16bit:
|
2017-04-12 17:39:38 +02:00
|
|
|
for (unsigned int y = 0; y < resp->p7_seven_packet_height; y++)
|
|
|
|
for (unsigned int x = 0; x < resp->p7_seven_packet_width; x++) {
|
2017-03-10 00:02:37 +01:00
|
|
|
/* get pixel */
|
2017-03-10 11:36:34 +01:00
|
|
|
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);
|
2017-03-11 14:17:44 +01:00
|
|
|
pixels[y][x] |= (t & 31) << (0 + 3);
|
2017-03-10 00:02:37 +01:00
|
|
|
|
|
|
|
/* go to next */
|
|
|
|
vram += 2;
|
|
|
|
}
|
|
|
|
break;
|
2016-09-17 19:12:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-06 19:01:37 +02:00
|
|
|
/**
|
|
|
|
* p7_getscreen:
|
|
|
|
* Get the screen.
|
|
|
|
*
|
2016-09-25 22:01:42 +02:00
|
|
|
* @arg handle the libp7 handle
|
2016-09-06 19:01:37 +02:00
|
|
|
* @arg callback the main callback for the function.
|
|
|
|
* for each correctly received frame, the function will
|
2016-09-17 19:12:27 +02:00
|
|
|
* be called with the dimensions (w, h) and the pixels
|
|
|
|
* matrix.
|
2016-09-06 19:01:37 +02:00
|
|
|
* if it returns 0, the function stops.
|
|
|
|
* @return if it worked
|
|
|
|
*/
|
|
|
|
|
2017-04-20 02:28:36 +02:00
|
|
|
p7_define_ufunc(p7_getscreen, p7_attrs_getscreen,
|
|
|
|
p7_handle_t *handle, p7_screenfunc_t *callback)
|
2016-09-06 19:01:37 +02:00
|
|
|
{
|
2016-09-25 22:01:42 +02:00
|
|
|
int err;
|
2016-10-09 16:26:04 +02:00
|
|
|
/* make checks */
|
|
|
|
chk_handle(handle);
|
2017-04-11 02:39:21 +02:00
|
|
|
chk_seven(handle);
|
2016-10-09 16:26:04 +02:00
|
|
|
chk_passive(handle);
|
2016-09-10 01:46:03 +02:00
|
|
|
|
2017-01-27 00:00:57 +01:00
|
|
|
/* allocate pixels */
|
2017-03-10 00:02:37 +01:00
|
|
|
uint32_t **pixels = malloc(sizeof(uint32_t*) * MAX_VRAM_HEIGHT
|
2017-01-27 00:00:57 +01:00
|
|
|
+ sizeof(uint32_t) * MAX_VRAM_WIDTH * MAX_VRAM_HEIGHT);
|
2017-03-10 00:02:37 +01:00
|
|
|
if (!pixels) return (p7_error_alloc);
|
2017-01-27 00:00:57 +01:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
2016-09-06 19:01:37 +02:00
|
|
|
/* main loop */
|
2017-03-10 16:49:52 +01:00
|
|
|
handle->_flags |= p7_intflag_adjscreen;
|
2016-09-06 19:01:37 +02:00
|
|
|
while (1) {
|
2016-09-08 11:48:01 +02:00
|
|
|
/* get packet */
|
2017-03-27 12:42:35 +02:00
|
|
|
if ((err = p7_seven_recv(handle, 0)))
|
2016-09-25 22:01:42 +02:00
|
|
|
return (err);
|
2017-04-12 17:39:38 +02:00
|
|
|
if (response.p7_seven_packet_type != p7_seven_type_ohp)
|
2016-09-25 22:01:42 +02:00
|
|
|
return (p7_error_unknown);
|
2016-09-06 19:01:37 +02:00
|
|
|
|
2016-09-17 19:12:27 +02:00
|
|
|
/* convert */
|
2017-04-12 17:39:38 +02:00
|
|
|
if (response.p7_seven_packet_pictype) {
|
2017-03-10 10:33:50 +01:00
|
|
|
p7_getscreen_adapt(pixels, &response);
|
2016-09-17 19:12:27 +02:00
|
|
|
|
2017-03-10 10:33:50 +01:00
|
|
|
/* then call back the callback */
|
2017-04-12 17:39:38 +02:00
|
|
|
if (!(*callback)(response.p7_seven_packet_width,
|
|
|
|
response.p7_seven_packet_height, pixels))
|
2017-03-10 10:33:50 +01:00
|
|
|
break;
|
|
|
|
}
|
2016-09-06 19:01:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* stop */
|
2017-03-10 00:02:37 +01:00
|
|
|
free(pixels);
|
2016-09-25 22:01:42 +02:00
|
|
|
return (0);
|
2016-09-06 19:01:37 +02:00
|
|
|
}
|