bert: fix it (nw)

This commit is contained in:
Olivier Galibert 2019-06-27 15:39:45 +02:00
parent c05e716513
commit 379bba82b6
2 changed files with 33 additions and 39 deletions

View File

@ -5,21 +5,12 @@
* An emulation of the BERT ASIC found in the NCD 16 X terminal.
*
* Sources:
* - none known
*
* TODO:
* - shift amounts greater than 16
* - other control bits
* - none known, but there's a full simulation in the firmware to test it
*/
#include "emu.h"
#include "bert.h"
#define LOG_GENERAL (1U << 0)
//#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(BERT, bert_device, "ncd_bert_asic", "NCD BERT ASIC")
bert_device::bert_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@ -32,7 +23,8 @@ bert_device::bert_device(const machine_config &mconfig, const char *tag, device_
void bert_device::device_start()
{
save_item(NAME(m_control));
save_item(NAME(m_shifter));
save_item(NAME(m_history));
save_item(NAME(m_step));
m_memory = m_memory_space->cache<1, 0, ENDIANNESS_BIG>();
}
@ -40,44 +32,46 @@ void bert_device::device_start()
void bert_device::device_reset()
{
m_control = 0;
m_shifter = 0;
m_history = 0;
m_step = 0;
}
void bert_device::map(address_map &map)
{
map(0x000000, 0x7fffff).rw(FUNC(bert_device::read), FUNC(bert_device::write));
map(0x000000, 0x000001).lw16("control", [this](u16 data) { LOG("control 0x%04x\n", data); m_control = data; });
}
u16 bert_device::read(offs_t offset)
{
u16 const data = m_memory->read_word(offset << 1);
unsigned const shift = m_control & 0x1f;
u16 const mask_r = (1 << shift) - 1;
constexpr u16 type = 0x00ca;
u16 data = m_memory->read_word(offset << 1);
u16 res;
u16 result = (m_shifter << (16 - shift)) | (data >> shift);
m_shifter = data & mask_r;
if(type & (1 << (((m_control >> 8) & 0xc) | m_step))) {
// mask
res = m_control & 0x200 ? ~data : data;
} else {
// data
u32 tmp = m_control & 0x10 ? (data << 16) | m_history : (m_history << 16) | data;
res = tmp >> (m_control & 15);
if(m_control & 0x100)
res = ~res;
m_history = m_control & 0x1000 ? 0 : data;
}
if (BIT(m_control, 8))
result = ~result;
m_step = (m_step + 1) & 3;
LOG("r 0x%06x 0x%04x 0x%04x 0x%04x (%s)\n", offset << 1, data, result, m_shifter, machine().describe_context());
return result;
return res;
}
void bert_device::write(offs_t offset, u16 data)
void bert_device::write(offs_t offset, u16 data, u16 mem_mask)
{
unsigned const shift = m_control & 0x1f;
u16 const mask_r = (1 << shift) - 1;
u16 result = (data << shift) | (m_shifter & mask_r);
m_shifter = data >> (16 - shift);
if (BIT(m_control, 8))
result = ~result;
LOG("w 0x%06x 0x%04x 0x%04x 0x%04x (%s)\n", offset << 1, data, result, m_shifter, machine().describe_context());
m_memory->write_word(offset << 1, result);
m_step = 0;
m_memory->write_word(offset << 1, data, mem_mask);
if(!offset) {
COMBINE_DATA(&m_control);
m_step = 0;
if(m_control & 0x1000)
m_history = 0;
}
}

View File

@ -14,7 +14,6 @@ public:
bert_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
void map(address_map &map);
protected:
@ -22,14 +21,15 @@ protected:
virtual void device_reset() override;
u16 read(offs_t offset);
void write(offs_t offset, u16 data);
void write(offs_t offset, u16 data, u16 mem_mask);
private:
required_address_space m_memory_space;
memory_access_cache<1, 0, ENDIANNESS_BIG> *m_memory;
u16 m_control;
u16 m_shifter;
u16 m_history;
u32 m_step;
};
DECLARE_DEVICE_TYPE(BERT, bert_device)