updated presets; verilog code dup detect; need to handle local/ include files somehow

This commit is contained in:
Steven Hugg 2018-07-31 14:41:27 -04:00
parent 94a932c08d
commit 2dbc60aa2e
16 changed files with 257 additions and 143 deletions

@ -1 +1 @@
Subproject commit ebf81921f80024e3e94c7a8e1235ab59464fa5ef Subproject commit 4334727f0e07acd4541b0a7b8f81a5984cd4aafe

View File

@ -34,9 +34,10 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<nav class="navbar navbar-inverse navbar-fixed-top"> <nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container"> <div class="container">
<div class="navbar-header"> <div class="navbar-header">
<a class="navbar-brand" href="https://twitter.com/8bitworkshop">@8bitworkshop</a> <span class="navbar-brand"><a target="_new" href="https://twitter.com/8bitworkshop" class="twitter-follow-button" data-show-count="false">Follow @8bitworkshop</a></span>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<a class="navbar-brand" href="./blog/">Blog</a> <a class="navbar-brand" href="./blog/">Blog</a>
<a class="navbar-brand" href="https://www.amazon.com/default/e/B01N7J10NF/ref=dp_byline_cont_pop_book_1">Books</a> <a class="navbar-brand" href="https://www.amazon.com/default/e/B01N7J10NF/ref=dp_byline_cont_pop_book_1" target="_blank" onclick="ga('send', 'event', 'books', 'click');">Books</a>
</div> </div>
<div id="navbar" class="hidden-sm hidden-xs"> <div id="navbar" class="hidden-sm hidden-xs">
<form class="navbar-form navbar-right"> <form class="navbar-form navbar-right">
@ -80,11 +81,12 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
We've got debugging tools too; single step through your code and use our CPU Cycle Analyzer to We've got debugging tools too; single step through your code and use our CPU Cycle Analyzer to
develop that perfect Stella kernel. develop that perfect Stella kernel.
</p> </p>
<img class="img-responsive" src="images/atarivcs.jpg">
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<h2>Arcade Games</h2> <h2>Arcade Games</h2>
<p> <p>
You can develop your own games on classic arcade game hardware, using our in-browser C compiler. You can develop your own games on classic arcade game hardware, using our in-browser C compiler targeting the Z80 CPU.
Platforms include Platforms include
<a href="redir.html?platform=vicdual">VIC Dual</a>, <a href="redir.html?platform=vicdual">VIC Dual</a>,
<a href="redir.html?platform=mw8080bw">Midway 8080</a>, <a href="redir.html?platform=mw8080bw">Midway 8080</a>,
@ -92,8 +94,54 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<a href="redir.html?platform=vector-z80color">Atari Vector</a>, <a href="redir.html?platform=vector-z80color">Atari Vector</a>,
and and
<a href="redir.html?platform=williams-z80">Williams</a>. <a href="redir.html?platform=williams-z80">Williams</a>.
<img class="img-responsive" src="images/arcadegames.jpg">
</p> </p>
</div> </div>
<div class="col-md-4">
<p>
We're always adding new things here, so subscribe to our mailing list for updates!
</p>
<style> .gumroad-follow-form-embed { zoom: 1; } .gumroad-follow-form-embed:before, .gumroad-follow-form-embed:after { display: table; line-height: 0; content: ""; } .gumroad-follow-form-embed:after { clear: both; } .gumroad-follow-form-embed * { margin: 0; border: 0; padding: 0; outline: 0; box-sizing: border-box !important; float: left !important; } .gumroad-follow-form-embed input { border-radius: 4px; border-top-right-radius: 0; border-bottom-right-radius: 0; font-family: -apple-system, ".SFNSDisplay-Regular", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 15px; line-height: 20px; background: #fff; border: 1px solid #ddd; border-right: 0; color: #aaa; padding: 10px; box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.02); background-position: top right; background-repeat: no-repeat; text-rendering: optimizeLegibility; font-smoothing: antialiased; -webkit-appearance: none; -moz-appearance: caret; width: 65% !important; height: 40px !important; } .gumroad-follow-form-embed button { border-radius: 4px; border-top-left-radius: 0; border-bottom-left-radius: 0; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.12); -webkit-transition: all .05s ease-in-out; transition: all .05s ease-in-out; display: inline-block; padding: 11px 15px 12px; cursor: pointer; color: #fff; font-size: 15px; line-height: 100%; font-family: -apple-system, ".SFNSDisplay-Regular", "Helvetica Neue", Helvetica, Arial, sans-serif; background: #36a9ae; border: 1px solid #31989d; filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#5ccfd4, endColorstr=#329ca1, GradientType=0)"; background: -webkit-linear-gradient(#5ccfd4, #329ca1); background: linear-gradient(to bottom, #5ccfd4, #329ca1); height: 40px !important; width: 35% !important; } </style> <form action="https://gumroad.com/follow_from_embed_form" class="form gumroad-follow-form-embed" method="post"> <input name="seller_id" type="hidden" value="1507538753888"> <input name="email" placeholder="Your email address" type="email"> <button data-custom-highlight-color="" type="submit">Subscribe</button> </form>
<p></p>
<!-- Begin MailChimp Signup Form -->
<!--
<link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css">
<style type="text/css">
#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
/* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
</style>
<div id="mc_embed_signup">
<form action="https://8bitworkshop.us19.list-manage.com/subscribe/post?u=819ee5274c8c9c1afe2005023&amp;id=75411a270f" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
<div id="mc_embed_signup_scroll">
<h2>We're always adding new things here, so subscribe to our mailing list for updates!</h2>
<div class="indicates-required"><span class="asterisk">*</span> indicates required</div>
<div class="mc-field-group">
<label for="mce-EMAIL">Email Address <span class="asterisk">*</span>
</label>
<input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL">
</div>
<div class="mc-field-group">
<label for="mce-FNAME">First Name (optional)</label>
<input type="text" value="" name="FNAME" class="" id="mce-FNAME">
</div>
<div class="mc-field-group">
<label for="mce-LNAME">Last Name (optional)</label>
<input type="text" value="" name="LNAME" class="" id="mce-LNAME">
</div>
<div id="mce-responses" class="clear">
<div class="response" id="mce-error-response" style="display:none"></div>
<div class="response" id="mce-success-response" style="display:none"></div>
</div>
<div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_819ee5274c8c9c1afe2005023_75411a270f" tabindex="-1" value=""></div>
<div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
</div>
</form>
</div>
<script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script><script type='text/javascript'>(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';fnames[2]='LNAME';ftypes[2]='text';fnames[3]='ADDRESS';ftypes[3]='address';fnames[4]='PHONE';ftypes[4]='phone';}(jQuery));var $mcj = jQuery.noConflict(true);</script>
-->
<!--End mc_embed_signup-->
</div>
<!-- <!--
<div class="col-md-4"> <div class="col-md-4">
<h2>Hardware Design</h2> <h2>Hardware Design</h2>
@ -113,12 +161,12 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-md-3">
<a target="_blank" href="https://www.amazon.com/gp/product/1541021304/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1541021304&linkCode=as2&tag=pzp-20&linkId=c149f6365c0a676065eb6d7c5f8dd6ae"> <a target="_blank" href="https://www.amazon.com/gp/product/1541021304/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1541021304&linkCode=as2&tag=pzp-20&linkId=c149f6365c0a676065eb6d7c5f8dd6ae" onclick="ga('send', 'event', 'books', 'click', 'vcs');">
<img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=US&ASIN=1541021304&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=pzp-20" ></a> <img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=US&ASIN=1541021304&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=pzp-20" ></a>
<img src="//ir-na.amazon-adsystem.com/e/ir?t=pzp-20&l=am2&o=1&a=1541021304" /> <img src="//ir-na.amazon-adsystem.com/e/ir?t=pzp-20&l=am2&o=1&a=1541021304" />
</div> </div>
<div class="col-md-8"> <div class="col-md-8">
<a target="_blank" href="https://www.amazon.com/gp/product/1541021304/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1541021304&linkCode=as2&tag=pzp-20&linkId=c149f6365c0a676065eb6d7c5f8dd6ae"> <a target="_blank" href="https://www.amazon.com/gp/product/1541021304/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1541021304&linkCode=as2&tag=pzp-20&linkId=c149f6365c0a676065eb6d7c5f8dd6ae" onclick="ga('send', 'event', 'books', 'click', 'vcs');">
<h3>Making Games For The Atari 2600</h3> <h3>Making Games For The Atari 2600</h3>
</a> </a>
<p>The Atari 2600 was released in 1977, and now there's finally a book about how to write games for it! You'll learn about the 6502 CPU, NTSC frames, scanlines, cycle counting, players, missiles, collisions, procedural generation, pseudo-3D, and more. While using the manual, take advantage of our Web-based IDE to write 6502 assembly code, and see your code run instantly in the browser. We'll cover the same programming tricks that master programmers used to make classic games. Create your own graphics and sound, and share your games with friends!</p> <p>The Atari 2600 was released in 1977, and now there's finally a book about how to write games for it! You'll learn about the 6502 CPU, NTSC frames, scanlines, cycle counting, players, missiles, collisions, procedural generation, pseudo-3D, and more. While using the manual, take advantage of our Web-based IDE to write 6502 assembly code, and see your code run instantly in the browser. We'll cover the same programming tricks that master programmers used to make classic games. Create your own graphics and sound, and share your games with friends!</p>
@ -126,18 +174,31 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-md-3">
<a target="_blank" href="https://www.amazon.com/gp/product/1545484759/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1545484759&linkCode=as2&tag=pzp-20&linkId=2f3c42111bffe3466830939fff4053fc"> <a target="_blank" href="https://www.amazon.com/gp/product/1545484759/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1545484759&linkCode=as2&tag=pzp-20&linkId=2f3c42111bffe3466830939fff4053fc" onclick="ga('send', 'event', 'books', 'click', 'arcade');">
<img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=US&ASIN=1545484759&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=pzp-20" ></a> <img border="0" src="//ws-na.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=US&ASIN=1545484759&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=pzp-20" ></a>
<img src="//ir-na.amazon-adsystem.com/e/ir?t=pzp-20&l=am2&o=1&a=1545484759" /> <img src="//ir-na.amazon-adsystem.com/e/ir?t=pzp-20&l=am2&o=1&a=1545484759" />
</div> </div>
<div class="col-md-8"> <div class="col-md-8">
<a target="_blank" href="https://www.amazon.com/gp/product/1545484759/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1545484759&linkCode=as2&tag=pzp-20&linkId=2f3c42111bffe3466830939fff4053fc"> <a target="_blank" href="https://www.amazon.com/gp/product/1545484759/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1545484759&linkCode=as2&tag=pzp-20&linkId=2f3c42111bffe3466830939fff4053fc" onclick="ga('send', 'event', 'books', 'click', 'arcade');">
<h3>Making 8-Bit Arcade Games in C</h3> <h3>Making 8-Bit Arcade Games in C</h3>
</a> </a>
<p>With this book, you'll learn all about the hardware of Golden Age 8-bit arcade games produced in the late 1970s to early 1980s. We'll learn how to use the C programming language to write code for the Z80 CPU. The following arcade platforms are covered: * Midway 8080 (Space Invaders) * VIC Dual (Carnival) * Galaxian/Scramble (Namco) * Atari Color Vector * Williams (Defender, Robotron) We'll describe how to create video and sound for each platform. Use the online 8bitworkshop IDE to compile your C programs and play them right in the browser!</p> <p>With this book, you'll learn all about the hardware of Golden Age 8-bit arcade games produced in the late 1970s to early 1980s. We'll learn how to use the C programming language to write code for the Z80 CPU. The following arcade platforms are covered: * Midway 8080 (Space Invaders) * VIC Dual (Carnival) * Galaxian/Scramble (Namco) * Atari Color Vector * Williams (Defender, Robotron) We'll describe how to create video and sound for each platform. Use the online 8bitworkshop IDE to compile your C programs and play them right in the browser!</p>
</div> </div>
</div> </div>
</div> </div>
<div class="container">
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6">
</div>
<div class="col-md-3">
</div>
</div>
</div>
<hr> <hr>

View File

@ -48,6 +48,9 @@ TODO:
- compile stuck when errors unchanged - compile stuck when errors unchanged
- sound mute? - sound mute?
- $error updates source editor - $error updates source editor
- Revert loads cached files?
- Verilog compile spins forever?
- how to revert included files?
WEB WORKER FORMAT WEB WORKER FORMAT

View File

@ -10,16 +10,18 @@ module ball_absolute_top(clk, reset, hsync, vsync, rgb);
wire [8:0] hpos; wire [8:0] hpos;
wire [8:0] vpos; wire [8:0] vpos;
reg [8:0] ball_hpos; reg [8:0] ball_hpos; // ball current X position
reg [8:0] ball_vpos; reg [8:0] ball_vpos; // ball current Y position
reg [8:0] ball_horiz_initial = 128; reg [8:0] ball_horiz_move = -2; // ball current X velocity
reg [8:0] ball_horiz_move = -2; reg [8:0] ball_vert_move = 2; // ball current Y velocity
reg [8:0] ball_vert_initial = 128;
reg [8:0] ball_vert_move = 2;
localparam BALL_SIZE = 4; localparam ball_horiz_initial = 128; // ball initial X position
localparam ball_vert_initial = 128; // ball initial Y position
localparam BALL_SIZE = 4; // ball size (in pixels)
// video sync generator
hvsync_generator hvsync_gen( hvsync_generator hvsync_gen(
.clk(clk), .clk(clk),
.reset(reset), .reset(reset),
@ -34,9 +36,11 @@ module ball_absolute_top(clk, reset, hsync, vsync, rgb);
always @(posedge vsync or posedge reset) always @(posedge vsync or posedge reset)
begin begin
if (reset) begin if (reset) begin
// reset ball position to center
ball_hpos <= ball_horiz_initial; ball_hpos <= ball_horiz_initial;
ball_vpos <= ball_vert_initial; ball_vpos <= ball_vert_initial;
end else begin end else begin
// add velocity vector to ball position
ball_hpos <= ball_hpos + ball_horiz_move; ball_hpos <= ball_hpos + ball_horiz_move;
ball_vpos <= ball_vpos + ball_vert_move; ball_vpos <= ball_vpos + ball_vert_move;
end end
@ -54,19 +58,22 @@ module ball_absolute_top(clk, reset, hsync, vsync, rgb);
ball_horiz_move <= -ball_horiz_move; ball_horiz_move <= -ball_horiz_move;
end end
// offset of ball position from video beam
wire [8:0] ball_hdiff = hpos - ball_hpos; wire [8:0] ball_hdiff = hpos - ball_hpos;
wire [8:0] ball_vdiff = vpos - ball_vpos; wire [8:0] ball_vdiff = vpos - ball_vpos;
// ball graphics output
wire ball_hgfx = ball_hdiff < BALL_SIZE; wire ball_hgfx = ball_hdiff < BALL_SIZE;
wire ball_vgfx = ball_vdiff < BALL_SIZE; wire ball_vgfx = ball_vdiff < BALL_SIZE;
wire ball_gfx = ball_hgfx && ball_vgfx; wire ball_gfx = ball_hgfx && ball_vgfx;
// collide with vertical and horizontal boundaries // collide with vertical and horizontal boundaries
// these are set when the ball touches a border
wire ball_vert_collide = ball_vpos >= 240 - BALL_SIZE; wire ball_vert_collide = ball_vpos >= 240 - BALL_SIZE;
wire ball_horiz_collide = ball_hpos >= 256 - BALL_SIZE; wire ball_horiz_collide = ball_hpos >= 256 - BALL_SIZE;
wire grid_gfx = (((hpos&7)==0) && ((vpos&7)==0));
// combine signals to RGB output
wire grid_gfx = (((hpos&7)==0) && ((vpos&7)==0));
wire r = display_on && (ball_hgfx | ball_gfx); wire r = display_on && (ball_hgfx | ball_gfx);
wire g = display_on && (grid_gfx | ball_gfx); wire g = display_on && (grid_gfx | ball_gfx);
wire b = display_on && (ball_vgfx | ball_gfx); wire b = display_on && (ball_vgfx | ball_gfx);

View File

@ -13,34 +13,34 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
wire [8:0] hpos; wire [8:0] hpos;
wire [8:0] vpos; wire [8:0] vpos;
reg [8:0] paddle_pos; reg [8:0] paddle_pos; // paddle X position
reg [8:0] ball_x; reg [8:0] ball_x; // ball X position
reg [8:0] ball_y; reg [8:0] ball_y; // ball Y position
reg ball_dir_x; reg ball_dir_x; // ball X direction (0=left, 1=right)
reg ball_speed_x; reg ball_speed_x; // ball speed (0=1 pixel/frame, 1=2 pixels/frame)
reg ball_dir_y; reg ball_dir_y; // ball Y direction (0=up, 1=down)
reg brick_array [0:BRICKS_H*BRICKS_V-1]; // 16*8 = 128 bits reg brick_array [0:BRICKS_H*BRICKS_V-1]; // 16*8 = 128 bits
wire [3:0] score0; wire [3:0] score0; // score right digit
wire [3:0] score1; wire [3:0] score1; // score left digit
wire [3:0] lives; wire [3:0] lives; // # lives remaining
reg incscore; reg incscore; // incscore signal
reg declives = 0; // TODO reg declives = 0; // TODO
localparam BRICKS_H = 16; localparam BRICKS_H = 16; // # of bricks across
localparam BRICKS_V = 8; localparam BRICKS_V = 8; // # of bricks down
localparam BALL_DIR_LEFT = 0; localparam BALL_DIR_LEFT = 0;
localparam BALL_DIR_RIGHT = 1; localparam BALL_DIR_RIGHT = 1;
localparam BALL_DIR_DOWN = 1; localparam BALL_DIR_DOWN = 1;
localparam BALL_DIR_UP = 0; localparam BALL_DIR_UP = 0;
localparam PADDLE_WIDTH = 31; localparam PADDLE_WIDTH = 31; // horizontal paddle size
localparam BALL_SIZE = 6; localparam BALL_SIZE = 6; // square ball size
// video sync generator
hvsync_generator hvsync_gen( hvsync_generator hvsync_gen(
.clk(clk), .clk(clk),
.reset(reset), .reset(reset),
@ -52,35 +52,37 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
); );
// scoreboard // scoreboard
wire score_gfx; // output from score generator
player_stats stats(.reset(reset), player_stats stats(.reset(reset),
.score0(score0), .score1(score1), .incscore(incscore), .score0(score0), .score1(score1), .incscore(incscore),
.lives(lives), .declives(declives)); .lives(lives), .declives(declives));
wire score_gfx;
scoreboard_generator score_gen( scoreboard_generator score_gen(
.score0(score0), .score1(score1), .lives(lives), .score0(score0), .score1(score1), .lives(lives),
.vpos(vpos), .hpos(hpos), .vpos(vpos), .hpos(hpos),
.board_gfx(score_gfx)); .board_gfx(score_gfx));
wire [5:0] hcell = hpos[8:3]; wire [5:0] hcell = hpos[8:3]; // horizontal brick index
wire [5:0] vcell = vpos[8:3]; wire [5:0] vcell = vpos[8:3]; // vertical brick index
wire lr_border = hcell==0 || hcell==31; wire lr_border = hcell==0 || hcell==31; // along horizontal border?
// TODO: unsigned compare doesn't work in JS // TODO: unsigned compare doesn't work in JS
wire [8:0] paddle_rel_x = ((hpos-paddle_pos) & 9'h1ff); wire [8:0] paddle_rel_x = ((hpos-paddle_pos) & 9'h1ff);
// player paddle graphics signal
wire paddle_gfx = (vcell == 28) && (paddle_rel_x < PADDLE_WIDTH); wire paddle_gfx = (vcell == 28) && (paddle_rel_x < PADDLE_WIDTH);
wire [8:0] ball_rel_x = (hpos-ball_x); // difference between ball position and video beam
wire [8:0] ball_rel_y = (vpos-ball_y); wire [8:0] ball_rel_x = (hpos - ball_x);
wire [8:0] ball_rel_y = (vpos - ball_y);
// ball graphics signal
wire ball_gfx = ball_rel_x < BALL_SIZE wire ball_gfx = ball_rel_x < BALL_SIZE
&& ball_rel_y < BALL_SIZE; && ball_rel_y < BALL_SIZE;
reg main_gfx; reg main_gfx; // main graphics signal (bricks and borders)
reg brick_present; reg brick_present; // 1 when we are drawing a brick
reg [6:0] brick_index; reg [6:0] brick_index;// index into array of current brick
// brick graphics signal
wire brick_gfx = lr_border || (brick_present && vpos[2:0] != 0 && hpos[3:1] != 4); wire brick_gfx = lr_border || (brick_present && vpos[2:0] != 0 && hpos[3:1] != 4);
// scan bricks: compute brick_index and brick_present flag // scan bricks: compute brick_index and brick_present flag
@ -92,14 +94,11 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
if (hpos[3:0] == 8) begin if (hpos[3:0] == 8) begin
// compute brick index // compute brick index
brick_index <= {vpos[5:3], hpos[7:4]}; brick_index <= {vpos[5:3], hpos[7:4]};
//main_gfx <= 0; // 2 pixel horiz spacing between bricks
end end
// every 17th pixel // every 17th pixel
else if (hpos[3:0] == 9) begin else if (hpos[3:0] == 9) begin
// load brick bit from array // load brick bit from array
brick_present <= brick_array[brick_index]; brick_present <= brick_array[brick_index];
end else begin
//main_gfx <= brick_present && vpos[2:0] != 0; // 1 pixel vert. spacing
end end
end else begin end else begin
brick_present <= 0; brick_present <= 0;
@ -111,6 +110,7 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
if (!hpaddle) if (!hpaddle)
paddle_pos <= vpos; paddle_pos <= vpos;
// 1 when ball signal intersects main (brick + border) signal
wire ball_pixel_collide = main_gfx & ball_gfx; wire ball_pixel_collide = main_gfx & ball_gfx;
/* verilator lint_off MULTIDRIVEN */ /* verilator lint_off MULTIDRIVEN */
@ -141,6 +141,7 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
incscore <= 0; // reset incscore incscore <= 0; // reset incscore
end end
// computes position of ball in relation to center of paddle
wire signed [8:0] ball_paddle_dx = ball_x - paddle_pos + 8; wire signed [8:0] ball_paddle_dx = ball_x - paddle_pos + 8;
// ball bounce: determine new velocity/direction // ball bounce: determine new velocity/direction
@ -189,9 +190,11 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
always @(negedge vsync or posedge reset) always @(negedge vsync or posedge reset)
begin begin
if (reset) begin if (reset) begin
// reset ball position to top center
ball_x <= 128; ball_x <= 128;
ball_y <= 180; ball_y <= 180;
end else begin end else begin
// move ball horizontal and vertical position
if (ball_dir_x == BALL_DIR_RIGHT) if (ball_dir_x == BALL_DIR_RIGHT)
ball_x <= ball_x + (ball_speed_x?1:0) + 1; ball_x <= ball_x + (ball_speed_x?1:0) + 1;
else else
@ -223,8 +226,8 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
endcase endcase
end end
// combine signals to RGB output
wire grid_gfx = (((hpos&7)==0) || ((vpos&7)==0)); wire grid_gfx = (((hpos&7)==0) || ((vpos&7)==0));
wire r = display_on && (ball_gfx | paddle_gfx); wire r = display_on && (ball_gfx | paddle_gfx);
wire g = display_on && (main_gfx | ball_gfx); wire g = display_on && (main_gfx | ball_gfx);
wire b = display_on && (grid_gfx | ball_gfx | brick_present); wire b = display_on && (grid_gfx | ball_gfx | brick_present);

View File

@ -9,7 +9,6 @@ module ball_slip_counter_top(clk, reset, hsync, vsync, rgb);
wire display_on; wire display_on;
wire [8:0] hpos; wire [8:0] hpos;
wire [8:0] vpos; wire [8:0] vpos;
reg ball_reset;
// 9-bit ball timers // 9-bit ball timers
reg [8:0] ball_htimer; reg [8:0] ball_htimer;
@ -26,7 +25,11 @@ module ball_slip_counter_top(clk, reset, hsync, vsync, rgb);
// 5-bit constants to load into counters // 5-bit constants to load into counters
localparam ball_horiz_prefix = 5'b01100; // 192 localparam ball_horiz_prefix = 5'b01100; // 192
localparam ball_vert_prefix = 5'b01111; // 240 localparam ball_vert_prefix = 5'b01111; // 240
// reset ball; will be unset when video beam reaches center position
reg ball_reset;
// video sync generator
hvsync_generator hvsync_gen( hvsync_generator hvsync_gen(
.clk(clk), .clk(clk),
.reset(reset), .reset(reset),
@ -64,10 +67,10 @@ module ball_slip_counter_top(clk, reset, hsync, vsync, rgb);
if (reset) if (reset)
ball_reset <= 1; ball_reset <= 1;
else if (hpos == 128 && vpos == 128) else if (hpos == 128 && vpos == 128)
ball_reset <= 0; ball_reset <= 0; // un-reset when beam reaches center position
end end
// collide with vertical and horizontal boundaries // collide with vertical and horizontal boundaries?
wire ball_vert_collide = ball_vgfx && vpos >= 240; wire ball_vert_collide = ball_vgfx && vpos >= 240;
wire ball_horiz_collide = ball_hgfx && hpos >= 256 && vpos == 255; wire ball_horiz_collide = ball_hgfx && hpos >= 256 && vpos == 255;
@ -75,7 +78,7 @@ module ball_slip_counter_top(clk, reset, hsync, vsync, rgb);
always @(posedge ball_vert_collide or posedge reset) always @(posedge ball_vert_collide or posedge reset)
begin begin
if (reset) if (reset)
ball_vert_move <= 4'd9; ball_vert_move <= 4'd9; // initial vertical velocity
else else
ball_vert_move <= (4'd9 ^ 4'd11) ^ ball_vert_move; // change dir. ball_vert_move <= (4'd9 ^ 4'd11) ^ ball_vert_move; // change dir.
end end
@ -84,13 +87,13 @@ module ball_slip_counter_top(clk, reset, hsync, vsync, rgb);
always @(posedge ball_horiz_collide or posedge reset) always @(posedge ball_horiz_collide or posedge reset)
begin begin
if (reset) if (reset)
ball_horiz_move <= 4'd10; ball_horiz_move <= 4'd10; // initial horizontal velocity
else else
ball_horiz_move <= (4'd10 ^ 4'd12) ^ ball_horiz_move; // change dir. ball_horiz_move <= (4'd10 ^ 4'd12) ^ ball_horiz_move; // change dir.
end end
// compute ball display // compute ball display
wire ball_hgfx = ball_htimer >= 508; wire ball_hgfx = ball_htimer >= 508; // 512-508 = 4 pixel ball
wire ball_vgfx = ball_vtimer >= 508; wire ball_vgfx = ball_vtimer >= 508;
wire ball_gfx = ball_hgfx && ball_vgfx; wire ball_gfx = ball_hgfx && ball_vgfx;

View File

@ -3,12 +3,14 @@
`include "hvsync_generator.v" `include "hvsync_generator.v"
// module for 10-digit bitmap ROM
module digits10_case(digit, yofs, bits); module digits10_case(digit, yofs, bits);
input [3:0] digit; input [3:0] digit; // digit 0-9
input [2:0] yofs; input [2:0] yofs; // vertical offset (0-4)
output reg [4:0] bits; output reg [4:0] bits; // output (5 bits)
// combine {digit,yofs} into single ROM address
wire [6:0] caseexpr = {digit,yofs}; wire [6:0] caseexpr = {digit,yofs};
always @(*) always @(*)
@ -79,13 +81,13 @@ endmodule
module digits10_array(digit, yofs, bits); module digits10_array(digit, yofs, bits);
input [3:0] digit; input [3:0] digit; // digit 0-9
input [2:0] yofs; input [2:0] yofs; // vertical offset (0-4)
output [4:0] bits; output [4:0] bits; // output (5 bits)
reg [4:0] bitarray[0:15][0:4]; reg [4:0] bitarray[0:15][0:4]; // ROM array
assign bits = bitarray[digit][yofs]; assign bits = bitarray[digit][yofs]; // assign module output
integer i,j; integer i,j;
@ -157,6 +159,7 @@ module digits10_array(digit, yofs, bits);
end end
endmodule endmodule
// test module
module test_numbers_top(clk, reset, hsync, vsync, rgb); module test_numbers_top(clk, reset, hsync, vsync, rgb);
input clk, reset; input clk, reset;

View File

@ -10,18 +10,18 @@ module hvsync_generator(clk, reset, hsync, vsync, display_on, hpos, vpos);
output reg [8:0] hpos; output reg [8:0] hpos;
output reg [8:0] vpos; output reg [8:0] vpos;
// constant declarations for TV-simulator sync parameters // declarations for TV-simulator sync parameters
// horizontal // horizontal constants
parameter H_DISPLAY = 256; // horizontal display width parameter H_DISPLAY = 256; // horizontal display width
parameter H_BACK = 23; // horizontal left border (back porch) parameter H_BACK = 23; // horizontal left border (back porch)
parameter H_FRONT = 7; // horizontal right border (front porch) parameter H_FRONT = 7; // horizontal right border (front porch)
parameter H_SYNC = 23; // horizontal sync width parameter H_SYNC = 23; // horizontal sync width
// vertical // vertical constants
parameter V_DISPLAY = 240; // vertical display height parameter V_DISPLAY = 240; // vertical display height
parameter V_TOP = 5; // vertical top border parameter V_TOP = 5; // vertical top border
parameter V_BOTTOM = 14; // vertical bottom border parameter V_BOTTOM = 14; // vertical bottom border
parameter V_SYNC = 3; // vertical sync # lines parameter V_SYNC = 3; // vertical sync # lines
// derived // derived constants
parameter H_SYNC_START = H_DISPLAY + H_FRONT; parameter H_SYNC_START = H_DISPLAY + H_FRONT;
parameter H_SYNC_END = H_DISPLAY + H_FRONT + H_SYNC - 1; parameter H_SYNC_END = H_DISPLAY + H_FRONT + H_SYNC - 1;
parameter H_MAX = H_DISPLAY + H_BACK + H_FRONT + H_SYNC - 1; parameter H_MAX = H_DISPLAY + H_BACK + H_FRONT + H_SYNC - 1;
@ -29,8 +29,8 @@ module hvsync_generator(clk, reset, hsync, vsync, display_on, hpos, vpos);
parameter V_SYNC_END = V_DISPLAY + V_BOTTOM + V_SYNC - 1; parameter V_SYNC_END = V_DISPLAY + V_BOTTOM + V_SYNC - 1;
parameter V_MAX = V_DISPLAY + V_TOP + V_BOTTOM + V_SYNC - 1; parameter V_MAX = V_DISPLAY + V_TOP + V_BOTTOM + V_SYNC - 1;
wire hmaxxed = (hpos == H_MAX) || reset; wire hmaxxed = (hpos == H_MAX) || reset; // set when hpos is maximum
wire vmaxxed = (vpos == V_MAX) || reset; wire vmaxxed = (vpos == V_MAX) || reset; // set when vpos is maximum
// horizontal position counter // horizontal position counter
always @(posedge clk) always @(posedge clk)
@ -53,6 +53,7 @@ module hvsync_generator(clk, reset, hsync, vsync, display_on, hpos, vpos);
vpos <= vpos + 1; vpos <= vpos + 1;
end end
// display_on is set when beam is in "safe" visible frame
assign display_on = (hpos<H_DISPLAY) && (vpos<V_DISPLAY); assign display_on = (hpos<H_DISPLAY) && (vpos<V_DISPLAY);
endmodule endmodule

View File

@ -1,15 +1,15 @@
`ifndef LFSR_V `ifndef LFSR_V
`define LFSR_V `define LFSR_V
module LFSR(clk,reset,enable,lfsr); module LFSR(clk, reset, enable, lfsr);
parameter TAPS = 8'b11101; parameter TAPS = 8'b11101; // bitmask for taps
parameter INVERT = 0; parameter INVERT = 0; // invert feedback bit?
localparam NBITS = $size(TAPS); localparam NBITS = $size(TAPS); // bit width (derived from TAPS)
input clk, reset; input clk, reset;
input enable; input enable; // only perform shift when enable=1
output reg [NBITS-1:0] lfsr; output reg [NBITS-1:0] lfsr; // shift register
wire feedback = lfsr[NBITS-1] ^ INVERT; wire feedback = lfsr[NBITS-1] ^ INVERT;

View File

@ -10,9 +10,11 @@ module paddles_top(clk, reset, hsync, vsync, hpaddle, vpaddle, rgb);
wire [8:0] hpos; wire [8:0] hpos;
wire [8:0] vpos; wire [8:0] vpos;
// player position (only set at VSYNC)
reg [7:0] player_x; reg [7:0] player_x;
reg [7:0] player_y; reg [7:0] player_y;
// paddle position (set continuously during frame)
reg [7:0] paddle_x; reg [7:0] paddle_x;
reg [7:0] paddle_y; reg [7:0] paddle_y;

View File

@ -12,17 +12,22 @@ module racing_game_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
wire [8:0] hpos; wire [8:0] hpos;
wire [8:0] vpos; wire [8:0] vpos;
// player car position (set at VSYNC)
reg [7:0] player_x; reg [7:0] player_x;
reg [7:0] player_y; reg [7:0] player_y;
// paddle position (set continuously during frame)
reg [7:0] paddle_x; reg [7:0] paddle_x;
reg [7:0] paddle_y; reg [7:0] paddle_y;
// enemy car position
reg [7:0] enemy_x = 128; reg [7:0] enemy_x = 128;
reg [7:0] enemy_y = 128; reg [7:0] enemy_y = 128;
reg enemy_dir = 0; // enemy car direction, 1=right, 0=left
reg enemy_dir = 0;
reg [15:0] track_pos = 0; reg [15:0] track_pos = 0; // player position along track (16 bits)
reg [7:0] speed = 31; reg [7:0] speed = 31; // player velocity along track (8 bits)
// video sync generator
hvsync_generator hvsync_gen( hvsync_generator hvsync_gen(
.clk(clk), .clk(clk),
.reset(0), .reset(0),
@ -33,6 +38,14 @@ module racing_game_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
.vpos(vpos) .vpos(vpos)
); );
// set paddle registers
always @(posedge hsync)
begin
if (!hpaddle) paddle_x <= vpos[7:0];
if (!vpaddle) paddle_y <= vpos[7:0];
end
// wire up car sprite ROM
wire [3:0] car_sprite_yofs; wire [3:0] car_sprite_yofs;
wire [7:0] car_sprite_bits; wire [7:0] car_sprite_bits;
@ -40,16 +53,19 @@ module racing_game_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
.yofs(car_sprite_yofs), .yofs(car_sprite_yofs),
.bits(car_sprite_bits)); .bits(car_sprite_bits));
// signals for player sprite generator
wire player_vstart = {1'd0,player_y} == vpos; wire player_vstart = {1'd0,player_y} == vpos;
wire player_hstart = {1'd0,player_x} == hpos; wire player_hstart = {1'd0,player_x} == hpos;
wire player_gfx; wire player_gfx;
wire player_is_drawing; wire player_is_drawing;
// signals for enemy sprite generator
wire enemy_vstart = {1'd0,enemy_y} == vpos; wire enemy_vstart = {1'd0,enemy_y} == vpos;
wire enemy_hstart = {1'd0,enemy_x} == hpos; wire enemy_hstart = {1'd0,enemy_x} == hpos;
wire enemy_gfx; wire enemy_gfx;
wire enemy_is_drawing; wire enemy_is_drawing;
// player sprite generator
sprite_renderer player_renderer( sprite_renderer player_renderer(
.clk(clk), .clk(clk),
.vstart(player_vstart), .vstart(player_vstart),
@ -60,6 +76,7 @@ module racing_game_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
.gfx(player_gfx), .gfx(player_gfx),
.in_progress(player_is_drawing)); .in_progress(player_is_drawing));
// enemy sprite generator
sprite_renderer enemy_renderer( sprite_renderer enemy_renderer(
.clk(clk), .clk(clk),
.vstart(enemy_vstart), .vstart(enemy_vstart),
@ -69,17 +86,14 @@ module racing_game_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
.rom_bits(car_sprite_bits), .rom_bits(car_sprite_bits),
.gfx(enemy_gfx), .gfx(enemy_gfx),
.in_progress(player_is_drawing)); .in_progress(player_is_drawing));
always @(posedge hsync) // signals for enemy bouncing off left/right borders
begin
if (!hpaddle) paddle_x <= vpos[7:0];
if (!vpaddle) paddle_y <= vpos[7:0];
end
wire enemy_hit_left = (enemy_x == 64); wire enemy_hit_left = (enemy_x == 64);
wire enemy_hit_right = (enemy_x == 192); wire enemy_hit_right = (enemy_x == 192);
wire enemy_hit_edge = enemy_hit_left || enemy_hit_right; wire enemy_hit_edge = enemy_hit_left || enemy_hit_right;
// update player, enemy, track counters
// runs once per frame
always @(posedge vsync) always @(posedge vsync)
begin begin
player_x <= paddle_x; player_x <= paddle_x;
@ -101,6 +115,7 @@ module racing_game_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
speed <= speed - 1; speed <= speed - 1;
end end
// set to 1 when player collides with enemy or track
reg frame_collision; reg frame_collision;
always @(posedge clk) always @(posedge clk)
@ -109,10 +124,12 @@ module racing_game_top(clk, hsync, vsync, rgb, hpaddle, vpaddle);
else if (vsync) else if (vsync)
frame_collision <= 0; frame_collision <= 0;
// track graphics signals
wire track_offside = (hpos[7:5]==0) || (hpos[7:5]==7); wire track_offside = (hpos[7:5]==0) || (hpos[7:5]==7);
wire track_shoulder = (hpos[7:3]==3) || (hpos[7:3]==28); wire track_shoulder = (hpos[7:3]==3) || (hpos[7:3]==28);
wire track_gfx = (vpos[5:1]!=track_pos[5:1]) && track_offside; wire track_gfx = (vpos[5:1]!=track_pos[5:1]) && track_offside;
// combine signals for RGB output
wire r = display_on && (player_gfx || enemy_gfx || track_shoulder); wire r = display_on && (player_gfx || enemy_gfx || track_shoulder);
wire g = display_on && (player_gfx || track_gfx); wire g = display_on && (player_gfx || track_gfx);
wire b = display_on && (enemy_gfx || track_shoulder); wire b = display_on && (enemy_gfx || track_shoulder);

View File

@ -1,3 +1,4 @@
`include "hvsync_generator.v" `include "hvsync_generator.v"
`include "ram.v" `include "ram.v"
@ -53,14 +54,12 @@ module sprite_scanline_renderer(clk, reset, hpos, vpos, rgb,
output [15:0] rom_addr; // sprite ROM address output [15:0] rom_addr; // sprite ROM address
input [15:0] rom_data; // sprite ROM data input [15:0] rom_data; // sprite ROM data
// copy of sprite data from RAM // copy of sprite data from RAM (N entries)
reg [7:0] sprite_xpos[0:N-1]; reg [7:0] sprite_xpos[0:N-1];
reg [7:0] sprite_ypos[0:N-1]; reg [7:0] sprite_ypos[0:N-1];
reg [7:0] sprite_attr[0:N-1]; reg [7:0] sprite_attr[0:N-1];
// mapping of N sprites to M line slots
reg [NB-1:0] sprite_to_line[0:M-1];
// M sprite slots
reg [7:0] line_xpos[0:M-1]; // X pos for M slots reg [7:0] line_xpos[0:M-1]; // X pos for M slots
reg [7:0] line_yofs[0:M-1]; // Y pos for M slots reg [7:0] line_yofs[0:M-1]; // Y pos for M slots
reg [7:0] line_attr[0:M-1]; // attr for M slots reg [7:0] line_attr[0:M-1]; // attr for M slots
@ -74,6 +73,7 @@ module sprite_scanline_renderer(clk, reset, hpos, vpos, rgb,
reg [8:0] write_ofs; reg [8:0] write_ofs;
reg [15:0] out_bitmap; reg [15:0] out_bitmap;
reg [7:0] out_attr; reg [7:0] out_attr;
reg romload;
// which sprite are we currently reading? // which sprite are we currently reading?
wire [NB-1:0] load_index = hpos[NB:1]; wire [NB-1:0] load_index = hpos[NB:1];
@ -122,43 +122,49 @@ module sprite_scanline_renderer(clk, reset, hpos, vpos, rgb,
endcase endcase
end end
end else if (hpos < N*2) begin end else if (hpos < N*2) begin
// setup vars for next phase
k <= 0; k <= 0;
romload <= 0;
// select the sprites that will appear in this scanline // select the sprites that will appear in this scanline
case (hpos[0]) case (hpos[0])
// compute Y offset of sprite relative to scanline // compute Y offset of sprite relative to scanline
0: z <= 8'(vpos - sprite_ypos[i]); 0: z <= 8'(vpos - sprite_ypos[i]);
// sprite is active if Y offset is 0..15
1: begin 1: begin
// sprite is active if Y offset is 0..15
if (z < 16) begin if (z < 16) begin
line_xpos[j] <= sprite_xpos[i]; // save X pos
line_yofs[j] <= z; // save Y offset line_yofs[j] <= z; // save Y offset
sprite_to_line[j] <= i; // save main array index line_attr[j] <= sprite_attr[i]; // save attr
line_active[j] <= 1; // mark sprite active line_active[j] <= 1; // mark sprite active
j <= j + 1; // inc counter j <= j + 1; // inc counter
end end
i <= i + 1; // inc main array counter i <= i + 1; // inc main array counter
end end
endcase endcase
end else if (hpos < N*2+M*24) begin end else if (hpos < N*2+M*18) begin
// setup vars for next phase
j <= 0; j <= 0;
// divide hpos by 24 (8 setup + 16 render) // if sprite shift register is empty, load new sprite
if ((hpos[3:0] < 8) ^^ hpos[4]) begin if (out_bitmap == 0) begin
// render sprites into write buffer case (romload)
case (hpos[3:0]) 0: begin
// grab index into main sprite array // set ROM address and fetch bitmap
0: i <= sprite_to_line[k]; rom_addr <= {4'b0, line_attr[k][7:4], line_yofs[k]};
// load scanline buffer offset to write end
1: write_ofs <= {~vpos[0], sprite_xpos[i]}; 1: begin
// set ROM address and fetch bitmap // load scanline buffer offset to write
2: rom_addr <= {4'b0, sprite_attr[i][7:4], line_yofs[k]}; write_ofs <= {~vpos[0], line_xpos[k]};
// fetch 0 if sprite is inactive // fetch 0 if sprite is inactive
3: out_bitmap <= line_active[k] ? rom_data : 0; out_bitmap <= line_active[k] ? rom_data : 0;
// load attribute for sprite // load attribute for sprite
4: out_attr <= sprite_attr[i]; out_attr <= line_attr[k];
// disable sprite for next scanline // disable sprite for next scanline
6: line_active[k] <= 0; line_active[k] <= 0;
// go to next sprite in 2ndary buffer // go to next sprite in 2ndary buffer
7: k <= k + 1; k <= k + 1;
end
endcase endcase
romload <= !romload;
end else begin end else begin
// write color to scanline buffer if low bit == 1 // write color to scanline buffer if low bit == 1
if (out_bitmap[0]) if (out_bitmap[0])

View File

@ -1,4 +1,4 @@

.include "hvsync_generator.v" .include "hvsync_generator.v"
.include "font_cp437_8x8.v" .include "font_cp437_8x8.v"
.include "ram.v" .include "ram.v"
@ -140,11 +140,15 @@ MoveSprites:
mov dx,@SpriteTable mov dx,@SpriteTable
mov cx,#5 mov cx,#5
MoveSLoop: MoveSLoop:
mov ax,[dx] ; x/y pos mov ax,[dx] ; x/y pos
mov bx,[dx+1] ; attributes/dir mov bx,[dx+1] ; direction
and bx,#3 ; bx = direction (0-3) rol bx
rol bx
rol bx
rol bx
and bx,#3 ; bx = direction (0-3)
add bx,@DirectionXY add bx,@DirectionXY
add ax,[bx] ; lookup & add to x/y add ax,[bx] ; lookup & add to x/y
; make sure we don't collide with wall ; make sure we don't collide with wall
mov ex,ax mov ex,ax
add ex,#$08 add ex,#$08
@ -170,19 +174,18 @@ MoveSLoop:
bz DoNotUpdatePos bz DoNotUpdatePos
; update x/y position ; update x/y position
mov [dx],ax ; store x/y pos mov [dx],ax ; store x/y pos
inc dx
inc dx
NextSLoop: NextSLoop:
add dx,#2
dec cx dec cx
bnz MoveSLoop bnz MoveSLoop
rts rts
; Choose a new direction ; Choose a new direction
DoNotUpdatePos: DoNotUpdatePos:
mov bx,[dx+1] ; attributes/dir add dx,#1
inc bx mov bx,[dx] ; direction
inc dx add bx,@$1000
mov [dx],bx mov [dx],bx
inc dx sub dx,#1
jmp NextSLoop jmp NextSLoop
HelloWorld: HelloWorld:
@ -190,6 +193,7 @@ HelloWorld:
.data 0 .data 0
SpriteInitData: SpriteInitData:
.data $b373 $1233
.data $8363 $3456 .data $8363 $3456
.data $8373 $4567 .data $8373 $4567
.data $8383 $5678 .data $8383 $5678

View File

@ -592,27 +592,28 @@ var VerilogPlatform = function(mainElement, options) {
this.loadROM = function(title, output) { this.loadROM = function(title, output) {
var mod; var mod;
if (output.code) { if (output.code) {
try { // is code identical?
mod = new Function('base', output.code); if (current_output && current_output.code == output.code) {
} catch (e) { } else {
this.printErrorCodeContext(e, output.code); try {
throw e; mod = new Function('base', output.code);
} catch (e) {
this.printErrorCodeContext(e, output.code);
throw e;
}
// compile Verilog code
var base = new VerilatorBase();
gen = new mod(base);
//$.extend(gen, base);
gen.__proto__ = base;
current_output = output;
module_name = output.name ? output.name.substr(1) : "top";
trace_ports = current_output.ports;
trace_signals = current_output.ports.concat(current_output.signals);
trace_index = 0;
// power on module
this.poweron();
} }
// compile Verilog code
var base = new VerilatorBase();
gen = new mod(base);
//$.extend(gen, base);
gen.__proto__ = base;
current_output = output;
module_name = output.name ? output.name.substr(1) : "top";
trace_ports = current_output.ports;
trace_signals = current_output.ports.concat(current_output.signals);
trace_index = 0;
// power on module
this.poweron();
} else {
// TODO: :^P
output = {program_rom_variable: title, program_rom: output};
} }
// replace program ROM, if using the assembler // replace program ROM, if using the assembler
if (output.program_rom && output.program_rom_variable) { if (output.program_rom && output.program_rom_variable) {
@ -624,6 +625,7 @@ var VerilogPlatform = function(mainElement, options) {
} else { } else {
alert("No program_rom variable found (" + output.program_rom_variable + ")"); alert("No program_rom variable found (" + output.program_rom_variable + ")");
} }
this.reset();
} }
// restart audio // restart audio
restartAudio(); restartAudio();

View File

@ -60,7 +60,7 @@ export class CodeProject {
var m; var m;
while (m = re.exec(text)) { while (m = re.exec(text)) {
files.push(m[2]); files.push(m[2]);
files.push('local/'+m[2]); // TODO? //files.push('local/'+m[2]); // TODO: shows up 2x in interface
} }
} else { } else {
var re = /^\s*([;#]|[/][/][#])link\s+"(.+?)"/gm; var re = /^\s*([;#]|[/][/][#])link\s+"(.+?)"/gm;

View File

@ -1120,6 +1120,8 @@ function compileJSASM(asmcode, platform, options, is_inline) {
result.output.program_rom = asmout; result.output.program_rom = asmout;
// cpu_platform__DOT__program_rom // cpu_platform__DOT__program_rom
result.output.program_rom_variable = jsasm_module_top + "__DOT__program_rom"; result.output.program_rom_variable = jsasm_module_top + "__DOT__program_rom";
result.listings = {};
result.listings[options.path] = {lines:result.lines};
} }
return result; return result;
} }