mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-06-20 08:29:30 +00:00
fixed sample-based audio
This commit is contained in:
parent
e7067ff50d
commit
8c3939ac6c
87
presets/verilog/cargame.asm
Normal file
87
presets/verilog/cargame.asm
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
.arch nano8
|
||||||
|
.org 128
|
||||||
|
|
||||||
|
.define PADDLE_X 0
|
||||||
|
.define PADDLE_Y 1
|
||||||
|
.define PLAYER_X 2
|
||||||
|
.define PLAYER_Y 3
|
||||||
|
.define ENEMY_X 4
|
||||||
|
.define ENEMY_Y 5
|
||||||
|
.define ENEMY_DIR 6
|
||||||
|
.define SPEED 7
|
||||||
|
.define TRACKPOS_LO 8
|
||||||
|
.define TRACKPOS_HI 9
|
||||||
|
|
||||||
|
.define IN_HPOS $40
|
||||||
|
.define IN_VPOS $41
|
||||||
|
.define IN_FLAGS $42
|
||||||
|
|
||||||
|
.define F_DISPLAY 1
|
||||||
|
.define F_HPADDLE 2
|
||||||
|
.define F_VPADDLE 4
|
||||||
|
.define F_HSYNC 8
|
||||||
|
.define F_VSYNC 16
|
||||||
|
.define F_COLLIDE 32
|
||||||
|
|
||||||
|
Start:
|
||||||
|
lda 128
|
||||||
|
sta PLAYER_X
|
||||||
|
sta ENEMY_X
|
||||||
|
sta ENEMY_Y
|
||||||
|
lda 180
|
||||||
|
sta PLAYER_Y
|
||||||
|
zero A
|
||||||
|
sta SPEED
|
||||||
|
; test hpaddle flag
|
||||||
|
DisplayLoop:
|
||||||
|
lda F_HPADDLE
|
||||||
|
ldb IN_FLAGS
|
||||||
|
andrb NOP
|
||||||
|
bz DisplayLoop
|
||||||
|
; [vpos] -> paddle_x
|
||||||
|
ldb IN_VPOS
|
||||||
|
movrb A
|
||||||
|
sta PLAYER_X
|
||||||
|
; wait for vsync=1 then vsync=0
|
||||||
|
lda F_VSYNC
|
||||||
|
ldb IN_FLAGS
|
||||||
|
WaitForVsyncOn:
|
||||||
|
andrb NOP
|
||||||
|
bz WaitForVsyncOn
|
||||||
|
WaitForVsyncOff:
|
||||||
|
andrb NOP
|
||||||
|
bnz WaitForVsyncOff
|
||||||
|
; check collision
|
||||||
|
lda F_COLLIDE
|
||||||
|
ldb IN_FLAGS
|
||||||
|
andrb NOP
|
||||||
|
bz NoCollision
|
||||||
|
; load slow speed
|
||||||
|
lda 16
|
||||||
|
sta SPEED
|
||||||
|
NoCollision:
|
||||||
|
; update speed
|
||||||
|
ldb SPEED
|
||||||
|
movrb A
|
||||||
|
inc A
|
||||||
|
; don't store if == 0
|
||||||
|
bz MaxSpeed
|
||||||
|
sta SPEED
|
||||||
|
MaxSpeed:
|
||||||
|
movrb A
|
||||||
|
lsr A
|
||||||
|
lsr A
|
||||||
|
lsr A
|
||||||
|
lsr A
|
||||||
|
; add to lo byte of track pos
|
||||||
|
ldb TRACKPOS_LO
|
||||||
|
addrb B
|
||||||
|
swapab
|
||||||
|
sta TRACKPOS_LO
|
||||||
|
swapab
|
||||||
|
; update enemy vert pos
|
||||||
|
ldb ENEMY_Y
|
||||||
|
addrb A
|
||||||
|
sta ENEMY_Y
|
||||||
|
jmp DisplayLoop
|
||||||
|
reset
|
163
presets/verilog/music.v
Normal file
163
presets/verilog/music.v
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
`include "hvsync_generator.v"
|
||||||
|
|
||||||
|
module sound_psg(clk, reset, out, reg_sel, reg_data, reg_write);
|
||||||
|
|
||||||
|
input clk, reset;
|
||||||
|
input [3:0] reg_sel;
|
||||||
|
input [7:0] reg_data;
|
||||||
|
input reg_write;
|
||||||
|
output [7:0] out;
|
||||||
|
|
||||||
|
parameter NVOICES = 4;
|
||||||
|
|
||||||
|
reg outputs[NVOICES];
|
||||||
|
reg [17:0] count[NVOICES];
|
||||||
|
reg [7:0] register[16];
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
out = 0;
|
||||||
|
for (int i=0; i<NVOICES; i++) begin
|
||||||
|
if (count[i][17:6] == {register[i*2+1][3:0], register[i*2]}) begin
|
||||||
|
outputs[i] <= outputs[i] ^ 1;
|
||||||
|
count[i] <= 0;
|
||||||
|
end else begin
|
||||||
|
count[i] <= count[i] + 1;
|
||||||
|
end
|
||||||
|
/* verilator lint_off BLKSEQ */
|
||||||
|
if (register[15][i] && outputs[i]) begin
|
||||||
|
out = out + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (reg_write) begin
|
||||||
|
register[reg_sel] <= reg_data;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule;
|
||||||
|
|
||||||
|
module music_player(clk, reset, advance,
|
||||||
|
psg_sel, psg_data, psg_write);
|
||||||
|
|
||||||
|
parameter NVOICES = 4;
|
||||||
|
|
||||||
|
input clk, reset;
|
||||||
|
input advance;
|
||||||
|
output [3:0] psg_sel;
|
||||||
|
output [7:0] psg_data;
|
||||||
|
output psg_write;
|
||||||
|
|
||||||
|
//./mknotes.py -m 12 -f 75898
|
||||||
|
// Namespace(bias=0, freq=75898.0, length=64, maxbits=12.0, upper=49)
|
||||||
|
// 434.7 3.23120101673 49
|
||||||
|
|
||||||
|
reg [11:0] note_table[64] = '{
|
||||||
|
2960, 2794, 2637, 2489, 2349, 2217, 2093, 1975,
|
||||||
|
1864, 1760, 1661, 1568, 1480, 1397, 1318, 1244,
|
||||||
|
1175, 1109, 1046, 988, 932, 880, 831, 784,
|
||||||
|
740, 698, 659, 622, 587, 554, 523, 494,
|
||||||
|
466, 440, 415, 392, 370, 349, 330, 311,
|
||||||
|
294, 277, 262, 247, 233, 220, 208, 196,
|
||||||
|
185, 175, 165, 156, 147, 139, 131, 123,
|
||||||
|
117, 110, 104, 98, 92, 87, 82, 78
|
||||||
|
};
|
||||||
|
|
||||||
|
reg [7:0] music_table[292] = '{
|
||||||
|
8'h1e,8'h12,8'h8c,8'h23,8'h17,8'h86,8'h2f,8'h86,8'h36,8'h2a,8'h27,8'h86,8'h2f,8'h86,8'h33,8'h1e,8'h23,8'h86,8'h36,8'h2a,8'h86,8'h24,8'h18,8'h86,8'h2e,8'h86,8'h2a,8'h36,8'h25,8'h86,8'h2e,8'h86,8'h31,8'h28,8'h22,8'h86,8'h36,8'h2a,8'h86,8'h1e,8'h22,8'h28,8'h8c,8'h1e,8'h12,8'h8c,8'h23,8'h17,8'h86,8'h2f,8'h86,8'h36,8'h2a,8'h27,8'h86,8'h2f,8'h86,8'h33,8'h1e,8'h23,8'h86,8'h36,8'h2a,8'h86,8'h24,8'h18,8'h86,8'h2e,8'h86,8'h36,8'h2a,8'h25,8'h86,8'h2e,8'h86,8'h31,8'h28,8'h22,8'h86,8'h36,8'h2a,8'h86,8'h28,8'h22,8'h1e,8'h8c,8'h12,8'h1e,8'h86,8'h36,8'h2a,8'h86,8'h1f,8'h13,8'h86,8'h2f,8'h86,8'h32,8'h86,8'h37,8'h2b,8'h86,8'h1e,8'h12,8'h86,8'h36,8'h2a,8'h86,8'h1e,8'h12,8'h86,8'h2a,8'h36,8'h86,8'h1f,8'h13,8'h86,8'h2f,8'h86,8'h32,8'h86,8'h37,8'h2b,8'h86,8'h1e,8'h12,8'h86,8'h36,8'h2a,8'h92,8'h0b,8'h86,8'h17,8'h86,8'h1a,8'h86,8'h23,8'h86,8'h17,8'h86,8'h23,8'h86,8'h26,8'h86,8'h2f,8'h86,8'h23,8'h86,8'h2f,8'h86,8'h32,8'h86,8'h3b,8'h86,8'h2f,8'h86,8'h3b,8'h86,8'h3e,8'h86,8'h86,8'h3b,8'h29,8'h2c,8'h8c,8'h3b,8'h32,8'h2f,8'h8c,8'h3b,8'h32,8'h2f,8'h8c,8'h3b,8'h29,8'h2c,8'h86,8'h3b,8'h86,8'h33,8'h2f,8'h2a,8'h86,8'h86,8'h33,8'h2f,8'h2a,8'h86,8'h3f,8'h86,8'h2a,8'h2f,8'h33,8'h86,8'h3b,8'h86,8'h33,8'h2f,8'h2a,8'h86,8'h37,8'h3b,8'h86,8'h32,8'h2f,8'h2b,8'h86,8'h3d,8'h86,8'h3e,8'h37,8'h2b,8'h86,8'h3b,8'h86,8'h3d,8'h33,8'h2f,8'h86,8'h3f,8'h36,8'h86,8'h33,8'h2f,8'h2a,8'h86,8'h3b,8'h86,8'h3f,8'h36,8'h33,8'h86,8'h3b,8'h86,8'h3d,8'h36,8'h2a,8'h8c,8'h3b,8'h36,8'h33,8'h92,8'h3b,8'h2f,8'h86,8'h26,8'h23,8'h20,8'h8c,8'h3b,8'h2f,8'h1d,8'h8c,8'h3b,8'h2f,8'h26,8'h8c,8'h3b,8'h2f,8'h26,8'h86,8'h3b,8'h2f,8'h86,8'h1e,8'h23,8'h27,8'h86,8'h36,8'h86,8'h38,8'h2f,8'h27,8'h86,8'h33,8'h86,8'h36,8'h27,8'h23,8'h86,8'h38,8'h2f,8'h86,8'h1e,8'h23,8'h27,8'h86,8'h2f,8'h2b,8'h86,8'h26,8'hff
|
||||||
|
};
|
||||||
|
|
||||||
|
reg [15:0] music_ptr = 0;
|
||||||
|
reg [2:0] freech = 0;
|
||||||
|
reg [7:0] cur_duration = 0;
|
||||||
|
reg [3:0] ch_durations[NVOICES];
|
||||||
|
|
||||||
|
reg [7:0] psg_regs[16];
|
||||||
|
reg [3:0] next_reg;
|
||||||
|
|
||||||
|
wire [7:0] note = music_table[music_ptr[8:0]];
|
||||||
|
wire [11:0] period = note_table[note[5:0]];
|
||||||
|
|
||||||
|
always @(posedge advance or posedge reset) begin
|
||||||
|
if (reset) begin
|
||||||
|
cur_duration <= 0;
|
||||||
|
music_ptr <= 0;
|
||||||
|
psg_regs[15] <= 0;
|
||||||
|
end else if (cur_duration == 0) begin
|
||||||
|
// TODO: 0xff
|
||||||
|
music_ptr <= music_ptr + 1;
|
||||||
|
if (note[7]) begin
|
||||||
|
cur_duration <= note & 63;
|
||||||
|
end else begin
|
||||||
|
psg_regs[freech*2] <= period[7:0];
|
||||||
|
psg_regs[freech*2+1] <= 8'(period[11:8]);
|
||||||
|
ch_durations[freech+0] = 4;
|
||||||
|
psg_regs[15][freech] <= 1;
|
||||||
|
freech <= (freech == NVOICES-1) ? 0 : freech+1;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
cur_duration <= cur_duration - 1;
|
||||||
|
for (int i=0; i<NVOICES; i++) begin
|
||||||
|
if (ch_durations[i] == 0) begin
|
||||||
|
psg_regs[15][i] <= 0;
|
||||||
|
end else begin
|
||||||
|
ch_durations[i] <= ch_durations[i] - 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clk or posedge reset) begin
|
||||||
|
psg_sel <= next_reg;
|
||||||
|
psg_data <= psg_regs[next_reg];
|
||||||
|
psg_write <= 1;
|
||||||
|
next_reg <= next_reg + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule;
|
||||||
|
|
||||||
|
module top(clk, reset, hsync, vsync, rgb, spkr);
|
||||||
|
|
||||||
|
input clk, reset;
|
||||||
|
output hsync, vsync;
|
||||||
|
output [2:0] rgb;
|
||||||
|
output [7:0] spkr;
|
||||||
|
wire display_on;
|
||||||
|
wire [8:0] hpos;
|
||||||
|
wire [8:0] vpos;
|
||||||
|
|
||||||
|
hvsync_generator hvsync_gen(
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
.hsync(hsync),
|
||||||
|
.vsync(vsync),
|
||||||
|
.display_on(display_on),
|
||||||
|
.hpos(hpos),
|
||||||
|
.vpos(vpos)
|
||||||
|
);
|
||||||
|
|
||||||
|
wire r = display_on && spkr[2];
|
||||||
|
wire g = display_on && spkr[1];
|
||||||
|
wire b = display_on && spkr[0];
|
||||||
|
assign rgb = {b,g,r};
|
||||||
|
|
||||||
|
reg [3:0] sel;
|
||||||
|
reg [7:0] data;
|
||||||
|
reg write = 0;
|
||||||
|
|
||||||
|
sound_psg psg(
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
.reg_sel(sel),
|
||||||
|
.reg_data(data),
|
||||||
|
.reg_write(write),
|
||||||
|
.out(spkr));
|
||||||
|
|
||||||
|
music_player player(
|
||||||
|
.clk(hsync),
|
||||||
|
.reset(reset),
|
||||||
|
.advance(vsync),
|
||||||
|
.psg_sel(sel),
|
||||||
|
.psg_data(data),
|
||||||
|
.psg_write(write)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
84
presets/verilog/nano8.cfg
Normal file
84
presets/verilog/nano8.cfg
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
; Architecture file for the NANO8
|
||||||
|
|
||||||
|
; default output format is a memory initialization file
|
||||||
|
.outfmt mif
|
||||||
|
|
||||||
|
; mif file is this big
|
||||||
|
.mifwords 256
|
||||||
|
.mifwidth 8
|
||||||
|
|
||||||
|
; Opcodes for core instruction set
|
||||||
|
.define A 0
|
||||||
|
.define B 1
|
||||||
|
.define IP 2
|
||||||
|
.define NOP 3
|
||||||
|
|
||||||
|
.define ADD 8
|
||||||
|
|
||||||
|
; ALU A + B -> dest
|
||||||
|
mova 2 { 00 (0) 0000 }
|
||||||
|
movb 2 { 00 (0) 0001 }
|
||||||
|
inc 2 { 00 (0) 0010 }
|
||||||
|
dec 2 { 00 (0) 0011 }
|
||||||
|
or 2 { 00 (0) 0100 }
|
||||||
|
and 2 { 00 (0) 0101 }
|
||||||
|
xor 2 { 00 (0) 0110 }
|
||||||
|
zero 2 { 00 (0) 0111 }
|
||||||
|
add 2 { 00 (0) 1000 }
|
||||||
|
sub 2 { 00 (0) 1001 }
|
||||||
|
asl 2 { 00 (0) 1010 }
|
||||||
|
lsr 2 { 00 (0) 1011 }
|
||||||
|
adc 2 { 00 (0) 1100 }
|
||||||
|
sbb 2 { 00 (0) 1101 }
|
||||||
|
rol 2 { 00 (0) 1110 }
|
||||||
|
ror 2 { 00 (0) 1111 }
|
||||||
|
|
||||||
|
; ALU A + immediate -> dest
|
||||||
|
movi 2 8 { 01 (0) 0001 (1) }
|
||||||
|
ori 2 8 { 01 (0) 0100 (1) }
|
||||||
|
andi 2 8 { 01 (0) 0101 (1) }
|
||||||
|
xori 2 8 { 01 (0) 0110 (1) }
|
||||||
|
addi 2 8 { 01 (0) 1000 (1) }
|
||||||
|
subi 2 8 { 01 (0) 1001 (1) }
|
||||||
|
asli 2 8 { 01 (0) 1010 (1) }
|
||||||
|
lsri 2 8 { 01 (0) 1011 (1) }
|
||||||
|
adci 2 8 { 01 (0) 1100 (1) }
|
||||||
|
sbbi 2 8 { 01 (0) 1101 (1) }
|
||||||
|
roli 2 8 { 01 (0) 1110 (1) }
|
||||||
|
rori 2 8 { 01 (0) 1111 (1) }
|
||||||
|
|
||||||
|
; ALU A + read [B] -> dest
|
||||||
|
movrb 2 { 11 (0) 0001 }
|
||||||
|
orrb 2 { 11 (0) 0100 }
|
||||||
|
andrb 2 { 11 (0) 0101 }
|
||||||
|
xorrb 2 { 11 (0) 0110 }
|
||||||
|
addrb 2 { 11 (0) 1000 }
|
||||||
|
subrb 2 { 11 (0) 1001 }
|
||||||
|
aslrb 2 { 11 (0) 1010 }
|
||||||
|
lsrrb 2 { 11 (0) 1011 }
|
||||||
|
adcrb 2 { 11 (0) 1100 }
|
||||||
|
sbbrb 2 { 11 (0) 1101 }
|
||||||
|
rolrb 2 { 11 (0) 1110 }
|
||||||
|
rorrb 2 { 11 (0) 1111 }
|
||||||
|
|
||||||
|
; A -> write [nnnn]
|
||||||
|
sta 4 { 1001 (0) }
|
||||||
|
|
||||||
|
; other insns
|
||||||
|
clc { 10001000 }
|
||||||
|
swapab { 10000001 }
|
||||||
|
reset { 10001111 }
|
||||||
|
|
||||||
|
lda 8 { 01 00 0001 (0) }
|
||||||
|
ldb 8 { 01 01 0001 (0) }
|
||||||
|
jmp 8 { 01 10 0001 (0) }
|
||||||
|
|
||||||
|
; conditional branch
|
||||||
|
bcc 8 { 1010 0001 (0) }
|
||||||
|
bcs 8 { 1010 0011 (0) }
|
||||||
|
bz 8 { 1010 0100 (0) }
|
||||||
|
bnz 8 { 1010 1100 (0) }
|
||||||
|
|
||||||
|
|
||||||
|
; allow raw byte positioning
|
||||||
|
byte 8 { (0) } ; One byte constant
|
265
presets/verilog/race_game_cpu.v
Normal file
265
presets/verilog/race_game_cpu.v
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
`include "hvsync_generator.v"
|
||||||
|
`include "sprite_renderer.v"
|
||||||
|
`include "cpu8.v"
|
||||||
|
|
||||||
|
// uncomment to see scope view
|
||||||
|
//`define DEBUG
|
||||||
|
|
||||||
|
module sprite_multiple_top(clk, reset, hsync, vsync, hpaddle, vpaddle,
|
||||||
|
address_bus, to_cpu, from_cpu, write_enable
|
||||||
|
`ifdef DEBUG
|
||||||
|
, output [7:0] A
|
||||||
|
, output [7:0] B
|
||||||
|
, output [7:0] IP
|
||||||
|
, output carry
|
||||||
|
, output zero
|
||||||
|
`else
|
||||||
|
, output [2:0] rgb
|
||||||
|
`endif
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk, reset;
|
||||||
|
input hpaddle, vpaddle;
|
||||||
|
output hsync, vsync;
|
||||||
|
wire display_on;
|
||||||
|
wire [8:0] hpos;
|
||||||
|
wire [8:0] vpos;
|
||||||
|
`ifdef DEBUG
|
||||||
|
wire [2:0] rgb;
|
||||||
|
assign IP = cpu.IP;
|
||||||
|
assign A = cpu.A;
|
||||||
|
assign B = cpu.B;
|
||||||
|
assign carry = cpu.carry;
|
||||||
|
assign zero = cpu.zero;
|
||||||
|
`endif
|
||||||
|
|
||||||
|
parameter PADDLE_X = 0;
|
||||||
|
parameter PADDLE_Y = 1;
|
||||||
|
parameter PLAYER_X = 2;
|
||||||
|
parameter PLAYER_Y = 3;
|
||||||
|
parameter ENEMY_X = 4;
|
||||||
|
parameter ENEMY_Y = 5;
|
||||||
|
parameter ENEMY_DIR = 6;
|
||||||
|
parameter SPEED = 7;
|
||||||
|
parameter TRACKPOS_LO = 8;
|
||||||
|
parameter TRACKPOS_HI = 9;
|
||||||
|
|
||||||
|
parameter IN_HPOS = 8'b01000000;
|
||||||
|
parameter IN_VPOS = 8'b01000001;
|
||||||
|
parameter IN_FLAGS = 8'b01000010;
|
||||||
|
|
||||||
|
reg [7:0] ram[0:63];
|
||||||
|
reg [7:0] rom[0:127];
|
||||||
|
|
||||||
|
output wire [7:0] address_bus;
|
||||||
|
output reg [7:0] to_cpu;
|
||||||
|
output wire [7:0] from_cpu;
|
||||||
|
output wire write_enable;
|
||||||
|
|
||||||
|
CPU cpu(.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
.address(address_bus),
|
||||||
|
.data_in(to_cpu),
|
||||||
|
.data_out(from_cpu),
|
||||||
|
.write(write_enable));
|
||||||
|
|
||||||
|
always @(posedge clk)
|
||||||
|
if (write_enable)
|
||||||
|
ram[address_bus[5:0]] <= from_cpu;
|
||||||
|
|
||||||
|
always @(*)
|
||||||
|
casez (address_bus)
|
||||||
|
// RAM
|
||||||
|
8'b00??????: to_cpu = ram[address_bus[5:0]];
|
||||||
|
// special read registers
|
||||||
|
IN_HPOS: to_cpu = hpos[7:0];
|
||||||
|
IN_VPOS: to_cpu = vpos[7:0];
|
||||||
|
IN_FLAGS: to_cpu = {2'b0, frame_collision,
|
||||||
|
vsync, hsync, vpaddle, hpaddle, display_on};
|
||||||
|
// ROM
|
||||||
|
8'b1???????: to_cpu = rom[address_bus[6:0]];
|
||||||
|
default: ;
|
||||||
|
endcase
|
||||||
|
|
||||||
|
hvsync_generator hvsync_gen(
|
||||||
|
.clk(clk),
|
||||||
|
.reset(0),
|
||||||
|
.hsync(hsync),
|
||||||
|
.vsync(vsync),
|
||||||
|
.display_on(display_on),
|
||||||
|
.hpos(hpos),
|
||||||
|
.vpos(vpos)
|
||||||
|
);
|
||||||
|
|
||||||
|
wire player_vstart = {1'0,ram[PLAYER_Y]} == vpos;
|
||||||
|
wire player_hstart = {1'0,ram[PLAYER_X]} == hpos;
|
||||||
|
wire player_gfx;
|
||||||
|
wire player_is_drawing;
|
||||||
|
|
||||||
|
wire enemy_vstart = {1'0,ram[ENEMY_Y]} == vpos;
|
||||||
|
wire enemy_hstart = {1'0,ram[ENEMY_X]} == hpos;
|
||||||
|
wire enemy_gfx;
|
||||||
|
wire enemy_is_drawing;
|
||||||
|
|
||||||
|
wire [3:0] car_sprite_yofs;
|
||||||
|
wire [7:0] car_sprite_bits;
|
||||||
|
|
||||||
|
car_bitmap car(
|
||||||
|
.yofs(car_sprite_yofs),
|
||||||
|
.bits(car_sprite_bits));
|
||||||
|
|
||||||
|
sprite_renderer player_renderer(
|
||||||
|
.clk(clk),
|
||||||
|
.vstart(player_vstart),
|
||||||
|
.hstart(player_hstart),
|
||||||
|
.load(hpos == 256), //TODO?
|
||||||
|
.rom_addr(car_sprite_yofs),
|
||||||
|
.rom_bits(car_sprite_bits),
|
||||||
|
.gfx(player_gfx),
|
||||||
|
.in_progress(player_is_drawing));
|
||||||
|
|
||||||
|
sprite_renderer enemy_renderer(
|
||||||
|
.clk(clk),
|
||||||
|
.vstart(enemy_vstart),
|
||||||
|
.hstart(enemy_hstart),
|
||||||
|
.load(hpos == 260), //TODO?
|
||||||
|
.rom_addr(car_sprite_yofs),
|
||||||
|
.rom_bits(car_sprite_bits),
|
||||||
|
.gfx(enemy_gfx),
|
||||||
|
.in_progress(player_is_drawing));
|
||||||
|
|
||||||
|
/*
|
||||||
|
always @(posedge hsync)
|
||||||
|
begin
|
||||||
|
if (!hpaddle) ram[PADDLE_X] <= vpos[7:0];
|
||||||
|
if (!vpaddle) ram[PADDLE_Y] <= vpos[7:0];
|
||||||
|
end
|
||||||
|
|
||||||
|
wire enemy_hit_left = (enemy_x == 64);
|
||||||
|
wire enemy_hit_right = (enemy_x == 192);
|
||||||
|
wire enemy_hit_edge = enemy_hit_left || enemy_hit_right;
|
||||||
|
|
||||||
|
always @(posedge vsync)
|
||||||
|
begin
|
||||||
|
player_x <= paddle_x;
|
||||||
|
player_y <= 180;
|
||||||
|
track_pos <= track_pos + {11'b0,speed[7:4]};
|
||||||
|
enemy_y <= enemy_y + {3'b0, speed[7:4]};
|
||||||
|
if (enemy_hit_edge)
|
||||||
|
enemy_dir <= !enemy_dir;
|
||||||
|
if (enemy_dir ^ enemy_hit_edge)
|
||||||
|
enemy_x <= enemy_x + 1;
|
||||||
|
else
|
||||||
|
enemy_x <= enemy_x - 1;
|
||||||
|
// collision check?
|
||||||
|
if (frame_collision)
|
||||||
|
speed <= 16;
|
||||||
|
else if (speed < ~paddle_y)
|
||||||
|
speed <= speed + 1;
|
||||||
|
else
|
||||||
|
speed <= speed - 1;
|
||||||
|
end
|
||||||
|
*/
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
rom = '{
|
||||||
|
// initialize registers
|
||||||
|
`I_CONST_IMM_A,
|
||||||
|
128,
|
||||||
|
`I_STORE_A(PLAYER_X),
|
||||||
|
`I_STORE_A(ENEMY_X),
|
||||||
|
`I_STORE_A(ENEMY_Y),
|
||||||
|
`I_CONST_IMM_A,
|
||||||
|
180,
|
||||||
|
`I_STORE_A(PLAYER_Y),
|
||||||
|
`I_ZERO_A,
|
||||||
|
`I_STORE_A(SPEED),
|
||||||
|
// test hpaddle flag
|
||||||
|
`I_CONST_IMM_A,
|
||||||
|
8'b00000010,
|
||||||
|
`I_CONST_IMM_B,
|
||||||
|
IN_FLAGS,
|
||||||
|
`I_COMPUTE_READB(DEST_NOP, OP_AND),
|
||||||
|
`I_BRANCH_IF_ZERO(1),
|
||||||
|
128+10,
|
||||||
|
// [vpos] -> paddle_x
|
||||||
|
`I_CONST_IMM_B,
|
||||||
|
IN_VPOS,
|
||||||
|
`I_COMPUTE_READB(DEST_A, OP_LOAD_B),
|
||||||
|
`I_STORE_A(PLAYER_X),
|
||||||
|
// wait for vsync=1 then vsync=0
|
||||||
|
`I_CONST_IMM_A,
|
||||||
|
8'b00010000,
|
||||||
|
`I_CONST_IMM_B,
|
||||||
|
IN_FLAGS,
|
||||||
|
`I_COMPUTE_READB(DEST_NOP, OP_AND),
|
||||||
|
`I_BRANCH_IF_ZERO(1),
|
||||||
|
128+25,
|
||||||
|
`I_COMPUTE_READB(DEST_NOP, OP_AND),
|
||||||
|
`I_BRANCH_IF_ZERO(0),
|
||||||
|
128+28,
|
||||||
|
// check collision
|
||||||
|
`I_CONST_IMM_A,
|
||||||
|
8'b00100000,
|
||||||
|
`I_CONST_IMM_B,
|
||||||
|
IN_FLAGS,
|
||||||
|
`I_COMPUTE_READB(DEST_NOP, OP_AND),
|
||||||
|
`I_BRANCH_IF_ZERO(1),
|
||||||
|
128+41,
|
||||||
|
// load slow speed
|
||||||
|
`I_CONST_IMM_A,
|
||||||
|
16,
|
||||||
|
`I_STORE_A(SPEED),
|
||||||
|
// update speed
|
||||||
|
`I_CONST_IMM_B,
|
||||||
|
SPEED,
|
||||||
|
`I_COMPUTE_READB(DEST_A, OP_LOAD_B),
|
||||||
|
`I_COMPUTE(DEST_A, OP_INC),
|
||||||
|
// don't store if == 0
|
||||||
|
`I_BRANCH_IF_ZERO(1),
|
||||||
|
128+48,
|
||||||
|
`I_STORE_A(SPEED),
|
||||||
|
// branch target
|
||||||
|
`I_COMPUTE_READB(DEST_A, OP_LOAD_B),
|
||||||
|
`I_COMPUTE(DEST_A, OP_LSR),
|
||||||
|
`I_COMPUTE(DEST_A, OP_LSR),
|
||||||
|
`I_COMPUTE(DEST_A, OP_LSR),
|
||||||
|
`I_COMPUTE(DEST_A, OP_LSR),
|
||||||
|
// add to lo byte of track pos
|
||||||
|
`I_CONST_IMM_B,
|
||||||
|
TRACKPOS_LO,
|
||||||
|
`I_COMPUTE_READB(DEST_B, OP_ADD),
|
||||||
|
`I_SWAP_AB,
|
||||||
|
`I_STORE_A(TRACKPOS_LO),
|
||||||
|
`I_SWAP_AB,
|
||||||
|
// update enemy vert pos
|
||||||
|
`I_CONST_IMM_B,
|
||||||
|
ENEMY_Y,
|
||||||
|
`I_COMPUTE_READB(DEST_A, OP_ADD),
|
||||||
|
`I_STORE_A(ENEMY_Y),
|
||||||
|
// repeat main loop
|
||||||
|
`I_JUMP_IMM,
|
||||||
|
128+10,
|
||||||
|
// leftover elements
|
||||||
|
63{0}
|
||||||
|
};
|
||||||
|
end
|
||||||
|
|
||||||
|
reg frame_collision;
|
||||||
|
|
||||||
|
always @(posedge clk)
|
||||||
|
if (player_gfx && (enemy_gfx || track_gfx))
|
||||||
|
frame_collision <= 1;
|
||||||
|
else if (vpos==0)
|
||||||
|
frame_collision <= 0;
|
||||||
|
|
||||||
|
wire track_offside = (hpos[7:5]==0) || (hpos[7:5]==7);
|
||||||
|
wire track_shoulder = (hpos[7:3]==3) || (hpos[7:3]==28);
|
||||||
|
wire track_gfx = (vpos[5:1]!=ram[TRACKPOS_LO][5:1]) && track_offside;
|
||||||
|
|
||||||
|
wire r = display_on && (player_gfx || enemy_gfx || track_shoulder);
|
||||||
|
wire g = display_on && (player_gfx || track_gfx);
|
||||||
|
wire b = display_on && (enemy_gfx || track_shoulder);
|
||||||
|
assign rgb = {b,g,r};
|
||||||
|
|
||||||
|
endmodule
|
27
src/audio.js
27
src/audio.js
|
@ -311,11 +311,11 @@ var SampleAudio = function(clockfreq) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var sfrac, sinc, accum;
|
var sfrac, sinc, accum;
|
||||||
var buffer, bufpos, bufferlist;
|
var buffer, bufpos, bufferlist;
|
||||||
|
var idrain, ifill;
|
||||||
|
|
||||||
function mix(ape) {
|
function mix(ape) {
|
||||||
var buflen=ape.outputBuffer.length;
|
var buflen=ape.outputBuffer.length;
|
||||||
var lbuf = ape.outputBuffer.getChannelData(0);
|
var lbuf = ape.outputBuffer.getChannelData(0);
|
||||||
//var rbuf = ape.outputBuffer.getChannelData(1);
|
|
||||||
var m = this.module;
|
var m = this.module;
|
||||||
if (!m) m = ape.srcElement.module;
|
if (!m) m = ape.srcElement.module;
|
||||||
if (!m) return;
|
if (!m) return;
|
||||||
|
@ -323,10 +323,12 @@ var SampleAudio = function(clockfreq) {
|
||||||
m.callback(lbuf);
|
m.callback(lbuf);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
var buf = bufferlist[1];
|
var buf = bufferlist[idrain];
|
||||||
for (var i=0; i<lbuf.length; i++) {
|
for (var i=0; i<lbuf.length; i++) {
|
||||||
lbuf[i] = buf[i];
|
lbuf[i] = buf[i];
|
||||||
|
//lbuf[i] = (i&128) ? 1.0 : 0.33;
|
||||||
}
|
}
|
||||||
|
idrain = (idrain + 1) % bufferlist.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,11 +345,7 @@ var SampleAudio = function(clockfreq) {
|
||||||
// Amiga 500 fixed filter at 6kHz. WebAudio lowpass is 12dB/oct, whereas
|
// Amiga 500 fixed filter at 6kHz. WebAudio lowpass is 12dB/oct, whereas
|
||||||
// older Amigas had a 6dB/oct filter at 4900Hz.
|
// older Amigas had a 6dB/oct filter at 4900Hz.
|
||||||
self.filterNode=self.context.createBiquadFilter();
|
self.filterNode=self.context.createBiquadFilter();
|
||||||
if (self.amiga500) {
|
self.filterNode.frequency.value=6000;
|
||||||
self.filterNode.frequency.value=6000;
|
|
||||||
} else {
|
|
||||||
self.filterNode.frequency.value=28867;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "LED filter" at 3275kHz - off by default
|
// "LED filter" at 3275kHz - off by default
|
||||||
self.lowpassNode=self.context.createBiquadFilter();
|
self.lowpassNode=self.context.createBiquadFilter();
|
||||||
|
@ -381,7 +379,9 @@ var SampleAudio = function(clockfreq) {
|
||||||
accum = 0;
|
accum = 0;
|
||||||
bufpos = 0;
|
bufpos = 0;
|
||||||
bufferlist = [];
|
bufferlist = [];
|
||||||
for (var i=0; i<2; i++) {
|
idrain = 1;
|
||||||
|
ifill = 0;
|
||||||
|
for (var i=0; i<3; i++) {
|
||||||
var arrbuf = new ArrayBuffer(self.bufferlen*4);
|
var arrbuf = new ArrayBuffer(self.bufferlen*4);
|
||||||
bufferlist[i] = new Float32Array(arrbuf);
|
bufferlist[i] = new Float32Array(arrbuf);
|
||||||
}
|
}
|
||||||
|
@ -400,8 +400,10 @@ var SampleAudio = function(clockfreq) {
|
||||||
buffer[bufpos++] = value;
|
buffer[bufpos++] = value;
|
||||||
if (bufpos >= buffer.length) {
|
if (bufpos >= buffer.length) {
|
||||||
bufpos = 0;
|
bufpos = 0;
|
||||||
bufferlist[0] = bufferlist[1];
|
bufferlist[ifill] = buffer;
|
||||||
bufferlist[1] = buffer;
|
var inext = (ifill + 1) % bufferlist.length;
|
||||||
|
if (inext != idrain) ifill = inext;
|
||||||
|
buffer = bufferlist[ifill];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,8 +413,9 @@ var SampleAudio = function(clockfreq) {
|
||||||
sfrac += sinc;
|
sfrac += sinc;
|
||||||
if (sfrac >= 1) {
|
if (sfrac >= 1) {
|
||||||
sfrac -= 1;
|
sfrac -= 1;
|
||||||
accum = 0;
|
value *= sfrac;
|
||||||
this.addSingleSample(accum / sfrac);
|
this.addSingleSample(accum - value);
|
||||||
|
accum = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,7 +181,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
var idata, timer;
|
var idata, timer;
|
||||||
var gen;
|
var gen;
|
||||||
var frameRate = 60;
|
var frameRate = 60;
|
||||||
var AUDIO_FREQ = 15750;
|
var AUDIO_FREQ = (256+23+7+23)*262*60; // 4857480
|
||||||
var current_output;
|
var current_output;
|
||||||
var paddle_x = 0;
|
var paddle_x = 0;
|
||||||
var paddle_y = 0;
|
var paddle_y = 0;
|
||||||
|
@ -219,7 +219,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
|
|
||||||
function vidtick() {
|
function vidtick() {
|
||||||
gen.tick2();
|
gen.tick2();
|
||||||
audio.addSingleSample(0+gen.spkr); // TODO: sync with audio freq
|
audio.feedSample((gen.spkr&255)*(1.0/255.0), 1);
|
||||||
if (debugCond && debugCond()) debugCond = null;
|
if (debugCond && debugCond()) debugCond = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user