-
Notifications
You must be signed in to change notification settings - Fork 920
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
.clang-format definition #182
Comments
I tried writing one that conforms to the current style, where eg. there's a newline between |
We can infer from line numbers and the beta how code was originally written, but this will take time. The PSX symbol tells us how many lines each function is, so a single line function that has three lines, we can infer |
Starting reading from https://github.com/nomdenom/devil-beta/blob/f32eb0ed7ec9ca33077de32d24c4548b4feb99ac/Source/control.cpp#L811 we can probably also infer that the braces for |
Good find. Would have looked something like: if ( gbMaxPlayers == 1 ) {
pBtmBuff = (char *)DiabloAllocPtr(0x16800, 1018, "C:\\Diablo\\Direct\\CONTROL.CPP");
memset(pBtmBuff, 0, 0x16800u);
} else {
pBtmBuff = (char *)DiabloAllocPtr(0x2D000, 1021, "C:\\Diablo\\Direct\\CONTROL.CPP");
memset(pBtmBuff, 0, 0x2D000u);
}
pManaBuff = (char *)DiabloAllocPtr(0x1E40, 1024, "C:\\Diablo\\Direct\\CONTROL.CPP");
memset(pManaBuff, 0, 0x1E40u);
pLifeBuff = (char *)DiabloAllocPtr(0x1E40, 1026, "C:\\Diablo\\Direct\\CONTROL.CPP"); |
FreeMissileGFX is also quite interesting. I can't quite get it to match up though. //----- (0043ED95) --------------------------------------------------------
void __fastcall FreeMissileGFX(int mi)
{
signed int i; // [esp+10h] [ebp-4h]
if ( misfiledata[mi].mFlags & 4 )
{
if ( misfiledata[mi].mAnimData[0] )
{
mem_free_dbg(
&misfiledata[mi].mAnimData[0][-4 * misfiledata[mi].mAnimFAmt],
907,
"C:\\Diablo\\Direct\\MISSILES.CPP");
misfiledata[mi].mAnimData[0] = 0;
}
}
else
{
for ( i = 0; misfiledata[mi].mAnimFAmt > i; ++i )
{
if ( misfiledata[mi].mAnimData[i] )
{
mem_free_dbg(misfiledata[mi].mAnimData[i], 916, "C:\\Diablo\\Direct\\MISSILES.CPP");
misfiledata[mi].mAnimData[i] = 0;
}
}
}
} |
Similarly LoadMissileGFX is quite interesting. And likewise, I can't get it match up correctly. //----- (0043EAA9) --------------------------------------------------------
void __fastcall LoadMissileGFX(BYTE mi)
{
char pszName[256]; // [esp+10h] [ebp-108h]
int i; // [esp+110h] [ebp-8h]
unsigned __int8 *anim; // [esp+114h] [ebp-4h]
if ( misfiledata[mi].mFlags & 4 ) {
sprintf(pszName, "Missiles\\%s.CEL", misfiledata[mi].mName);
anim = LoadFileInMem(pszName, 0, 866, "C:\\Diablo\\Direct\\MISSILES.CPP");
for ( i = 0; misfiledata[mi].mAnimFAmt > i; ++i ) {
misfiledata[mi].mAnimData[i] = &anim[*(_DWORD *)&anim[4 * i]];
}
} else if ( misfiledata[mi].mAnimFAmt == 1 ) {
sprintf(pszName, "Missiles\\%s.CEL", misfiledata[mi].mName);
if ( !misfiledata[mi].mAnimData[0] ) {
misfiledata[mi].mAnimData[0] = LoadFileInMem(pszName, 0, 874, "C:\\Diablo\\Direct\\MISSILES.CPP");
}
} else {
for ( i = 0; misfiledata[mi].mAnimFAmt > i; ++i ) {
sprintf(pszName, "Missiles\\%s%i.CEL", misfiledata[mi].mName, i + 1);
if ( !misfiledata[mi].mAnimData[i] ) {
misfiledata[mi].mAnimData[i] = LoadFileInMem(pszName, 0, 879, "C:\\Diablo\\Direct\\MISSILES.CPP");
}
}
}
} |
Ah, a clue from codec.cpp. Invocations of From codec_decode if ( !pbSrcDst )
assertion_failed(130, "C:\\Diablo\\Direct\\CODEC.CPP");
if ( !pszPassword )
assertion_failed(131, "C:\\Diablo\\Direct\\CODEC.CPP"); Where the original probably looked as follows: assert(pbSrcDst != NULL, __LINE__, __FILE__);
assert(pszPassword != NULL, __LINE__, __FILE__); Or even (where line numbers and source file name is added in a macro expansion): assert(pbSrcDst != NULL);
assert(pszPassword != NULL); |
The line info will also help us tell which if-branch was placed first. e.g. from AddHall: void __fastcall AddHall(int nX1, int nY1, int nX2, int nY2, int nHd)
{
HALLNODE *v7; // [esp+14h] [ebp-8h]
HALLNODE *i; // [esp+18h] [ebp-4h]
if ( pHallList )
{
v7 = (HALLNODE *)DiabloAllocPtr(24, 1571, "C:\\Diablo\\Direct\\DRLG_L2.CPP");
v7->nHallx1 = nX1;
v7->nHally1 = nY1;
v7->nHallx2 = nX2;
v7->nHally2 = nY2;
v7->nHalldir = nHd;
v7->pNext = 0;
for ( i = pHallList; i->pNext; i = i->pNext )
;
i->pNext = v7;
}
else
{
pHallList = (HALLNODE *)DiabloAllocPtr(24, 1562, "C:\\Diablo\\Direct\\DRLG_L2.CPP");
pHallList->nHallx1 = nX1;
pHallList->nHally1 = nY1;
pHallList->nHallx2 = nX2;
pHallList->nHally2 = nY2;
pHallList->nHalldir = nHd;
pHallList->pNext = 0;
}
} Here, the branches of the if statements should swap place as the else branch of the decompiled code has a line number (1562) preceding the if-branch (1571). |
Hmm, seems like ternary if-statement may have been used. See for instance InitControlPan: pPanelButtons = LoadFileInMem("CtrlPan\\Panel8bu.CEL", 0, 1055, "C:\\Diablo\\Direct\\CONTROL.CPP");
for ( j = 0; j < 8; ++j )
panbtn[j] = 0;
panbtndown = 0;
if ( gbMaxPlayers == 1 )
numpanbtns = 6;
else
numpanbtns = 8;
pChrButtons = LoadFileInMem("Data\\CharBut.CEL", 0, 1061, "C:\\Diablo\\Direct\\CONTROL.CPP"); Using ternary if-statement to get it to match up: pPanelButtons = LoadFileInMem("CtrlPan\\Panel8bu.CEL", 0, 1055, "C:\\Diablo\\Direct\\CONTROL.CPP");
for ( j = 0; j < 8; ++j ) {
panbtn[j] = 0;
}
panbtndown = 0;
numpanbtns = ( gbMaxPlayers == 1 ) ? 6 : 8;
pChrButtons = LoadFileInMem("Data\\CharBut.CEL", 0, 1061, "C:\\Diablo\\Direct\\CONTROL.CPP"); |
Yeah it's highly likely they used macros everywhere for assertions, which influenced the line numbers. Even for the functions
|
@squidcc pointed out a section with a few interesting lines https://github.com/nomdenom/devil-beta/blob/f32eb0ed7ec9ca33077de32d24c4548b4feb99ac/Source/control.cpp#L858
Also https://github.com/nomdenom/devil-beta/blob/f32eb0ed7ec9ca33077de32d24c4548b4feb99ac/Source/control.cpp#L810 would probably have been formatted the following:
So again no braces for single line statements, but also both braces are on the same line as the else. |
Another interesting part is https://github.com/nomdenom/devil-beta/blob/f32eb0ed7ec9ca33077de32d24c4548b4feb99ac/Source/control.cpp#L871 - 889 showing that they had at most 4 lines to handle the player class differences, I don't see any sane way to do this so maybe they used a macro for this? |
You could do that class handling stuff on two lines using stacked ternary operators. Also if _pClass was typed as an enum the compiler might have made the assumption that it could only be one of the defined values. |
seritools pointed out this as an option:
|
@squidcc tried exactly that, but I don't have faith in the compiler regarding that anymore :D Also typing _pClass as an enum would force it to 4 bytes size (specifying the storage size wasn't a thing back then) |
Hmm, I just considered that we probably won't be able to find a uniform style for the project that was used throughout the original. Because, that probably wasn't the case. There were more than one developer, so perhaps more than one style was used. That being said, we can try to find something that is as close to the truth of most functions as possible, and then use that throughout Devilution. |
So, I've been playing around a bit with clang-format. There are a few pre-declared styles. Perhaps we should just evaluate these and choose the one we like the most? As a test, I applied the Mozilla style and did a bindiff on the executable. Besides the timestamp, it's identical, so we can be safe that the code logic is not modified. To generate the clang-format config, I ran My suggestion is that we evaluate the five pre-declared styles of clang-format, and simply pick the one we like the most.
I'll create a few branches, one for each style, so we can discuss what the code looks like. Hopefully, this way we can simply run Edit: to convert all the files, I used:
|
So, @AJenbo, @nomdenom, @galaxyhaxz, @seritools, @squidcc, @ApertureSecurity. Which style do you like the most? I suggest we put it to a vote :) Look at the following branches to see what each style looks like, using 👍 LLVM: https://github.com/mewpull/devilution/blob/clang-format-llvm/Source/player.cpp Note: I don't think any of these styles is perfect, but that's not the point. Agreeing on one style is better, as it allows us to focus on more interesting parts. Then later on in the project, the style can be refined. |
Haha, great. I actually ruled out the WebKit style on first glance, since it didn't have align trailing comments. However, I forgot this is a simple setting =P So, we should definitely add this setting if going for WebKit. I think most styles look quite well, and very much like that it becomes a completely uniform look throughout the code. So +1 for WebKit if we add the align trailing line comments setting. Otherwise, I am also fine with the other styles. |
Current votes:
|
Found something interesting in the sym file. ClrPlrPath and InitDungMsgs are both reported as 4 line in PSX. PM_DoNewLvl and PM_DoStand are both reported as 2 lines, even though it's only "return false" i find it hard to make a function fit on only 2 lines unless it's some thing like:
But that just seams very odd... Also there is a very consistent 7 line gap between one function ending and the next one starting. I guess this could have been for comments, but maybe it dosn't count the signature or brackets? |
A common convention is to have the return type on its own line, BOOL
__fastcall PM_DoStand(int pnum) { return FALSE; } Edit: note, the |
Also, it probably makes sense to fix the includes so they do not need to be ordered in a specific way (by adding prerequisite header includes into the headers themselves). This way they can also be included independently and eg. IDEs such as CLion do not choke on them. |
🎉 |
really exiting that we got this in :) |
It would be good if we could write a .clang-format that set the code style for the project. This would help developers stick to the right/consistent style.
Preferably clang-format would be run early on for the entire source so that it's cleaner to work with and masks less history from blame.
The text was updated successfully, but these errors were encountered: