rlm@1: #include <cstdio>
rlm@1: #include <cstring>
rlm@1: 
rlm@1: #include "../common/System.h"
rlm@1: #include "gbPrinter.h"
rlm@1: 
rlm@1: u8  gbPrinterStatus = 0;
rlm@1: int gbPrinterState  = 0;
rlm@1: u8  gbPrinterData[0x280*9];
rlm@1: u8  gbPrinterPacket[0x400];
rlm@1: int gbPrinterCount     = 0;
rlm@1: int gbPrinterDataCount = 0;
rlm@1: int gbPrinterDataSize  = 0;
rlm@1: int gbPrinterResult    = 0;
rlm@1: 
rlm@1: bool gbPrinterCheckCRC()
rlm@1: {
rlm@1: 	u16 crc = 0;
rlm@1: 
rlm@1: 	for (int i = 2; i < (6+gbPrinterDataSize); i++)
rlm@1: 	{
rlm@1: 		crc += gbPrinterPacket[i];
rlm@1: 	}
rlm@1: 
rlm@1: 	int msgCrc = gbPrinterPacket[6+gbPrinterDataSize] +
rlm@1: 	             (gbPrinterPacket[7+gbPrinterDataSize]<<8);
rlm@1: 
rlm@1: 	return msgCrc == crc;
rlm@1: }
rlm@1: 
rlm@1: void gbPrinterReset()
rlm@1: {
rlm@1: 	gbPrinterState     = 0;
rlm@1: 	gbPrinterDataSize  = 0;
rlm@1: 	gbPrinterDataCount = 0;
rlm@1: 	gbPrinterCount     = 0;
rlm@1: 	gbPrinterStatus    = 0;
rlm@1: 	gbPrinterResult    = 0;
rlm@1: }
rlm@1: 
rlm@1: void gbPrinterShowData()
rlm@1: {
rlm@1: 	systemGbPrint(gbPrinterData,
rlm@1: 	              gbPrinterPacket[6],
rlm@1: 	              gbPrinterPacket[7],
rlm@1: 	              gbPrinterPacket[8],
rlm@1: 	              gbPrinterPacket[9]);
rlm@1: 	/*
rlm@1: 	   allegro_init();
rlm@1: 	   install_keyboard();
rlm@1: 	   set_gfx_mode(GFX_AUTODETECT, 160, 144, 0, 0);
rlm@1: 	   PALETTE pal;
rlm@1: 	   pal[0].r = 255;
rlm@1: 	   pal[0].g = 255;
rlm@1: 	   pal[0].b = 255;
rlm@1: 	   pal[1].r = 168;
rlm@1: 	   pal[1].g = 168;
rlm@1: 	   pal[1].b = 168;
rlm@1: 	   pal[2].r = 96;
rlm@1: 	   pal[2].g = 96;
rlm@1: 	   pal[2].b = 96;
rlm@1: 	   pal[3].r = 0;
rlm@1: 	   pal[3].g = 0;
rlm@1: 	   pal[3].b = 0;
rlm@1: 	   set_palette(pal);
rlm@1: 	   acquire_screen();
rlm@1: 	   u8 *data = gbPrinterData;
rlm@1: 	   for(int y = 0; y < 0x12; y++) {
rlm@1: 	   for(int x = 0; x < 0x14; x++) {
rlm@1: 	    for(int k = 0; k < 8; k++) {
rlm@1: 	      int a = *data++;
rlm@1: 	      int b = *data++;
rlm@1: 	      for(int j = 0; j < 8; j++) {
rlm@1: 	        int mask = 1 << (7-j);
rlm@1: 	        int c = 0;
rlm@1: 	        if(a & mask)
rlm@1: 	          c++;
rlm@1: 	        if(b & mask)
rlm@1: 	          c+=2;
rlm@1: 	        putpixel(screen, x*8+j, y*8+k, c);
rlm@1: 	      }
rlm@1: 	    }
rlm@1: 	   }
rlm@1: 	   }
rlm@1: 	   release_screen();
rlm@1: 	   while(!keypressed()) {
rlm@1: 	   }
rlm@1: 	 */
rlm@1: }
rlm@1: 
rlm@1: void gbPrinterReceiveData()
rlm@1: {
rlm@1: 	if (gbPrinterPacket[3]) // compressed
rlm@1: 	{
rlm@1: 		u8 *data = &gbPrinterPacket[6];
rlm@1: 		u8 *dest = &gbPrinterData[gbPrinterDataCount];
rlm@1: 		int len  = 0;
rlm@1: 		while (len < gbPrinterDataSize)
rlm@1: 		{
rlm@1: 			u8 control = *data++;
rlm@1: 			if (control & 0x80) // repeated data
rlm@1: 			{
rlm@1: 				control &= 0x7f;
rlm@1: 				control += 2;
rlm@1: 				memset(dest, *data++, control);
rlm@1: 				len  += control;
rlm@1: 				dest += control;
rlm@1: 			}
rlm@1: 			else // raw data
rlm@1: 			{
rlm@1: 				control++;
rlm@1: 				memcpy(dest, data, control);
rlm@1: 				dest += control;
rlm@1: 				data += control;
rlm@1: 				len  += control;
rlm@1: 			}
rlm@1: 		}
rlm@1: 	}
rlm@1: 	else
rlm@1: 	{
rlm@1: 		memcpy(&gbPrinterData[gbPrinterDataCount],
rlm@1: 		       &gbPrinterPacket[6],
rlm@1: 		       gbPrinterDataSize);
rlm@1: 		gbPrinterDataCount += gbPrinterDataSize;
rlm@1: 	}
rlm@1: }
rlm@1: 
rlm@1: void gbPrinterCommand()
rlm@1: {
rlm@1: 	switch (gbPrinterPacket[2])
rlm@1: 	{
rlm@1: 	case 0x01:
rlm@1: 		// reset/initialize packet
rlm@1: 		gbPrinterDataCount = 0;
rlm@1: 		gbPrinterStatus    = 0;
rlm@1: 		break;
rlm@1: 	case 0x02:
rlm@1: 		// print packet
rlm@1: 		gbPrinterShowData();
rlm@1: 		break;
rlm@1: 	case 0x04:
rlm@1: 		// data packet
rlm@1: 		gbPrinterReceiveData();
rlm@1: 		break;
rlm@1: 	case 0x0f:
rlm@1: 		// NUL packet
rlm@1: 		break;
rlm@1: 	}
rlm@1: }
rlm@1: 
rlm@1: u8 gbPrinterSend(u8 byte)
rlm@1: {
rlm@1: 	switch (gbPrinterState)
rlm@1: 	{
rlm@1: 	case 0:
rlm@1: 		gbPrinterCount = 0;
rlm@1: 		// receiving preamble
rlm@1: 		if (byte == 0x88)
rlm@1: 		{
rlm@1: 			gbPrinterPacket[gbPrinterCount++] = byte;
rlm@1: 			gbPrinterState++;
rlm@1: 		}
rlm@1: 		else
rlm@1: 		{
rlm@1: 			// todo: handle failure
rlm@1: 			gbPrinterReset();
rlm@1: 		}
rlm@1: 		break;
rlm@1: 	case 1:
rlm@1: 		// receiving preamble
rlm@1: 		if (byte == 0x33)
rlm@1: 		{
rlm@1: 			gbPrinterPacket[gbPrinterCount++] = byte;
rlm@1: 			gbPrinterState++;
rlm@1: 		}
rlm@1: 		else
rlm@1: 		{
rlm@1: 			// todo: handle failure
rlm@1: 			gbPrinterReset();
rlm@1: 		}
rlm@1: 		break;
rlm@1: 	case 2:
rlm@1: 		// receiving header
rlm@1: 		gbPrinterPacket[gbPrinterCount++] = byte;
rlm@1: 		if (gbPrinterCount == 6)
rlm@1: 		{
rlm@1: 			gbPrinterState++;
rlm@1: 			gbPrinterDataSize = gbPrinterPacket[4] + (gbPrinterPacket[5]<<8);
rlm@1: 		}
rlm@1: 		break;
rlm@1: 	case 3:
rlm@1: 		// receiving data
rlm@1: 		if (gbPrinterDataSize)
rlm@1: 		{
rlm@1: 			gbPrinterPacket[gbPrinterCount++] = byte;
rlm@1: 			if (gbPrinterCount == (6+gbPrinterDataSize))
rlm@1: 			{
rlm@1: 				gbPrinterState++;
rlm@1: 			}
rlm@1: 			break;
rlm@1: 		}
rlm@1: 		gbPrinterState++;
rlm@1: 	// intentionally move to next if no data to receive
rlm@1: 	case 4:
rlm@1: 		// receiving CRC
rlm@1: 		gbPrinterPacket[gbPrinterCount++] = byte;
rlm@1: 		gbPrinterState++;
rlm@1: 		break;
rlm@1: 	case 5:
rlm@1: 		// receiving CRC-2
rlm@1: 		gbPrinterPacket[gbPrinterCount++] = byte;
rlm@1: 		if (gbPrinterCheckCRC())
rlm@1: 		{
rlm@1: 			gbPrinterCommand();
rlm@1: 		}
rlm@1: 		gbPrinterState++;
rlm@1: 		break;
rlm@1: 	case 6:
rlm@1: 		// receiving dummy 1
rlm@1: 		gbPrinterPacket[gbPrinterCount++] = byte;
rlm@1: 		gbPrinterResult = 0x81;
rlm@1: 		gbPrinterState++;
rlm@1: 		break;
rlm@1: 	case 7:
rlm@1: 		// receiving dummy 2
rlm@1: 		gbPrinterPacket[gbPrinterCount++] = byte;
rlm@1: 		gbPrinterResult = gbPrinterStatus;
rlm@1: 		gbPrinterState  = 0;
rlm@1: 		gbPrinterCount  = 0;
rlm@1: 		break;
rlm@1: 	}
rlm@1: 	return gbPrinterResult;
rlm@1: }
rlm@1: