mirror of
https://github.com/holub/mame
synced 2025-04-26 10:13:37 +03:00
Merge branch 'master' of https://github.com/mamedev/mame
This commit is contained in:
commit
72be63e246
@ -193,8 +193,6 @@ function cheat.startplugin()
|
||||
return
|
||||
end
|
||||
|
||||
local function is_oneshot(cheat) return cheat.script and not cheat.script.run and not cheat.script.off end
|
||||
|
||||
local function run_if(cheat, func)
|
||||
if func then
|
||||
local stat, err = pcall(func)
|
||||
@ -293,7 +291,7 @@ function cheat.startplugin()
|
||||
end
|
||||
|
||||
local function bpset(cheat, dev, addr, func)
|
||||
if is_oneshot(cheat) then
|
||||
if cheat:is_oneshot() then
|
||||
error("bpset not permitted in oneshot cheat")
|
||||
return
|
||||
end
|
||||
@ -302,7 +300,7 @@ function cheat.startplugin()
|
||||
end
|
||||
|
||||
local function wpset(cheat, dev, space, wptype, addr, len, func)
|
||||
if is_oneshot(cheat) then
|
||||
if cheat:is_oneshot() then
|
||||
error("wpset not permitted in oneshot cheat")
|
||||
return
|
||||
end
|
||||
@ -333,7 +331,7 @@ function cheat.startplugin()
|
||||
local function input_trans(list)
|
||||
local xlate = { start = {}, stop = {}, last = 0 }
|
||||
local function errout(port, field)
|
||||
cheat.enabled = false
|
||||
cheat:set_enabled(false)
|
||||
error(port .. field .. " not found")
|
||||
return
|
||||
end
|
||||
@ -369,7 +367,7 @@ function cheat.startplugin()
|
||||
end
|
||||
|
||||
local function input_run(cheat, list)
|
||||
if not is_oneshot(cheat) then
|
||||
if not cheat:is_oneshot() then
|
||||
cheat.enabled = false
|
||||
error("input_run only allowed in one shot cheats")
|
||||
return
|
||||
@ -379,6 +377,72 @@ function cheat.startplugin()
|
||||
inputs[#inputs + 1] = list
|
||||
end
|
||||
|
||||
local function param_calc(param)
|
||||
if param.item then
|
||||
if not param.item[param.index] then -- uh oh
|
||||
param.index = 1
|
||||
end
|
||||
param.value = param.item[param.index].value
|
||||
return
|
||||
end
|
||||
param.value = param.min + (param.step * (param.index - 1))
|
||||
if param.value > param.max then
|
||||
param.value = param.max
|
||||
end
|
||||
end
|
||||
|
||||
-- return is current state, ui change
|
||||
local function set_enabled(cheat, state)
|
||||
if cheat:is_oneshot() then
|
||||
if state then
|
||||
if cheat.parameter and cheat.script.change and cheat.parameter.index ~= 0 then
|
||||
param_calc(cheat.parameter)
|
||||
cheat.cheat_env.param = cheat.parameter.value
|
||||
cheat.script.change()
|
||||
elseif not cheat.parameter and cheat.script.on then
|
||||
cheat.script.on()
|
||||
end
|
||||
end
|
||||
return false, false
|
||||
end
|
||||
if cheat.enabled == state then
|
||||
return state, false
|
||||
end
|
||||
if not state then
|
||||
cheat.enabled = false
|
||||
run_if(cheat, cheat.script.off)
|
||||
bwpclr(cheat)
|
||||
else
|
||||
cheat.enabled = true
|
||||
run_if(cheat, cheat.script.on)
|
||||
end
|
||||
return state, true
|
||||
end
|
||||
|
||||
-- return is current index, ui change
|
||||
local function set_index(cheat, index)
|
||||
local param = cheat.parameter
|
||||
local oldindex = param.index
|
||||
if (param.index < 0) or (param.index >= param.last) or (param.index == index) then
|
||||
return param.index, false
|
||||
end
|
||||
param.index = index
|
||||
if index == 0 then
|
||||
cheat.cheat_env.param = param.min
|
||||
cheat:set_enabled(false)
|
||||
else
|
||||
if oldindex == 0 then
|
||||
cheat:set_enabled(true)
|
||||
end
|
||||
param_calc(param)
|
||||
cheat.cheat_env.param = param.value
|
||||
if not cheat:is_oneshot() then
|
||||
run_if(cheat, cheat.script.change)
|
||||
end
|
||||
end
|
||||
return index, true
|
||||
end
|
||||
|
||||
local function parse_cheat(cheat)
|
||||
cheat.cheat_env = { draw_text = draw_text,
|
||||
draw_line = draw_line,
|
||||
@ -396,6 +460,9 @@ function cheat.startplugin()
|
||||
{ insert = table.insert,
|
||||
remove = table.remove } }
|
||||
cheat.enabled = false
|
||||
cheat.set_enabled = set_enabled;
|
||||
cheat.get_enabled = function(cheat) return cheat.enabled end
|
||||
cheat.is_oneshot = function(cheat) return cheat.script and not cheat.script.run and not cheat.script.off end
|
||||
|
||||
-- verify scripts are valid first
|
||||
if not cheat.script then
|
||||
@ -500,6 +567,24 @@ function cheat.startplugin()
|
||||
if not param then
|
||||
return
|
||||
end
|
||||
cheat.set_index = set_index;
|
||||
cheat.set_value = function(cheat, value)
|
||||
local idx = ((value - cheat.parameter.min) / cheat.parameter.step) + 1
|
||||
local chg = false
|
||||
if math.integer(idx) == idx then
|
||||
idx, chg = cheat:set_index(idx)
|
||||
end
|
||||
return cheat.parameter.value, chg
|
||||
end
|
||||
cheat.get_index = function(cheat) return cheat.parameter.index end
|
||||
cheat.get_value = function(cheat) return cheat.parameter.value end
|
||||
cheat.get_text = function(cheat)
|
||||
if cheat.parameter.item then
|
||||
return cheat.parameter.item[cheat.parameter.index]
|
||||
else
|
||||
return cheat.parameter.value
|
||||
end
|
||||
end
|
||||
param.min = tonumber(param.min) or 0
|
||||
param.max = tonumber(param.max) or #param.item
|
||||
param.step = tonumber(param.step) or 1
|
||||
@ -508,7 +593,7 @@ function cheat.startplugin()
|
||||
if not item.value then
|
||||
item.value = (count * param.step) + param.min
|
||||
else
|
||||
item.value = tonumber(item.value)
|
||||
item.value = tonumber(item.value)
|
||||
end
|
||||
end
|
||||
param.last = #param.item
|
||||
@ -579,7 +664,7 @@ function cheat.startplugin()
|
||||
end
|
||||
menu[num][2] = ""
|
||||
menu[num][3] = "off"
|
||||
elseif is_oneshot(cheat) then
|
||||
elseif cheat:is_oneshot() then
|
||||
menu[num][2] = _("Set")
|
||||
menu[num][3] = 0
|
||||
else
|
||||
@ -593,7 +678,7 @@ function cheat.startplugin()
|
||||
end
|
||||
else
|
||||
if cheat.parameter.index == 0 then
|
||||
if is_oneshot(cheat) then
|
||||
if cheat:is_oneshot() then
|
||||
menu[num][2] = _("Set")
|
||||
else
|
||||
menu[num][2] = _("Off")
|
||||
@ -640,22 +725,12 @@ function cheat.startplugin()
|
||||
hotkeymenu = true
|
||||
elseif index == 3 then
|
||||
for num, cheat in pairs(cheats) do
|
||||
if cheat.enabled then
|
||||
run_if(cheat, cheat.script.off)
|
||||
bwpclr(cheat)
|
||||
end
|
||||
cheat.enabled = false
|
||||
if cheat.parameter then
|
||||
cheat.parameter.value = cheat.parameter.min
|
||||
cheat.parameter.index = 0
|
||||
end
|
||||
cheat:set_enabled(false)
|
||||
cheat:set_index(0)
|
||||
end
|
||||
elseif index == 4 then
|
||||
for num, cheat in pairs(cheats) do
|
||||
if cheat.enabled then
|
||||
run_if(cheat, cheat.script.off)
|
||||
bwpclr(cheat)
|
||||
end
|
||||
cheat:set_enabled(false)
|
||||
end
|
||||
cheats = load_cheats()
|
||||
for num, cheat in pairs(cheats) do
|
||||
@ -666,20 +741,6 @@ function cheat.startplugin()
|
||||
return true
|
||||
end
|
||||
|
||||
local function param_calc(param)
|
||||
if param.item then
|
||||
if not param.item[param.index] then -- uh oh
|
||||
param.index = 1
|
||||
end
|
||||
param.value = param.item[param.index].value
|
||||
return
|
||||
end
|
||||
param.value = param.min + (param.step * (param.index - 1))
|
||||
if param.value > param.max then
|
||||
param.value = param.max
|
||||
end
|
||||
end
|
||||
|
||||
local cheat = cheats[index]
|
||||
if not cheat then
|
||||
return false
|
||||
@ -690,72 +751,31 @@ function cheat.startplugin()
|
||||
end
|
||||
elseif event == "left" then
|
||||
if cheat.parameter then
|
||||
local param = cheat.parameter
|
||||
if param.index == 1 then
|
||||
param.index = 0
|
||||
cheat.enabled = false
|
||||
cheat.cheat_env.param = param.min
|
||||
run_if(cheat, cheat.script.off)
|
||||
bwpclr(cheat)
|
||||
return true
|
||||
elseif param.index == 0 then
|
||||
return false
|
||||
end
|
||||
param.index = param.index - 1
|
||||
param_calc(param)
|
||||
cheat.cheat_env.param = param.value
|
||||
if not is_oneshot(cheat) then
|
||||
run_if(cheat, cheat.script.change)
|
||||
end
|
||||
return true
|
||||
local idx, chg = cheat:set_index(cheat:get_index() - 1)
|
||||
return chg
|
||||
else
|
||||
if cheat.enabled and not is_oneshot(cheat) then
|
||||
cheat.enabled = false
|
||||
run_if(cheat, cheat.script.off)
|
||||
bwpclr(cheat)
|
||||
return true
|
||||
if not cheat:is_oneshot() then
|
||||
return cheat:set_enabled(false)
|
||||
end
|
||||
return false
|
||||
end
|
||||
elseif event == "right" then
|
||||
if cheat.parameter then
|
||||
local param = cheat.parameter
|
||||
if param.index == 0 then
|
||||
cheat.enabled = true
|
||||
run_if(cheat, cheat.script.on)
|
||||
elseif param.index == param.last then
|
||||
return false
|
||||
end
|
||||
param.index = param.index + 1
|
||||
param_calc(param)
|
||||
cheat.cheat_env.param = param.value
|
||||
if not is_oneshot(cheat) then
|
||||
run_if(cheat, cheat.script.change)
|
||||
end
|
||||
return true
|
||||
local idx, chd = cheat:set_index(cheat:get_index() + 1)
|
||||
return chd
|
||||
else
|
||||
if not cheat.enabled and not is_oneshot(cheat) then
|
||||
cheat.enabled = true
|
||||
run_if(cheat, cheat.script.on)
|
||||
return true
|
||||
if not cheat:is_oneshot() then
|
||||
local state, chg = cheat:set_enabled(true)
|
||||
return chg
|
||||
end
|
||||
return false
|
||||
end
|
||||
elseif event == "select" then
|
||||
if is_oneshot(cheat) then
|
||||
if cheat.parameter and cheat.script.change and cheat.parameter.index ~= 0 then
|
||||
param_calc(cheat.parameter)
|
||||
cheat.cheat_env.param = cheat.parameter.value
|
||||
cheat.script.change()
|
||||
local subtext
|
||||
if cheat.parameter.item then
|
||||
subtext = cheat.parameter.item[cheat.parameter.index]
|
||||
else
|
||||
subtext = cheat.parameter.value
|
||||
end
|
||||
manager:machine():popmessage(string.format(_("Activated: %s = %s"), cheat.desc, subtext))
|
||||
if cheat:is_oneshot() then
|
||||
cheat:set_enabled(true)
|
||||
if cheat.parameter and cheat.script.change and cheat:get_index() ~= 0 then
|
||||
manager:machine():popmessage(string.format(_("Activated: %s = %s"), cheat.desc, cheat:get_text()))
|
||||
elseif not cheat.parameter and cheat.script.on then
|
||||
cheat.script.on()
|
||||
manager:machine():popmessage(string.format(_("Activated: %s"), cheat.desc))
|
||||
end
|
||||
end
|
||||
@ -810,7 +830,7 @@ function cheat.startplugin()
|
||||
if cheat.hotkeys and cheat.hotkeys.keys then
|
||||
if manager:machine():input():seq_pressed(cheat.hotkeys.keys) then
|
||||
if not cheat.hotkeys.pressed then
|
||||
if is_oneshot(cheat) then
|
||||
if cheat:is_oneshot() then
|
||||
if not run_if(cheat, cheat.script.change) then
|
||||
run_if(cheat, cheat.script.on)
|
||||
end
|
||||
|
@ -348,8 +348,8 @@
|
||||
#define LOG_EXTRA 0
|
||||
#define LOG_IOT_EXTRA 0
|
||||
|
||||
#define READ_PDP_18BIT(A) ((signed)m_program->read_dword((A)<<2))
|
||||
#define WRITE_PDP_18BIT(A,V) (m_program->write_dword((A)<<2,(V)))
|
||||
#define READ_PDP_18BIT(A) ((signed)m_program->read_dword(A))
|
||||
#define WRITE_PDP_18BIT(A,V) (m_program->write_dword((A),(V)))
|
||||
|
||||
|
||||
#define PC m_pc
|
||||
@ -378,12 +378,15 @@
|
||||
#define PREVIOUS_PC ((PC & ADDRESS_EXTENSION_MASK) | ((PC-1) & BASE_ADDRESS_MASK))
|
||||
|
||||
|
||||
DEFINE_DEVICE_TYPE(PDP1, pdp1_device, "pdp1_cpu", "DEC PDP1")
|
||||
DEFINE_DEVICE_TYPE(PDP1, pdp1_device, "pdp1_cpu", "DEC PDP-1 Central Processor")
|
||||
|
||||
|
||||
pdp1_device::pdp1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: cpu_device(mconfig, PDP1, tag, owner, clock)
|
||||
, m_program_config("program", ENDIANNESS_BIG, 32, 18, 0)
|
||||
, m_program_config("program", ENDIANNESS_BIG, 32, 18, -2) // data is actually 18 bits wide
|
||||
, m_extern_iot(64, iot_delegate(*this))
|
||||
, m_read_binary_word(*this)
|
||||
, m_io_sc_callback(*this)
|
||||
{
|
||||
m_program_config.m_is_octal = true;
|
||||
}
|
||||
@ -405,16 +408,9 @@ void pdp1_device::device_config_complete()
|
||||
// or initialize to defaults if none provided
|
||||
else
|
||||
{
|
||||
memset(&read_binary_word, 0, sizeof(read_binary_word));
|
||||
memset(&io_sc_callback, 0, sizeof(io_sc_callback));
|
||||
extend_support = 0;
|
||||
hw_mul_div = 0;
|
||||
type_20_sbs = 0;
|
||||
|
||||
for (auto & elem : extern_iot)
|
||||
{
|
||||
memset(&elem, 0, sizeof(elem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,34 +491,6 @@ void pdp1_device::execute_set_input(int irqline, int state)
|
||||
}
|
||||
|
||||
|
||||
static void null_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
|
||||
{
|
||||
pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device);
|
||||
|
||||
pdp1->pdp1_null_iot(op2, nac, mb, io, ac);
|
||||
}
|
||||
|
||||
static void lem_eem_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
|
||||
{
|
||||
pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device);
|
||||
|
||||
pdp1->pdp1_lem_eem_iot(op2, nac, mb, io, ac);
|
||||
}
|
||||
|
||||
static void sbs_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
|
||||
{
|
||||
pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device);
|
||||
|
||||
pdp1->pdp1_sbs_iot(op2, nac, mb, io, ac);
|
||||
}
|
||||
|
||||
static void type_20_sbs_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
|
||||
{
|
||||
pdp1_device *pdp1 = dynamic_cast<pdp1_device*>(device);
|
||||
|
||||
pdp1->pdp1_type_20_sbs_iot(op2, nac, mb, io, ac);
|
||||
}
|
||||
|
||||
void pdp1_device::device_start()
|
||||
{
|
||||
int i;
|
||||
@ -569,12 +537,12 @@ void pdp1_device::device_start()
|
||||
/* set up params and callbacks */
|
||||
for (i=0; i<64; i++)
|
||||
{
|
||||
m_extern_iot[i] = (extern_iot[i])
|
||||
? extern_iot[i]
|
||||
: null_iot;
|
||||
m_extern_iot[i].resolve();
|
||||
if (m_extern_iot[i].isnull())
|
||||
m_extern_iot[i] = iot_delegate(*this, FUNC(pdp1_device::null_iot));
|
||||
}
|
||||
m_read_binary_word = read_binary_word;
|
||||
m_io_sc_callback = io_sc_callback;
|
||||
m_read_binary_word.resolve();
|
||||
m_io_sc_callback.resolve();
|
||||
m_extend_support = extend_support;
|
||||
m_hw_mul_div = hw_mul_div;
|
||||
m_type_20_sbs = type_20_sbs;
|
||||
@ -599,13 +567,13 @@ void pdp1_device::device_start()
|
||||
|
||||
if (m_extend_support)
|
||||
{
|
||||
m_extern_iot[074] = lem_eem_iot;
|
||||
m_extern_iot[074] = iot_delegate(*this, FUNC(pdp1_device::lem_eem_iot));
|
||||
}
|
||||
m_extern_iot[054] = m_extern_iot[055] = m_extern_iot[056] = sbs_iot;
|
||||
m_extern_iot[054] = m_extern_iot[055] = m_extern_iot[056] = iot_delegate(*this, FUNC(pdp1_device::sbs_iot));
|
||||
if (m_type_20_sbs)
|
||||
{
|
||||
m_extern_iot[050] = m_extern_iot[051] = m_extern_iot[052] = m_extern_iot[053]
|
||||
= type_20_sbs_iot;
|
||||
= iot_delegate(*this, FUNC(pdp1_device::type_20_sbs_iot));
|
||||
}
|
||||
|
||||
state_add( PDP1_PC, "PC", m_pc).formatstr("%06O");
|
||||
@ -796,9 +764,6 @@ void pdp1_device::execute_run()
|
||||
{
|
||||
do
|
||||
{
|
||||
debugger_instruction_hook(PC);
|
||||
|
||||
|
||||
/* ioh should be cleared at the end of the instruction cycle, and ios at the
|
||||
start of next instruction cycle, but who cares? */
|
||||
if (m_ioh && m_ios)
|
||||
@ -815,8 +780,8 @@ void pdp1_device::execute_run()
|
||||
{
|
||||
case 0:
|
||||
/* read first word as instruction */
|
||||
if (m_read_binary_word)
|
||||
(*m_read_binary_word)(this); /* data will be transferred to IO register */
|
||||
if (!m_read_binary_word.isnull())
|
||||
m_read_binary_word(); /* data will be transferred to IO register */
|
||||
m_rim_step = 1;
|
||||
m_ios = 0;
|
||||
break;
|
||||
@ -860,8 +825,8 @@ void pdp1_device::execute_run()
|
||||
|
||||
case 2:
|
||||
/* read second word as data */
|
||||
if (m_read_binary_word)
|
||||
(*m_read_binary_word)(this); /* data will be transferred to IO register */
|
||||
if (!m_read_binary_word.isnull())
|
||||
m_read_binary_word(); /* data will be transferred to IO register */
|
||||
m_rim_step = 3;
|
||||
m_ios = 0;
|
||||
break;
|
||||
@ -940,6 +905,7 @@ void pdp1_device::execute_run()
|
||||
|
||||
if (! m_cycle)
|
||||
{ /* no instruction in progress: time to fetch a new instruction, I guess */
|
||||
debugger_instruction_hook(PC);
|
||||
MB = READ_PDP_18BIT(MA = PC);
|
||||
INCREMENT_PC;
|
||||
IR = MB >> 13; /* basic opcode */
|
||||
@ -1564,7 +1530,7 @@ void pdp1_device::execute_instruction()
|
||||
{ /* IOT with IO wait */
|
||||
if (m_ioc)
|
||||
{ /* the iot command line is pulsed only if ioc is asserted */
|
||||
(*m_extern_iot[MB & 0000077])(this, MB & 0000077, (MB & 0004000) == 0, MB, &IO, AC);
|
||||
m_extern_iot[MB & 0000077](MB & 0000077, (MB & 0004000) == 0, MB, IO, AC);
|
||||
|
||||
m_ioh = 1; /* enable io wait */
|
||||
|
||||
@ -1587,7 +1553,7 @@ void pdp1_device::execute_instruction()
|
||||
}
|
||||
else
|
||||
{ /* IOT with no IO wait */
|
||||
(*m_extern_iot[MB & 0000077])(this, MB & 0000077, (MB & 0004000) != 0, MB, &IO, AC);
|
||||
m_extern_iot[MB & 0000077](MB & 0000077, (MB & 0004000) != 0, MB, IO, AC);
|
||||
}
|
||||
break;
|
||||
case OPR: /* Operate Instruction Group */
|
||||
@ -1639,7 +1605,7 @@ no_fetch:
|
||||
/*
|
||||
Handle unimplemented IOT
|
||||
*/
|
||||
void pdp1_device::pdp1_null_iot(int op2, int nac, int mb, int *io, int ac)
|
||||
void pdp1_device::null_iot(int op2, int nac, int mb, int &io, int ac)
|
||||
{
|
||||
/* Note that the dummy IOT 0 is used to wait for the completion pulse
|
||||
generated by the a pending IOT (IOT with completion pulse but no IO wait) */
|
||||
@ -1661,7 +1627,7 @@ void pdp1_device::pdp1_null_iot(int op2, int nac, int mb, int *io, int ac)
|
||||
|
||||
IOT 74: LEM/EEM
|
||||
*/
|
||||
void pdp1_device::pdp1_lem_eem_iot(int op2, int nac, int mb, int *io, int ac)
|
||||
void pdp1_device::lem_eem_iot(int op2, int nac, int mb, int &io, int ac)
|
||||
{
|
||||
if (! m_extend_support) /* extend mode supported? */
|
||||
{
|
||||
@ -1684,7 +1650,7 @@ void pdp1_device::pdp1_lem_eem_iot(int op2, int nac, int mb, int *io, int ac)
|
||||
IOT 55: esm
|
||||
IOT 56: cbs
|
||||
*/
|
||||
void pdp1_device::pdp1_sbs_iot(int op2, int nac, int mb, int *io, int ac)
|
||||
void pdp1_device::sbs_iot(int op2, int nac, int mb, int &io, int ac)
|
||||
{
|
||||
switch (op2)
|
||||
{
|
||||
@ -1727,7 +1693,7 @@ void pdp1_device::pdp1_sbs_iot(int op2, int nac, int mb, int *io, int ac)
|
||||
IOT 52: isb
|
||||
IOT 53: cac
|
||||
*/
|
||||
void pdp1_device::pdp1_type_20_sbs_iot(int op2, int nac, int mb, int *io, int ac)
|
||||
void pdp1_device::type_20_sbs_iot(int op2, int nac, int mb, int &io, int ac)
|
||||
{
|
||||
int channel, mask;
|
||||
if (! m_type_20_sbs) /* type 20 sequence break system supported? */
|
||||
@ -1820,6 +1786,6 @@ void pdp1_device::pulse_start_clear()
|
||||
field_interrupt();
|
||||
|
||||
/* now, we kindly ask IO devices to reset, too */
|
||||
if (m_io_sc_callback)
|
||||
(*m_io_sc_callback)(this);
|
||||
if (!m_io_sc_callback.isnull())
|
||||
m_io_sc_callback();
|
||||
}
|
||||
|
@ -20,20 +20,8 @@ enum
|
||||
};
|
||||
|
||||
|
||||
typedef void (*pdp1_extern_iot_func)(device_t *device, int op2, int nac, int mb, int *io, int ac);
|
||||
typedef void (*pdp1_read_binary_word_func)(device_t *device);
|
||||
typedef void (*pdp1_io_sc_func)(device_t *device);
|
||||
|
||||
|
||||
struct pdp1_reset_param_t
|
||||
{
|
||||
/* callbacks for iot instructions (required for any I/O) */
|
||||
pdp1_extern_iot_func extern_iot[64];
|
||||
/* read a word from the perforated tape reader (required for read-in mode) */
|
||||
pdp1_read_binary_word_func read_binary_word;
|
||||
/* callback called when sc is pulsed: IO devices should reset */
|
||||
pdp1_io_sc_func io_sc_callback;
|
||||
|
||||
/* 0: no extend support, 1: extend with 15-bit address, 2: extend with 16-bit address */
|
||||
int extend_support;
|
||||
/* 1 to use hardware multiply/divide (MUL, DIV) instead of MUS, DIS */
|
||||
@ -49,6 +37,10 @@ class pdp1_device : public cpu_device
|
||||
, public pdp1_reset_param_t
|
||||
{
|
||||
public:
|
||||
typedef device_delegate<void (int op2, int nac, int mb, int &io, int ac)> iot_delegate;
|
||||
typedef device_delegate<void ()> read_binary_word_delegate;
|
||||
typedef device_delegate<void ()> io_sc_delegate;
|
||||
|
||||
enum opcode
|
||||
{
|
||||
AND = 001,
|
||||
@ -83,14 +75,17 @@ public:
|
||||
// construction/destruction
|
||||
pdp1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
template <int I, typename... T> void set_iot_callback(T &&... args) { m_extern_iot[I].set(std::forward<T>(args)...); }
|
||||
template <typename... T> void set_read_binary_word(T &&... args) { m_read_binary_word.set(std::forward<T>(args)...); }
|
||||
template <typename... T> void set_io_sc_callback(T &&... args) { m_io_sc_callback.set(std::forward<T>(args)...); }
|
||||
void set_reset_param(const pdp1_reset_param_t *param) { m_reset_param = param; }
|
||||
|
||||
void pulse_start_clear();
|
||||
void io_complete() { m_ios = 1; }
|
||||
void pdp1_null_iot(int op2, int nac, int mb, int *io, int ac);
|
||||
void pdp1_lem_eem_iot(int op2, int nac, int mb, int *io, int ac);
|
||||
void pdp1_sbs_iot(int op2, int nac, int mb, int *io, int ac);
|
||||
void pdp1_type_20_sbs_iot(int op2, int nac, int mb, int *io, int ac);
|
||||
void null_iot(int op2, int nac, int mb, int &io, int ac);
|
||||
void lem_eem_iot(int op2, int nac, int mb, int &io, int ac);
|
||||
void sbs_iot(int op2, int nac, int mb, int &io, int ac);
|
||||
void type_20_sbs_iot(int op2, int nac, int mb, int &io, int ac);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
@ -167,11 +162,11 @@ private:
|
||||
int m_no_sequence_break; /* disable sequence break recognition for one cycle */
|
||||
|
||||
/* callbacks for iot instructions (required for any I/O) */
|
||||
pdp1_extern_iot_func m_extern_iot[64];
|
||||
std::vector<iot_delegate> m_extern_iot;
|
||||
/* read a word from the perforated tape reader (required for read-in mode) */
|
||||
pdp1_read_binary_word_func m_read_binary_word;
|
||||
read_binary_word_delegate m_read_binary_word;
|
||||
/* callback called when sc is pulsed: IO devices should reset */
|
||||
pdp1_io_sc_func m_io_sc_callback;
|
||||
io_sc_delegate m_io_sc_callback;
|
||||
|
||||
/* 0: no extend support, 1: extend with 15-bit address, 2: extend with 16-bit address */
|
||||
int m_extend_support;
|
||||
|
@ -19,7 +19,7 @@ inline void pdp1_disassembler::ea()
|
||||
|
||||
u32 pdp1_disassembler::opcode_alignment() const
|
||||
{
|
||||
return 4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
offs_t pdp1_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
|
||||
@ -290,5 +290,5 @@ offs_t pdp1_disassembler::disassemble(std::ostream &stream, offs_t pc, const dat
|
||||
//etime = 5;
|
||||
break;
|
||||
}
|
||||
return 4;
|
||||
return 1;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ DEFINE_DEVICE_TYPE(PDP8, pdp8_device, "pdp8_cpu", "DEC PDP8")
|
||||
|
||||
pdp8_device::pdp8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: cpu_device(mconfig, PDP8, tag, owner, clock),
|
||||
m_program_config("program", ENDIANNESS_BIG, 12, 12),
|
||||
m_program_config("program", ENDIANNESS_BIG, 12, 12, -1),
|
||||
m_pc(0),
|
||||
m_ac(0),
|
||||
m_mb(0),
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
u32 pdp8_disassembler::opcode_alignment() const
|
||||
{
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
offs_t pdp8_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
|
||||
@ -164,5 +164,5 @@ offs_t pdp8_disassembler::disassemble(std::ostream &stream, offs_t pc, const dat
|
||||
}
|
||||
}
|
||||
|
||||
return 2 | SUPPORTED;
|
||||
return 1 | SUPPORTED | (opcode == 4 ? STEP_OVER : 0);
|
||||
}
|
||||
|
@ -450,22 +450,22 @@ void multipcm_device::write(offs_t offset, uint8_t data)
|
||||
|
||||
DEFINE_DEVICE_TYPE(MULTIPCM, multipcm_device, "ymw258f", "Yamaha YMW-258-F")
|
||||
|
||||
multipcm_device::multipcm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, MULTIPCM, tag, owner, clock),
|
||||
device_sound_interface(mconfig, *this),
|
||||
device_rom_interface(mconfig, *this),
|
||||
m_stream(nullptr),
|
||||
m_slots(nullptr),
|
||||
m_cur_slot(0),
|
||||
m_address(0),
|
||||
m_rate(0),
|
||||
m_attack_step(nullptr),
|
||||
m_decay_release_step(nullptr),
|
||||
m_freq_step_table(nullptr),
|
||||
m_left_pan_table(nullptr),
|
||||
m_right_pan_table(nullptr),
|
||||
m_linear_to_exp_volume(nullptr),
|
||||
m_total_level_steps(nullptr)
|
||||
multipcm_device::multipcm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, MULTIPCM, tag, owner, clock),
|
||||
device_sound_interface(mconfig, *this),
|
||||
device_rom_interface(mconfig, *this),
|
||||
m_stream(nullptr),
|
||||
m_slots(nullptr),
|
||||
m_cur_slot(0),
|
||||
m_address(0),
|
||||
m_rate(0),
|
||||
m_attack_step(nullptr),
|
||||
m_decay_release_step(nullptr),
|
||||
m_freq_step_table(nullptr),
|
||||
m_left_pan_table(nullptr),
|
||||
m_right_pan_table(nullptr),
|
||||
m_linear_to_exp_volume(nullptr),
|
||||
m_total_level_steps(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@ -577,16 +577,16 @@ void multipcm_device::device_start()
|
||||
// Slots
|
||||
m_slots = make_unique_clear<slot_t []>(28);
|
||||
|
||||
save_pointer(STRUCT_MEMBER(m_slots.get(), m_regs), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots.get(), m_playing), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots.get(), m_base), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots.get(), m_offset), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots.get(), m_step), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots.get(), m_pan), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots.get(), m_total_level), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots.get(), m_dest_total_level), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots.get(), m_total_level_step), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots.get(), m_prev_sample), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots, m_regs), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots, m_playing), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots, m_base), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots, m_offset), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots, m_step), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots, m_pan), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots, m_total_level), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots, m_dest_total_level), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots, m_total_level_step), 28);
|
||||
save_pointer(STRUCT_MEMBER(m_slots, m_prev_sample), 28);
|
||||
|
||||
for (int32_t slot = 0; slot < 28; ++slot)
|
||||
{
|
||||
|
@ -84,7 +84,7 @@ debug_view_memory_source::debug_view_memory_source(std::string &&name, void *bas
|
||||
, m_base(base)
|
||||
, m_blocklength(element_size * num_elements)
|
||||
, m_numblocks(num_blocks)
|
||||
, m_blockstride(element_size * block_stride)
|
||||
, m_blockstride(block_stride)
|
||||
, m_offsetxor(0)
|
||||
, m_endianness(ENDIANNESS_NATIVE)
|
||||
, m_prefsize(std::min(element_size, 8))
|
||||
|
@ -416,7 +416,7 @@ inline save_error save_manager::do_write(T check_space, U write_block, V start_h
|
||||
{
|
||||
const u32 blocksize = entry->m_typesize * entry->m_typecount;
|
||||
const u8 *data = reinterpret_cast<const u8 *>(entry->m_data);
|
||||
for (u32 b = 0; entry->m_blockcount > b; ++b, data += (entry->m_typesize * entry->m_stride))
|
||||
for (u32 b = 0; entry->m_blockcount > b; ++b, data += entry->m_stride)
|
||||
if (!write_block(data, blocksize))
|
||||
return STATERR_WRITE_ERROR;
|
||||
}
|
||||
@ -460,7 +460,7 @@ inline save_error save_manager::do_read(T check_length, U read_block, V start_he
|
||||
{
|
||||
const u32 blocksize = entry->m_typesize * entry->m_typecount;
|
||||
u8 *data = reinterpret_cast<u8 *>(entry->m_data);
|
||||
for (u32 b = 0; entry->m_blockcount > b; ++b, data += (entry->m_typesize * entry->m_stride))
|
||||
for (u32 b = 0; entry->m_blockcount > b; ++b, data += entry->m_stride)
|
||||
if (!read_block(data, blocksize))
|
||||
return STATERR_READ_ERROR;
|
||||
|
||||
@ -984,7 +984,7 @@ save_manager::state_entry::state_entry(void *data, const char *name, device_t *d
|
||||
void save_manager::state_entry::flip_data()
|
||||
{
|
||||
u8 *data = reinterpret_cast<u8 *>(m_data);
|
||||
for (u32 b = 0; m_blockcount > b; ++b, data += (m_typesize * m_stride))
|
||||
for (u32 b = 0; m_blockcount > b; ++b, data += m_stride)
|
||||
{
|
||||
u16 *data16;
|
||||
u32 *data32;
|
||||
|
@ -171,10 +171,9 @@ public:
|
||||
void save_item(device_t *device, const char *module, const char *tag, int index, ItemType &value, ElementType StructType::*element, const char *valname)
|
||||
{
|
||||
static_assert(std::is_base_of<StructType, typename array_unwrap<ItemType>::underlying_type>::value, "Called save_item on a non-matching struct member pointer!");
|
||||
static_assert(!(sizeof(typename array_unwrap<ItemType>::underlying_type) % sizeof(typename array_unwrap<ElementType>::underlying_type)), "Called save_item on an unaligned struct member!");
|
||||
static_assert(!std::is_pointer<ElementType>::value, "Called save_item on a struct member pointer!");
|
||||
static_assert(is_atom<typename array_unwrap<ElementType>::underlying_type>::value, "Called save_item on a non-fundamental type!");
|
||||
save_memory(device, module, tag, index, valname, array_unwrap<ElementType>::ptr(array_unwrap<ItemType>::ptr(value)->*element), array_unwrap<ElementType>::SIZE, array_unwrap<ElementType>::SAVE_COUNT, array_unwrap<ItemType>::SAVE_COUNT, sizeof(typename array_unwrap<ItemType>::underlying_type) / sizeof(typename array_unwrap<ElementType>::underlying_type));
|
||||
save_memory(device, module, tag, index, valname, array_unwrap<ElementType>::ptr(array_unwrap<ItemType>::ptr(value)->*element), array_unwrap<ElementType>::SIZE, array_unwrap<ElementType>::SAVE_COUNT, array_unwrap<ItemType>::SAVE_COUNT, sizeof(typename array_unwrap<ItemType>::underlying_type));
|
||||
}
|
||||
|
||||
// templatized wrapper for pointers
|
||||
@ -188,28 +187,25 @@ public:
|
||||
void save_pointer(device_t *device, const char *module, const char *tag, int index, ItemType *value, ElementType StructType::*element, const char *valname, u32 count)
|
||||
{
|
||||
static_assert(std::is_base_of<StructType, typename array_unwrap<ItemType>::underlying_type>::value, "Called save_pointer on a non-matching struct member pointer!");
|
||||
static_assert(!(sizeof(typename array_unwrap<ItemType>::underlying_type) % sizeof(typename array_unwrap<ElementType>::underlying_type)), "Called save_pointer on an unaligned struct member!");
|
||||
static_assert(!std::is_pointer<ElementType>::value, "Called save_pointer on a struct member pointer!");
|
||||
static_assert(is_atom<typename array_unwrap<ElementType>::underlying_type>::value, "Called save_pointer on a non-fundamental type!");
|
||||
save_memory(device, module, tag, index, valname, array_unwrap<ElementType>::ptr(array_unwrap<ItemType>::ptr(value[0])->*element), array_unwrap<ElementType>::SIZE, array_unwrap<ElementType>::SAVE_COUNT, array_unwrap<ItemType>::SAVE_COUNT * count, sizeof(typename array_unwrap<ItemType>::underlying_type) / sizeof(typename array_unwrap<ElementType>::underlying_type));
|
||||
save_memory(device, module, tag, index, valname, array_unwrap<ElementType>::ptr(array_unwrap<ItemType>::ptr(value[0])->*element), array_unwrap<ElementType>::SIZE, array_unwrap<ElementType>::SAVE_COUNT, array_unwrap<ItemType>::SAVE_COUNT * count, sizeof(typename array_unwrap<ItemType>::underlying_type));
|
||||
}
|
||||
|
||||
// templatized wrapper for std::unique_ptr
|
||||
template <typename ItemType>
|
||||
void save_pointer(device_t *device, const char *module, const char *tag, int index, const std::unique_ptr<ItemType []> &value, const char *valname, u32 count)
|
||||
std::enable_if_t<is_atom<typename array_unwrap<ItemType>::underlying_type>::value> save_pointer(device_t *device, const char *module, const char *tag, int index, const std::unique_ptr<ItemType []> &value, const char *valname, u32 count)
|
||||
{
|
||||
static_assert(is_atom<typename array_unwrap<ItemType>::underlying_type>::value, "Called save_pointer on a non-fundamental type!");
|
||||
save_memory(device, module, tag, index, valname, array_unwrap<ItemType>::ptr(value[0]), array_unwrap<ItemType>::SIZE, array_unwrap<ItemType>::SAVE_COUNT * count);
|
||||
}
|
||||
|
||||
template <typename ItemType, typename StructType, typename ElementType>
|
||||
std::enable_if_t<is_atom<typename array_unwrap<ItemType>::underlying_type>::value> save_pointer(device_t *device, const char *module, const char *tag, int index, const std::unique_ptr<ItemType []> &value, ElementType StructType::*element, const char *valname, u32 count)
|
||||
void save_pointer(device_t *device, const char *module, const char *tag, int index, const std::unique_ptr<ItemType []> &value, ElementType StructType::*element, const char *valname, u32 count)
|
||||
{
|
||||
static_assert(std::is_base_of<StructType, typename array_unwrap<ItemType>::underlying_type>::value, "Called save_pointer on a non-matching struct member pointer!");
|
||||
static_assert(!(sizeof(typename array_unwrap<ItemType>::underlying_type) % sizeof(typename array_unwrap<ElementType>::underlying_type)), "Called save_pointer on an unaligned struct member!");
|
||||
static_assert(!std::is_pointer<ElementType>::value, "Called save_pointer on a struct member pointer!");
|
||||
static_assert(is_atom<typename array_unwrap<ElementType>::underlying_type>::value, "Called save_pointer on a non-fundamental type!");
|
||||
save_memory(device, module, tag, index, valname, array_unwrap<ElementType>::ptr(array_unwrap<ItemType>::ptr(value[0])->*element), array_unwrap<ElementType>::SIZE, array_unwrap<ElementType>::SAVE_COUNT, array_unwrap<ItemType>::SAVE_COUNT * count, sizeof(typename array_unwrap<ItemType>::underlying_type) / sizeof(typename array_unwrap<ElementType>::underlying_type));
|
||||
save_memory(device, module, tag, index, valname, array_unwrap<ElementType>::ptr(array_unwrap<ItemType>::ptr(value[0])->*element), array_unwrap<ElementType>::SIZE, array_unwrap<ElementType>::SAVE_COUNT, array_unwrap<ItemType>::SAVE_COUNT * count, sizeof(typename array_unwrap<ItemType>::underlying_type));
|
||||
}
|
||||
|
||||
// templatized wrapper for std::vector
|
||||
|
@ -1171,7 +1171,7 @@ void lua_engine::initialize()
|
||||
item_type.set("read", [this](save_item &item, int offset) -> sol::object {
|
||||
if(!item.base || (offset >= item.count))
|
||||
return sol::make_object(sol(), sol::nil);
|
||||
const void *const data = reinterpret_cast<const uint8_t *>(item.base) + (item.size * item.stride * (offset / item.valcount));
|
||||
const void *const data = reinterpret_cast<const uint8_t *>(item.base) + (item.stride * (offset / item.valcount));
|
||||
uint64_t ret = 0;
|
||||
switch(item.size)
|
||||
{
|
||||
@ -1199,7 +1199,6 @@ void lua_engine::initialize()
|
||||
else
|
||||
{
|
||||
const uint32_t blocksize = item.size * item.valcount;
|
||||
const uint32_t bytestride = item.size * item.stride;
|
||||
uint32_t remaining = buff->get_len();
|
||||
uint8_t *dest = reinterpret_cast<uint8_t *>(buff->get_ptr());
|
||||
while(remaining)
|
||||
@ -1207,7 +1206,7 @@ void lua_engine::initialize()
|
||||
const uint32_t blockno = offset / blocksize;
|
||||
const uint32_t available = blocksize - (offset % blocksize);
|
||||
const uint32_t chunk = (available < remaining) ? available : remaining;
|
||||
const void *const source = reinterpret_cast<const uint8_t *>(item.base) + (blockno * bytestride) + (offset % blocksize);
|
||||
const void *const source = reinterpret_cast<const uint8_t *>(item.base) + (blockno * item.stride) + (offset % blocksize);
|
||||
std::memcpy(dest, source, chunk);
|
||||
offset += chunk;
|
||||
remaining -= chunk;
|
||||
@ -1219,7 +1218,7 @@ void lua_engine::initialize()
|
||||
item_type.set("write", [](save_item &item, int offset, uint64_t value) {
|
||||
if(!item.base || (offset >= item.count))
|
||||
return;
|
||||
void *const data = reinterpret_cast<uint8_t *>(item.base) + (item.size * item.stride * (offset / item.valcount));
|
||||
void *const data = reinterpret_cast<uint8_t *>(item.base) + (item.stride * (offset / item.valcount));
|
||||
switch(item.size)
|
||||
{
|
||||
case 1:
|
||||
|
@ -265,11 +265,6 @@ TODO:
|
||||
accesses done by the sound CPU to the YM2203 I/O ports. At the very least, there
|
||||
could be some filters.
|
||||
|
||||
There are also Bubble Bobble bootlegs with a P8749H MCU, however the MCU
|
||||
is protected against reading and the main code only differs by 1 byte from
|
||||
Bubble Bobble. If the MCU were to be dumped that would also make for
|
||||
interesting comparisons.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
@ -1864,7 +1859,7 @@ ROM_START( bub68705 )
|
||||
ROM_LOAD( "a71-25.41", 0x0000, 0x0100, CRC(2d0f8545) SHA1(089c31e2f614145ef2743164f7b52ae35bc06808) ) /* video timing */
|
||||
ROM_END
|
||||
|
||||
ROM_START( bub8749 ) // all ROMs match bublbobl1 but for the MCU, which is different. 2-PCB set probably comes from Italy
|
||||
ROM_START( bub8749 ) // All ROMs match bublbobl1 but for the MCU, which is different. 2-PCB set probably comes from Italy
|
||||
ROM_REGION( 0x30000, "maincpu", 0 )
|
||||
ROM_LOAD( "6-27256.bin", 0x00000, 0x08000, CRC(32c8305b) SHA1(6bf69b3edfbefd33cd670a762b4bf0b39629a220) )
|
||||
// ROMs banked at 8000-bfff
|
||||
@ -1897,7 +1892,7 @@ ROM_START( bub8749 ) // all ROMs match bublbobl1 but for the MCU, which is diffe
|
||||
// 0x70000-0x7ffff empty
|
||||
|
||||
ROM_REGION( 0x0100, "proms", 0 )
|
||||
ROM_LOAD( "6301-in", 0x0000, 0x0100, BAD_DUMP CRC(2d0f8545) SHA1(089c31e2f614145ef2743164f7b52ae35bc06808) ) // video timing, not dumped for this set
|
||||
ROM_LOAD( "6301-in", 0x00000, 0x0100, CRC(2d0f8545) SHA1(089c31e2f614145ef2743164f7b52ae35bc06808) ) // Video timing
|
||||
|
||||
// Located on CPU/Sound Board
|
||||
ROM_REGION( 0x0003, "plds", 0 )
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -168,59 +168,216 @@ enum
|
||||
pen_lightpen_pressed = pen_green
|
||||
};
|
||||
|
||||
/* tape reader registers */
|
||||
struct tape_reader_t
|
||||
class pdp1_state;
|
||||
|
||||
// tape reader device
|
||||
class pdp1_readtape_image_device : public device_t,
|
||||
public device_image_interface
|
||||
{
|
||||
device_image_interface *fd; /* file descriptor of tape image */
|
||||
public:
|
||||
// construction/destruction
|
||||
pdp1_readtape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
|
||||
|
||||
int motor_on; /* 1-bit reader motor on */
|
||||
auto st_ptr() { return m_st_ptr.bind(); }
|
||||
|
||||
int rb; /* 18-bit reader buffer */
|
||||
int rcl; /* 1-bit reader clutch */
|
||||
int rc; /* 2-bit reader counter */
|
||||
int rby; /* 1-bit reader binary mode flip-flop */
|
||||
int rcp; /* 1-bit reader "need a completion pulse" flip-flop */
|
||||
void iot_rpa(int op2, int nac, int mb, int &io, int ac);
|
||||
void iot_rpb(int op2, int nac, int mb, int &io, int ac);
|
||||
void iot_rrb(int op2, int nac, int mb, int &io, int ac);
|
||||
|
||||
emu_timer *timer; /* timer to simulate reader timing */
|
||||
void tape_read_binary();
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
|
||||
// image-level overrides
|
||||
virtual iodevice_t image_type() const noexcept override { return IO_PUNCHTAPE; }
|
||||
|
||||
virtual bool is_readable() const noexcept override { return true; }
|
||||
virtual bool is_writeable() const noexcept override { return false; }
|
||||
virtual bool is_creatable() const noexcept override { return false; }
|
||||
virtual bool must_be_loaded() const noexcept override { return false; }
|
||||
virtual bool is_reset_on_load() const noexcept override { return false; }
|
||||
virtual const char *file_extensions() const noexcept override { return "tap,rim"; }
|
||||
|
||||
virtual image_init_result call_load() override;
|
||||
virtual void call_unload() override;
|
||||
|
||||
public:
|
||||
TIMER_CALLBACK_MEMBER(reader_callback);
|
||||
|
||||
int tape_read(uint8_t *reply);
|
||||
void begin_tape_read(int binary, int nac);
|
||||
|
||||
required_device<pdp1_device> m_maincpu;
|
||||
|
||||
devcb_write_line m_st_ptr;
|
||||
|
||||
int m_motor_on; // 1-bit reader motor on
|
||||
|
||||
int m_rb; // 18-bit reader buffer
|
||||
int m_rcl; // 1-bit reader clutch
|
||||
int m_rc; // 2-bit reader counter
|
||||
int m_rby; // 1-bit reader binary mode flip-flop
|
||||
int m_rcp; // 1-bit reader "need a completion pulse" flip-flop
|
||||
|
||||
emu_timer *m_timer; // timer to simulate reader timing
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* tape puncher registers */
|
||||
struct tape_puncher_t
|
||||
// tape puncher device
|
||||
class pdp1_punchtape_image_device : public device_t,
|
||||
public device_image_interface
|
||||
{
|
||||
device_image_interface *fd; /* file descriptor of tape image */
|
||||
public:
|
||||
// construction/destruction
|
||||
pdp1_punchtape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
|
||||
|
||||
emu_timer *timer; /* timer to generate completion pulses */
|
||||
auto st_ptp() { return m_st_ptp.bind(); }
|
||||
|
||||
void iot_ppa(int op2, int nac, int mb, int &io, int ac);
|
||||
void iot_ppb(int op2, int nac, int mb, int &io, int ac);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
|
||||
// image-level overrides
|
||||
virtual iodevice_t image_type() const noexcept override { return IO_PUNCHTAPE; }
|
||||
|
||||
virtual bool is_readable() const noexcept override { return false; }
|
||||
virtual bool is_writeable() const noexcept override { return true; }
|
||||
virtual bool is_creatable() const noexcept override { return true; }
|
||||
virtual bool must_be_loaded() const noexcept override { return false; }
|
||||
virtual bool is_reset_on_load() const noexcept override { return false; }
|
||||
virtual const char *file_extensions() const noexcept override { return "tap,rim"; }
|
||||
|
||||
virtual image_init_result call_load() override;
|
||||
virtual void call_unload() override;
|
||||
|
||||
public:
|
||||
TIMER_CALLBACK_MEMBER(puncher_callback);
|
||||
|
||||
void tape_write(uint8_t data);
|
||||
|
||||
required_device<pdp1_device> m_maincpu;
|
||||
|
||||
devcb_write_line m_st_ptp;
|
||||
|
||||
emu_timer *m_timer; // timer to generate completion pulses
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* typewriter registers */
|
||||
struct typewriter_t
|
||||
// typewriter device
|
||||
class pdp1_typewriter_device : public device_t,
|
||||
public device_image_interface
|
||||
{
|
||||
device_image_interface *fd; /* file descriptor of output image */
|
||||
public:
|
||||
// construction/destruction
|
||||
pdp1_typewriter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
|
||||
|
||||
int tb; /* typewriter buffer */
|
||||
auto st_tyo() { return m_st_tyo.bind(); }
|
||||
auto st_tyi() { return m_st_tyi.bind(); }
|
||||
|
||||
emu_timer *tyo_timer;/* timer to generate completion pulses */
|
||||
void iot_tyo(int op2, int nac, int mb, int &io, int ac);
|
||||
void iot_tyi(int op2, int nac, int mb, int &io, int ac);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
|
||||
// image-level overrides
|
||||
virtual iodevice_t image_type() const noexcept override { return IO_PRINTER; }
|
||||
|
||||
virtual bool is_readable() const noexcept override { return false; }
|
||||
virtual bool is_writeable() const noexcept override { return true; }
|
||||
virtual bool is_creatable() const noexcept override { return true; }
|
||||
virtual bool must_be_loaded() const noexcept override { return false; }
|
||||
virtual bool is_reset_on_load() const noexcept override { return false; }
|
||||
virtual const char *file_extensions() const noexcept override { return "typ"; }
|
||||
|
||||
virtual image_init_result call_load() override;
|
||||
virtual void call_unload() override;
|
||||
|
||||
public:
|
||||
TIMER_CALLBACK_MEMBER(tyo_callback);
|
||||
|
||||
void linefeed();
|
||||
void drawchar(int character);
|
||||
void typewriter_out(uint8_t data);
|
||||
|
||||
void pdp1_keyboard();
|
||||
|
||||
required_device<pdp1_device> m_maincpu;
|
||||
required_device<pdp1_state> m_driver_state;
|
||||
required_ioport_array<4> m_twr;
|
||||
|
||||
devcb_write_line m_st_tyo;
|
||||
devcb_write_line m_st_tyi;
|
||||
|
||||
int m_tb; // typewriter buffer
|
||||
|
||||
emu_timer *m_tyo_timer; // timer to generate completion pulses
|
||||
|
||||
int m_old_typewriter_keys[4];
|
||||
int m_color;
|
||||
bitmap_ind16 m_bitmap;
|
||||
int m_pos;
|
||||
int m_case_shift;
|
||||
};
|
||||
|
||||
/* MIT parallel drum (mostly similar to type 23) */
|
||||
struct parallel_drum_t
|
||||
// MIT parallel drum (mostly similar to type 23)
|
||||
class pdp1_cylinder_image_device : public device_t,
|
||||
public device_image_interface
|
||||
{
|
||||
device_image_interface *fd; /* file descriptor of drum image */
|
||||
public:
|
||||
// construction/destruction
|
||||
pdp1_cylinder_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
|
||||
|
||||
int il; /* initial location (12-bit) */
|
||||
int wc; /* word counter (12-bit) */
|
||||
int wcl; /* word core location counter (16-bit) */
|
||||
int rfb; /* read field buffer (5-bit) */
|
||||
int wfb; /* write field buffer (5-bit) */
|
||||
void iot_dia(int op2, int nac, int mb, int &io, int ac);
|
||||
void iot_dba(int op2, int nac, int mb, int &io, int ac);
|
||||
void iot_dcc(int op2, int nac, int mb, int &io, int ac);
|
||||
void iot_dra(int op2, int nac, int mb, int &io, int ac);
|
||||
|
||||
int dba;
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
|
||||
emu_timer *rotation_timer; /* timer called each time dc is 0 */
|
||||
emu_timer *il_timer; /* timer called each time dc is il */
|
||||
// image-level overrides
|
||||
virtual iodevice_t image_type() const noexcept override { return IO_CYLINDER; }
|
||||
|
||||
virtual bool is_readable() const noexcept override { return true; }
|
||||
virtual bool is_writeable() const noexcept override { return true; }
|
||||
virtual bool is_creatable() const noexcept override { return true; }
|
||||
virtual bool must_be_loaded() const noexcept override { return false; }
|
||||
virtual bool is_reset_on_load() const noexcept override { return false; }
|
||||
virtual const char *file_extensions() const noexcept override { return "drm"; }
|
||||
|
||||
virtual image_init_result call_load() override;
|
||||
virtual void call_unload() override;
|
||||
|
||||
public:
|
||||
void set_il(int il);
|
||||
uint32_t drum_read(int field, int position);
|
||||
void drum_write(int field, int position, uint32_t data);
|
||||
|
||||
required_device<pdp1_device> m_maincpu;
|
||||
|
||||
int m_il; // initial location (12-bit)
|
||||
int m_wc; // word counter (12-bit)
|
||||
int m_wcl; // word core location counter (16-bit)
|
||||
int m_rfb; // read field buffer (5-bit)
|
||||
int m_wfb; // write field buffer (5-bit)
|
||||
|
||||
int m_dba;
|
||||
|
||||
emu_timer *m_rotation_timer;// timer called each time dc is 0
|
||||
emu_timer *m_il_timer; // timer called each time dc is il
|
||||
};
|
||||
|
||||
|
||||
@ -239,6 +396,10 @@ public:
|
||||
pdp1_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_tape_reader(*this, "readt"),
|
||||
m_tape_puncher(*this, "punch"),
|
||||
m_typewriter(*this, "typewriter"),
|
||||
m_parallel_drum(*this, "drum"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_palette(*this, "palette"),
|
||||
m_crt(*this, "crt"),
|
||||
@ -248,21 +409,20 @@ public:
|
||||
m_tstadd(*this, "TSTADD"),
|
||||
m_twdmsb(*this, "TWDMSB"),
|
||||
m_twdlsb(*this, "TWDLSB"),
|
||||
m_twr(*this, "TWR.%u", 0),
|
||||
m_cfg(*this, "CFG"),
|
||||
m_io_lightpen(*this, "LIGHTPEN"),
|
||||
m_lightx(*this, "LIGHTX"),
|
||||
m_lighty(*this, "LIGHTY")
|
||||
{ }
|
||||
|
||||
required_device<pdp1_device> m_maincpu;
|
||||
required_device<pdp1_readtape_image_device> m_tape_reader;
|
||||
required_device<pdp1_punchtape_image_device> m_tape_puncher;
|
||||
required_device<pdp1_typewriter_device> m_typewriter;
|
||||
required_device<pdp1_cylinder_image_device> m_parallel_drum;
|
||||
int m_io_status;
|
||||
tape_reader_t m_tape_reader;
|
||||
tape_puncher_t m_tape_puncher;
|
||||
typewriter_t m_typewriter;
|
||||
emu_timer *m_dpy_timer;
|
||||
lightpen_t m_lightpen;
|
||||
parallel_drum_t m_parallel_drum;
|
||||
required_device<pdp1_device> m_maincpu;
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
@ -271,9 +431,6 @@ public:
|
||||
uint32_t screen_update_pdp1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
DECLARE_WRITE_LINE_MEMBER(screen_vblank_pdp1);
|
||||
INTERRUPT_GEN_MEMBER(pdp1_interrupt);
|
||||
TIMER_CALLBACK_MEMBER(reader_callback);
|
||||
TIMER_CALLBACK_MEMBER(puncher_callback);
|
||||
TIMER_CALLBACK_MEMBER(tyo_callback);
|
||||
TIMER_CALLBACK_MEMBER(dpy_callback);
|
||||
void pdp1_machine_stop();
|
||||
inline void pdp1_plot_pixel(bitmap_ind16 &bitmap, int x, int y, uint32_t color);
|
||||
@ -286,39 +443,35 @@ public:
|
||||
void pdp1_draw_string(bitmap_ind16 &bitmap, const char *buf, int x, int y, int color);
|
||||
void pdp1_draw_panel_backdrop(bitmap_ind16 &bitmap);
|
||||
void pdp1_draw_panel(bitmap_ind16 &bitmap);
|
||||
void pdp1_typewriter_linefeed();
|
||||
void pdp1_typewriter_drawchar(int character);
|
||||
void pdp1_update_lightpen_state(const lightpen_t *new_state);
|
||||
void pdp1_draw_circle(bitmap_ind16 &bitmap, int x, int y, int radius, int color_);
|
||||
void pdp1_erase_lightpen(bitmap_ind16 &bitmap);
|
||||
void pdp1_draw_lightpen(bitmap_ind16 &bitmap);
|
||||
int tape_read(uint8_t *reply);
|
||||
void begin_tape_read(int binary, int nac);
|
||||
void tape_write(uint8_t data);
|
||||
void typewriter_out(uint8_t data);
|
||||
void parallel_drum_set_il(int il);
|
||||
uint32_t drum_read(int field, int position);
|
||||
void drum_write(int field, int position, uint32_t data);
|
||||
void pdp1_keyboard();
|
||||
void pdp1_lightpen();
|
||||
int read_spacewar() { return m_spacewar->read(); }
|
||||
|
||||
template <int Mask> DECLARE_WRITE_LINE_MEMBER(io_status_w);
|
||||
|
||||
void pdp1(machine_config &config);
|
||||
void pdp1_map(address_map &map);
|
||||
private:
|
||||
void iot_dpy(int op2, int nac, int mb, int &io, int ac);
|
||||
|
||||
void iot_011(int op2, int nac, int mb, int &io, int ac);
|
||||
|
||||
void iot_cks(int op2, int nac, int mb, int &io, int ac);
|
||||
|
||||
void io_state_clear();
|
||||
|
||||
pdp1_reset_param_t m_reset_param;
|
||||
int m_old_typewriter_keys[4];
|
||||
int m_old_lightpen;
|
||||
int m_old_control_keys;
|
||||
int m_old_tw_keys;
|
||||
int m_old_ta_keys;
|
||||
int m_typewriter_color;
|
||||
bitmap_ind16 m_panel_bitmap;
|
||||
bitmap_ind16 m_typewriter_bitmap;
|
||||
lightpen_t m_lightpen_state;
|
||||
lightpen_t m_previous_lightpen_state;
|
||||
int m_pos;
|
||||
int m_case_shift;
|
||||
|
||||
public:
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<crt_device> m_crt;
|
||||
@ -328,7 +481,6 @@ private:
|
||||
required_ioport m_tstadd;
|
||||
required_ioport m_twdmsb;
|
||||
required_ioport m_twdlsb;
|
||||
required_ioport_array<4> m_twr;
|
||||
required_ioport m_cfg;
|
||||
required_ioport m_io_lightpen;
|
||||
required_ioport m_lightx;
|
||||
|
@ -37,17 +37,17 @@ inline void pdp1_state::pdp1_plot_pixel(bitmap_ind16 &bitmap, int x, int y, uint
|
||||
*/
|
||||
void pdp1_state::video_start()
|
||||
{
|
||||
m_typewriter_color = color_typewriter_black;
|
||||
m_typewriter->m_color = color_typewriter_black;
|
||||
|
||||
/* alloc bitmaps for our private fun */
|
||||
m_panel_bitmap.allocate(panel_window_width, panel_window_height, BITMAP_FORMAT_IND16);
|
||||
m_typewriter_bitmap.allocate(typewriter_window_width, typewriter_window_height, BITMAP_FORMAT_IND16);
|
||||
m_typewriter->m_bitmap.allocate(typewriter_window_width, typewriter_window_height, BITMAP_FORMAT_IND16);
|
||||
|
||||
/* set up out bitmaps */
|
||||
pdp1_draw_panel_backdrop(m_panel_bitmap);
|
||||
|
||||
const rectangle typewriter_bitmap_bounds(0, typewriter_window_width-1, 0, typewriter_window_height-1);
|
||||
m_typewriter_bitmap.fill(pen_typewriter_bg, typewriter_bitmap_bounds);
|
||||
m_typewriter->m_bitmap.fill(pen_typewriter_bg, typewriter_bitmap_bounds);
|
||||
}
|
||||
|
||||
|
||||
@ -84,7 +84,7 @@ uint32_t pdp1_state::screen_update_pdp1(screen_device &screen, bitmap_ind16 &bit
|
||||
pdp1_draw_panel(m_panel_bitmap);
|
||||
copybitmap(bitmap, m_panel_bitmap, 0, 0, panel_window_offset_x, panel_window_offset_y, cliprect);
|
||||
|
||||
copybitmap(bitmap, m_typewriter_bitmap, 0, 0, typewriter_window_offset_x, typewriter_window_offset_y, cliprect);
|
||||
copybitmap(bitmap, m_typewriter->m_bitmap, 0, 0, typewriter_window_offset_x, typewriter_window_offset_y, cliprect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -353,28 +353,28 @@ enum
|
||||
};
|
||||
|
||||
|
||||
void pdp1_state::pdp1_typewriter_linefeed()
|
||||
void pdp1_typewriter_device::linefeed()
|
||||
{
|
||||
uint8_t buf[typewriter_window_width];
|
||||
int y;
|
||||
|
||||
assert(typewriter_window_width <= m_typewriter_bitmap.width());
|
||||
assert(typewriter_window_height <= m_typewriter_bitmap.height());
|
||||
assert(typewriter_window_width <= m_bitmap.width());
|
||||
assert(typewriter_window_height <= m_bitmap.height());
|
||||
for (y=0; y<typewriter_window_height-typewriter_scroll_step; y++)
|
||||
{
|
||||
std::copy_n(&m_typewriter_bitmap.pix16(y+typewriter_scroll_step, 0), typewriter_window_width, buf);
|
||||
draw_scanline8(m_typewriter_bitmap, 0, y, typewriter_window_width, buf, m_palette->pens());
|
||||
std::copy_n(&m_bitmap.pix16(y+typewriter_scroll_step, 0), typewriter_window_width, buf);
|
||||
draw_scanline8(m_bitmap, 0, y, typewriter_window_width, buf, m_driver_state->m_palette->pens());
|
||||
}
|
||||
|
||||
const rectangle typewriter_scroll_clear_window(0, typewriter_window_width-1, typewriter_window_height-typewriter_scroll_step, typewriter_window_height-1);
|
||||
m_typewriter_bitmap.fill(pen_typewriter_bg, typewriter_scroll_clear_window);
|
||||
m_bitmap.fill(pen_typewriter_bg, typewriter_scroll_clear_window);
|
||||
}
|
||||
|
||||
void pdp1_state::pdp1_typewriter_drawchar(int character)
|
||||
void pdp1_typewriter_device::drawchar(int character)
|
||||
{
|
||||
static const char ascii_table[2][64] =
|
||||
{ /* n-s = non-spacing */
|
||||
{ /* lower case */
|
||||
{ // n-s = non-spacing
|
||||
{ // lower case
|
||||
' ', '1', '2', '3',
|
||||
'4', '5', '6', '7',
|
||||
'8', '9', '*', '*',
|
||||
@ -392,7 +392,7 @@ void pdp1_state::pdp1_typewriter_drawchar(int character)
|
||||
'h', 'i', '*',/*Lower Case*/ '.',
|
||||
'*',/*Upper Case*/ '*',/*Backspace*/ '*', '*'/*Carriage Return*/
|
||||
},
|
||||
{ /* upper case */
|
||||
{ // upper case
|
||||
' ', '"', '\'', '~',
|
||||
'\202',/*implies*/ '\203',/*or*/ '\204',/*and*/ '<',
|
||||
'>', '\205',/*up arrow*/ '*', '*',
|
||||
@ -419,58 +419,58 @@ void pdp1_state::pdp1_typewriter_drawchar(int character)
|
||||
switch (character)
|
||||
{
|
||||
case 034:
|
||||
/* Black */
|
||||
m_typewriter_color = color_typewriter_black;
|
||||
// Black
|
||||
m_color = color_typewriter_black;
|
||||
break;
|
||||
|
||||
case 035:
|
||||
/* Red */
|
||||
m_typewriter_color = color_typewriter_red;
|
||||
// Red
|
||||
m_color = color_typewriter_red;
|
||||
break;
|
||||
|
||||
case 036:
|
||||
/* Tab */
|
||||
// Tab
|
||||
m_pos = m_pos + tab_step - (m_pos % tab_step);
|
||||
break;
|
||||
|
||||
case 072:
|
||||
/* Lower case */
|
||||
// Lower case
|
||||
m_case_shift = 0;
|
||||
break;
|
||||
|
||||
case 074:
|
||||
/* Upper case */
|
||||
// Upper case
|
||||
m_case_shift = 1;
|
||||
break;
|
||||
|
||||
case 075:
|
||||
/* Backspace */
|
||||
// Backspace
|
||||
if (m_pos)
|
||||
m_pos--;
|
||||
break;
|
||||
|
||||
case 077:
|
||||
/* Carriage Return */
|
||||
// Carriage Return
|
||||
m_pos = 0;
|
||||
pdp1_typewriter_linefeed();
|
||||
linefeed();
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Any printable character... */
|
||||
// Any printable character...
|
||||
|
||||
if (m_pos >= 80)
|
||||
{ /* if past right border, wrap around. (Right???) */
|
||||
pdp1_typewriter_linefeed(); /* next line */
|
||||
m_pos = 0; /* return to start of line */
|
||||
{ // if past right border, wrap around. (Right???)
|
||||
linefeed(); // next line
|
||||
m_pos = 0; // return to start of line
|
||||
}
|
||||
|
||||
/* print character (lookup ASCII equivalent in table) */
|
||||
pdp1_draw_char(m_typewriter_bitmap, ascii_table[m_case_shift][character],
|
||||
// print character (lookup ASCII equivalent in table)
|
||||
m_driver_state->pdp1_draw_char(m_bitmap, ascii_table[m_case_shift][character],
|
||||
8*m_pos, typewriter_write_offset_y,
|
||||
m_typewriter_color); /* print char */
|
||||
m_color); // print char
|
||||
|
||||
if ((character!= 040) && (character!= 056)) /* 040 and 056 are non-spacing characters */
|
||||
m_pos++; /* step carriage forward */
|
||||
if ((character!= 040) && (character!= 056)) // 040 and 056 are non-spacing characters
|
||||
m_pos++; // step carriage forward
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -483,8 +483,8 @@ static const dasm_table_entry dasm_table[] =
|
||||
{ "nsc8105", be, 0, []() -> util::disasm_interface * { return new m680x_disassembler(8105); } },
|
||||
{ "pace", le, -1, []() -> util::disasm_interface * { return new pace_disassembler; } },
|
||||
{ "patinho_feio", le, 0, []() -> util::disasm_interface * { return new patinho_feio_disassembler; } },
|
||||
{ "pdp1", be, 0, []() -> util::disasm_interface * { return new pdp1_disassembler; } },
|
||||
{ "pdp8", be, 0, []() -> util::disasm_interface * { return new pdp8_disassembler; } },
|
||||
{ "pdp1", be, -2, []() -> util::disasm_interface * { return new pdp1_disassembler; } },
|
||||
{ "pdp8", be, -1, []() -> util::disasm_interface * { return new pdp8_disassembler; } },
|
||||
{ "pic16", le, -1, []() -> util::disasm_interface * { return new pic16_disassembler; } },
|
||||
{ "pic16c5x", le, -1, []() -> util::disasm_interface * { return new pic16c5x_disassembler; } },
|
||||
{ "pic1670", le, -1, []() -> util::disasm_interface * { return new pic1670_disassembler; } },
|
||||
|
Loading…
Reference in New Issue
Block a user