mirror of
https://gitlab.com/MaddoScientisto/cirnogodot.git
synced 2026-06-01 10:15:45 +00:00
Build script
This commit is contained in:
parent
30d0365ae1
commit
1ed08d6a58
12 changed files with 505 additions and 5 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
||||||
# Godot 4+ specific ignores
|
# Godot 4+ specific ignores
|
||||||
.godot/
|
.godot/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
build/**
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Content Include="Export.ps1" />
|
||||||
<Content Include="Scripts\Resources\Events\tsconfig.json" />
|
<Content Include="Scripts\Resources\Events\tsconfig.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
274
CreateIcon.gd
Normal file
274
CreateIcon.gd
Normal file
|
|
@ -0,0 +1,274 @@
|
||||||
|
class_name CreateIcon
|
||||||
|
extends SceneTree
|
||||||
|
|
||||||
|
var error_callable: Callable
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
var arguments = OS.get_cmdline_args()
|
||||||
|
if arguments.size() != 4 and arguments.size() != 9:
|
||||||
|
print(
|
||||||
|
"Usage:\n godot -s CreateIcon.gd name <file>...\n",
|
||||||
|
"\n",
|
||||||
|
"Creates uncompressed windows ico file.\n",
|
||||||
|
"Add --headless to hide Godot console.\n",
|
||||||
|
"\n",
|
||||||
|
"Arguments:\n",
|
||||||
|
" godot path to Godot 4 beta2+ executable\n",
|
||||||
|
" name path to created icon\n",
|
||||||
|
" <file> provide one or six files. If one provided it will be scaled for all\n",
|
||||||
|
" icon resolutions. Multiple files should be 16x16, 32x32, 48x48, 64x64,\n",
|
||||||
|
" 128x128\n and 256x256 pixels big."
|
||||||
|
)
|
||||||
|
quit()
|
||||||
|
return
|
||||||
|
var images := []
|
||||||
|
if arguments.size() == 9:
|
||||||
|
var names := [arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8]]
|
||||||
|
var check_names := {}
|
||||||
|
for name in names:
|
||||||
|
if check_names.has(name):
|
||||||
|
printerr("File ", name, " was added more than once")
|
||||||
|
return
|
||||||
|
check_names[name] = true
|
||||||
|
images = load_images(names)
|
||||||
|
else:
|
||||||
|
images = prepare_images(arguments[3])
|
||||||
|
if not images.is_empty():
|
||||||
|
save_icon(arguments[2], images)
|
||||||
|
quit()
|
||||||
|
|
||||||
|
|
||||||
|
func load_images(paths: PackedStringArray) -> Array:
|
||||||
|
var images := []
|
||||||
|
for path in paths:
|
||||||
|
var image := Image.new()
|
||||||
|
var error = image.load(path)
|
||||||
|
if error:
|
||||||
|
print_error(str("Could not load image: ", path))
|
||||||
|
return []
|
||||||
|
image.convert(Image.FORMAT_RGBA8)
|
||||||
|
images.append(image)
|
||||||
|
images.sort_custom(sort_images_by_size)
|
||||||
|
var index := 0
|
||||||
|
for size in [16, 32, 48, 64, 128, 256]:
|
||||||
|
var image: Image = images[index]
|
||||||
|
if image.get_width() != size:
|
||||||
|
print_error(str("Image has incorrect width: ", image.get_width(), " expected: ", size))
|
||||||
|
return []
|
||||||
|
if image.get_height() != size:
|
||||||
|
print_error(str("Image has incorrect height: ", image.get_height(), " expected: ", size))
|
||||||
|
return []
|
||||||
|
index += 1
|
||||||
|
return images
|
||||||
|
|
||||||
|
|
||||||
|
func prepare_images(path: String) -> Array:
|
||||||
|
var images := []
|
||||||
|
for size in [16, 32, 48, 64, 128, 256]:
|
||||||
|
var image := Image.new()
|
||||||
|
var error = image.load(path)
|
||||||
|
if error:
|
||||||
|
print_error(str("Could not load image: ", path))
|
||||||
|
return []
|
||||||
|
image.convert(Image.FORMAT_RGBA8)
|
||||||
|
image.resize(size, size)
|
||||||
|
images.append(image)
|
||||||
|
return images
|
||||||
|
|
||||||
|
|
||||||
|
func save_icon(destination_path: String, images: Array) -> void:
|
||||||
|
var file = FileAccess.open(destination_path, FileAccess.WRITE)
|
||||||
|
if not file:
|
||||||
|
print_error(str("Could not open file for writing!\n", FileAccess.get_open_error()))
|
||||||
|
return
|
||||||
|
var icon_creator := IconCreator.new()
|
||||||
|
file.store_buffer(icon_creator.generate_icon(images))
|
||||||
|
|
||||||
|
|
||||||
|
func print_error(error_message: String) -> void:
|
||||||
|
printerr(error_message)
|
||||||
|
if error_callable:
|
||||||
|
error_callable.call(error_message)
|
||||||
|
|
||||||
|
|
||||||
|
static func sort_images_by_size(a: Image, b: Image) -> bool:
|
||||||
|
return a.get_width() < b.get_width()
|
||||||
|
|
||||||
|
|
||||||
|
class IconCreator:
|
||||||
|
const ADLER_MOD := 65521
|
||||||
|
const ZLIB_BLOCK_SIZE := 16384
|
||||||
|
const CRC_TABLE_SIZE := 256
|
||||||
|
const ICON_ENTRY_SIZE := 16
|
||||||
|
var PNG_SIGNATURE := PackedByteArray([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0a])
|
||||||
|
var IHDR_SIGNATURE := PackedByteArray([0x49, 0x48, 0x44, 0x52])
|
||||||
|
var IDAT_SIGNATURE := PackedByteArray([0x49, 0x44, 0x41, 0x54])
|
||||||
|
var IEND_SIGNATURE := PackedByteArray([0x49, 0x45, 0x4e, 0x44])
|
||||||
|
|
||||||
|
var crc_table: Array
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
crc_table = generate_crc_table()
|
||||||
|
|
||||||
|
|
||||||
|
func generate_icon(images: Array) -> PackedByteArray:
|
||||||
|
var result := PackedByteArray()
|
||||||
|
result.append_array(generate_icon_header(images.size()))
|
||||||
|
var offset := result.size() + images.size() * ICON_ENTRY_SIZE
|
||||||
|
var pngs := []
|
||||||
|
for image in images:
|
||||||
|
assert(image.get_format() == Image.FORMAT_RGBA8)
|
||||||
|
var png := generate_png(image)
|
||||||
|
pngs.append(png)
|
||||||
|
var icon_entry := generate_icon_entry(image, png.size(), offset)
|
||||||
|
result.append_array(icon_entry)
|
||||||
|
offset += png.size()
|
||||||
|
for png in pngs:
|
||||||
|
result.append_array(png)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func generate_icon_header(size: int) -> PackedByteArray:
|
||||||
|
var result := PackedByteArray()
|
||||||
|
result.append_array(lsb_first(0x0, 2)) # reserved
|
||||||
|
result.append_array(lsb_first(0x1, 2)) # icon type
|
||||||
|
result.append_array(lsb_first(size, 2)) # image count
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func generate_icon_entry(image: Image, size: int, offset: int) -> PackedByteArray:
|
||||||
|
var result := PackedByteArray()
|
||||||
|
result.append(image.get_width()) # width
|
||||||
|
result.append(image.get_height()) # height
|
||||||
|
result.append(0x0) # size of color palette
|
||||||
|
result.append(0x0) # reserved
|
||||||
|
result.append_array(lsb_first(0, 2)) # no color planes
|
||||||
|
result.append_array(lsb_first(32, 2)) # bits per pixel
|
||||||
|
result.append_array(lsb_first(size)) # size of embedded png
|
||||||
|
result.append_array(lsb_first(offset))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func generate_png(image: Image) -> PackedByteArray:
|
||||||
|
var result := PackedByteArray()
|
||||||
|
var header_chunk := generate_header_chunk(image.get_width(), image.get_height())
|
||||||
|
var data_chunk := generate_data_chunk(image)
|
||||||
|
var end_chunk := generate_end_chunk()
|
||||||
|
result.append_array(PNG_SIGNATURE)
|
||||||
|
result.append_array(generate_chunk(header_chunk))
|
||||||
|
result.append_array(generate_chunk(data_chunk))
|
||||||
|
result.append_array(generate_chunk(end_chunk))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func generate_chunk(chunk: PackedByteArray) -> PackedByteArray:
|
||||||
|
var result := PackedByteArray()
|
||||||
|
result.append_array(msb_first(chunk.size() - 4))
|
||||||
|
result.append_array(chunk)
|
||||||
|
result.append_array(msb_first(crc(chunk)))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func generate_header_chunk(width: int, height: int) -> PackedByteArray:
|
||||||
|
var result = PackedByteArray()
|
||||||
|
result.append_array(IHDR_SIGNATURE)
|
||||||
|
result.append_array(msb_first(width))
|
||||||
|
result.append_array(msb_first(height))
|
||||||
|
result.append(0x8) # bit depth
|
||||||
|
result.append(0x6) # color type 32bit RGBA
|
||||||
|
result.append(0x0) # compression method
|
||||||
|
result.append(0x0) # filter method
|
||||||
|
result.append(0x0) # interlace method
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func generate_data_chunk(image: Image) -> PackedByteArray:
|
||||||
|
@warning_ignore("shadowed_variable")
|
||||||
|
var filtered_pixels := filtered_pixels(image.get_width(), image.get_height(), image.get_data())
|
||||||
|
@warning_ignore("integer_division")
|
||||||
|
var zlib_block_count := filtered_pixels.size() / ZLIB_BLOCK_SIZE + (1 if filtered_pixels.size() % ZLIB_BLOCK_SIZE else 0)
|
||||||
|
var result := PackedByteArray()
|
||||||
|
result.append_array(IDAT_SIGNATURE)
|
||||||
|
result.append(0x78) # CMF
|
||||||
|
result.append(0x1) # FLG
|
||||||
|
for i in range(zlib_block_count):
|
||||||
|
var last_block := i == zlib_block_count - 1
|
||||||
|
result.append(0x1 if last_block else 0x0)
|
||||||
|
@warning_ignore("shadowed_variable")
|
||||||
|
var block_size := filtered_pixels.size() % ZLIB_BLOCK_SIZE if last_block else ZLIB_BLOCK_SIZE
|
||||||
|
result.append_array(block_size(block_size))
|
||||||
|
for b in range(block_size):
|
||||||
|
result.append(filtered_pixels[i * ZLIB_BLOCK_SIZE + b])
|
||||||
|
result.append_array(msb_first(adler(filtered_pixels)))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func generate_end_chunk() -> PackedByteArray:
|
||||||
|
return IEND_SIGNATURE
|
||||||
|
|
||||||
|
|
||||||
|
func filtered_pixels(width: int, height: int, pixels: PackedByteArray) -> PackedByteArray:
|
||||||
|
var result = PackedByteArray()
|
||||||
|
for row in range(height):
|
||||||
|
result.append(0x0)
|
||||||
|
for column in range(width * 4):
|
||||||
|
result.append(pixels[row * width * 4 + column])
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func generate_crc_table() -> Array:
|
||||||
|
var result = []
|
||||||
|
var c: int
|
||||||
|
for n in range(CRC_TABLE_SIZE):
|
||||||
|
c = n
|
||||||
|
for _i in range(8):
|
||||||
|
if (c & 1) != 0:
|
||||||
|
c = 0xedb88320 ^ (c >> 1)
|
||||||
|
else:
|
||||||
|
c = c >> 1
|
||||||
|
result.append(c)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func crc(bytes: PackedByteArray) -> int:
|
||||||
|
var c := 0xffffffff
|
||||||
|
for i in range(bytes.size()):
|
||||||
|
c = crc_table[(c ^ bytes[i]) & 0xff] ^ (c >> 8)
|
||||||
|
return c ^ 0xffffffff
|
||||||
|
|
||||||
|
|
||||||
|
func adler(bytes: PackedByteArray) -> int:
|
||||||
|
var a := 1
|
||||||
|
var b := 0
|
||||||
|
for byte in bytes:
|
||||||
|
a = (a + byte) % ADLER_MOD
|
||||||
|
b = (a + b) % ADLER_MOD
|
||||||
|
return b << 16 | a
|
||||||
|
|
||||||
|
|
||||||
|
func msb_first(i: int) -> PackedByteArray:
|
||||||
|
var result := PackedByteArray()
|
||||||
|
result.append((i >> 24) & 0xff)
|
||||||
|
result.append((i >> 16) & 0xff)
|
||||||
|
result.append((i >> 8) & 0xff)
|
||||||
|
result.append(i & 0xff)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func lsb_first(i: int, size = 4) -> PackedByteArray:
|
||||||
|
var result := PackedByteArray()
|
||||||
|
for _s in range(size):
|
||||||
|
result.append(i & 0xff)
|
||||||
|
i = i >> 8
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func block_size(i: int) -> PackedByteArray:
|
||||||
|
var result := PackedByteArray()
|
||||||
|
result.append(i & 0xff)
|
||||||
|
result.append((i >> 8) & 0xff)
|
||||||
|
result.append((i & 0xff) ^ 0xff)
|
||||||
|
result.append(((i >> 8) & 0xff) ^ 0xff)
|
||||||
|
return result
|
||||||
1
CreateIcon.gd.uid
Normal file
1
CreateIcon.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://bb0n1dj2k22gl
|
||||||
1
Export.ps1
Normal file
1
Export.ps1
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
F:\Apps\Godot_v4.4\Godot_v4.4-rc1_mono_win64.exe --headless --export-release "Windows Desktop" .\build\Cirno_No_Reason.exe
|
||||||
212
ReplaceIcon.gd
Normal file
212
ReplaceIcon.gd
Normal file
|
|
@ -0,0 +1,212 @@
|
||||||
|
class_name ReplaceIcon
|
||||||
|
extends SceneTree
|
||||||
|
|
||||||
|
const ICON_SIZE := 359559
|
||||||
|
|
||||||
|
var error_callable: Callable
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
var arguments = OS.get_cmdline_args()
|
||||||
|
if arguments.size() != 4:
|
||||||
|
print(
|
||||||
|
"Usage:\n",
|
||||||
|
" godot -s ReplaceIcon.gd icon name\n",
|
||||||
|
"\n",
|
||||||
|
"Replaces ico file in windows PE32+ executable.\n",
|
||||||
|
"Add --headless to hide Godot console.\n",
|
||||||
|
"\n",
|
||||||
|
"Arguments:\n",
|
||||||
|
" godot path to Godot 4 beta2+ executable\n",
|
||||||
|
" icon path to new icon\n",
|
||||||
|
" name path to modified PE32+ executable\n"
|
||||||
|
)
|
||||||
|
quit()
|
||||||
|
return
|
||||||
|
replace_icon(arguments[3], arguments[2])
|
||||||
|
quit()
|
||||||
|
|
||||||
|
|
||||||
|
func replace_icon(executable_path: String, icon_path: String) -> void:
|
||||||
|
var icon_replacer := IconReplacer.new()
|
||||||
|
|
||||||
|
var images := get_images(icon_path)
|
||||||
|
|
||||||
|
var executable_file := FileAccess.open(executable_path, FileAccess.READ_WRITE)
|
||||||
|
if not executable_file:
|
||||||
|
print_error("Could not open executable file!")
|
||||||
|
return
|
||||||
|
var headers := executable_file.get_buffer(2048)
|
||||||
|
var resources_section_entry := icon_replacer.find_resources_section_entry(headers)
|
||||||
|
if not resources_section_entry:
|
||||||
|
return
|
||||||
|
if resources_section_entry.size_of_raw_data < 359559:
|
||||||
|
print_error("Could not find icons in executable. Wrong template?")
|
||||||
|
return
|
||||||
|
|
||||||
|
executable_file.seek(resources_section_entry.pointer_to_raw_data)
|
||||||
|
var resources := executable_file.get_buffer(resources_section_entry.size_of_raw_data)
|
||||||
|
|
||||||
|
resources = icon_replacer.replace_icons(resources, resources_section_entry.virtual_address, images)
|
||||||
|
if not resources.is_empty():
|
||||||
|
executable_file.seek(resources_section_entry.pointer_to_raw_data)
|
||||||
|
executable_file.store_buffer(resources)
|
||||||
|
|
||||||
|
|
||||||
|
func get_images(icon_path: String) -> Dictionary:
|
||||||
|
var file := FileAccess.open(icon_path, FileAccess.READ)
|
||||||
|
if not file:
|
||||||
|
print_error(str("Could not open icon file!\n", FileAccess.get_open_error()))
|
||||||
|
return {}
|
||||||
|
return Icon.new(file.get_buffer(ICON_SIZE)).images
|
||||||
|
|
||||||
|
|
||||||
|
func print_error(error_message: String) -> void:
|
||||||
|
printerr(error_message)
|
||||||
|
if error_callable:
|
||||||
|
error_callable.call(error_message)
|
||||||
|
|
||||||
|
|
||||||
|
class IconReplacer:
|
||||||
|
enum ImageType {PE32 = 0x10b, PE32_PLUS = 0x20b}
|
||||||
|
|
||||||
|
const PE_HEADER_ADDRESS_OFFSET := 0x3c
|
||||||
|
const NUMBER_OF_SECTIONS_OFFSET := 0x6
|
||||||
|
const SIZE_OF_OPTIONAL_HEADER_OFFSET := 0x14
|
||||||
|
const MAGIC_OFFSET := 0x18
|
||||||
|
const COFF_HEADER_SIZE := 24
|
||||||
|
const SECTION_SIZE := 40
|
||||||
|
const SIZE_OF_RAW_DATA_OFFSET := 0x10
|
||||||
|
const POINTER_TO_RAW_DATA_OFFSET := 0x14
|
||||||
|
const DATA_ENTRY_SIZE := 16
|
||||||
|
|
||||||
|
var error_callable: Callable
|
||||||
|
|
||||||
|
|
||||||
|
func replace_icons(resources: PackedByteArray, rva_offset: int, images: Dictionary) -> PackedByteArray:
|
||||||
|
var data_entries := find_data_entries(resources)
|
||||||
|
for data_size in images.keys():
|
||||||
|
var icon_offset := find_icon_offset(data_entries, data_size, rva_offset)
|
||||||
|
if resources.slice(icon_offset + 1, icon_offset + 4).get_string_from_ascii() != "PNG":
|
||||||
|
print_error("Wrong icon type, PNG signature missing")
|
||||||
|
return PackedByteArray()
|
||||||
|
resources = IconReplacer.replace(resources, images[data_size], icon_offset)
|
||||||
|
return resources
|
||||||
|
|
||||||
|
|
||||||
|
func find_icon_offset(data_entries: Array, data_size: int, rva_offset: int) -> int:
|
||||||
|
for data_entry in data_entries:
|
||||||
|
if data_entry.size == data_size:
|
||||||
|
return data_entry.rva - rva_offset
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
func find_resources_section_entry(headers: PackedByteArray) -> SectionEntry:
|
||||||
|
var header_offset := IconReplacer.lsb_first(headers, PE_HEADER_ADDRESS_OFFSET, 2)
|
||||||
|
var image_type := IconReplacer.lsb_first(headers, header_offset + MAGIC_OFFSET, 2)
|
||||||
|
if not image_type == ImageType.PE32_PLUS:
|
||||||
|
print_error("Only PE32+ executables are handled.")
|
||||||
|
return null
|
||||||
|
var sections_size := IconReplacer.lsb_first(headers, header_offset + NUMBER_OF_SECTIONS_OFFSET, 2)
|
||||||
|
var size_of_optional_header := IconReplacer.lsb_first(headers, header_offset + SIZE_OF_OPTIONAL_HEADER_OFFSET, 2)
|
||||||
|
var sections_offset := header_offset + COFF_HEADER_SIZE + size_of_optional_header
|
||||||
|
for _i in range(sections_size):
|
||||||
|
var section_name = headers.slice(sections_offset, sections_offset + 8).get_string_from_ascii()
|
||||||
|
if section_name == ".rsrc":
|
||||||
|
return SectionEntry.new(headers.slice(sections_offset, sections_offset + SECTION_SIZE))
|
||||||
|
sections_offset += SECTION_SIZE
|
||||||
|
return null
|
||||||
|
|
||||||
|
|
||||||
|
func find_data_entries(resources: PackedByteArray) -> Array:
|
||||||
|
var result := []
|
||||||
|
parse_table(resources, 0, result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func parse_table(resources: PackedByteArray, offset: int, data_entries: Array) -> void:
|
||||||
|
var entry_count := IconReplacer.lsb_first(resources, offset + 14, 2)
|
||||||
|
offset += 16
|
||||||
|
for _i in range(entry_count):
|
||||||
|
parse_entry(resources, offset, data_entries)
|
||||||
|
offset += 8
|
||||||
|
|
||||||
|
|
||||||
|
func parse_entry(resources: PackedByteArray, offset: int, data_entries: Array) -> void:
|
||||||
|
var entry_offset := IconReplacer.lsb_first(resources, offset + 4)
|
||||||
|
if entry_offset & 0x80000000:
|
||||||
|
parse_table(resources, entry_offset & 0x7fffffff, data_entries)
|
||||||
|
else:
|
||||||
|
parse_data_entry(resources, entry_offset, data_entries)
|
||||||
|
|
||||||
|
|
||||||
|
func parse_data_entry(resources: PackedByteArray, offset: int, data_entries: Array) -> void:
|
||||||
|
data_entries.append(DataEntry.new(resources.slice(offset, offset + DATA_ENTRY_SIZE)))
|
||||||
|
|
||||||
|
|
||||||
|
func print_error(error_message: String) -> void:
|
||||||
|
printerr(error_message)
|
||||||
|
if error_callable:
|
||||||
|
error_callable.call(error_message)
|
||||||
|
|
||||||
|
|
||||||
|
static func lsb_first(bytes: PackedByteArray, offset: int, byte_count = 4) -> int:
|
||||||
|
var result := 0
|
||||||
|
for i in range(byte_count, 0, -1):
|
||||||
|
result = (result << 8) + bytes[offset + i - 1]
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
static func replace(bytes: PackedByteArray, replacement: PackedByteArray, index: int) -> PackedByteArray:
|
||||||
|
for i in range(replacement.size()):
|
||||||
|
bytes.set(index + i, replacement[i])
|
||||||
|
return bytes
|
||||||
|
|
||||||
|
|
||||||
|
class SectionEntry:
|
||||||
|
const VIRTUAL_ADDRESS_OFFSET := 0x0c
|
||||||
|
const SIZE_OF_RAW_DATA_OFFSET = 0x10
|
||||||
|
const POINTER_TO_RAW_DATA_OFFSET = 0x14
|
||||||
|
|
||||||
|
var virtual_address: int
|
||||||
|
var pointer_to_raw_data: int
|
||||||
|
var size_of_raw_data: int
|
||||||
|
|
||||||
|
|
||||||
|
func _init(bytes: PackedByteArray) -> void:
|
||||||
|
virtual_address = IconReplacer.lsb_first(bytes, VIRTUAL_ADDRESS_OFFSET)
|
||||||
|
size_of_raw_data = IconReplacer.lsb_first(bytes, SIZE_OF_RAW_DATA_OFFSET)
|
||||||
|
pointer_to_raw_data = IconReplacer.lsb_first(bytes, POINTER_TO_RAW_DATA_OFFSET)
|
||||||
|
|
||||||
|
|
||||||
|
class DataEntry:
|
||||||
|
const RVA_OFFSET := 0
|
||||||
|
const SIZE_OFFSET := 4
|
||||||
|
|
||||||
|
var rva: int
|
||||||
|
var size: int
|
||||||
|
|
||||||
|
|
||||||
|
func _init(bytes: PackedByteArray) -> void:
|
||||||
|
rva = IconReplacer.lsb_first(bytes, RVA_OFFSET)
|
||||||
|
size = IconReplacer.lsb_first(bytes, SIZE_OFFSET)
|
||||||
|
|
||||||
|
|
||||||
|
class Icon:
|
||||||
|
const IMAGE_COUNT_OFFSET := 0x4
|
||||||
|
const IMAGES_OFFSET := 0x6
|
||||||
|
const ICON_ENTRY_SIZE := 16
|
||||||
|
const SIZE_OFFSET := 0x8
|
||||||
|
const DATA_OFFSET := 0xc
|
||||||
|
|
||||||
|
var images := {}
|
||||||
|
|
||||||
|
|
||||||
|
func _init(bytes: PackedByteArray) -> void:
|
||||||
|
var image_count := IconReplacer.lsb_first(bytes, IMAGE_COUNT_OFFSET, 2)
|
||||||
|
var offset := IMAGES_OFFSET
|
||||||
|
for i in image_count:
|
||||||
|
var size := IconReplacer.lsb_first(bytes, offset + SIZE_OFFSET)
|
||||||
|
var data_offset := IconReplacer.lsb_first(bytes, offset + DATA_OFFSET)
|
||||||
|
images[size] = bytes.slice(data_offset, data_offset + size)
|
||||||
|
offset += ICON_ENTRY_SIZE
|
||||||
1
ReplaceIcon.gd.uid
Normal file
1
ReplaceIcon.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cdbkovbleadx1
|
||||||
BIN
Sprites/Actors/Cirno.aseprite
(Stored with Git LFS)
BIN
Sprites/Actors/Cirno.aseprite
(Stored with Git LFS)
Binary file not shown.
BIN
Sprites/Icon.ico
Normal file
BIN
Sprites/Icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
7
addons/scene_palette/save_data/save_data.tres
Normal file
7
addons/scene_palette/save_data/save_data.tres
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
[gd_resource type="Resource" script_class="PalettePluginSaveData" load_steps=2 format=3 uid="uid://c6r8j36esb764"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://d2vskl7301jhr" path="res://addons/scene_palette/resources/rsc_pallete_plugin_save_data.gd" id="1_tuhxn"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_tuhxn")
|
||||||
|
favorites = {}
|
||||||
|
|
@ -10,8 +10,10 @@ export_filter="all_resources"
|
||||||
include_filter=""
|
include_filter=""
|
||||||
exclude_filter=""
|
exclude_filter=""
|
||||||
export_path="../builds/cirnoreason.exe"
|
export_path="../builds/cirnoreason.exe"
|
||||||
|
patches=PackedStringArray()
|
||||||
encryption_include_filters=""
|
encryption_include_filters=""
|
||||||
encryption_exclude_filters=""
|
encryption_exclude_filters=""
|
||||||
|
seed=0
|
||||||
encrypt_pck=false
|
encrypt_pck=false
|
||||||
encrypt_directory=false
|
encrypt_directory=false
|
||||||
script_export_mode=2
|
script_export_mode=2
|
||||||
|
|
@ -32,7 +34,7 @@ codesign/digest_algorithm=1
|
||||||
codesign/description=""
|
codesign/description=""
|
||||||
codesign/custom_options=PackedStringArray()
|
codesign/custom_options=PackedStringArray()
|
||||||
application/modify_resources=true
|
application/modify_resources=true
|
||||||
application/icon=""
|
application/icon="uid://dicat7qqa0a7o"
|
||||||
application/console_wrapper_icon=""
|
application/console_wrapper_icon=""
|
||||||
application/icon_interpolation=4
|
application/icon_interpolation=4
|
||||||
application/file_version=""
|
application/file_version=""
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ project/assembly_name="Cirno"
|
||||||
|
|
||||||
[editor_plugins]
|
[editor_plugins]
|
||||||
|
|
||||||
enabled=PackedStringArray("res://addons/DebugGUI/plugin.cfg", "res://addons/dialogic/plugin.cfg", "res://addons/smoothing/plugin.cfg")
|
enabled=PackedStringArray("res://addons/DebugGUI/plugin.cfg", "res://addons/dialogic/plugin.cfg", "res://addons/scene_palette/plugin.cfg", "res://addons/smoothing/plugin.cfg")
|
||||||
|
|
||||||
[global_group]
|
[global_group]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue