Advertisement
Moolah60

ACNL Pattern Stuff 2

Jan 10th, 2019
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.41 KB | None | 0 0
  1. typedef unsigned char u8;
  2. typedef unsigned short u16;
  3. typedef unsigned int u32;
  4.  
  5. enum class DesignType : u8 {
  6.     DressLongSleeve = 0,
  7.     DressShortSleeve = 1,
  8.     DressSleeveless = 2,
  9.     ShirtLongSleeve = 3,
  10.     ShirtShortSleeve = 4,
  11.     ShirtSleeveless = 5,
  12.     HornedHat = 6,
  13.     KnitHat = 7,
  14.     PhotoBoard = 8,
  15.     Pattern = 9
  16. };
  17.  
  18. static const u16 word_88EA5C[12] = {0x1000, 0xE00, 0xC00, 0xC00, 0xA00, 0x800, 0x400, 0x400, 0xB81, 0x400, 0x400, 0x400};
  19.  
  20. static const u8 byte_88E754[8] = {0, 0, 0, 0x20, 0x20, 0, 0x20, 0x20};
  21.  
  22. static const u32 dword_88E85C[128] = {
  23.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3FC00000, 0xFFF80000, 0xFFFE0000, 0xFFFF0000, 0xFFFF8000, 0xFFFFC000,
  24.     0xFFFFC000, 0xFFFFE000, 0xFFFFE000, 0xFFFFE000, 0xFFFFE000, 0xFFFFE000, 0xFFFFC000, 0xFFFFC000, 0xFFFF8000,
  25.     0xFFFF0000, 0xFFFC0000, 0xFFF00000, 0x1F800000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  26.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 0xF, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0x7F,
  27.     0x7F, 0x7F, 0x3F, 0x1F, 0x1F, 0xF, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  28.     0, 0, 0, 0, 0, 0, 0, 0
  29. };
  30.  
  31. static const u8 byte_88E75C[256] = {
  32.     0x0A, 0x0A, 0x0A, 0x0A, 0x02, 0x08, 0x08, 0x02, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0A, 0x0A, 0x02, 0x02,
  33.     0x02, 0x09, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0B, 0x01, 0x03, 0x03, 0x03, 0x09, 0x03, 0x09,
  34.     0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00,
  35.     0x00, 0x00, 0x00, 0x0B, 0x0A, 0x08, 0x08, 0x08, 0x08, 0x0B, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
  36.     0x0A, 0x0A, 0x08, 0x0A, 0x0A, 0x0B, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x0E, 0x09, 0x09, 0x09,
  37.     0x09, 0x09, 0x09, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x09, 0x09,
  38.     0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x00, 0x00, 0x00,
  39.     0x00, 0x00, 0x00, 0x0B, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B,
  40.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x04, 0x04, 0x04,
  41.     0x04, 0x0B, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x0D, 0x0D, 0x05, 0x0D, 0x05, 0x05, 0x05, 0x05,
  42.     0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x05, 0x05, 0x07, 0x00, 0x00, 0x00,
  43.     0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x0D, 0x0B, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
  44.     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  45. };
  46.  
  47. u8 PatternUnknownSetter(Pattern* pattern) {
  48.     u8 result = 0;
  49.     u8 oldChecksum = 0;
  50.     u16 patternTypeModifierValue = word_88EA5C[pattern->Type];
  51.     u16 tempBuffer[16]; // Each palette index (0 - 0xFF) has an entry in @byte_88E75C. This tempBuffer increments one of its values based on the palette index's offset value in that byte array.
  52.     if (pattern->Type == DesignType::PhotoBoard) {
  53.         for (u32 patternEntry = 0; patternEntry < 4; patternEntry++) {
  54.             for (u32 y = 0; y < 32; y++) {
  55.                 for (u32 x = 0; x < 32; x++) {
  56.                     if (byte_88E754[2 * patternEntry] + x < 0x34 && !(dword_88E85C[y + 32 * patternEntry] & (1 << x))) {
  57.                         u32 patternPixelPaletteIndex = (*(u32*) pattern->PatternData[4 * (((patternEntry * 0x80) & 0x1FF) + 4 * ((y & 0x1F) / 8))] >> (4 * x & 0x1F);
  58.                         if (patternPixelPaletteIndex == 0xF) {
  59.                             patternPixelPaletteIndex = 0;
  60.                         }
  61.  
  62.                         tempBuffer[byte_88E75C[pattern->Palette[patternPixelPaletteIndex]]]++;
  63.                     }
  64.                 }
  65.             }
  66.         }
  67.     }
  68.  
  69.     // TODO: Other Pattern types
  70.  
  71.     // Process the temp buffer.
  72.     // Grab the index with the highest occurrance.
  73.     u32 mostOccurredIdx = 0;
  74.  
  75.     for (u32 i = 0; i < 15; i++) {
  76.         if (tempBuffer[i] > tempBuffer[mostOccurredIdx]) {
  77.             mostOccurredIdx = i;
  78.         }
  79.     }
  80.  
  81.     // Grab the second most occurring index.
  82.     u32 secondMostOccurredIndex = 0;
  83.     for (u32 i = 0; i < 15; i++) {
  84.         if (i != mostOccurredIdx && tempBuffer[i] > tempBuffer[secondMostOccurredIndex]) {
  85.             secondMostOccurredIndex = i;
  86.         }
  87.     }
  88.  
  89.     u16* mostOccurredPtr = &tempBuffer[mostOccurredIdx];
  90.     u16 mostOccurredValue = tempBuffer[mostOccurredIdx];
  91.     float patternTypeThreshold = (float) patternTypeModifierValue * 0.9f;
  92.    
  93.     // Clamp pattern type modifier value to minimum. That's what the COERCE_SIGNED_INT is doing. It's some way to check the precision of the floating point value.
  94.     if (patternTypeThreshold <= 0.0002) {
  95.         patternTypeThreshold = 0.0002;
  96.     }
  97.  
  98.     float patternTypeThreshold2 = (float) patternTypeModifierValue * 0.35f;
  99.     if (patternTypeThreshold2 < 0.0002) {
  100.         patternTypeThreshold2 = 0.0002;
  101.     }
  102.  
  103.     if ((float) mostOccurredValue < patternTypeThreshold) {
  104.         if ((float) mostOccurredValue < patternTypeThreshold2) {
  105.             oldChecksum = pattern->Checksum;
  106.             result = 0xCC; // Default checksum?
  107.         }
  108.         else {
  109.             pattern->Checksum = pattern->Checksum & 0xF0 | mostOccurredIdx & 0x0F;
  110.             u8 lowerChecksumNibble = pattern->Checksum & 0x0F;
  111.  
  112.             float secondMostOccurranceThreshold = (float) (patternTypeModifierValue - mostOccurredValue) * 0.6f;
  113.             if (secondMostOccurranceThreshold < 0.0002) {
  114.                 secondMostOccurranceThreshold = 0.0002;
  115.             }
  116.  
  117.             if ((float) tempBuffer[secondMostOccurredIndex] < secondMostOccurranceThreshold) {
  118.                 result = 0xC0 | lowerChecksumNibble; // could be simplified to result = 0xC0 | (mostOccurredIdx & 0xF);
  119.             }
  120.             else {
  121.                 result = ((secondMostOccurredIndex & 0x0F) << 4) | lowerChecksumNibble; // Again could be simplified to: ((secondMostOccurredIndex & 0x0F) << 4) | (mostOccurredIdx & 0xF);
  122.             }
  123.         }
  124.     }
  125.     else {
  126.         result = (pattern->Checksum & 0xF0 | mostOccurredValue) & 0xF | ((mostOccurredValue & 0xF) << 4);
  127.     }
  128.  
  129.     Pattern->Checksum = result;
  130.     return result;
  131. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement