#include <windows.h>
#include "xliveless.h"

#pragma pack(push, 1)
struct TrackNode {
	WORD	wX;
	WORD	wY;
	WORD	wZ;
	WORD	_f6;
	WORD	_f8;
	BYTE	bIsStation;
	BYTE	_fB;
};

#pragma pack (pop)

__declspec(align(16)) struct Vector3 {
	float	x;
	float	y;
	float	z;
	float	__pad;	// TODO: а нужно ли это? проверить: возможно align автоматически добавит это поле	
};


void (__cdecl *CTrackManager__readTrackFile) (char * pszFileName, TrackNode ** ppTrackNodes, DWORD * pdwTrackSize, 
	float * pfTrackLength, DWORD * pdwStationNameCount, Vector3 * ppvStationCoords, 
	float * ppfStationDistances, BYTE * pnbStationTypes, DWORD * pdwStationNameHashes, int * pnStationNodeNumbers) = 
(void (__cdecl *)(char *, TrackNode**, DWORD *, float *, DWORD *, Vector3 *, float *, BYTE *, DWORD *, int *))
(0xAC1880+dwLoadOffset);

#define TRACK_COUNT		12
#define STATIONS_PER_TRACK      20

char * trackFileNames[TRACK_COUNT] = {
"common:/data/paths/TracksQueens.dat",		// 0
"common:/data/paths/TracksQueens2.dat",		// 1
"common:/data/paths/TracksBronx.dat", 		// 2
"common:/data/paths/TracksBronx2.dat",		// 3
"common:/data/paths/cablecar_northern.dat", 	// 4
"common:/data/paths/cablecar_southern.dat",	// 5
"common:/data/paths/TracksPlaneOnGround1.dat",	// 6
"common:/data/paths/TracksPlaneOnGround2.dat",	// 7
"common:/data/paths/TracksPlaneInFlight.dat",	// 8
"common:/data/paths/TracksPlaneInFlight2.dat",	// 9
"common:/data/paths/TracksPlaneInFlight3.dat",	// 10
"common:/data/paths/TracksPlaneInFlight4.dat"	// 11
};

TrackNode ** _trackNodes = (TrackNode **)(0x14D278C+dwLoadOffset);
DWORD * _trackSizes = (DWORD *)(0x14D275C+dwLoadOffset);
float * _trackLengths = (float *)(0x14D17A8+dwLoadOffset);
DWORD * _stationNameCounts = (DWORD *)(0x14D1BD8+dwLoadOffset);
Vector3 * _stationCoords = (Vector3 *)(0x14D27C0+dwLoadOffset);
float * _stationDistances = (float *)(0x14D1FD0+dwLoadOffset);
BYTE * _stationTypes = (BYTE *)(0x14D16B8+dwLoadOffset);
DWORD * _stationNameHashes = (DWORD *)(0x14D2398+dwLoadOffset);
int * _stationNodeNumbers = (int *)(0x14D1C10+dwLoadOffset);

void CTrackManager__readTrackFiles () {
	trace ("readTrackFiles  called\n");
	
//	for (DWORD i = 0; i < TRACK_COUNT; i++) { 
//		trace ("TRACK: '%s', %08x, %08x, %08x\n", trackFileNames[i], (DWORD)(_trackNodes+i), (DWORD)(_trackSizes+i), 
//			(DWORD)(_stationDistances+i*STATIONS_PER_TRACK));
//	}
//	ExitProcess(0);

	for (DWORD i = 0; i < TRACK_COUNT; i++) {
		if (trackNodes[i] == NULL)
			CTrackManager__readTrackFile (
				trackFileNames[i], 
				_trackNodes+i, 
				_trackSizes+i, 
				_trackLengths+i,
				_stationNameCounts+i, 
				_stationCoords+i*STATIONS_PER_TRACK, 
				_stationDistances+i*STATIONS_PER_TRACK,
				_stationTypes+i*STATIONS_PER_TRACK, 
				_stationNameHashes+i*STATIONS_PER_TRACK,
				_stationNodeNumbers+i*STATIONS_PER_TRACK);
		trace ("TRACK: '%s' => %d nodes, %d total length\n", trackFileNames[i], _trackSizes[i], (int)(_trackLengths[i]));
	}
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved) {
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		if (dwGameVersion == 0x00010004) {
			injectFunction (0xAC1D40, (DWORD)CTrackManager__readTrackFiles);
			trace ("[tracks plugin]: successfully loaded\n");
		} else 
			trace ("[tracks plugin]: incorrect game version (expected 1.0.4 EN)\n");
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}
