Cherry
14.06.2013, 23:25
Ich habe vorhin einen Minipatch gemacht nachdem ich einen seltsamen "Division by zero error" eines 2k3-Projektes untersucht habe. Dieser Patch wird auch in DynRPG integriert werden.
Dieser Patch ist deshalb auch nur für RM2k3 v1.08 erhältlich.
Der Patch behebt einen Fehler im RPG Maker der dazu führen konnte dass das Spiel mit einem "Division by zero error" abgestürzt ist wenn bestimmte Pictureoperationen durchgeführt wurden, im Speziellen Randfälle wie Pictures mit kleinem Zoomlevel am Rand des Bildschirms.
Download: http://share.cherrytree.at/showfile-10156/rpg_rt_division_by_zero_bugfix.ips
Der RPG Maker verwendet eine Funktion mit der ein bestimmtes Rechteck aus einem sogenannten "Sheet" auf ein bestimmtes Zielrechteck auf einem sogenannten "Board" gezeichnet wird, dabei kann das Bild auch verzerrt werden (das wird für die Zoomfunktion verwendet). Um jetzt die Koordinaten so zu korrigieren dass Bereiche die über das Sheet oder das Board hinausragen würden gar nicht gezeichnet werden (weil das ja nicht ginge), werden die beiden Rechtecksangaben hiermit angepasst:
void __usercall FitRect(signed int *srcLeft<eax>, signed int *srcTop<edx>, signed int *x<ecx>, int dstBoardHeight, int dstBoardWidth, int srcSheetHeight, int srcSheetWidth, int *dstHeight, int *dstWidth, int *srcHeight, int *srcWidth, int *y)
{
signed int *x_; // edi@1
signed int *srcTop_; // esi@1
signed int *srcLeft_; // ebx@1
x_ = x;
srcTop_ = srcTop;
srcLeft_ = srcLeft;
FitRectCoordinate(srcLeft, x, srcWidth, srcSheetWidth, dstWidth);
FitRectCoordinate(srcTop_, y, srcHeight, srcSheetHeight, dstHeight);
FitRectCoordinate(x_, srcLeft_, dstWidth, dstBoardWidth, srcWidth);
FitRectCoordinate(y, srcTop_, dstHeight, dstBoardHeight, srcHeight);
}
void __userpurge FitRectCoordinate(signed int *srcPos<eax>, signed int *dstPos<edx>, int *srcSize<ecx>, int srcSheetSize, int *dstSize)
{
int *dstSize_; // esi@1
int srcSize_deref; // edi@2
int srcSize_deref2; // edi@5
signed int *dstPos_; // [sp+Ch] [bp-4h]@1
dstPos_ = dstPos;
dstSize_ = dstSize;
if ( *srcPos < 0 )
{
srcSize_deref = *srcSize;
*srcSize += *srcPos;
if ( *srcSize > 0 )
{
*dstSize_ = *srcSize * *dstSize_ / srcSize_deref;
*dstPos_ -= *dstSize_ * *srcPos / *srcSize;
*srcPos = 0;
}
}
if ( *srcSize + *srcPos > srcSheetSize )
{
srcSize_deref2 = *srcSize;
*srcSize = srcSheetSize - *srcPos;
*dstSize_ = *srcSize * *dstSize_ / srcSize_deref2; // Crash hier weil srcSize_deref2 == 0
if ( !*dstSize_ )
*dstSize_ = 1;
}
}
Ignoriere die teilweise mehrfach vorhandenen Variablen, der Code kommt von einem Decompiler.
An der markierten Zeile ist das Programm abgestürzt weil srcSize_deref2 da 0 war. Ich habe jetzt quasi ein if(srcSize_deref2 != 0) { ... } else { *dstSize_ = 0; } um die Zeile herumgemacht.
Dieser Patch ist deshalb auch nur für RM2k3 v1.08 erhältlich.
Der Patch behebt einen Fehler im RPG Maker der dazu führen konnte dass das Spiel mit einem "Division by zero error" abgestürzt ist wenn bestimmte Pictureoperationen durchgeführt wurden, im Speziellen Randfälle wie Pictures mit kleinem Zoomlevel am Rand des Bildschirms.
Download: http://share.cherrytree.at/showfile-10156/rpg_rt_division_by_zero_bugfix.ips
Der RPG Maker verwendet eine Funktion mit der ein bestimmtes Rechteck aus einem sogenannten "Sheet" auf ein bestimmtes Zielrechteck auf einem sogenannten "Board" gezeichnet wird, dabei kann das Bild auch verzerrt werden (das wird für die Zoomfunktion verwendet). Um jetzt die Koordinaten so zu korrigieren dass Bereiche die über das Sheet oder das Board hinausragen würden gar nicht gezeichnet werden (weil das ja nicht ginge), werden die beiden Rechtecksangaben hiermit angepasst:
void __usercall FitRect(signed int *srcLeft<eax>, signed int *srcTop<edx>, signed int *x<ecx>, int dstBoardHeight, int dstBoardWidth, int srcSheetHeight, int srcSheetWidth, int *dstHeight, int *dstWidth, int *srcHeight, int *srcWidth, int *y)
{
signed int *x_; // edi@1
signed int *srcTop_; // esi@1
signed int *srcLeft_; // ebx@1
x_ = x;
srcTop_ = srcTop;
srcLeft_ = srcLeft;
FitRectCoordinate(srcLeft, x, srcWidth, srcSheetWidth, dstWidth);
FitRectCoordinate(srcTop_, y, srcHeight, srcSheetHeight, dstHeight);
FitRectCoordinate(x_, srcLeft_, dstWidth, dstBoardWidth, srcWidth);
FitRectCoordinate(y, srcTop_, dstHeight, dstBoardHeight, srcHeight);
}
void __userpurge FitRectCoordinate(signed int *srcPos<eax>, signed int *dstPos<edx>, int *srcSize<ecx>, int srcSheetSize, int *dstSize)
{
int *dstSize_; // esi@1
int srcSize_deref; // edi@2
int srcSize_deref2; // edi@5
signed int *dstPos_; // [sp+Ch] [bp-4h]@1
dstPos_ = dstPos;
dstSize_ = dstSize;
if ( *srcPos < 0 )
{
srcSize_deref = *srcSize;
*srcSize += *srcPos;
if ( *srcSize > 0 )
{
*dstSize_ = *srcSize * *dstSize_ / srcSize_deref;
*dstPos_ -= *dstSize_ * *srcPos / *srcSize;
*srcPos = 0;
}
}
if ( *srcSize + *srcPos > srcSheetSize )
{
srcSize_deref2 = *srcSize;
*srcSize = srcSheetSize - *srcPos;
*dstSize_ = *srcSize * *dstSize_ / srcSize_deref2; // Crash hier weil srcSize_deref2 == 0
if ( !*dstSize_ )
*dstSize_ = 1;
}
}
Ignoriere die teilweise mehrfach vorhandenen Variablen, der Code kommt von einem Decompiler.
An der markierten Zeile ist das Programm abgestürzt weil srcSize_deref2 da 0 war. Ich habe jetzt quasi ein if(srcSize_deref2 != 0) { ... } else { *dstSize_ = 0; } um die Zeile herumgemacht.