1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-11-25 03:34:05 +00:00

can scroll scope when paused; updates to presets

This commit is contained in:
Steven Hugg 2018-02-28 11:09:29 -06:00
parent 8f1563f88e
commit db005dc98e
4 changed files with 88 additions and 54 deletions

View File

@ -7,7 +7,7 @@
`include "sound_generator.v"
`include "cpu16.v"
module maze_game_top(clk, reset, hsync, vsync, rgb);
module cpu_platform(clk, reset, hsync, vsync, rgb);
input clk, reset;
output hsync, vsync;
@ -19,11 +19,10 @@ module maze_game_top(clk, reset, hsync, vsync, rgb);
// video RAM bus
wire [15:0] ram_read;
reg [15:0] ram_write = 0;
reg ram_writeenable = 0;
reg [15:0] ram_write;
reg ram_writeenable;
// multiplex sprite and tile RAM
wire sprite_ram_select = (vpos == 256);
reg [15:0] tile_ram_addr;
reg [5:0] sprite_ram_addr;
wire tile_reading;
@ -32,8 +31,8 @@ module maze_game_top(clk, reset, hsync, vsync, rgb);
always @(*)
if (cpu_busy) begin
if (sprite_ram_select)
mux_ram_addr = {9'b1111111, sprite_ram_addr};
if (sprite_reading)
mux_ram_addr = {9'b111111100, sprite_ram_addr};
else
mux_ram_addr = tile_ram_addr[14:0];
end else
@ -141,34 +140,45 @@ module maze_game_top(clk, reset, hsync, vsync, rgb);
.org 0x8000
.len 1024
mov sp,@$6fff
mov dx,@Init
mov dx,@InitPageTable
jsr dx
mov ax,#0
mov dx,@Clear
mov ax,@$4ffe
mov dx,@ClearTiles
jsr dx
mov dx,@ClearSprites
jsr dx
reset
Init:
InitPageTable:
mov ax,@$6000 ; screen buffer
mov bx,@$7e00 ; page table start
mov cx,#32 ; 32 rows
InitLoop:
InitPTLoop:
mov [bx],ax
mov [ax],ax
add ax,#32
inc bx
dec cx
bnz InitLoop
bnz InitPTLoop
rts
Clear:
mov bx,@$7e00
mov cx,@1024
ClearTiles:
mov bx,@$6000
mov cx,@$390
ClearLoop:
mov [bx],ax
inc bx
dec cx
bnz ClearLoop
rts
ClearSprites:
mov bx,@$7f00
mov ax,#0
mov cx,#$80
ClearSLoop:
mov ax,[bx]
add ax,@$101
mov [bx],ax
inc bx
dec cx
bnz ClearSLoop
__endasm
};
end

View File

@ -94,7 +94,8 @@ module sprite_scanline_renderer(clk, reset, hpos, vpos, rgb,
if (reset || vpos[8]) begin
// load sprites from RAM on line 260
// 8 cycles per sprite
if (vpos == 260 && hpos < N*8) begin
// do first sprite twice b/c CPU might still be busy
if (vpos == 260 && hpos < N*8+8) begin
ram_busy <= 1;
case (hpos[2:0])
3: begin
@ -167,13 +168,6 @@ module sprite_scanline_renderer(clk, reset, hpos, vpos, rgb,
scanline[read_bufidx] <= 0;
end
initial
begin
sprite_xpos[0] = 0;
sprite_ypos[0] = 0;
sprite_attr[0] = 1;
end
endmodule
module test_scanline_render_top(clk, reset, hsync, vsync, rgb);

View File

@ -2,7 +2,7 @@
`include "font_cp437_8x8.v"
`include "ram.v"
module tile_renderer(clk, reset, hpos, vpos, display_on,
module tile_renderer(clk, reset, hpos, vpos,
rgb,
ram_addr, ram_read, ram_busy,
rom_addr, rom_data);
@ -10,7 +10,6 @@ module tile_renderer(clk, reset, hpos, vpos, display_on,
input clk, reset;
input [8:0] hpos;
input [8:0] vpos;
input display_on;
output [3:0] rgb;
output reg [15:0] ram_addr;
@ -22,33 +21,42 @@ module tile_renderer(clk, reset, hpos, vpos, display_on,
reg [7:0] page_base = 8'h7e; // page table base (8 bits)
reg [15:0] row_base; // row table base (16 bits)
wire [4:0] row = vpos[7:3]; // 5-bit row, vpos / 8
reg [4:0] row;
//wire [4:0] row = vpos[7:3]; // 5-bit row, vpos / 8
wire [4:0] col = hpos[7:3]; // 5-bit column, hpos / 8
wire [2:0] yofs = vpos[2:0]; // scanline of cell (0-7)
wire [2:0] xofs = hpos[2:0]; // which pixel to draw (0-7)
reg [7:0] char;
reg [7:0] attr;
reg [15:0] cur_cell;
wire [7:0] cur_char = cur_cell[7:0];
wire [7:0] cur_attr = cur_cell[15:8];
// tile ROM address
assign rom_addr = {char, yofs};
assign rom_addr = {cur_char, yofs};
reg [15:0] row_buffer[0:31];
// lookup char and attr
always @(posedge clk) begin
// reset row to 0 when last row displayed
if (vpos == 248) begin
row <= 0;
end
// time to read a row?
if (vpos[2:0] == 7) begin
// read row_base from page table (2 bytes)
case (hpos[7:0])
186: ram_busy <= 1;
185: ram_busy <= 1;
190: ram_addr <= {page_base, 3'b000, row};
192: row_base <= ram_read;
192+32: ram_busy <= 0;
192+32: begin
ram_busy <= 0;
row <= row + 1;
end
endcase
// load row of tile data from RAM
if (hpos >= 192 && hpos < 192+32) begin
// (last two twice)
if (hpos >= 192 && hpos < 192+34) begin
ram_addr <= row_base + 16'(hpos[4:0]);
row_buffer[hpos[4:0]-2] <= ram_read;
end
@ -57,17 +65,16 @@ module tile_renderer(clk, reset, hpos, vpos, display_on,
if (hpos < 256) begin
case (hpos[2:0])
7: begin
char <= row_buffer[col][7:0];
attr <= row_buffer[col][15:8];
cur_cell <= row_buffer[col+1];
end
endcase
end else if (hpos == 308) begin
cur_cell <= row_buffer[0];
end
end
// extract bit from ROM output
assign rgb = display_on
? (rom_data[~xofs] ? attr[3:0] : attr[7:4])
: 0;
assign rgb = rom_data[~xofs] ? cur_attr[3:0] : cur_attr[7:4];
endmodule
@ -108,26 +115,38 @@ module test_tilerender_top(clk, reset, hsync, vsync, rgb);
.addr(ram_addr),
.we(ram_writeenable)
);
wire [3:0] rgb_tile;
tile_renderer tile_gen(
.clk(clk),
.reset(reset),
.hpos(hpos),
.vpos(vpos),
.display_on(display_on),
.ram_addr(ram_addr),
.ram_read(ram_read),
.ram_busy(ram_busy),
.rom_addr(rom_addr),
.rom_data(rom_data),
.rgb(rgb)
.rgb(rgb_tile)
);
assign rgb = display_on ? rgb_tile : rgb_tile|8;
// tile ROM
font_cp437_8x8 tile_rom(
.addr(rom_addr),
.data(rom_data)
);
initial begin
for (int i=0; i<32; i++) begin
ram.mem[16'h7e00 + 16'(i)] = 16'(i*32);
ram.mem[16'(i*32)] = 16'hfa1b;
ram.mem[16'(i*32+31)] = 16'hfb1a;
ram.mem[16'(i)] = 16'hfc18;
ram.mem[16'(28*32+i)] = 16'hfd19;
end
end
endmodule

View File

@ -24,7 +24,7 @@ var VERILOG_PRESETS = [
{id:'tile_renderer.v', name:'Tile Renderer'},
{id:'sprite_scanline_renderer.v', name:'Sprite Scanline Renderer'},
{id:'cpu16.v', name:'16-Bit CPU'},
{id:'maze_game.v', name:'Maze Game'},
{id:'cpu_platform.v', name:'CPU Platform'},
];
var VERILOG_KEYCODE_MAP = makeKeycodeMap([
@ -332,7 +332,7 @@ var VerilogPlatform = function(mainElement, options) {
var fps = self.getFrameRate();
// darken the previous frame?
if (fps < 45) {
var mask = fps > 10 ? 0xcfffffff : 0x7fdddddd;
var mask = fps > 5 ? 0xe7ffffff : 0x7fdddddd;
for (var i=0; i<idata.length; i++)
idata[i] &= mask;
}
@ -342,6 +342,15 @@ var VerilogPlatform = function(mainElement, options) {
updateVideoFrameCycles(cyclesPerFrame * fps/60 + 1, sync, trace);
//if (trace) displayTraceBuffer();
updateInspectionFrame();
updateAnimateScope(trace);
updateInspectionPostFrame();
self.restartDebugState();
gen.__unreset();
}
function updateAnimateScope() {
var fps = self.getFrameRate();
var trace = fps < 0.02;
if (scope_a > 0.01) {
video.getContext().fillStyle = "black";
video.getContext().fillRect(0, 0, videoWidth, videoHeight);
@ -359,9 +368,6 @@ var VerilogPlatform = function(mainElement, options) {
// smooth transition
scope_a = scope_a * 0.9 + (trace?1.0:0.0) * 0.1;
scope_y_top = (1 - scope_a*0.7) * videoHeight - (1 - scope_a) * scope_y_offset;
updateInspectionPostFrame();
self.restartDebugState();
gen.__unreset();
}
function displayTraceBuffer() {
@ -520,7 +526,7 @@ var VerilogPlatform = function(mainElement, options) {
if (mouse_pressed) {
scope_y_offset = clamp(Math.min(0,-scope_max_y+videoHeight), 0, scope_y_offset + new_y - paddle_y);
scope_time_x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 16);
dirty = true;
redrawFrame();
}
paddle_x = clamp(8, 240, new_x);
paddle_y = clamp(8, 240, new_y);
@ -529,16 +535,17 @@ var VerilogPlatform = function(mainElement, options) {
scope_time_x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 16);
mouse_pressed = true;
if (e.target.setCapture) e.target.setCapture();
dirty = true;
redrawFrame();
});
$(video.canvas).mouseup(function(e) {
mouse_pressed = false;
if (e.target.setCapture) e.target.releaseCapture();
redrawFrame();
});
$(video.canvas).keydown(function(e) {
switch (e.keyCode) {
case 37: scope_time_x--; dirty=true; break;
case 39: scope_time_x++; dirty=true; break;
case 37: scope_time_x--; redrawFrame(); break;
case 39: scope_time_x++; redrawFrame(); break;
}
});
idata = video.getFrameData();
@ -555,6 +562,10 @@ var VerilogPlatform = function(mainElement, options) {
self.setFrameRate(60);
}
function redrawFrame() {
updateAnimateScope();
}
this.printErrorCodeContext = function(e, code) {
if (e.lineNumber && e.message) {
var lines = code.split('\n');