galaga: Manually apply pull request #3532: star field lfsr

implementation

Manually applied the lfsr part of #3532 and verifying against static
star field. Also added documentation and my findings about the known
star field decoding algorithms.
This commit is contained in:
couriersud 2019-05-12 14:07:43 +02:00
parent 380fb5d313
commit 4be4bb12e9
2 changed files with 102 additions and 0 deletions

View File

@ -63,6 +63,8 @@ public:
void galaga_mem4(address_map &map);
void gatsbee_main_map(address_map &map);
void starfield_init();
protected:
virtual void machine_start() override;
virtual void machine_reset() override;

View File

@ -11,6 +11,12 @@
#include "emu.h"
#include "includes/galaga.h"
#define LOG_DEBUG (1 << 0U)
#define LOG_ALL (LOG_DEBUG)
#define VERBOSE (LOG_ALL)
#include "logmacro.h"
#define MAX_STARS 252
#define STARS_COLOR_BASE (64*4+64*4)
@ -376,7 +382,99 @@ void galaga_state::galaga_palette(palette_device &palette) const
palette.set_pen_indirect(64*4 + 64*4 + i, 32 + i);
}
/***************************************************************************
Star field documentation
Couriersud, May 2019:
The code below was manually applied based on a pull request from
Jindřich Makovička. He based his work on information published by
Wolfgang Scherr about the 05XX on pin4.at.
Wolfgang shared is VHDL implementation with the MAME team. I have
created a spreadsheet implementation for his decode logic.
Both implementations use the same Galois type LFSR( tap 15,12,10,5).
Using the same seed value, the following holds true:
Decode_W(lfsr[t-4]) = Decode_J(lfsr[t])
The two decoding algorithm (Wolfgang, Jindřich) thus deliver the same
results but with a 4 clock difference.
Jindřich's code filters out stars with y<4. This matches the starfield
measurements documented above. Wolfgang states that his code matches his
measurements and there are stars with y<4.
We need to have a closer look at this.
Both implementations are complex compared to other star field gnerators
used in the industry. We thus now have two decoding solutions matching
the output. I wonder if there is a simpler one.
***************************************************************************/
void galaga_state::starfield_init()
{
const uint16_t feed = 0x9420;
int idx = 0;
for (uint16_t sf = 0; sf < 4; ++sf)
{
// starfield select flags
uint16_t sf1 = (sf >> 1) & 1;
uint16_t sf2 = sf & 1;
uint16_t i = 0x70cc;
for (int cnt = 0; cnt < 65535; ++cnt)
{
// output enable lookup
uint16_t xor1 = i ^ (i >> 3);
uint16_t xor2 = xor1 ^ (i >> 2);
uint16_t oe = (sf1 ? 0 : 0x4000) | ((sf1 ^ sf2) ? 0 : 0x1000);
if ((i & 0x8007) == 0x8007
&& (~i & 0x2008) == 0x2008
&& (xor1 & 0x0100) == (sf1 ? 0 : 0x0100)
&& (xor2 & 0x0040) == (sf2 ? 0 : 0x0040)
&& (i & 0x5000) == oe
&& cnt >= 256 * 4)
{
// color lookup
uint16_t xor3 = (i >> 1) ^ (i >> 6);
uint16_t clr =
(((i >> 9) & 0x07)
| ((xor3 ^ (i >> 4) ^ (i >> 7)) & 0x08)
| (~xor3 & 0x10)
| (((i >> 2) ^ (i >> 5)) & 0x20))
^ ((i & 0x4000) ? 0 : 0x24)
^ ((((i >> 2) ^ i) & 0x1000) ? 0x21 : 0);
#if 0
m_star_seed_tab[idx].x = cnt % 256;
m_star_seed_tab[idx].y = cnt / 256;
m_star_seed_tab[idx].col = clr;
m_star_seed_tab[idx].set = sf;
#else
int x = cnt % 256;
int y = cnt / 256;
int col = clr;
int set = sf;
if ((x != s_star_seed_tab[idx].x) || (y != s_star_seed_tab[idx].y)
|| (col != s_star_seed_tab[idx].col) || (s_star_seed_tab[idx].set != set))
LOGMASKED(LOG_DEBUG, "Mismatch: %d %d %d %d %d %d %d %d\n", x, y, col, set, s_star_seed_tab[idx].x,
s_star_seed_tab[idx].y, s_star_seed_tab[idx].col, s_star_seed_tab[idx].set);
#endif
++idx;
}
// update the LFSR
if (i & 1)
i = (i >> 1) ^ feed;
else
i = (i >> 1);
}
}
}
/***************************************************************************
@ -433,6 +531,8 @@ VIDEO_START_MEMBER(galaga_state,galaga)
save_item(NAME(m_stars_scrollx));
save_item(NAME(m_stars_scrolly));
save_item(NAME(m_galaga_gfxbank));
starfield_init();
}