summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2020-09-13 20:49:52 -0700
committer Aaron Giles <aaron@aarongiles.com>2020-09-13 20:49:52 -0700
commit72be63e246b6f4f4cfa991a47f7a23645ce403ad (patch)
tree2d50b59e2d81c508cf300d4f713ef64f55f8a599
parent83e54266ab000f0035660d48d618b12020a832d7 (diff)
parentcfeef27495b0daa3d5ee6eb67c251ff1e2efdd95 (diff)
Merge branch 'master' of https://github.com/mamedev/mame
-rw-r--r--plugins/cheat/init.lua202
-rw-r--r--src/devices/cpu/pdp1/pdp1.cpp90
-rw-r--r--src/devices/cpu/pdp1/pdp1.h33
-rw-r--r--src/devices/cpu/pdp1/pdp1dasm.cpp4
-rw-r--r--src/devices/cpu/pdp8/pdp8.cpp2
-rw-r--r--src/devices/cpu/pdp8/pdp8dasm.cpp4
-rw-r--r--src/devices/sound/multipcm.cpp52
-rw-r--r--src/emu/debug/dvmemory.cpp2
-rw-r--r--src/emu/save.cpp6
-rw-r--r--src/emu/save.h14
-rw-r--r--src/frontend/mame/luaengine.cpp7
-rw-r--r--src/mame/drivers/bublbobl.cpp9
-rw-r--r--src/mame/drivers/pdp1.cpp709
-rw-r--r--src/mame/includes/pdp1.h264
-rw-r--r--src/mame/video/pdp1.cpp66
-rw-r--r--src/tools/unidasm.cpp4
16 files changed, 735 insertions, 733 deletions
diff --git a/plugins/cheat/init.lua b/plugins/cheat/init.lua
index 3ac15851404..2293e3c0605 100644
--- a/plugins/cheat/init.lua
+++ b/plugins/cheat/init.lua
@@ -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
diff --git a/src/devices/cpu/pdp1/pdp1.cpp b/src/devices/cpu/pdp1/pdp1.cpp
index a8704ad29d3..389c2fa75e3 100644
--- a/src/devices/cpu/pdp1/pdp1.cpp
+++ b/src/devices/cpu/pdp1/pdp1.cpp
@@ -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();
}
diff --git a/src/devices/cpu/pdp1/pdp1.h b/src/devices/cpu/pdp1/pdp1.h
index 1c2d5c7eea3..570f8afab4d 100644
--- a/src/devices/cpu/pdp1/pdp1.h
+++ b/src/devices/cpu/pdp1/pdp1.h
@@ -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;
diff --git a/src/devices/cpu/pdp1/pdp1dasm.cpp b/src/devices/cpu/pdp1/pdp1dasm.cpp
index 9b04c91ec87..0c3286a9257 100644
--- a/src/devices/cpu/pdp1/pdp1dasm.cpp
+++ b/src/devices/cpu/pdp1/pdp1dasm.cpp
@@ -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 &params)
@@ -290,5 +290,5 @@ offs_t pdp1_disassembler::disassemble(std::ostream &stream, offs_t pc, const dat
//etime = 5;
break;
}
- return 4;
+ return 1;
}
diff --git a/src/devices/cpu/pdp8/pdp8.cpp b/src/devices/cpu/pdp8/pdp8.cpp
index 3084c1bb29d..e8090c8dfde 100644
--- a/src/devices/cpu/pdp8/pdp8.cpp
+++ b/src/devices/cpu/pdp8/pdp8.cpp
@@ -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),
diff --git a/src/devices/cpu/pdp8/pdp8dasm.cpp b/src/devices/cpu/pdp8/pdp8dasm.cpp
index 389cf11fda7..8c2e57573b5 100644
--- a/src/devices/cpu/pdp8/pdp8dasm.cpp
+++ b/src/devices/cpu/pdp8/pdp8dasm.cpp
@@ -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 &params)
@@ -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);
}
diff --git a/src/devices/sound/multipcm.cpp b/src/devices/sound/multipcm.cpp
index 34e0e95b511..c4a5892990f 100644
--- a/src/devices/sound/multipcm.cpp
+++ b/src/devices/sound/multipcm.cpp
@@ -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)
{
diff --git a/src/emu/debug/dvmemory.cpp b/src/emu/debug/dvmemory.cpp
index 7f07e48b6ed..fe1b9da419a 100644
--- a/src/emu/debug/dvmemory.cpp
+++ b/src/emu/debug/dvmemory.cpp
@@ -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))
diff --git a/src/emu/save.cpp b/src/emu/save.cpp
index b2456d17b6f..b95ff1796b4 100644
--- a/src/emu/save.cpp
+++ b/src/emu/save.cpp
@@ -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;
diff --git a/src/emu/save.h b/src/emu/save.h
index c892cd0b2ba..f31e3762d5b 100644
--- a/src/emu/save.h
+++ b/src/emu/save.h
@@ -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
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index 8e7ad2665be..4f44c3ad9d4 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -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:
diff --git a/src/mame/drivers/bublbobl.cpp b/src/mame/drivers/bublbobl.cpp
index 77e839790b8..57b5c77c633 100644
--- a/src/mame/drivers/bublbobl.cpp
+++ b/src/mame/drivers/bublbobl.cpp
@@ -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 )
diff --git a/src/mame/drivers/pdp1.cpp b/src/mame/drivers/pdp1.cpp
index 72861de561b..5be34e9984b 100644
--- a/src/mame/drivers/pdp1.cpp
+++ b/src/mame/drivers/pdp1.cpp
@@ -382,29 +382,6 @@ or both IOT incompletely, or screw up completely. I insist that such an error c
by a pdp-1 programming error, even if there is no emulator error. */
#define LOG_IOT_OVERLAP 0
-static void pdp1_tape_read_binary(device_t *device);
-static void pdp1_io_sc_callback(device_t *device);
-
-static void iot_rpa(device_t *device, int op2, int nac, int mb, int *io, int ac);
-static void iot_rpb(device_t *device, int op2, int nac, int mb, int *io, int ac);
-static void iot_rrb(device_t *device, int op2, int nac, int mb, int *io, int ac);
-static void iot_ppa(device_t *device, int op2, int nac, int mb, int *io, int ac);
-static void iot_ppb(device_t *device, int op2, int nac, int mb, int *io, int ac);
-
-static void iot_tyo(device_t *device, int op2, int nac, int mb, int *io, int ac);
-static void iot_tyi(device_t *device, int op2, int nac, int mb, int *io, int ac);
-
-static void iot_dpy(device_t *device, int op2, int nac, int mb, int *io, int ac);
-
-static void iot_dia(device_t *device, int op2, int nac, int mb, int *io, int ac);
-static void iot_dba(device_t *device, int op2, int nac, int mb, int *io, int ac);
-static void iot_dcc(device_t *device, int op2, int nac, int mb, int *io, int ac);
-static void iot_dra(device_t *device, int op2, int nac, int mb, int *io, int ac);
-
-static void iot_011(device_t *device, int op2, int nac, int mb, int *io, int ac);
-
-static void iot_cks(device_t *device, int op2, int nac, int mb, int *io, int ac);
-
/*
devices which are known to generate a completion pulse (source: maintenance manual 9-??,
@@ -451,33 +428,6 @@ enum
static pdp1_reset_param_t pdp1_reset_param =
{
- { /* external iot handlers. NULL means that the iot is unimplemented, unless there are
- parentheses around the iot name, in which case the iot is internal to the cpu core. */
- /* I put a ? when the source is the handbook, since a) I have used the maintenance manual
- as the primary source (as it goes more into details) b) the handbook and the maintenance
- manual occasionnally contradict each other. */
- /* dia, dba, dcc, dra are documented in MIT PDP-1 COMPUTER MODIFICATION
- BULLETIN no. 2 (drumInstrWriteup.bin/drumInstrWriteup.txt), and are
- similar to IOT documented in Parallel Drum Type 23 Instruction Manual. */
- /* (iot) rpa rpb tyo tyi ppa ppb dpy */
- nullptr, iot_rpa, iot_rpb, iot_tyo, iot_tyi, iot_ppa, iot_ppb, iot_dpy,
- /* spacewar */
- nullptr, iot_011, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- /* lag glf?/jsp? gpl?/gpr?/gcf? */
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- /* rrb rcb? rcc? cks mcs mes mel */
- iot_rrb, nullptr, nullptr, iot_cks, nullptr, nullptr, nullptr, nullptr,
- /* cad? rac? rbc? pac lpr/lfb/lsp swc/sci/sdf?/shr? scv? */
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- /* (dsc) (asc) (isb) (cac) (lsm) (esm) (cbs) */
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- /* icv? dia dba dcc dra mri|rlc? mrf/inr?/ccr? */
- nullptr, iot_dia, iot_dba, iot_dcc, iot_dra, nullptr, nullptr, nullptr,
- /* mcb|dur? mwc|mtf? mrc|sfc?... msm|cgo? (eem/lem) mic muf */
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- },
- pdp1_tape_read_binary,
- pdp1_io_sc_callback,
0, /* extend mode support defined in input ports and pdp1_init_machine */
0, /* hardware multiply/divide support defined in input ports and pdp1_init_machine */
0 /* type 20 sequence break system support defined in input ports and pdp1_init_machine */
@@ -492,7 +442,7 @@ void pdp1_state::machine_reset()
pdp1_reset_param.type_20_sbs = (cfg >> pdp1_config_type_20_sbs_bit) & pdp1_config_type_20_sbs_mask;
/* reset device state */
- m_tape_reader.rcl = m_tape_reader.rc = 0;
+ m_tape_reader->m_rcl = m_tape_reader->m_rc = 0;
m_io_status = io_st_tyo | io_st_ptp;
m_lightpen.active = m_lightpen.down = 0;
m_lightpen.x = m_lightpen.y = 0;
@@ -505,7 +455,7 @@ void pdp1_state::pdp1_machine_stop()
{
/* the core will take care of freeing the timers, BUT we must set the variables
to NULL if we don't want to risk confusing the tape image init function */
- m_tape_reader.timer = m_tape_puncher.timer = m_typewriter.tyo_timer = m_dpy_timer = nullptr;
+ m_tape_reader->m_timer = m_tape_puncher->m_timer = m_typewriter->m_tyo_timer = m_dpy_timer = nullptr;
}
@@ -649,12 +599,7 @@ void pdp1_state::machine_start()
machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&pdp1_state::pdp1_machine_stop,this));
- m_tape_reader.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pdp1_state::reader_callback),this));
- m_tape_puncher.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pdp1_state::puncher_callback),this));
- m_typewriter.tyo_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pdp1_state::tyo_callback),this));
m_dpy_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pdp1_state::dpy_callback),this));
- m_tape_reader.timer->adjust(attotime::zero, 0, attotime::from_hz(2500));
- m_tape_reader.timer->enable(0);
}
@@ -662,136 +607,85 @@ void pdp1_state::machine_start()
perforated tape handling
*/
-class pdp1_readtape_image_device : public device_t,
- public device_image_interface
-{
-public:
- // construction/destruction
- pdp1_readtape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // 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;
-
-protected:
- // device-level overrides
- virtual void device_start() override { }
-};
-
-DEFINE_DEVICE_TYPE(PDP1_READTAPE, pdp1_readtape_image_device, "pdp1_readtape_image", "PDP1 Tape Reader")
+DEFINE_DEVICE_TYPE(PDP1_READTAPE, pdp1_readtape_image_device, "pdp1_readtape_image", "PDP-1 Tape Reader")
pdp1_readtape_image_device::pdp1_readtape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, PDP1_READTAPE, tag, owner, clock)
, device_image_interface(mconfig, *this)
+ , m_maincpu(*this, "^maincpu")
+ , m_st_ptr(*this)
{
}
-class pdp1_punchtape_image_device : public device_t,
- public device_image_interface
+void pdp1_readtape_image_device::device_resolve_objects()
{
-public:
- // construction/destruction
- pdp1_punchtape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // 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;
-
-protected:
- // device-level overrides
- virtual void device_start() override { }
-};
+ m_st_ptr.resolve_safe();
+}
+
+void pdp1_readtape_image_device::device_start()
+{
+ m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pdp1_readtape_image_device::reader_callback),this));
+ m_timer->adjust(attotime::zero, 0, attotime::from_hz(2500));
+ m_timer->enable(0);
+}
+
-DEFINE_DEVICE_TYPE(PDP1_PUNCHTAPE, pdp1_punchtape_image_device, "pdp1_punchtape_image_device", "PDP1 Tape Puncher")
+DEFINE_DEVICE_TYPE(PDP1_PUNCHTAPE, pdp1_punchtape_image_device, "pdp1_punchtape_image_device", "PDP-1 Tape Puncher")
pdp1_punchtape_image_device::pdp1_punchtape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, PDP1_PUNCHTAPE, tag, owner, clock)
, device_image_interface(mconfig, *this)
+ , m_maincpu(*this, "^maincpu")
+ , m_st_ptp(*this)
{
}
+void pdp1_punchtape_image_device::device_resolve_objects()
+{
+ m_st_ptp.resolve_safe();
+}
-class pdp1_printer_image_device : public device_t,
- public device_image_interface
+void pdp1_punchtape_image_device::device_start()
{
-public:
- // construction/destruction
- pdp1_printer_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // 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;
-
-protected:
- // device-level overrides
- virtual void device_start() override { }
-};
+ m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pdp1_punchtape_image_device::puncher_callback),this));
+}
-DEFINE_DEVICE_TYPE(PDP1_PRINTER, pdp1_printer_image_device, "pdp1_printer_image", "PDP1 Typewriter")
-pdp1_printer_image_device::pdp1_printer_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, PDP1_PRINTER, tag, owner, clock)
+DEFINE_DEVICE_TYPE(PDP1_TYPEWRITER, pdp1_typewriter_device, "pdp1_typewriter_image", "PDP-1 Typewriter")
+
+pdp1_typewriter_device::pdp1_typewriter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PDP1_TYPEWRITER, tag, owner, clock)
, device_image_interface(mconfig, *this)
+ , m_maincpu(*this, "^maincpu")
+ , m_driver_state(*this, DEVICE_SELF_OWNER)
+ , m_twr(*this, "^TWR.%u", 0)
+ , m_st_tyo(*this)
+ , m_st_tyi(*this)
{
}
-class pdp1_cylinder_image_device : public device_t,
- public device_image_interface
+void pdp1_typewriter_device::device_resolve_objects()
{
-public:
- // construction/destruction
- pdp1_cylinder_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // 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;
-
-protected:
- // device-level overrides
- virtual void device_start() override { }
-};
+ m_st_tyo.resolve_safe();
+ m_st_tyi.resolve_safe();
+}
-DEFINE_DEVICE_TYPE(PDP1_CYLINDER, pdp1_cylinder_image_device, "pdp1_cylinder_image", "PDP1 Cylinder")
+void pdp1_typewriter_device::device_start()
+{
+ m_tyo_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pdp1_typewriter_device::tyo_callback),this));
+}
+
+
+DEFINE_DEVICE_TYPE(PDP1_CYLINDER, pdp1_cylinder_image_device, "pdp1_cylinder_image", "PDP-1 Cylinder")
pdp1_cylinder_image_device::pdp1_cylinder_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, PDP1_CYLINDER, tag, owner, clock)
, device_image_interface(mconfig, *this)
+ , m_maincpu(*this, "^maincpu")
+{
+}
+
+void pdp1_cylinder_image_device::device_start()
{
}
@@ -800,28 +694,23 @@ pdp1_cylinder_image_device::pdp1_cylinder_image_device(const machine_config &mco
*/
image_init_result pdp1_readtape_image_device::call_load()
{
- pdp1_state *state = machine().driver_data<pdp1_state>();
-
- /* reader unit */
- state->m_tape_reader.fd = this;
-
- /* start motor */
- state->m_tape_reader.motor_on = 1;
+ // start motor
+ m_motor_on = 1;
/* restart reader IO when necessary */
/* note that this function may be called before pdp1_init_machine, therefore
- before state->m_tape_reader.timer is allocated. It does not matter, as the clutch is never
+ before m_timer is allocated. It does not matter, as the clutch is never
down at power-up, but we must not call timer_enable with a nullptr parameter! */
- if (state->m_tape_reader.timer)
+ if (m_timer)
{
- if (state->m_tape_reader.motor_on && state->m_tape_reader.rcl)
+ if (m_motor_on && m_rcl)
{
- state->m_tape_reader.timer->enable(1);
+ m_timer->enable(1);
}
else
{
- state->m_tape_reader.timer->enable(0);
+ m_timer->enable(0);
}
}
@@ -830,24 +719,19 @@ image_init_result pdp1_readtape_image_device::call_load()
void pdp1_readtape_image_device::call_unload()
{
- pdp1_state *state = machine().driver_data<pdp1_state>();
-
- /* reader unit */
- state->m_tape_reader.fd = nullptr;
-
- /* stop motor */
- state->m_tape_reader.motor_on = 0;
+ // stop motor
+ m_motor_on = 0;
- if (state->m_tape_reader.timer)
- state->m_tape_reader.timer->enable(0);
+ if (m_timer)
+ m_timer->enable(0);
}
/*
Read a byte from perforated tape
*/
-int pdp1_state::tape_read(uint8_t *reply)
+int pdp1_readtape_image_device::tape_read(uint8_t *reply)
{
- if (m_tape_reader.fd && (m_tape_reader.fd->fread(reply, 1) == 1))
+ if (is_loaded() && (fread(reply, 1) == 1))
return 0; /* unit OK */
else
return 1; /* unit not ready */
@@ -857,91 +741,88 @@ int pdp1_state::tape_read(uint8_t *reply)
/*
common code for tape read commands (RPA, RPB, and read-in mode)
*/
-void pdp1_state::begin_tape_read( int binary, int nac)
+void pdp1_readtape_image_device::begin_tape_read(int binary, int nac)
{
- m_tape_reader.rb = 0;
- m_tape_reader.rcl = 1;
- m_tape_reader.rc = (binary) ? 1 : 3;
- m_tape_reader.rby = (binary) ? 1 : 0;
- m_tape_reader.rcp = nac;
+ m_rb = 0;
+ m_rcl = 1;
+ m_rc = (binary) ? 1 : 3;
+ m_rby = (binary) ? 1 : 0;
+ m_rcp = nac;
if (LOG_IOT_OVERLAP)
{
- if (m_tape_reader.timer->enable(0))
+ if (m_timer->enable(0))
logerror("Error: overlapped perforated tape reads (Read-in mode, RPA/RPB instruction)\n");
}
/* set up delay if tape is advancing */
- if (m_tape_reader.motor_on && m_tape_reader.rcl)
+ if (m_motor_on && m_rcl)
{
/* delay is approximately 1/400s */
- m_tape_reader.timer->enable(1);
+ m_timer->enable(1);
}
else
{
- m_tape_reader.timer->enable(0);
+ m_timer->enable(0);
}
}
/*
timer callback to simulate reader IO
*/
-TIMER_CALLBACK_MEMBER(pdp1_state::reader_callback)
+TIMER_CALLBACK_MEMBER(pdp1_readtape_image_device::reader_callback)
{
- int not_ready;
- uint8_t data;
-
- if (m_tape_reader.rc)
+ if (m_rc)
{
- not_ready = tape_read(& data);
+ uint8_t data;
+ int not_ready = tape_read(&data);
if (not_ready)
{
- m_tape_reader.motor_on = 0; /* let us stop the motor */
+ m_motor_on = 0; // let us stop the motor
}
else
{
- if ((! m_tape_reader.rby) || (data & 0200))
+ if ((!m_rby) || (data & 0200))
{
- m_tape_reader.rb |= (m_tape_reader.rby) ? (data & 077) : data;
+ m_rb |= (m_rby) ? (data & 077) : data;
- if (m_tape_reader.rc != 3)
+ if (m_rc != 3)
{
- m_tape_reader.rb <<= 6;
+ m_rb <<= 6;
}
- m_tape_reader.rc = (m_tape_reader.rc+1) & 3;
+ m_rc = (m_rc+1) & 3;
- if (m_tape_reader.rc == 0)
- { /* IO complete */
- m_tape_reader.rcl = 0;
- if (m_tape_reader.rcp)
+ if (m_rc == 0)
+ { // IO complete
+ m_rcl = 0;
+ if (m_rcp)
{
- m_maincpu->set_state_int(PDP1_IO, m_tape_reader.rb); /* transfer reader buffer to IO */
+ m_maincpu->set_state_int(PDP1_IO, m_rb); // transfer reader buffer to IO
m_maincpu->set_state_int(PDP1_IOS,1);
}
else
- m_io_status |= io_st_ptr;
+ m_st_ptr(1);
}
}
}
}
- if (m_tape_reader.motor_on && m_tape_reader.rcl)
+ if (m_motor_on && m_rcl)
{
- m_tape_reader.timer->enable(1);
+ m_timer->enable(1);
}
else
{
- m_tape_reader.timer->enable(0);
+ m_timer->enable(0);
}
}
/*
Initiate read of a 18-bit word in binary format from tape (used in read-in mode)
*/
-void pdp1_tape_read_binary(device_t *device)
+void pdp1_readtape_image_device::tape_read_binary()
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
- state->begin_tape_read(1, 1);
+ begin_tape_read(1, 1);
}
/*
@@ -971,13 +852,12 @@ void pdp1_tape_read_binary(device_t *device)
* IO Bits 10 11 12 13 14 15 16 17
* TAPE CHANNELS 8 7 6 5 4 3 2 1
*/
-static void iot_rpa(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_readtape_image_device::iot_rpa(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
if (LOG_IOT_EXTRA)
- device->logerror("Warning, RPA instruction not fully emulated: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ logerror("Warning, RPA instruction not fully emulated: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
- state->begin_tape_read(0, nac);
+ begin_tape_read(0, nac);
}
/*
@@ -1009,63 +889,52 @@ static void iot_rpa(device_t *device, int op2, int nac, int mb, int *io, int ac)
* different (730002 or 724002) the 18-bit word read from tape is automatically
* transferred to the IO Register via the Reader Buffer.
*/
-static void iot_rpb(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_readtape_image_device::iot_rpb(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
if (LOG_IOT_EXTRA)
- device->logerror("Warning, RPB instruction not fully emulated: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ logerror("Warning, RPB instruction not fully emulated: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
- state->begin_tape_read(1, nac);
+ begin_tape_read(1, nac);
}
/*
rrb iot callback
*/
-static void iot_rrb(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_readtape_image_device::iot_rrb(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
if (LOG_IOT_EXTRA)
- device->logerror("RRB instruction: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ logerror("RRB instruction: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
- *io = state->m_tape_reader.rb;
- state->m_io_status &= ~io_st_ptr;
+ io = m_rb;
+ m_st_ptr(0);
}
image_init_result pdp1_punchtape_image_device::call_load()
{
- pdp1_state *state = machine().driver_data<pdp1_state>();
-
- /* punch unit */
- state->m_tape_puncher.fd = this;
-
return image_init_result::PASS;
}
void pdp1_punchtape_image_device::call_unload()
{
- pdp1_state *state = machine().driver_data<pdp1_state>();
-
- /* punch unit */
- state->m_tape_puncher.fd = nullptr;
}
/*
Write a byte to perforated tape
*/
-void pdp1_state::tape_write(uint8_t data)
+void pdp1_punchtape_image_device::tape_write(uint8_t data)
{
- if (m_tape_puncher.fd)
- m_tape_puncher.fd->fwrite(& data, 1);
+ if (is_loaded())
+ fwrite(&data, 1);
}
/*
timer callback to generate punch completion pulse
*/
-TIMER_CALLBACK_MEMBER(pdp1_state::puncher_callback)
+TIMER_CALLBACK_MEMBER(pdp1_punchtape_image_device::puncher_callback)
{
int nac = param;
- m_io_status |= io_st_ptp;
+ m_st_ptp(1);
if (nac)
{
m_maincpu->set_state_int(PDP1_IOS,1);
@@ -1086,22 +955,21 @@ TIMER_CALLBACK_MEMBER(pdp1_state::puncher_callback)
* For each In-Out Transfer instruction one line of tape is punched. In-Out Register
* Bit 17 conditions Hole 1. Bit 16 conditions Hole 2, etc. Bit 10 conditions Hole 8
*/
-static void iot_ppa(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_punchtape_image_device::iot_ppa(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
if (LOG_IOT_EXTRA)
- device->logerror("PPA instruction: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ logerror("PPA instruction: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
- state->tape_write(*io & 0377);
- state->m_io_status &= ~io_st_ptp;
- /* delay is approximately 1/63.3 second */
+ tape_write(io & 0377);
+ m_st_ptp(0);
+ // delay is approximately 1/63.3 second
if (LOG_IOT_OVERLAP)
{
- if (state->m_tape_puncher.timer->enable(0))
- device->logerror("Error: overlapped PPA/PPB instructions: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ if (m_timer->enable(0))
+ logerror("Error: overlapped PPA/PPB instructions: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
}
- state->m_tape_puncher.timer->adjust(attotime::from_usec(15800), nac);
+ m_timer->adjust(attotime::from_usec(15800), nac);
}
/*
@@ -1115,21 +983,20 @@ static void iot_ppa(device_t *device, int op2, int nac, int mb, int *io, int ac)
* Bit 5 conditions Hole 1. Bit 4 conditions Hole 2, etc. Bit 0 conditions Hole 6.
* Hole 7 is left blank. Hole 8 is always punched in this mode.
*/
-static void iot_ppb(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_punchtape_image_device::iot_ppb(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
if (LOG_IOT_EXTRA)
- device->logerror("PPB instruction: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ logerror("PPB instruction: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
- state->tape_write((*io >> 12) | 0200);
- state->m_io_status &= ~io_st_ptp;
+ tape_write((io >> 12) | 0200);
+ m_st_ptp(0);
/* delay is approximately 1/63.3 second */
if (LOG_IOT_OVERLAP)
{
- if (state->m_tape_puncher.timer->enable(0))
- device->logerror("Error: overlapped PPA/PPB instructions: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ if (m_timer->enable(0))
+ logerror("Error: overlapped PPA/PPB instructions: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
}
- state->m_tape_puncher.timer->adjust(attotime::from_usec(15800), nac);
+ m_timer->adjust(attotime::from_usec(15800), nac);
}
@@ -1143,35 +1010,29 @@ static void iot_ppb(device_t *device, int op2, int nac, int mb, int *io, int ac)
/*
Open a file for typewriter output
*/
-image_init_result pdp1_printer_image_device::call_load()
+image_init_result pdp1_typewriter_device::call_load()
{
- pdp1_state *state = machine().driver_data<pdp1_state>();
- /* open file */
- state->m_typewriter.fd = this;
-
- state->m_io_status |= io_st_tyo;
+ m_st_tyo(1);
return image_init_result::PASS;
}
-void pdp1_printer_image_device::call_unload()
+void pdp1_typewriter_device::call_unload()
{
- pdp1_state *state = machine().driver_data<pdp1_state>();
- state->m_typewriter.fd = nullptr;
}
/*
Write a character to typewriter
*/
-void pdp1_state::typewriter_out(uint8_t data)
+void pdp1_typewriter_device::typewriter_out(uint8_t data)
{
if (LOG_IOT_EXTRA)
logerror("typewriter output %o\n", data);
- pdp1_typewriter_drawchar(data);
- if (m_typewriter.fd)
+ drawchar(data);
+ if (is_loaded())
#if 1
- m_typewriter.fd->fwrite(& data, 1);
+ fwrite(& data, 1);
#else
{
static const char ascii_table[2][64] =
@@ -1219,47 +1080,47 @@ void pdp1_state::typewriter_out(uint8_t data)
switch (data)
{
case 034:
- /* Black: ignore */
+ // Black: ignore
//color = color_typewriter_black;
{
static const char black[5] = { '\033', '[', '3', '0', 'm' };
- image_fwrite(m_typewriter.fd, black, sizeof(black));
+ fwrite(black, sizeof(black));
}
break;
case 035:
- /* Red: ignore */
+ // Red: ignore
//color = color_typewriter_red;
{
static const char red[5] = { '\033', '[', '3', '1', 'm' };
- image_fwrite(m_typewriter.fd, red, sizeof(red));
+ fwrite(red, sizeof(red));
}
break;
case 072:
- /* Lower case */
+ // Lower case
m_case_shift = 0;
break;
case 074:
- /* Upper case */
+ // Upper case
m_case_shift = 1;
break;
case 077:
- /* Carriage Return */
+ // Carriage Return
{
static const char line_end[2] = { '\r', '\n' };
- image_fwrite(m_typewriter.fd, line_end, sizeof(line_end));
+ fwrite(line_end, sizeof(line_end));
}
break;
default:
- /* Any printable character... */
+ // Any printable character...
- if ((data != 040) && (data != 056)) /* 040 and 056 are non-spacing characters: don't try to print right now */
+ if ((data != 040) && (data != 056)) // 040 and 056 are non-spacing characters: don't try to print right now
/* print character (lookup ASCII equivalent in table) */
- image_fwrite(m_typewriter.fd, & ascii_table[m_case_shift][data], 1);
+ fwrite(&ascii_table[m_case_shift][data], 1);
break;
}
@@ -1270,10 +1131,10 @@ void pdp1_state::typewriter_out(uint8_t data)
/*
timer callback to generate typewriter completion pulse
*/
-TIMER_CALLBACK_MEMBER(pdp1_state::tyo_callback)
+TIMER_CALLBACK_MEMBER(pdp1_typewriter_device::tyo_callback)
{
int nac = param;
- m_io_status |= io_st_tyo;
+ m_st_tyo(1);
if (nac)
{
m_maincpu->set_state_int(PDP1_IOS,1);
@@ -1283,20 +1144,18 @@ TIMER_CALLBACK_MEMBER(pdp1_state::tyo_callback)
/*
tyo iot callback
*/
-static void iot_tyo(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_typewriter_device::iot_tyo(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
- int ch, delay;
-
if (LOG_IOT_EXTRA)
- device->logerror("Warning, TYO instruction not fully emulated: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ logerror("Warning, TYO instruction not fully emulated: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
- ch = (*io) & 077;
+ int ch = io & 077;
- state->typewriter_out(ch);
- state->m_io_status &= ~io_st_tyo;
+ typewriter_out(ch);
+ m_st_tyo(0);
/* compute completion delay (source: maintenance manual 9-12, 9-13 and 9-14) */
+ int delay;
switch (ch)
{
case 072: /* lower-case */
@@ -1316,11 +1175,11 @@ static void iot_tyo(device_t *device, int op2, int nac, int mb, int *io, int ac)
}
if (LOG_IOT_OVERLAP)
{
- if (state->m_typewriter.tyo_timer->enable(0))
- device->logerror("Error: overlapped TYO instruction: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ if (m_tyo_timer->enable(0))
+ logerror("Error: overlapped TYO instruction: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
}
- state->m_typewriter.tyo_timer->adjust(attotime::from_msec(delay), nac);
+ m_tyo_timer->adjust(attotime::from_msec(delay), nac);
}
/*
@@ -1337,21 +1196,16 @@ static void iot_tyo(device_t *device, int op2, int nac, int mb, int *io, int ac)
* clears the In-Out Register before transferring the information and also clears
* the type-in status bit.
*/
-static void iot_tyi(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_typewriter_device::iot_tyi(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
if (LOG_IOT_EXTRA)
- device->logerror("Warning, TYI instruction not fully emulated: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ logerror("Warning, TYI instruction not fully emulated: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
- *io = state->m_typewriter.tb;
- if (! (state->m_io_status & io_st_tyi))
- *io |= 0100;
+ io = m_tb;
+ if (! (m_driver_state->m_io_status & io_st_tyi))
+ io |= 0100;
else
- {
- state->m_io_status &= ~io_st_tyi;
- if (USE_SBS)
- state->m_maincpu->set_input_line(0, CLEAR_LINE); /* PDP1 - interrupt it, baby */
- }
+ m_st_tyi(0);
}
@@ -1403,25 +1257,20 @@ TIMER_CALLBACK_MEMBER(pdp1_state::dpy_callback)
Light on one pixel on CRT
*/
-static void iot_dpy(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_state::iot_dpy(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
- int x;
- int y;
-
-
- x = ((ac+0400000) & 0777777) >> 8;
- y = (((*io)+0400000) & 0777777) >> 8;
- state->pdp1_plot(x, y);
+ int x = ((ac+0400000) & 0777777) >> 8;
+ int y = ((io+0400000) & 0777777) >> 8;
+ pdp1_plot(x, y);
/* light pen 32 support */
- state->m_io_status &= ~io_st_pen;
+ m_io_status &= ~io_st_pen;
- if (state->m_lightpen.down && ((x-state->m_lightpen.x)*(x-state->m_lightpen.x)+(y-state->m_lightpen.y)*(y-state->m_lightpen.y) < state->m_lightpen.radius*state->m_lightpen.radius))
+ if (m_lightpen.down && ((x-m_lightpen.x)*(x-m_lightpen.x)+(y-m_lightpen.y)*(y-m_lightpen.y) < m_lightpen.radius*m_lightpen.radius))
{
- state->m_io_status |= io_st_pen;
+ m_io_status |= io_st_pen;
- state->m_maincpu->set_state_int(PDP1_PF3, 1);
+ m_maincpu->set_state_int(PDP1_PF3, 1);
}
if (nac)
@@ -1431,10 +1280,10 @@ static void iot_dpy(device_t *device, int op2, int nac, int mb, int *io, int ac)
{
/* note that overlap detection is incomplete: it will only work if both DPY
instructions require a completion pulse */
- if (state->m_dpy_timer->enable(0))
- device->logerror("Error: overlapped DPY instruction: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ if (m_dpy_timer->enable(0))
+ logerror("Error: overlapped DPY instruction: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
}
- state->m_dpy_timer->adjust(attotime::from_usec(50));
+ m_dpy_timer->adjust(attotime::from_usec(50));
}
}
@@ -1444,35 +1293,33 @@ static void iot_dpy(device_t *device, int op2, int nac, int mb, int *io, int ac)
MIT parallel drum (variant of type 23)
*/
-void pdp1_state::parallel_drum_set_il(int il)
+void pdp1_cylinder_image_device::set_il(int il)
{
- attotime il_phase;
+ m_il = il;
- m_parallel_drum.il = il;
-
- il_phase = ((PARALLEL_DRUM_WORD_TIME * il) - m_parallel_drum.rotation_timer->elapsed());
+ attotime il_phase = ((PARALLEL_DRUM_WORD_TIME * il) - m_rotation_timer->elapsed());
if (il_phase < attotime::zero)
il_phase = il_phase + PARALLEL_DRUM_ROTATION_TIME;
- m_parallel_drum.il_timer->adjust(il_phase, 0, PARALLEL_DRUM_ROTATION_TIME);
+ m_il_timer->adjust(il_phase, 0, PARALLEL_DRUM_ROTATION_TIME);
}
#ifdef UNUSED_FUNCTION
-TIMER_CALLBACK_MEMBER(pdp1_state::il_timer_callback)
+TIMER_CALLBACK_MEMBER(pdp1_cylinder_image_device::il_timer_callback)
{
- if (m_parallel_drum.dba)
+ if (m_dba)
{
/* set break request and status bit 5 */
/* ... */
}
}
-void pdp1_state::parallel_drum_init(pdp1_state *state)
+void pdp1_cylinder_image_device::parallel_drum_init(pdp1_state *state)
{
- m_parallel_drum.rotation_timer = machine().scheduler().timer_alloc();
- m_parallel_drum.rotation_timer->adjust(PARALLEL_DRUM_ROTATION_TIME, 0, PARALLEL_DRUM_ROTATION_TIME);
+ m_rotation_timer = machine().scheduler().timer_alloc();
+ m_rotation_timer->adjust(PARALLEL_DRUM_ROTATION_TIME, 0, PARALLEL_DRUM_ROTATION_TIME);
- m_parallel_drum.il_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pdp1_state::il_timer_callback),this));
- parallel_drum_set_il(0);
+ m_il_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pdp1_cylinder_image_device::il_timer_callback),this));
+ set_il(0);
}
#endif
@@ -1481,46 +1328,38 @@ void pdp1_state::parallel_drum_init(pdp1_state *state)
*/
image_init_result pdp1_cylinder_image_device::call_load()
{
- pdp1_state *state = machine().driver_data<pdp1_state>();
- /* open file */
- state->m_parallel_drum.fd = this;
-
return image_init_result::PASS;
}
void pdp1_cylinder_image_device::call_unload()
{
- pdp1_state *state = machine().driver_data<pdp1_state>();
- state->m_parallel_drum.fd = nullptr;
}
-static void iot_dia(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_cylinder_image_device::iot_dia(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
- state->m_parallel_drum.wfb = ((*io) & 0370000) >> 12;
- state->parallel_drum_set_il((*io) & 0007777);
+ m_wfb = (io & 0370000) >> 12;
+ set_il(io & 0007777);
- state->m_parallel_drum.dba = 0; /* right? */
+ m_dba = 0; /* right? */
}
-static void iot_dba(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_cylinder_image_device::iot_dba(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
- state->m_parallel_drum.wfb = ((*io) & 0370000) >> 12;
- state->parallel_drum_set_il((*io) & 0007777);
+ m_wfb = (io & 0370000) >> 12;
+ set_il(io & 0007777);
- state->m_parallel_drum.dba = 1;
+ m_dba = 1;
}
/*
Read a word from drum
*/
-uint32_t pdp1_state::drum_read(int field, int position)
+uint32_t pdp1_cylinder_image_device::drum_read(int field, int position)
{
int offset = (field*4096+position)*3;
uint8_t buf[3];
- if (m_parallel_drum.fd && (!m_parallel_drum.fd->fseek(offset, SEEK_SET)) && (m_parallel_drum.fd->fread( buf, 3) == 3))
+ if (is_loaded() && (!fseek(offset, SEEK_SET)) && (fread(buf, 3) == 3))
return ((buf[0] << 16) | (buf[1] << 8) | buf[2]) & 0777777;
return 0;
@@ -1529,67 +1368,62 @@ uint32_t pdp1_state::drum_read(int field, int position)
/*
Write a word to drum
*/
-void pdp1_state::drum_write(int field, int position, uint32_t data)
+void pdp1_cylinder_image_device::drum_write(int field, int position, uint32_t data)
{
int offset = (field*4096+position)*3;
uint8_t buf[3];
- if (m_parallel_drum.fd)
+ if (is_loaded())
{
buf[0] = data >> 16;
buf[1] = data >> 8;
buf[2] = data;
- m_parallel_drum.fd->fseek(offset, SEEK_SET);
- m_parallel_drum.fd->fwrite( buf, 3);
+ fseek(offset, SEEK_SET);
+ fwrite(buf, 3);
}
}
-static void iot_dcc(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_cylinder_image_device::iot_dcc(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
- attotime delay;
- int dc;
+ m_rfb = (io & 0370000) >> 12;
+ m_wc = - (io & 0007777);
- state->m_parallel_drum.rfb = ((*io) & 0370000) >> 12;
- state->m_parallel_drum.wc = - ((*io) & 0007777);
+ m_wcl = ac & 0177777/*0007777???*/;
- state->m_parallel_drum.wcl = ac & 0177777/*0007777???*/;
-
- state->m_parallel_drum.dba = 0; /* right? */
+ m_dba = 0; /* right? */
/* clear status bit 5... */
/* do transfer */
- delay = state->m_parallel_drum.il_timer->remaining();
- dc = state->m_parallel_drum.il;
+ attotime delay = m_il_timer->remaining();
+ int dc = m_il;
do
{
- if ((state->m_parallel_drum.wfb >= 1) && (state->m_parallel_drum.wfb <= 22))
+ if ((m_wfb >= 1) && (m_wfb <= 22))
{
- state->drum_write(state->m_parallel_drum.wfb-1, dc, (signed)state->m_maincpu->space(AS_PROGRAM).read_dword(state->m_parallel_drum.wcl<<2));
+ drum_write(m_wfb-1, dc, (signed)m_maincpu->space(AS_PROGRAM).read_dword(m_wcl));
}
- if ((state->m_parallel_drum.rfb >= 1) && (state->m_parallel_drum.rfb <= 22))
+ if ((m_rfb >= 1) && (m_rfb <= 22))
{
- state->m_maincpu->space(AS_PROGRAM).write_dword(state->m_parallel_drum.wcl<<2, state->drum_read(state->m_parallel_drum.rfb-1, dc));
+ m_maincpu->space(AS_PROGRAM).write_dword(m_wcl, drum_read(m_rfb-1, dc));
}
- state->m_parallel_drum.wc = (state->m_parallel_drum.wc+1) & 07777;
- state->m_parallel_drum.wcl = (state->m_parallel_drum.wcl+1) & 0177777/*0007777???*/;
+ m_wc = (m_wc+1) & 07777;
+ m_wcl = (m_wcl+1) & 0177777/*0007777???*/;
dc = (dc+1) & 07777;
- if (state->m_parallel_drum.wc)
+ if (m_wc)
delay = delay + PARALLEL_DRUM_WORD_TIME;
- } while (state->m_parallel_drum.wc);
- state->m_maincpu->adjust_icount(-state->m_maincpu->attotime_to_cycles(delay));
+ } while (m_wc);
+ m_maincpu->adjust_icount(-m_maincpu->attotime_to_cycles(delay));
/* if no error, skip */
- state->m_maincpu->set_state_int(PDP1_PC, state->m_maincpu->state_int(PDP1_PC)+1);
+ m_maincpu->set_state_int(PDP1_PC, m_maincpu->state_int(PDP1_PC)+1);
}
-static void iot_dra(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_cylinder_image_device::iot_dra(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
- (*io) = (state->m_parallel_drum.rotation_timer->elapsed() *
- (ATTOSECONDS_PER_SECOND / (PARALLEL_DRUM_WORD_TIME.as_attoseconds()))).seconds() & 0007777;
+ io = (m_rotation_timer->elapsed() *
+ (ATTOSECONDS_PER_SECOND / (PARALLEL_DRUM_WORD_TIME.as_attoseconds()))).seconds() & 0007777;
/* set parity error and timing error... */
}
@@ -1607,9 +1441,9 @@ static void iot_dra(device_t *device, int op2, int nac, int mb, int *io, int ac)
fire rocket, and fire torpedo. low order 4 bits, same for
other ship. routine is entered by jsp cwg.
*/
-static void iot_011(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_state::iot_011(int op2, int nac, int mb, int &io, int ac)
{
- int key_state = device->machine().driver_data<pdp1_state>()->read_spacewar();
+ int key_state = m_spacewar->read();
int reply;
@@ -1637,7 +1471,7 @@ static void iot_011(device_t *device, int op2, int nac, int mb, int *io, int ac)
if (key_state & HSPACE_PLAYER1)
reply |= 014;
- *io = reply;
+ io = reply;
}
@@ -1646,13 +1480,24 @@ static void iot_011(device_t *device, int op2, int nac, int mb, int *io, int ac)
check IO status
*/
-static void iot_cks(device_t *device, int op2, int nac, int mb, int *io, int ac)
+void pdp1_state::iot_cks(int op2, int nac, int mb, int &io, int ac)
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
if (LOG_IOT_EXTRA)
- device->logerror("CKS instruction: mb=0%06o, (%s)\n", (unsigned) mb, device->machine().describe_context());
+ logerror("CKS instruction: mb=0%06o, (%s)\n", (unsigned) mb, machine().describe_context());
- *io = state->m_io_status;
+ io = m_io_status;
+}
+
+template <int Mask>
+WRITE_LINE_MEMBER(pdp1_state::io_status_w)
+{
+ if (state)
+ m_io_status |= Mask;
+ else
+ m_io_status &= ~Mask;
+
+ if (USE_SBS && Mask == io_st_tyi)
+ m_maincpu->set_input_line(0, state ? ASSERT_LINE : CLEAR_LINE); /* PDP1 - interrupt it, baby */
}
@@ -1661,30 +1506,29 @@ static void iot_cks(device_t *device, int op2, int nac, int mb, int *io, int ac)
IO devices should reset
*/
-void pdp1_io_sc_callback(device_t *device)
+void pdp1_state::io_state_clear()
{
- pdp1_state *state = device->machine().driver_data<pdp1_state>();
- state->m_tape_reader.rcl = state->m_tape_reader.rc = 0;
- if (state->m_tape_reader.timer)
- state->m_tape_reader.timer->enable(0);
+ m_tape_reader->m_rcl = m_tape_reader->m_rc = 0;
+ if (m_tape_reader->m_timer)
+ m_tape_reader->m_timer->enable(0);
- if (state->m_tape_puncher.timer)
- state->m_tape_puncher.timer->enable(0);
+ if (m_tape_puncher->m_timer)
+ m_tape_puncher->m_timer->enable(0);
- if (state->m_typewriter.tyo_timer)
- state->m_typewriter.tyo_timer->enable(0);
+ if (m_typewriter->m_tyo_timer)
+ m_typewriter->m_tyo_timer->enable(0);
- if (state->m_dpy_timer)
- state->m_dpy_timer->enable(0);
+ if (m_dpy_timer)
+ m_dpy_timer->enable(0);
- state->m_io_status = io_st_tyo | io_st_ptp;
+ m_io_status = io_st_tyo | io_st_ptp;
}
/*
typewriter keyboard handler
*/
-void pdp1_state::pdp1_keyboard()
+void pdp1_typewriter_device::pdp1_keyboard()
{
int i;
int j;
@@ -1706,13 +1550,10 @@ void pdp1_state::pdp1_keyboard()
{
for (j=0; (((typewriter_transitions >> j) & 1) == 0) /*&& (j<16)*/; j++)
;
- m_typewriter.tb = (i << 4) + j;
- m_io_status |= io_st_tyi;
- #if USE_SBS
- m_maincpu->set_input_line(0, ASSERT_LINE); /* PDP1 - interrupt it, baby */
- #endif
+ m_tb = (i << 4) + j;
+ m_st_tyi(1);
m_maincpu->set_state_int(PDP1_PF1, 1);
- pdp1_typewriter_drawchar(m_typewriter.tb); /* we want to echo input */
+ drawchar(m_tb); /* we want to echo input */
break;
}
}
@@ -1835,7 +1676,7 @@ INTERRUPT_GEN_MEMBER(pdp1_state::pdp1_interrupt)
m_maincpu->set_state_int(PDP1_MA, m_maincpu->state_int(PDP1_PC));
m_maincpu->set_state_int(PDP1_IR, pdp1_device::LAC); /* this instruction is actually executed */
- m_maincpu->set_state_int(PDP1_MB, (signed)m_maincpu->space(AS_PROGRAM).read_dword(PDP1_MA<<2));
+ m_maincpu->set_state_int(PDP1_MB, (signed)m_maincpu->space(AS_PROGRAM).read_dword(PDP1_MA));
m_maincpu->set_state_int(PDP1_AC, m_maincpu->state_int(PDP1_MB));
}
if (control_transitions & pdp1_deposit)
@@ -1847,7 +1688,7 @@ INTERRUPT_GEN_MEMBER(pdp1_state::pdp1_interrupt)
m_maincpu->set_state_int(PDP1_IR, pdp1_device::DAC); /* this instruction is actually executed */
m_maincpu->set_state_int(PDP1_MB, m_maincpu->state_int(PDP1_AC));
- m_maincpu->space(AS_PROGRAM).write_dword(m_maincpu->state_int(PDP1_MA)<<2, m_maincpu->state_int(PDP1_MB));
+ m_maincpu->space(AS_PROGRAM).write_dword(m_maincpu->state_int(PDP1_MA), m_maincpu->state_int(PDP1_MB));
}
if (control_transitions & pdp1_read_in)
{ /* set cpu to read instructions from perforated tape */
@@ -1911,7 +1752,7 @@ INTERRUPT_GEN_MEMBER(pdp1_state::pdp1_interrupt)
m_old_tw_keys = 0;
m_old_ta_keys = 0;
- pdp1_keyboard();
+ m_typewriter->pdp1_keyboard();
}
pdp1_lightpen();
@@ -1926,6 +1767,37 @@ void pdp1_state::pdp1(machine_config &config)
m_maincpu->set_reset_param(&pdp1_reset_param);
m_maincpu->set_addrmap(AS_PROGRAM, &pdp1_state::pdp1_map);
m_maincpu->set_vblank_int("screen", FUNC(pdp1_state::pdp1_interrupt)); /* dummy interrupt: handles input */
+ /* external iot handlers. 00, 50 to 56 and 74 are internal to the cpu core. */
+ /* I put a ? when the source is the handbook, since a) I have used the maintenance manual
+ as the primary source (as it goes more into details) b) the handbook and the maintenance
+ manual occasionnally contradict each other. */
+ /* (iot) rpa rpb tyo tyi ppa ppb dpy */
+ /* spacewar */
+ /* lag glf?/jsp? gpl?/gpr?/gcf? */
+ /* rrb rcb? rcc? cks mcs mes mel */
+ /* cad? rac? rbc? pac lpr/lfb/lsp swc/sci/sdf?/shr? scv? */
+ /* (dsc) (asc) (isb) (cac) (lsm) (esm) (cbs) */
+ /* icv? dia dba dcc dra mri|rlc? mrf/inr?/ccr? */
+ /* mcb|dur? mwc|mtf? mrc|sfc?... msm|cgo? (eem/lem) mic muf */
+ m_maincpu->set_iot_callback<001>(m_tape_reader, FUNC(pdp1_readtape_image_device::iot_rpa));
+ m_maincpu->set_iot_callback<002>(m_tape_reader, FUNC(pdp1_readtape_image_device::iot_rpb));
+ m_maincpu->set_iot_callback<003>(m_typewriter, FUNC(pdp1_typewriter_device::iot_tyo));
+ m_maincpu->set_iot_callback<004>(m_typewriter, FUNC(pdp1_typewriter_device::iot_tyi));
+ m_maincpu->set_iot_callback<005>(m_tape_puncher, FUNC(pdp1_punchtape_image_device::iot_ppa));
+ m_maincpu->set_iot_callback<006>(m_tape_puncher, FUNC(pdp1_punchtape_image_device::iot_ppb));
+ m_maincpu->set_iot_callback<007>(FUNC(pdp1_state::iot_dpy));
+ m_maincpu->set_iot_callback<011>(FUNC(pdp1_state::iot_011));
+ m_maincpu->set_iot_callback<030>(m_tape_reader, FUNC(pdp1_readtape_image_device::iot_rrb));
+ m_maincpu->set_iot_callback<033>(FUNC(pdp1_state::iot_cks));
+ /* dia, dba, dcc, dra are documented in MIT PDP-1 COMPUTER MODIFICATION
+ BULLETIN no. 2 (drumInstrWriteup.bin/drumInstrWriteup.txt), and are
+ similar to IOT documented in Parallel Drum Type 23 Instruction Manual. */
+ m_maincpu->set_iot_callback<061>(m_parallel_drum, FUNC(pdp1_cylinder_image_device::iot_dia));
+ m_maincpu->set_iot_callback<062>(m_parallel_drum, FUNC(pdp1_cylinder_image_device::iot_dba));
+ m_maincpu->set_iot_callback<063>(m_parallel_drum, FUNC(pdp1_cylinder_image_device::iot_dcc));
+ m_maincpu->set_iot_callback<064>(m_parallel_drum, FUNC(pdp1_cylinder_image_device::iot_dra));
+ m_maincpu->set_read_binary_word(m_tape_reader, FUNC(pdp1_readtape_image_device::tape_read_binary));
+ m_maincpu->set_io_sc_callback(FUNC(pdp1_state::io_state_clear));
/* video hardware (includes the control panel and typewriter output) */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
@@ -1942,10 +1814,17 @@ void pdp1_state::pdp1(machine_config &config)
m_crt->set_offsets(crt_window_offset_x, crt_window_offset_y);
m_crt->set_size(crt_window_width, crt_window_height);
- PDP1_READTAPE(config, "readt", 0);
- PDP1_PUNCHTAPE(config, "punch", 0);
- PDP1_PRINTER(config, "typewriter", 0);
- PDP1_CYLINDER(config, "drum", 0);
+ PDP1_READTAPE(config, m_tape_reader);
+ m_tape_reader->st_ptr().set(FUNC(pdp1_state::io_status_w<io_st_ptr>));
+
+ PDP1_PUNCHTAPE(config, m_tape_puncher);
+ m_tape_puncher->st_ptp().set(FUNC(pdp1_state::io_status_w<io_st_ptp>));
+
+ PDP1_TYPEWRITER(config, m_typewriter);
+ m_typewriter->st_tyo().set(FUNC(pdp1_state::io_status_w<io_st_tyo>));
+ m_typewriter->st_tyi().set(FUNC(pdp1_state::io_status_w<io_st_tyi>));
+
+ PDP1_CYLINDER(config, m_parallel_drum);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_pdp1);
PALETTE(config, m_palette, FUNC(pdp1_state::pdp1_palette), total_colors_needed + ARRAY_LENGTH(pdp1_pens), total_colors_needed);
diff --git a/src/mame/includes/pdp1.h b/src/mame/includes/pdp1.h
index 102554eb438..2d237290b81 100644
--- a/src/mame/includes/pdp1.h
+++ b/src/mame/includes/pdp1.h
@@ -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);
+
+ auto st_ptr() { return m_st_ptr.bind(); }
+
+ 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);
+
+ void tape_read_binary();
+
+protected:
+ // device-level overrides
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
- int motor_on; /* 1-bit reader motor on */
+ // image-level overrides
+ virtual iodevice_t image_type() const noexcept override { return IO_PUNCHTAPE; }
- 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 */
+ 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"; }
- emu_timer *timer; /* timer to simulate reader timing */
+ 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);
+
+ 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; }
- emu_timer *timer; /* timer to generate completion pulses */
+ 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);
+
+ auto st_tyo() { return m_st_tyo.bind(); }
+ auto st_tyi() { return m_st_tyi.bind(); }
+
+ 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);
- int tb; /* typewriter buffer */
+ 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 *tyo_timer;/* timer to generate completion pulses */
+ 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);
+
+ 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 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) */
+protected:
+ // device-level overrides
+ virtual void device_start() override;
- int dba;
+ // image-level overrides
+ virtual iodevice_t image_type() const noexcept override { return IO_CYLINDER; }
- emu_timer *rotation_timer; /* timer called each time dc is 0 */
- emu_timer *il_timer; /* timer called each time dc is il */
+ 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;
diff --git a/src/mame/video/pdp1.cpp b/src/mame/video/pdp1.cpp
index 6f2462196a6..793f9ea5a56 100644
--- a/src/mame/video/pdp1.cpp
+++ b/src/mame/video/pdp1.cpp
@@ -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;
}
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index 1c6c9b1a160..b5a175c1d96 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -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; } },