vbagx/source/vba/dmg/gbPrinter.cpp
2008-10-18 06:49:04 +00:00

230 lines
5.5 KiB
C++

// 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 "../agb/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;
}