summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/mame/atari/atarist.cpp25
-rw-r--r--src/mame/atari/stvideo.cpp205
-rw-r--r--src/mame/atari/stvideo.h6
3 files changed, 142 insertions, 94 deletions
diff --git a/src/mame/atari/atarist.cpp b/src/mame/atari/atarist.cpp
index 3d274b69559..f7fd82f5117 100644
--- a/src/mame/atari/atarist.cpp
+++ b/src/mame/atari/atarist.cpp
@@ -805,23 +805,30 @@ void st_state::st_super_map(address_map &map)
map(0x000000, 0x000007).rom().region(M68000_TAG, 0);
map(0x000000, 0x000007).before_delay(NAME([](offs_t) { return 64; })).w(m_maincpu, FUNC(m68000_device::berr_w));
map(0x400000, 0xf9ffff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
- //map(0xfa0000, 0xfbffff) // mapped by the cartslot
+ map(0xfa0000, 0xfbffff).noprw(); // mapped by the cartslot
map(0xfc0000, 0xfeffff).rom().region(M68000_TAG, 0);
map(0xfc0000, 0xfeffff).before_delay(NAME([](offs_t) { return 64; })).w(m_maincpu, FUNC(m68000_device::berr_w));
- // Do a bus error if nothing answers
- map(0xff0000, 0xffffff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
map(0xff8000, 0xff8fff).m(m_mmu, FUNC(st_mmu_device::map));
map(0xff8000, 0xff8fff).m(m_video, FUNC(st_video_device::map));
- map(0xff8800, 0xff8800).rw(YM2149_TAG, FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)).mirror(0xfc);
- map(0xff8802, 0xff8802).rw(YM2149_TAG, FUNC(ay8910_device::data_r), FUNC(ay8910_device::data_w)).mirror(0xfc);
+ map(0xff8800, 0xff8800).after_delay(NAME([](offs_t) { return 1; })).rw(YM2149_TAG, FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)).mirror(0xfc);
+ map(0xff8802, 0xff8802).after_delay(NAME([](offs_t) { return 1; })).rw(YM2149_TAG, FUNC(ay8910_device::data_r), FUNC(ay8910_device::data_w)).mirror(0xfc);
// no blitter on original ST
map(0xfffa00, 0xfffa3f).rw(m_mfp, FUNC(mc68901_device::read), FUNC(mc68901_device::write)).umask16(0x00ff);
map(0xfffc00, 0xfffc03).rw(m_acia[0], FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask16(0xff00);
map(0xfffc04, 0xfffc07).rw(m_acia[1], FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask16(0xff00);
+
+ // Do a bus error where nothing answers in 64 cycles
+ map(0xff0000, 0xff7fff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
+ map(0xff8100, 0xff81ff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
+ map(0xff8300, 0xff85ff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
+ map(0xff8700, 0xff87ff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
+ map(0xff8900, 0xfff9ff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
+ map(0xfffb00, 0xfffbff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
+ map(0xfffd00, 0xffffff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
}
void st_state::st_user_map(address_map &map)
@@ -829,8 +836,10 @@ void st_state::st_user_map(address_map &map)
// Ram mapped by the mmu
map.unmap_value_high();
map(0x000000, 0x0007ff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
- map(0x400000, 0xfbffff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
+ map(0x400000, 0xf9ffff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
+ map(0xfa0000, 0xfbffff).noprw(); // mapped by the cartslot
map(0xfc0000, 0xfeffff).rom().region(M68000_TAG, 0).w(m_maincpu, FUNC(m68000_device::berr_w));
+ map(0xfc0000, 0xfeffff).before_delay(NAME([](offs_t) { return 64; })).w(m_maincpu, FUNC(m68000_device::berr_w));
map(0xff0000, 0xffffff).before_delay(NAME([](offs_t) { return 64; })).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
}
@@ -1432,8 +1441,8 @@ void st_state::st(machine_config &config)
m_video->set_ram(m_mainram);
m_video->set_mmu(m_mmu);
m_video->de_cb().set(m_mfp, FUNC(mc68901_device::tbi_w));
- m_video->hsync_cb().set([this](int state) { if(state) m_maincpu->set_input_line(2, ASSERT_LINE); });
- m_video->vsync_cb().set([this](int state) { if(state) m_maincpu->set_input_line(4, ASSERT_LINE); });
+ m_video->hsync_cb().set([this](int state) { if(!state) m_maincpu->set_input_line(2, ASSERT_LINE); });
+ m_video->vsync_cb().set([this](int state) { if(!state) m_maincpu->set_input_line(4, ASSERT_LINE); });
// sound hardware
SPEAKER(config, "mono").front_center();
diff --git a/src/mame/atari/stvideo.cpp b/src/mame/atari/stvideo.cpp
index d533efdfa3b..73adbcd53f9 100644
--- a/src/mame/atari/stvideo.cpp
+++ b/src/mame/atari/stvideo.cpp
@@ -284,10 +284,10 @@ const u32 st_video_device::cycles_per_screen[3] = { 128*313, 127*263, 56*501 };
static INPUT_PORTS_START(stvideo)
PORT_START("config")
PORT_CONFNAME( 15, 4, "GLUE wake state")
- PORT_CONFSETTING( 0, "1" )
- PORT_CONFSETTING( 4, "2" )
- PORT_CONFSETTING( 8, "3" )
- PORT_CONFSETTING( 12, "4" )
+ PORT_CONFSETTING( 12, "DL3 / WS2" )
+ PORT_CONFSETTING( 8, "DL4 / WS4" )
+ PORT_CONFSETTING( 4, "DL5 / WS3" )
+ PORT_CONFSETTING( 0, "DL6 / WS1" )
INPUT_PORTS_END
ioport_constructor st_video_device::device_input_ports() const
@@ -326,7 +326,6 @@ void st_video_device::device_start()
m_de_timer = timer_alloc(FUNC(st_video_device::de_event ), this);
save_item(NAME(m_start_screen_time));
- save_item(NAME(m_start_line_time));
save_item(NAME(m_shifter_base_x));
save_item(NAME(m_shifter_update_time));
save_item(NAME(m_prev_glue_tick));
@@ -384,7 +383,8 @@ void st_video_device::device_reset()
m_vdec = 0;
m_vsync = 1;
m_hsync = 0;
- m_start_screen_time = m_start_line_time = time_now() >> 4;
+ m_start_screen_time = time_now() >> 4;
+ m_hsc_base = m_hdec_base = 0;
m_shifter_update_time = (time_now() | 15) + 1;
m_shifter_base_x = 0;
m_pixcnt = 4;
@@ -402,7 +402,7 @@ void st_video_device::device_reset()
m_hde = 0;
m_rr[0] = m_rr[1] = m_rr[2] = m_rr[3] = 0;
m_ir[0] = m_ir[1] = m_ir[2] = m_ir[3] = 0;
- m_prev_glue_tick = 1;
+ m_prev_glue_tick = 0;
m_screen_bitmap.fill(0x808080);
@@ -445,9 +445,11 @@ void st_video_device::hsync_on()
void st_video_device::hsync_off(u64 glue_tick)
{
if(m_hsync) {
- m_shifter_base_x = (glue_tick << 4) | m_phase->read();
+ m_shifter_base_x = (glue_tick << 3) + m_phase->read() - 32;
m_shifter_y ++;
+ m_hdec_base = glue_tick - 1;
+
m_hsync = 0;
m_hsync_cb(0);
if(m_vsync)
@@ -456,30 +458,41 @@ void st_video_device::hsync_off(u64 glue_tick)
m_vdec ++;
if(m_vdec == vde_start[m_mode])
m_vde = 1;
- else if(m_vdec == vde_end[m_mode])
+ else if(m_vdec == vde_end[m_mode]) {
m_vde = 0;
+ if(m_de)
+ next_de_event((glue_tick | 1) + 1, 0);
+ }
+
+ if(v)
+ logerror("%s hsync 0\n", context());
}
}
-TIMER_CALLBACK_MEMBER(st_video_device::de_event)
+void st_video_device::de_set(bool level)
{
u64 now = time_now();
shifter_sync(now);
- m_de = param;
+ m_de = level;
m_de_cb(m_de);
- if(param) {
+ if(level) {
m_load_current = (now & ~15) + 16 + 8;
m_load_end = 0;
} else
m_load_end = (now & ~15) + 16 + 8;
if(v)
- logerror("%s de %d lc=%d le=%d\n", context(now), m_de, m_load_current/4, m_load_end/4);
+ logerror("%s de %d lc=%d le=%d delta=%d\n", context(now), m_de, m_load_current/4, m_load_end/4, m_load_current - now);
+}
+
+TIMER_CALLBACK_MEMBER(st_video_device::de_event)
+{
+ de_set(param);
}
void st_video_device::next_de_event(u64 glue_tick, int level)
{
- u64 when = (glue_tick << 4) + m_phase->read() + 8;
+ u64 when = (glue_tick << 3) + m_phase->read() - 32;
attotime dt = attotime::from_ticks(2*when+1, 2*clock()) - machine().time();
m_de_timer->adjust(dt, level);
}
@@ -494,7 +507,7 @@ void st_video_device::hde_on(u64 glue_tick)
m_pixcnt_en = false;
m_rdelay = 0;
}
- next_de_event(glue_tick, 1);
+ next_de_event((glue_tick | 1) + 1, 1);
}
}
@@ -504,7 +517,7 @@ void st_video_device::hde_off(u64 glue_tick)
logerror("%s hde 0\n", context());
if(m_hde) {
m_hde = 0;
- next_de_event(glue_tick, 0);
+ next_de_event((glue_tick | 1) + 1, 0);
}
}
@@ -651,25 +664,21 @@ std::string st_video_device::context(u64 now)
static const char *const mt[3] = { "50Hz", "60Hz", "71Hz" };
if(!now)
now = time_now();
- shifter_sync(now);
- u64 phase = m_phase->read();
- u64 glue_tick = now >> 4;
- if((now & 15) < phase && glue_tick)
- glue_tick --;
- u16 hsc = m_hsc_base + (glue_tick - m_start_line_time);
- u16 hdec = m_hsync ? 0 : (hsc - m_hdec_base) & 127;
+ auto [glue_tick, hsc, hdec] = compute_glue_tick(now);
u64 mtick = machine().root_device().subdevice<cpu_device>("m68000")->total_cycles();
u32 pc = machine().root_device().subdevice<cpu_device>("m68000")->pcbase();
- return util::string_format("[%s %06x %6d %6d %6d %6d %03d/%03d %03d/%03d s:%c%c de:%c%c%c %s]",
+ return util::string_format("[%s %06x %6d.%d %6d %6d %4d %4d %03d/%03d %03d/%03d s:%c%c de:%c%c%c %s]",
util::string_format("%08d.%x", now >> 4, now & 15),
pc,
- now - ((m_start_screen_time << 4) | phase),
- glue_tick - m_start_screen_time,
- now >> 2,
+ (glue_tick - m_start_screen_time) >> 1,
+ (glue_tick - m_start_screen_time) & 1,
mtick,
+ glue_tick,
+ glue_tick - m_hsc_base,
+ glue_tick - m_hdec_base,
hsc, m_vsc,
hdec, m_vdec,
m_hsync ? 'h' : '-', m_vsync ? 'v' : '-',
@@ -678,45 +687,55 @@ std::string st_video_device::context(u64 now)
mt[m_mode]);
}
+std::tuple<u64, u16, u16> st_video_device::compute_glue_tick(u64 now)
+{
+ // Glue tick is doubled to count up and down edges
+
+ u64 phase = m_phase->read();
+ u64 glue_tick = (now + 32 - phase) >> 3; // Avoid negative values after adjustement, with some margin
+
+ u16 hsc = (glue_tick - m_hsc_base) >> 1;
+ u16 hdec = m_hsync ? 0 : ((glue_tick - m_hdec_base) >> 1) & 127;
+ return std::make_tuple(glue_tick, hsc, hdec);
+}
+
void st_video_device::glue_sync()
{
static const char *const mt[3] = { "50Hz", "60Hz", "71Hz" };
u64 now = time_now();
shifter_sync(now);
- u64 phase = m_phase->read();
- u64 glue_tick = now >> 4;
- if((now & 15) < phase && glue_tick)
- glue_tick --;
+ auto [glue_tick, hsc, hdec] = compute_glue_tick(now);
if(glue_tick == m_prev_glue_tick)
return;
- m_prev_glue_tick = glue_tick;
- u16 hsc = m_hsc_base + (glue_tick - m_start_line_time);
- u16 hdec = m_hsync ? 0 : (hsc - m_hdec_base) & 127;
+ bool hsc_edge = (glue_tick >= m_prev_glue_tick+2) || !(glue_tick & 1);
+ bool hdec_edge = (glue_tick >= m_prev_glue_tick+2) || (glue_tick & 1);
+
+ m_prev_glue_tick = glue_tick;
if(v)
- logerror("%s glue sync tick=%d\n", context(), glue_tick);
+ logerror("%s glue sync tick=%d.%d\n", context(), glue_tick >> 1, glue_tick & 1);
if(hsc >= 128) {
if(m_mode == M_71) {
hsync_off(glue_tick);
- m_hdec_base = 127;
- hdec = 1;
+ hdec = 0;
}
- m_hdec_base += base_hsc[m_mode];
m_vsc ++;
if(m_vsc == 512) {
m_vsync = 0;
+ m_adr_live = m_adr_base;
m_vdec = 0;
m_vsync_cb(0);
u64 dt = glue_tick - m_start_screen_time;
// We put the (0, 0) position at hsync off, vsync off. We
// remove the blanked zone at 50 and 60Hz.
- if(dt != cycles_per_screen[m_mode]) {
+ if(dt != 2*cycles_per_screen[m_mode]) {
logerror("Video mode: %s\n", mt[m_mode]);
+ logerror("dt=%d cps=%d / %d\n", dt, cycles_per_screen[m_mode], 2*cycles_per_screen[m_mode]);
switch(m_mode) {
case 0: screen().configure(128*8, 313, rectangle(8*(121-112), 8*(128-112 + 98-0), 223-199, 506-199-1), attotime::from_ticks(16*cycles_per_screen[m_mode], clock()).as_attoseconds()); break;
case 1: screen().configure(127*8, 263, rectangle(8*(121-112), 8*(128-112 + 99-1), 264-249, 506-249-1), attotime::from_ticks(16*cycles_per_screen[m_mode], clock()).as_attoseconds()); break;
@@ -731,57 +750,70 @@ void st_video_device::glue_sync()
m_vsync = 1;
m_vsync_cb(1);
m_vde = 0;
+ if(m_de)
+ next_de_event((glue_tick | 1) + 1, 0);
m_adr_live = m_adr_base;
}
- hsc = m_hsc_base = base_hsc[m_mode];
- m_start_line_time = glue_tick;
+ hsc = base_hsc[m_mode];
+ m_hsc_base = glue_tick - 2*hsc;
}
switch(m_mode) {
case M_50:
- if(hsc == 102) {
- hsync_on();
- if(m_hde)
- hde_off(glue_tick);
+ if(hsc_edge) {
+ if(hsc == 102) {
+ hsync_on();
+ if(m_hde)
+ hde_off(glue_tick);
+ }
+ else if(hsc == 112) {
+ hsync_off(glue_tick);
+ hdec = 0;
+ m_hdec_base = glue_tick - 1;
+ }
}
- else if(hsc == 112) {
- hsync_off(glue_tick);
- hdec = 1;
- m_hdec_base = 111;
+ if(hdec_edge) {
+ if(hdec == 17)
+ hde_on(glue_tick);
+ else if(hdec == 97)
+ hde_off(glue_tick);
}
- if(hdec == 17)
- hde_on(glue_tick);
- else if(hdec == 97)
- hde_off(glue_tick);
break;
case M_60:
- if(hsc == 102) {
- hsync_on();
- if(m_hde)
+ if(hsc_edge) {
+ if(hsc == 102) {
+ hsync_on();
+ if(m_hde)
+ hde_off(glue_tick);
+ } else if(hsc == 112) {
+ hsync_off(glue_tick);
+ hdec = 0;
+ }
+ }
+ if(hdec_edge) {
+ if(hdec == 16)
+ hde_on(glue_tick);
+ else if(hdec == 96)
hde_off(glue_tick);
- } else if(hsc == 112) {
- hsync_off(glue_tick);
- hdec = 1;
- m_hdec_base = 111;
}
- if(hdec == 16)
- hde_on(glue_tick);
- else if(hdec == 96)
- hde_off(glue_tick);
break;
case M_71:
- if(hsc == 122) {
- hsync_on();
- if(m_hde)
+ if(hsc_edge) {
+ if(hsc == 122) {
+ hsync_on();
+ if(m_hde)
+ hde_off(glue_tick);
+ }
+ }
+ if(hdec_edge) {
+ if(hdec == 4)
+ hde_on(glue_tick);
+ else if(hdec == 44)
hde_off(glue_tick);
}
- if(hdec == 4)
- hde_on(glue_tick);
- else if(hdec == 44)
- hde_off(glue_tick);
break;
}
}
@@ -791,12 +823,7 @@ void st_video_device::glue_determine_next_event()
{
u64 now = time_now();
- u64 phase = m_phase->read();
- u64 glue_tick = now >> 4;
- if((now & 15) < phase)
- glue_tick --;
- u16 hsc = m_hsc_base + (glue_tick - m_start_line_time);
- u16 hdec = m_hsync ? 0 : (hsc - m_hdec_base) & 127;
+ auto [glue_tick, hsc, hdec] = compute_glue_tick(now);
u16 hsc_next = 128;
u16 hdec_next = 128;
@@ -834,13 +861,18 @@ void st_video_device::glue_determine_next_event()
break;
}
- if(v)
- logerror("%s next hsc %d hdec %d\n", context(), hsc_next, hdec_next);
- hsc_next -= hsc;
- hdec_next -= hdec;
- u16 delta = hsc_next < hdec_next || m_hsync ? hsc_next : hdec_next;
- next_event(((glue_tick + delta) << 4) | phase);
+ u16 hsc_delta = ((hsc_next - hsc) << 1) - (glue_tick & 1);
+ u16 hdec_delta = ((hdec_next - hdec) << 1) - (~glue_tick & 1);
+
+ u16 delta = hsc_delta < hdec_delta || m_hsync ? hsc_delta : hdec_delta;
+
+ if(v) {
+ u64 gt = glue_tick + delta - m_start_screen_time;
+ logerror("%s next hsc %d hdec %d targetting %d.%d\n", context(), hsc_next, hdec_next, gt >> 1, gt & 1);
+ }
+
+ next_event(((glue_tick + delta) << 3) + m_phase->read() - 32);
}
TIMER_CALLBACK_MEMBER(st_video_device::timer_event)
@@ -884,8 +916,13 @@ u8 st_video_device::adr_live_m_r()
u8 st_video_device::adr_live_l_r()
{
shifter_sync();
- // v = true;
logerror("%s adr %06x - %06x\n", context(), m_adr_base, m_adr_live);
+ u32 pc = machine().root_device().subdevice<cpu_device>("m68000")->pcbase();
+ if(pc == 0x8644)
+ v = false; // level 16
+ if(pc == 0x84f0)
+ v = false; // main menu
+ // v = true;
return m_adr_live;
}
diff --git a/src/mame/atari/stvideo.h b/src/mame/atari/stvideo.h
index d741ad17048..72e95c39888 100644
--- a/src/mame/atari/stvideo.h
+++ b/src/mame/atari/stvideo.h
@@ -56,12 +56,12 @@ private:
emu_timer *m_event_timer;
emu_timer *m_de_timer;
- u64 m_start_screen_time, m_start_line_time, m_shifter_base_x, m_shifter_update_time;
+ u64 m_start_screen_time, m_hsc_base, m_hdec_base, m_shifter_base_x, m_shifter_update_time;
u64 m_prev_glue_tick;
u64 m_load_current, m_load_end;
u16 m_ir[4], m_rr[4];
u32 m_adr_base, m_adr_live;
- u16 m_hsc_base, m_hdec_base, m_vsc, m_vdec, m_shifter_y;
+ u16 m_vsc, m_vdec, m_shifter_y;
u16 m_palette[16];
u8 m_sync, m_res, m_vsync, m_hsync, m_vde, m_hde, m_de;
u8 m_mode;
@@ -96,6 +96,8 @@ private:
void update_mode();
void shifter_handle_load();
void shifter_sync(u64 now = 0);
+ void de_set(bool level);
+ std::tuple<u64, u16, u16> compute_glue_tick(u64 now);
void glue_sync();
void glue_determine_next_event();