|
#!/usr/bin/env python |
|
# coding: utf-8 |
|
|
|
import struct |
|
import sys |
|
|
|
import PIL |
|
import PIL.Image |
|
|
|
palette_software = [ |
|
0x000000,0x000080,0x0000FF, 0x800000,0x800080,0x8000FF, 0xFF0000,0xFF0080,0xFF00FF, |
|
0x008000,0x008080,0x0080FF, 0x808000,0x808080,0x8080FF, 0xFF8000,0xFF8080,0xFF80FF, |
|
0x00FF00,0x00FF80,0x00FFFF, 0x80FF00,0x80FF80,0x80FFFF, 0xFFFF00,0xFFFF80,0xFFFFFF] |
|
palette_hardware = [20, 4, 21, 28, 24, 29, 12, 5, 13, 22, 6, 23, 30, 0, 31, 14, 7, 15, 18, 2, 19, 26, 25, 27, 10, 3, 11] |
|
standard_palette = b'\x04\x04\n\x13\x0c\x0b\x14\x15\r\x06\x1e\x1f\x07\x12\x19\x04\x17\x04\x04\n\x13\x0c\x0b\x14\x15\r\x06\x1e\x1f\x07\x12\x19\n\x07' |
|
|
|
def read_inks(memory_data): |
|
inks = [] |
|
for ink in memory_data[0x4002:0x4012]: |
|
assert ink in palette_hardware |
|
hw_index = palette_hardware.index(ink) |
|
sw_color = palette_software[hw_index] |
|
inks.append(sw_color) |
|
return inks |
|
|
|
|
|
def convert_image_from_memory(memory_data, mode=None): |
|
image = PIL.Image.new('RGB', (640, 400), color=0xff0080) |
|
if mode is None: |
|
mode = memory_data[0x4000] |
|
inks = read_inks(memory_data) |
|
scale_x = 4 >> mode |
|
pixels_per_byte = 2 << mode |
|
scale_y = 2 |
|
for screen_y in range(200): |
|
screen_row = screen_y % 8 |
|
screen_line = screen_y // 8 |
|
for screen_x in range(640 // scale_x): |
|
screen_col = screen_x // pixels_per_byte |
|
screen_pixel = screen_x % pixels_per_byte |
|
memory_pos = screen_row * 0x800 + screen_line * 80 + screen_col |
|
memory_value = memory_data[memory_pos] |
|
if mode == 2: |
|
current_ink = (memory_value & (128 >> screen_pixel)) >> (7 - screen_pixel) |
|
elif mode == 1: |
|
current_ink0 = (memory_value >> 0 & 15 & (8 >> screen_pixel)) >> (3 - screen_pixel) |
|
current_ink1 = (memory_value >> 4 & 15 & (8 >> screen_pixel)) >> (3 - screen_pixel) |
|
current_ink = (current_ink0 << 1) + current_ink1 |
|
elif mode == 0: |
|
current_ink0 = (memory_value >> 0 & 15 & (2 >> screen_pixel)) >> (1 - screen_pixel) |
|
current_ink1 = (memory_value >> 2 & 15 & (2 >> screen_pixel)) >> (1 - screen_pixel) |
|
current_ink2 = (memory_value >> 4 & 15 & (2 >> screen_pixel)) >> (1 - screen_pixel) |
|
current_ink3 = (memory_value >> 6 & 15 & (2 >> screen_pixel)) >> (1 - screen_pixel) |
|
current_ink = (current_ink0 << 3) + (current_ink1 << 2) + (current_ink2 << 1) + current_ink3 |
|
try: |
|
pixel_value = inks[current_ink] |
|
except: |
|
print(current_ink, file=sys.stderr) |
|
raise |
|
for pixel_y in range(scale_y): |
|
for pixel_x in range(scale_x): |
|
color = struct.unpack('>I', struct.pack('<I', pixel_value))[0] >> 8 |
|
image.putpixel((screen_x * scale_x + pixel_x, screen_y * scale_y + pixel_y), color) |
|
#break |
|
return image |
|
|
|
with open(r"SCREEN.BIN", 'rb') as f: |
|
memory_data = f.read() |
|
|
|
image = convert_image_from_memory(memory_data) |
|
image.save('Screen.png') |