sinclair/next/specnext_vtest.cpp: Factory Video test (joistick's XYZ to activate)
This commit is contained in:
parent
fdce3c40fa
commit
6f78bdf018
@ -32,6 +32,7 @@
|
|||||||
#include "specnext_sprites.h"
|
#include "specnext_sprites.h"
|
||||||
#include "specnext_tiles.h"
|
#include "specnext_tiles.h"
|
||||||
#include "specnext_uart.h"
|
#include "specnext_uart.h"
|
||||||
|
#include "specnext_vtest.h"
|
||||||
|
|
||||||
#include "bus/midi/midi.h"
|
#include "bus/midi/midi.h"
|
||||||
#include "bus/rs232/rs232.h"
|
#include "bus/rs232/rs232.h"
|
||||||
@ -145,6 +146,7 @@ public:
|
|||||||
, m_layer2(*this, "layer2")
|
, m_layer2(*this, "layer2")
|
||||||
, m_lores(*this, "lores")
|
, m_lores(*this, "lores")
|
||||||
, m_sprites(*this, "sprites")
|
, m_sprites(*this, "sprites")
|
||||||
|
, m_vtest(*this, "vtest")
|
||||||
, m_io_video(*this, "VIDEO")
|
, m_io_video(*this, "VIDEO")
|
||||||
, m_io_layers(*this, "LYRS")
|
, m_io_layers(*this, "LYRS")
|
||||||
, m_io_mouse(*this, "mouse_input%u", 0U)
|
, m_io_mouse(*this, "mouse_input%u", 0U)
|
||||||
@ -389,8 +391,10 @@ private:
|
|||||||
required_device<specnext_layer2_device> m_layer2;
|
required_device<specnext_layer2_device> m_layer2;
|
||||||
required_device<specnext_lores_device> m_lores;
|
required_device<specnext_lores_device> m_lores;
|
||||||
required_device<specnext_sprites_device> m_sprites;
|
required_device<specnext_sprites_device> m_sprites;
|
||||||
|
required_device<specnext_vtest_device> m_vtest;
|
||||||
optional_ioport m_io_video;
|
optional_ioport m_io_video;
|
||||||
optional_ioport m_io_layers;
|
optional_ioport m_io_layers;
|
||||||
|
bool m_video_test_pattern_active = false;
|
||||||
required_ioport_array<4> m_io_mouse;
|
required_ioport_array<4> m_io_mouse;
|
||||||
required_ioport m_io_joy_left;
|
required_ioport m_io_joy_left;
|
||||||
required_ioport m_io_joy_right;
|
required_ioport m_io_joy_right;
|
||||||
@ -989,6 +993,7 @@ void specnext_state::update_video_mode()
|
|||||||
m_tiles->set_raster_offset(left, top);
|
m_tiles->set_raster_offset(left, top);
|
||||||
m_layer2->set_raster_offset(left, top);
|
m_layer2->set_raster_offset(left, top);
|
||||||
m_sprites->set_raster_offset(left, top);
|
m_sprites->set_raster_offset(left, top);
|
||||||
|
m_vtest->set_raster_offset(left, top);
|
||||||
|
|
||||||
m_eff_nr_03_machine_timing = m_nr_03_machine_timing;
|
m_eff_nr_03_machine_timing = m_nr_03_machine_timing;
|
||||||
m_eff_nr_05_5060 = m_nr_05_5060;
|
m_eff_nr_05_5060 = m_nr_05_5060;
|
||||||
@ -997,6 +1002,12 @@ void specnext_state::update_video_mode()
|
|||||||
|
|
||||||
u32 specnext_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
u32 specnext_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||||
{
|
{
|
||||||
|
if (m_video_test_pattern_active)
|
||||||
|
{
|
||||||
|
m_vtest->draw(bitmap, cliprect);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
rectangle clip256x192 = m_clip256x192;
|
rectangle clip256x192 = m_clip256x192;
|
||||||
clip256x192 &= cliprect;
|
clip256x192 &= cliprect;
|
||||||
rectangle clip320x256 = m_clip320x256;
|
rectangle clip320x256 = m_clip320x256;
|
||||||
@ -2770,6 +2781,7 @@ INTERRUPT_GEN_MEMBER(specnext_state::specnext_interrupt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
line_irq_adjust();
|
line_irq_adjust();
|
||||||
|
m_video_test_pattern_active = ((m_io_joy_left->read() & 0x700) == 0x700) || ((m_io_joy_right->read() & 0x700) == 0x700);
|
||||||
if (!port_ff_interrupt_disable())
|
if (!port_ff_interrupt_disable())
|
||||||
{
|
{
|
||||||
m_irq_on_timer->adjust(m_screen->time_until_pos(m_video_timings.int_v, m_video_timings.int_h << 1));
|
m_irq_on_timer->adjust(m_screen->time_until_pos(m_video_timings.int_v, m_video_timings.int_h << 1));
|
||||||
@ -3276,7 +3288,6 @@ INPUT_PORTS_START(specnext)
|
|||||||
PORT_CONFSETTING(0x00, "360x288 (HDMI)" )
|
PORT_CONFSETTING(0x00, "360x288 (HDMI)" )
|
||||||
PORT_CONFSETTING(0x01, "320x256 (VGA)" )
|
PORT_CONFSETTING(0x01, "320x256 (VGA)" )
|
||||||
PORT_BIT(0xfe, IP_ACTIVE_HIGH, IPT_UNUSED)
|
PORT_BIT(0xfe, IP_ACTIVE_HIGH, IPT_UNUSED)
|
||||||
|
|
||||||
PORT_START("mouse_input0")
|
PORT_START("mouse_input0")
|
||||||
PORT_BIT(0x7ff, 0, IPT_MOUSE_X) PORT_SENSITIVITY(100)
|
PORT_BIT(0x7ff, 0, IPT_MOUSE_X) PORT_SENSITIVITY(100)
|
||||||
|
|
||||||
@ -3373,6 +3384,7 @@ void specnext_state::machine_start()
|
|||||||
// Save
|
// Save
|
||||||
save_item(NAME(m_page_shadow));
|
save_item(NAME(m_page_shadow));
|
||||||
save_item(NAME(m_bootrom_en));
|
save_item(NAME(m_bootrom_en));
|
||||||
|
save_item(NAME(m_video_test_pattern_active));
|
||||||
save_item(NAME(m_port_ff_data));
|
save_item(NAME(m_port_ff_data));
|
||||||
save_item(NAME(m_port_1ffd_special_old));
|
save_item(NAME(m_port_1ffd_special_old));
|
||||||
save_item(NAME(m_port_1ffd_data));
|
save_item(NAME(m_port_1ffd_data));
|
||||||
@ -3618,6 +3630,7 @@ void specnext_state::reset_hard()
|
|||||||
{
|
{
|
||||||
m_nr_02_hard_reset = 0;
|
m_nr_02_hard_reset = 0;
|
||||||
m_bootrom_en = 1;
|
m_bootrom_en = 1;
|
||||||
|
m_video_test_pattern_active = 0;
|
||||||
|
|
||||||
m_dma->dma_mode_w(0);
|
m_dma->dma_mode_w(0);
|
||||||
// nmi_mf = 0;
|
// nmi_mf = 0;
|
||||||
@ -4164,6 +4177,7 @@ void specnext_state::tbblue(machine_config &config)
|
|||||||
// drawgfx doesn't allow to mask palette access and in case of 256-color sprite does use offset, the index overflow palette boundries.
|
// drawgfx doesn't allow to mask palette access and in case of 256-color sprite does use offset, the index overflow palette boundries.
|
||||||
// We are duplicating palletes to imitate mask on palette index which required by sprites device.
|
// We are duplicating palletes to imitate mask on palette index which required by sprites device.
|
||||||
SPECNEXT_SPRITES(config, m_sprites, 0).set_palette(m_palette->device().tag(), 0x600, 0x800);
|
SPECNEXT_SPRITES(config, m_sprites, 0).set_palette(m_palette->device().tag(), 0x600, 0x800);
|
||||||
|
SPECNEXT_VTEST(config, m_vtest, 0);
|
||||||
|
|
||||||
SPECNEXT_COPPER(config, m_copper, 28_MHz_XTAL);
|
SPECNEXT_COPPER(config, m_copper, 28_MHz_XTAL);
|
||||||
m_copper->out_nextreg_cb().set([this](offs_t offset, u8 data) { m_next_regs.write_byte(offset, data); });
|
m_copper->out_nextreg_cb().set([this](offs_t offset, u8 data) { m_next_regs.write_byte(offset, data); });
|
||||||
|
|||||||
164
src/mame/sinclair/next/specnext_vtest.cpp
Normal file
164
src/mame/sinclair/next/specnext_vtest.cpp
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Andrei I. Holub
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "specnext_vtest.h"
|
||||||
|
|
||||||
|
|
||||||
|
DEFINE_DEVICE_TYPE(SPECNEXT_VTEST, specnext_vtest_device, "vtest", "Spectrum Next Video Test Pattern")
|
||||||
|
|
||||||
|
|
||||||
|
specnext_vtest_device::specnext_vtest_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||||
|
: device_t(mconfig, SPECNEXT_VTEST, tag, owner, clock)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void specnext_vtest_device::draw(bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||||
|
{
|
||||||
|
static constexpr unsigned BORDER = 32;
|
||||||
|
static constexpr unsigned FULL_W = 640;
|
||||||
|
static constexpr unsigned FULL_H = 192 + (BORDER << 1); // 256
|
||||||
|
|
||||||
|
const int ox = m_offset_h - (BORDER << 1); // left - 64
|
||||||
|
const int oy = m_offset_v - BORDER; // top - 32
|
||||||
|
|
||||||
|
// FPGA video_test_pattern.vhd vertical state machine (FPGA line numbers):
|
||||||
|
//
|
||||||
|
// VS_BLANK_0 : lines 0-47 black (48 lines)
|
||||||
|
// VS_RAINBOW : lines 48-111 rainbow (64 lines)
|
||||||
|
// VS_BLANK_1 : lines 112-127 black (16 lines)
|
||||||
|
// VS_RG : lines 128-191 RG ramp (64 lines)
|
||||||
|
// VS_BLANK_2 : lines 192-207 black (16 lines)
|
||||||
|
// VS_BGR : lines 208-271 BGR ramp(64 lines)
|
||||||
|
// remainder : black
|
||||||
|
|
||||||
|
// MAME doesn't scandouble, so FPGA line counts are halved (>> 1)
|
||||||
|
static constexpr unsigned BLANK0_LINES = 48 >> 1;
|
||||||
|
static constexpr unsigned RAINBOW_LINES = 64 >> 1;
|
||||||
|
static constexpr unsigned BLANK1_LINES = 16 >> 1;
|
||||||
|
static constexpr unsigned RG_LINES = 64 >> 1;
|
||||||
|
static constexpr unsigned BLANK2_LINES = 16 >> 1;
|
||||||
|
static constexpr unsigned BGR_LINES = 64 >> 1;
|
||||||
|
|
||||||
|
static constexpr unsigned RAINBOW_START = BLANK0_LINES;
|
||||||
|
static constexpr unsigned RAINBOW_END = RAINBOW_START + RAINBOW_LINES;
|
||||||
|
static constexpr unsigned RG_START = RAINBOW_END + BLANK1_LINES;
|
||||||
|
static constexpr unsigned RG_END = RG_START + RG_LINES;
|
||||||
|
static constexpr unsigned BGR_START = RG_END + BLANK2_LINES;
|
||||||
|
static constexpr unsigned BGR_END = BGR_START + BGR_LINES;
|
||||||
|
|
||||||
|
for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
|
||||||
|
{
|
||||||
|
const int vrow = y - oy;
|
||||||
|
if (vrow < 0 || vrow >= FULL_H)
|
||||||
|
{
|
||||||
|
u32 *pix = &bitmap.pix(y, cliprect.left());
|
||||||
|
for (int x = cliprect.left(); x <= cliprect.right(); x++, pix++)
|
||||||
|
*pix = rgb_t::black();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine vertical band
|
||||||
|
unsigned band_row = 0;
|
||||||
|
int band_id; // 0=rainbow, 1=RG, 2=BGR, -1=blank
|
||||||
|
|
||||||
|
if (vrow >= BGR_START && vrow < BGR_END)
|
||||||
|
{
|
||||||
|
band_id = 2;
|
||||||
|
band_row = vrow - BGR_START;
|
||||||
|
}
|
||||||
|
else if (vrow >= RG_START && vrow < RG_END)
|
||||||
|
{
|
||||||
|
band_id = 1;
|
||||||
|
band_row = vrow - RG_START;
|
||||||
|
}
|
||||||
|
else if (vrow >= RAINBOW_START && vrow < RAINBOW_END)
|
||||||
|
{
|
||||||
|
band_id = 0;
|
||||||
|
band_row = vrow - RAINBOW_START;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
band_id = -1;
|
||||||
|
|
||||||
|
bool is_3bit = (band_id >= 0) && (band_row < 8);
|
||||||
|
bool is_4bit = (band_id >= 0) && (band_row >= 8 && band_row < 16);
|
||||||
|
|
||||||
|
u32 *pix = &bitmap.pix(y, cliprect.left());
|
||||||
|
for (int x = cliprect.left(); x <= cliprect.right(); x++, pix++)
|
||||||
|
{
|
||||||
|
const int hcol = x - ox;
|
||||||
|
|
||||||
|
if (band_id < 0 || hcol < 0 || hcol >= FULL_W)
|
||||||
|
{
|
||||||
|
*pix = rgb_t::black();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 r8 = 0, g8 = 0, b8 = 0;
|
||||||
|
|
||||||
|
if (band_id == 0) // Rainbow
|
||||||
|
{
|
||||||
|
const unsigned delta_top = hcol * 255 / FULL_W;
|
||||||
|
const unsigned phase = hcol * 512 / FULL_W;
|
||||||
|
|
||||||
|
r8 = u8(~delta_top & 0xff);
|
||||||
|
b8 = u8(delta_top & 0xff);
|
||||||
|
g8 = (phase < 256) ? u8(phase & 0xff) : u8(~phase & 0xff);
|
||||||
|
}
|
||||||
|
else if (band_id == 1) // Red/Green ramp
|
||||||
|
{
|
||||||
|
const unsigned half = FULL_W / 2;
|
||||||
|
if (hcol < half)
|
||||||
|
{
|
||||||
|
r8 = hcol * 255 / half;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g8 = (hcol - half) * 255 / half;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Blue/Grey ramp
|
||||||
|
{
|
||||||
|
const unsigned half = FULL_W / 2;
|
||||||
|
if (hcol < half)
|
||||||
|
{
|
||||||
|
b8 = hcol * 255 / half;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const u8 grey = (hcol - half) * 255 / half;
|
||||||
|
r8 = grey;
|
||||||
|
g8 = grey;
|
||||||
|
b8 = grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_4bit)
|
||||||
|
{
|
||||||
|
r8 &= 0xf0;
|
||||||
|
g8 &= 0xf0;
|
||||||
|
b8 &= 0xf0;
|
||||||
|
}
|
||||||
|
else if (is_3bit)
|
||||||
|
{
|
||||||
|
r8 &= 0xe0;
|
||||||
|
g8 &= 0xe0;
|
||||||
|
b8 &= 0xe0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pix = rgb_t(r8, g8, b8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void specnext_vtest_device::device_add_mconfig(machine_config &config)
|
||||||
|
{
|
||||||
|
m_offset_h = 0;
|
||||||
|
m_offset_v = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void specnext_vtest_device::device_start()
|
||||||
|
{
|
||||||
|
save_item(NAME(m_offset_h));
|
||||||
|
save_item(NAME(m_offset_v));
|
||||||
|
}
|
||||||
27
src/mame/sinclair/next/specnext_vtest.h
Normal file
27
src/mame/sinclair/next/specnext_vtest.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Andrei I. Holub
|
||||||
|
#ifndef MAME_SINCLAIR_NEXT_SPECNEXT_VTEST_H
|
||||||
|
#define MAME_SINCLAIR_NEXT_SPECNEXT_VTEST_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class specnext_vtest_device : public device_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
specnext_vtest_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||||
|
|
||||||
|
void set_raster_offset(u16 offset_h, u16 offset_v) { m_offset_h = offset_h; m_offset_v = offset_v; }
|
||||||
|
|
||||||
|
void draw(bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
|
||||||
|
virtual void device_start() override ATTR_COLD;
|
||||||
|
|
||||||
|
private:
|
||||||
|
u16 m_offset_h, m_offset_v;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
DECLARE_DEVICE_TYPE(SPECNEXT_VTEST, specnext_vtest_device)
|
||||||
|
#endif // MAME_SINCLAIR_NEXT_SPECNEXT_VTEST_H
|
||||||
Loading…
Reference in New Issue
Block a user