/* V2MemTest - A CLI Tool to test & fix Voodoo² TMU System * Copyright (C) 2026 ChaCha * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include "FaultSources.h" #include "Utils.h" const def_sFaultSourceScoreRec _ar_dFaultScores[NB_FAULT_SOURCE] = { { .eThisFaultSource = VOODOO_BOARD, .szName = "VOODOO_BOARD", .szLoc = "Main Board", .eParrentFaultSource = _INVALID_FAULT_SOURCE_, .dScore = 0.0, .dWeight = 1.0, }, FAULT_SOURCES(GEN_FAULT_SOURCES_ARRAY) }; void FaultSource_reset(def_sFaultSourceScoreRec* const pCtx) { memcpy( pCtx, _ar_dFaultScores, sizeof(_ar_dFaultScores)); } static unsigned long FaultSource_getNbDeps( const def_sFaultSourceScoreRec* const pCtx, const def_eFaultSource eFaultSource) { unsigned long res = 0; for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx ) if(pCtx[idx].eParrentFaultSource == eFaultSource) res++; return res; } void FaultSource_addScore( def_sFaultSourceScoreRec* const pCtx, def_eFaultSource eFaultSource, double dScore) { double dDivider = 1.0; do { //if(dDivider==1.0) // printf("set Score %f to %s\n",dScore,pCtx[eFaultSource].szName); dScore /= dDivider; pCtx[eFaultSource].dScore += dScore; eFaultSource = pCtx[eFaultSource].eParrentFaultSource; dDivider *= 5; }while(eFaultSource != _INVALID_FAULT_SOURCE_); } void FaultSource_nomalize( def_sFaultSourceScoreRec* const pCtx) { double dSum = 0.0; for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx ) dSum+= pCtx[idx].dScore; if(dSum != 0) FaultSource_divideAll(pCtx,dSum); } // This function can only be used on non-sorted Rec (is relies on indexes)! void FaultSource_sum( def_sFaultSourceScoreRec** const pCtxRef, const unsigned int uNbRef, def_sFaultSourceScoreRec* const pCtx) { for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx ) { for(unsigned long idxRef = 0; idxRef < uNbRef; ++idxRef ) { pCtx[idx].dScore += pCtxRef[idxRef][idx].dScore; } } FaultSource_divideAll(pCtx,uNbRef); } void FaultSource_divideAll( def_sFaultSourceScoreRec* const pCtx, const double dDivider) { for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx ) pCtx[idx].dScore /= dDivider; } static unsigned long FaultSource_GetIdx( const def_sFaultSourceScoreRec* const pCtx, const def_eFaultSource eFaultSource) { for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx ) if(pCtx[idx].eThisFaultSource == eFaultSource) return idx; return _INVALID_FAULT_SOURCE_; } static inline void FaultSource_Swap( def_sFaultSourceScoreRec* const pCtx, const def_eFaultSource A, const def_eFaultSource B) { def_sFaultSourceScoreRec tmp; memcpy( &tmp, &pCtx[A], sizeof(def_sFaultSourceScoreRec)); memcpy( &pCtx[A], &pCtx[B], sizeof(def_sFaultSourceScoreRec)); memcpy( &pCtx[B], &tmp, sizeof(def_sFaultSourceScoreRec)); } void FaultSource_getSorted( def_sFaultSourceScoreRec* const pDst, const def_sFaultSourceScoreRec* const pCtx) { unsigned char bSwapped = 1; memcpy( pDst, pCtx, sizeof(_ar_dFaultScores)); for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx ) pDst[idx].dScore *= pDst[idx].dWeight; // shaker sort FixMe: use qsort() while(bSwapped) { bSwapped = 0; for(unsigned long idx=0; idx < (NB_FAULT_SOURCE - 1); ++idx ) { if( pDst[idx].dScore < pDst[idx + 1].dScore) { FaultSource_Swap( pDst, idx, idx + 1); bSwapped = 1; break; } } for(long idx = (NB_FAULT_SOURCE-2); idx >= 0; --idx ) { if( pDst[idx].dScore < pDst[idx + 1].dScore) { FaultSource_Swap( pDst, idx, idx + 1); bSwapped = 1; break; } } } // updating refs for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx ) pDst[idx].eParrentFaultSource = FaultSource_GetIdx( pDst, pDst[idx].eParrentFaultSource); for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx ) pDst[idx].eThisFaultSource = idx; } void FaultSource_getLoc( const def_sFaultSourceScoreRec* const pCtx, def_eFaultSource eFaultSource, char* const loc) { loc[0]='\0'; strcpy(loc, pCtx[eFaultSource].szLoc); eFaultSource = pCtx[eFaultSource].eParrentFaultSource; while(eFaultSource != _INVALID_FAULT_SOURCE_) { static char buff[1024]; sprintf(buff, "%s->%s", pCtx[eFaultSource].szLoc, loc); strcpy(loc, buff); eFaultSource = pCtx[eFaultSource].eParrentFaultSource; } } void FaultSource_display(const def_sFaultSourceScoreRec* const pCtx) { printf("------------------------------------------------\n"); printf("\ndefects list:\n\n"); printf("score\telement [Loc]\n"); printf("------------------------------------------------\n"); for(unsigned long idx = 0; (idx < NB_FAULT_SOURCE) && (pCtx[idx].dScore > 0); ++idx ) { static char buff[1024] = {0}; buff[0]='\0'; FaultSource_getLoc(pCtx,idx, buff); printf("%02.3f\t%s [%s]\n", pCtx[idx].dScore, pCtx[idx].szName, buff ); } } void ByteBitFaultSet( def_sFaultSourceScoreRec* const pCtx, const uint8_t ErrorMark, const double dScore, const def_eFaultSource eFaultSource) { for(unsigned char bitPos = 0; bitPos <= 7 ; ++bitPos) if(ErrorMark & (1u << bitPos)) { FaultSource_addScore(pCtx, eFaultSource + bitPos, dScore); } } void WordBitFaultSet( def_sFaultSourceScoreRec* const pCtx, const uint16_t ErrorMark, const double dScore, const def_eFaultSource eFaultSource) { for(unsigned char bitPos = 0; bitPos <= 15 ; ++bitPos) if(ErrorMark & (1u << bitPos)) { FaultSource_addScore(pCtx, eFaultSource + bitPos, dScore); } } void LWordBitFaultSet( def_sFaultSourceScoreRec* const pCtx, const uint32_t ErrorMark, const double dScore, const def_eFaultSource eFaultSourceL, const def_eFaultSource eFaultSourceH) { for(unsigned char bitPos = 0; bitPos <= 31 ; ++bitPos) if(ErrorMark & (1u << bitPos)) { if(bitPos < 16) FaultSource_addScore(pCtx, eFaultSourceL + bitPos, dScore); else FaultSource_addScore(pCtx, eFaultSourceH + bitPos - 16, dScore); } } void QuartetBitFaultSet( def_sFaultSourceScoreRec* const pCtx, const uint8_t ErrorMark, const double dScore, const def_eFaultSource eFaultSource) { for(uint8_t bitPos = 0; bitPos < 4 ; ++bitPos) if(ErrorMark & (1u << bitPos)) FaultSource_addScore(pCtx, eFaultSource + bitPos, dScore); } void RGBToBus_Fault( def_sFaultSourceScoreRec* const pCtx, const uint32_t ErrorMark, const double dScore, const def_eFaultSource eFaultSource) { const uint16_t u16pix1 = ErrorMark & 0xFFFF; const uint16_t u16pix2 = (ErrorMark>>16) & 0xFFFF; uint16_t u16Bus_r8 = ((u16pix1>>11) & 0x1F) << 3; uint16_t u16Bus_g8 = ((u16pix1>>5) & 0x3F) << 2; uint16_t u16Bus_b8 = ((u16pix1>>0) & 0x1F) << 3; uint16_t u16Bus_a8 = 0; /* uint16_t u16Fault_W1 = (u16Bus_g8<<8) + u16Bus_b8; uint16_t u16Fault_W2 = (u16Bus_a8<<8) + u16Bus_r8; */ /* Incoming data wont have Alpha channel, so we must normalize * Fault weight */ ByteBitFaultSet(pCtx, u16Bus_b8, dScore/2, eFaultSource); ByteBitFaultSet(pCtx, u16Bus_g8, dScore, eFaultSource + 8); ByteBitFaultSet(pCtx, u16Bus_r8, dScore/2, eFaultSource); //ByteBitFaultSet(pCtx, u16Bus_a8, dScore, eFaultSource + 8); u16Bus_r8 = ((u16pix2>>11) & 0x1F) << 3; u16Bus_g8 = ((u16pix2>>5) & 0x3F) << 2; u16Bus_b8 = ((u16pix2>>0) & 0x1F) << 3; u16Bus_a8 = 0; /* uint16_t u16Fault_W3 = (u16Bus_g8<<8) + u16Bus_b8; uint16_t u16Fault_W4 = (u16Bus_a8<<8) + u16Bus_r8; */ /* Incoming data wont have Alpha channel, so we must normalize * Fault weight */ ByteBitFaultSet(pCtx, u16Bus_b8, dScore/2, eFaultSource); ByteBitFaultSet(pCtx, u16Bus_g8, dScore, eFaultSource + 8); ByteBitFaultSet(pCtx, u16Bus_r8, dScore/2, eFaultSource); //ByteBitFaultSet(pCtx, u16Bus_a8, dScore, eFaultSource + 8); } void RGBToBus_Fault_Quartets( def_sFaultSourceScoreRec* const pCtx, const uint32_t ErrorMark, const double dScore, const def_eFaultSource eFaultSource1, const def_eFaultSource eFaultSource2, const def_eFaultSource eFaultSource3, const def_eFaultSource eFaultSource4) { const uint16_t u16pix1 = ErrorMark & 0xFFFF; const uint16_t u16pix2 = (ErrorMark>>16) & 0xFFFF; uint16_t u16Bus_r8 = ((u16pix1>>11) & 0x1F) << 3; uint16_t u16Bus_g8 = ((u16pix1>>5) & 0x3F) << 2; uint16_t u16Bus_b8 = ((u16pix1>>0) & 0x1F) << 3; uint16_t u16Bus_a8 = 0; /* uint16_t u16Fault_W1 = (u16Bus_g8<<8) + u16Bus_b8; uint16_t u16Fault_W2 = (u16Bus_a8<<8) + u16Bus_r8; */ /* Incoming data wont have Alpha channel, so we must normalize * Fault weight */ QuartetBitFaultSet(pCtx, u16Bus_b8 & 0xF, dScore/2, eFaultSource1); QuartetBitFaultSet(pCtx, (u16Bus_b8<<4) & 0xF, dScore/2, eFaultSource2); QuartetBitFaultSet(pCtx, u16Bus_g8 & 0xF, dScore, eFaultSource3); QuartetBitFaultSet(pCtx, (u16Bus_g8<<4) & 0xF, dScore, eFaultSource4); QuartetBitFaultSet(pCtx, u16Bus_r8 & 0xF, dScore/2, eFaultSource1); QuartetBitFaultSet(pCtx, (u16Bus_r8<<4) & 0xF, dScore/2, eFaultSource2); //QuartetBitFaultSet(pCtx, u16Bus_a8 & 0xF, dScore, eFaultSource3); //QuartetBitFaultSet(pCtx, (u16Bus_a8<<4) & 0xF, dScore, eFaultSource4); u16Bus_r8 = ((u16pix2>>11) & 0x1F) << 3; u16Bus_g8 = ((u16pix2>>5) & 0x3F) << 2; u16Bus_b8 = ((u16pix2>>0) & 0x1F) << 3; u16Bus_a8 = 0; /* uint16_t u16Fault_W3 = (u16Bus_g8<<8) + u16Bus_b8; uint16_t u16Fault_W4 = (u16Bus_a8<<8) + u16Bus_r8; */ /* Incoming data wont have Alpha channel, so we must normalize * Fault weight */ QuartetBitFaultSet(pCtx, u16Bus_b8 & 0xF, dScore/2, eFaultSource1); QuartetBitFaultSet(pCtx, (u16Bus_b8<<4) & 0xF, dScore/2, eFaultSource2); QuartetBitFaultSet(pCtx, u16Bus_g8 & 0xF, dScore, eFaultSource3); QuartetBitFaultSet(pCtx, (u16Bus_g8<<4) & 0xF, dScore, eFaultSource4); QuartetBitFaultSet(pCtx, u16Bus_r8 & 0xF, dScore/2, eFaultSource1); QuartetBitFaultSet(pCtx, (u16Bus_r8<<4) & 0xF, dScore/2, eFaultSource2); //QuartetBitFaultSet(pCtx, u16Bus_a8 & 0xF, dScore, eFaultSource3); //QuartetBitFaultSet(pCtx, (u16Bus_a8<<4) & 0xF, dScore, eFaultSource4); }