diff --git a/css/ui.css b/css/ui.css index 4507c00a..0c38b524 100644 --- a/css/ui.css +++ b/css/ui.css @@ -20,16 +20,18 @@ } .tooltipbox .tooltiptext { visibility: hidden; - width: 120px; - background-color: black; + width: 500px; + background-color: #660000; color: #fff; text-align: center; border-radius: 6px; padding: 5px 0; - /* Position the tooltip */ position: absolute; z-index: 10; + /*
tag wrap */ + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ } .tooltipbox:hover .tooltiptext { visibility: visible; diff --git a/presets/verilog/ball_paddle.v b/presets/verilog/ball_paddle.v new file mode 100644 index 00000000..31c14788 --- /dev/null +++ b/presets/verilog/ball_paddle.v @@ -0,0 +1,106 @@ +`include "hvsync_generator.v" + +module ball_paddle_top(clk, hpaddle, hsync, vsync, rgb); + + input clk; + input hpaddle; + output hsync, vsync; + output [2:0] rgb; + wire display_on; + wire [8:0] hpos; + wire [8:0] vpos; + + reg [8:0] paddle_pos; + + reg [8:0] ball_x = 128; + reg [8:0] ball_y = 128; + reg signed [1:0] ball_vel_x = 0; + reg ball_vel_y = BALL_VEL_DOWN; + + localparam BALL_VEL_DOWN = 1; + localparam BALL_VEL_UP = 0; + + localparam PADDLE_WIDTH = 31; + localparam BALL_SIZE = 8; + + hvsync_generator hvsync_gen( + .clk(clk), + .hsync(hsync), + .vsync(vsync), + .display_on(display_on), + .hpos(hpos), + .vpos(vpos) + ); + + // TODO: only works when paddle at bottom of screen! + always @(posedge hsync) + if (!hpaddle) + paddle_pos <= vpos; + + // TODO: unsigned compare doesn't work in JS + wire [8:0] paddle_rel_x = ((hpos-paddle_pos) & 9'h1ff); + wire paddle_gfx = paddle_rel_x < PADDLE_WIDTH; + + wire [8:0] ball_rel_x = (hpos-ball_x); + wire [8:0] ball_rel_y = (vpos-ball_y); + + wire ball_gfx = ball_rel_x < BALL_SIZE + && ball_rel_y < BALL_SIZE; + + wire [5:0] hcell = hpos[8:3]; + wire [5:0] vcell = vpos[8:3]; + wire lr_border = hcell==0 || hcell==31; + + wire main_gfx; + + always @(posedge clk) + case (vpos[8:3]) + 0: main_gfx = 1; + 28: main_gfx = paddle_gfx | lr_border; + default: main_gfx = lr_border; + endcase; + + wire ball_pixel_collide = main_gfx & ball_gfx; + + /* verilator lint_off MULTIDRIVEN */ + reg [4:0] ball_collide_bits = 0; + /* verilator lint_on MULTIDRIVEN */ + + always @(posedge clk) + if (ball_pixel_collide) begin + if (paddle_gfx) begin // did we collide w/ paddle? + ball_collide_bits[4] <= 1; + end else begin // collided with playfield + if (!ball_rel_x[2] & !ball_rel_y[2]) ball_collide_bits[0] <= 1; + if (ball_rel_x[2] & !ball_rel_y[2]) ball_collide_bits[1] <= 1; + if (!ball_rel_x[2] & ball_rel_y[2]) ball_collide_bits[2] <= 1; + if (ball_rel_x[2] & ball_rel_y[2]) ball_collide_bits[3] <= 1; + end + end + + always @(posedge vsync) + begin + if (ball_collide_bits[4]) begin // collided with paddle? + reg signed [1:0] ball_paddle_dx = ball_x[6:5] - paddle_pos[6:5]; + ball_vel_y <= BALL_VEL_UP; // paddle top + ball_vel_x <= ball_vel_x + ball_paddle_dx; + end else casez (ball_collide_bits[3:0]) // collided with playfield + 0: ; + 4'b01?1: if (ball_vel_x<0) ball_vel_x <= -ball_vel_x-1; // left + 4'b101?: if (ball_vel_x>=0) ball_vel_x <= -ball_vel_x-1; // right + 4'b1100: ball_vel_y <= BALL_VEL_UP; + 4'b0011: ball_vel_y <= BALL_VEL_DOWN; + endcase; + ball_collide_bits <= 0; + ball_x <= ball_x + 9'(ball_vel_x) + 9'(ball_vel_x>=0); // TODO: signed? + ball_y <= ball_y + (ball_vel_y==BALL_VEL_DOWN?1:-1); + end; + + wire grid_gfx = (((hpos&7)==0) || ((vpos&7)==0)); + + wire r = display_on && (grid_gfx | ball_gfx); + wire g = display_on && (main_gfx | ball_gfx); + wire b = display_on && ball_gfx; + assign rgb = {b,g,r}; + +endmodule diff --git a/presets/verilog/hvsync_generator.v b/presets/verilog/hvsync_generator.v index 99ec0e00..3415412d 100644 --- a/presets/verilog/hvsync_generator.v +++ b/presets/verilog/hvsync_generator.v @@ -1,12 +1,12 @@ module hvsync_generator( - clk, hsync, vsync, inDisplayArea, CounterX, CounterY); + clk, hsync, vsync, display_on, hpos, vpos); input clk; output hsync, vsync; - output inDisplayArea; - output [8:0] CounterX; - output [8:0] CounterY; + output reg display_on; + output reg [8:0] hpos; + output reg [8:0] vpos; // constant declarations for VGA sync parameters localparam H_DISPLAY = 256; // horizontal display area @@ -25,35 +25,32 @@ module hvsync_generator( localparam START_V_RETRACE = V_DISPLAY + V_B_BORDER; localparam END_V_RETRACE = V_DISPLAY + V_B_BORDER + V_RETRACE - 1; - reg [8:0] CounterX; - reg [8:0] CounterY; - wire CounterXmaxed = (CounterX==H_MAX); - wire CounterYmaxed = (CounterY==V_MAX); + wire hmaxxed = (hpos==H_MAX); + wire vmaxxed = (vpos==V_MAX); always @(posedge clk) - if(CounterXmaxed) - CounterX <= 0; + if(hmaxxed) + hpos <= 0; else - CounterX <= CounterX + 1; + hpos <= hpos + 1; always @(posedge clk) - if(CounterXmaxed) - if (!CounterYmaxed) - CounterY <= CounterY + 1; + if(hmaxxed) + if (!vmaxxed) + vpos <= vpos + 1; else - CounterY <= 0; + vpos <= 0; reg vga_HS, vga_VS; always @(posedge clk) begin - vga_HS <= (CounterX>=280 && CounterX<288); // change this value to move the display horizontally - vga_VS <= (CounterY==START_V_RETRACE); // change this value to move the display vertically + vga_HS <= (hpos>=280 && hpos<288); // change this value to move the display horizontally + vga_VS <= (vpos==START_V_RETRACE); // change this value to move the display vertically end - reg inDisplayArea; always @(posedge clk) begin - inDisplayArea <= (CounterXVL_EXTENDS_II(x,lbits,rhs); } + + var VL_LTES_III = this.VL_LTES_III = function(x,lbits,y,lhs,rhs) { + return VL_EXTENDS_II(x,lbits,lhs) <= VL_EXTENDS_II(x,lbits,rhs); } + + var VL_GTES_III = this.VL_GTES_III = function(x,lbits,y,lhs,rhs) { + return VL_EXTENDS_II(x,lbits,lhs) >= VL_EXTENDS_II(x,lbits,rhs); } + +// + function VerilatorBase() { - this.VL_RAND_RESET_I = function(bits) { return Math.floor(Math.random() * (1< maxv) ? maxv : v; + } + this.start = function() { // TODO video = new RasterVideo(mainElement,videoWidth,videoHeight); video.create(); setKeyboardFromMap(video, switches, VERILOG_KEYCODE_MAP); $(video.canvas).mousemove(function(e) { - paddle_x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width()); - paddle_y = Math.floor(e.offsetY * video.canvas.height / $(video.canvas).height() - 20); + paddle_x = clamp(4,255,Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 20)); + paddle_y = clamp(4,255,Math.floor(e.offsetY * video.canvas.height / $(video.canvas).height() - 20)); }); audio = new SampleAudio(AUDIO_FREQ); idata = video.getFrameData(); diff --git a/src/ui.js b/src/ui.js index aff27b10..b609880a 100644 --- a/src/ui.js +++ b/src/ui.js @@ -172,7 +172,7 @@ function scrollProfileView(_ed) { } function newEditor(mode) { - var isAsm = (mode != 'text/x-csrc'); + var isAsm = mode=='6502' || mode =='z80'; editor = CodeMirror(document.getElementById('editor'), { theme: 'mbo', lineNumbers: true,