Initial Intellivison commits

Test game: Armor Battle
This commit is contained in:
alyosha-tas 2016-11-11 16:47:55 -05:00 committed by GitHub
parent e72ce6d9cb
commit 65e43ca1c4
5 changed files with 320 additions and 19 deletions

View File

@ -1,4 +1,5 @@
using BizHawk.Emulation.Common;
using System;
namespace BizHawk.Emulation.Cores.Intellivision
{
@ -38,6 +39,9 @@ namespace BizHawk.Emulation.Cores.Intellivision
public void FrameAdvance(bool render, bool rendersound)
{
Frame++;
// read the controller state here for now
get_controller_state();
//_stic.Mobs();
_cpu.AddPendingCycles(14934);
while (_cpu.GetPendingCycles() > 0)
{
@ -46,6 +50,9 @@ namespace BizHawk.Emulation.Cores.Intellivision
Connect();
_cpu.LogData();
}
_stic.Background();
_stic.Mobs();
}
public int Frame { get; private set; }
@ -71,5 +78,67 @@ namespace BizHawk.Emulation.Cores.Intellivision
{
}
public void get_controller_state()
{
ushort result = 0;
// player 1
for (int i = 0; i < 31; i++)
{
if (Controller.IsPressed(IntellivisionController.BoolButtons[i]))
{
result |= HandControllerButtons[i];
}
}
_psg.Register[14] = (ushort)(0xFF - result);
result = 0;
// player 2
for (int i = 31; i < 62; i++)
{
if (Controller.IsPressed(IntellivisionController.BoolButtons[i]))
{
result |= HandControllerButtons[i];
}
}
_psg.Register[15] = (ushort)(0xFF - result);
}
static byte[] HandControllerButtons = new byte[] {
0x60, //OUTPUT_ACTION_BUTTON_BOTTOM_LEFT
0xC0, //OUTPUT_ACTION_BUTTON_BOTTOM_RIGHT
0xA0, //OUTPUT_ACTION_BUTTON_TOP
0x48, //OUTPUT_KEYPAD_ZERO
0x81, //OUTPUT_KEYPAD_ONE
0x41, //OUTPUT_KEYPAD_TWO
0x21, //OUTPUT_KEYPAD_THREE
0x82, //OUTPUT_KEYPAD_FOUR
0x42, //OUTPUT_KEYPAD_FIVE
0x22, //OUTPUT_KEYPAD_SIX
0x84, //OUTPUT_KEYPAD_SEVEN
0x44, //OUTPUT_KEYPAD_EIGHT
0x24, //OUTPUT_KEYPAD_NINE
0x28, //OUTPUT_KEYPAD_ENTER
0x88, //OUTPUT_KEYPAD_CLEAR
0x04, //OUTPUT_DISC_NORTH
0x14, //OUTPUT_DISC_NORTH_NORTH_EAST
0x16, //OUTPUT_DISC_NORTH_EAST
0x06, //OUTPUT_DISC_EAST_NORTH_EAST
0x02, //OUTPUT_DISC_EAST
0x12, //OUTPUT_DISC_EAST_SOUTH_EAST
0x13, //OUTPUT_DISC_SOUTH_EAST
0x03, //OUTPUT_DISC_SOUTH_SOUTH_EAST
0x01, //OUTPUT_DISC_SOUTH
0x11, //OUTPUT_DISC_SOUTH_SOUTH_WEST
0x19, //OUTPUT_DISC_SOUTH_WEST
0x09, //OUTPUT_DISC_WEST_SOUTH_WEST
0x08, //OUTPUT_DISC_WEST
0x18, //OUTPUT_DISC_WEST_NORTH_WEST
0x1C, //OUTPUT_DISC_NORTH_WEST
0x0C //OUTPUT_DISC_NORTH_NORTH_WEST
};
}
}
}

View File

@ -1,4 +1,6 @@
namespace BizHawk.Emulation.Cores.Intellivision
using System;
namespace BizHawk.Emulation.Cores.Intellivision
{
public sealed partial class Intellivision
{
@ -7,8 +9,8 @@
private byte[] ScratchpadRam = new byte[240];
private ushort[] SystemRam = new ushort[352];
private ushort[] ExecutiveRom = new ushort[4096]; // TODO: Intellivision II support?
private byte[] GraphicsRom = new byte[2048];
private byte[] GraphicsRam = new byte[512];
public byte[] GraphicsRom = new byte[2048];
public byte[] GraphicsRam = new byte[512];
public ushort ReadMemory(ushort addr)
{
@ -37,6 +39,18 @@
else if (addr <= 0x01FF)
{
// PSG.
//controllers
if (addr==0x01FE)
{
//Console.WriteLine("reading controller");
return _psg.Register[14];
}
if (addr == 0x01FF)
{
//Console.WriteLine("reading controller");
return _psg.Register[15];
}
break;
}
else if (addr <= 0x035F)

View File

@ -98,16 +98,18 @@ namespace BizHawk.Emulation.Cores.Intellivision
new ControllerDefinition
{
Name = "Intellivision Controller",
BoolButtons = {
"P1 Up", "P1 Down", "P1 Left", "P1 Right",
"P1 L", "P1 R",
BoolButtons = {
"P1 L", "P1 R", "P1 Top",
"P1 Key 0", "P1 Key 1", "P1 Key 2", "P1 Key 3", "P1 Key 4", "P1 Key 5",
"P1 Key 6", "P1 Key 7", "P1 Key 8", "P1 Key 9", "P1 Enter", "P1 Clear",
"P1 N", "P1 NNE", "P1 NE", "P1 ENE","P1 E", "P1 ESE", "P1 SE", "P1 SSE",
"P1 S", "P1 SSW", "P1 SW", "P1 WSW","P1 W", "P1 WNW", "P1 NW", "P1 NNW",
"P2 Up", "P2 Down", "P2 Left", "P2 Right",
"P2 L", "P2 R",
"P2 L", "P2 R", "P2 Top",
"P2 Key 0", "P2 Key 1", "P2 Key 2", "P2 Key 3", "P2 Key 4", "P2 Key 5",
"P2 Key 6", "P2 Key 7", "P2 Key 8", "P2 Key 9", "P2 Enter", "P2 Clear"
"P2 Key 6", "P2 Key 7", "P2 Key 8", "P2 Key 9", "P2 Enter", "P2 Clear",
"P2 N", "P2 NNE", "P2 NE", "P2 ENE","P2 E", "P2 ESE", "P2 SE", "P2 SSE",
"P2 S", "P2 SSW", "P2 SW", "P2 WSW","P2 W", "P2 WNW", "P2 NW", "P2 NNW",
}
};
}

View File

@ -4,7 +4,7 @@ namespace BizHawk.Emulation.Cores.Intellivision
{
public sealed class PSG
{
private ushort[] Register = new ushort[16];
public ushort[] Register = new ushort[16];
public int TotalExecutedCycles;
public int PendingCycles;

View File

@ -1,5 +1,6 @@
using System;
using BizHawk.Emulation.Common;
using BizHawk.Common.NumberExtensions;
namespace BizHawk.Emulation.Cores.Intellivision
{
@ -9,25 +10,28 @@ namespace BizHawk.Emulation.Cores.Intellivision
private ushort[] Register = new ushort[64];
private ushort ColorSP = 0x0028;
public byte[] mobs = new byte[8];
public byte[] y_mobs = new byte[8];
public int TotalExecutedCycles;
public int PendingCycles;
public Func<ushort, ushort> ReadMemory;
public Func<ushort, ushort, bool> WriteMemory;
public int[] FrameBuffer = new int[159 * 96];
public int[] BGBuffer = new int[159 * 96];
public int[] FrameBuffer = new int[159 * 192];
public int[] GetVideoBuffer()
{
Background();
Mobs();
return FrameBuffer;
}
public int VirtualWidth { get { return 159; } }
public int BufferWidth { get { return 159; } }
public int VirtualHeight { get { return 192; } }
public int BufferHeight { get { return 96; } }
public int BufferHeight { get { return 192; } }
public int BackgroundColor { get { return 0; } }
public void Reset()
@ -304,7 +308,7 @@ namespace BizHawk.Emulation.Cores.Intellivision
color = 3;
}
}
FrameBuffer[pixel] = ColorToRGBA(colors[color]);
BGBuffer[pixel] = ColorToRGBA(colors[color]);
}
}
continue;
@ -348,22 +352,234 @@ namespace BizHawk.Emulation.Cores.Intellivision
if ((row & 0x1) != 0)
{
// The pixels go right as the bits get less significant.
FrameBuffer[pixel] = ColorToRGBA(fg);
BGBuffer[pixel] = ColorToRGBA(fg);
}
else
{
FrameBuffer[pixel] = ColorToRGBA(bg);
BGBuffer[pixel] = ColorToRGBA(bg);
}
row >>= 1;
}
}
}
}
// now that we have the cards in BGbuffer, we can double vertical resolution to get Frame buffer
for (int j=0;j<96;j++)
{
for (int i = 0; i < 159; i++)
{
FrameBuffer[(j * 2) * 159 + i] = BGBuffer[j * 159 + i];
FrameBuffer[(j * 2+1) * 159 + i] = BGBuffer[j * 159 + i];
}
}
}
// see for more details: http://spatula-city.org/~im14u2c/intv/jzintv-1.0-beta3/doc/programming/stic.txt
/*
The STIC provides 3 registers for controlling each MOB, and a 4th register
for reading its collision (or "interaction") status. The registers are
laid out as follows:
X Register: Address = $0000 + MOB #
13 12 11 10 9 8 7 6 5 4 3 2 1 0
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| ?? | ?? | ?? | X |VISB|INTR| X Coordinate |
| | | |SIZE| | | (0 to 255) |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
Y Register: Address = $0008 + MOB #
13 12 11 10 9 8 7 6 5 4 3 2 1 0
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| ?? | ?? | Y | X | Y | Y |YRES| Y Coordinate |
| | |FLIP|FLIP|SIZ4|SIZ2| | (0 to 127) |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
A Register: Address = $0010 + MOB #
13 12 11 10 9 8 7 6 5 4 3 2 1 0
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
|PRIO| FG |GRAM| GRAM/GROM Card # (0 to 255) | FG Color |
| |bit3|GROM| (bits 9, 10 ignored for GRAM) | Bits 0-2 |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
C Register: Address = $0018 + MOB #
13 12 11 10 9 8 7 6 5 4 3 2 1 0
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| ?? | ?? | ?? | ?? |COLL|COLL|COLL|COLL|COLL|COLL|COLL|COLL|COLL|COLL|
| | | | |BORD| BG |MOB7|MOB6|MOB5|MOB4|MOB3|MOB2|MOB1|MOB0|
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
*/
public void Mobs()
{
// TODO
// fill the frame buffer with graphics for each of the 8 mobs
ushort x;
ushort y;
ushort attr;
byte row;
for (int i = 0; i < 8; i++)
{
x = Register[i];
y = Register[i + 8];
attr = Register[i + 16];
byte card = (byte)(attr >> 3);
bool gram = attr.Bit(11);
byte loc_color = (byte)(attr & 3);
bool color_3 = attr.Bit(12);
if (color_3)
loc_color += 4;
byte loc_x = (byte)(x & 0xFF);
byte loc_y = (byte)(y & 0x7F);
bool vis = x.Bit(9);
bool x_flip = y.Bit(10);
bool y_flip = y.Bit(11);
bool yres = y.Bit(7);
bool ysiz2 = y.Bit(8);
bool ysiz4 = y.Bit(9);
// setting yres implicitly uses an even card first
if (yres)
card &= 0xFE;
// in GRAM mode only take the first 6 bits of the card number
if (gram)
card &= 0x3F;
//pull the data from the card into the mobs array
for (int j=0;j<8;j++)
{
if (gram)
{
row = (byte)ReadMemory((ushort)(0x3800 + 8 * card + j));
}
else
{
row = (byte)ReadMemory((ushort)(0x3000 + 8 * card + j));
}
mobs[j] = row;
}
// assign the y_mob, used to double vertical resolution
if (yres)
{
for (int j = 0; j < 8; j++)
{
if (gram)
{
row = (byte)ReadMemory((ushort)(0x3800 + 8 * (card + 1) + j));
}
else
{
row = (byte)ReadMemory((ushort)(0x3000 + 8 * (card + 1) + j));
}
y_mobs[j] = row;
}
}
//flip mobs accordingly
if (x_flip)
{
for (int j = 0; j < 8; j++)
{
byte temp_0 = (byte)((mobs[j] & 1) << 7);
byte temp_1 = (byte)((mobs[j] & 2) << 5);
byte temp_2 = (byte)((mobs[j] & 4) << 3);
byte temp_3 = (byte)((mobs[j] & 8) << 1);
byte temp_4 = (byte)((mobs[j] & 16) >> 1);
byte temp_5 = (byte)((mobs[j] & 32) >> 3);
byte temp_6 = (byte)((mobs[j] & 64) >> 5);
byte temp_7 = (byte)((mobs[j] & 128) >> 7);
mobs[j] = (byte)(temp_0 + temp_1 + temp_2 + temp_3 + temp_4 + temp_5 + temp_6 + temp_7);
}
if (yres)
{
for (int j = 0; j < 8; j++)
{
byte temp_0 = (byte)((y_mobs[j] & 1) << 7);
byte temp_1 = (byte)((y_mobs[j] & 2) << 5);
byte temp_2 = (byte)((y_mobs[j] & 4) << 3);
byte temp_3 = (byte)((y_mobs[j] & 8) << 1);
byte temp_4 = (byte)((y_mobs[j] & 16) >> 1);
byte temp_5 = (byte)((y_mobs[j] & 32) >> 3);
byte temp_6 = (byte)((y_mobs[j] & 64) >> 5);
byte temp_7 = (byte)((y_mobs[j] & 128) >> 7);
y_mobs[j] = (byte)(temp_0 + temp_1 + temp_2 + temp_3 + temp_4 + temp_5 + temp_6 + temp_7);
}
}
}
if (y_flip)
{
byte temp_0 = mobs[0];
byte temp_1 = mobs[1];
byte temp_2 = mobs[2];
byte temp_3 = mobs[3];
mobs[0] = mobs[7];
mobs[1] = mobs[6];
mobs[2] = mobs[5];
mobs[3] = mobs[4];
mobs[4] = temp_3;
mobs[5] = temp_2;
mobs[6] = temp_1;
mobs[7] = temp_0;
}
//TODO:stretch
//TODO:collision
//TODO:pixel priority
//draw the mob
//we already have the BG at this point, so for now let's assume mobs have priority for testing
for (int j = 0; j < 8; j++)
{
for (int k = 0; k < 8; k++)
{
bool pixel = mobs[j].Bit(7 - k);
if ((loc_x + k) < 159 && (loc_y + j) < 192 && pixel && vis)
{
FrameBuffer[(loc_y + j) * 159 + loc_x + k] = ColorToRGBA(loc_color);
}
}
}
if (yres)
{
for (int j = 0; j < 8; j++)
{
for (int k = 0; k < 8; k++)
{
bool pixel = y_mobs[j].Bit(7 - k);
if ((loc_x + k) < 159 && (loc_y+8 + j) < 192 && pixel && vis)
{
FrameBuffer[(loc_y+8 + j) * 159 + loc_x + k] = ColorToRGBA(loc_color);
}
}
}
}
}
}
}
}