summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/bert.cpp
blob: b175a3efad70e57b1e80f509b08ac9b274a63a2b (plain) (tree)
1
2
3
4
5
6
7
8






                                                                
                                                                           




                 
                                                                       



                                                                                                    





                                   

                                   

                                    
                                        




                                

                      

                           




                                                                                      

 




                                          

                                    




                                        
                                    
                                                   
















                                                                                                 

 
                                                              
 


                                         
                                                                                         


                       
                   
                                                         





                                         
 
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay

/*
 * An emulation of the BERT ASIC found in the NCD 16 X terminal.
 *
 * Sources:
 *   - none known, but there's a full simulation in the firmware to test it
 */

#include "emu.h"
#include "bert.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)
	: device_t(mconfig, BERT, tag, owner, clock)
	, m_memory_space(*this, finder_base::DUMMY_TAG, 24, 16)
{
}

void bert_device::device_start()
{
	save_item(NAME(m_control));
	save_item(NAME(m_history));
	save_item(NAME(m_step));
	save_item(NAME(m_qlc_mode));
	save_item(NAME(m_qlc_src));
	m_memory_space->cache(m_memory);
}

void bert_device::device_reset()
{
	m_control = 0;
	m_history = 0;
	m_step = 0;
	m_qlc_mode = false;
	m_qlc_src = 0;
}

void bert_device::map(address_map &map)
{
	map(0x000000, 0x7fffff).rw(FUNC(bert_device::read), FUNC(bert_device::write));
}

void bert_device::set_qlc_mode(bool state)
{
	m_qlc_mode = state;
}

u16 bert_device::read(offs_t offset)
{
	if(m_qlc_mode) {
		m_qlc_src = offset << 1;
		return 0;
	}

	constexpr u16 type = 0x00ca;
	u16 data = m_memory.read_word(offset << 1);
	u16 res;

	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;
	}

	m_step = (m_step + 1) & 3;

	return res;
}

void bert_device::write(offs_t offset, u16 data, u16 mem_mask)
{
	if(m_qlc_mode) {
		u32 dest = offset << 1;
		for(u32 i=0; i<512; i+=2)
			m_memory.write_word(dest + i, m_memory.read_word(m_qlc_src + i));
		return;
	}

	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;
	}
}