mirror of
https://github.com/holub/mame
synced 2025-06-01 18:41:47 +03:00

machines promoted to WORKING ----- Golden Nugget Casino [David Haywood, Sean Riddle] Sudoku Plug & Play TV Game '6 Intelligent Games' [David Haywood, Sean Riddle] Frogger (MSI Plug & Play, white joystick) [David Haywood, Sean Riddle] 35 in 1 Super Twins [David Haywood, Sean Riddle] Vs. Maxx 17-in-1 [David Haywood, Sean Riddle] made use of the code that was already partially present in the NES PPU code to handle emphasis modes, used to highlight tally bars etc. in 'nes rampart', apply a red tint to 'fds bublbobl' and dim the screen in a number of other games. fixed a number of issues with VT palette modes that was causing black screens in many games, allowing them to be promoted added a timing kludge for interrupts in the NES Frogger titles, until timings are better overall,makes playfield stable here and in a number of other places so that other things can be improved note "Vs. Maxx 17-in-1" was added as NOT WORKING in this same cycle so if this gets merged before freeze they'll need to be moved to the 'new working' section. This is a checkpoint, further code improvements and refactors will come later.
299 lines
7.1 KiB
C++
299 lines
7.1 KiB
C++
// license:BSD-3-Clause
|
|
// copyright-holders:David Haywood
|
|
/******************************************************************************
|
|
|
|
******************************************************************************/
|
|
|
|
#include "emu.h"
|
|
#include "video/ppu2c0x_sh6578.h"
|
|
|
|
#define LOG_PPU_EXTRA (1U << 1)
|
|
|
|
//#define VERBOSE (LOG_PPU_EXTRA)
|
|
|
|
#include "logmacro.h"
|
|
|
|
// devices
|
|
DEFINE_DEVICE_TYPE(PPU_SH6578, ppu_sh6578_device, "ppu_sh6578", "SH6578 PPU (NTSC)")
|
|
DEFINE_DEVICE_TYPE(PPU_SH6578PAL, ppu_sh6578pal_device, "ppu_sh6578pal", "SH6578 PPU (PAL)")
|
|
|
|
ppu_sh6578_device::ppu_sh6578_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock) :
|
|
ppu2c0x_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(ppu_sh6578_device::ppu_internal_map), this))
|
|
{
|
|
m_paletteram_in_ppuspace = false;
|
|
m_line_write_increment_large = 32;
|
|
m_videoram_addr_mask = 0xffff;
|
|
m_global_refresh_mask = 0xffff;
|
|
}
|
|
|
|
ppu_sh6578_device::ppu_sh6578_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
|
|
ppu_sh6578_device(mconfig, PPU_SH6578, tag, owner, clock)
|
|
{
|
|
}
|
|
|
|
ppu_sh6578pal_device::ppu_sh6578pal_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
|
|
ppu_sh6578_device(mconfig, PPU_SH6578PAL, tag, owner, clock)
|
|
{
|
|
m_scanlines_per_frame = PAL_SCANLINES_PER_FRAME;
|
|
m_vblank_first_scanline = VBLANK_FIRST_SCANLINE_PALC;
|
|
}
|
|
|
|
|
|
// Palette RAM is _NOT_ mapped to PPU space here
|
|
void ppu_sh6578_device::ppu_internal_map(address_map& map)
|
|
{
|
|
map(0x0000, 0x1fff).ram();
|
|
map(0x2000, 0x27ff).ram();
|
|
map(0x2800, 0x7fff).nopr();
|
|
|
|
map(0x8000, 0xffff).ram(); // machine specific?
|
|
}
|
|
|
|
void ppu_sh6578_device::device_start()
|
|
{
|
|
start_nopalram();
|
|
|
|
m_palette_ram.resize(0x40);
|
|
|
|
for (int i = 0; i < 0x40; i++)
|
|
m_palette_ram[i] = 0x00;
|
|
|
|
save_item(NAME(m_palette_ram));
|
|
}
|
|
|
|
void ppu_sh6578_device::device_reset()
|
|
{
|
|
ppu2c0x_device::device_reset();
|
|
m_colsel_pntstart = 0x00;
|
|
}
|
|
|
|
void ppu_sh6578_device::scanline_increment_fine_ycounter()
|
|
{
|
|
/* increment the fine y-scroll */
|
|
m_refresh_data += 0x1000;
|
|
|
|
/* if it's rolled, increment the coarse y-scroll */
|
|
if (m_refresh_data & 0x8000)
|
|
{
|
|
uint16_t tmp;
|
|
tmp = (m_refresh_data & 0x03e0) + 0x20;
|
|
m_refresh_data &= 0x7c1f;
|
|
|
|
if (tmp == 0x0400)
|
|
m_refresh_data ^= 0x0800;
|
|
else
|
|
m_refresh_data |= (tmp & 0x03e0);
|
|
|
|
//logerror("updating refresh_data: %04x\n", m_refresh_data);
|
|
}
|
|
}
|
|
|
|
void ppu_sh6578_device::draw_sprite_pixel(int sprite_xpos, int color, int pixel, uint8_t pixel_data, bitmap_rgb32& bitmap)
|
|
{
|
|
uint8_t palval = m_palette_ram[(pixel_data | color << 2)] & 0x3f;
|
|
bitmap.pix32(m_scanline, sprite_xpos + pixel) = m_nespens[palval];
|
|
}
|
|
|
|
void ppu_sh6578_device::read_tile_plane_data(int address, int color)
|
|
{
|
|
m_planebuf[0] = readbyte(address);
|
|
m_planebuf[1] = readbyte(address + 8);
|
|
|
|
m_extplanebuf[0] = readbyte(address + 16);
|
|
m_extplanebuf[1] = readbyte(address + 24);
|
|
}
|
|
|
|
void ppu_sh6578_device::draw_tile(uint8_t* line_priority, int color_byte, int color_bits, int address, int start_x, uint32_t back_pen, uint32_t*& dest)
|
|
{
|
|
int color = color_byte;
|
|
|
|
color &= 0xc;
|
|
|
|
read_tile_plane_data(address, color);
|
|
|
|
/* render the pixel */
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
uint8_t pix;
|
|
|
|
pix = ((m_planebuf[0] & 0x80) >> 7);
|
|
pix |= ((m_planebuf[1] & 0x80) >> 6);
|
|
pix |= ((m_extplanebuf[0] & 0x80) >> 5);
|
|
pix |= ((m_extplanebuf[1] & 0x80) >> 4);
|
|
|
|
m_planebuf[0] <<= 1;
|
|
m_planebuf[1] <<= 1;
|
|
m_extplanebuf[0] <<= 1;
|
|
m_extplanebuf[1] <<= 1;
|
|
|
|
if ((start_x + i) >= 0 && (start_x + i) < VISIBLE_SCREEN_WIDTH)
|
|
{
|
|
pen_t pen;
|
|
|
|
uint8_t palval = m_palette_ram[(pix | color << 2)] & 0x3f;
|
|
|
|
bool trans = false;
|
|
if ((palval & 0x1f) == 0x1f)
|
|
trans = true;
|
|
|
|
if (!trans)
|
|
{
|
|
pen = m_nespens[palval];
|
|
}
|
|
else
|
|
{
|
|
uint8_t palval = m_palette_ram[0x0] & 0x3f;
|
|
pen = m_nespens[palval];
|
|
}
|
|
|
|
*dest = pen;
|
|
|
|
// priority marking
|
|
if (!trans)
|
|
line_priority[start_x + i] |= 0x02;
|
|
}
|
|
dest++;
|
|
}
|
|
}
|
|
|
|
void ppu_sh6578_device::draw_background(uint8_t* line_priority)
|
|
{
|
|
bitmap_rgb32& bitmap = *m_bitmap;
|
|
|
|
uint8_t color_mask = 0xff;
|
|
//const pen_t* color_table;
|
|
|
|
/* setup the color mask and colortable to use */
|
|
|
|
//TODO FIX
|
|
if (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO)
|
|
{
|
|
color_mask = 0xf0;
|
|
}
|
|
else
|
|
{
|
|
color_mask = 0xff;
|
|
}
|
|
|
|
|
|
/* cache the background pen */
|
|
pen_t back_pen = m_nespens[m_back_color & color_mask];
|
|
|
|
/* determine where in the nametable to start drawing from */
|
|
/* based on the current scanline and scroll regs */
|
|
uint8_t scroll_x_coarse = m_refresh_data & 0x001f;
|
|
uint8_t scroll_y_coarse = (m_refresh_data & 0x03e0) >> 5;
|
|
uint16_t nametable = (m_refresh_data & 0x0c00);
|
|
uint8_t scroll_y_fine = (m_refresh_data & 0x7000) >> 12;
|
|
|
|
int x = scroll_x_coarse;
|
|
|
|
/* get the tile index */
|
|
int tile_index = (nametable<<1) + scroll_y_coarse * 64;
|
|
|
|
/* set up dest */
|
|
int start_x = (m_x_fine ^ 0x07) - 7;
|
|
uint32_t* dest = &bitmap.pix32(m_scanline, start_x);
|
|
|
|
m_tilecount = 0;
|
|
|
|
/* draw the 32 or 33 tiles that make up a line */
|
|
while (m_tilecount < 34)
|
|
{
|
|
int color_byte;
|
|
int index1;
|
|
int page2, address;
|
|
|
|
index1 = tile_index + (x << 1);
|
|
|
|
if (m_colsel_pntstart & 1)
|
|
{
|
|
index1 &= 0x7ff;
|
|
index1 += 0x2000;
|
|
}
|
|
else
|
|
{
|
|
index1 &= 0x1fff;
|
|
}
|
|
|
|
// page2 is the output of the nametable read (this section is the FIRST read per tile!)
|
|
page2 = readbyte(index1);
|
|
|
|
/* Figure out which byte in the color table to use */
|
|
color_byte = readbyte(index1 + 1);
|
|
|
|
if (start_x < VISIBLE_SCREEN_WIDTH)
|
|
{
|
|
address = ((page2 | (color_byte<<8)) & 0x0fff) << 4;
|
|
// plus something that accounts for y
|
|
address += scroll_y_fine;
|
|
|
|
draw_tile(line_priority, (color_byte >> 4) & 0xf, 0, address, start_x, back_pen, dest);
|
|
|
|
start_x += 8;
|
|
|
|
/* move to next tile over and toggle the horizontal name table if necessary */
|
|
x++;
|
|
if (x > 31)
|
|
{
|
|
x = 0;
|
|
tile_index ^= 0x800;
|
|
}
|
|
}
|
|
m_tilecount++;
|
|
}
|
|
|
|
/* if the left 8 pixels for the background are off, blank 'em */
|
|
if (!(m_regs[PPU_CONTROL1] & PPU_CONTROL1_BACKGROUND_L8))
|
|
{
|
|
dest = &bitmap.pix32(m_scanline);
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
*(dest++) = back_pen;
|
|
line_priority[i] ^= 0x02;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ppu_sh6578_device::read_sprite_plane_data(int address)
|
|
{
|
|
m_planebuf[0] = readbyte((address + 0) & 0x3fff);
|
|
m_planebuf[1] = readbyte((address + 8) & 0x3fff);
|
|
}
|
|
|
|
|
|
int ppu_sh6578_device::apply_sprite_pattern_page(int index1, int size)
|
|
{
|
|
index1 += (((m_colsel_pntstart >> 2) & 0x3) * 0x1000);
|
|
return index1;
|
|
}
|
|
|
|
/*
|
|
void ppu_sh6578_device::draw_sprites(uint8_t* line_priority)
|
|
{
|
|
}
|
|
*/
|
|
|
|
void ppu_sh6578_device::write_extended(offs_t offset, uint8_t data)
|
|
{
|
|
LOGMASKED(LOG_PPU_EXTRA, "%s: ppu_sh6578_device::write : Color Select & PNT Start Address : %02x\n", machine().describe_context(), data);
|
|
m_colsel_pntstart = data;
|
|
}
|
|
|
|
|
|
uint8_t ppu_sh6578_device::read_extended(offs_t offset)
|
|
{
|
|
LOGMASKED(LOG_PPU_EXTRA, "%s: ppu_sh6578_device::read : Color Select & PNT Start Address\n", machine().describe_context());
|
|
return m_colsel_pntstart;
|
|
}
|
|
|
|
void ppu_sh6578_device::palette_write(offs_t offset, uint8_t data)
|
|
{
|
|
m_palette_ram[offset] = data;
|
|
}
|
|
|
|
uint8_t ppu_sh6578_device::palette_read(offs_t offset)
|
|
{
|
|
return m_palette_ram[offset];
|
|
}
|