ddr/kc.cpp, ddr/kc_m.cpp: Tidied up a little.

This commit is contained in:
Vas Crabb 2023-03-15 04:33:09 +11:00
parent 79cd0eedce
commit 57ec3ee4a1
7 changed files with 340 additions and 361 deletions

View File

@ -1276,7 +1276,7 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container)
image_handler_ingame();
if (ui_disabled)
return ui_disabled;
return 0;
if (machine().ui_input().pressed(IPT_UI_CANCEL))
{

View File

@ -352,11 +352,11 @@ void pda600_copro_device::received_byte(u8 byte)
{
if (0)
{
std::string tmp = "";
std::ostringstream tmp;
for (auto b : m_buf)
tmp += util::string_format("%02X ", b);
util::stream_format(tmp, "%02X ", b);
logerror("%s\n", tmp);
logerror("%s\n", std::move(tmp).str());
}
u8 checksum = 0;

View File

@ -3,4 +3,4 @@
DDR - Deutsche Demokratische Republik
Driver files for hardware made in East Germany, before the German unification.
Intellectual property was publicly owned.
Intellectual property was publicly owned.

View File

@ -13,12 +13,12 @@
******************************************************************************/
/* Core includes */
#include "emu.h"
#include "kc.h"
#include "machine/input_merger.h"
#include "softlist_dev.h"
#include "screen.h"
#include "speaker.h"
@ -201,7 +201,7 @@ void kc_state::kc85_base(machine_config &config, uint32_t clock)
void kc_state::kc85_2_3(machine_config &config, uint32_t clock)
{
kc85_base(config, KC85_2_CLOCK);
kc85_base(config, KC85_2_CLOCK);
m_maincpu->set_addrmap(AS_PROGRAM, &kc_state::kc85_2_mem);
m_maincpu->set_addrmap(AS_IO, &kc_state::kc85_2_io);
@ -239,7 +239,7 @@ void kc85_4_state::kc85_4(machine_config &config)
m_maincpu->set_addrmap(AS_IO, &kc85_4_state::kc85_4_io);
m_z80pio->out_pb_callback().set(FUNC(kc85_4_state::pio_portb_w));
m_z80ctc->zc_callback<0>().set(FUNC(kc85_3_state::ctc_zc0_callback));
m_z80ctc->zc_callback<0>().set(FUNC(kc85_4_state::ctc_zc0_callback));
m_screen->set_screen_update(FUNC(kc85_4_state::screen_update));
@ -309,7 +309,7 @@ ROM_START(kc85_5)
ROMX_LOAD("caos43e.855", 0x2000, 0x2000, CRC(b66fc6c3) SHA1(521ac2fbded4148220f8af2d5a5ab99634364079), ROM_BIOS(1))
ROM_END
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 1987, kc85_2, 0, 0, kc85_2, kc85, kc_state, empty_init, u8"VEB Mikroelektronik \"Wilhelm Pieck\" Mühlhausen", "HC900 / KC 85/2", MACHINE_NOT_WORKING)
COMP( 1987, kc85_3, kc85_2, 0, kc85_3, kc85, kc85_3_state, empty_init, u8"VEB Mikroelektronik \"Wilhelm Pieck\" Mühlhausen", "KC 85/3", MACHINE_NOT_WORKING)
COMP( 1989, kc85_4, kc85_2, 0, kc85_4, kc85, kc85_4_state, empty_init, u8"VEB Mikroelektronik \"Wilhelm Pieck\" Mühlhausen", "KC 85/4", MACHINE_NOT_WORKING)

View File

@ -10,47 +10,30 @@
#pragma once
/* Devices */
#include "imagedev/cassette.h"
#include "machine/ram.h"
#include "machine/timer.h"
// Components
#include "cpu/z80/z80.h"
#include "machine/z80daisy.h"
#include "machine/z80ctc.h"
#include "machine/z80pio.h"
#include "machine/ram.h"
#include "kc_keyb.h"
#include "machine/rescap.h"
#include "sound/spkrdev.h"
#include "emupal.h"
#include "screen.h"
// Devices
#include "imagedev/cassette.h"
#include "imagedev/snapquik.h"
// Expansions
#include "bus/kc/d002.h"
#include "bus/kc/d004.h"
#include "bus/kc/kc.h"
#include "bus/kc/ram.h"
#include "bus/kc/rom.h"
#include "bus/kc/d002.h"
#include "bus/kc/d004.h"
#include "cpu/z80/z80.h"
#include "imagedev/cassette.h"
#include "imagedev/snapquik.h"
#include "machine/ram.h"
#include "machine/rescap.h"
#include "machine/timer.h"
#include "machine/z80ctc.h"
#include "machine/z80daisy.h"
#include "machine/z80pio.h"
#include "sound/spkrdev.h"
// Formats
#include "formats/kc_cas.h"
// from service manual
#define KC85_2_CLOCK 1751938
#define KC85_4_CLOCK 1773447
#define KC85_4_SCREEN_PIXEL_RAM_SIZE 0x04000
#define KC85_4_SCREEN_COLOUR_RAM_SIZE 0x04000
#define KC85_PALETTE_SIZE 24
#define KC85_SCREEN_WIDTH 320
#define KC85_SCREEN_HEIGHT 256
#include "emupal.h"
#include "screen.h"
// cassette input polling frequency
#define KC_CASSETTE_TIMER_FREQUENCY attotime::from_hz(44100)
@ -72,6 +55,20 @@ public:
, m_expansions(*this, {"m8", "mc", "exp"})
{ }
void kc85_2(machine_config &config) ATTR_COLD;
protected:
// from service manual
static inline constexpr uint32_t KC85_2_CLOCK = 1'751'938;
static inline constexpr uint32_t KC85_4_CLOCK = 1'773'447;
static inline constexpr unsigned KC85_4_SCREEN_PIXEL_RAM_SIZE = 0x04000;
static inline constexpr unsigned KC85_4_SCREEN_COLOUR_RAM_SIZE = 0x04000;
static inline constexpr unsigned KC85_PALETTE_SIZE = 24;
static inline constexpr unsigned KC85_SCREEN_WIDTH = 320;
static inline constexpr unsigned KC85_SCREEN_HEIGHT = 256;
required_device<z80_device> m_maincpu;
required_device<z80pio_device> m_z80pio;
required_device<z80ctc_device> m_z80ctc;
@ -83,6 +80,28 @@ public:
required_device<screen_device> m_screen;
required_device_array<kcexp_slot_device, 3> m_expansions;
// driver state
uint8_t * m_ram_base = nullptr;
std::unique_ptr<uint8_t[]> m_video_ram{};
int m_pio_data[2]{};
int m_high_resolution = 0;
uint8_t m_ardy = 0U;
uint8_t m_brdy = 0U;
int m_kc85_blink_state = 0;
int m_k0_line = 0;
int m_k1_line = 0;
uint8_t m_dac_level = 0U;
// cassette
emu_timer * m_cassette_timer = nullptr;
emu_timer * m_cassette_oneshot_timer = nullptr;
int m_astb = 0;
int m_cassette_in = 0;
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override ATTR_COLD;
virtual void video_start() override ATTR_COLD;
// modules read/write
uint8_t expansion_read(offs_t offset);
void expansion_write(offs_t offset, uint8_t data);
@ -97,13 +116,6 @@ public:
uint8_t expansion_io_read(offs_t offset);
void expansion_io_write(offs_t offset, uint8_t data);
void kc85_2(machine_config &config);
protected:
// defined in machine/kc.cpp
virtual void machine_start() override;
virtual void machine_reset() override;
// bankswitch
virtual void update_0x00000();
virtual void update_0x04000();
@ -134,42 +146,23 @@ protected:
virtual void dac_update();
void tapeout_update();
// defined in video/kc.cpp
virtual void video_start() override;
virtual uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER( video_toggle_blink_state );
void video_draw_8_pixels(bitmap_ind16 &bitmap, int x, int y, uint8_t colour_byte, uint8_t gfx_byte);
// driver state
uint8_t * m_ram_base = nullptr;
std::unique_ptr<uint8_t[]> m_video_ram{};
int m_pio_data[2]{};
int m_high_resolution = 0;
uint8_t m_ardy = 0U;
uint8_t m_brdy = 0U;
int m_kc85_blink_state = 0;
int m_k0_line = 0;
int m_k1_line = 0;
uint8_t m_dac_level = 0U;
// cassette
emu_timer * m_cassette_timer = nullptr;
emu_timer * m_cassette_oneshot_timer = nullptr;
int m_astb = 0;
int m_cassette_in = 0;
void kc85_palette(palette_device &palette) const;
void kc85_palette(palette_device &palette) const ATTR_COLD;
TIMER_CALLBACK_MEMBER(kc_cassette_oneshot_timer);
TIMER_CALLBACK_MEMBER(kc_cassette_timer_callback);
TIMER_DEVICE_CALLBACK_MEMBER(kc_scanline);
DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);
void kc85_slots(machine_config &config);
void kc85_base(machine_config &config, uint32_t clock);
void kc85_2_3(machine_config &config, uint32_t clock);
void kc85_2_io(address_map &map);
void kc85_2_mem(address_map &map);
void kc85_slots(machine_config &config) ATTR_COLD;
void kc85_base(machine_config &config, uint32_t clock) ATTR_COLD;
void kc85_2_3(machine_config &config, uint32_t clock) ATTR_COLD;
void kc85_2_mem(address_map &map) ATTR_COLD;
void kc85_2_io(address_map &map) ATTR_COLD;
};
@ -181,22 +174,22 @@ public:
, m_speaker(*this, "speaker")
{ }
void kc85_3(machine_config &config) ATTR_COLD;
protected:
required_device<speaker_sound_device> m_speaker;
// driver state
uint8_t m_speaker_level = 0U;
// CTC callback
DECLARE_WRITE_LINE_MEMBER( ctc_zc0_callback );
void kc85_3(machine_config &config);
protected:
// PIO callback
void pio_portb_w(uint8_t data) override;
// sound
virtual void speaker_update();
// driver state
uint8_t m_speaker_level = 0U;
};
@ -207,12 +200,17 @@ public:
: kc85_3_state(mconfig, type, tag)
{ }
void kc85_4(machine_config &config);
void kc85_5(machine_config &config);
void kc85_4(machine_config &config) ATTR_COLD;
void kc85_5(machine_config &config) ATTR_COLD;
protected:
// defined in machine/kc.cpp
virtual void machine_reset() override;
// driver state
uint8_t m_port_84_data = 0U;
uint8_t m_port_86_data = 0U;
uint8_t * m_display_video_ram = 0U;
virtual void machine_reset() override ATTR_COLD;
virtual void video_start() override ATTR_COLD;
virtual void update_0x04000() override;
virtual void update_0x08000() override;
@ -223,8 +221,6 @@ protected:
void kc85_4_86_w(uint8_t data);
void kc85_4_84_w(uint8_t data);
// defined in video/kc.cpp
virtual void video_start() override;
virtual uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) override;
void video_control_w(int data);
@ -235,12 +231,8 @@ protected:
void dac_update() override;
void speaker_update() override;
// driver state
uint8_t m_port_84_data = 0U;
uint8_t m_port_86_data = 0U;
uint8_t * m_display_video_ram = 0U;
void kc85_4_io(address_map &map);
void kc85_4_mem(address_map &map);
void kc85_4_mem(address_map &map) ATTR_COLD;
void kc85_4_io(address_map &map) ATTR_COLD;
};
#endif // MAME_DDR_KC_H

View File

@ -4,8 +4,9 @@
#include "emu.h"
#include "kc.h"
#define KC_DEBUG 0
#define LOG(x) do { if (KC_DEBUG) logerror x; } while (0)
//#define VERBOSE 0
#include "logmacro.h"
struct kcc_header
{
@ -282,7 +283,7 @@ void kc_state::update_0x00000()
/* access ram? */
if (m_pio_data[0] & (1<<1))
{
LOG(("ram0 enabled\n"));
LOG("ram0 enabled\n");
/* yes; set address of bank */
space.install_rom(0x0000, 0x3fff, m_ram_base);
@ -291,14 +292,14 @@ void kc_state::update_0x00000()
if ((m_pio_data[0] & (1<<3)) == 0)
{
/* yes */
LOG(("ram0 write protected\n"));
LOG("ram0 write protected\n");
/* ram is enabled and write protected */
space.unmap_write(0x0000, 0x3fff);
}
else
{
LOG(("ram0 write enabled\n"));
LOG("ram0 write enabled\n");
/* ram is enabled and write enabled */
space.install_writeonly(0x0000, 0x3fff, m_ram_base);
@ -306,7 +307,7 @@ void kc_state::update_0x00000()
}
else
{
LOG(("Module at 0x0000\n"));
LOG("Module at 0x0000\n");
space.install_read_handler (0x0000, 0x3fff, read8sm_delegate(*this, FUNC(kc_state::expansion_read)), 0);
space.install_write_handler(0x0000, 0x3fff, write8sm_delegate(*this, FUNC(kc_state::expansion_write)), 0);
@ -318,7 +319,7 @@ void kc_state::update_0x04000()
{
address_space &space = m_maincpu->space( AS_PROGRAM );
LOG(("Module at 0x4000\n"));
LOG("Module at 0x4000\n");
space.install_read_handler (0x4000, 0x7fff, read8sm_delegate(*this, FUNC(kc_state::expansion_4000_r)), 0);
space.install_write_handler(0x4000, 0x7fff, write8sm_delegate(*this, FUNC(kc_state::expansion_4000_w)), 0);
@ -334,14 +335,14 @@ void kc_state::update_0x0c000()
if ((m_pio_data[0] & (1<<7)) && memregion("basic") != nullptr)
{
/* BASIC takes next priority */
LOG(("BASIC rom 0x0c000\n"));
LOG("BASIC rom 0x0c000\n");
space.install_rom(0xc000, 0xdfff, memregion("basic")->base());
space.unmap_write(0xc000, 0xdfff);
}
else
{
LOG(("Module at 0x0c000\n"));
LOG("Module at 0x0c000\n");
space.install_read_handler (0xc000, 0xdfff, read8sm_delegate(*this, FUNC(kc_state::expansion_c000_r)), 0);
space.install_write_handler(0xc000, 0xdfff, write8sm_delegate(*this, FUNC(kc_state::expansion_c000_w)), 0);
@ -356,14 +357,14 @@ void kc_state::update_0x0e000()
if (m_pio_data[0] & (1<<0))
{
/* enable CAOS rom in memory range 0x0e000-0x0ffff */
LOG(("CAOS rom 0x0e000\n"));
LOG("CAOS rom 0x0e000\n");
/* read will access the rom */
space.install_rom(0xe000, 0xffff, memregion("caos")->base() + 0x2000);
space.unmap_write(0xe000, 0xffff);
}
else
{
LOG(("Module at 0x0e000\n"));
LOG("Module at 0x0e000\n");
space.install_read_handler (0xe000, 0xffff, read8sm_delegate(*this, FUNC(kc_state::expansion_e000_r)), 0);
space.install_write_handler(0xe000, 0xffff, write8sm_delegate(*this, FUNC(kc_state::expansion_e000_w)), 0);
@ -379,13 +380,13 @@ void kc_state::update_0x08000()
if (m_pio_data[0] & (1<<2))
{
/* IRM enabled */
LOG(("IRM enabled\n"));
LOG("IRM enabled\n");
space.install_ram(0x8000, 0xbfff, &m_video_ram[0]);
}
else
{
LOG(("Module at 0x8000!\n"));
LOG("Module at 0x8000!\n");
space.install_read_handler(0x8000, 0xbfff, read8sm_delegate(*this, FUNC(kc_state::expansion_8000_r)), 0);
space.install_write_handler(0x8000, 0xbfff, write8sm_delegate(*this, FUNC(kc_state::expansion_8000_w)), 0);
@ -401,7 +402,7 @@ void kc85_4_state::update_0x04000()
/* access ram? */
if (m_port_86_data & (1<<0))
{
LOG(("RAM4 enabled\n"));
LOG("RAM4 enabled\n");
/* yes */
space.install_rom(0x4000, 0x7fff, m_ram_base + 0x4000);
@ -410,14 +411,14 @@ void kc85_4_state::update_0x04000()
if ((m_port_86_data & (1<<1)) == 0)
{
/* yes */
LOG(("ram4 write protected\n"));
LOG("ram4 write protected\n");
/* ram is enabled and write protected */
space.nop_write(0x4000, 0x7fff);
}
else
{
LOG(("ram4 write enabled\n"));
LOG("ram4 write enabled\n");
/* ram is enabled and write enabled */
space.install_writeonly(0x4000, 0x7fff, m_ram_base + 0x4000);
@ -425,10 +426,10 @@ void kc85_4_state::update_0x04000()
}
else
{
LOG(("Module at 0x4000\n"));
LOG("Module at 0x4000\n");
space.install_read_handler (0x4000, 0x7fff, read8sm_delegate(*this, FUNC(kc_state::expansion_4000_r)), 0);
space.install_write_handler(0x4000, 0x7fff, write8sm_delegate(*this, FUNC(kc_state::expansion_4000_w)), 0);
space.install_read_handler (0x4000, 0x7fff, read8sm_delegate(*this, FUNC(kc85_4_state::expansion_4000_r)), 0);
space.install_write_handler(0x4000, 0x7fff, write8sm_delegate(*this, FUNC(kc85_4_state::expansion_4000_w)), 0);
}
}
@ -441,7 +442,7 @@ void kc85_4_state::update_0x0c000()
if (m_port_86_data & (1<<7))
{
/* CAOS rom takes priority */
LOG(("CAOS rom 0x0c000\n"));
LOG("CAOS rom 0x0c000\n");
space.install_rom(0xc000, 0xdfff, memregion("caos")->base());
space.unmap_write(0xc000, 0xdfff);
@ -451,7 +452,7 @@ void kc85_4_state::update_0x0c000()
if (m_pio_data[0] & (1<<7))
{
/* BASIC takes next priority */
LOG(("BASIC rom 0x0c000\n"));
LOG("BASIC rom 0x0c000\n");
int bank = memregion("basic")->bytes() == 0x8000 ? (m_port_86_data>>5) & 0x03 : 0;
@ -460,10 +461,10 @@ void kc85_4_state::update_0x0c000()
}
else
{
LOG(("Module at 0x0c000\n"));
LOG("Module at 0x0c000\n");
space.install_read_handler (0xc000, 0xdfff, read8sm_delegate(*this, FUNC(kc_state::expansion_c000_r)), 0);
space.install_write_handler(0xc000, 0xdfff, write8sm_delegate(*this, FUNC(kc_state::expansion_c000_w)), 0);
space.install_read_handler (0xc000, 0xdfff, read8sm_delegate(*this, FUNC(kc85_4_state::expansion_c000_r)), 0);
space.install_write_handler(0xc000, 0xdfff, write8sm_delegate(*this, FUNC(kc85_4_state::expansion_c000_w)), 0);
}
}
}
@ -475,7 +476,7 @@ void kc85_4_state::update_0x08000()
if (m_pio_data[0] & (1<<2))
{
/* IRM enabled - has priority over RAM8 enabled */
LOG(("IRM enabled\n"));
LOG("IRM enabled\n");
uint8_t* ram_page = &m_video_ram[(BIT(m_port_84_data, 2)<<15) | (BIT(m_port_84_data, 1)<<14)];
@ -484,7 +485,7 @@ void kc85_4_state::update_0x08000()
}
else if (m_pio_data[1] & (1<<5))
{
LOG(("RAM8 enabled\n"));
LOG("RAM8 enabled\n");
int ram8_block;
uint8_t *mem_ptr;
@ -511,14 +512,14 @@ void kc85_4_state::update_0x08000()
if ((m_pio_data[1] & (1<<6)) == 0)
{
/* ram8 is enabled and write protected */
LOG(("RAM8 write protected\n"));
LOG("RAM8 write protected\n");
space.nop_write(0x8000, 0xa7ff);
space.nop_write(0xa800, 0xbfff);
}
else
{
LOG(("RAM8 write enabled\n"));
LOG("RAM8 write enabled\n");
/* ram8 is enabled and write enabled */
space.install_writeonly(0x8000, 0xa7ff, mem_ptr);
@ -527,10 +528,10 @@ void kc85_4_state::update_0x08000()
}
else
{
LOG(("Module at 0x8000\n"));
LOG("Module at 0x8000\n");
space.install_read_handler(0x8000, 0xbfff, read8sm_delegate(*this, FUNC(kc_state::expansion_8000_r)), 0);
space.install_write_handler(0x8000, 0xbfff, write8sm_delegate(*this, FUNC(kc_state::expansion_8000_w)), 0);
space.install_read_handler(0x8000, 0xbfff, read8sm_delegate(*this, FUNC(kc85_4_state::expansion_8000_r)), 0);
space.install_write_handler(0x8000, 0xbfff, write8sm_delegate(*this, FUNC(kc85_4_state::expansion_8000_w)), 0);
}
}
@ -612,7 +613,8 @@ void kc85_3_state::pio_portb_w(uint8_t data)
void kc85_4_state::pio_portb_w(uint8_t data)
{
// reset tone flip-flops
if (((m_pio_data[1] & 1) == 1) & ((data & 1) == 0)) {
if (((m_pio_data[1] & 1) == 1) & ((data & 1) == 0))
{
m_k0_line = 0;
m_k1_line = 0;
}
@ -641,7 +643,7 @@ bit 0: BILD .display screen 0 or 1
void kc85_4_state::kc85_4_84_w(uint8_t data)
{
LOG(("0x84 W: %02x\n", data));
LOG("0x84 W: %02x\n", data);
m_port_84_data = data;
@ -668,7 +670,7 @@ bit 0: ACCESS RAM 4
void kc85_4_state::kc85_4_86_w(uint8_t data)
{
LOG(("0x86 W: %02x\n", data));
LOG("0x86 W: %02x\n", data);
m_port_86_data = data;
@ -829,3 +831,224 @@ void kc85_4_state::machine_reset()
m_port_84_data = 0x00;
m_port_86_data = 0x00;
}
// Initialise the palette
void kc_state::kc85_palette(palette_device &palette) const
{
// 3 bit colour value. bit 2->green, bit 1->red, bit 0->blue
static constexpr rgb_t kc85_pens[KC85_PALETTE_SIZE] =
{
// foreground colours, "full" of each component
{ 0x00, 0x00, 0x00 }, // black
{ 0x00, 0x00, 0xd0 }, // blue
{ 0xd0, 0x00, 0x00 }, // red
{ 0xd0, 0x00, 0xd0 }, // magenta
{ 0x00, 0xd0, 0x00 }, // green
{ 0x00, 0xd0, 0xd0 }, // cyan
{ 0xd0, 0xd0, 0x00 }, // yellow
{ 0xd0, 0xd0, 0xd0 }, // white
// full of each component + half of another component
{ 0x00, 0x00, 0x00 }, // black
{ 0x60, 0x00, 0xa0 }, // violet
{ 0xa0, 0x60, 0x00 }, // brown
{ 0xa0, 0x00, 0x60 }, // red/purple
{ 0x00, 0xa0, 0x60 }, // pastel green
{ 0x00, 0x60, 0xa0 }, // sky blue
{ 0xa0, 0xa0, 0x60 }, // yellow/green
{ 0xd0, 0xd0, 0xd0 }, // white
// background colours are slightly darker than foreground colours
{ 0x00, 0x00, 0x00 }, // black
{ 0x00, 0x00, 0xa0 }, // dark blue
{ 0xa0, 0x00, 0x00 }, // dark red
{ 0xa0, 0x00, 0xa0 }, // dark magenta
{ 0x00, 0xa0, 0x00 }, // dark green
{ 0x00, 0xa0, 0xa0 }, // dark cyan
{ 0xa0, 0xa0, 0x00 }, // dark yellow
{ 0xa0, 0xa0, 0xa0 } // dark white (grey)
};
palette.set_pen_colors(0, kc85_pens);
}
/* set new blink state */
WRITE_LINE_MEMBER( kc_state::video_toggle_blink_state )
{
if (state)
{
m_screen->update_partial(m_screen->vpos());
m_kc85_blink_state = !m_kc85_blink_state;
}
}
/* draw 8 pixels */
void kc_state::video_draw_8_pixels(bitmap_ind16 &bitmap, int x, int y, uint8_t colour_byte, uint8_t gfx_byte)
{
if (m_high_resolution)
{
/* High resolution: 4 colors for block */
int const pens[4] = {
0, // black
2, // red
5, // cyan
7 }; // white
int px = x;
for (int a = 0; a < 8; a++)
{
int pen = pens[((gfx_byte>>7) & 0x07) | ((colour_byte>>6) & 0x02)];
if ((px >= 0) && (px < bitmap.width()) && (y >= 0) && (y < bitmap.height()))
{
bitmap.pix(y, px) = pen;
}
px++;
colour_byte <<= 1;
gfx_byte <<= 1;
}
}
else
{
/* Low resolution: 2 colors for block */
/* 16 foreground colours, 8 background colours */
/* bit 7 = 1: flash between foreground and background colour 0: no flash */
/* bit 6: adjusts foreground colours by adding half of another component */
/* bit 5,4,3 = foreground colour */
/* bit 5: background colour -> Green */
/* bit 4: background colour -> Red */
/* bit 3: background colour -> Blue */
/* bit 2,1,0 = background colour */
/* bit 2: background colour -> Green */
/* bit 1: background colour -> Red */
/* bit 0: background colour -> Blue */
int background_pen = (colour_byte&7) + 16;
int foreground_pen = ((colour_byte>>3) & 0x0f);
if ((colour_byte & 0x80) && m_kc85_blink_state && (m_pio_data[1] & 0x80))
{
foreground_pen = background_pen;
}
int const pens[2] = { background_pen, foreground_pen };
int px = x;
for (int a = 0; a < 8; a++)
{
int pen = pens[(gfx_byte >> 7) & 0x01];
if ((px >= 0) && (px < bitmap.width()) && (y >= 0) && (y < bitmap.height()))
{
bitmap.pix(y, px) = pen;
}
px++;
gfx_byte <<= 1;
}
}
}
/***************************************************************************
KC85/4 video hardware
***************************************************************************/
void kc85_4_state::video_start()
{
m_video_ram = make_unique_clear<uint8_t[]>((KC85_4_SCREEN_COLOUR_RAM_SIZE*2) + (KC85_4_SCREEN_PIXEL_RAM_SIZE*2));
m_display_video_ram = &m_video_ram[0];
m_kc85_blink_state = 0;
}
void kc85_4_state::video_control_w(int data)
{
/* calculate address of video ram to display */
if (data & 1)
m_display_video_ram = &m_video_ram[KC85_4_SCREEN_PIXEL_RAM_SIZE + KC85_4_SCREEN_COLOUR_RAM_SIZE];
else
m_display_video_ram = &m_video_ram[0];
m_high_resolution = (data & 0x08) ? 0 : 1;
}
uint32_t kc85_4_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
uint8_t const *const pixel_ram = m_display_video_ram;
uint8_t const *const colour_ram = pixel_ram + 0x04000;
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
for (int x = 0; x< (KC85_SCREEN_WIDTH >> 3); x++)
{
uint16_t const offset = y | (x<<8);
uint8_t const colour_byte = colour_ram[offset];
uint8_t const gfx_byte = pixel_ram[offset];
video_draw_8_pixels(bitmap, (x<<3), y, colour_byte, gfx_byte);
}
}
return 0;
}
/***************************************************************************
KC85/3 video
***************************************************************************/
void kc_state::video_start()
{
m_video_ram = make_unique_clear<uint8_t[]>(0x4000);
m_kc85_blink_state = 0;
}
uint32_t kc_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
/* colour ram takes up 0x02800 bytes */
uint8_t const *const pixel_ram = &m_video_ram[0];
uint8_t const *const colour_ram = &m_video_ram[0x2800];
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
{
for (int x = 0; x< (KC85_SCREEN_WIDTH >> 3); x++)
{
int pixel_offset,colour_offset;
if ((x & 0x020)==0)
{
pixel_offset = (x & 0x01f) | (((y>>2) & 0x03)<<5) |
((y & 0x03)<<7) | (((y>>4) & 0x0f)<<9);
colour_offset = (x & 0x01f) | (((y>>2) & 0x03f)<<5);
}
else
{
/* 1 0 1 0 0 V7 V6 V1 V0 V3 V2 V5 V4 H2 H1 H0 */
/* 1 0 1 1 0 0 0 V7 V6 V3 V2 V5 V4 H2 H1 H0 */
pixel_offset = 0x02000+((x & 0x07) | (((y>>4) & 0x03)<<3) |
(((y>>2) & 0x03)<<5) | ((y & 0x03)<<7) | ((y>>6) & 0x03)<<9);
colour_offset = 0x0800+((x & 0x07) | (((y>>4) & 0x03)<<3) |
(((y>>2) & 0x03)<<5) | ((y>>6) & 0x03)<<7);
}
uint8_t const colour_byte = colour_ram[colour_offset];
uint8_t const gfx_byte = pixel_ram[pixel_offset];
video_draw_8_pixels(bitmap,(x<<3),y, colour_byte, gfx_byte);
}
}
return 0;
}

View File

@ -1,236 +0,0 @@
// license:GPL-2.0+
// copyright-holders:Kevin Thacker,Sandro Ronco
/***************************************************************************
kc.c
Functions to emulate the video hardware of the kc85/4,kc85/3
***************************************************************************/
#include "emu.h"
#include "kc.h"
#include "screen.h"
// 3 bit colour value. bit 2->green, bit 1->red, bit 0->blue
static constexpr rgb_t kc85_pens[KC85_PALETTE_SIZE] =
{
// foreground colours, "full" of each component
{ 0x00, 0x00, 0x00 }, // black
{ 0x00, 0x00, 0xd0 }, // blue
{ 0xd0, 0x00, 0x00 }, // red
{ 0xd0, 0x00, 0xd0 }, // magenta
{ 0x00, 0xd0, 0x00 }, // green
{ 0x00, 0xd0, 0xd0 }, // cyan
{ 0xd0, 0xd0, 0x00 }, // yellow
{ 0xd0, 0xd0, 0xd0 }, // white
// full of each component + half of another component
{ 0x00, 0x00, 0x00 }, // black
{ 0x60, 0x00, 0xa0 }, // violet
{ 0xa0, 0x60, 0x00 }, // brown
{ 0xa0, 0x00, 0x60 }, // red/purple
{ 0x00, 0xa0, 0x60 }, // pastel green
{ 0x00, 0x60, 0xa0 }, // sky blue
{ 0xa0, 0xa0, 0x60 }, // yellow/green
{ 0xd0, 0xd0, 0xd0 }, // white
// background colours are slightly darker than foreground colours
{ 0x00, 0x00, 0x00 }, // black
{ 0x00, 0x00, 0xa0 }, // dark blue
{ 0xa0, 0x00, 0x00 }, // dark red
{ 0xa0, 0x00, 0xa0 }, // dark magenta
{ 0x00, 0xa0, 0x00 }, // dark green
{ 0x00, 0xa0, 0xa0 }, // dark cyan
{ 0xa0, 0xa0, 0x00 }, // dark yellow
{ 0xa0, 0xa0, 0xa0 } // dark white (grey)
};
// Initialise the palette
void kc_state::kc85_palette(palette_device &palette) const
{
palette.set_pen_colors(0, kc85_pens);
}
/* set new blink state */
WRITE_LINE_MEMBER( kc_state::video_toggle_blink_state )
{
if (state)
{
m_screen->update_partial(m_screen->vpos());
m_kc85_blink_state = !m_kc85_blink_state;
}
}
/* draw 8 pixels */
void kc_state::video_draw_8_pixels(bitmap_ind16 &bitmap, int x, int y, uint8_t colour_byte, uint8_t gfx_byte)
{
if (m_high_resolution)
{
/* High resolution: 4 colors for block */
int const pens[4] = {
0, // black
2, // red
5, // cyan
7 }; // white
int px = x;
for (int a=0; a<8; a++)
{
int pen = pens[((gfx_byte>>7) & 0x07) | ((colour_byte>>6) & 0x02)];
if ((px >= 0) && (px < bitmap.width()) && (y >= 0) && (y < bitmap.height()))
{
bitmap.pix(y, px) = pen;
}
px++;
colour_byte <<= 1;
gfx_byte <<= 1;
}
}
else
{
/* Low resolution: 2 colors for block */
/* 16 foreground colours, 8 background colours */
/* bit 7 = 1: flash between foreground and background colour 0: no flash */
/* bit 6: adjusts foreground colours by adding half of another component */
/* bit 5,4,3 = foreground colour */
/* bit 5: background colour -> Green */
/* bit 4: background colour -> Red */
/* bit 3: background colour -> Blue */
/* bit 2,1,0 = background colour */
/* bit 2: background colour -> Green */
/* bit 1: background colour -> Red */
/* bit 0: background colour -> Blue */
int background_pen = (colour_byte&7) + 16;
int foreground_pen = ((colour_byte>>3) & 0x0f);
if ((colour_byte & 0x80) && m_kc85_blink_state && (m_pio_data[1] & 0x80))
{
foreground_pen = background_pen;
}
int const pens[2] = { background_pen, foreground_pen };
int px = x;
for (int a=0; a<8; a++)
{
int pen = pens[(gfx_byte>>7) & 0x01];
if ((px >= 0) && (px < bitmap.width()) && (y >= 0) && (y < bitmap.height()))
{
bitmap.pix(y, px) = pen;
}
px++;
gfx_byte <<= 1;
}
}
}
/***************************************************************************
KC85/4 video hardware
***************************************************************************/
void kc85_4_state::video_start()
{
m_video_ram = make_unique_clear<uint8_t[]>((KC85_4_SCREEN_COLOUR_RAM_SIZE*2) + (KC85_4_SCREEN_PIXEL_RAM_SIZE*2));
m_display_video_ram = &m_video_ram[0];
m_kc85_blink_state = 0;
}
void kc85_4_state::video_control_w(int data)
{
/* calculate address of video ram to display */
if (data & 1)
m_display_video_ram = &m_video_ram[KC85_4_SCREEN_PIXEL_RAM_SIZE + KC85_4_SCREEN_COLOUR_RAM_SIZE];
else
m_display_video_ram = &m_video_ram[0];
m_high_resolution = (data & 0x08) ? 0 : 1;
}
uint32_t kc85_4_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
uint8_t *pixel_ram = m_display_video_ram;
uint8_t *colour_ram = pixel_ram + 0x04000;
for (int y=cliprect.min_y; y<=cliprect.max_y; y++)
{
for (int x=0; x<(KC85_SCREEN_WIDTH>>3); x++)
{
uint16_t offset = y | (x<<8);
uint8_t colour_byte = colour_ram[offset];
uint8_t gfx_byte = pixel_ram[offset];
video_draw_8_pixels(bitmap, (x<<3), y, colour_byte, gfx_byte);
}
}
return 0;
}
/***************************************************************************
KC85/3 video
***************************************************************************/
void kc_state::video_start()
{
m_video_ram = make_unique_clear<uint8_t[]>(0x4000);
m_kc85_blink_state = 0;
}
uint32_t kc_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
/* colour ram takes up 0x02800 bytes */
uint8_t *pixel_ram = &m_video_ram[0];
uint8_t *colour_ram = &m_video_ram[0x2800];
for (int y=cliprect.min_y; y<=cliprect.max_y; y++)
{
for (int x=0; x<(KC85_SCREEN_WIDTH>>3); x++)
{
int pixel_offset,colour_offset;
if ((x & 0x020)==0)
{
pixel_offset = (x & 0x01f) | (((y>>2) & 0x03)<<5) |
((y & 0x03)<<7) | (((y>>4) & 0x0f)<<9);
colour_offset = (x & 0x01f) | (((y>>2) & 0x03f)<<5);
}
else
{
/* 1 0 1 0 0 V7 V6 V1 V0 V3 V2 V5 V4 H2 H1 H0 */
/* 1 0 1 1 0 0 0 V7 V6 V3 V2 V5 V4 H2 H1 H0 */
pixel_offset = 0x02000+((x & 0x07) | (((y>>4) & 0x03)<<3) |
(((y>>2) & 0x03)<<5) | ((y & 0x03)<<7) | ((y>>6) & 0x03)<<9);
colour_offset = 0x0800+((x & 0x07) | (((y>>4) & 0x03)<<3) |
(((y>>2) & 0x03)<<5) | ((y>>6) & 0x03)<<7);
}
uint8_t colour_byte = colour_ram[colour_offset];
uint8_t gfx_byte = pixel_ram[pixel_offset];
video_draw_8_pixels(bitmap,(x<<3),y, colour_byte, gfx_byte);
}
}
return 0;
}