// Step2.cpp : implementation file
//
#include "stdafx.h"
#include <memory.h>
#include "romdump.h"
#include "Step2.h"
#include "Serial.h"

#define STEPS	8+14
#define STEPIT	dlg->m_Progress.StepIt()

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CStep2 dialog


CStep2::CStep2(CWnd* pParent /*=NULL*/)
	: CDialog(CStep2::IDD, pParent)
{
	//{{AFX_DATA_INIT(CStep2)
	//}}AFX_DATA_INIT
}


void CStep2::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CStep2)
	DDX_Control(pDX, IDC_STATE, m_State);
	DDX_Control(pDX, IDOK, m_Ok);
	DDX_Control(pDX, IDC_PROGRESS, m_Progress);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CStep2, CDialog)
	//{{AFX_MSG_MAP(CStep2)
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CStep2 message handlers

int CStep2::OpenError()
{
	MessageBox("Fatal error:\nCannot open serial port !","ROMDump Wizard - Error",MB_ICONSTOP|MB_OK);
	EndDialog(IDCANCEL);
	return 0;
}

int CStep2::WriteError()
{
	MessageBox("Fatal error:\nCannot write to serial port !","ROMDump Wizard - Error",MB_ICONSTOP|MB_OK);
	EndDialog(IDCANCEL);
	return 0;
}

int CStep2::ReadError()
{
	MessageBox("Fatal error:\nCannot read from serial port !","ROMDump Wizard - Error",MB_ICONSTOP|MB_OK);
	EndDialog(IDCANCEL);
	return 0;
}

int CStep2::ProtocolError(int i)
{
	char buffer[32];
	wsprintf(buffer, "Protocol Error (%i)", i);
	MessageBox(buffer,"ROMDump Wizard - Error",MB_ICONSTOP|MB_OK);
	EndDialog(IDCANCEL);
	return 0;
}

char *ROMDump[] =
{
	"GROB 8 553 D9D20D8A812BF8111920BB000D9D2049703CCD20F14008F511108FC1523203481000C",	// 1
	"A13114B31A48409EA508508418F2D7608FD8F3520340FFFF0EF681AF048F2D7608FD8F3520340FFF",	// 2
	"F0EF681AF031F0110080820815901DD0808206159081AF13340FFF68B61481AF0181AF1CD5340FFF",	// 3
	"68BD40D5EC5606C7181AF0277E1808240000781AF0381AF13340FFF78B66060108706063416D9081",	// 4
	"AF0181AF1CD5340FFF78BD40D5EC5606A1181AF02870C17B21341F00F8FFB620791165F034000F78",	// 5
	"0434000E7804725134000FF80534000F780534000FF80534000E7805808240000881AF0381AF1334",	// 6
	"0FFFB8B63581AF0181AF1CD5340FFFB8BD40D5EC5606E6081AF027480345F00C8FAC620727080824",	// 7
	"0000C81AF0381AF1381AF0181AF1CD5340FFFF8BD40D5EC4A181AF0271308518F5F008732077711F",	// 8
	"0110080820015908F5E0108D3415081B58082415000C2134870D01F1F0076A001F5F008808240510",	// 9
	"0F4D8152715771547151716F17FCD57E01861531B000F714E1BA960814E8089714C1B8210014C340",	//10
	"000C80480481AF1113081AF1281AF00747031A37CD0156776507E9016F81AF10818F8F52D861B334",	//11
	"0000C8058058058051BA960814E8088714C1B8210014C1B040F714E01AF531F0AE76C20132D61328",	//12
	"0F480F080F480F380F180F3D53140AE7AE2A897D10BF5A6F5FE0131D07A2031A07220018082103A6",	//13
	"280821939EEC08082170A621F2110015B0808707F1D6114D010000000000000000B2130B2130",		//14
	NULL
};

DWORD WINAPI Step2_Thread(LPVOID lpdlg)
{
	FILE *rom;
	CStep2 *dlg = (CStep2*)lpdlg;
	BYTE *res;
	DWORD len;
	int i, j;

//1-open serial port
	if (SerialOpen()==FALSE) return dlg->OpenError();
	STEPIT;
//2-ask for server mode
	if (dlg->MessageBox("Please put your HP48 in SERVER mode.","ROMDump Wizard",MB_OKCANCEL)==IDCANCEL)
	{
		dlg->EndDialog(IDCANCEL);
		return 0;
	}
	STEPIT;
//3-delete ROMDump if it already exists
	res = (BYTE*)CommandPKT("CLEAR HEX 'ROMDump' PURGE",&len);
	if (res==NULL) dlg->ProtocolError(1);
	free(res);
	STEPIT;
//4-send ROMDump to the HP48
	do SendPKT('S',0,"~* @-#Y3"); while (RecvPKT()!='Y');
	j = 0;
	SendPKT('F',++j,"ROMDump");
	if (RecvPKT()!='Y') dlg->ProtocolError(4);
	STEPIT;
	i=0;
	while (ROMDump[i])
	{
		SendPKT('D',++j,ROMDump[i]);
		if (RecvPKT()!='Y') dlg->ProtocolError(5+10*i);
		i++;
		STEPIT;
	}
	SendPKT('Z',++j,"");
	if (RecvPKT()!='Y') dlg->ProtocolError(6);
	SendPKT('B',++j,"");
	if (RecvPKT()!='Y') dlg->ProtocolError(7);
//5-assemble ROMDump
	res = (BYTE*)CommandPKT("ROMDump OBJ#Í ##4017h SYSEVAL ##56B6h SYSEVAL DROP NEWOB 'ROMDump' STO",&len);
	if (res==NULL) dlg->ProtocolError(1);
	free(res);
	STEPIT;
//6-execute ROMDump to get HP48 type (G/S)
//	dlg->MessageBox("Your HP48 will say 'Port Closed'. Just ignore it.","ROMDump Wizard", MB_OK);
	res = (BYTE*)DumpRange(0x7FFF0,0x7FFFF);
	if ((res[6]=='4')&&(res[7]=='8'))
		Type = HP48S;
	else
		Type = HP48G;
	free(res);
	STEPIT;
//7-ok, now display the type and dump
	dlg->m_State.SetWindowText("Now dumping the ROM...");
	switch (Type)
	{
	case HP48S:
		dlg->MessageBox("An HP48S/SX was detected.\n","ROMDump Wizard",MB_OK);
		res = DumpRangeBin(dlg,0x00000,0x7FFFF);
		if (RecvPKT()!='E') dlg->ProtocolError(9);
		if (res==NULL)
		{
			dlg->MessageBox("Error while transfering the ROM.\n","ROMDump Wizard",MB_OK);
			dlg->EndDialog(IDCANCEL);
			return 0;
		}
		if (!CheckROM(res,HP48S))
		{
			dlg->MessageBox("ROM CRC check fails. Try again.\n","ROMDump Wizard",MB_OK);
			dlg->EndDialog(IDCANCEL);
			return 0;
		}
		rom = fopen("ROM.48S","wb");
		for (i=0; i<=0x7FFFF; i++) fputc(res[i]&0xF, rom);
		fclose(rom);
		break;
	case HP48G:
		dlg->MessageBox("An HP48G/GX was detected.\n","ROMDump Wizard",MB_OK);
		res = DumpRangeBin(dlg,0x00000,0xFFFFF);
		if (res==NULL)
		{
			dlg->MessageBox("Error while transfering the ROM.\n","ROMDump Wizard",MB_OK);
			dlg->EndDialog(IDCANCEL);
			return 0;
		}
		if (!CheckROM(res,HP48G))
		{
			dlg->MessageBox("ROM CRC check fails. Try again.\n","ROMDump Wizard",MB_OK);
			dlg->EndDialog(IDCANCEL);
			return 0;
		}
		rom = fopen("ROM.48G","wb");
		for (i=0; i<=0xFFFFF; i++) fputc(res[i]&0xF, rom);
		fclose(rom);
		break;
	}
	STEPIT;
//8-delete ROMDump
	res = (BYTE*)CommandPKT("'ROMDump' PURGE",&len);
	if (res==NULL) dlg->ProtocolError(1);
	free(res);
	STEPIT;
// All done !
	dlg->EndDialog(IDOK);
	return 0;
}

BOOL CStep2::OnInitDialog() 
{
	DWORD id_thread;
	CDialog::OnInitDialog();

	m_Progress.SetRange(0,STEPS);
	m_Progress.SetStep(1);
	m_Progress.SetPos(0);
	h_thread = CreateThread(NULL,0,&Step2_Thread,(LPVOID)this,0,&id_thread);
	return TRUE;
}

void CStep2::OnDestroy() 
{
	TerminateThread(h_thread,(DWORD)(-1));
	SerialClose();
	CDialog::OnDestroy();
}
