Skip to content

Commit

Permalink
[NES] Add NTSC RGBS mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
sorgelig committed Jan 6, 2016
1 parent 6327590 commit 3200ed2
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 79 deletions.
76 changes: 28 additions & 48 deletions cores/nes/mist/NES_mist.v
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,15 @@ wire [1:0] switches;
// it to control the menu on the OSD
parameter CONF_STR = {
"NES;NES;",
"O1,HQ2X,OFF,ON;",
"O1,HQ2X(VGA-Only),OFF,ON;",
"T2,Start;",
"T3,Select;",
"T4,Reset;"
};

parameter CONF_STR_LEN = 8+15+9+10+9;
parameter CONF_STR_LEN = 8+25+9+10+9;
wire [7:0] status;
wire scandoubler_disable;

user_io #(.STRLEN(CONF_STR_LEN)) user_io(
.conf_str ( CONF_STR ),
Expand All @@ -152,6 +153,7 @@ user_io #(.STRLEN(CONF_STR_LEN)) user_io(

.SWITCHES (switches ),
.BUTTONS (buttons ),
.scandoubler_disable(scandoubler_disable),

.JOY0 (joyA ),
.JOY1 (joyB ),
Expand All @@ -163,12 +165,6 @@ user_io #(.STRLEN(CONF_STR_LEN)) user_io(
.ps2_clk ( )
);

wire [4:0] nes_r;
wire [4:0] nes_g;
wire [4:0] nes_b;
wire nes_hs;
wire nes_vs;

// if "Start" or "Select" are selected from the menu keep them set for half a second
// status 2 and 3 are start and select from the OSD
reg [23:0] select_cnt;
Expand All @@ -193,29 +189,7 @@ wire [7:0] nes_joy_A = { joyB[0], joyB[1], joyB[2], joyB[3],
joyB[7] | strt, joyB[6] | sel, joyB[5], joyB[4] };
wire [7:0] nes_joy_B = { joyA[0], joyA[1], joyA[2], joyA[3],
joyA[7], joyA[6], joyA[5], joyA[4] };

osd #(0,0,4) osd (
.pclk ( clk ),

// spi for OSD
.sdi ( SPI_DI ),
.sck ( SPI_SCK ),
.ss ( SPI_SS3 ),

.red_in ( { nes_r, 1'b0} ),
.green_in ( { nes_g, 1'b0} ),
.blue_in ( { nes_b, 1'b0} ),
.hs_in ( nes_hs ),
.vs_in ( nes_vs ),

.red_out ( VGA_R ),
.green_out ( VGA_G ),
.blue_out ( VGA_B ),
.hs_out ( VGA_HS ),
.vs_out ( VGA_VS )
);


wire clock_locked;
wire clk85;
clk clock_21mhz(.inclk0(CLOCK_27[0]), .c0(clk85), .c1(SDRAM_CLK), .locked(clock_locked));
Expand Down Expand Up @@ -250,10 +224,6 @@ osd #(0,0,4) osd (
wire loader_clk;
reg [7:0] loader_btn, loader_btn_2;

// NES Palette -> RGB332 conversion
reg [14:0] pallut[0:63];
initial $readmemh("../src/nes_palette.txt", pallut);

wire [8:0] cycle;
wire [8:0] scanline;
wire [15:0] sample;
Expand Down Expand Up @@ -385,20 +355,30 @@ data_io data_io (
.d ( loader_input )
);

wire [14:0] doubler_pixel;
wire doubler_sync;
wire [9:0] vga_hcounter, doubler_x;
wire [9:0] vga_vcounter;

VgaDriver vga(clk, nes_hs, nes_vs, nes_r, nes_g, nes_b, vga_hcounter, vga_vcounter, doubler_x, doubler_pixel, doubler_sync, 1'b0);

wire [14:0] pixel_in = pallut[color];
Hq2x hq2x(clk, pixel_in, !status[1], // enabled
scanline[8], // reset_frame
(cycle[8:3] == 42), // reset_line
doubler_x, // 0-511 for line 1, or 512-1023 for line 2.
doubler_sync, // new frame has just started
doubler_pixel); // pixel is outputted
wire nes_hs;
wire nes_vs;

VgaDriver vga(
.clk(clk),
.sdi(SPI_DI),
.sck(SPI_SCK),
.ss(SPI_SS3),
.color(color),
.sync_frame(scanline[8]),
.sync_line((cycle[8:3] == 42)),
.mode(scandoubler_disable),
.vga_smooth(!status[1]),
.border(1'b0),

.vga_h(nes_hs),
.vga_v(nes_vs),
.VGA_R(VGA_R),
.VGA_G(VGA_G),
.VGA_B(VGA_B)
);

assign VGA_HS = scandoubler_disable ? ~(nes_hs ^ nes_vs) : nes_hs;
assign VGA_VS = scandoubler_disable ? 1'b1 : nes_vs;

assign AUDIO_R = audio;
assign AUDIO_L = audio;
Expand Down
6 changes: 4 additions & 2 deletions cores/nes/mist/user_io.v
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module user_io #(parameter STRLEN=0) (
output [7:0] JOY1,
output [1:0] BUTTONS,
output [1:0] SWITCHES,
output scandoubler_disable,

output reg [7:0] status,

Expand All @@ -48,12 +49,13 @@ reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
reg [7:0] byte_cnt; // counts bytes
reg [7:0] joystick0;
reg [7:0] joystick1;
reg [3:0] but_sw;
reg [4:0] but_sw;

assign JOY0 = joystick0;
assign JOY1 = joystick1;
assign BUTTONS = but_sw[1:0];
assign SWITCHES = but_sw[3:2];
assign scandoubler_disable = but_sw[4];

// this variant of user_io is for 8 bit cores (type == a4) only
wire [7:0] core_type = 8'ha4;
Expand Down Expand Up @@ -164,7 +166,7 @@ always@(posedge SPI_CLK or posedge SPI_SS_IO) begin

if(byte_cnt != 0) begin
if(cmd == 8'h01)
but_sw <= { sbuf[2:0], SPI_MOSI };
but_sw <= { sbuf[3:0], SPI_MOSI };

if(cmd == 8'h02)
joystick0 <= { sbuf, SPI_MOSI };
Expand Down
107 changes: 78 additions & 29 deletions cores/nes/src/vga.v
Original file line number Diff line number Diff line change
@@ -1,47 +1,96 @@
// Copyright (c) 2012-2013 Ludvig Strigeus
// This program is GPL Licensed. See COPYING for the full license.

module VgaDriver(input clk,
output reg vga_h, output reg vga_v,
output reg [4:0] vga_r, output reg[4:0] vga_g, output reg[4:0] vga_b,
output [9:0] vga_hcounter,
output [9:0] vga_vcounter,
output [9:0] next_pixel_x, // The pixel we need NEXT cycle.
input [14:0] pixel, // Pixel for current cycle.
input sync,
input border);
module VgaDriver(
input clk,
input [5:0] color, // Pixel for current cycle.
input sync_frame,
input sync_line,
input mode,
input vga_smooth,
input border,

input sck,
input ss,
input sdi,

output reg vga_h,
output reg vga_v,
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B
);

// NES Palette -> RGB555 conversion
reg [15:0] pallut[0:63];
initial $readmemh("nes_palette.txt", pallut);
wire [14:0] pixel = pallut[color][14:0];

// Horizontal and vertical counters
reg [9:0] h, v;
wire hpicture = (h < 512); // 512 lines of picture
wire hsync_on = (h == 512 + 23 + 35); // HSync ON, 23+35 pixels front porch
wire hsync_off = (h == 512 + 23 + 35 + 82); // Hsync off, 82 pixels sync
wire hpicture = (h < 512); // 512 lines of picture
wire hsync_on = (h == 512 + 23 + (mode ? 18 : 35)); // HSync ON, 23+35 pixels front porch
wire hsync_off = (h == 512 + 23 + (mode ? 18 : 35) + 82); // Hsync off, 82 pixels sync
wire hend = (h == 681); // End of line, 682 pixels.

wire vpicture = (v < 480); // 480 lines of picture
wire vsync_on = hsync_on && (v == 480 + 10); // Vsync ON, 10 lines front porch.
wire vsync_off = hsync_on && (v == 480 + 12); // Vsync OFF, 2 lines sync signal
wire vend = (v == 523); // End of picture, 524 lines. (Should really be 525 according to NTSC spec)
wire vpicture = (v < (480 >> mode)); // 480 lines of picture
wire vsync_on = hsync_on && (v == (mode ? 240 + 5 : 480 + 10)); // Vsync ON, 10 lines front porch.
wire vsync_off = hsync_on && (v == (mode ? 240 + 14 : 480 + 12)); // Vsync OFF, 2 lines sync signal
wire vend = (v == (523 >> mode)); // End of picture, 524 lines. (Should really be 525 according to NTSC spec)
wire inpicture = hpicture && vpicture;
assign vga_hcounter = h;
assign vga_vcounter = v;
wire [9:0] new_h = (hend || sync) ? 0 : h + 1;
assign next_pixel_x = {sync ? 1'b0 : hend ? !v[0] : v[0], new_h[8:0]};
wire [9:0] new_h = (hend || (mode ? sync_frame : doubler_sync)) ? 10'd0 : h + 10'd1;

wire [14:0] doubler_pixel;
wire doubler_sync;

Hq2x hq2x(clk, pixel, vga_smooth, // enabled
sync_frame, // reset_frame
sync_line, // reset_line
{doubler_sync ? 1'b0 : hend ? !v[0] : v[0], new_h[8:0]}, // 0-511 for line 1, or 512-1023 for line 2.
doubler_sync, // new frame has just started
doubler_pixel); // pixel is outputted

reg clk2 = 1'b0;
always @(posedge clk) clk2 <= ~clk2;
wire clkv = mode ? clk2 : clk;

osd #(10'd0,10'd0,3'd4) osd (
.pclk(clkv),

.sck(sck),
.sdi(sdi),
.ss(ss),

.red_in ({vga_r, 1'b0}),
.green_in({vga_g, 1'b0}),
.blue_in ({vga_b, 1'b0}),
.hs_in(vga_h),
.vs_in(vga_v),

.red_out(VGA_R),
.green_out(VGA_G),
.blue_out(VGA_B)
);

reg [4:0] vga_r;
reg [4:0] vga_g;
reg [4:0] vga_b;

always @(posedge clk) begin
always @(posedge clkv) begin
h <= new_h;
if (sync) begin
if(mode ? sync_frame : doubler_sync) begin
vga_v <= 1;
vga_h <= 1;
v <= 0;
end else begin
vga_h <= hsync_on ? 0 : hsync_off ? 1 : vga_h;
vga_h <= hsync_on ? 1'b0 : hsync_off ? 1'b1 : vga_h;
if (hend)
v <= vend ? 0 : v + 1;
vga_v <= vsync_on ? 0 : vsync_off ? 1 : vga_v;
vga_r <= pixel[4:0];
vga_g <= pixel[9:5];
vga_b <= pixel[14:10];
if (border && (h == 0 || h == 511 || v == 0 || v == 479)) begin
v <= vend ? 10'd0 : v + 10'd1;
vga_v <= vsync_on ? 1'b0 : vsync_off ? 1'b1 : vga_v;
vga_r <= mode ? pixel[4:0] : doubler_pixel[4:0];
vga_g <= mode ? pixel[9:5] : doubler_pixel[9:5];
vga_b <= mode ? pixel[14:10] : doubler_pixel[14:10];
if (border && (h == 0 || h == 511 || v == 0 || v == (479 >> mode))) begin
vga_r <= 4'b1111;
vga_g <= 4'b1111;
vga_b <= 4'b1111;
Expand Down

0 comments on commit 3200ed2

Please sign in to comment.