vbagx/source/vba/gb/gbPrinter.cpp

250 lines
5.7 KiB
C++
Raw Normal View History

2008-09-14 22:40:26 +02:00
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
// Copyright (C) 1999-2003 Forgotten
// Copyright (C) 2004 Forgotten and the VBA development team
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or(at your option)
// any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <stdio.h>
#include <string.h>
#include "../GBA.h"
u8 gbPrinterStatus = 0;
int gbPrinterState = 0;
u8 gbPrinterData[0x280*9];
u8 gbPrinterPacket[0x400];
int gbPrinterCount = 0;
int gbPrinterDataCount = 0;
int gbPrinterDataSize = 0;
int gbPrinterResult = 0;
bool gbPrinterCheckCRC()
{
u16 crc = 0;
for(int i = 2; i < (6+gbPrinterDataSize); i++)
{
crc += gbPrinterPacket[i];
}
int msgCrc = gbPrinterPacket[6+gbPrinterDataSize] +
(gbPrinterPacket[7+gbPrinterDataSize]<<8);
return msgCrc == crc;
}
void gbPrinterReset()
{
gbPrinterState = 0;
gbPrinterDataSize = 0;
gbPrinterDataCount = 0;
gbPrinterCount = 0;
gbPrinterStatus = 0;
gbPrinterResult = 0;
}
void gbPrinterShowData()
{
systemGbPrint(gbPrinterData,
gbPrinterPacket[6],
gbPrinterPacket[7],
gbPrinterPacket[8],
gbPrinterPacket[9]);
/*
allegro_init();
install_keyboard();
set_gfx_mode(GFX_AUTODETECT, 160, 144, 0, 0);
PALETTE pal;
pal[0].r = 255;
pal[0].g = 255;
pal[0].b = 255;
pal[1].r = 168;
pal[1].g = 168;
pal[1].b = 168;
pal[2].r = 96;
pal[2].g = 96;
pal[2].b = 96;
pal[3].r = 0;
pal[3].g = 0;
pal[3].b = 0;
set_palette(pal);
acquire_screen();
u8 *data = gbPrinterData;
for(int y = 0; y < 0x12; y++) {
for(int x = 0; x < 0x14; x++) {
for(int k = 0; k < 8; k++) {
int a = *data++;
int b = *data++;
for(int j = 0; j < 8; j++) {
int mask = 1 << (7-j);
int c = 0;
if(a & mask)
c++;
if(b & mask)
c+=2;
putpixel(screen, x*8+j, y*8+k, c);
}
}
}
}
release_screen();
while(!keypressed()) {
}
*/
}
void gbPrinterReceiveData()
{
if(gbPrinterPacket[3])
{ // compressed
u8 *data = &gbPrinterPacket[6];
u8 *dest = &gbPrinterData[gbPrinterDataCount];
int len = 0;
while(len < gbPrinterDataSize)
{
u8 control = *data++;
if(control & 0x80)
{ // repeated data
control &= 0x7f;
control += 2;
memset(dest, *data++, control);
len += control;
dest += control;
}
else
{ // raw data
control++;
memcpy(dest, data, control);
dest += control;
data += control;
len += control;
}
}
}
else
{
memcpy(&gbPrinterData[gbPrinterDataCount],
&gbPrinterPacket[6],
gbPrinterDataSize);
gbPrinterDataCount += gbPrinterDataSize;
}
}
void gbPrinterCommand()
{
switch(gbPrinterPacket[2])
{
case 0x01:
// reset/initialize packet
gbPrinterDataCount = 0;
gbPrinterStatus = 0;
break;
case 0x02:
// print packet
gbPrinterShowData();
break;
case 0x04:
// data packet
gbPrinterReceiveData();
break;
case 0x0f:
// NUL packet
break;
}
}
u8 gbPrinterSend(u8 b)
{
switch(gbPrinterState)
{
case 0:
gbPrinterCount = 0;
// receiving preamble
if(b == 0x88)
{
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
}
else
{
// todo: handle failure
gbPrinterReset();
}
break;
case 1:
// receiving preamble
if(b == 0x33)
{
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
}
else
{
// todo: handle failure
gbPrinterReset();
}
break;
case 2:
// receiving header
gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCount == 6)
{
gbPrinterState++;
gbPrinterDataSize = gbPrinterPacket[4] + (gbPrinterPacket[5]<<8);
}
break;
case 3:
// receiving data
if(gbPrinterDataSize)
{
gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCount == (6+gbPrinterDataSize))
{
gbPrinterState++;
}
break;
}
gbPrinterState++;
// intentionally move to next if no data to receive
case 4:
// receiving CRC
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterState++;
break;
case 5:
// receiving CRC-2
gbPrinterPacket[gbPrinterCount++] = b;
if(gbPrinterCheckCRC())
{
gbPrinterCommand();
}
gbPrinterState++;
break;
case 6:
// receiving dummy 1
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterResult = 0x81;
gbPrinterState++;
break;
case 7:
// receiving dummy 2
gbPrinterPacket[gbPrinterCount++] = b;
gbPrinterResult = gbPrinterStatus;
gbPrinterState = 0;
gbPrinterCount = 0;
break;
}
return gbPrinterResult;
}