Ambrosia Ramblings

From Pikmin Technical Knowledge Base
Jump to: navigation, search

Just before starting[edit]

https://github.com/JohnFiddleystein/PikminDatamining

https://github.com/JohnFiddleystein/Resources NEW GITHUB THATS PRETTY GOODDDD


The Developer Exe Program[edit]

My favourite thing in the entire world! I datamine it.

ATX SERVER DATAMINING: File:AtxAgeEditor AtxServer takes 3 commands, 'app', 'fil', 'age'. You SHOULD be to connect using a raw tcp connection with netcat or puTTY (raw connection) with localhost:1369 but when you do the program hangs until you enter something. When you do enter something it says plugAtxServer: unknown service 'first 3 letters of whatever you typed here'. not adding No matter what you put it always says that.

UPDATE (as of 29/12/2018 i figured it out!) Because it was made in C/C++ you need to make it a null terminated string. you can do it in python by doing this:

message = b'age\00' and then

sock.sendall(message) (where sock is sock = socket.create_connection(('localhost', 1369)))

only sending age works right now, but the error message has something to do with recv (recieving). So look forward to that in the future!!!

Anyways, when looking at the strings in the .dll for clues as to what this means, you can find 3 functions. using previous tests as a base for this hypothesis, we can conclude:


(previous test) .rdata:100293BC 00000014 C service : AgeEditor


.rdata:100293D4 00000016 C service : AgeFunction


.rdata:10029540 00000015 C service : FileAccess .

or, in simple terms and with educated guesses, we can conclude that: .

AgeEditor was used to edit files and the game itself. .

FileAccess is used when it wants to edit or open a file. This is why using +direct hangs on loading params. As its trying to do something with it.(edited) .

AgeFunctions is unknown currently, i'm looking at it right now and will update this when i find anything

CoreNode *__thiscall sub_10003380(CoreNode *this, int a2, int a3) {

 CoreNode *result; // eax
 CoreNode *v4; // [esp+4Ch] [ebp-4h]
 v4 = this;
 *((_DWORD *)this + 9) = a2;
 *((_DWORD *)this + 14) = a3;
 if ( *((_DWORD *)this + 14) )
   CoreNode::setName(this, "service : AgeFunction");
 else
   CoreNode::setName(this, "service : AgeEditor");
 *((_BYTE *)v4 + 60) = 0;
 *((_BYTE *)v4 + 61) = 0;
 *((_BYTE *)v4 + 48) = 0;
 *((_DWORD *)v4 + 8) = 0;
 result = v4;
 *((_DWORD *)v4 + 11) = 1;
 return result;

} pseudocode to determine whether its an agefunction or editor. CoreNode::setName is imported from sysCore.dll.

Test.card[edit]

screw you minty <3

Test.Card is one of the most mysterious files in the game. Well, I made a breakthrough! yay

Starting at offset 00002010, there are seemingly random assortments of characters. Right?

tnoc������������hcac���û��G� ����������ÿÿíñ'Áð��DvÊ�krow����íñ'‚��D3J����BH��tnip������������ÿÿÿÿeno1�����������W�ÿ�ÿ����î�vÁð��D3Ī� ����������ÿÿÄ© �Áà��E/��meti��� �tnip������������ÿÿÿÿeno1�����°�����E�ÿ�ÿ ����������ÿÿĺ�šÁÀ��D|€�meti��� �tnip������������ÿÿÿÿeno1�����������E�ÿ�ÿ Ì��������ÿÿÁã8ñÂ7�¡E |€meti�����tnip������������ÿÿÿÿeno1

Now take that for example. you see the characters, tnoc, tnip, eno1, meti and so on.


BUT


You can reverse the characters!!!

Cont (short for controller?), pint, 1one, item, and more!

This is a list of what I could find.

tnoc = cont

krow = work

tnip = pint

eno1 = 1one

hcac = cach

D3J = J3D (library used to create pikmin 2 and super mario sunshine.)

enon = none

iket = teki

dnri = irnd

nota = aton

cric = circ

wiket = tekiw

uf01 (looks familliar...)

Reading from.... 000070E0....

kcem = meck

pofu = ufop

gmil = limg

fsiv = visf

Happy test.card'ing everyone!


Plaintext C++ Code :facepalm:[edit]

In sysbootup.opt on the pal disc. There lay rubbish to us, well thats what it looks like at first. When scrolling through in notepad++, i noticed that there was a lot code. here is all of it nicely formatted from discord (where i documented it)

       e = ageNode->pr->service;
       conn->invoke(out, this);  
       UIWindow *serverWin = (UIWindow *)nodeMgr->findNode("AtxServer");
       if(serverWin)
       { 
           SendMessage(serverWin->wnd, WM_COMMAND, IDM_ATTACH_SERVICE, (LPARAM)conn); 
       } 
   } 

} invalidateRect(); } /*-------------------------------------------------------------------------------------*/ void AgeGadgetOptionBox::finishCall(bool refr, bool refs) {

   if(refr) 
   { 
       ((AgeViewLeaf *)currNode)->refreshNode(propsheet->sectionPtr->handle);  
       ageNode->pr->service->stream->writeInt(CALL_GENAGE); 
       ageNode->pr->service->stream->writeInt(propsheet->sectionPtr->handle);  
       SendMessage(((UIWindow *)propsheet->avt->Parent())->wnd, WM_CLOSE, 0, 0); 
       return; 
   }  
   if(refs) 
   { 
       PRINT("refreshing section with parent = %s\n", currSection->name); 
       currSection->handleNameClick(NULL, 0, 0); 
   }  
   invalidateRect(); 

} /*-------------------------------------------------------------------------------------*/ void AgeNodeOptionBox::initialise(char *c, int t, int h, AtxService *service) {

   AgeNode::initialise(c, t, h, service);  
   OptionBoxPropEvent *obpr = new OptionBoxPropEvent(service, handle); 
   obpr->read(service->stream);  
   sizeWidth = service->stream->readInt();  
   for(int i = 0;i < 256;i++) 
   { 
       if(service->stream->readInt() == 0) 
           break; 
       String n = service->stream->readString(); 
       int on = service->stream->readInt(); 
       if(on == obpr->val) 
           obpr->currItem = i;  
       obpr->flags[i] = new FlagBit(n, on, 1); 
   } 
   obpr->numItems = i;  pr = obpr; 

} /*- End of File -----------------------------------------------------------------------*/ = i;obpr->flags[i] = new FlagBit(n, on, 1);}obpr->numItems = i;pr = obpr;}

| ***WHAT MODELS HAVE BEEN RENAMED:*** |[edit]

'bosses' folder summarised: a lot of model.mod files 'bosses' folder:

'bosses/king' folder king.mod used to be called model.mod

'bosses/kingback' folder kingback.mod used to be called model.mod

'bosses/kogane' folder kogane.mod used to be called model.mod

'bosses/mizu' folder mizu.mod used to be called model.mod

'bosses/pom' folder pom.mod used to be called model.mod

'bosses/slime' folder slime.mod used to be called body.mod

'bosses/snake' folder snake.mod used to be called model.mod

'objects' folder summarised: some interesting names definetly. 'objects' folder:

'bomb' folder bomb.mod used to be called model.mod

'cylinder' folder cylinder.mod used to be called red3.mod

'gate' folder gt_hard.mod used to be called gate_hd.mod gt_soft.mod used to be called gate_so.mod

'hinderrock' folder cube10.mod used to be called mv_st10.mod

'plants' folder kinokolt.mod used to be called kinoko_light.mod

'rocket' folder (what the fuck is this folder) key.mod used to be called key2.mod rocket.mod used to be called key.mod

'ufo' folder ufo0705.mod used to be called kiso.mod

'pikis' folder summarised: interesting names :) 'pikis' folder: nv1Model.mod used to be called newnavi.mod, interestingly enough, an older version of its collinfo can be found in the 'parms/' folder nv2Model.mod used to be called navi.mod nv3Model.mod used to be called newNavi.mod, kinModel.mod used to be called piki_kinokomodel.mod, redModel.mod used to be called piki_redmodel.mod yelModel.mod used to be called piki_yellowmodel.mod bluModel.mod used to be called piki_bluemodel.mod

'tekis' folder summarised: a LOT of model.mod files 'tekis' folder:

'beatle' folder beatle.mod used to be called model.mod

'chappb' folder chappb.mod used to be called model.mod

'chappy' folder chappy.mod used to be called model.mod

'collec' folder collec.mod used to be called model.mod

'dororo' folder dororo.mod used to be called model.mod

'frog' folder frog.mod used to be called model.mod

'frow' folder frow.mod used to be called frog_w.mod

'hibaA' folder hibA.mod used to be called model.mod

'hollec' folder hollec.mod used to be called model.mod

'iwagon' folder iwagon.mod used to be called rock.mod

'kabekuiA/B/C' folder (because im lazy) kabekuiA.mod used to be called kabekuia.mod kabekuiB.mod used to be called kabekuib.mod kabekuiC.mod used to be called kabekuic.mod

'kinoko' folder kinoko.mod used to be called model.mod

'mar' folder mar.mod used to be called model.mod

'miurin' folder miurin.mod used to be called model.mod

'namazu' folder (this is some weird folder) namazu.mod used to be called model.mod and some of its 'codes' are literally 'shit'.

'napkid' folder napkid.mod used to be called sarai.mod

'palm' folder palm.mod used to be called pelplant.mod

'pearl' folder pearl.mod used to be called model.mod

'qurione' folder qurione.mod used to be called model.mod

'rocpe' folder rocpe.mod used to be called model.mod

'shell' folder shell.mod used to be called model.mod

'swallob' folder swallob.mod used to be called model.mod

'swallow' folder swallow.mod used to be called model.mod

'tamago' folder tamago.mod used to be called model.mod

'testdata' summarised: hiba used to be called model.mod smh 'testdata' folder: hibaA.mod used to be called model.mod


| ***HOW THE GAME LOADS INI FILES AT THE END OF MOD FILES:*** |[edit]

Disclaimer: Value just means any ascii character, this isnt going to be 100% accurate but it is going to be quite accurate, and finally if there is a value it reads, I haven't figured out what it does with it yet unless specified otherwise. Have fun!

Collision:

The ObjCollInfo class contains code for loading plaintext collision info. Here is how its parsed. If "id" is found then read the next 4 bytes as an 'ID32' aka a 4 char string, if "code" is found then it reads the next 4 bytes as an 'ID32' aka a 4 char string, if "type" is found then it reads the next value found on that line. However, this one is different. If a certain value is set to '1' (have no clue what it is), it then reads 6 other values after that. (wtf) If that certain value is set to 2, then it reads another value after the one in type and copies that value to somewhere in memory. (WHY???) If "getminy" is found then some value gets set to 1. If "collinfo" is found then it simply repeats the function after allocating enough memory.

Oddly enough, if type 2 is used, there (from what i've noticed) always is an external collision model file used in the next line, ` platform 'filename with directory relative to dataDir/' ` This may be what the thing I said about 7 lines ago is about.

Light Group:

if "type" is found then read the next value found on that line. if "flags" is found then read the next value found on that line. if "dir" is found then read the next 3 values found on that line. if "colour" is found then read the next 4 values and then set the colour of 'something' to those values if "texture" is found then check if the next value is "NULL", if it isnt then duplicate that text to somewhere in memory for some reason. if "material" is found then do the same from above. if "lightflare" is found then do LightFlare::loadini(); aka the next function im going to do.

Light Flare:

if "size" is found then read the next value on that line if "pos" is found then read the next 3 values on that line.

Route:

if "id" is found, then read the next 4 chars on that line. if "name" is found then read the next value found on that line. if "colour" is found then read the next 4 values on that line and set the colour of 'something' to those values. if "point" is found then allocate bytes, if done successfully then load the RoutePoint, and do RoutePoint::loadini which i will document after this. if "link" is found then get the next 2 values and check if they are the same. If they arent the same then do some maths with 4 variables including the 2 values from before, then check if the new 2 variables aren't 0/NULL. If they aren't then add add a new corenode (object in game hierarchy).

RoutePoint: if "index" is found then read the next value on that line. if "pos" is found then read the next 3 values on that line. if "state" is found then read the next value on that line. if "width" is found then read the next value on that line.

| ***INTERESTING UNUSED PARSING FUNCTION*** |[edit]

Back when DCA used to be plaintext, there was a parser that the development programs used to parse it. Also, funnily enough, the PLAINTEXT DCK function is basically the same besides some maths to do with PI at the end.

PLAINTEXT DCA / DCK (DCK has some more stuff at the end):

if "<ANM_INFO>" is found, then load the function getAnimInfo(), which does this: if "numjoints" is found then read the next value on that line and do some math/un-named function stuff if "numframes" is found then read the next value on that line if "<SCALING>" is found then allocate memory, try to load a DataChunk() and load getData(), which does this: if "size" is found then read the next value, do DataChunk::setDataSize(), and read the next value, then at the end of the function call DataChunk::addData(), if "<ROTATION>" is found then do what happened above in "<SCALING>" ^^^, if "<TRANSLATION>" is found then just do what happened in "<SCALING>" ^^^, if "<JOINT>" is found then read the next value on that line, then call a new section.

This is essentially its own function so im going to indent here: BTW MOST OF THIS STUFF IS UNUSED!!! if "index" is found within this new section then read the next value on that line, if "name" is found then read the next value on that line, if "kind" is found then read the next value on that line, if "parent" is found then read the next 2 values on that line and do some maths, if "child" is found then read the next 2 values, if "brother_next" is found then read the next 2 values, if "brother_prev" is found then read the next 2 values, if "sx_param" is found then read the next 2 values, if "sy_param" is found then read the next 2 values, if "sz_param" is found then read the next 2 values, if "rx_param" is found then read the next 2 values, if "ry_param" is found then read the next 2 values, if "rz_param" is found then read the next 2 values, if "tx_param" is found then read the next 2 values, if "ty_param" is found then read the next 2 values, if "tz_param" is found then read the next 2 values.

EXE STUFF (100% rambling here):[edit]

while ( !CmdStream::endOfCmds(a2) && !CmdStream::endOfSection(a2)) means loop from the start of the file until the end of it.

navi_start does not do anything. There is no reference to it anywhere in any parsing code whatsoever.

There is an unused ini file called 'play_3.ini' found in the 'stages/' folder. the Pal Demo tries to load it among stage1.ini and practice.ini.

The ageserver vftable only contains stream functions, like reading bytes, floats, strings, writing them and general stream commands.

Potentially unused enemy called the Otimoti, here are its outputs in the exe: TaiOtimotiStartDroppingWaterAction::start, TaiOtimotiFailToJumpAction::act, TaiOtimotiAirWaiting::act, TaiOtimotiDroppingAction::actByEvent, TaiOtimotiAttackingAction::act.

NAKA PARTS are anything within the '/objects/' directory

Anything to do with CoreNodes are just hierarchy shit.

Interesting string array: teki, navi, water, seed, key, door, gate, fall water, gem5, gem10, gem20, gem50, gem1, never use this, bomb gen, bomb, pikihead, goal, fulcrum, rope, ivy, cylinder test, sluice soft, sluice hard, sluice bomb, sluice bombhard, rocket, dual test, <demo:sunset> start, <demo:sunset> goal, kusa, ufo, weeds, <weed>, rockgen, grassgen, fish, <bo base>, secret1, workobject, boss:Spider, boss:Giant, boss:Snake, boss:TwSnake, boss:King, boss:Slime, boss:Kogane, boss:Pom, boss:KingBack, boss:Mizu, boss:XXX3,PLANT, PELLET

What the game calls a 2DRoot is set to "screen/sys_blo/" and "screen/otona_tex/"

CHID means challenge mode ID in the stages.ini file.

cnv files are meant for converting entire folders and simplifying the process down to a format.

The keyword 'jimen' is used to signify collision triangles in the plaintext formats.

Rooms are frequently mentioned in reference to collisions. They can be 'linked'.

the phases of collision creation go as follows: phase 1. summing tri count, phase 2. making plance and vert list for %d tris, phase 3. making plane and vert list, pass 4a. clearing edge links, pass 4b. finding connecting edges, and finally, BaseShape::createCollisions();

Joints have a hierarchy.

| *-*-* HERE ARE MY EXE IDENTIFIERS *-*-* |[edit]

CommandStream or CMDStream is custom file operations like reading, writing and parsing. newPikiGame does not mean a literal NEW PIKMIN GAME as I previously thought. It just means a new game as in when you start a new save file kinda game. If there is an allocateBytesOnHeap on func then an IF statement that meansif the bytes have been allocated then do this. Else do *that* sysCon is just if the any output window is active at that moment in time.

i THINK corenodes are like objects in the hierarchy of pikmin 1. thats why they get created and destroyed all the time. This may be like pikmin 1. With having an empty gameobject used to describe everything within its children. This could also explain how the memory dump is structured once the scene loads in demo versions of pikmin.

EDIT: CORENODES ARE A HIERARCHY!! CONFIRMED BY PLUGTEXCONV. ```cpp Output::filtDmdImport("Fixing hierarchy for %d joints\n", *(v86 + 22));

 for ( mm = 0; mm < *(v86 + 22); ++mm )
 {
   if ( *(*(v86 + 23) + 284 * mm + 24) == -1 )
     CoreNode::add((v86 + 968), (284 * mm + *(v86 + 23)));
   else
     CoreNode::add((*(v86 + 23) + 284 * *(*(v86 + 23) + 284 * mm + 24)), (284 * mm + *(v86 + 23)));
 }```
 haha i was right.