summaryrefslogtreecommitdiffstats
path: root/src/hbmame/video/neogeo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/hbmame/video/neogeo.cpp')
-rw-r--r--src/hbmame/video/neogeo.cpp267
1 files changed, 267 insertions, 0 deletions
diff --git a/src/hbmame/video/neogeo.cpp b/src/hbmame/video/neogeo.cpp
new file mode 100644
index 00000000000..fb77b8d8334
--- /dev/null
+++ b/src/hbmame/video/neogeo.cpp
@@ -0,0 +1,267 @@
+// license:BSD-3-Clause
+// copyright-holders:Bryan McPhail,Ernesto Corvi,Andrew Prime,Zsolt Vasvari
+// thanks-to:Fuzz
+/***************************************************************************
+
+ Neo-Geo hardware
+
+****************************************************************************/
+
+#include "emu.h"
+#include "includes/neogeo.h"
+#include "video/resnet.h"
+
+#define NUM_PENS (0x1000)
+#define VERBOSE (0)
+
+
+
+/*************************************
+ *
+ * Palette handling
+ *
+ *************************************/
+
+void neogeo_state::create_rgb_lookups()
+{
+ static const int resistances[] = {3900, 2200, 1000, 470, 220};
+
+ /* compute four sets of weights - with or without the pulldowns -
+ ensuring that we use the same scaler for all */
+ double weights_normal[5];
+ double scaler = compute_resistor_weights(0, 255, -1,
+ 5, resistances, weights_normal, 0, 0,
+ 0, nullptr, nullptr, 0, 0,
+ 0, nullptr, nullptr, 0, 0);
+
+ double weights_dark[5];
+ compute_resistor_weights(0, 255, scaler,
+ 5, resistances, weights_dark, 8200, 0,
+ 0, nullptr, nullptr, 0, 0,
+ 0, nullptr, nullptr, 0, 0);
+
+ double weights_shadow[5];
+ compute_resistor_weights(0, 255, scaler,
+ 5, resistances, weights_shadow, 150, 0,
+ 0, nullptr, nullptr, 0, 0,
+ 0, nullptr, nullptr, 0, 0);
+
+ double weights_dark_shadow[5];
+ compute_resistor_weights(0, 255, scaler,
+ 5, resistances, weights_dark_shadow, 1.0 / ((1.0 / 8200) + (1.0 / 150)), 0,
+ 0, nullptr, nullptr, 0, 0,
+ 0, nullptr, nullptr, 0, 0);
+
+ for (int i = 0; i < 32; i++)
+ {
+ int i4 = (i >> 4) & 1;
+ int i3 = (i >> 3) & 1;
+ int i2 = (i >> 2) & 1;
+ int i1 = (i >> 1) & 1;
+ int i0 = (i >> 0) & 1;
+ m_palette_lookup[i][0] = combine_weights(weights_normal, i0, i1, i2, i3, i4);
+ m_palette_lookup[i][1] = combine_weights(weights_dark, i0, i1, i2, i3, i4);
+ m_palette_lookup[i][2] = combine_weights(weights_shadow, i0, i1, i2, i3, i4);
+ m_palette_lookup[i][3] = combine_weights(weights_dark_shadow, i0, i1, i2, i3, i4);
+ }
+}
+
+void neogeo_state::set_pens()
+{
+ const pen_t *pen_base = m_palette->pens() + m_palette_bank + (m_screen_shadow ? 0x2000 : 0);
+ m_sprgen->set_pens(pen_base);
+ m_bg_pen = pen_base + 0xfff;
+}
+
+
+void neogeo_state::neogeo_set_screen_shadow( int data )
+{
+ m_screen_shadow = data;
+ set_pens();
+}
+
+
+void neogeo_state::neogeo_set_palette_bank( int data )
+{
+ m_palette_bank = data ? 0x1000 : 0;
+ set_pens();
+}
+
+
+READ16_MEMBER(neogeo_state::neogeo_paletteram_r)
+{
+ return m_paletteram[m_palette_bank + offset];
+}
+
+
+WRITE16_MEMBER(neogeo_state::neogeo_paletteram_w)
+{
+ offset += m_palette_bank;
+ data = COMBINE_DATA(&m_paletteram[offset]);
+
+ int dark = data >> 15;
+ int r = ((data >> 14) & 0x1) | ((data >> 7) & 0x1e);
+ int g = ((data >> 13) & 0x1) | ((data >> 3) & 0x1e);
+ int b = ((data >> 12) & 0x1) | ((data << 1) & 0x1e);
+
+ m_palette->set_pen_color(offset,
+ m_palette_lookup[r][dark],
+ m_palette_lookup[g][dark],
+ m_palette_lookup[b][dark]); // normal
+
+ m_palette->set_pen_color(offset + 0x2000,
+ m_palette_lookup[r][dark+2],
+ m_palette_lookup[g][dark+2],
+ m_palette_lookup[b][dark+2]); // shadow
+}
+
+
+
+/*************************************
+ *
+ * Video system start
+ *
+ *************************************/
+
+void neogeo_state::video_start()
+{
+ create_rgb_lookups();
+
+ m_paletteram.resize(0x1000 * 2);
+ memset(&m_paletteram[0], 0, 0x1000 * 2 * sizeof(m_paletteram[0]));
+
+ m_screen_shadow = 0;
+ m_palette_bank = 0;
+
+ save_item(NAME(m_paletteram));
+ save_item(NAME(m_screen_shadow));
+ save_item(NAME(m_palette_bank));
+ machine().save().register_postload(save_prepost_delegate(FUNC(neogeo_state::set_pens), this));
+
+ set_pens();
+}
+
+
+
+/*************************************
+ *
+ * Video update
+ *
+ *************************************/
+
+uint32_t neogeo_state::screen_update_neogeo(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ // fill with background color first
+ bitmap.fill(*m_bg_pen, cliprect);
+
+ m_sprgen->draw_sprites(bitmap, cliprect.min_y);
+
+ m_sprgen->draw_fixed_layer(bitmap, cliprect.min_y);
+
+ return 0;
+}
+
+
+
+/*************************************
+ *
+ * Video control
+ *
+ *************************************/
+
+uint16_t neogeo_state::get_video_control( )
+{
+ uint16_t ret;
+ uint16_t v_counter;
+
+ /*
+ The format of this very important location is: AAAA AAAA A??? BCCC
+
+ A is the raster line counter. mosyougi relies solely on this to do the
+ raster effects on the title screen; sdodgeb loops waiting for the top
+ bit to be 1; zedblade heavily depends on it to work correctly (it
+ checks the top bit in the IRQ2 handler).
+ B is definitely a PAL/NTSC flag. (LSPC2 only) Evidence:
+ 1) trally changes the position of the speed indicator depending on
+ it (0 = lower 1 = higher).
+ 2) samsho3 sets a variable to 60 when the bit is 0 and 50 when it's 1.
+ This is obviously the video refresh rate in Hz.
+ 3) samsho3 sets another variable to 256 or 307. This could be the total
+ screen height (including vblank), or close to that.
+ Some games (e.g. lstbld2, samsho3) do this (or similar):
+ bclr #$0, $3c000e.l
+ when the bit is set, so 3c000e (whose function is unknown) has to be
+ related
+ C animation counter lower 3 bits
+ */
+
+ /* the vertical counter chain goes from 0xf8 - 0x1ff */
+ v_counter = m_screen->vpos() + 0x100;
+
+ if (v_counter >= 0x200)
+ v_counter = v_counter - NEOGEO_VTOTAL;
+
+ ret = (v_counter << 7) | (m_sprgen->neogeo_get_auto_animation_counter() & 0x0007);
+
+ if (VERBOSE) logerror("%s: video_control read (%04x)\n", machine().describe_context(), ret);
+
+ return ret;
+}
+
+
+void neogeo_state::set_video_control( uint16_t data )
+{
+ if (VERBOSE) logerror("%s: video control write %04x\n", machine().describe_context(), data);
+
+ m_sprgen->set_auto_animation_speed(data >> 8);
+ m_sprgen->set_auto_animation_disabled(data & 0x0008);
+
+ neogeo_set_display_position_interrupt_control(data & 0x00f0);
+}
+
+
+READ16_MEMBER(neogeo_state::neogeo_video_register_r)
+{
+ uint16_t ret;
+
+ /* accessing the LSB only is not mapped */
+ if (mem_mask == 0x00ff)
+ ret = neogeo_unmapped_r(space, 0, 0xffff) & 0x00ff;
+ else
+ {
+ switch (offset)
+ {
+ default:
+ case 0x00:
+ case 0x01: ret = m_sprgen->get_videoram_data(); break;
+ case 0x02: ret = m_sprgen->get_videoram_modulo(); break;
+ case 0x03: ret = get_video_control(); break;
+ }
+ }
+
+ return ret;
+}
+
+
+WRITE16_MEMBER(neogeo_state::neogeo_video_register_w)
+{
+ /* accessing the LSB only is not mapped */
+ if (mem_mask != 0x00ff)
+ {
+ /* accessing the MSB only stores same data in MSB and LSB */
+ if (mem_mask == 0xff00)
+ data = (data & 0xff00) | (data >> 8);
+
+ switch (offset)
+ {
+ case 0x00: m_sprgen->set_videoram_offset(data); break;
+ case 0x01: m_sprgen->set_videoram_data(data); break;
+ case 0x02: m_sprgen->set_videoram_modulo(data); break;
+ case 0x03: set_video_control(data); break;
+ case 0x04: neogeo_set_display_counter_msb(data); break;
+ case 0x05: neogeo_set_display_counter_lsb(data); break;
+ case 0x06: neogeo_acknowledge_interrupt(data); break;
+ case 0x07: break; // d0: pause timer for 32 lines when in PAL mode (LSPC2 only)
+ }
+ }
+}