mirror of
https://github.com/holub/mame
synced 2025-07-06 02:18:09 +03:00
casio/pickytlk.cpp: Add tablet support (#12226)
This commit is contained in:
parent
4726781363
commit
6a08db6399
@ -42,7 +42,7 @@ enum
|
||||
HCD62121_R70, HCD62121_R74, HCD62121_R78, HCD62121_R7C
|
||||
};
|
||||
|
||||
// TODO - Max value stored with "movb reg,f" is 0x3f, is bit 5 set in other instructions?
|
||||
constexpr u8 FLAG_INPUT = 0x20;
|
||||
constexpr u8 FLAG_CL = 0x10;
|
||||
constexpr u8 FLAG_Z = 0x08;
|
||||
constexpr u8 FLAG_C = 0x04;
|
||||
@ -80,6 +80,7 @@ hcd62121_cpu_device::hcd62121_cpu_device(const machine_config &mconfig, const ch
|
||||
, m_opt_cb(*this)
|
||||
, m_ki_cb(*this, 0)
|
||||
, m_in0_cb(*this, 0)
|
||||
, m_input_flag_cb(*this, 0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -639,6 +640,15 @@ inline void hcd62121_cpu_device::set_cl_flag(bool is_cl)
|
||||
}
|
||||
|
||||
|
||||
void hcd62121_cpu_device::set_input_flag(bool is_input_set)
|
||||
{
|
||||
if (is_input_set)
|
||||
m_f |= FLAG_INPUT;
|
||||
else
|
||||
m_f &= ~FLAG_INPUT;
|
||||
}
|
||||
|
||||
|
||||
inline void hcd62121_cpu_device::op_msk(int size)
|
||||
{
|
||||
bool zero_high = true;
|
||||
@ -888,7 +898,13 @@ void hcd62121_cpu_device::execute_run()
|
||||
m_cycles_until_timeout = 0;
|
||||
m_is_infinite_timeout = false;
|
||||
}
|
||||
else if (m_is_infinite_timeout)
|
||||
|
||||
if (m_input_flag_cb() != 0)
|
||||
{
|
||||
set_input_flag(false);
|
||||
}
|
||||
|
||||
if (m_is_infinite_timeout)
|
||||
{
|
||||
m_icount = 0;
|
||||
}
|
||||
@ -2180,6 +2196,8 @@ void hcd62121_cpu_device::execute_run()
|
||||
// Approximately 209.34ms
|
||||
m_cycles_until_timeout = 0x400 * TIMER_STATE_READ_CYCLES;
|
||||
break;
|
||||
case 0x09:
|
||||
case 0x0b:
|
||||
case 0x49:
|
||||
case 0x4b:
|
||||
case 0xc9:
|
||||
|
@ -17,6 +17,7 @@ public:
|
||||
auto opt_cb() { return m_opt_cb.bind(); }
|
||||
auto ki_cb() { return m_ki_cb.bind(); }
|
||||
auto in0_cb() { return m_in0_cb.bind(); }
|
||||
auto input_flag_cb() { return m_input_flag_cb.bind(); }
|
||||
|
||||
protected:
|
||||
enum
|
||||
@ -74,6 +75,7 @@ private:
|
||||
void set_zl_flag(bool is_zl);
|
||||
void set_zh_flag(bool is_zh);
|
||||
void set_cl_flag(bool is_cl);
|
||||
void set_input_flag(bool is_input_set);
|
||||
void op_msk(int size);
|
||||
void op_and(int size);
|
||||
void op_or(int size);
|
||||
@ -126,6 +128,7 @@ private:
|
||||
devcb_write8 m_opt_cb;
|
||||
devcb_read8 m_ki_cb;
|
||||
devcb_read8 m_in0_cb;
|
||||
devcb_read8 m_input_flag_cb;
|
||||
};
|
||||
|
||||
|
||||
|
@ -4,7 +4,11 @@
|
||||
|
||||
Driver for Casio Picky Talk
|
||||
|
||||
Missing inputs, and I/O callbacks copied from CFX9850G need to be reviewed.
|
||||
TODO:
|
||||
|
||||
- Communication port;
|
||||
- Panel active buttons display;
|
||||
- Review PORT/OPT callbacks copied from CFX9850G;
|
||||
|
||||
Some points of interest can be accessed under the debugger:
|
||||
|
||||
@ -28,9 +32,17 @@
|
||||
|
||||
#include "cpu/hcd62121/hcd62121.h"
|
||||
|
||||
#include "crsshair.h"
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
|
||||
#include "pickytlk.lh"
|
||||
|
||||
#define LOG_IO (1U << 1)
|
||||
#define LOG_TABLET (1U << 2)
|
||||
|
||||
//#define VERBOSE (LOG_IO | LOG_TABLET)
|
||||
#include "logmacro.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -39,9 +51,12 @@ class pickytlk_state : public driver_device
|
||||
public:
|
||||
pickytlk_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_video_ram(*this, "video_ram")
|
||||
, m_display_ram(*this, "display_ram")
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_io_buttons(*this, "BUTTONS")
|
||||
, m_io_pen_x(*this, "PEN_X")
|
||||
, m_io_pen_y(*this, "PEN_Y")
|
||||
, m_io_pen_y_rescale(*this, "PEN_Y_RESCALE")
|
||||
, m_ko(0)
|
||||
, m_port(0)
|
||||
, m_opt(0)
|
||||
@ -49,31 +64,134 @@ public:
|
||||
|
||||
void pickytlk(machine_config &config);
|
||||
|
||||
DECLARE_CROSSHAIR_MAPPER_MEMBER(pen_y_mapper);
|
||||
DECLARE_CUSTOM_INPUT_MEMBER(pen_y_rescale_r);
|
||||
ioport_value pen_target_r();
|
||||
|
||||
private:
|
||||
enum pen_target : u8
|
||||
{
|
||||
PEN_TARGET_LCD = 0,
|
||||
PEN_TARGET_PANEL = 1,
|
||||
};
|
||||
|
||||
enum pen_state : u8
|
||||
{
|
||||
PEN_RELEASE = 0,
|
||||
PEN_PRESS = 1,
|
||||
PEN_HOLD = 2,
|
||||
};
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void kol_w(u8 data);
|
||||
void koh_w(u8 data);
|
||||
void port_w(u8 data);
|
||||
void opt_w(u8 data);
|
||||
u8 ki_r();
|
||||
u8 in0_r();
|
||||
u8 input_flag_read();
|
||||
|
||||
TIMER_CALLBACK_MEMBER(io_timer_tick);
|
||||
u8 io_pen_x_read();
|
||||
u8 io_pen_y_read();
|
||||
u8 tablet_read(offs_t offset);
|
||||
void tablet_write(offs_t offset, u8 data);
|
||||
|
||||
void update_crosshair(screen_device &screen);
|
||||
void pickytlk_palette(palette_device &palette) const;
|
||||
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
void pickytlk_mem(address_map &map);
|
||||
|
||||
required_shared_ptr<u8> m_video_ram;
|
||||
static constexpr float rescale(float x, float min_x, float max_x, float a, float b)
|
||||
{
|
||||
// Rescaling (min-max normalization) from [min_x..max_x] to [a..b].
|
||||
return a + (((x - min_x) * (b - a)) / (max_x - min_x));
|
||||
}
|
||||
|
||||
required_shared_ptr<u8> m_display_ram;
|
||||
required_device<hcd62121_cpu_device> m_maincpu;
|
||||
|
||||
required_ioport m_io_buttons;
|
||||
required_ioport m_io_pen_x;
|
||||
required_ioport m_io_pen_y;
|
||||
required_ioport m_io_pen_y_rescale;
|
||||
|
||||
u16 m_ko; // KO lines
|
||||
u8 m_port; // PORT lines (serial I/O)
|
||||
u8 m_opt; // OPT lines (contrast)
|
||||
std::unique_ptr<u8[]> m_io_tablet_regs;
|
||||
emu_timer *m_io_timer;
|
||||
u8 m_pen_state;
|
||||
u8 m_pen_target;
|
||||
};
|
||||
|
||||
void pickytlk_state::machine_start()
|
||||
{
|
||||
save_item(NAME(m_ko));
|
||||
save_item(NAME(m_port));
|
||||
save_item(NAME(m_opt));
|
||||
m_io_tablet_regs = make_unique_clear<u8[]>(0x100);
|
||||
save_pointer(NAME(m_io_tablet_regs), 0x100);
|
||||
m_io_timer = timer_alloc(FUNC(pickytlk_state::io_timer_tick), this);
|
||||
save_item(NAME(m_pen_state));
|
||||
save_item(NAME(m_pen_target));
|
||||
}
|
||||
|
||||
void pickytlk_state::machine_reset()
|
||||
{
|
||||
memset(m_io_tablet_regs.get(), 0, 0x100);
|
||||
m_io_timer->reset(attotime::never);
|
||||
m_pen_state = PEN_RELEASE;
|
||||
m_pen_target = PEN_TARGET_LCD;
|
||||
}
|
||||
|
||||
CROSSHAIR_MAPPER_MEMBER(pickytlk_state::pen_y_mapper)
|
||||
{
|
||||
// Parameter `linear_value` is ignored, since we will read the input port directly
|
||||
// for adjustments, just need to return that value in the expected range [0.0f..1.0f].
|
||||
return (float) pen_y_rescale_r() / 0xff;
|
||||
}
|
||||
|
||||
CUSTOM_INPUT_MEMBER(pickytlk_state::pen_y_rescale_r)
|
||||
{
|
||||
/*
|
||||
There are two distinct areas that can be interacted with the pen:
|
||||
- LCD screen visible area: pen coordinates in [0x20..0xa0];
|
||||
- Bottom panel: pen coordinates in [0xa0..0xf0];
|
||||
In order to transparently map coordinates between each area, we split
|
||||
the value across these areas, but rescaled to the input port's full range.
|
||||
*/
|
||||
const s16 io_pen_y_min = m_io_pen_y->field(0xff)->minval();
|
||||
const s16 io_pen_y_max = m_io_pen_y->field(0xff)->maxval();
|
||||
const s16 screen_y_max = io_pen_y_max * 0.6f;
|
||||
s16 adjusted_value = m_io_pen_y->read();
|
||||
if (adjusted_value > screen_y_max)
|
||||
{
|
||||
adjusted_value = rescale(adjusted_value, screen_y_max, io_pen_y_max, io_pen_y_min, io_pen_y_max);
|
||||
m_pen_target = PEN_TARGET_PANEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
adjusted_value = rescale(adjusted_value, io_pen_y_min, screen_y_max, io_pen_y_min, io_pen_y_max);
|
||||
m_pen_target = PEN_TARGET_LCD;
|
||||
}
|
||||
|
||||
return adjusted_value;
|
||||
}
|
||||
|
||||
ioport_value pickytlk_state::pen_target_r()
|
||||
{
|
||||
return m_pen_target;
|
||||
}
|
||||
|
||||
void pickytlk_state::pickytlk_mem(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x007fff).mirror(0x008000).rom();
|
||||
map(0x080000, 0x0807ff).ram().share("video_ram");
|
||||
map(0x080000, 0x0807ff).ram();
|
||||
map(0x080300, 0x08030f).rw(FUNC(pickytlk_state::tablet_read), FUNC(pickytlk_state::tablet_write));
|
||||
// map(0x100000, 0x10ffff) // some memory mapped i/o???
|
||||
// map(0x110000, 0x11ffff) // some memory mapped i/o???
|
||||
map(0x200000, 0x2fffff).rom().region("mask_rom", 0);
|
||||
@ -82,34 +200,124 @@ void pickytlk_state::pickytlk_mem(address_map &map)
|
||||
// map(0xe10000, 0xe1ffff) // some memory mapped i/o???
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(pickytlk_state::io_timer_tick)
|
||||
{
|
||||
if (m_pen_state == PEN_PRESS)
|
||||
{
|
||||
m_pen_state = PEN_HOLD;
|
||||
}
|
||||
}
|
||||
|
||||
u8 pickytlk_state::io_pen_x_read()
|
||||
{
|
||||
// Pen callibration tests seem to check coordinates relative to the center of the LCD screen,
|
||||
// and those offsets also align with the LCD position relative to the full tablet surface.
|
||||
s16 io_pen_x_min = m_io_pen_x->field(0xff)->minval();
|
||||
s16 io_pen_x_max = m_io_pen_x->field(0xff)->maxval();
|
||||
s16 io_pen_x_pos = m_io_pen_x->read();
|
||||
return rescale(io_pen_x_pos, io_pen_x_min, io_pen_x_max, 0x20, 0xdf);
|
||||
}
|
||||
|
||||
u8 pickytlk_state::io_pen_y_read()
|
||||
{
|
||||
s16 io_pen_y_min = m_io_pen_y->field(0xff)->minval();
|
||||
s16 io_pen_y_max = m_io_pen_y->field(0xff)->maxval();
|
||||
s16 io_pen_y_pos = pen_y_rescale_r();
|
||||
return (m_pen_target == PEN_TARGET_LCD)
|
||||
? rescale(io_pen_y_pos, io_pen_y_min, io_pen_y_max, 0x20, 0xa0)
|
||||
: rescale(io_pen_y_pos, io_pen_y_min, io_pen_y_max, 0xa0, 0xf0);
|
||||
}
|
||||
|
||||
u8 pickytlk_state::tablet_read(offs_t offset)
|
||||
{
|
||||
/*
|
||||
Pen coordinates can return a mirrored value when bit 4 is not set.
|
||||
Both pairs of values <x1,x2>, <y1,y2> are approximated from these tests:
|
||||
- General case:
|
||||
- x1 + x2 > 0xc8
|
||||
- y1 + y2 > 0xc8
|
||||
- Reset screen with "OK" prompt:
|
||||
- x1 > 0x7d
|
||||
- y1 > 0x7d
|
||||
- Pen callibration:
|
||||
- x1 < 0x72
|
||||
- x2 < 0x72
|
||||
- y1 < 0x64
|
||||
- y1 > 0x68
|
||||
*/
|
||||
LOGMASKED(LOG_TABLET, "%s: tablet_read [%02x] = %02x\n", machine().describe_context(), offset, m_io_tablet_regs[offset]);
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
u8 y = BIT(m_ko, 7) ? io_pen_y_read() : 0;
|
||||
LOGMASKED(LOG_TABLET, "%s: pen y = %02x\n", machine().describe_context(), y);
|
||||
return BIT(m_ko, 4) ? y : (0xff - y);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
u8 x = BIT(m_ko, 6) ? io_pen_x_read() : 0;
|
||||
LOGMASKED(LOG_TABLET, "%s: pen x = %02x\n", machine().describe_context(), x);
|
||||
return BIT(m_ko, 4) ? x : (0xff - x);
|
||||
}
|
||||
case 4:
|
||||
// Can return 0 if other values are not stable/ready?
|
||||
return 0x80;
|
||||
default:
|
||||
return m_io_tablet_regs[offset];
|
||||
}
|
||||
}
|
||||
|
||||
void pickytlk_state::tablet_write(offs_t offset, u8 data)
|
||||
{
|
||||
LOGMASKED(LOG_TABLET, "%s: tablet_write [%02x] = %02x\n", machine().describe_context(), offset, data);
|
||||
m_io_tablet_regs[offset] = data;
|
||||
}
|
||||
|
||||
void pickytlk_state::kol_w(u8 data)
|
||||
{
|
||||
m_ko = (m_ko & 0xff00) | data;
|
||||
logerror("%s: KO is now %04x\n", machine().describe_context(), m_ko);
|
||||
LOGMASKED(LOG_IO, "%s: KO = %04x\n", machine().describe_context(), m_ko);
|
||||
}
|
||||
|
||||
void pickytlk_state::koh_w(u8 data)
|
||||
{
|
||||
m_ko = (m_ko & 0x00ff) | (u16(data) << 8);
|
||||
logerror("%s: KO is now %04x\n", machine().describe_context(), m_ko);
|
||||
LOGMASKED(LOG_IO, "%s: KO = %04x\n", machine().describe_context(), m_ko);
|
||||
}
|
||||
|
||||
void pickytlk_state::port_w(u8 data)
|
||||
{
|
||||
m_port = data;
|
||||
logerror("%s: PORT is now %02x\n", machine().describe_context(), m_port);
|
||||
LOGMASKED(LOG_IO, "%s: PORT = %02x\n", machine().describe_context(), m_port);
|
||||
}
|
||||
|
||||
void pickytlk_state::opt_w(u8 data)
|
||||
{
|
||||
m_opt = data;
|
||||
logerror("%s: OPT is now %02x\n", machine().describe_context(), m_opt);
|
||||
LOGMASKED(LOG_IO, "%s: OPT = %02x\n", machine().describe_context(), m_opt);
|
||||
}
|
||||
|
||||
u8 pickytlk_state::ki_r()
|
||||
{
|
||||
// TODO
|
||||
return 0;
|
||||
if (BIT(m_io_buttons->read(), 6))
|
||||
{
|
||||
if (m_pen_state == PEN_RELEASE)
|
||||
{
|
||||
m_pen_state = PEN_PRESS;
|
||||
// FIXME: Adjust delay when more accurate instruction timings are implemented.
|
||||
// Program code waits for input flag to be stable by executing `mov DSIZE,0xff`
|
||||
// then `movq R00,R00` 15 times (see pickytlk ROM @ 2015f6).
|
||||
m_io_timer->adjust(attotime::from_msec(1), 0, attotime::never);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pen_state = PEN_RELEASE;
|
||||
m_io_timer->reset(attotime::never);
|
||||
}
|
||||
|
||||
return m_pen_state == PEN_PRESS ? 0x80 : 0;
|
||||
}
|
||||
|
||||
u8 pickytlk_state::in0_r()
|
||||
@ -124,6 +332,17 @@ u8 pickytlk_state::in0_r()
|
||||
return 0x30 & ~0x00;
|
||||
}
|
||||
|
||||
u8 pickytlk_state::input_flag_read()
|
||||
{
|
||||
return m_pen_state == PEN_HOLD ? 0 : 1;
|
||||
}
|
||||
|
||||
void pickytlk_state::update_crosshair(screen_device &screen)
|
||||
{
|
||||
// Either screen crosshair or layout view's cursor should be visible at a time.
|
||||
machine().crosshair().get_crosshair(0).set_screen(m_pen_target ? CROSSHAIR_SCREEN_NONE : &screen);
|
||||
}
|
||||
|
||||
void pickytlk_state::pickytlk_palette(palette_device &palette) const
|
||||
{
|
||||
palette.set_pen_color(0, 0xee, 0xee, 0xcc);
|
||||
@ -134,6 +353,8 @@ void pickytlk_state::pickytlk_palette(palette_device &palette) const
|
||||
|
||||
u32 pickytlk_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
update_crosshair(screen);
|
||||
|
||||
u16 offset = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
@ -149,7 +370,10 @@ u32 pickytlk_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, c
|
||||
|
||||
for (int b = 0; b < 8; b++)
|
||||
{
|
||||
row[x + b] = (BIT(data1, b) << 1) | BIT(data2, b);
|
||||
if (x + b < 127)
|
||||
{
|
||||
row[x + b] = (BIT(data1, b) << 1) | BIT(data2, b);
|
||||
}
|
||||
}
|
||||
|
||||
offset++;
|
||||
@ -161,7 +385,19 @@ u32 pickytlk_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, c
|
||||
|
||||
|
||||
static INPUT_PORTS_START(pickytlk)
|
||||
// TODO
|
||||
// TODO: On/Off/Reset
|
||||
PORT_START("BUTTONS")
|
||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("Pen Down")
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(pickytlk_state, pen_target_r)
|
||||
|
||||
PORT_START("PEN_X")
|
||||
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_NAME("Pen X")
|
||||
|
||||
PORT_START("PEN_Y")
|
||||
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_NAME("Pen Y") PORT_CROSSHAIR_MAPPER_MEMBER(DEVICE_SELF, pickytlk_state, pen_y_mapper)
|
||||
|
||||
PORT_START("PEN_Y_RESCALE")
|
||||
PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(pickytlk_state, pen_y_rescale_r)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -175,17 +411,19 @@ void pickytlk_state::pickytlk(machine_config &config)
|
||||
m_maincpu->opt_cb().set(FUNC(pickytlk_state::opt_w));
|
||||
m_maincpu->ki_cb().set(FUNC(pickytlk_state::ki_r));
|
||||
m_maincpu->in0_cb().set(FUNC(pickytlk_state::in0_r));
|
||||
m_maincpu->input_flag_cb().set(FUNC(pickytlk_state::input_flag_read));
|
||||
|
||||
// TODO: Touchpad layout
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_size(128, 64);
|
||||
screen.set_visarea(0, 127, 0, 63);
|
||||
screen.set_size(127, 64);
|
||||
screen.set_visarea(0, 126, 0, 63);
|
||||
screen.set_screen_update(FUNC(pickytlk_state::screen_update));
|
||||
screen.set_palette("palette");
|
||||
|
||||
// TODO: Verify amount of colors and palette. Colors can be changed by changing the contrast.
|
||||
PALETTE(config, "palette", FUNC(pickytlk_state::pickytlk_palette), 4);
|
||||
|
||||
config.set_default_layout(layout_pickytlk);
|
||||
}
|
||||
|
||||
|
||||
|
116
src/mame/layout/pickytlk.lay
Normal file
116
src/mame/layout/pickytlk.lay
Normal file
@ -0,0 +1,116 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
license:CC0-1.0
|
||||
-->
|
||||
<mamelayout version="2">
|
||||
<element name="pencursor">
|
||||
<image state="1">
|
||||
<data><![CDATA[
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1" height="1" viewBox="0 0 1 1">
|
||||
<g fill="none" stroke="#6666ff" stroke-width="0.06" stroke-opacity="1">
|
||||
<circle cx="0.5" cy="0.5" r="0.1" />
|
||||
<circle cx="0.5" cy="0.5" r="0.47" />
|
||||
<line x1="0.03" y1="0.5" x2="0.4" y2="0.5" />
|
||||
<line x1="0.6" y1="0.5" x2="0.97" y2="0.5" />
|
||||
<line x1="0.5" y1="0.03" x2="0.5" y2="0.4" />
|
||||
<line x1="0.5" y1="0.6" x2="0.5" y2="0.97" />
|
||||
<line />
|
||||
</g>
|
||||
</svg>
|
||||
]]></data>
|
||||
</image>
|
||||
</element>
|
||||
|
||||
<!--
|
||||
Panel labels:
|
||||
|
||||
| ワリア | ▲ | △ |メニュー|
|
||||
| ◀ | ▶ |
|
||||
| 修正 | ▼ | ▽ | OK |
|
||||
|
||||
Panel labels (translated):
|
||||
|
||||
| Clear | ▲ | △ | Menu |
|
||||
| ◀ | ▶ |
|
||||
| Edit | ▼ | ▽ | OK |
|
||||
-->
|
||||
<element name="panel">
|
||||
<!-- background -->
|
||||
<rect><color red="0.78" green="0.86" blue="0.74" /><bounds x="0" y="0" width="128" height="12" /></rect>
|
||||
<rect><color red="1" green="1" blue="1" /><bounds x="0" y="12" width="128" height="30" /></rect>
|
||||
<!-- 1st row -->
|
||||
<rect><color red="0.82" green="0.47" blue="0.35" /><bounds x="1" y="13" width="30" height="12" /></rect>
|
||||
<text string="Clear" ><color red="1" green="1" blue="1" /><bounds x="2" y="14" width="28" height="10" /></text>
|
||||
<rect><color red="0.82" green="0.47" blue="0.35" /><bounds x="33" y="13" width="30" height="8" /></rect>
|
||||
<text string="▲" ><color red="1" green="1" blue="1" /><bounds x="34" y="12" width="28" height="10" /></text>
|
||||
<rect><color red="0.82" green="0.47" blue="0.35" /><bounds x="65" y="13" width="30" height="12" /></rect>
|
||||
<text string="Previous"><color red="1" green="1" blue="1" /><bounds x="66" y="14" width="28" height="10" /></text>
|
||||
<rect><color red="0.82" green="0.47" blue="0.35" /><bounds x="97" y="13" width="30" height="12" /></rect>
|
||||
<text string="Menu" ><color red="1" green="1" blue="1" /><bounds x="98" y="14" width="28" height="10" /></text>
|
||||
<!-- 2nd row -->
|
||||
<rect><color red="0.82" green="0.47" blue="0.35" /><bounds x="33" y="23" width="14" height="6" /></rect>
|
||||
<text string="◄" ><color red="1" green="1" blue="1" /><bounds x="34" y="22" width="12" height="8" /></text>
|
||||
<rect><color red="0.82" green="0.47" blue="0.35" /><bounds x="49" y="23" width="14" height="6" /></rect>
|
||||
<text string="►" ><color red="1" green="1" blue="1" /><bounds x="50" y="22" width="12" height="8" /></text>
|
||||
<!-- 3rd row -->
|
||||
<rect><color red="0.82" green="0.47" blue="0.35" /><bounds x="1" y="27" width="30" height="12" /></rect>
|
||||
<text string="Edit"><color red="1" green="1" blue="1" /><bounds x="2" y="28" width="28" height="10" /></text>
|
||||
<rect><color red="0.82" green="0.47" blue="0.35" /><bounds x="33" y="31" width="30" height="8" /></rect>
|
||||
<text string="▼" ><color red="1" green="1" blue="1" /><bounds x="34" y="30" width="28" height="10" /></text>
|
||||
<rect><color red="0.82" green="0.47" blue="0.35" /><bounds x="65" y="27" width="30" height="12" /></rect>
|
||||
<text string="Next"><color red="1" green="1" blue="1" /><bounds x="66" y="28" width="28" height="10" /></text>
|
||||
<rect><color red="0.82" green="0.47" blue="0.35" /><bounds x="97" y="27" width="30" height="12" /></rect>
|
||||
<text string="OK" ><color red="1" green="1" blue="1" /><bounds x="98" y="28" width="28" height="10" /></text>
|
||||
</element>
|
||||
|
||||
<view name="Default View">
|
||||
<screen index="0">
|
||||
<bounds x="0" y="0" width="128" height="64" />
|
||||
</screen>
|
||||
|
||||
<element id="panel" ref="panel">
|
||||
<bounds x="0" y="64" width="128" height="42" />
|
||||
</element>
|
||||
|
||||
<element id="pencursor" ref="pencursor">
|
||||
<!-- will be positioned by script -->
|
||||
<bounds x="0" y="8" width="0.2" height="0.2" />
|
||||
<color alpha="0.7" />
|
||||
</element>
|
||||
</view>
|
||||
|
||||
<script><![CDATA[
|
||||
file:set_resolve_tags_callback(
|
||||
function ()
|
||||
local panel = file.views['Default View'].items['panel']
|
||||
|
||||
-- recompute target pen cursor size and area when necessary
|
||||
local curxoffs, curyoffs, curxscale, curyscale, curwidth, curheight
|
||||
file.views['Default View']:set_recomputed_callback(
|
||||
function ()
|
||||
local bounds = panel.bounds
|
||||
curwidth = bounds.width / 16
|
||||
curheight = bounds.height * 4 / 16
|
||||
curxoffs = bounds.x0 - (curwidth * 0.5)
|
||||
curyoffs = bounds.y0 - (curheight * 0.5)
|
||||
curxscale = bounds.width / 255
|
||||
curyscale = bounds.height / 255
|
||||
end)
|
||||
|
||||
-- animate the position of the pen cursor
|
||||
local penctrl = file.device:ioport('BUTTONS')
|
||||
local penx = file.device:ioport('PEN_X')
|
||||
local peny = file.device:ioport('PEN_Y_RESCALE')
|
||||
file.views['Default View'].items['pencursor']:set_element_state_callback(
|
||||
function ()
|
||||
return (penctrl:read() & 0x80) >> 7
|
||||
end)
|
||||
file.views['Default View'].items['pencursor']:set_bounds_callback(
|
||||
function ()
|
||||
local x = curxoffs + (penx:read() * curxscale)
|
||||
local y = curyoffs + (peny:read() * curyscale)
|
||||
return emu.render_bounds(x, y, x + curwidth, y + curheight)
|
||||
end)
|
||||
end)
|
||||
]]></script>
|
||||
</mamelayout>
|
Loading…
Reference in New Issue
Block a user