Vectrex: new display method, looks much better

This commit is contained in:
alyosha-tas 2020-04-18 15:42:10 -04:00
parent 6d699012a6
commit 5238d660cd
4 changed files with 294 additions and 23 deletions

View File

@ -162,6 +162,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
{
//Console.WriteLine(PB7_undriven + " " + !wrt_val.Bit(7));
ppu.ramp_sig = !wrt_val.Bit(7);
ppu.new_draw_line();
if (PB7_undriven && !wrt_val.Bit(7))
{
PB7_undriven = false;
@ -206,6 +207,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
{
ppu.y_vel = (byte)(portA_ret ^ 0x80);
}
ppu.new_draw_line();
}
}
@ -237,6 +240,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
}
ppu.x_vel = (byte)(portA_ret ^ 0x80);
ppu.new_draw_line();
int_fl &= 0xE7;
update_int_fl();
@ -281,8 +285,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
}
else
{
ppu.y_vel = (byte)(portA_ret ^ 0x80);
ppu.y_vel = (byte)(portA_ret ^ 0x80);
}
ppu.new_draw_line();
}
}
@ -314,6 +319,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
}
ppu.x_vel = (byte)(portA_ret ^ 0x80);
ppu.new_draw_line();
int_fl &= 0xFC;
update_int_fl();
@ -336,6 +342,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
{
PB7 = false;
ppu.ramp_sig = true;
ppu.new_draw_line();
}
t1_shot_go = true;
@ -399,6 +406,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
if ((value & 0xE0) == 0xC0) { ppu.blank_sig = true; }
else { ppu.blank_sig = false; }
ppu.new_draw_line();
break;
case 0xD:
// writing to flags does not clear bit 7 directly
@ -440,13 +449,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
}
else
{
if (sel1) { ppu.bright = portA_ret; }
else { ppu.y_vel = portA_ret; }
if (sel1) { ppu.bright = portA_ret; Console.WriteLine("brightness change?"); }
else { ppu.y_vel = portA_ret; ppu.new_draw_line(); }
}
}
else
{
ppu.x_vel = portA_ret;
ppu.new_draw_line();
}
int_fl &= 0xFC;
@ -470,7 +480,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
update_int_fl();
if (int_en.Bit(6)) { cpu.IRQPending = true; }
if (t1_ctrl.Bit(7)) { PB7 = !PB7; ppu.ramp_sig = !PB7; }
if (t1_ctrl.Bit(7)) { PB7 = !PB7; ppu.ramp_sig = !PB7; ppu.new_draw_line(); }
}
else
{
@ -481,7 +491,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
int_fl |= 0x40;
update_int_fl();
if (int_en.Bit(6)) { cpu.IRQPending = true; }
if (t1_ctrl.Bit(7)) { PB7 = true; ppu.ramp_sig = false; }
if (t1_ctrl.Bit(7)) { PB7 = true; ppu.ramp_sig = false; ppu.new_draw_line(); }
t1_shot_go = false;
}
@ -538,6 +548,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
else
{
ppu.blank_sig = !shift_reg.Bit(7 - shift_count);
ppu.new_draw_line();
shift_count++;
shift_reg_wait = 1;

View File

@ -16,6 +16,21 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
public static uint br = 0xFFFFFFFF;
// lines to draw in a frame and vairables to go to new line
public double[] draw_lines = new double[1024 * 4 * 4];
public uint[] line_brights = new uint[1024 * 3 * 4];
public bool[] line_vis = new bool[1024 * 4];
public double[] draw_lines_old_screen = new double[1024 * 4 * 4];
public uint[] line_brights_old_screen = new uint[1024 * 3 * 4];
public bool[] line_vis_old_screen = new bool[1024 * 4];
public int line_pointer_old_screen;
public int line_pointer;
public bool blank_old, zero_old;
public byte x_vel_old, y_vel_old;
public uint bright_int_1_old;
public void tick()
{
//Console.WriteLine(ramp_sig + " " + zero_sig + " " + blank_sig + " " + Core.cpu.TotalExecutedCycles + " " + (x_vel - 128.0) + " " + x_pos
@ -39,18 +54,16 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
if (x_pos < 2) { off_screen = true; if (x_pos < (2 - 256)) { x_pos = (2 - 256); } }
if (y_pos > 385) { off_screen = true; if (y_pos > (385 + 256)) { y_pos = (385 + 256); } }
if (y_pos < 2) { off_screen = true; if (y_pos < (2 - 256)) { y_pos = (2 - 256); } }
}
else if (zero_sig)
{
x_pos = 128 + 2;
y_pos = 192 + 2;
}
/*
if (!blank_sig && !off_screen)
{
Core._vidbuffer[(int)(Math.Round(x_pos) + 260 * Math.Round(y_pos))] |= (int)(br & bright_int_1);
Core._vidbuffer[(int)(Math.Round(x_pos) + 1 + 260 * Math.Round(y_pos))] |= (int)(br & bright_int_2);
@ -66,7 +79,223 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
Core._vidbuffer[(int)(Math.Round(x_pos) + 1 + 260 * (Math.Round(y_pos) - 1))] |= (int)(br & bright_int_3);
Core._vidbuffer[(int)(Math.Round(x_pos) - 1 + 260 * (Math.Round(y_pos) + 1))] |= (int)(br & bright_int_3);
Core._vidbuffer[(int)(Math.Round(x_pos) - 1 + 260 * (Math.Round(y_pos) - 1))] |= (int)(br & bright_int_3);
}
*/
}
public void draw_screen()
{
// screen is 2 times the internal size of the image
double start_x = 0;
double end_x = 0;
double start_y = 0;
double end_y = 0;
uint c_bright = 0;
for (int i = 0; i < line_pointer; i++)
{
if (line_vis[i] == true)
{
start_x = draw_lines[i * 4];
start_y = draw_lines[i * 4 + 1];
end_x = draw_lines[i * 4 + 2];
end_y = draw_lines[i * 4 + 3];
c_bright = line_brights[i * 3];
double steps = 0;
double max_x = Math.Abs(end_x - start_x);
double max_y = Math.Abs(end_y - start_y);
bool draw_this_line = true;
if ((start_x < 2) && (end_x < 2)) { draw_this_line = false; }
if ((start_y < 2) && (end_y < 2)) { draw_this_line = false; }
if ((start_x > 257) && (end_x > 257)) { draw_this_line = false; }
if ((start_y > 385) && (end_y > 385)) { draw_this_line = false; }
if (draw_this_line)
{
// truncate lines to only be on screen
if ((start_x >= 2) && (end_x < 2)) { max_x = start_x - 2; end_x = 2; }
if ((end_x >= 2) && (start_x < 2)) { max_x = end_x - 2; start_x = 2; }
if ((start_x <= 257) && (end_x > 257)) { max_x = 257 - start_x; end_x = 257; }
if ((end_x <= 257) && (start_x >= 257)) { max_x = 257 - end_x; start_x = 257; }
if ((start_y >= 2) && (end_y < 2)) { max_y = start_y - 2; end_y = 2; }
if ((end_y >= 2) && (start_y < 2)) { max_y = end_y - 2; start_y = 2; }
if ((start_y <= 385) && (end_y > 385)) { max_y = 385 - start_y; end_y = 257; }
if ((end_y <= 385) && (start_y >= 385)) { max_y = 385 - end_y; start_y = 385; }
// screen size is double internal size
start_x *= 2;
end_x *= 2;
start_y *= 2;
end_y *= 2;
max_x *= 2;
max_y *= 2;
steps = Math.Max(max_x, max_y) + 1;
double x_step = (end_x - start_x) / steps;
double y_step = (end_y - start_y) / steps;
for (int j = 0; j <= steps; j++)
{
Core._vidbuffer[(int)(Math.Round(start_x + x_step * j) + 260 * 2 * Math.Round(start_y + y_step * j))] |= (int)(br & c_bright);
// at minimum need to make 3 pixels thick to be represetnative of a real vectrex, add more for glow
Core._vidbuffer[(int)(Math.Round(start_x + x_step * j) + 1 + 260 * 2 * Math.Round(start_y + y_step * j))] |= (int)(br & c_bright);
Core._vidbuffer[(int)(Math.Round(start_x + x_step * j) - 1 + 260 * 2 * Math.Round(start_y + y_step * j))] |= (int)(br & c_bright);
Core._vidbuffer[(int)(Math.Round(start_x + x_step * j) + 260 * 2 * (Math.Round(start_y + y_step * j) + 1))] |= (int)(br & c_bright);
Core._vidbuffer[(int)(Math.Round(start_x + x_step * j) + 260 * 2 * (Math.Round(start_y + y_step * j) - 1))] |= (int)(br & c_bright);
}
}
}
}
// copy all the data to the old screen arrays to save it for loading states
for (int i = 0; i < line_pointer; i++)
{
draw_lines_old_screen[i * 4] = draw_lines[i * 4];
draw_lines_old_screen[i * 4 + 1] = draw_lines[i * 4 + 1];
draw_lines_old_screen[i * 4 + 2] = draw_lines[i * 4 + 2];
draw_lines_old_screen[i * 4 + 3] = draw_lines[i * 4 + 3];
line_brights_old_screen[i * 3] = line_brights[i * 3];
line_brights_old_screen[i * 3 + 1] = line_brights[i * 3 + 1];
line_brights_old_screen[i * 3 + 2] = line_brights[i * 3 + 2];
line_vis_old_screen[i] = line_vis[i];
}
line_pointer_old_screen = line_pointer;
// reset pointer back to zero but keep current starting point
draw_lines[0] = draw_lines[line_pointer * 4];
draw_lines[1] = draw_lines[line_pointer * 4 + 1];
line_vis[0] = line_vis[line_pointer];
line_brights[0] = line_brights[line_pointer * 3];
line_pointer = 0;
}
public void draw_old_screen()
{
// screen is 2 times the internal size of the image
double start_x = 0;
double end_x = 0;
double start_y = 0;
double end_y = 0;
uint c_bright = 0;
for (int i = 0; i < line_pointer_old_screen; i++)
{
if (line_vis_old_screen[i] == true)
{
start_x = draw_lines_old_screen[i * 4];
start_y = draw_lines_old_screen[i * 4 + 1];
end_x = draw_lines_old_screen[i * 4 + 2];
end_y = draw_lines_old_screen[i * 4 + 3];
c_bright = line_brights_old_screen[i * 3];
double steps = 0;
double max_x = Math.Abs(end_x - start_x);
double max_y = Math.Abs(end_y - start_y);
bool draw_this_line = true;
if ((start_x < 2) && (end_x < 2)) { draw_this_line = false; }
if ((start_y < 2) && (end_y < 2)) { draw_this_line = false; }
if ((start_x > 257) && (end_x > 257)) { draw_this_line = false; }
if ((start_y > 385) && (end_y > 385)) { draw_this_line = false; }
if (draw_this_line)
{
// truncate lines to only be on screen
if ((start_x >= 2) && (end_x < 2)) { max_x = start_x - 2; end_x = 2; }
if ((end_x >= 2) && (start_x < 2)) { max_x = end_x - 2; start_x = 2; }
if ((start_x <= 257) && (end_x > 257)) { max_x = 257 - start_x; end_x = 257; }
if ((end_x <= 257) && (start_x >= 257)) { max_x = 257 - end_x; start_x = 257; }
if ((start_y >= 2) && (end_y < 2)) { max_y = start_y - 2; end_y = 2; }
if ((end_y >= 2) && (start_y < 2)) { max_y = end_y - 2; start_y = 2; }
if ((start_y <= 385) && (end_y > 385)) { max_y = 385 - start_y; end_y = 257; }
if ((end_y <= 385) && (start_y >= 385)) { max_y = 385 - end_y; start_y = 385; }
// screen size is double internal size
start_x *= 2;
end_x *= 2;
start_y *= 2;
end_y *= 2;
max_x *= 2;
max_y *= 2;
steps = Math.Max(max_x, max_y) + 1;
double x_step = (end_x - start_x) / steps;
double y_step = (end_y - start_y) / steps;
for (int j = 0; j <= steps; j++)
{
Core._framebuffer[(int)(Math.Round(start_x + x_step * j) + 260 * 2 * Math.Round(start_y + y_step * j))] |= (int)(br & c_bright);
// at minimum need to make 3 pixels thick to be represetnative of a real vectrex, add more for glow
Core._framebuffer[(int)(Math.Round(start_x + x_step * j) + 1 + 260 * 2 * Math.Round(start_y + y_step * j))] |= (int)(br & c_bright);
Core._framebuffer[(int)(Math.Round(start_x + x_step * j) - 1 + 260 * 2 * Math.Round(start_y + y_step * j))] |= (int)(br & c_bright);
Core._framebuffer[(int)(Math.Round(start_x + x_step * j) + 260 * 2 * (Math.Round(start_y + y_step * j) + 1))] |= (int)(br & c_bright);
Core._framebuffer[(int)(Math.Round(start_x + x_step * j) + 260 * 2 * (Math.Round(start_y + y_step * j) - 1))] |= (int)(br & c_bright);
}
}
}
}
}
public void new_draw_line()
{
if (((ramp_sig && !zero_sig) && ((x_vel != x_vel_old) || (y_vel != y_vel_old))) ||
(blank_sig != blank_old) ||
(bright_int_1 != bright_int_1_old) ||
(zero_sig != zero_old))
{
draw_lines[line_pointer * 4 + 2] = x_pos;
draw_lines[line_pointer * 4 + 3] = y_pos;
line_pointer++;
draw_lines[line_pointer * 4] = x_pos;
draw_lines[line_pointer * 4 + 1] = y_pos;
line_brights[line_pointer * 3] = bright_int_1;
line_brights[line_pointer * 3 + 1] = bright_int_2;
line_brights[line_pointer * 3 + 2] = bright_int_3;
line_vis[line_pointer] = !blank_sig;
}
if (ramp_sig && !zero_sig)
{
x_vel_old = x_vel;
y_vel_old = y_vel;
}
zero_old = zero_sig;
blank_old = blank_sig;
bright_int_1_old = bright_int_1;
}
public void Reset()
@ -78,6 +307,21 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
vec_scale = x_vel = y_vel = bright = 0;
x_pos = 128 + 2;
y_pos = 192 + 2;
line_pointer = 0;
blank_old = zero_old = true;
x_vel_old = y_vel_old = 0;
bright_int_1_old = 0;
// initial line array values
draw_lines[line_pointer * 5] = x_pos;
draw_lines[line_pointer * 5 + 1] = y_pos;
line_brights[line_pointer * 3] = 0;
line_brights[line_pointer * 3 + 1] = 0;
line_brights[line_pointer * 3 + 2] = 0;
line_vis[line_pointer] = !blank_sig;
}
public void SyncState(Serializer ser)
@ -99,6 +343,21 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
ser.Sync(nameof(bright_int_1), ref bright_int_1);
ser.Sync(nameof(bright_int_2), ref bright_int_2);
ser.Sync(nameof(bright_int_3), ref bright_int_3);
ser.Sync(nameof(draw_lines), ref draw_lines, false);
ser.Sync(nameof(line_brights), ref line_brights, false);
ser.Sync(nameof(line_vis), ref line_vis, false);
ser.Sync(nameof(line_pointer), ref line_pointer);
ser.Sync(nameof(blank_old), ref blank_old);
ser.Sync(nameof(zero_old), ref zero_old);
ser.Sync(nameof(x_vel_old), ref x_vel_old);
ser.Sync(nameof(y_vel_old), ref y_vel_old);
ser.Sync(nameof(bright_int_1_old), ref bright_int_1_old);
ser.Sync(nameof(draw_lines_old_screen), ref draw_lines_old_screen, false);
ser.Sync(nameof(line_brights_old_screen), ref line_brights_old_screen, false);
ser.Sync(nameof(line_vis_old_screen), ref line_vis_old_screen, false);
ser.Sync(nameof(line_pointer_old_screen), ref line_pointer_old_screen);
}
}
}

View File

@ -128,6 +128,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
public void get_video_frame()
{
ppu.draw_screen();
for (int i = 0; i < _vidbuffer.Length; i++)
{
_framebuffer[i] = _vidbuffer[i];
@ -136,10 +138,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
}
public int VirtualWidth => 256 + 4;
public int VirtualHeight => 384 + 4;
public int BufferWidth => 256 + 4;
public int BufferHeight => 384 + 4;
public int VirtualWidth => (256 + 4) * 2;
public int VirtualHeight => (384 + 4) * 2;
public int BufferWidth => (256 + 4) * 2;
public int BufferHeight => (384 + 4) * 2;
public int BackgroundColor => unchecked((int)0xFF000000);
public int VsyncNumerator => _frameHz;
public int VsyncDenominator => 1;

View File

@ -7,14 +7,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
{
private void SyncState(Serializer ser)
{
byte[] core = null;
if (ser.IsWriter)
{
var ms = new MemoryStream();
ms.Close();
core = ms.ToArray();
}
ser.BeginSection("VECTREX");
cpu.SyncState(ser);
@ -77,8 +69,15 @@ namespace BizHawk.Emulation.Cores.Consoles.Vectrex
ser.Sync(nameof(joy2_LR), ref joy2_LR);
ser.Sync(nameof(joy2_UD), ref joy2_UD);
ser.Sync(nameof(_framebuffer), ref _framebuffer, false);
ser.Sync(nameof(_vidbuffer), ref _vidbuffer, false);
// referesh the screen buffer
if (ser.IsReader)
{
for (int i = 0; i < _framebuffer.Length; i++)
{
_framebuffer[i] = 0;
}
ppu.draw_old_screen();
}
ser.EndSection();
}