// Copyright 2024 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
struct Color(UInt)
///|
pub fn rgb(color : UInt) -> Color {
color
}
///|
/// Sets the color of the palette at the given index.
///
/// @param index the index of the palette to set, from 1 to 4 (inclusive)
/// @param color the color to set
pub fn set_palette(index : UInt, color : Color) -> Unit {
if index == 0 || index > 4 {
trace("Palette index out of range")
panic()
}
store_i32(
address_PALETTE + (index.reinterpret_as_int() - 1) * 4,
color.0.reinterpret_as_int(),
)
}
///|
/// Gets the color of the palette at the given index.
///
/// @param index the index of the palette to get, from 1 to 4 (inclusive)
/// @return the color at the given index
pub fn get_palette(index : UInt) -> Color {
if index == 0 || index > 4 {
trace("Palette index out of range")
panic()
}
load_s32(address_PALETTE + (index.reinterpret_as_int() - 1) * 4).reinterpret_as_uint()
}
///|
/// Sets the draw color at the given index.
///
/// @param index the index of the draw color to set, from 1 to 4 (inclusive)
/// @param palette the index of the palette to set the draw color to, from 1 to 4 (inclusive), or 0 for transparent
pub fn set_draw_colors(palette : UInt, index? : UInt = 1) -> Unit {
if index == 0 || index > 4 || palette > 4 {
trace("Draw color index or palette index out of range")
panic()
}
let current_color = load_u16(address_DRAW_COLORS)
let updated_color = bitset(current_color, palette, (index - 1U) * 4U, 4U)
store_i16(address_DRAW_COLORS, updated_color.reinterpret_as_int())
}
///|
/// Gets the draw color at the given index.
///
/// @param index the index of the draw color to get, from 1 to 4 (inclusive)
/// @return the index of the palette that the draw color is set to
pub fn get_draw_colors(index : UInt) -> UInt {
if index == 0 || index > 4 {
trace("Draw color index out of range")
panic()
}
bitget(load_u16(address_DRAW_COLORS), (index - 1U) * 4U, 4U)
}
///|
pub struct GamePad {
button_1 : Bool
button_2 : Bool
button_left : Bool
button_right : Bool
button_up : Bool
button_down : Bool
} derive(Eq, Default)
///|
/// Gets the state of the gamepads.
///
/// @param index the index of the gamepad to get, from 1 to 4 (inclusive)
/// @return the state of the gamepads
pub fn get_gamepad(index? : UInt = 1) -> GamePad {
if index.reinterpret_as_int() > 4 {
trace("Gamepad index out of range")
panic()
}
let state = load_byte(address_GAMEPADS + index.reinterpret_as_int() - 1).to_int()
GamePad::{
button_1: (state & 1) == 1,
button_2: (state & 2) == 2,
button_left: (state & 16) == 16,
button_right: (state & 32) == 32,
button_up: (state & 64) == 64,
button_down: (state & 128) == 128,
}
}
///|
pub struct Mouse {
x : Int
y : Int
left : Bool
middle : Bool
right : Bool
} derive(Eq, Default)
///|
/// Gets the state of the mouse.
///
/// @return the state of the mouse
pub fn get_mouse() -> Mouse {
let buttons = load_byte(address_MOUSE_BUTTONS).to_int().reinterpret_as_uint()
Mouse::{
x: load_s16(address_MOUSE_X),
y: load_s16(address_MOUSE_Y),
left: (buttons & 1U) == 1U,
right: (buttons & 2U) == 2U,
middle: (buttons & 4U) == 4U,
}
}
///|
/// Manipulate the framebuffer directly.
///
/// @param index the index of the pixel to set, from 0 to 160 * 160 (exclusive)
/// @param palette the index of the palette to set the pixel to, from 1 to 4 (inclusive)
pub fn set_frame_buffer(index : UInt, palette : UInt) -> Unit {
if index >= 160U * 160U || palette == 0 || palette > 4 {
trace("Frame buffer index or palette index out of range")
panic()
}
let byte = load_byte(address_FRAMEBUFFER + index.reinterpret_as_int() / 4)
let new_byte = bitset(
byte.to_int().reinterpret_as_uint(),
palette - 1,
index % 4U * 2U,
2U,
)
store_byte(
address_FRAMEBUFFER + index.reinterpret_as_int() / 4,
new_byte.reinterpret_as_int().to_byte(),
)
}
///|
/// Get the palette index of the pixel at the specified index.
///
/// # Parameters
///
/// - `index` : The index of the frame buffer to retrieve. Must be a `UInt` and
/// should be within the valid range of the frame buffer (0 to 160 * 160 - 1).
///
/// # Returns
///
/// - the index of the palette.
pub fn get_frame_buffer(index : UInt) -> UInt {
if index >= 160U * 160U {
trace("Frame buffer index out of range")
panic()
}
let byte = load_byte(address_FRAMEBUFFER + index.reinterpret_as_int() / 4)
bitget(byte.to_int().reinterpret_as_uint(), index % 4U * 2U, 2U) + 1U
}
///|
/// Status of netplay
///
/// The index is from 1 to 4 (inclusive)
pub struct Netplay {
index : UInt
active : Bool
}
///|
/// Gets the state of the netplay.
///
/// @return the state of the netplay
pub fn get_netplay() -> Netplay {
let flags = load_byte(address_NETPLAY).to_int().reinterpret_as_uint()
Netplay::{ index: (flags & 0b11U) + 1, active: (flags & 4U) == 4U }
}
///|
pub fn set_system_preserve_framebuffer(b : Bool) -> Unit {
let flags = load_byte(address_SYSTEM_FLAGS)
let new_flags = bitset(
flags.to_int().reinterpret_as_uint(),
if b {
1
} else {
0
},
0U,
1U,
)
store_byte(address_SYSTEM_FLAGS, new_flags.reinterpret_as_int().to_byte())
}
///|
pub fn get_system_preserve_framebuffer() -> Bool {
let flags = load_byte(address_SYSTEM_FLAGS)
(flags.to_int() & 1) == 1
}
///|
pub fn set_system_hide_gamepad_overlay(b : Bool) -> Unit {
let flags = load_byte(address_SYSTEM_FLAGS)
let new_flags = bitset(
flags.to_int().reinterpret_as_uint(),
if b {
1
} else {
0
},
1U,
1U,
)
store_byte(address_SYSTEM_FLAGS, new_flags.reinterpret_as_int().to_byte())
}
///|
pub fn get_system_hide_gamepad_overlay() -> Bool {
let flags = load_byte(address_SYSTEM_FLAGS)
(flags.to_int() & 2) == 2
}