defmodule PerplexityMacro.ROM do @moduledoc "Binds zero-page mailbox registers to Elixir handlers." use GenServer defstruct [:emulator_pid, :bridge_mode, :memory_map] def start_link(opts), do: GenServer.start_link(__MODULE__, opts, name: __MODULE__) @impl true def init(opts) do state = %__MODULE__{emulator_pid: Keyword.get(opts, :emulator_pid), bridge_mode: :file_mapped, memory_map: :ets.new(:rom_mailbox, [:public, :set])} {:ok, state} end @impl true def handle_call({:read_mailbox}, _from, state) do status = read_byte(state, 0x03) reply = case status do 0x01 -> {:request, decode_capability(read_byte(state, 0x02)), read_query(state), read_nonce(state)} _ -> :idle end {:reply, reply, state} end @impl true def handle_cast({:write_result, tlv_payload, crc16}, state) do write_bytes(state, 0x46, tlv_payload) write_word(state, 0xC6, crc16) write_byte(state, 0x03, 0x02) {:noreply, state} end defp read_byte(_state, addr), do: :ets.lookup_element(:rom_mailbox, addr, 2, 0) defp write_byte(state, addr, val), do: :ets.insert(state.memory_map, {addr, val}) defp write_bytes(state, start_addr, bytes) do bytes |> :binary.bin_to_list() |> Enum.with_index(start_addr) |> Enum.each(fn {b,a} -> write_byte(state, a, b) end) end defp write_word(state, addr, val) do <> = <> write_byte(state, addr, lo); write_byte(state, addr+1, hi) end defp decode_capability(1), do: :search defp decode_capability(2), do: :fetch defp decode_capability(3), do: :browse defp decode_capability(4), do: :code defp decode_capability(5), do: :model defp decode_capability(6), do: :wikipedia defp decode_capability(7), do: :mathematica defp decode_capability(8), do: :dictionary defp decode_capability(_), do: :unknown defp read_query(_state), do: "synthetic_research_query" defp read_nonce(_state), do: 0xDEAD end