Welcome to TA: Kingdoms |
|
| Wqaopl's tnt maker | |
| | |
Author | Message |
---|
$_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Wqaopl's tnt maker Tue Aug 02, 2016 3:04 pm | |
| Wqapol still around? Mind sharing any info on interpreting .tnt road/item maps on tnt files? I've been messing around with tnt file from kmp lately and I got to render all of the map info (including palette support) except roadmap and item positions. Upon doing some research I found TNT Maker by wqaopl which displays them correctly (downloaded at alltakdownloads henrique site) And in that tool Wqaopl got them right (although minimap and tabmap arent finished) so mind if we trade some knowledge ? I see you were using greyscale to render the minimap and big minimap and in the README you mention you still need to do research on how to implement the color palettes. I did greyscale for the heightmap too: But for the minimap and big minimap I managed to decode the palettes and this was the result: and My poor attempt at rendering the road/itemmaps (?): Anyway to get the palette just grab the .pcx file for the map race (ex: taros.pcx) and skip to offset 0x84 and read from there in RGB order (3 bytes per color) and the palette has 256 colors (so 768 bytes total) and you just access eachcolor normally by indexing to the palette
Last edited by $_Spagg on Wed Aug 03, 2016 5:50 pm; edited 3 times in total | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Tue Aug 02, 2016 3:07 pm | |
| Edit: I dunno what the other values signify in the .pcx file, I just skipped bytes until something worked!
Aalso this means it should be easy to change the palette too since theyre just in raw RGB order. Proof: https://i.imgur.com/kiy9Qg0.png
Edit- the palette size is actually 256 since the length of the file from 0x84 to the end of the file is 768 (768 / 3 = 256), not 255 (miscalculated that part, was wondering what would happen with a color index of 255) | |
| | | rammstein
Posts : 74 Reputation : 5 Join date : 2010-04-16 Age : 32 Location : Sweden
| Subject: Re: Wqaopl's tnt maker Wed Aug 03, 2016 6:07 pm | |
| It was some time since I last worked with tnt files, but I think I used the following post on TA Universe for help: http://www.tauniverse.com/forum/showthread.php?t=23627
Maybe it will be of use for you. | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Thu Aug 04, 2016 8:17 am | |
| That was a very helpful read, thanks for the link | |
| | | Wqaopl
Posts : 216 Reputation : 2 Join date : 2008-08-14
| Subject: Re: Wqaopl's tnt maker Fri Aug 05, 2016 5:51 am | |
| sorry i did not see your post for ages
the tnt file is quite simple ish lets see if i can remeber whow it goes struct TNTHEDDER{ DWORD FileID; DWORD Width; DWORD Height; DWORD SeaLevel; DWORD LHeightMap; DWORD LAttributes; DWORD LFeatureNames; DWORD FeaturesNb; DWORD LTerrainNames; DWORD LUmapping; DWORD LVmapping; DWORD LSmallMiniMap; DWORD LBigMiniMap; };
LHeightMap is a one byte gray scale using width * hight for size LAttributes is a two byte map of objects using width * hight for size the values of 65531 and 65535 are the road map and blocking map. the other valuse map to the feature list.
LFeatureNames is a 132 byte char string with FeaturesNb providing the nuber of names LTerrainNames i a 4 byte list using width * hight for size and corasponds to the bitmap images in the hpi files
the uv map is the 32 pixel offset? in the terrain bitmap and is each a one byte list the size of each is (width /2)*(hight/2)
for the mini maps the first 8 bytes are the with and hight respectively with a 4 byte bitmap
if you want a better anser looking at the tnt file itself wil probably yeals better ansers =) but i hope this helps. | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Mon Aug 08, 2016 2:14 pm | |
| ^ Yep, that helps, even though I already had most of the header figured out (the pictures from the post at the top that I generated with C++) Except for the "features" part which should be easy now with your post and rammenstein's I had no idea the word the at 0x0C was for the sea height also (since even maps without any water seem to have sea height too), I'm looking into what does that even do or how the sea height affects the map Anyway soon my desktop kmp visualiser will be alive | |
| | | Vhaerun
Posts : 118 Reputation : 12 Join date : 2014-01-12 Age : 44 Location : VA, USA
| Subject: Re: Wqaopl's tnt maker Mon Aug 08, 2016 2:53 pm | |
| Some good work and knowledge. Also, you two should try your minds at making a TAF editing/making program much like GafBuilder. If you do decide to try and make a TAF editor, I can point you to the relevent information if you do not know it. | |
| | | Wqaopl
Posts : 216 Reputation : 2 Join date : 2008-08-14
| Subject: Re: Wqaopl's tnt maker Mon Aug 08, 2016 3:24 pm | |
| my next aim was to try and use hpi file so i could make a map editer with a full rainge of options, help i needed =( | |
| | | Vhaerun
Posts : 118 Reputation : 12 Join date : 2014-01-12 Age : 44 Location : VA, USA
| Subject: Re: Wqaopl's tnt maker Mon Aug 08, 2016 3:36 pm | |
| Much like TA's Annihilator map making program? | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Mon Aug 08, 2016 3:39 pm | |
| - Vhaerun I dont know much about the GAF builder (I dont even remember what is a "TAF") what would be the changes between the existing GAF builder and the new one? I like the idea but i haven't used the GAF builder much in the past - Wqaopl I have an HPI reader function in C++ which im using to grab the TNT bytes directly from the kmp The code is all in Qt C++ though... I can post the source later if you want, although I should probably organize it better... Since you talked about map editor, I tried making a map editor too, found way too confusing because of how strange the tiles are... - Spoiler:
Basically the source of my despair is that the width/height of the tile representation is disproportional, the map is organized in rows of tilenames (the ones in the terrain) and the real pixel dimension is different from the width and height, tiles are bigger in width than they are in height (probably to create the angular view in the game, since you don't actually see the map from the top to bottom, but kinda angled from the top to bottom, which is why the terrain representation is weird and the map ends up with smaller height than it should be) Found too boring to wrap my head around it so i just moved to a next project | |
| | | Vhaerun
Posts : 118 Reputation : 12 Join date : 2014-01-12 Age : 44 Location : VA, USA
| Subject: Re: Wqaopl's tnt maker Mon Aug 08, 2016 3:54 pm | |
| Gaf files are the animation files used mainly in TA; in TA:K, taf files are used which according to this post here at TAUniverse: Taf File format by Xon are basically gaf files but use a different compression and are 16 bit images versus 8 bit. The source code is here: GafBuilder1.2 but I do not know how to compile the source to make it execute. | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Mon Aug 08, 2016 4:11 pm | |
| I see, once I finish KMP visualizer and HPI Tools (combination of hpi viewer and hpi pack in one program, with drag&drop facilities) I'd like to help with this | |
| | | Wqaopl
Posts : 216 Reputation : 2 Join date : 2008-08-14
| Subject: Re: Wqaopl's tnt maker Mon Aug 08, 2016 4:23 pm | |
| i can see making a hightmap editer confusing but a map editer should start out just stiching TNT info together as its all the same thing and ment to fit together.
the hpi c++ code will help me whatever libary it uses the referance im using is just so slightly off.
as for a gaf/taf editer it looks like boring info/entry management and is back of the list of intrests =(
allthow i was planing on creating a program that delt with all the TAK files | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Mon Aug 08, 2016 4:34 pm | |
| I dont have the full hpi code C++ on this machine (my map previewer is navigating the kmp directly and dirty, without fulyl reading the headers and skimming straight into the first .tnt HPI entry it finds) But I have a java prototype which I make a long time ago: it's kinda dirty too but it should work (I used the HPI view as reference) https://drive.google.com/file/d/0ByHfuH4MPaOXXzV0YnJMd1NTLWs/view?usp=sharing
As for the qt code I'm making a standalone version in parallel to an HPI tool program (which like I said above, is intended to make it easy to manipulate HPI files by combining both the ability to view HPIs and pack them back in one program) But that should take more time since I have the map thing as priority for now | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Mon Aug 08, 2016 4:39 pm | |
| Also if you don't already have the source to HPI viewer you can download here: https://drive.google.com/open?id=0ByHfuH4MPaOXTXZKRGFFMEM4OGc
| |
| | | Vhaerun
Posts : 118 Reputation : 12 Join date : 2014-01-12 Age : 44 Location : VA, USA
| Subject: Re: Wqaopl's tnt maker Mon Aug 08, 2016 8:10 pm | |
| Understandable on the TAF program. When you get the time and are real bored Before Pocket Geek left us, he shared his version of HPI view which can read TAF files. I do not know if it is here or at one of the other sites, but it is HPI view 1.95pg. Now if you use that program to open data hpi or IPdata hpi and look in the anims folder, you can see how wonderful the TAF animations are. As an aside here is a bit of code from Pocket geek's viewtaf.c: // // TAF Viewer Code // #include #include #include #include #include
#include "resource.h" #include "hpiview.h" #include "splitstuf.h" #include "viewstuf.h" #include "palette.h"
#pragma pack(1)
typedef struct _VIEWOPTION { int option; int Length; int Version; char *Name; char *buff; TAFHEADER *Header; TAFENTRY *CurEntry; TAFFRAMEENTRY *FrameEntry; TAFFRAMEDATA **gfd; HPALETTE hpal; HDC hdc; int CurFrame; int xofs; int yofs; } VIEWOPTION;
#pragma pack()
const char ViewTafJpgWindowClass[] = "HPIViewTafJpg"; int ViewTafClassRegistered = FALSE;
void FreeFrameStuff(VIEWOPTION *vo) { if (vo->gfd) { FreeMem(vo->gfd); vo->gfd = NULL; } }
void FrameToHDC(HDC hdc, VIEWOPTION *vo, TAFFRAMEDATA *gfd) { unsigned char *frame; int bcount; int count; int repeat; unsigned char mask; int xcount; int ycount; int y; COLORREF *color; int xofs = vo->xofs - gfd->XPos; int yofs = vo->yofs - gfd->YPos;
frame = vo->buff + gfd->PtrFrameData; switch (vo->Version) { case HPI_V1 : color = TAColor; break; case HPI_V2 : color = TAKColor; break; default : color = TAColor; } if (gfd->Compressed==1) { for (ycount = 0; ycount < gfd->Height; ycount++) { bcount = *((short *) frame); frame += sizeof(short); y = yofs + ycount; xcount = xofs; count = 0; while (count < bcount) { mask = (unsigned char) frame[count++]; if ((mask & 0x01) == 0x01) { // transparent xcount += (mask >> 1); } else if ((mask & 0x02) == 0x02) { // repeat next byte repeat = (mask >> 2) + 1; while (repeat--) { SetPixelV(hdc, xcount++, y, color[frame[count]]); } count++; } else { repeat = (mask >> 2) + 1; while (repeat--) { SetPixelV(hdc, xcount++, y, color[frame[count++]]); } } } frame += bcount; } } else if(gfd->Compressed==0){ for (ycount = 0; ycount < gfd->Height; ycount++) { for (xcount = 0; xcount < gfd->Width; xcount++) { SetPixelV(hdc, xcount+xofs, ycount+yofs, color[*frame++]); } } } else if(gfd->Compressed==4) { COLORREF color=0; BYTE* pColor = (BYTE*)&color; for (ycount = 0; ycount < gfd->Height; ycount++) { for (xcount = 0; xcount < gfd->Width; xcount++){ // AAAARRRRBBBBGGGG WORD pixel = *(WORD*)frame; pColor[0] = (pixel & 0xF000) >> 8; pColor[1] = (pixel & 0x00F0); pColor[2] = (pixel & 0x000F) << 4; pColor[3] = (pixel & 0xF000) >> 4; if( pColor[0] ) SetPixelV(hdc, xcount+xofs, ycount+yofs, color ); frame += 2; } } } else if(gfd->Compressed==5) { COLORREF color=0; BYTE* pColor = (BYTE*)&color; for (ycount = 0; ycount < gfd->Height; ycount++) { for (xcount = 0; xcount < gfd->Width; xcount++){ // ARRRRRBBBBBGGGGG WORD pixel = *(WORD*)frame; pColor[0] = ((pixel & 0x8000) == 0) ? 0 : 255; pColor[1] = (pixel & 0x03E0) >> 2; pColor[2] = (pixel & 0x001F) << 3; pColor[3] = (pixel & 0x7C00) >> 7; if( pColor[0] ) SetPixelV(hdc, xcount+xofs, ycount+yofs, color ); frame += 2; } } } else for (ycount = 0; ycount < gfd->Height; ycount++) for (xcount = 0; xcount < gfd->Width; xcount++) SetPixelV(hdc, xcount+xofs, ycount+yofs, color[*frame++]); }
void ShowFrameData(HWND hwndJpg, HDC hdc, VIEWOPTION *vo, TAFFRAMEDATA *gfd) { int i; int *SubFrame; TAFFRAMEDATA *gfdSub;
if( gfd->FramePointers==(-256) ) FrameToHDC(hdc, vo, gfd); else if ( gfd->FramePointers ) { SubFrame = (void *) (vo->buff + gfd->PtrFrameData); for (i = 0; i < gfd->FramePointers; i++) { gfdSub = (void *) (vo->buff + *SubFrame); FrameToHDC(hdc, vo, gfdSub); SubFrame++; } } else FrameToHDC(hdc, vo, gfd); }
void SetCurrentFrame(HWND hwndJpg, VIEWOPTION *vo, int FrameNo) { char strFrameNo[16]; char strFramePtr[16]; TAFFRAMEDATA *gfd; HWND hwnd = GetParent(hwndJpg);
vo->CurFrame = FrameNo; sprintf( strFrameNo, "Frame %d", FrameNo ); //SetDlgItemInt(hwnd, IDC_CURFRAME, FrameNo, FALSE); SetDlgItemText(hwnd, IDC_CURFRAME, strFrameNo ); gfd = vo->gfd[FrameNo]; SetDlgItemInt(hwnd, IDC_WIDTH, gfd->Width, TRUE); SetDlgItemInt(hwnd, IDC_HEIGHT, gfd->Height, TRUE); SetDlgItemInt(hwnd, IDC_XPOS, gfd->XPos, TRUE); SetDlgItemInt(hwnd, IDC_YPOS, gfd->YPos, TRUE); sprintf( strFramePtr, "%i", gfd->FramePointers ); SetDlgItemText(hwnd, IDC_SUBFRAMES, strFramePtr ); //SetDlgItemInt(hwnd, IDC_SUBFRAMES, gfd->FramePointers, FALSE); SetDlgItemInt(hwnd, IDC_FRAME_UN, vo->FrameEntry[FrameNo].Unknown1, TRUE); SetDlgItemInt(hwnd, IDC_FRAME_UN1, gfd->Unknown1, TRUE); SetDlgItemInt(hwnd, IDC_FRAME_UN2, gfd->Unknown2, TRUE); SetDlgItemInt(hwnd, IDC_FRAME_UN3, gfd->Unknown3, FALSE); SetDlgItemInt(hwnd, IDC_FRAME_COMPRESSED, gfd->Compressed, TRUE);
InvalidateRect(hwndJpg, NULL, TRUE); //UpdateWindow(hwndJpg); }
void TafListSelect(HWND hwnd, HWND hwndList, VIEWOPTION *vo) { int index; int i; HWND hwndJpg = GetDlgItem(hwnd, IDC_PICTURE);
index = SendMessage(hwndList, LB_GETCURSEL, 0, 0); if (index == LB_ERR) return;
FreeFrameStuff(vo);
vo->CurEntry = (void *) SendMessage(hwndList, LB_GETITEMDATA, index, 0); vo->FrameEntry = (void *) (vo->CurEntry+1);
SetDlgItemInt(hwnd, IDC_FRAMES, vo->CurEntry->Frames, FALSE); SetDlgItemInt(hwnd, IDC_ENTRY_UN1, vo->CurEntry->Unknown1, FALSE); SetDlgItemInt(hwnd, IDC_ENTRY_UN2, vo->CurEntry->Unknown2, FALSE);
SendDlgItemMessage(hwnd, IDC_SLIDE, TBM_SETRANGE, TRUE, MAKELONG(0, vo->CurEntry->Frames - 1)); SendDlgItemMessage(hwnd, IDC_SLIDE, TBM_SETPOS, TRUE, 0);
SetDlgItemText(hwnd, IDC_CURFRAME, ""); SetDlgItemText(hwnd, IDC_WIDTH, ""); SetDlgItemText(hwnd, IDC_HEIGHT, ""); SetDlgItemText(hwnd, IDC_XPOS, ""); SetDlgItemText(hwnd, IDC_YPOS, ""); SetDlgItemText(hwnd, IDC_SUBFRAMES, "");
if (!vo->CurEntry->Frames) { InvalidateRect(hwndJpg, NULL, TRUE); return; }
vo->gfd = GetMem(vo->CurEntry->Frames * sizeof(TAFFRAMEDATA *), TRUE);
for (i = 0; i < vo->CurEntry->Frames; i++) { vo->gfd[i] = (void *) (vo->buff + vo->FrameEntry[i].PtrFrameTable); }
SetCurrentFrame(hwndJpg, vo, 0); }
int LoadViewTaf(HWND hwnd, VIEWOPTION *vo) { TAFHEADER *Taf; long *EntryPtr; int EntryNo; int Index; TAFENTRY *Entry; HWND hwndList; Taf = (void *) vo->buff; vo->Header = Taf;
EntryPtr = (long *) (vo->buff + sizeof(TAFHEADER));
SendDlgItemMessage(hwnd, IDC_TAFLIST, LB_RESETCONTENT, 0, 0);
for (EntryNo = 0; EntryNo < Taf->Entries; EntryNo++) { Entry = (TAFENTRY *) (vo->buff + *EntryPtr); Index = SendDlgItemMessage(hwnd, IDC_TAFLIST, LB_ADDSTRING, 0, (LPARAM) Entry->Name); SendDlgItemMessage(hwnd, IDC_TAFLIST, LB_SETITEMDATA, Index, (LPARAM) Entry);
EntryPtr++; } if (EntryNo) { hwndList = GetDlgItem(hwnd, IDC_TAFLIST); SendMessage(hwndList, LB_SETCURSEL, 0, 0); TafListSelect(hwnd, hwndList, vo); }
return TRUE; }
long WndProcViewTafInit(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { //wm_initdialog HICON hiSmall; HICON hiLarge; RECT rc; int x; int y; int inset;
VIEWOPTION *vo = (void *) (lParam);
SetWindowLong(hwnd, GWL_USERDATA, (long) vo);
hiSmall = LoadImage(hThisInstance, MAKEINTRESOURCE(IDI_MAIN), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); hiLarge = LoadIcon(hThisInstance, MAKEINTRESOURCE(IDI_MAIN));
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hiLarge); SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hiSmall);
SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM) vo->Name); SetDlgItemText(hwnd, IDC_TAFNAME, vo->Name); GetWindowRect(GetDlgItem(hwnd, IDC_TAFLIST), &rc); ConvertToClient(hwnd, &rc); inset = rc.left; x = rc.right + inset;
GetWindowRect(GetDlgItem(hwnd, IDC_YPOS), &rc); ConvertToClient(hwnd, &rc); y = rc.bottom + inset;
CreateWindowEx(WS_EX_CLIENTEDGE, ViewTafJpgWindowClass, "", WS_CHILD | WS_VISIBLE, x, y, 100, 100, hwnd, (HMENU) IDC_PICTURE, hThisInstance, NULL);
if (!LoadViewTaf(hwnd, vo)) PostMessage(hwnd, WM_CLOSE, 0, 0);
SetDlgItemInt(hwnd, IDC_ENTRIES, vo->Header->Entries, FALSE); SetDlgItemInt(hwnd, IDC_HEADER_UN, vo->Header->Unknown1, TRUE);
return 0; }
long WndProcViewTafSize(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) // wm_size { RECT rc; HWND hwndChild; int fwSizeType = wParam; // resizing flag int nWidth = LOWORD(lParam); // width of client area int nHeight = HIWORD(lParam); // height of client area int x;
if (fwSizeType == SIZE_MINIMIZED) return FALSE;
hwndChild = GetDlgItem(hwnd, IDC_TAFLIST); GetWindowRect(hwndChild, &rc); MoveWindow(hwndChild, 2, 2, rc.right-rc.left, nHeight - 4, TRUE); x = rc.right - rc.left + 6; hwndChild = GetDlgItem(hwnd, IDC_PICTURE); GetWindowRect(hwndChild, &rc); ConvertToClient(hwnd, &rc); MoveWindow(hwndChild, x, rc.top, nWidth - x - 2, nHeight-rc.top-2, TRUE); return FALSE; }
LRESULT WndProcViewTafCommand(HWND hwnd, UINT message, WPARAM wParam, LONG lParam) { VIEWOPTION *vo; UINT idItem = LOWORD(wParam); UINT wNotifyCode = HIWORD(wParam); HWND hwndCtl = (HWND) lParam;
vo = (void *) GetWindowLong(hwnd, GWL_USERDATA);
switch (idItem) { case IDC_TAFLIST : if (wNotifyCode == LBN_SELCHANGE) TafListSelect(hwnd, hwndCtl, vo); return 0; } return 0; }
long WndProcViewTafScroll(HWND hwnd, UINT message, UINT wParam, LONG lParam) { // wm_hscroll - from slider int wNotifyCode = LOWORD(wParam); // scroll bar value VIEWOPTION *vo; int NewPos;
vo = (void *) GetWindowLong(hwnd, GWL_USERDATA);
if (!vo->CurEntry->Frames) return 0; NewPos = SendMessage((HWND) lParam, TBM_GETPOS, 0, 0); SetCurrentFrame(GetDlgItem(hwnd, IDC_PICTURE), vo, NewPos); return 0; }
long WndProcViewTafClose(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { VIEWOPTION *vo; vo = (void *) GetWindowLong(hwnd, GWL_USERDATA);
FreeFrameStuff(vo); if (vo->Name) FreeMem(vo->Name); if (vo->hpal) DeleteObject(vo->hpal); if (vo->buff) FreeMem(vo->buff); FreeMem(vo);
DestroyWindow(hwnd); return FALSE; }
LRESULT CALLBACK WndProcViewTaf(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND : return WndProcViewTafCommand(hwnd, message, wParam, lParam); case WM_SIZE : return WndProcViewTafSize(hwnd, message, wParam, lParam); case WM_HSCROLL : return WndProcViewTafScroll(hwnd, message, wParam, lParam); case WM_INITDIALOG : return WndProcViewTafInit(hwnd, message, wParam, lParam); case WM_CLOSE : return WndProcViewTafClose(hwnd, message, wParam, lParam); } return FALSE; }
long WndProcViewJpgTafPaint(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) // wm_paint { PAINTSTRUCT ps; VIEWOPTION *vo; TAFFRAMEDATA *gfd; RECT rc; HWND hwndParent = GetParent(hwnd);
BeginPaint(hwnd, &ps);
vo = (void *) GetWindowLong(hwndParent, GWL_USERDATA); if (vo->gfd) { // Select palette and realize it. SelectPalette(ps.hdc, vo->hpal, FALSE ); RealizePalette(ps.hdc);
gfd = (void *) (vo->buff + vo->FrameEntry[vo->CurFrame].PtrFrameTable); GetClientRect(hwnd, &rc);
vo->xofs = (rc.right / 2) + vo->gfd[0]->XPos - (vo->gfd[0]->Width / 2); vo->yofs = (rc.bottom / 2) + vo->gfd[0]->YPos - (vo->gfd[0]->Height / 2); ShowFrameData(hwnd, ps.hdc, vo, gfd); } EndPaint(hwnd, &ps); return 0; }
LRESULT CALLBACK WndProcViewTafJpg(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_PAINT : return WndProcViewJpgTafPaint(hwnd, message, wParam, lParam); } return DefWindowProc(hwnd, message, wParam, lParam); }
void RegisterViewTafClasses(void) { WNDCLASSEX wndclass;
if (ViewTafClassRegistered) return;
//Main Window wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; //CS_OWNDC; wndclass.lpfnWndProc = WndProcViewTafJpg; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hThisInstance; wndclass.hIcon = NULL; wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = ViewTafJpgWindowClass; wndclass.hIconSm = NULL; RegisterClassEx(&wndclass);
ViewTafClassRegistered = TRUE; }
void DumpFrameData(FILE *f, char *buff, int PtrFrameTable, int FrameNo, int level) { TAFFRAMEDATA *gfd; int *SubFrame; int i; char spaces[100]; int bytes; char *data; int count; int mask; int x; int repeat;
FillMemory(spaces, sizeof(spaces), ' '); spaces[level * 3] = 0; gfd = (void *) (buff + PtrFrameTable); fprintf(f, "%sW: %d H: %d X: %d Y: %d\n", spaces, gfd->Width, gfd->Height, gfd->XPos, gfd->YPos); fprintf(f, "%sU1: %d Compressed: %d FramePointers: %d U2: %d U3: 0x%08X\n", spaces, gfd->Unknown1, gfd->Compressed, gfd->FramePointers, gfd->Unknown2, gfd->Unknown3); fprintf(f, "%sPtrFrameData: 0x%08X\n", spaces, gfd->PtrFrameData); if (gfd->FramePointers) { SubFrame = (void *) (buff + gfd->PtrFrameData); for (i = 0; i < gfd->FramePointers; i++) { DumpFrameData(f, buff, *SubFrame, i, level+1); SubFrame++; } } else { data = buff + gfd->PtrFrameData; for (i = 0; i < gfd->Height; i++) { fprintf(f, "%sLine %3d", spaces, i); bytes = *((short *) data); data += sizeof(short); count = 0; while (count < bytes) { mask = (unsigned char) data[count++]; if ((mask & 0x01) == 0x01) { // transparent for (x = 0; x < (mask >> 1); x++) fprintf(f, " "); } else if ((mask & 0x02) == 0x02) { // repeat next byte repeat = (mask >> 2) + 1; while (repeat--) fprintf(f, " %02X", (unsigned char) data[count]); count++; } else { repeat = (mask >> 2) + 1; while (repeat--) fprintf(f, " %02X", (unsigned char) data[count++]); } } data += bytes; fprintf(f, "*\n"); } fprintf(f, "\n"); data = buff + gfd->PtrFrameData; for (i = 0; i < gfd->Height; i++) { fprintf(f, "%sLine %3d", spaces, i); bytes = *((short *) data); data += sizeof(short); for (count = 0; count < bytes; count++) { fprintf(f, " %02X", (unsigned char) data[count]); } fprintf(f, "\n"); data += bytes; } } }
void DumpTAF(char *buff, char *Name) { FILE *f; char fname[MAX_PATH]; TAFHEADER *Taf; long *EntryPtr; int EntryNo; TAFENTRY *Entry; TAFFRAMEENTRY *FrameEntry; int i;
strcpy(fname, Name); strcat(fname, ".dmp"); f = fopen(fname, "wtc");
Taf = (void *) buff;
EntryPtr = (long *) (buff + sizeof(TAFHEADER));
for (EntryNo = 0; EntryNo < Taf->Entries; EntryNo++) { Entry = (TAFENTRY *) (buff + *EntryPtr); fprintf(f, "\nEntryPtr 0x%08X\nName %s Frames %d U1: %d U2: %d\n", *EntryPtr, Entry->Name, Entry->Frames, Entry->Unknown1, Entry->Unknown2); FrameEntry = (void *) (Entry+1);
if (Entry->Frames) { for (i = 0; i < Entry->Frames; i++) { fprintf(f, "Frame %d\n", i); fprintf(f, "PtrFrameTable: 0x%08X\n", FrameEntry[i].PtrFrameTable); fprintf(f, "FrameEntry.Unknown1: 0x%08X\n", FrameEntry[i].Unknown1); DumpFrameData(f, buff, FrameEntry[i].PtrFrameTable, i, 0); } } EntryPtr++; } fclose(f); }
void InitVOStuff(VIEWOPTION *vo) { LOGPALETTE *lp; PALETTEENTRY *pal; int i;
// Allocate memory for color palette. lp = GetMem(sizeof(LOGPALETTE)+(256 * sizeof(PALETTEENTRY)), FALSE);
lp->palVersion = 0x300; lp->palNumEntries = 256;
// Load each color into the palette. switch (vo->Version) { case HPI_V1 : pal = TAPalette; break; case HPI_V2 : pal = TAKPalette; break; default : pal = TAPalette; } for (i = 0; i < 256; i++ ) { lp->palPalEntry[i].peRed = pal[i].peRed; lp->palPalEntry[i].peGreen = pal[i].peGreen; lp->palPalEntry[i].peBlue = pal[i].peBlue; lp->palPalEntry[i].peFlags = pal[i].peFlags; }
// Create the Palette. vo->hpal = CreatePalette(lp); FreeMem(lp); }
int ViewTafFile(char *buff, int Length, char *Name, int option, HPIITEM *hi) { HWND hwnd; VIEWOPTION *vo;
//DumpTAF(buff, Name); //FreeMem(buff); //return TRUE;
RegisterViewTafClasses(); vo = GetMem(sizeof(VIEWOPTION), TRUE);
vo->Version = hi->hfd->Version; vo->Length = Length; vo->buff = buff; vo->Name = DupString(Name); vo->option = option;
InitVOStuff(vo);
hwnd = CreateDialogParam(hThisInstance, MAKEINTRESOURCE(IDD_TAFVIEW), NULL, WndProcViewTaf, (LPARAM) vo);
if (!hwnd) return FALSE;
ShowWindow(hwnd, SW_SHOWNORMAL);
// buff is freed when the window closes return TRUE; }
Sorry if it long but hope you enjoy seeing what I see about TAF files.
Thanks guys.
| |
| | | Wqaopl
Posts : 216 Reputation : 2 Join date : 2008-08-14
| Subject: Re: Wqaopl's tnt maker Wed Aug 10, 2016 4:51 pm | |
| if you have the c++ code for the switch i would lie to see it and the other scripts such as "hpiview.h". and yes im kind of giving up on working out HIP myselth as i dont get much time to program =/ | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Wed Aug 10, 2016 5:39 pm | |
| hpiview.h and hpiview.c are in the hpiview source code I posted earlier
You can try their code, or wait until I make an hpi lib (which I should start since I pretty much gave up in continuing my kmap previewer as is) (Not that I gave up but that I want to rewrite it from scratch to avoid the spaggetti code that was created by loading the tnt, ota and txt files directly from the .kmp file (without properly organizing the headers etc)
If you try the hpiview source code just remember that it implements both TA hpi and TAK hpis and they are structurally different (hpiview source generally calls TA hpis by ____1 and TAK hpi things by ____2 like HPIENTRY1 and HPIENTRY2 structs or the LoadDirectory1 and LoadDirectory2 functions) Also tak by default compresses with zlib while ta uses LZ77
If you run into a problem with an HPI related code you can post in this thread too | |
| | | Wqaopl
Posts : 216 Reputation : 2 Join date : 2008-08-14
| Subject: Re: Wqaopl's tnt maker Thu Aug 11, 2016 4:42 am | |
| i atualy got round to unspegetiyfying my code - .h:
#pragma once #include #include
#define ID_HightMap 1001 #define ID_Attributes 1002 #define ID_FeatureNames 2003 #define ID_TerrainNames 2004 #define ID_Umapping 3005 #define ID_Vmapping 3006 #define ID_SmallMiniMap 1007 #define ID_BigMiniMap 1008
class TNTData { PBITMAPINFO pbmi; HBITMAP ACTIVEBITMAP;
DWORD FileSizeByt; public:
struct TNTHEDDER{ DWORD IDversion; DWORD Width; DWORD Height; DWORD SeaLevel; DWORD LHeightMap; DWORD LAttributes; DWORD LFeatureNames; DWORD FeaturesNb; DWORD LTerrainNames; DWORD LUmapping; DWORD LVmapping; DWORD LSmallMiniMap; DWORD LBigMiniMap; }; struct FNames { DWORD FeturID; // ID for referance BYTE Name[128]; };
struct SHightMap { DWORD Bytes; // Width * Hight BYTE *pHeightMap; }; struct SAttributes { DWORD Bytes; // width * hight * 2 DWORD ArrLenth; // Width * Hight UWORD *pAttributes; }; struct SFeatureNames { DWORD Bytes; // FeaturesNb * 132 DWORD ArrLenth; // FeaturesNb FNames *pFeatureNames; }; struct STerrainNames { DWORD Bytes; // Width * Height DWORD ArrLenth; // Width * Height / 4 DWORD *pTerrainNames; }; struct SUmapping { DWORD Bytes; // 2*( width/2 * hight/2) DWORD ArrLenth;// width/2 * hight/2 UWORD *pUmapping; }; struct SVmapping { DWORD Bytes; // 2*( width/2 * hight/2) DWORD ArrLenth; // width/2 * hight/2 UWORD *pVmapping; }; struct SSmallMiniMap { DWORD Width; // byte 0 to byte 3 DWORD Hight; // byte 4 to byte 7 DWORD Bytes; //MiniMap_size_Width * MiniMap_size_Hight WITH THE 8 byte offset BYTE *pSmallMiniMap; // 8 byte offset }; struct SBigMiniMap { DWORD Width; // byte 0 to byte 3 DWORD Hight; // byte 4 to byte 7/ DWORD Bytes; //MiniMap_size_Width * MiniMap_size_Hight WITH THE 8 byte offset BYTE *pBigMiniMap; // 8 byte offset };
DWORD number_of_brushes;
TNTHEDDER FileHedder; SHightMap TheHightMap; SAttributes TheAttributes; SFeatureNames TheFeatureNames; STerrainNames TheTerrainNames; SUmapping TheUmapping; SVmapping TheVmapping; SSmallMiniMap TheSmallMiniMap; SBigMiniMap TheBigMiniMap;
bool LoadTNTDataFile(LPCTSTR pszFileName); HBITMAP GetActiveBitMap(); HBITMAP SetActiveBitMap(int Identifyer);
TNTData(); TNTData(LPCTSTR pszFileName); virtual ~TNTData(); };
and - .cpp:
#include "TNT_Class.h"
void SetupData(TNTData * info) {
info->FileHedder.FeaturesNb = 0; info->FileHedder.Height = 0; info->FileHedder.IDversion = 0; info->FileHedder.IDversion = 0; info->FileHedder.LAttributes = 0; info->FileHedder.LSmallMiniMap = 0; info->FileHedder.LFeatureNames = 0; info->FileHedder.LHeightMap = 0; info->FileHedder.LBigMiniMap = 0; info->FileHedder.LTerrainNames = 0; info->FileHedder.LUmapping = 0; info->FileHedder.LVmapping = 0; info->FileHedder.SeaLevel = 0; info->FileHedder.Width = 0;
info->number_of_brushes = 0;
info->TheAttributes.ArrLenth = 0; info->TheAttributes.Bytes = 0; info->TheAttributes.pAttributes = nullptr;
info->TheBigMiniMap.Bytes = 0; info->TheBigMiniMap.Hight = 0; info->TheBigMiniMap.pBigMiniMap = nullptr; info->TheBigMiniMap.Width = 0;
info->TheFeatureNames.ArrLenth = 0; info->TheFeatureNames.Bytes = 0; info->TheFeatureNames.pFeatureNames = nullptr;
info->TheHightMap.Bytes = 0; info->TheHightMap.pHeightMap = nullptr;
info->TheSmallMiniMap.Bytes = 0; info->TheSmallMiniMap.Hight = 0; info->TheSmallMiniMap.pSmallMiniMap = nullptr; info->TheSmallMiniMap.Width = 0;
info->TheTerrainNames.ArrLenth = 0; info->TheTerrainNames.Bytes = 0; info->TheTerrainNames.pTerrainNames = nullptr;
info->TheUmapping.Bytes = 0; info->TheUmapping.ArrLenth = 0; info->TheUmapping.pUmapping = nullptr;
info->TheVmapping.Bytes = 0; info->TheVmapping.ArrLenth = 0; info->TheVmapping.pVmapping = nullptr;
}
bool TNTData::LoadTNTDataFile(LPCTSTR pszFileName) { BOOL bSuccess = FALSE;
HANDLE hFile; DWORD dwFileSize;
hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile != INVALID_HANDLE_VALUE) {
dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize != 0xFFFFFFFF) { LPBYTE pszFileText; pszFileText = (LPBYTE)GlobalAlloc(GPTR, dwFileSize + 1);
if (pszFileText != NULL) { DWORD dwRead;
if (ReadFile(hFile, pszFileText, dwFileSize, &dwRead, NULL)) { DWORD ARRCOUNTER; pszFileText[dwFileSize] = 0; // Add null termination
TNTHEDDER * TempHed = (TNTHEDDER *)pszFileText; FileHedder = *TempHed;
//********** HIGHTMAP BYTES **********// BYTE * TempHig = (BYTE *)&pszFileText[FileHedder.LHeightMap]; TheHightMap.Bytes = FileHedder.Width * FileHedder.Height; TheHightMap.pHeightMap = new BYTE[TheHightMap.Bytes]; ARRCOUNTER = 0; while (ARRCOUNTER < TheHightMap.Bytes) { TheHightMap.pHeightMap[ARRCOUNTER] = TempHig[ARRCOUNTER]; ARRCOUNTER++; }
//********** ATTRABUTES WORDS **********// UWORD * TempAtra = (UWORD *)&pszFileText[FileHedder.LAttributes]; TheAttributes.ArrLenth = FileHedder.Width * FileHedder.Height; TheAttributes.Bytes = TheAttributes.ArrLenth * 2; TheAttributes.pAttributes = new UWORD[TheAttributes.ArrLenth]; ARRCOUNTER = 0; while (ARRCOUNTER < TheAttributes.ArrLenth) { TheAttributes.pAttributes[ARRCOUNTER] = TempAtra[ARRCOUNTER]; ARRCOUNTER++; }
//********** FEATURES BYTES[132] **********// FNames * TempFet = (FNames *)&pszFileText[FileHedder.LFeatureNames]; TheFeatureNames.ArrLenth = FileHedder.FeaturesNb; TheFeatureNames.Bytes = TheFeatureNames.ArrLenth * 132; TheFeatureNames.pFeatureNames = new FNames[TheFeatureNames.ArrLenth]; ARRCOUNTER = 0; while (ARRCOUNTER < TheFeatureNames.ArrLenth) { TheFeatureNames.pFeatureNames[ARRCOUNTER] = TempFet[ARRCOUNTER]; ARRCOUNTER++; }
//********** TERAINNAMES DWORDS **********// DWORD * TempTer = (DWORD *)&pszFileText[FileHedder.LTerrainNames]; TheTerrainNames.Bytes = FileHedder.Width * FileHedder.Height; TheTerrainNames.ArrLenth = TheTerrainNames.Bytes / 4; TheTerrainNames.pTerrainNames = new DWORD[TheTerrainNames.ArrLenth]; ARRCOUNTER = 0; while (ARRCOUNTER < TheTerrainNames.ArrLenth) { TheTerrainNames.pTerrainNames[ARRCOUNTER] = TempTer[ARRCOUNTER]; ARRCOUNTER++; }
//********** UMAPPING UWORD **********// WORD * TempUmp = (WORD *)&pszFileText[FileHedder.LUmapping]; TheUmapping.Bytes = ((FileHedder.Width / 2) * (FileHedder.Height / 2)) * 2; TheUmapping.ArrLenth = (FileHedder.Width / 2) * (FileHedder.Height / 2); TheUmapping.pUmapping = new UWORD[TheUmapping.ArrLenth]; ARRCOUNTER = 0; while (ARRCOUNTER < TheUmapping.Bytes) { TheUmapping.pUmapping[ARRCOUNTER] = TempUmp[ARRCOUNTER]; ARRCOUNTER++; }
//********** VMAPPING UWORD **********// BYTE * TempVmp = (BYTE *)&pszFileText[FileHedder.LVmapping]; TheVmapping.Bytes = (FileHedder.Width / 2) * (FileHedder.Height / 2); TheVmapping.ArrLenth = (FileHedder.Width / 2) * (FileHedder.Height / 2); TheVmapping.pVmapping = new UWORD[TheVmapping.ArrLenth]; ARRCOUNTER = 0; while (ARRCOUNTER < TheVmapping.Bytes) { TheVmapping.pVmapping[ARRCOUNTER] = TempVmp[ARRCOUNTER]; ARRCOUNTER++; }
//********** SMALLMAP BYTES **********// DWORD * TempSwid = (DWORD *)&pszFileText[FileHedder.LSmallMiniMap]; TheSmallMiniMap.Width = *TempSwid;
DWORD * TempShig = (DWORD *)&pszFileText[FileHedder.LSmallMiniMap + 4]; TheSmallMiniMap.Hight = *TempShig;
BYTE * TempSmp = (BYTE *)&pszFileText[FileHedder.LSmallMiniMap + 8]; TheSmallMiniMap.Bytes = TheSmallMiniMap.Width * TheSmallMiniMap.Hight; TheSmallMiniMap.pSmallMiniMap = new BYTE[TheSmallMiniMap.Bytes]; ARRCOUNTER = 0; while (ARRCOUNTER < TheSmallMiniMap.Bytes) { TheSmallMiniMap.pSmallMiniMap[ARRCOUNTER] = TempSmp[ARRCOUNTER]; ARRCOUNTER++; }
//********** BIGMAP BYTES **********// DWORD * TempBwid = (DWORD *)&pszFileText[FileHedder.LBigMiniMap ]; TheBigMiniMap.Width = *TempBwid;
DWORD * TempBhig = (DWORD *)&pszFileText[FileHedder.LBigMiniMap + 4]; TheBigMiniMap.Hight = *TempBhig;
BYTE * TempBmp = (BYTE *)&pszFileText[FileHedder.LBigMiniMap + 8]; TheBigMiniMap.Bytes = TheBigMiniMap.Width * TheBigMiniMap.Hight; TheBigMiniMap.pBigMiniMap = new BYTE[TheBigMiniMap.Bytes]; ARRCOUNTER = 0; while (ARRCOUNTER < TheBigMiniMap.Bytes) { TheBigMiniMap.pBigMiniMap[ARRCOUNTER] = TempBmp[ARRCOUNTER]; ARRCOUNTER++; }
bSuccess = TRUE; // It worked! } GlobalFree(pszFileText); }
} CloseHandle(hFile); } return bSuccess; }
HBITMAP TNTData::GetActiveBitMap() { return ACTIVEBITMAP; }
HBITMAP TNTData::SetActiveBitMap(int Identifyer) { if (ACTIVEBITMAP != nullptr) { DeleteObject(ACTIVEBITMAP); ACTIVEBITMAP = nullptr; } switch (Identifyer) { case ID_HightMap: if (TheHightMap.pHeightMap != nullptr) { unsigned char* pixels; long imige_exsess = 0;
int bitwidth = FileHedder.Width; while (bitwidth % 4 != 0) { bitwidth++; imige_exsess++; }
long pixwidth = FileHedder.Width; long pixhight = FileHedder.Height;
HDC hdc = CreateCompatibleDC(NULL); pbmi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader); pbmi->bmiHeader.biWidth = bitwidth; pbmi->bmiHeader.biHeight = -pixhight; pbmi->bmiHeader.biPlanes = 1; pbmi->bmiHeader.biBitCount = 8; pbmi->bmiHeader.biCompression = BI_RGB; pbmi->bmiHeader.biSizeImage = 0;// ((((pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount) + 31) & ~31) >> 3) * pbmi->bmiHeader.biHeight; pbmi->bmiHeader.biXPelsPerMeter = 14173; pbmi->bmiHeader.biYPelsPerMeter = 14173; pbmi->bmiHeader.biClrUsed = 0; pbmi->bmiHeader.biClrImportant = 0;
long long arrlenth = bitwidth * pixhight;
for (int i = 0; i < 256; i++) { pbmi->bmiColors[i].rgbRed = i; pbmi->bmiColors[i].rgbGreen = i; pbmi->bmiColors[i].rgbBlue = i; pbmi->bmiColors[i].rgbReserved = 0; }
ACTIVEBITMAP = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)(&pixels), NULL, NULL);
long long counter = 0;
while (counter < arrlenth) { pixels[counter] = 0; counter++; }
counter = 0; long long counter__ = 0; while (counter__ < arrlenth) { long YYY = counter__ / bitwidth; while ( counter__ < bitwidth * (YYY + 1) && counter__ >= (bitwidth * YYY) + pixwidth ) { counter__++; } if (counter__ < arrlenth) { pixels[counter__] = TheHightMap.pHeightMap[counter]; }
counter++; counter__++; } } break; case ID_Attributes: break; case ID_FeatureNames: break; case ID_TerrainNames: break; case ID_Umapping: break; case ID_Vmapping: break; case ID_SmallMiniMap: break; case ID_BigMiniMap: break; default: return nullptr; break; }
return ACTIVEBITMAP; }
TNTData::TNTData() { SetupData(this); FileSizeByt = 0; ACTIVEBITMAP = nullptr; }
TNTData::TNTData(LPCTSTR pszFileName) { SetupData(this); FileSizeByt = 0; LoadTNTDataFile(pszFileName); ACTIVEBITMAP = nullptr; }
TNTData::~TNTData(){ if (ACTIVEBITMAP != nullptr) { DeleteObject(ACTIVEBITMAP); ACTIVEBITMAP = nullptr; }
if (TheAttributes.pAttributes != nullptr) { delete[] TheAttributes.pAttributes; TheAttributes.pAttributes = nullptr; } if (TheBigMiniMap.pBigMiniMap != nullptr) { delete[] TheBigMiniMap.pBigMiniMap; TheBigMiniMap.pBigMiniMap = nullptr; } if (TheFeatureNames.pFeatureNames != nullptr) { delete[] TheFeatureNames.pFeatureNames; TheFeatureNames.pFeatureNames = nullptr; } if (TheHightMap.pHeightMap != nullptr) { delete[] TheHightMap.pHeightMap; TheHightMap.pHeightMap = nullptr; } if (TheSmallMiniMap.pSmallMiniMap != nullptr) { delete[] TheSmallMiniMap.pSmallMiniMap; TheSmallMiniMap.pSmallMiniMap = nullptr; } if (TheTerrainNames.pTerrainNames != nullptr) { delete[] TheTerrainNames.pTerrainNames; TheTerrainNames.pTerrainNames = nullptr; } if (TheUmapping.pUmapping != nullptr) { delete[] TheUmapping.pUmapping; TheUmapping.pUmapping = nullptr; } if (TheVmapping.pVmapping != nullptr) { delete[] TheVmapping.pVmapping; TheVmapping.pVmapping = nullptr; } }
missing most of the bitmap setup and as i lirned c++ by my self theres no garenty of no mistakes but it should be easy to add to if needed =) also i did not get round to adding palets for all the bitmaps | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Thu Aug 11, 2016 2:15 pm | |
| Managing bitmaps for windows is so complicated I wish it was easy like with Qt images, this is how it is done in Qt: - Code:
-
QImage image = new QImage(wid, hei, QImage::Format_RGB32); for (int y = 0; y < hei; y++) { for (int x = 0; x < wid; x++) { quint8 next = buffer->at(offset++); // QRgb pixel = qRgb(next, next, next); // greyscale color quint32 pixel = palette[next]; // palette color image->setPixel(x, y, pixel); } }
Too bad I'll need to learn too if I want to finish thumbnail previewer for windows (even worse because i never programmed on Windows) Anyway this is what I was talking about the features map, this is a rendered "tab" map: (440 x 431) - Spoiler:
This is the rendered features map: (320 x 320) - Spoiler:
Since the dimensions are different, the way I did to translate the mana coordinates was simple scaling math: newX = oldX * (newWid / oldWid) Where oldX = the X coord in the features map; oldWid = the width of the featues map (320); newWid = the width of the tab map (440) And the same for Y Result: Red circles = the mana on the resulting coordinates - Spoiler:
They might look to be aligned but they aren't, actually that is actualy in vain because the problem is that the features map doesn't scale correctly with the tab map, obviously. Here's a justaposition of both (features map is scaled up): - Spoiler:
The misalignment becomes more visible the closes to the bottom right (higher coordinates) - Spoiler:
I believe Knowing how to fix this would also help with the cartographer since it is basically the same issue with dimension scaling that I mentioned earlier A solution off my head is that to properly scaling the dimensions from the features map into the tab map dimensions first it's needed to crop the tab map (like cartographer seems to display a red area, that might be the area to crop) and then scale normally into the new cropped dimensions Or maybe, instead of cropping the tab map it should be padded instead (to meet the same proportion as the featue maps, e.g 1:1 proportions) Edit: padding the tab map dimensions clearly make much more sense since cropping would only make them more misaligned, now what is left is find out the proper ammount to pad the dimensions I'll do some experimenting, if you have any idea please fire it off | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Thu Aug 11, 2016 2:35 pm | |
| This is the red area in cartographer which I speak of and which the tab map cuts off causing the disproportionate dimensions: (Measuring the pixels on the screen, seems to be always 16 for width and 64 for height) Edit: this is even weirder than I thought A 10 x 10 (cartographer settings) map gives me a 440 x 431 pixels tab map, but a 8 x 8 map gives me a 442 x 431 pixels tab map Even though the proportions are the same, the proportions for the tab map it creates isn't Edit: Created some throwaway maps and now I saw a pattern here: (cartographer sizes -> tab map sizes) 10 x 10 -> 440 x 431 9 x 9 -> 441 x 431 8 x 8 -> 442 x 431 7 x 7 -> 443 x 431 but then it becomes dumb out of a sudden 6 x 6 -> 446 x 431 5 x 5 -> 449 x 431 4 x 4 -> 453 x 431 3 x 3 -> 461 x 431 2 x 2 -> 478 x 431 1 x 1 -> 511 x 409 | |
| | | Wqaopl
Posts : 216 Reputation : 2 Join date : 2008-08-14
| Subject: Re: Wqaopl's tnt maker Fri Aug 12, 2016 3:47 am | |
| using the tab map or mini map is wong as they are scaled after the map is compiled for gameplay the mini map will alwayes fit into the top right box for egsample. use the height map for this and see if you get the same error.
as for bitmaps for windows i just go for a good egsample and ran with it the basic setup that is
unsigned char* pixels; long imige_exsess = 0;
int bitwidth = FileHedder.Width; while (bitwidth % 4 != 0) { bitwidth++; imige_exsess++; }
long pixwidth = FileHedder.Width; long pixhight = FileHedder.Height;
HDC hdc = CreateCompatibleDC(NULL); pbmi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader); pbmi->bmiHeader.biWidth = bitwidth; pbmi->bmiHeader.biHeight = -pixhight; pbmi->bmiHeader.biPlanes = 1; pbmi->bmiHeader.biBitCount = 8; pbmi->bmiHeader.biCompression = BI_RGB; pbmi->bmiHeader.biSizeImage = 0;// ((((pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount) + 31) & ~31) >> 3) * pbmi->bmiHeader.biHeight; pbmi->bmiHeader.biXPelsPerMeter = 14173; pbmi->bmiHeader.biYPelsPerMeter = 14173; pbmi->bmiHeader.biClrUsed = 0; pbmi->bmiHeader.biClrImportant = 0;
long long arrlenth = bitwidth * pixhight;
for (int i = 0; i < 256; i++) { pbmi->bmiColors[i].rgbRed = i; pbmi->bmiColors[i].rgbGreen = i; pbmi->bmiColors[i].rgbBlue = i; pbmi->bmiColors[i].rgbReserved = 0; }
ACTIVEBITMAP = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)(&pixels), NULL, NULL);
CreateDIBSection is the funtion that does the magic and that bitmaps are always aliened to the forth byte. unsigned char* pixels is just a referance and is used by CreateDIBSection to return the bitmap array of pixels that you can alter anyway you want after.
the actural bitmap is in the HBITMAP but to use any inage you need to conect it to a DC and then use the DC such as StretchBlt to resize it to a thumnal size. | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Fri Aug 12, 2016 7:37 am | |
| Yes but because the heightmap has the same dimensions as the features map so no scaling is needed I'm very convinced that in order to scale first I need to add to the dimensions of the tab map the "cut" parts that appear on cartographer (those red parts don't get into the tab map, so they need to be added during the calculation to translate the features into the tab map) the only problem is find out the weird formula that generates 511x409 from 1x1 and 440x431 from 10x10 But if all goes wrong I'll have to put these in the height map afterall and same for the player positions Also thanks for the code with the bitmap | |
| | | Wqaopl
Posts : 216 Reputation : 2 Join date : 2008-08-14
| Subject: Re: Wqaopl's tnt maker Fri Aug 12, 2016 8:10 am | |
| if you are loading the hpi files you could always just make a map image from the original bitmaps then scale \"***\" needed.
or subtract the offset from the feture map then scale it...
the famula for the size should not be hard to calculate i will give it a go | |
| | | $_Spagg
Posts : 385 Reputation : 14 Join date : 2010-10-31 Age : 111 Location : Brazil
| Subject: Re: Wqaopl's tnt maker Fri Aug 12, 2016 8:24 am | |
| Yes Im loading directly from the hpi but what do you mean make a map image from the original bitmaps? You mean create my own "tab" map by hand instead of using the one inside the tnt? | |
| | | Sponsored content
| Subject: Re: Wqaopl's tnt maker | |
| |
| | | | Wqaopl's tnt maker | |
|
Similar topics | |
|
| Permissions in this forum: | You cannot reply to topics in this forum
| |
| |
| |
|