parent
e72ce6d9cb
commit
65e43ca1c4
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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",
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue