TI-83 emulator lol
This commit is contained in:
parent
0aeb57c3b6
commit
3c7534e92a
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
|
@ -47,6 +47,7 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Consoles\Calculator\TI83.cs" />
|
||||
<Compile Include="Consoles\Sega\SMS\MemoryMap.CodeMasters.cs" />
|
||||
<Compile Include="Consoles\Sega\SMS\MemoryMap.Sega.cs" />
|
||||
<Compile Include="Consoles\Sega\SMS\VDP.ModeTMS.cs" />
|
||||
|
|
|
@ -0,0 +1,449 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using BizHawk.Emulation.CPUs.Z80;
|
||||
|
||||
//http://www.ticalc.org/pub/text/calcinfo/
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.Calculator
|
||||
{
|
||||
public class TI83 : IEmulator
|
||||
{
|
||||
//hardware
|
||||
Z80A cpu = new Z80A();
|
||||
byte[] rom;
|
||||
byte[] ram;
|
||||
int romPageLow3Bits;
|
||||
int romPageHighBit;
|
||||
bool maskOn;
|
||||
bool onPressed = false;
|
||||
int keyboardMask;
|
||||
|
||||
int disp_mode;
|
||||
int disp_move;
|
||||
uint disp_x, disp_y;
|
||||
int m_LinkOutput, m_LinkState;
|
||||
bool m_CursorMoved;
|
||||
//-------
|
||||
|
||||
|
||||
public byte ReadMemory(ushort addr)
|
||||
{
|
||||
int romPage = romPageLow3Bits | (romPageHighBit << 3);
|
||||
//Console.WriteLine("read memory: {0:X4}", addr);
|
||||
if (addr < 0x4000)
|
||||
return rom[addr]; //ROM zero-page
|
||||
else if (addr < 0x8000)
|
||||
return rom[romPage*0x4000+addr-0x4000]; //other rom page
|
||||
else return ram[addr - 0x8000];
|
||||
}
|
||||
|
||||
public void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
if (addr < 0x4000)
|
||||
return; //ROM zero-page
|
||||
else if (addr < 0x8000)
|
||||
return; //other rom page
|
||||
else ram[addr - 0x8000] = value;
|
||||
}
|
||||
|
||||
public void WriteHardware(ushort addr, byte value)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0: //PORT_LINK
|
||||
romPageHighBit = (value >> 4) & 1;
|
||||
m_LinkOutput = value & 3;
|
||||
m_LinkState = m_LinkOutput ^ 3;
|
||||
break;
|
||||
case 1: //PORT_KEYBOARD:
|
||||
keyboardMask = value;
|
||||
Console.WriteLine("write PORT_KEYBOARD {0:X2}",value);
|
||||
break;
|
||||
case 2: //PORT_ROMPAGE
|
||||
romPageLow3Bits = value & 0x7;
|
||||
break;
|
||||
case 3: //PORT_STATUS
|
||||
maskOn = ((value & 1) == 1);
|
||||
break;
|
||||
case 16: //PORT_DISPCTRL
|
||||
//Console.WriteLine("write PORT_DISPCTRL {0}",value);
|
||||
WriteDispCtrl(value);
|
||||
break;
|
||||
case 17: //PORT_DISPDATA
|
||||
//Console.WriteLine("write PORT_DISPDATA {0}",value);
|
||||
WriteDispData(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public byte ReadHardware(ushort addr)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0: //PORT_LINK
|
||||
return (byte)((romPageHighBit << 4) | (m_LinkState<<2) | m_LinkOutput);
|
||||
case 1: //PORT_KEYBOARD:
|
||||
//Console.WriteLine("read PORT_KEYBOARD");
|
||||
return ReadKeyboard();
|
||||
case 2: //PORT_ROMPAGE
|
||||
return (byte)romPageLow3Bits;
|
||||
case 3: //PORT_STATUS
|
||||
{
|
||||
//Console.WriteLine("read PORT_STATUS");
|
||||
byte ret = 0;
|
||||
// Bits:
|
||||
// 0 - Set if ON key is down and ON key is trapped
|
||||
// 1 - Update things (keyboard etc)
|
||||
// 2 - Unknown, but used
|
||||
// 3 - Set if ON key is up
|
||||
// 4-7 - Unknown
|
||||
//if (onPressed && maskOn) ret |= 1;
|
||||
//if (!onPressed) ret |= 0x8;
|
||||
ret |= 0x8; //on key is up
|
||||
ret |= 0x2; //link isnt emulated
|
||||
return ret;
|
||||
}
|
||||
|
||||
case 4: //PORT_INTCTRL
|
||||
Console.WriteLine("read PORT_INTCTRL");
|
||||
return 0xFF;
|
||||
|
||||
case 16: //PORT_DISPCTRL
|
||||
Console.WriteLine("read DISPCTRL");
|
||||
break;
|
||||
|
||||
case 17: //PORT_DISPDATA
|
||||
return ReadDispData();
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
byte ReadKeyboard()
|
||||
{
|
||||
//ref TI-9X
|
||||
|
||||
int ret = 0xFF;
|
||||
Console.WriteLine("keyboardMask: {0:X2}",keyboardMask);
|
||||
if ((keyboardMask & 1) == 0)
|
||||
{
|
||||
if (Controller.IsPressed("DOWN")) ret ^= 1;
|
||||
if (Controller.IsPressed("LEFT")) ret ^= 2;
|
||||
if (Controller.IsPressed("RIGHT")) ret ^= 4;
|
||||
if (Controller.IsPressed("UP")) ret ^= 8;
|
||||
}
|
||||
if ((keyboardMask & 2) == 0)
|
||||
{
|
||||
if (Controller.IsPressed("ENTER")) ret ^= 1;
|
||||
if (Controller.IsPressed("PLUS")) ret ^= 2;
|
||||
if (Controller.IsPressed("MINUS")) ret ^= 4;
|
||||
if (Controller.IsPressed("MULTIPLY")) ret ^= 8;
|
||||
if (Controller.IsPressed("DIVIDE")) ret ^= 16;
|
||||
//(exponent key)
|
||||
if (Controller.IsPressed("CLEAR")) ret ^= 64;
|
||||
}
|
||||
if ((keyboardMask & 4) == 0)
|
||||
{
|
||||
if (Controller.IsPressed("3")) ret ^= 2;
|
||||
if (Controller.IsPressed("6")) ret ^= 4;
|
||||
if (Controller.IsPressed("9")) ret ^= 8;
|
||||
}
|
||||
if ((keyboardMask & 8) == 0)
|
||||
{
|
||||
if (Controller.IsPressed("DOT")) ret ^= 1;
|
||||
if (Controller.IsPressed("2")) ret ^= 2;
|
||||
if (Controller.IsPressed("5")) ret ^= 4;
|
||||
if (Controller.IsPressed("8")) ret ^= 8;
|
||||
}
|
||||
if ((keyboardMask & 16) == 0)
|
||||
{
|
||||
if (Controller.IsPressed("0")) ret ^= 1;
|
||||
if (Controller.IsPressed("1")) ret ^= 2;
|
||||
if (Controller.IsPressed("4")) ret ^= 4;
|
||||
if (Controller.IsPressed("7")) ret ^= 8;
|
||||
}
|
||||
|
||||
return (byte)ret;
|
||||
|
||||
}
|
||||
|
||||
byte ReadDispData()
|
||||
{
|
||||
if (m_CursorMoved)
|
||||
{
|
||||
m_CursorMoved = false;
|
||||
return 0x00; //not accurate this should be stale data or something
|
||||
}
|
||||
|
||||
byte ret;
|
||||
if (disp_mode == 1)
|
||||
{
|
||||
ret = vram[disp_y * 12 + disp_x];
|
||||
}
|
||||
else
|
||||
{
|
||||
int column = 6 * (int)disp_x;
|
||||
int offset = (int)disp_y * 12 + (column >> 3);
|
||||
int shift = 10 - (column & 7);
|
||||
ret = (byte)(((vram[offset] << 8) | vram[offset + 1]) >> shift);
|
||||
}
|
||||
|
||||
doDispMove();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WriteDispData(byte value)
|
||||
{
|
||||
int offset = -1;
|
||||
if (disp_mode == 1)
|
||||
{
|
||||
offset = (int)disp_y * 12 + (int)disp_x;
|
||||
vram[offset] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
int column = 6 * (int)disp_x;
|
||||
offset = (int)disp_y * 12 + (column >> 3);
|
||||
if (offset < 0x300)
|
||||
{
|
||||
int shift = column & 7;
|
||||
int mask = ~(252 >> shift);
|
||||
int Data = value << 2;
|
||||
vram[offset] = (byte)(vram[offset] & mask | (Data >> shift));
|
||||
if (shift > 2 && offset < 0x2ff)
|
||||
{
|
||||
offset++;
|
||||
|
||||
shift = 8 - shift;
|
||||
|
||||
mask = ~(252 << shift);
|
||||
vram[offset] = (byte)(vram[offset] & mask | (Data << shift));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doDispMove();
|
||||
}
|
||||
|
||||
void doDispMove()
|
||||
{
|
||||
switch (disp_move)
|
||||
{
|
||||
case 0: disp_y--; break;
|
||||
case 1: disp_y++; break;
|
||||
case 2: disp_x--; break;
|
||||
case 3: disp_x++; break;
|
||||
}
|
||||
|
||||
disp_x &= 0xF; //0xF or 0x1F? dunno
|
||||
disp_y &= 0x3F;
|
||||
}
|
||||
|
||||
void WriteDispCtrl(byte value)
|
||||
{
|
||||
if (value <= 1)
|
||||
disp_mode = value;
|
||||
else if (value >= 4 && value <= 7)
|
||||
disp_move = value - 4;
|
||||
else if ((value & 0xC0) == 0x40)
|
||||
{
|
||||
//hardware scroll
|
||||
}
|
||||
else if ((value & 0xE0) == 0x20)
|
||||
{
|
||||
disp_x = (uint)(value & 0x1F);
|
||||
m_CursorMoved = true;
|
||||
}
|
||||
else if ((value & 0xC0) == 0x80)
|
||||
{
|
||||
disp_y = (uint)(value & 0x3F);
|
||||
m_CursorMoved = true;
|
||||
}
|
||||
else if ((value & 0xC0) == 0xC0)
|
||||
{
|
||||
//contrast
|
||||
}
|
||||
else if (value == 2)
|
||||
{
|
||||
}
|
||||
else if (value == 3)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public TI83()
|
||||
{
|
||||
cpu.ReadMemory = ReadMemory;
|
||||
cpu.WriteMemory = WriteMemory;
|
||||
cpu.ReadHardware = ReadHardware;
|
||||
cpu.WriteHardware = WriteHardware;
|
||||
cpu.IRQCallback = IRQCallback;
|
||||
cpu.NMICallback = NMICallback;
|
||||
}
|
||||
|
||||
void IRQCallback()
|
||||
{
|
||||
//Console.WriteLine("IRQ with vec {0} and cpu.InterruptMode {1}", cpu.RegisterI, cpu.InterruptMode);
|
||||
cpu.Interrupt = false;
|
||||
}
|
||||
|
||||
void NMICallback()
|
||||
{
|
||||
Console.WriteLine("NMI");
|
||||
cpu.NonMaskableInterrupt = false;
|
||||
}
|
||||
|
||||
protected byte[] vram = new byte[0x300];
|
||||
class MyVideoProvider : IVideoProvider
|
||||
{
|
||||
TI83 emu;
|
||||
public MyVideoProvider(TI83 emu)
|
||||
{
|
||||
this.emu = emu;
|
||||
}
|
||||
|
||||
public int[] GetVideoBuffer() {
|
||||
//unflatten bit buffer
|
||||
int[] pixels = new int[96*64];
|
||||
int i=0;
|
||||
for(int y=0;y<64;y++)
|
||||
for (int x = 0; x < 96; x++)
|
||||
{
|
||||
int offset = y * 96 + x;
|
||||
int bufbyte = offset >> 3;
|
||||
int bufbit = offset & 7;
|
||||
int bit = ((emu.vram[bufbyte] >> (7 - bufbit)) & 1);
|
||||
if(bit==0)
|
||||
pixels[i++] = 0xFFFFFF;
|
||||
else
|
||||
pixels[i++] = 0;
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
public int BufferWidth { get { return 96; } }
|
||||
public int BufferHeight { get { return 64; } }
|
||||
public int BackgroundColor { get { return 0; } }
|
||||
}
|
||||
public IVideoProvider VideoProvider { get { return new MyVideoProvider(this); } }
|
||||
|
||||
class MySoundProvider : ISoundProvider
|
||||
{
|
||||
public void GetSamples(short[] samples)
|
||||
{
|
||||
}
|
||||
}
|
||||
public ISoundProvider SoundProvider { get { return new MySoundProvider(); } }
|
||||
|
||||
public static readonly ControllerDefinition TI83Controller =
|
||||
new ControllerDefinition
|
||||
{
|
||||
Name = "TI83 Controls",
|
||||
BoolButtons = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9","DOT",
|
||||
"ON","ENTER",
|
||||
"DOWN","LEFT","UP","RIGHT",
|
||||
"PLUS","MINUS","MULTIPLY","DIVIDE",
|
||||
"CLEAR"
|
||||
}
|
||||
};
|
||||
|
||||
public ControllerDefinition ControllerDefinition { get { return TI83Controller; } }
|
||||
|
||||
IController controller;
|
||||
public IController Controller
|
||||
{
|
||||
get { return controller; }
|
||||
set { controller = value; }
|
||||
}
|
||||
//configuration
|
||||
ushort startPC;
|
||||
|
||||
public void LoadGame(IGame game)
|
||||
{
|
||||
rom = game.GetRomData();
|
||||
foreach (string opt in game.GetOptions())
|
||||
{
|
||||
//different calculators (different revisions?) have different initPC. we track this in the game database by rom hash
|
||||
//if( *(unsigned long *)(m_pRom + 0x6ce) == 0x04D3163E ) m_Regs.PC.W = 0x6ce; //KNOWN
|
||||
//else if( *(unsigned long *)(m_pRom + 0x6f6) == 0x04D3163E ) m_Regs.PC.W = 0x6f6; //UNKNOWN
|
||||
|
||||
if (opt.StartsWith("initPC"))
|
||||
startPC = ushort.Parse(opt.Split('=')[1], NumberStyles.HexNumber);
|
||||
}
|
||||
|
||||
HardReset();
|
||||
}
|
||||
|
||||
public void FrameAdvance(bool render)
|
||||
{
|
||||
//I eyeballed this speed
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
onPressed = Controller.IsPressed("ON");
|
||||
//and this was derived from other emus
|
||||
cpu.ExecuteCycles(10000);
|
||||
cpu.Interrupt = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void HardReset()
|
||||
{
|
||||
cpu.Reset();
|
||||
ram = new byte[0x8000];
|
||||
for(int i=0;i<0x8000;i++)
|
||||
ram[i] = 0xFF;
|
||||
cpu.RegisterPC = startPC;
|
||||
|
||||
cpu.IFF1 = false;
|
||||
cpu.IFF2 = false;
|
||||
cpu.InterruptMode = 2;
|
||||
|
||||
maskOn = false;
|
||||
romPageHighBit = 0;
|
||||
romPageLow3Bits = 0;
|
||||
keyboardMask = 0;
|
||||
|
||||
disp_mode = 0;
|
||||
disp_move = 0;
|
||||
disp_x = disp_y = 0;
|
||||
}
|
||||
|
||||
public int Frame
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
public bool DeterministicEmulation { get { return true; } set { } }
|
||||
|
||||
public byte[] SaveRam { get { return null; } }
|
||||
public bool SaveRamModified
|
||||
{
|
||||
get { return false; }
|
||||
set { }
|
||||
}
|
||||
|
||||
public void SaveStateText(TextWriter writer)
|
||||
{
|
||||
}
|
||||
|
||||
public void LoadStateText(TextReader reader)
|
||||
{
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter writer)
|
||||
{
|
||||
}
|
||||
|
||||
public void LoadStateBinary(BinaryReader reader)
|
||||
{
|
||||
}
|
||||
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,5 +17,6 @@ namespace BizHawk.MultiClient
|
|||
public static IController SMSControls;
|
||||
public static IController PCEControls;
|
||||
public static IController GenControls;
|
||||
public static IController TI83Controls;
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ using System.Windows.Forms;
|
|||
using BizHawk.Core;
|
||||
using BizHawk.Emulation.Consoles.Sega;
|
||||
using BizHawk.Emulation.Consoles.TurboGrafx;
|
||||
using BizHawk.Emulation.Consoles.Calculator;
|
||||
|
||||
namespace BizHawk.MultiClient
|
||||
{
|
||||
|
@ -151,6 +152,34 @@ namespace BizHawk.MultiClient
|
|||
genControls.BindMulti("P1 C", Global.Config.GenP1C);
|
||||
genControls.BindMulti("P1 Start", Global.Config.GenP1Start);
|
||||
Global.GenControls = genControls;
|
||||
|
||||
|
||||
var TI83Controls = new Controller(TI83.TI83Controller);
|
||||
TI83Controls.BindMulti("0", "D0"); //numpad 4,8,6,2 (up/down/left/right) dont work in slimdx!! wtf!!
|
||||
TI83Controls.BindMulti("1", "D1");
|
||||
TI83Controls.BindMulti("2", "D2");
|
||||
TI83Controls.BindMulti("3", "D3");
|
||||
TI83Controls.BindMulti("4", "D4");
|
||||
TI83Controls.BindMulti("5", "D5");
|
||||
TI83Controls.BindMulti("6", "D6");
|
||||
TI83Controls.BindMulti("7", "D7");
|
||||
TI83Controls.BindMulti("8", "D8");
|
||||
TI83Controls.BindMulti("9", "D9");
|
||||
TI83Controls.BindMulti("ON", "Space");
|
||||
TI83Controls.BindMulti("ENTER", "NumberPadEnter");
|
||||
TI83Controls.BindMulti("DOWN", "DownArrow");
|
||||
TI83Controls.BindMulti("LEFT", "LeftArrow");
|
||||
TI83Controls.BindMulti("RIGHT", "RightArrow");
|
||||
TI83Controls.BindMulti("UP", "UpArrow");
|
||||
TI83Controls.BindMulti("PLUS", "NumberPadPlus");
|
||||
TI83Controls.BindMulti("MINUS", "NumberPadMinus");
|
||||
TI83Controls.BindMulti("MULTIPLY", "NumberPadStar");
|
||||
TI83Controls.BindMulti("DIVIDE", "NumberPadSlash");
|
||||
TI83Controls.BindMulti("CLEAR", "Escape");
|
||||
TI83Controls.BindMulti("DOT", "NumberPadPeriod");
|
||||
|
||||
Global.TI83Controls = TI83Controls;
|
||||
|
||||
}
|
||||
|
||||
private static void FormDragEnter(object sender, DragEventArgs e)
|
||||
|
@ -219,6 +248,10 @@ namespace BizHawk.MultiClient
|
|||
Global.Emulator = new Genesis(false);//TODO
|
||||
Global.Emulator.Controller = Global.GenControls;
|
||||
break;
|
||||
case "TI83":
|
||||
Global.Emulator = new TI83();
|
||||
Global.Emulator.Controller = Global.TI83Controls;
|
||||
break;
|
||||
}
|
||||
|
||||
Global.Emulator.LoadGame(game);
|
||||
|
|
|
@ -2258,4 +2258,4 @@ D5C782F2 V Bonk's Adventure (bad dump) PCE
|
|||
B486A8ED Dai Makai Mura SGX
|
||||
1F041166 Madoo Granzort SGX
|
||||
|
||||
D4448D09BBFDE687C04F9E3310E023AB ti83_1.rom TI83
|
||||
D4448D09BBFDE687C04F9E3310E023AB ti83_1.rom TI83 initPC=6ce
|
||||
|
|
Loading…
Reference in New Issue