Skip to content

Instantly share code, notes, and snippets.

@gschizas
Last active August 24, 2020 13:36
Show Gist options
  • Save gschizas/a3957810e2a366998f8ceef55198aa5e to your computer and use it in GitHub Desktop.
Save gschizas/a3957810e2a366998f8ceef55198aa5e to your computer and use it in GitHub Desktop.
Map The Prize for Amstrad CPC 6128 using BizHawk and directly converting screen memory to a large image
map_x = 1
map_y = 1
map_lvl = 1
handled_press = {}
function handle_keypress(keys, keyname, fn)
if (keys[keyname] ~= nil and (handled_press[keyname] == 0 or handled_press[keyname] == nil)) then
-- print(tostring(emu.framecount()) .. ": Key pressed")
fn()
handled_press[keyname] = 1
end
if (keys[keyname] == nil and handled_press[keyname] == 1) then
-- print(tostring(emu.framecount()) .. ": Key depressed")
-- print("End screenshot")
-- print(debug.getinfo(fn))
handled_press[keyname] = 0
end
end
function write_bytes(file_handle, buffer_start, buffer_length, buffer_domain)
raw_buffer = memory.readbyterange(buffer_start, buffer_length, buffer_domain)
buffer = string.char(unpack(raw_buffer, 0))
file_handle:write(buffer)
end
function screenshot()
print("Taking screenshot")
filename = string.format("Game Maps/Prize/Level_%02d-%02d-%02d.scr.bin", map_lvl, map_x, map_y)
-- filename = 'demo-mode0.bin'
print(map_lvl, map_x, map_y, filename)
file_handle = io.open(filename, 'wb')
for chunk = 0, 3 do
write_bytes(file_handle, chunk * 4096, 4096, "RAM3")
end
write_bytes(file_handle, 0xB7C3 - 0x8000, 1, "RAM2")
write_bytes(file_handle, 0xB7D4 - 0x8000, 34, "RAM2")
file_handle:close()
print("Done")
status_text = string.format(" ::: Level %02d %02d:%02d", map_lvl, map_x, map_y)
end
status_text = ""
while true do
map_text = string.format("Level %d | %d:%d", map_lvl, map_x, map_y)
if emu.framecount() % 8 == 0 then
status_text = ""
end
if emu.framecount() % 2 == 0 then
local keys = input.get()
handle_keypress(keys, "X1 Y", screenshot)
handle_keypress(keys, "X1 DpadLeft", function() map_x = map_x - 1 end)
handle_keypress(keys, "X1 DpadRight", function() map_x = map_x + 1 end)
handle_keypress(keys, "X1 DpadUp", function() map_y = map_y - 1 end)
handle_keypress(keys, "X1 DpadDown", function() map_y = map_y + 1 end)
handle_keypress(keys, "X1 LeftShoulder", function() map_lvl = map_lvl - 1 end)
handle_keypress(keys, "X1 RightShoulder", function() map_lvl = map_lvl + 1 end)
end
map_text = map_text .. status_text
gui.text(10, 0, map_text)
emu.frameadvance()
end
#!/usr/bin/env python3
# coding: utf-8
import pathlib
import re
import struct
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]
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, 320), 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(160):
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
def get_coords(filename):
coords = re.findall('\d\d-(?P<x>\d\d)-(?P<y>\d\d)', filename)
return int(coords[0][0]), int(coords[0][1])
bin_files = list(pathlib.Path(r'Game Maps/Prize').glob('Level_01-*.bin'))
raw_maps = {get_coords(fn.name): fn.read_bytes() for fn in bin_files}
min_x = min([c[0] for c in list(raw_maps.keys())])
max_x = max([c[0] for c in list(raw_maps.keys())])
min_y = min([c[1] for c in list(raw_maps.keys())])
max_y = max([c[1] for c in list(raw_maps.keys())])
full_map = PIL.Image.new('RGB', (640 * (1 + max_x - min_x), 320 * (1 + max_y - min_y)), color=0x5500AA)
for y in range(min_y, max_y + 1):
for x in range(min_x, max_x + 1):
print(f"{x}:{y}", end=' ')
if (x, y) in raw_maps:
partial_map = convert_image_from_memory(raw_maps[x, y])
# , x * 640 - 1, y * 320 - 1))
full_map.paste(partial_map, box=((x - 1) * 640, (y - 1) * 320))
full_map.save('Level01.png')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment