diff --git a/programs/basic_sprite.chalk b/programs/basic_sprite.chalk index f91bf9c..4a317e4 100644 --- a/programs/basic_sprite.chalk +++ b/programs/basic_sprite.chalk @@ -1,9 +1,12 @@ sprite dum [ -` xx ` -` xx ` -` xx ` +` x x ` +` x x ` +` x x ` +` ` +`x x` +` xxxxxx ` ] fun main(): u0 { - + draw_sprite(dum, 0, 0); } diff --git a/src/chalk/compiler.cr b/src/chalk/compiler.cr index a3d3044..6c291ff 100644 --- a/src/chalk/compiler.cr +++ b/src/chalk/compiler.cr @@ -67,6 +67,7 @@ module Chalk table.set_function "get_delay", FunctionEntry.new Builtin::InlineGetDelayFunction.new table.set_function "set_sound", FunctionEntry.new Builtin::InlineSetSoundFunction.new table.set_function "draw_number", FunctionEntry.new Builtin::InlineDrawNumberFunction.new + table.set_function "draw_sprite", FunctionEntry.new Builtin::InlineDrawSpriteFunction.new return table end @@ -180,15 +181,6 @@ module Chalk names = collect_calls(table) names.delete "main" - sprite_bytes = [] of UInt8 - offset = 0 - table.sprites.each do |k, v| - data = v.sprite.encode - v.offset = offset - offset += data.size - sprite_bytes.concat data - end - main_entry = table.get_function?("main").not_nil! all_instructions.concat create_code(main_entry.function.as(Trees::TreeFunction), table, Ir::JumpRelativeInstruction.new 0) @@ -203,9 +195,19 @@ module Chalk all_instructions << Ir::ReturnInstruction.new end + sprite_bytes = [] of UInt8 + offset = 0 + table.sprites.each do |k, v| + data = v.sprite.encode + v.addr = offset + all_instructions.size * 2 + offset += data.size + sprite_bytes.concat data + end + binary = [] of UInt8 file = File.open(@config.output, "w") generate_binary(table, all_instructions, binary) + binary.concat sprite_bytes binary.each do |byte| file.write_byte byte end diff --git a/src/chalk/inline.cr b/src/chalk/inline.cr index ce028cc..00ca617 100644 --- a/src/chalk/inline.cr +++ b/src/chalk/inline.cr @@ -81,5 +81,21 @@ module Chalk return Compiler::FunctionType.new([Compiler::Type::U8] * 3, Compiler::Type::U0) end end + + class InlineDrawSpriteFunction < InlineFunction + def generate!(emitter, params, table, target, free) + raise "First parameter should be a sprite name." if !params[0].is_a?(Trees::TreeId) + sprite_name = params[0].as(Trees::TreeId).id + sprite = table.get_sprite?(sprite_name).not_nil!.sprite + emitter.generate! params[1], table, free, free + 1 + emitter.generate! params[2], table, free + 1, free + 2 + emitter.instructions << Ir::SetISpriteInstruction.new params[0].as(Trees::TreeId).id + emitter.instructions << Ir::DrawInstruction.new free, free + 1, sprite.height.to_i32 + end + + def type + return Compiler::FunctionType.new([Compiler::Type::U8] * 3, Compiler::Type::U0) + end + end end end diff --git a/src/chalk/ir.cr b/src/chalk/ir.cr index 6e6a69c..9dbd941 100644 --- a/src/chalk/ir.cr +++ b/src/chalk/ir.cr @@ -297,6 +297,21 @@ module Chalk end end + class SetISpriteInstruction < Instruction + getter name + + def initialize(@name : String) + end + + def to_s(io) + io << "setispr " << @name + end + + def to_bin(table, stack, index) + return 0xa000 | (table.get_sprite?(@name).not_nil!.addr + 0x200) + end + end + # Instruction to add a register to I. class AddIRegInstruction < Instruction def initialize(@reg : Int32) diff --git a/src/chalk/sprite.cr b/src/chalk/sprite.cr index d3a7fe0..f0784bc 100644 --- a/src/chalk/sprite.cr +++ b/src/chalk/sprite.cr @@ -5,6 +5,10 @@ module Chalk @pixels = Hash(UInt8, UInt8).new(default_value: 0_u8) end + def height + return (@pixels.keys.max || 0_u8) + 1 + end + def initialize(string, blank_char = ' ') @pixels = Hash(UInt8, UInt8).new(default_value: 0_u8) string.split("\n").each_with_index do |s, i| diff --git a/src/chalk/table.cr b/src/chalk/table.cr index 3549fe6..e2c0729 100644 --- a/src/chalk/table.cr +++ b/src/chalk/table.cr @@ -36,9 +36,9 @@ module Chalk class SpriteEntry property sprite : Sprite - property offset : Int32 + property addr : Int32 - def initialize(@sprite, @offset = -1) + def initialize(@sprite, @addr = -1) end end