mirror of
				https://github.com/MarioSpore/Grinch-AP.git
				synced 2025-10-21 20:21:32 -06:00 
			
		
		
		
	
		
			
	
	
		
			70 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			70 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | 
 | ||
|  | class BackgroundEditor: | ||
|  |     def __init__(self, rom, index, *, attributes=False): | ||
|  |         self.__index = index | ||
|  |         self.__is_attributes = attributes | ||
|  | 
 | ||
|  |         self.tiles = {} | ||
|  |         if attributes: | ||
|  |             data = rom.background_attributes[index] | ||
|  |         else: | ||
|  |             data = rom.background_tiles[index] | ||
|  |         idx = 0 | ||
|  |         while data[idx] != 0x00: | ||
|  |             addr = data[idx] << 8 | data[idx + 1] | ||
|  |             amount = (data[idx + 2] & 0x3F) + 1 | ||
|  |             repeat = (data[idx + 2] & 0x40) == 0x40 | ||
|  |             vertical = (data[idx + 2] & 0x80) == 0x80 | ||
|  |             idx += 3 | ||
|  |             for n in range(amount): | ||
|  |                 self.tiles[addr] = data[idx] | ||
|  |                 if not repeat: | ||
|  |                     idx += 1 | ||
|  |                 addr += 0x20 if vertical else 0x01 | ||
|  |             if repeat: | ||
|  |                 idx += 1 | ||
|  | 
 | ||
|  |     def dump(self): | ||
|  |         if not self.tiles: | ||
|  |             return | ||
|  |         low = min(self.tiles.keys()) & 0xFFE0 | ||
|  |         high = (max(self.tiles.keys()) | 0x001F) + 1 | ||
|  |         print("0x%02x " % (self.__index) + "".join(map(lambda n: "%2X" % (n), range(0x20)))) | ||
|  |         for addr in range(low, high, 0x20): | ||
|  |             print("%04x " % (addr) + "".join(map(lambda n: ("%02X" % (self.tiles[addr + n])) if addr + n in self.tiles else "  ", range(0x20)))) | ||
|  | 
 | ||
|  |     def store(self, rom): | ||
|  |         # NOTE: This is not a very good encoder, but the background back has so much free space that we really don't care. | ||
|  |         # Improvements can be done to find long sequences of bytes and store those as repeated. | ||
|  |         result = bytearray() | ||
|  |         low = min(self.tiles.keys()) | ||
|  |         high = max(self.tiles.keys()) + 1 | ||
|  |         while low < high: | ||
|  |             if low not in self.tiles: | ||
|  |                 low += 1 | ||
|  |                 continue | ||
|  |             different_count = 1 | ||
|  |             while low + different_count in self.tiles and different_count < 0x40: | ||
|  |                 different_count += 1 | ||
|  |             same_count = 1 | ||
|  |             while low + same_count in self.tiles and self.tiles[low] == self.tiles[low + same_count] and same_count < 0x40: | ||
|  |                 same_count += 1 | ||
|  |             if same_count > different_count - 4 and same_count > 2: | ||
|  |                 result.append(low >> 8) | ||
|  |                 result.append(low & 0xFF) | ||
|  |                 result.append((same_count - 1) | 0x40) | ||
|  |                 result.append(self.tiles[low]) | ||
|  |                 low += same_count | ||
|  |             else: | ||
|  |                 result.append(low >> 8) | ||
|  |                 result.append(low & 0xFF) | ||
|  |                 result.append(different_count - 1) | ||
|  |                 for n in range(different_count): | ||
|  |                     result.append(self.tiles[low + n]) | ||
|  |                 low += different_count | ||
|  |         result.append(0x00) | ||
|  |         if self.__is_attributes: | ||
|  |             rom.background_attributes[self.__index] = result | ||
|  |         else: | ||
|  |             rom.background_tiles[self.__index] = result |