mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-04-04 05:30:20 +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 sfrac, sinc, accum;
|
||||
var buffer, bufpos, bufferlist;
|
||||
var idrain, ifill;
|
||||
|
||||
function mix(ape) {
|
||||
var buflen=ape.outputBuffer.length;
|
||||
var lbuf = ape.outputBuffer.getChannelData(0);
|
||||
//var rbuf = ape.outputBuffer.getChannelData(1);
|
||||
var m = this.module;
|
||||
if (!m) m = ape.srcElement.module;
|
||||
if (!m) return;
|
||||
@ -323,10 +323,12 @@ var SampleAudio = function(clockfreq) {
|
||||
m.callback(lbuf);
|
||||
return;
|
||||
} else {
|
||||
var buf = bufferlist[1];
|
||||
var buf = bufferlist[idrain];
|
||||
for (var i=0; i<lbuf.length; 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
|
||||
// older Amigas had a 6dB/oct filter at 4900Hz.
|
||||
self.filterNode=self.context.createBiquadFilter();
|
||||
if (self.amiga500) {
|
||||
self.filterNode.frequency.value=6000;
|
||||
} else {
|
||||
self.filterNode.frequency.value=28867;
|
||||
}
|
||||
self.filterNode.frequency.value=6000;
|
||||
|
||||
// "LED filter" at 3275kHz - off by default
|
||||
self.lowpassNode=self.context.createBiquadFilter();
|
||||
@ -381,7 +379,9 @@ var SampleAudio = function(clockfreq) {
|
||||
accum = 0;
|
||||
bufpos = 0;
|
||||
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);
|
||||
bufferlist[i] = new Float32Array(arrbuf);
|
||||
}
|
||||
@ -400,8 +400,10 @@ var SampleAudio = function(clockfreq) {
|
||||
buffer[bufpos++] = value;
|
||||
if (bufpos >= buffer.length) {
|
||||
bufpos = 0;
|
||||
bufferlist[0] = bufferlist[1];
|
||||
bufferlist[1] = buffer;
|
||||
bufferlist[ifill] = 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;
|
||||
if (sfrac >= 1) {
|
||||
sfrac -= 1;
|
||||
accum = 0;
|
||||
this.addSingleSample(accum / sfrac);
|
||||
value *= sfrac;
|
||||
this.addSingleSample(accum - value);
|
||||
accum = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
var idata, timer;
|
||||
var gen;
|
||||
var frameRate = 60;
|
||||
var AUDIO_FREQ = 15750;
|
||||
var AUDIO_FREQ = (256+23+7+23)*262*60; // 4857480
|
||||
var current_output;
|
||||
var paddle_x = 0;
|
||||
var paddle_y = 0;
|
||||
@ -219,7 +219,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
|
||||
function vidtick() {
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user