mirror of
https://github.com/UzixLS/zx-sizif-xxs.git
synced 2025-07-19 07:11:28 +03:00
merge latest changes from sizif-512
* add 4.4 MHz and 5.2 MHz turbo modes * handle magic key press if initialization wasn't completed before * replace 'timings', 'ram', 'plus3' settings with one 'machine' setting * refactor memory controller * significantly improve classic timings * magic rom: fix 'h' font character * fix hanging of esxdos browser after magic key double press * enable divmmc (esxdos OS) by magic rom on poweron; add NO-OS option * improve pause ('f12' on ps/2 keyboard or 'start' on gamepad) * magic rom: handle C-key on sega gamepad as exit
This commit is contained in:
@ -1,7 +1,8 @@
|
||||
package common;
|
||||
typedef enum { TIMINGS_PENT, TIMINGS_S48, TIMINGS_S128 } timings_t;
|
||||
typedef enum { TURBO_NONE, TURBO_7, TURBO_14 } turbo_t;
|
||||
typedef enum { RAM_512, RAM_48, RAM_128 } rammode_t;
|
||||
typedef enum { MACHINE_S48, MACHINE_S128, MACHINE_S3, MACHINE_PENT } machine_t;
|
||||
typedef enum { TURBO_NONE, TURBO_4, TURBO_5, TURBO_7, TURBO_14 } turbo_t;
|
||||
typedef enum { PANNING_MONO, PANNING_ABC, PANNING_ACB } panning_t;
|
||||
typedef enum { DIVMMC_OFF, DIVMMC_ON, DIVMMC_NOOS } divmmc_t;
|
||||
endpackage
|
||||
|
||||
|
||||
|
@ -5,16 +5,17 @@ module cpucontrol(
|
||||
input clk14,
|
||||
input clk7,
|
||||
input clk35,
|
||||
input ck14,
|
||||
input ck7,
|
||||
|
||||
cpu_bus bus,
|
||||
|
||||
input [8:0] vc,
|
||||
input [8:0] hc,
|
||||
input screen_contention,
|
||||
input [2:0] rampage128,
|
||||
input screen_loading,
|
||||
input machine_t machine,
|
||||
input turbo_t turbo,
|
||||
input timings_t timings,
|
||||
input pause,
|
||||
input ext_wait_cycle,
|
||||
input init_done_in,
|
||||
|
||||
@ -29,17 +30,19 @@ module cpucontrol(
|
||||
|
||||
|
||||
/* CONTENTION */
|
||||
wire iorq_contended = bus.iorq && (~bus.a[0] || (~bus.a[1] && ~bus.a[15]));
|
||||
reg mreq_delayed, iorq_delayed;
|
||||
always @(posedge clkcpu)
|
||||
mreq_delayed <= bus.mreq;
|
||||
always @(posedge clkcpu)
|
||||
iorq_delayed <= bus.iorq;
|
||||
wire contention_mem_addr = bus.a[14] & (~bus.a[15] | (bus.a[15] & rampage128[0]));
|
||||
iorq_delayed <= iorq_contended;
|
||||
wire contention_mem_page = (machine == MACHINE_S3)? rampage128[2] : rampage128[0];
|
||||
wire contention_mem_addr = bus.a[14] & (~bus.a[15] | (bus.a[15] & contention_mem_page));
|
||||
wire contention_mem = iorq_delayed == 1'b0 && mreq_delayed == 1'b0 && contention_mem_addr;
|
||||
wire contention_io = iorq_delayed == 1'b0 && bus.iorq;
|
||||
wire contention0 = screen_loading && (hc[2] || hc[3]) && (contention_mem || contention_io);
|
||||
wire contention = clkcpu && contention0 && turbo == TURBO_NONE && timings != TIMINGS_PENT;
|
||||
assign snow = (timings != TIMINGS_PENT) && bus.a[14] && ~bus.a[15] && bus.rfsh;
|
||||
wire contention_io = iorq_delayed == 1'b0 && iorq_contended;
|
||||
wire contention0 = screen_contention && (contention_mem || contention_io);
|
||||
wire contention = clkcpu && contention0 && turbo == TURBO_NONE && (machine == MACHINE_S48 || machine == MACHINE_S128 || machine == MACHINE_S3);
|
||||
assign snow = bus.a[14] && ~bus.a[15] && bus.rfsh && (machine == MACHINE_S48 || machine == MACHINE_S128);
|
||||
|
||||
|
||||
/* CLOCK */
|
||||
@ -47,35 +50,47 @@ reg [2:0] turbo_wait;
|
||||
wire turbo_wait_trig0 = bus.rd || bus.wr;
|
||||
reg turbo_wait_trig1;
|
||||
always @(posedge clk28) begin
|
||||
turbo_wait_trig1 <= turbo_wait_trig0;
|
||||
turbo_wait[0] <= turbo == TURBO_14 && turbo_wait_trig0 && !turbo_wait_trig1;
|
||||
turbo_wait[1] <= turbo_wait[0] && (bus.iorq || ext_wait_cycle);
|
||||
turbo_wait[2] <= turbo_wait[1];
|
||||
turbo_wait_trig1 <= turbo_wait_trig0;
|
||||
end
|
||||
|
||||
reg clkcpu_prev;
|
||||
assign clkcpu_ck = clkcpu && ! clkcpu_prev;
|
||||
assign clkwait = pause || contention || (|turbo_wait);
|
||||
always @(negedge clk28) begin
|
||||
assign clkcpu_ck = clkcpu && !clkcpu_prev;
|
||||
assign clkwait = contention || (|turbo_wait);
|
||||
always @(posedge clk28) begin
|
||||
clkcpu_prev <= clkcpu;
|
||||
clkcpu <= clkwait? clkcpu : (turbo == TURBO_14)? clk14 : (turbo == TURBO_7)? clk7 : clk35;
|
||||
if (clkwait)
|
||||
clkcpu <= clkcpu;
|
||||
else if (turbo == TURBO_14)
|
||||
clkcpu <= clk14;
|
||||
else if (turbo == TURBO_7 && ck14)
|
||||
clkcpu <= clk7;
|
||||
else if (turbo == TURBO_5 && ck14 && hc[1])
|
||||
clkcpu <= clk7;
|
||||
else if (turbo == TURBO_4 && ck14 && hc[1] && hc[2])
|
||||
clkcpu <= clk7;
|
||||
else if (ck7)
|
||||
clkcpu <= clk35;
|
||||
end
|
||||
|
||||
|
||||
/* INT GENERATOR */
|
||||
localparam INT_V_S48 = 247;
|
||||
localparam INT_H_S48 = 442;
|
||||
localparam INT_V_S128 = 247;
|
||||
localparam INT_H_S128 = 450;
|
||||
localparam INT_V_S48 = 248;
|
||||
localparam INT_H_S48 = 0;
|
||||
localparam INT_V_S128 = 248;
|
||||
localparam INT_H_S128 = 4;
|
||||
localparam INT_V_PENT = 239;
|
||||
localparam INT_H_PENT = 316;
|
||||
localparam INT_H_PENT = 322;
|
||||
wire int_begin =
|
||||
(timings == TIMINGS_PENT)?
|
||||
vc == INT_V_PENT && hc == INT_H_PENT :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
vc == INT_V_S48 && hc == INT_H_S48 :
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
vc == INT_V_S128 && hc == INT_H_S128 :
|
||||
// 48K
|
||||
vc == INT_V_S48 && hc == INT_H_S48 ;
|
||||
// Pentagon
|
||||
vc == INT_V_PENT && hc == INT_H_PENT ;
|
||||
|
||||
reg [4:0] int_cnt;
|
||||
assign n_int_next = (|int_cnt)? 1'b0 : 1'b1;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
@ -98,9 +113,25 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
n_rstcpu <= 0;
|
||||
else if (!init_done_in)
|
||||
n_rstcpu <= 0;
|
||||
else if (vc[0])
|
||||
`ifdef TESTBENCH
|
||||
else if (hc[4])
|
||||
n_rstcpu <= 1'b1;
|
||||
`endif
|
||||
else if (vc[8])
|
||||
n_rstcpu <= 1'b1;
|
||||
end
|
||||
|
||||
|
||||
/* T-STATES COUNTER (for debug) */
|
||||
`ifdef TESTBENCH
|
||||
integer tstate;
|
||||
always @(posedge clkcpu) begin
|
||||
if (!n_int_next && n_int)
|
||||
tstate <= -1;
|
||||
else
|
||||
tstate <= tstate + 1;
|
||||
end
|
||||
`endif
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -20,25 +20,26 @@ module divmmc(
|
||||
input magic_mode,
|
||||
input magic_map,
|
||||
|
||||
output reg [3:0] div_page,
|
||||
output div_map,
|
||||
output div_ram,
|
||||
output div_ramwr_mask,
|
||||
output div_wait
|
||||
output reg [3:0] page,
|
||||
output map,
|
||||
output reg automap,
|
||||
output ram,
|
||||
output ramwr_mask,
|
||||
output cpuwait
|
||||
);
|
||||
|
||||
reg div_automap, div_automap_next;
|
||||
reg automap_next;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
div_automap_next <= 0;
|
||||
div_automap <= 0;
|
||||
automap_next <= 0;
|
||||
automap <= 0;
|
||||
end
|
||||
else if (bus.m1 && bus.memreq && magic_map == 0) begin
|
||||
else if (bus.m1 && bus.memreq && !magic_map) begin
|
||||
if (!en_hooks || !en || rammap) begin
|
||||
div_automap_next <= 0;
|
||||
automap_next <= 0;
|
||||
end
|
||||
else if (bus.a_reg[15:3] == 13'h3FF) begin // exit vectors 1FF8-1FFF
|
||||
div_automap_next <= 0;
|
||||
automap_next <= 0;
|
||||
end
|
||||
else if (
|
||||
bus.a_reg == 16'h0000 || // power-on/reset/rst0/software restart
|
||||
@ -48,37 +49,37 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
bus.a_reg == 16'h04C6 || // tape save routine
|
||||
bus.a_reg == 16'h0562 // tape load and verify routine
|
||||
) begin
|
||||
div_automap_next <= 1'b1;
|
||||
automap_next <= 1'b1;
|
||||
end
|
||||
else if (bus.a_reg[15:8] == 8'h3D) begin // tr-dos mapping area
|
||||
div_automap_next <= 1'b1;
|
||||
div_automap <= 1'b1;
|
||||
automap_next <= 1'b1;
|
||||
automap <= 1'b1;
|
||||
end
|
||||
end
|
||||
else if (!bus.m1) begin
|
||||
div_automap <= div_automap_next;
|
||||
automap <= automap_next;
|
||||
end
|
||||
end
|
||||
|
||||
reg spi_rd;
|
||||
reg div_conmem, div_mapram;
|
||||
reg conmem, mapram;
|
||||
wire port_e3_cs = en && bus.ioreq && bus.a_reg[7:0] == 8'hE3;
|
||||
wire port_e7_cs = en && bus.ioreq && bus.a_reg[7:0] == 8'hE7;
|
||||
wire port_eb_cs = en && bus.ioreq && bus.a_reg[7:0] == 8'hEB;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
spi_rd <= 0;
|
||||
div_page <= 0;
|
||||
div_mapram <= 0;
|
||||
div_conmem <= 0;
|
||||
page <= 0;
|
||||
mapram <= 0;
|
||||
conmem <= 0;
|
||||
sd_cs <= 1'b1;
|
||||
end
|
||||
else begin
|
||||
spi_rd <= port_eb_cs && bus.rd;
|
||||
if (port_e3_cs && bus.wr) begin
|
||||
div_page <= bus.d_reg[3:0];
|
||||
div_mapram <= bus.d_reg[6] | div_mapram;
|
||||
div_conmem <= bus.d_reg[7];
|
||||
page <= bus.d_reg[3:0];
|
||||
mapram <= bus.d_reg[6] | mapram;
|
||||
conmem <= bus.d_reg[7];
|
||||
end
|
||||
if (port_e7_cs && bus.wr) begin
|
||||
sd_cs <= bus.d_reg[0];
|
||||
@ -88,7 +89,7 @@ end
|
||||
|
||||
reg [3:0] spi_cnt;
|
||||
wire spi_cnt_en = ~spi_cnt[3] | spi_cnt[2] | spi_cnt[1] | spi_cnt[0];
|
||||
assign div_wait = ~spi_cnt[3];
|
||||
assign cpuwait = ~spi_cnt[3];
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n)
|
||||
spi_cnt <= 0;
|
||||
@ -125,12 +126,15 @@ always @(posedge clk28) begin
|
||||
end
|
||||
|
||||
|
||||
assign div_map = div_automap | div_conmem;
|
||||
assign div_ram = (div_conmem == 1 && bus.a[13] == 1) ||
|
||||
(div_automap == 1 && bus.a[13] == 1) ||
|
||||
(div_conmem == 0 && div_automap == 1 && div_mapram == 1);
|
||||
assign div_ramwr_mask = bus.a[15] == 0 && bus.a[14] == 0 &&
|
||||
(bus.a[13] == 0 || div_page == 4'b0011) && div_conmem == 0 && div_automap == 1 && div_mapram == 1;
|
||||
assign map = automap | conmem;
|
||||
assign ram =
|
||||
(automap && bus.a[13]) ||
|
||||
(conmem && bus.a[13]) ||
|
||||
(!conmem && automap && mapram);
|
||||
assign ramwr_mask =
|
||||
!bus.a[15] && !bus.a[14] &&
|
||||
(!bus.a[13] || page == 4'b0011) &&
|
||||
!conmem && automap && mapram;
|
||||
|
||||
assign d_out_active = spi_rd;
|
||||
assign d_out = spi_reg;
|
||||
|
@ -4,26 +4,28 @@ module magic(
|
||||
input clk28,
|
||||
|
||||
cpu_bus bus,
|
||||
output [7:0] d_out,
|
||||
output d_out_active,
|
||||
|
||||
input n_int,
|
||||
input n_int_next,
|
||||
output reg n_nmi,
|
||||
|
||||
input magic_button,
|
||||
input pause_button,
|
||||
input sd_cd,
|
||||
input div_automap,
|
||||
|
||||
output reg magic_mode,
|
||||
output reg magic_map,
|
||||
|
||||
output reg magic_reboot,
|
||||
output reg magic_beeper,
|
||||
output timings_t timings,
|
||||
output machine_t machine,
|
||||
output turbo_t turbo,
|
||||
output rammode_t ram_mode,
|
||||
output panning_t panning,
|
||||
output reg joy_sinclair,
|
||||
output reg rom_plus3,
|
||||
output reg rom_alt48,
|
||||
output reg mix_acb,
|
||||
output reg mix_mono,
|
||||
output reg divmmc_en,
|
||||
output divmmc_t divmmc_en,
|
||||
output reg ulaplus_en,
|
||||
output reg covox_en,
|
||||
output reg sd_en
|
||||
@ -40,7 +42,7 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
magic_unmap_next <= 0;
|
||||
end
|
||||
else begin
|
||||
if (magic_button == 1'b1 && n_int == 1'b1 && n_int_next == 1'b0) begin
|
||||
if ((magic_button || pause_button) && n_int == 1'b1 && n_int_next == 1'b0) begin
|
||||
if (!magic_mode)
|
||||
n_nmi <= 1'b0;
|
||||
magic_mode <= 1'b1;
|
||||
@ -68,20 +70,16 @@ end
|
||||
|
||||
|
||||
/* MAGIC CONFIG */
|
||||
wire config_cs = magic_map && bus.ioreq && bus.a_reg[7:0] == 8'hff;
|
||||
wire config_cs = magic_map && bus.ioreq && bus.a_reg[7:0] == 8'hFF;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
magic_reboot <= 0;
|
||||
magic_beeper <= 0;
|
||||
timings <= TIMINGS_PENT;
|
||||
machine <= MACHINE_PENT;
|
||||
turbo <= TURBO_NONE;
|
||||
mix_acb <= 0;
|
||||
mix_mono <= 0;
|
||||
ram_mode <= RAM_512;
|
||||
rom_plus3 <= 1'b1;
|
||||
rom_alt48 <= 0;
|
||||
panning <= PANNING_ABC;
|
||||
joy_sinclair <= 0;
|
||||
divmmc_en <= 1'b1;
|
||||
divmmc_en <= DIVMMC_NOOS;
|
||||
ulaplus_en <= 1'b1;
|
||||
covox_en <= 1'b1;
|
||||
sd_en <= 1'b1;
|
||||
@ -89,18 +87,29 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
else if (config_cs && bus.wr) case (bus.a_reg[15:8])
|
||||
8'h00: magic_reboot <= bus.d_reg[0];
|
||||
8'h01: magic_beeper <= bus.d_reg[0];
|
||||
8'h02: timings <= timings_t'(bus.d_reg[1:0]);
|
||||
8'h03: turbo <= turbo_t'(bus.d_reg[1:0]);
|
||||
8'h04: {mix_mono, mix_acb} <= bus.d_reg[1:0];
|
||||
8'h05: rom_plus3 <= bus.d_reg[0];
|
||||
8'h06: rom_alt48 <= bus.d_reg[0];
|
||||
8'h02: machine <= machine_t'(bus.d_reg[2:0]);
|
||||
8'h03: turbo <= turbo_t'(bus.d_reg[2:0]);
|
||||
8'h04: panning <= panning_t'(bus.d_reg[1:0]);
|
||||
8'h07: joy_sinclair <= bus.d_reg[0];
|
||||
8'h08: ram_mode <= rammode_t'(bus.d_reg[1:0]);
|
||||
8'h09: divmmc_en <= bus.d_reg[0];
|
||||
8'h09: divmmc_en <= divmmc_t'(bus.d_reg[1:0]);
|
||||
8'h0a: ulaplus_en <= bus.d_reg[0];
|
||||
8'h0b: {sd_en, covox_en} <= bus.d_reg[1:0];
|
||||
endcase
|
||||
end
|
||||
|
||||
reg config_rd;
|
||||
wire [7:0] config_data = {4'b0000, div_automap, sd_cd, pause_button, magic_button};
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n)
|
||||
config_rd <= 0;
|
||||
else
|
||||
config_rd <= config_cs && bus.rd && bus.a_reg[15:8] == 8'hFF;
|
||||
end
|
||||
|
||||
|
||||
/* BUS CONTROLLER */
|
||||
assign d_out_active = config_rd;
|
||||
assign d_out = config_data;
|
||||
|
||||
|
||||
endmodule
|
||||
|
120
fpga/rtl/memcontrol.sv
Normal file
120
fpga/rtl/memcontrol.sv
Normal file
@ -0,0 +1,120 @@
|
||||
import common::*;
|
||||
|
||||
module memcontrol(
|
||||
input rst_n,
|
||||
input clk28,
|
||||
cpu_bus bus,
|
||||
output [18:0] va,
|
||||
inout [7:0] vd,
|
||||
output n_vrd,
|
||||
output n_vwr,
|
||||
|
||||
input machine_t machine,
|
||||
input screenpage,
|
||||
input screen_fetch,
|
||||
input screen_fetch_up,
|
||||
input snow,
|
||||
input [14:0] screen_addr,
|
||||
input magic_map,
|
||||
input [2:0] rampage128,
|
||||
input rompage128,
|
||||
input [2:0] port_1ffd,
|
||||
input [4:0] port_dffd,
|
||||
input [2:0] rampage_ext,
|
||||
input divmmc_en,
|
||||
input div_ram,
|
||||
input div_map,
|
||||
input div_ramwr_mask,
|
||||
input [3:0] div_page,
|
||||
|
||||
input [16:0] rom2ram_ram_address,
|
||||
input rom2ram_ram_wren,
|
||||
input [7:0] rom2ram_dataout,
|
||||
input magic_dout_active,
|
||||
input [7:0] magic_dout,
|
||||
input up_dout_active,
|
||||
input [7:0] up_dout,
|
||||
input div_dout_active,
|
||||
input [7:0] div_dout,
|
||||
input turbosound_dout_active,
|
||||
input [7:0] turbosound_dout,
|
||||
input ports_dout_active,
|
||||
input [7:0] ports_dout
|
||||
);
|
||||
|
||||
|
||||
/* MEMORY CONTROLLER */
|
||||
reg romreq, ramreq, ramreq_wr;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
romreq = 1'b0;
|
||||
ramreq = 1'b0;
|
||||
ramreq_wr = 1'b0;
|
||||
end
|
||||
else begin
|
||||
romreq = bus.mreq && !bus.rfsh && bus.a[14] == 0 && bus.a[15] == 0 &&
|
||||
(magic_map || (!div_ram && div_map) || (!div_ram && !port_dffd[4] && !port_1ffd[0]));
|
||||
ramreq = bus.mreq && !bus.rfsh && !romreq;
|
||||
ramreq_wr = ramreq && bus.wr && div_ramwr_mask == 0;
|
||||
end
|
||||
end
|
||||
|
||||
assign n_vrd = ((((ramreq || romreq) && bus.rd) || screen_fetch) && !rom2ram_ram_wren)? 1'b0 : 1'b1;
|
||||
assign n_vwr = ((ramreq_wr && bus.wr && !screen_fetch) || rom2ram_ram_wren)? 1'b0 : 1'b1;
|
||||
|
||||
/* VA[18:13] map
|
||||
* 00xxxx 128Kb of roms
|
||||
* 00111x 16Kb of magic ram
|
||||
* 01xxxx 128Kb of divmmc memory
|
||||
* 10xxxx 128Kb of extended ram (via port dffd)
|
||||
* 11xxxx 128Kb of main ram
|
||||
*/
|
||||
|
||||
reg [18:13] ram_a;
|
||||
always @(posedge clk28) begin
|
||||
ram_a <=
|
||||
magic_map & bus.a[15] & bus.a[14]? {2'b00, 3'b111, bus.a[13]} :
|
||||
magic_map? {3'b111, screenpage, bus.a[14:13]} :
|
||||
div_map & ~bus.a[14] & ~bus.a[15] & bus.a[13]? {2'b01, div_page} :
|
||||
div_map & ~bus.a[14] & ~bus.a[15]? {2'b01, 4'b0011} :
|
||||
port_dffd[3] & bus.a[15]? {2'b11, bus.a[14], bus.a[15], bus.a[14], bus.a[13]} :
|
||||
port_dffd[3] & bus.a[14]? {1'b1, ~rampage_ext[0], rampage128, bus.a[13]} :
|
||||
(port_1ffd[2] == 1'b0 && port_1ffd[0] == 1'b1)? {2'b11, port_1ffd[1], bus.a[15], bus.a[14], bus.a[13]} :
|
||||
(port_1ffd == 3'b101)? {2'b11, ~(bus.a[15] & bus.a[14]), bus.a[15], bus.a[14]} :
|
||||
(port_1ffd == 3'b111)? {2'b11, ~(bus.a[15] & bus.a[14]), (bus.a[15] | bus.a[14]), bus.a[14]} :
|
||||
bus.a[15] & bus.a[14]? {1'b1, ~rampage_ext[0], rampage128, bus.a[13]} :
|
||||
{2'b11, bus.a[14], bus.a[15], bus.a[14], bus.a[13]} ;
|
||||
end
|
||||
|
||||
reg [16:14] rom_a;
|
||||
always @(posedge clk28) begin
|
||||
rom_a <=
|
||||
magic_map? 3'd2 :
|
||||
div_map? 3'd3 :
|
||||
(machine == MACHINE_S3 && port_1ffd[2] == 1'b0 && rompage128 == 1'b0)? 3'd4 :
|
||||
(machine == MACHINE_S3 && port_1ffd[2] == 1'b0 && rompage128 == 1'b1)? 3'd5 :
|
||||
(machine == MACHINE_S3 && port_1ffd[2] == 1'b1 && rompage128 == 1'b0)? 3'd6 :
|
||||
(rompage128 == 1'b1)? 3'd1 :
|
||||
3'd0;
|
||||
end
|
||||
|
||||
assign va[18:0] =
|
||||
rom2ram_ram_wren? {2'b00, rom2ram_ram_address} :
|
||||
screen_fetch && snow? {3'b111, screenpage, screen_addr[14:8], {8{1'bz}}} :
|
||||
screen_fetch? {3'b111, screenpage, screen_addr} :
|
||||
romreq? {2'b00, rom_a[16:14], bus.a[13], {13{1'bz}}} :
|
||||
{ram_a[18:13], {13{1'bz}}};
|
||||
|
||||
assign vd[7:0] =
|
||||
~n_vrd? {8{1'bz}} :
|
||||
bus.wr? {8{1'bz}} :
|
||||
rom2ram_ram_wren? rom2ram_dataout :
|
||||
magic_dout_active? magic_dout :
|
||||
up_dout_active? up_dout :
|
||||
div_dout_active? div_dout :
|
||||
turbosound_dout_active? turbosound_dout :
|
||||
ports_dout_active? ports_dout :
|
||||
8'hFF;
|
||||
|
||||
|
||||
endmodule
|
@ -2,9 +2,6 @@ import common::*;
|
||||
module ports(
|
||||
input rst_n,
|
||||
input clk28,
|
||||
input en_128k,
|
||||
input en_plus3,
|
||||
input en_profi,
|
||||
input en_kempston,
|
||||
input en_sinclair,
|
||||
|
||||
@ -12,13 +9,12 @@ module ports(
|
||||
output [7:0] d_out,
|
||||
output d_out_active,
|
||||
|
||||
input timings_t timings,
|
||||
input clkcpu_ck,
|
||||
input screen_loading,
|
||||
input [7:0] attr_next,
|
||||
input machine_t machine,
|
||||
input port_ff_active,
|
||||
input [7:0] port_ff_data,
|
||||
input [4:0] kd,
|
||||
input [7:0] kempston_data,
|
||||
input magic_button,
|
||||
input magic_map,
|
||||
input tape_in,
|
||||
|
||||
output reg tape_out,
|
||||
@ -27,21 +23,21 @@ module ports(
|
||||
output reg screenpage,
|
||||
output reg rompage128,
|
||||
output reg [2:0] rampage128,
|
||||
output reg [3:0] rampage_ext,
|
||||
output reg [2:0] rampage_ext,
|
||||
output reg [2:0] port_1ffd,
|
||||
output reg port_dffd_d3,
|
||||
output reg port_dffd_d4
|
||||
output reg [4:0] port_dffd
|
||||
|
||||
);
|
||||
|
||||
|
||||
/* PORT #FF */
|
||||
wire [7:0] port_ff_data = attr_next;
|
||||
reg port_ff_rd;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n)
|
||||
port_ff_rd <= 0;
|
||||
else
|
||||
port_ff_rd <= bus.rd && bus.ioreq && (timings != TIMINGS_PENT || bus.a_reg[7:0] == 8'hFF) && screen_loading;
|
||||
port_ff_rd <= bus.rd && bus.ioreq && !magic_map && port_ff_active &&
|
||||
(machine != MACHINE_S3) && (machine != MACHINE_PENT || bus.a_reg[7:0] == 8'hFF);
|
||||
end
|
||||
|
||||
|
||||
@ -56,14 +52,14 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
end
|
||||
|
||||
reg [4:0] kd0;
|
||||
wire [7:0] port_fe_data = {~magic_button, tape_in, 1'b1, kd0};
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
wire [7:0] port_fe_data = {1'b1, tape_in, 1'b1, kd0};
|
||||
always @(negedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
beeper <= 0;
|
||||
tape_out <= 0;
|
||||
border <= 0;
|
||||
end
|
||||
else if (port_fe_cs && bus.wr && clkcpu_ck) begin // clkcpu_ck to synchronize border
|
||||
else if (port_fe_cs && bus.wr) begin
|
||||
beeper <= bus.d_reg[4];
|
||||
tape_out <= bus.d_reg[3];
|
||||
border <= bus.d_reg[2:0];
|
||||
@ -86,7 +82,9 @@ end
|
||||
|
||||
|
||||
/* PORT #7FFD */
|
||||
wire port_7ffd_cs = en_128k && bus.ioreq && bus.a_reg[1] == 0 && bus.a_reg[15] == 0 && (bus.a_reg[14] == 1'b1 || !en_plus3);
|
||||
wire port_7ffd_cs = bus.ioreq && bus.a_reg[1] == 0 && bus.a_reg[15] == 0 &&
|
||||
(bus.a_reg[14] == 1'b1 || (!magic_map && machine != MACHINE_S3)) &&
|
||||
(machine != MACHINE_S48 || magic_map);
|
||||
reg lock_7ffd;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
@ -95,7 +93,7 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
rompage128 <= 0;
|
||||
lock_7ffd <= 0;
|
||||
end
|
||||
else if (port_7ffd_cs && bus.wr && (lock_7ffd == 0 || port_dffd_d4 == 1'b1)) begin
|
||||
else if (port_7ffd_cs && bus.wr && (lock_7ffd == 0 || port_dffd[4] == 1'b1)) begin
|
||||
rampage128 <= bus.d_reg[2:0];
|
||||
screenpage <= bus.d_reg[3];
|
||||
rompage128 <= bus.d_reg[4];
|
||||
@ -105,23 +103,21 @@ end
|
||||
|
||||
|
||||
/* PORT #DFFD */
|
||||
wire port_dffd_cs = en_profi && bus.ioreq && bus.a_reg == 16'hDFFD;
|
||||
wire port_dffd_cs = bus.ioreq && bus.a_reg == 16'hDFFD && (machine == MACHINE_PENT || magic_map);
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
rampage_ext <= 0;
|
||||
port_dffd_d3 <= 0;
|
||||
port_dffd_d4 <= 0;
|
||||
port_dffd <= 0;
|
||||
end
|
||||
else if (port_dffd_cs && bus.wr) begin
|
||||
rampage_ext <= bus.d_reg[2:0];
|
||||
port_dffd_d3 <= bus.d_reg[3];
|
||||
port_dffd_d4 <= bus.d_reg[4];
|
||||
port_dffd <= bus.d_reg[4:0];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
/* PORT #1FFD */
|
||||
wire port_1ffd_cs = en_plus3 && bus.ioreq && bus.a_reg == 16'h1FFD;
|
||||
wire port_1ffd_cs = bus.ioreq && bus.a_reg == 16'h1FFD && (machine == MACHINE_S3 || magic_map);
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
port_1ffd <= 0;
|
||||
|
@ -136,8 +136,7 @@ always @(posedge clk or negedge rst_n) begin
|
||||
`PS2_PGDN: key2_pgdn <= is_press;
|
||||
|
||||
`PS2_F5: key_magic <= is_press;
|
||||
`PS2_F11: key_pause <= 1'b0;
|
||||
`PS2_F12: key_pause <= 1'b1;
|
||||
`PS2_F12: key_pause <= is_press;
|
||||
`PS2_DELETE: key2_del <= is_press;
|
||||
|
||||
`PS2_KP_8: joy_up <= is_press;
|
||||
|
@ -4,12 +4,12 @@ module screen(
|
||||
input rst_n,
|
||||
input clk28,
|
||||
|
||||
input timings_t timings,
|
||||
input machine_t machine,
|
||||
input [2:0] border,
|
||||
|
||||
output reg [2:0] r,
|
||||
output reg [2:0] g,
|
||||
output reg [2:0] b,
|
||||
output reg [1:0] b,
|
||||
output reg vsync,
|
||||
output reg hsync,
|
||||
output reg csync,
|
||||
@ -20,9 +20,11 @@ module screen(
|
||||
output [14:0] addr,
|
||||
input [7:0] fetch_data,
|
||||
|
||||
output loading,
|
||||
output contention,
|
||||
output blink,
|
||||
output reg [7:0] attr_next,
|
||||
output reg even_line,
|
||||
output port_ff_active,
|
||||
output [7:0] port_ff_data,
|
||||
|
||||
input up_en,
|
||||
output [5:0] up_ink_addr,
|
||||
@ -43,24 +45,24 @@ module screen(
|
||||
/* SCREEN CONTROLLER */
|
||||
localparam H_AREA = 256;
|
||||
localparam V_AREA = 192;
|
||||
localparam SCREEN_DELAY = 8;
|
||||
localparam SCREEN_DELAY = 13;
|
||||
|
||||
localparam H_LBORDER_S48 = 48 - SCREEN_DELAY;
|
||||
localparam H_RBORDER_S48 = 48 + SCREEN_DELAY;
|
||||
localparam H_BLANK1_S48 = 17;
|
||||
localparam H_LBORDER_S48 = 54 - SCREEN_DELAY;
|
||||
localparam H_RBORDER_S48 = 53 + SCREEN_DELAY;
|
||||
localparam H_BLANK1_S48 = 12;
|
||||
localparam H_SYNC_S48 = 33;
|
||||
localparam H_BLANK2_S48 = 46;
|
||||
localparam H_BLANK2_S48 = 40;
|
||||
localparam H_TOTAL_S48 = H_AREA + H_RBORDER_S48 + H_BLANK1_S48 + H_SYNC_S48 + H_BLANK2_S48 + H_LBORDER_S48;
|
||||
localparam V_BBORDER_S48 = 56;
|
||||
localparam V_SYNC_S48 = 8;
|
||||
localparam V_TBORDER_S48 = 56;
|
||||
localparam V_TOTAL_S48 = V_AREA + V_BBORDER_S48 + V_SYNC_S48 + V_TBORDER_S48;
|
||||
|
||||
localparam H_LBORDER_S128 = 48 - SCREEN_DELAY;
|
||||
localparam H_RBORDER_S128 = 48 + SCREEN_DELAY;
|
||||
localparam H_BLANK1_S128 = 25;
|
||||
localparam H_LBORDER_S128 = 58 - SCREEN_DELAY;
|
||||
localparam H_RBORDER_S128 = 57 + SCREEN_DELAY;
|
||||
localparam H_BLANK1_S128 = 12;
|
||||
localparam H_SYNC_S128 = 33;
|
||||
localparam H_BLANK2_S128 = 46;
|
||||
localparam H_BLANK2_S128 = 40;
|
||||
localparam H_TOTAL_S128 = H_AREA + H_RBORDER_S128 + H_BLANK1_S128 + H_SYNC_S128 + H_BLANK2_S128 + H_LBORDER_S128;
|
||||
localparam V_BBORDER_S128 = 55;
|
||||
localparam V_SYNC_S128 = 8;
|
||||
@ -78,12 +80,13 @@ localparam V_SYNC_PENT = 8;
|
||||
localparam V_TBORDER_PENT = 64;
|
||||
localparam V_TOTAL_PENT = V_AREA + V_BBORDER_PENT + V_SYNC_PENT + V_TBORDER_PENT;
|
||||
|
||||
reg [`CLOG2(`MAX(V_TOTAL_S128, V_TOTAL_PENT))-1:0] vc;
|
||||
reg [`CLOG2(`MAX(H_TOTAL_S128, H_TOTAL_PENT))+1:0] hc0;
|
||||
wire [`CLOG2(`MAX(H_TOTAL_S128, H_TOTAL_PENT))-1:0] hc = hc0[$bits(hc0)-1:2];
|
||||
reg [8:0] vc;
|
||||
reg [10:0] hc0;
|
||||
wire [8:0] hc = hc0[10:2];
|
||||
|
||||
assign vc_out = vc;
|
||||
assign hc_out = hc;
|
||||
|
||||
assign clk14 = hc0[0];
|
||||
assign clk7 = hc0[1];
|
||||
assign clk35 = hc0[2];
|
||||
@ -92,49 +95,49 @@ assign ck7 = hc0[0] & hc0[1];
|
||||
assign ck35 = hc0[0] & hc0[1] & hc0[2];
|
||||
|
||||
wire hc0_reset =
|
||||
(timings == TIMINGS_PENT)?
|
||||
hc0 == (H_TOTAL_PENT<<2) - 1'b1 :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
hc0 == (H_TOTAL_S48<<2) - 1'b1 :
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
hc0 == (H_TOTAL_S128<<2) - 1'b1 :
|
||||
// 48K
|
||||
hc0 == (H_TOTAL_S48<<2) - 1'b1 ;
|
||||
// Pentagon
|
||||
hc0 == (H_TOTAL_PENT<<2) - 1'b1 ;
|
||||
wire vc_reset =
|
||||
(timings == TIMINGS_PENT)?
|
||||
vc == V_TOTAL_PENT - 1'b1 :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
vc == V_TOTAL_S48 - 1'b1:
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
vc == V_TOTAL_S128 - 1'b1 :
|
||||
// 48K
|
||||
vc == V_TOTAL_S48 - 1'b1;
|
||||
// Pentagon
|
||||
vc == V_TOTAL_PENT - 1'b1 ;
|
||||
wire hsync0 =
|
||||
(timings == TIMINGS_PENT)?
|
||||
(hc >= (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT)) &&
|
||||
(hc < (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT + H_SYNC_PENT)) :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
(hc >= (H_AREA + H_RBORDER_S48 + H_BLANK1_S48)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S48 + H_BLANK1_S48 + H_SYNC_S48)) :
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
(hc >= (H_AREA + H_RBORDER_S128 + H_BLANK1_S128)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S128 + H_BLANK1_S128 + H_SYNC_S128)) :
|
||||
// 48K
|
||||
(hc >= (H_AREA + H_RBORDER_S48 + H_BLANK1_S48)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S48 + H_BLANK1_S48 + H_SYNC_S48)) ;
|
||||
// Pentagon
|
||||
(hc >= (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT)) &&
|
||||
(hc < (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT + H_SYNC_PENT)) ;
|
||||
wire vsync0 =
|
||||
(timings == TIMINGS_PENT)?
|
||||
(vc >= (V_AREA + V_BBORDER_PENT)) && (vc < (V_AREA + V_BBORDER_PENT + V_SYNC_PENT)) :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
(vc >= (V_AREA + V_BBORDER_S48)) && (vc < (V_AREA + V_BBORDER_S48 + V_SYNC_S48)) :
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
(vc >= (V_AREA + V_BBORDER_S128)) && (vc < (V_AREA + V_BBORDER_S128 + V_SYNC_S128)) :
|
||||
// 48K
|
||||
(vc >= (V_AREA + V_BBORDER_S48)) && (vc < (V_AREA + V_BBORDER_S48 + V_SYNC_S48)) ;
|
||||
// Pentagon
|
||||
(vc >= (V_AREA + V_BBORDER_PENT)) && (vc < (V_AREA + V_BBORDER_PENT + V_SYNC_PENT)) ;
|
||||
wire blank =
|
||||
(timings == TIMINGS_PENT)?
|
||||
((vc >= (V_AREA + V_BBORDER_PENT)) && (vc < (V_AREA + V_BBORDER_PENT + V_SYNC_PENT))) ||
|
||||
((hc >= (H_AREA + H_RBORDER_PENT)) &&
|
||||
(hc < (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT + H_SYNC_PENT + H_BLANK2_PENT))) :
|
||||
(timings == TIMINGS_S128)?
|
||||
(machine == MACHINE_S48)?
|
||||
((vc >= (V_AREA + V_BBORDER_S48)) && (vc < (V_AREA + V_BBORDER_S48 + V_SYNC_S48))) ||
|
||||
((hc >= (H_AREA + H_RBORDER_S48)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S48 + H_BLANK1_S48 + H_SYNC_S48 + H_BLANK2_S48))) :
|
||||
(machine == MACHINE_S128 || machine == MACHINE_S3)?
|
||||
((vc >= (V_AREA + V_BBORDER_S128)) && (vc < (V_AREA + V_BBORDER_S128 + V_SYNC_S128))) ||
|
||||
((hc >= (H_AREA + H_RBORDER_S128)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S128 + H_BLANK1_S128 + H_SYNC_S128 + H_BLANK2_S128))) :
|
||||
// 48K
|
||||
((vc >= (V_AREA + V_BBORDER_S48)) && (vc < (V_AREA + V_BBORDER_S48 + V_SYNC_S48))) ||
|
||||
((hc >= (H_AREA + H_RBORDER_S48)) &&
|
||||
(hc < (H_AREA + H_RBORDER_S48 + H_BLANK1_S48 + H_SYNC_S48 + H_BLANK2_S48))) ;
|
||||
// Pentagon
|
||||
((vc >= (V_AREA + V_BBORDER_PENT)) && (vc < (V_AREA + V_BBORDER_PENT + V_SYNC_PENT))) ||
|
||||
((hc >= (H_AREA + H_RBORDER_PENT)) &&
|
||||
(hc < (H_AREA + H_RBORDER_PENT + H_BLANK1_PENT + H_SYNC_PENT + H_BLANK2_PENT))) ;
|
||||
|
||||
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
@ -166,30 +169,61 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
blink_cnt <= blink_cnt + 1'b1;
|
||||
end
|
||||
|
||||
reg hsync0_delayed;
|
||||
always @(posedge clk28)
|
||||
hsync0_delayed <= hsync0;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n)
|
||||
even_line <= 0;
|
||||
else if (hsync0 && !hsync0_delayed)
|
||||
even_line <= ~even_line;
|
||||
end
|
||||
|
||||
wire [7:0] attr_border = {2'b00, border[2:0], 3'b000};
|
||||
|
||||
reg [7:0] bitmap, attr, bitmap_next;
|
||||
wire screen_show = (vc < V_AREA) && (hc0 >= (SCREEN_DELAY<<2) - 1) && (hc0 < ((H_AREA + SCREEN_DELAY)<<2) - 1);
|
||||
wire screen_update = hc0[4:0] == 5'b10011;
|
||||
wire border_update = (hc0[4:0] == 5'b10011) || (machine == MACHINE_PENT && ck7);
|
||||
wire bitmap_shift = hc0[1:0] == 2'b11;
|
||||
wire next_addr = hc0[4:0] == 5'b10001;
|
||||
|
||||
reg [7:0] vaddr;
|
||||
reg [7:3] haddr;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
vaddr <= 0;
|
||||
haddr <= 0;
|
||||
end
|
||||
else if (next_addr) begin
|
||||
vaddr <= vc[7:0];
|
||||
haddr <= hc[7:3];
|
||||
end
|
||||
end
|
||||
|
||||
reg loading;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n)
|
||||
loading <= 0;
|
||||
else
|
||||
loading <= (vc < V_AREA) && (hc0 > 15) && (hc0 < (H_AREA<<2) + 17);
|
||||
end
|
||||
|
||||
|
||||
wire [7:0] attr_border = {2'b00, border[2:0], border[2:0]};
|
||||
|
||||
reg [7:0] bitmap, attr, bitmap_next, attr_next;
|
||||
reg [7:0] up_ink0, up_paper0;
|
||||
|
||||
reg fetch_step;
|
||||
wire fetch_bitmap = fetch && fetch_step == 1'd1;
|
||||
wire fetch_attr = fetch && fetch_step == 1'd0;
|
||||
wire fetch_bitmap = fetch && fetch_step == 2'd0;
|
||||
wire fetch_attr = fetch && fetch_step == 2'd1;
|
||||
assign fetch_next = loading && fetch_allow;
|
||||
|
||||
assign addr = fetch_bitmap?
|
||||
{ 2'b10, vc[7:6], vc[2:0], vc[5:3], hc[7:3] } :
|
||||
{ 5'b10110, vc[7:3], hc[7:3] };
|
||||
|
||||
reg [7:0] up_ink0, up_paper0;
|
||||
{ 2'b10, vaddr[7:6], vaddr[2:0], vaddr[5:3], haddr[7:3] } :
|
||||
{ 5'b10110, vaddr[7:3], haddr[7:3] };
|
||||
assign up_ink_addr = { attr_next[7:6], 1'b0, attr_next[2:0] };
|
||||
assign up_paper_addr = { attr_next[7:6], 1'b1, attr_next[5:3] };
|
||||
|
||||
assign loading = (vc < V_AREA) && (hc < H_AREA || hc0_reset);
|
||||
wire screen_show = (vc < V_AREA) && (hc0 >= (SCREEN_DELAY<<2) - 2) && (hc0 < ((H_AREA + SCREEN_DELAY)<<2) - 2);
|
||||
wire screen_update = vc < V_AREA && hc <= H_AREA && hc != 0 && hc0[4:0] == 5'b11110;
|
||||
wire border_update = !screen_show && ((timings == TIMINGS_PENT && ck7) || hc0[4:0] == 5'b11110);
|
||||
wire bitmap_shift = hc0[1:0] == 2'b10;
|
||||
|
||||
assign fetch_next = loading && fetch_allow;
|
||||
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
fetch <= 0;
|
||||
@ -198,12 +232,14 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
bitmap <= 0;
|
||||
attr_next <= 0;
|
||||
bitmap_next <= 0;
|
||||
up_ink0 <= 0;
|
||||
up_paper0 <= 0;
|
||||
end
|
||||
else begin
|
||||
if (ck14) begin
|
||||
if (fetch)
|
||||
fetch_step <= fetch_step + 1'b1;
|
||||
fetch <= fetch_next;
|
||||
fetch <= fetch_allow;
|
||||
|
||||
if (fetch_attr)
|
||||
attr_next <= fetch_data;
|
||||
@ -211,12 +247,14 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
attr_next <= attr_border;
|
||||
if (fetch_bitmap)
|
||||
bitmap_next <= fetch_data;
|
||||
else if (!loading)
|
||||
bitmap_next <= 0;
|
||||
end
|
||||
|
||||
if (border_update)
|
||||
attr <= attr_border;
|
||||
else if (screen_update)
|
||||
if (screen_show && screen_update)
|
||||
attr <= attr_next;
|
||||
else if (!screen_show && border_update)
|
||||
attr <= attr_border;
|
||||
|
||||
if (screen_update)
|
||||
bitmap <= bitmap_next;
|
||||
@ -225,12 +263,24 @@ always @(posedge clk28 or negedge rst_n) begin
|
||||
|
||||
if (screen_update)
|
||||
up_ink0 <= up_ink;
|
||||
if (screen_update || (!screen_show && !loading))
|
||||
if (screen_update)
|
||||
up_paper0 <= up_paper;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
/* ATTRIBUTE PORT */
|
||||
wire port_ff_attr = (machine == MACHINE_PENT) || hc[3:1] == 3'h6 || hc[3:1] == 3'h0;
|
||||
wire port_ff_bitmap = (hc[3] && hc[1]);
|
||||
assign port_ff_active = loading && (port_ff_attr || port_ff_bitmap);
|
||||
assign port_ff_data =
|
||||
port_ff_attr? attr_next :
|
||||
port_ff_bitmap? bitmap_next :
|
||||
8'hFF;
|
||||
|
||||
assign contention = (vc < V_AREA) && (hc < H_AREA) && (hc[2] || hc[3]);
|
||||
|
||||
|
||||
/* RGBS generation */
|
||||
wire pixel = bitmap[7];
|
||||
always @(posedge clk28) begin
|
||||
@ -239,14 +289,16 @@ always @(posedge clk28) begin
|
||||
else if (up_en) begin
|
||||
g = pixel? up_ink0[7:5] : up_paper0[7:5];
|
||||
r = pixel? up_ink0[4:2] : up_paper0[4:2];
|
||||
b[2:1] = pixel? up_ink0[1:0] : up_paper0[1:0];
|
||||
b[0] = |b[2:1];
|
||||
b = pixel? up_ink0[1:0] : up_paper0[1:0];
|
||||
end
|
||||
else begin
|
||||
{g[2], r[2], b[2]} = (pixel ^ (attr[7] & blink))? attr[2:0] : attr[5:3];
|
||||
{g[1], r[1], b[1]} = {g[2] & attr[6], r[2] & attr[6], b[2] & attr[6]};
|
||||
{g[0], r[0], b[0]} = {g[2], r[2], b[2]};
|
||||
{g[2], r[2], b[1]} = (pixel ^ (attr[7] & blink))? attr[2:0] : attr[5:3];
|
||||
{g[1], r[1], b[0]} = {g[2] & attr[6], r[2] & attr[6], b[1] & attr[6]};
|
||||
{g[0], r[0]} = {g[2], r[2]};
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk28) begin
|
||||
csync = ~(vsync0 ^ hsync0);
|
||||
vsync = ~vsync0;
|
||||
hsync = ~hsync0;
|
||||
|
227
fpga/rtl/top.sv
227
fpga/rtl/top.sv
@ -48,11 +48,9 @@ pll pll0(.inclk0(clk_in), .c0(clk40), .c1(clk20), .locked(rst_n));
|
||||
|
||||
|
||||
/* SHARED DEFINITIONS */
|
||||
timings_t timings;
|
||||
machine_t machine;
|
||||
turbo_t turbo;
|
||||
rammode_t ram_mode;
|
||||
reg pause = 0;
|
||||
wire ps2_key_pause, ps2_key_reset;
|
||||
wire ps2_key_reset, ps2_key_pause;
|
||||
wire [2:0] border;
|
||||
wire magic_reboot, magic_beeper;
|
||||
wire up_active;
|
||||
@ -102,30 +100,25 @@ always @(posedge clk28) begin
|
||||
usrrst_n <= (!rst_n || ps2_key_reset || magic_reboot)? 1'b0 : 1'b1;
|
||||
end
|
||||
|
||||
/* PAUSE */
|
||||
always @(posedge clk28) begin
|
||||
if (n_int == 1'b0 && bus.rfsh)
|
||||
pause <= ps2_key_pause;
|
||||
end
|
||||
|
||||
|
||||
/* SCREEN CONTROLLER */
|
||||
wire blink;
|
||||
wire [2:0] screen_border = {border[2] ^ ~sd_cs, border[1] ^ magic_beeper, border[0] ^ (pause & blink)};
|
||||
wire [2:0] r, g, b;
|
||||
wire [2:0] screen_border = {border[2] ^ ~sd_cs, border[1] ^ magic_beeper, border[0]};
|
||||
wire [2:0] r, g;
|
||||
wire [1:0] b;
|
||||
wire hsync;
|
||||
wire screen_contention, port_ff_active;
|
||||
wire [14:0] screen_addr;
|
||||
wire [5:0] up_ink_addr, up_paper_addr;
|
||||
wire [7:0] up_ink, up_paper;
|
||||
wire screen_loading;
|
||||
wire [14:0] screen_addr;
|
||||
wire [7:0] attr_next;
|
||||
wire [8:0] vc, hc;
|
||||
wire [7:0] port_ff_data;
|
||||
wire clk14, clk7, clk35, ck14, ck7, ck35;
|
||||
screen screen0(
|
||||
.rst_n(rst_n),
|
||||
.rst_n(usrrst_n),
|
||||
.clk28(clk28),
|
||||
|
||||
.timings(timings),
|
||||
.machine(machine),
|
||||
.border(screen_border),
|
||||
|
||||
.r(r),
|
||||
@ -141,16 +134,17 @@ screen screen0(
|
||||
.fetch_next(screen_fetch_next),
|
||||
.fetch_data(bus.d),
|
||||
|
||||
.loading(screen_loading),
|
||||
.blink(blink),
|
||||
.attr_next(attr_next),
|
||||
|
||||
.up_en(up_active),
|
||||
.up_ink_addr(up_ink_addr),
|
||||
.up_paper_addr(up_paper_addr),
|
||||
.up_ink(up_ink),
|
||||
.up_paper(up_paper),
|
||||
|
||||
.contention(screen_contention),
|
||||
.blink(blink),
|
||||
.port_ff_active(port_ff_active),
|
||||
.port_ff_data(port_ff_data),
|
||||
|
||||
.vc_out(vc),
|
||||
.hc_out(hc),
|
||||
.clk14(clk14),
|
||||
@ -210,16 +204,17 @@ cpucontrol cpucontrol0(
|
||||
.clk14(clk14),
|
||||
.clk7(clk7),
|
||||
.clk35(clk35),
|
||||
.ck14(ck14),
|
||||
.ck7(ck7),
|
||||
|
||||
.bus(bus),
|
||||
|
||||
.vc(vc),
|
||||
.hc(hc),
|
||||
.rampage128(rampage128),
|
||||
.screen_loading(screen_loading),
|
||||
.machine(machine),
|
||||
.screen_contention(screen_contention),
|
||||
.turbo(turbo),
|
||||
.timings(timings),
|
||||
.pause(pause),
|
||||
.ext_wait_cycle(div_wait || up_active),
|
||||
.init_done_in(init_done),
|
||||
|
||||
@ -234,32 +229,39 @@ cpucontrol cpucontrol0(
|
||||
|
||||
|
||||
/* MAGIC */
|
||||
wire div_automap;
|
||||
wire [7:0] magic_dout;
|
||||
wire magic_dout_active;
|
||||
wire magic_mode, magic_map;
|
||||
wire divmmc_en, joy_sinclair, rom_plus3, rom_alt48, mix_acb, mix_mono, up_en, covox_en, sd_en;
|
||||
wire joy_sinclair, up_en, covox_en, sd_en;
|
||||
panning_t panning;
|
||||
divmmc_t divmmc_en;
|
||||
magic magic0(
|
||||
.rst_n(usrrst_n),
|
||||
.rst_n(n_rstcpu),
|
||||
.clk28(clk28),
|
||||
|
||||
.bus(bus),
|
||||
.d_out(magic_dout),
|
||||
.d_out_active(magic_dout_active),
|
||||
|
||||
.n_int(n_int),
|
||||
.n_int_next(n_int_next),
|
||||
.n_nmi(n_nmi),
|
||||
|
||||
.magic_button(ps2_key_magic),
|
||||
.pause_button(ps2_key_pause),
|
||||
.sd_cd(sd_cd),
|
||||
.div_automap(div_automap),
|
||||
|
||||
.magic_mode(magic_mode),
|
||||
.magic_map(magic_map),
|
||||
|
||||
.magic_reboot(magic_reboot),
|
||||
.magic_beeper(magic_beeper),
|
||||
.timings(timings),
|
||||
.machine(machine),
|
||||
.turbo(turbo),
|
||||
.ram_mode(ram_mode),
|
||||
.joy_sinclair(joy_sinclair),
|
||||
.rom_plus3(rom_plus3),
|
||||
.rom_alt48(rom_alt48),
|
||||
.mix_acb(mix_acb),
|
||||
.mix_mono(mix_mono),
|
||||
.panning(panning),
|
||||
.divmmc_en(divmmc_en),
|
||||
.ulaplus_en(up_en),
|
||||
.covox_en(covox_en),
|
||||
@ -273,31 +275,26 @@ wire ports_dout_active;
|
||||
wire beeper, tape_out;
|
||||
wire screenpage;
|
||||
wire rompage128;
|
||||
wire [3:0] rampage_ext;
|
||||
wire [2:0] rampage_ext;
|
||||
wire [2:0] port_1ffd;
|
||||
wire port_dffd_d3;
|
||||
wire port_dffd_d4;
|
||||
wire [4:0] port_dffd;
|
||||
ports ports0 (
|
||||
.rst_n(usrrst_n),
|
||||
.rst_n(n_rstcpu),
|
||||
.clk28(clk28),
|
||||
|
||||
.bus(bus),
|
||||
.d_out(ports_dout),
|
||||
.d_out_active(ports_dout_active),
|
||||
|
||||
.en_128k(ram_mode == RAM_512 || ram_mode == RAM_128),
|
||||
.en_plus3(rom_plus3),
|
||||
.en_profi(ram_mode == RAM_512),
|
||||
.en_kempston(!joy_sinclair),
|
||||
.en_sinclair(joy_sinclair),
|
||||
|
||||
.timings(timings),
|
||||
.clkcpu_ck(clkcpu_ck),
|
||||
.screen_loading(screen_loading),
|
||||
.attr_next(attr_next),
|
||||
.machine(machine),
|
||||
.port_ff_active(port_ff_active),
|
||||
.port_ff_data(port_ff_data),
|
||||
.kd(ps2_kd),
|
||||
.kempston_data({3'b000, ps2_joy_fire, ps2_joy_up, ps2_joy_down, ps2_joy_left, ps2_joy_right}),
|
||||
.magic_button(ps2_key_magic),
|
||||
.magic_map(magic_map),
|
||||
.tape_in(sd_miso_tape_in),
|
||||
|
||||
.tape_out(tape_out),
|
||||
@ -308,8 +305,7 @@ ports ports0 (
|
||||
.rampage128(rampage128),
|
||||
.rampage_ext(rampage_ext),
|
||||
.port_1ffd(port_1ffd),
|
||||
.port_dffd_d3(port_dffd_d3),
|
||||
.port_dffd_d4(port_dffd_d4)
|
||||
.port_dffd(port_dffd)
|
||||
);
|
||||
|
||||
|
||||
@ -318,7 +314,7 @@ wire turbosound_dout_active;
|
||||
wire [7:0] turbosound_dout;
|
||||
wire [7:0] ay_a0, ay_b0, ay_c0, ay_a1, ay_b1, ay_c1;
|
||||
turbosound turbosound0(
|
||||
.rst_n(usrrst_n),
|
||||
.rst_n(n_rstcpu),
|
||||
.clk28(clk28),
|
||||
.ck35(ck35),
|
||||
.en(1'b1),
|
||||
@ -328,8 +324,6 @@ turbosound turbosound0(
|
||||
.d_out(turbosound_dout),
|
||||
.d_out_active(turbosound_dout_active),
|
||||
|
||||
.pause(pause),
|
||||
|
||||
.ay_a0(ay_a0),
|
||||
.ay_b0(ay_b0),
|
||||
.ay_c0(ay_c0),
|
||||
@ -355,10 +349,9 @@ soundrive soundrive0(
|
||||
.ch_r1(soundrive_r1)
|
||||
);
|
||||
|
||||
|
||||
/* SOUND MIXER */
|
||||
mixer mixer0(
|
||||
.rst_n(rst_n),
|
||||
.rst_n(usrrst_n),
|
||||
.clk28(clk28),
|
||||
|
||||
.beeper(beeper ^ magic_beeper),
|
||||
@ -375,8 +368,8 @@ mixer mixer0(
|
||||
.sd_r0(soundrive_r0),
|
||||
.sd_r1(soundrive_r1),
|
||||
|
||||
.ay_acb(mix_acb),
|
||||
.mono(mix_mono),
|
||||
.ay_acb(panning == PANNING_ABC),
|
||||
.mono(panning == PANNING_MONO),
|
||||
|
||||
.dac_l(snd_l),
|
||||
.dac_r(snd_r)
|
||||
@ -389,12 +382,12 @@ wire [7:0] div_dout;
|
||||
wire [3:0] div_page;
|
||||
wire sd_mosi0;
|
||||
divmmc divmmc0(
|
||||
.rst_n(usrrst_n),
|
||||
.rst_n(n_rstcpu),
|
||||
.clk28(clk28),
|
||||
.ck14(ck14),
|
||||
.ck7(ck7),
|
||||
.en(divmmc_en),
|
||||
.en_hooks(~sd_cd),
|
||||
.en(divmmc_en == DIVMMC_ON || divmmc_en == DIVMMC_NOOS),
|
||||
.en_hooks(divmmc_en == DIVMMC_ON),
|
||||
|
||||
.bus(bus),
|
||||
.d_out(div_dout),
|
||||
@ -405,15 +398,16 @@ divmmc divmmc0(
|
||||
.sd_sck(sd_sck),
|
||||
.sd_cs(sd_cs),
|
||||
|
||||
.rammap(port_dffd_d4 | port_1ffd[0]),
|
||||
.rammap(port_dffd[4] | port_1ffd[0]),
|
||||
.magic_mode(magic_mode),
|
||||
.magic_map(magic_map),
|
||||
|
||||
.div_page(div_page),
|
||||
.div_map(div_map),
|
||||
.div_ram(div_ram),
|
||||
.div_ramwr_mask(div_ramwr_mask),
|
||||
.div_wait(div_wait)
|
||||
.page(div_page),
|
||||
.map(div_map),
|
||||
.automap(div_automap),
|
||||
.ram(div_ram),
|
||||
.ramwr_mask(div_ramwr_mask),
|
||||
.cpuwait(div_wait)
|
||||
);
|
||||
assign sd_mosi = (~sd_cd)? sd_mosi0 : tape_out;
|
||||
|
||||
@ -422,7 +416,7 @@ assign sd_mosi = (~sd_cd)? sd_mosi0 : tape_out;
|
||||
wire up_dout_active;
|
||||
wire [7:0] up_dout;
|
||||
ulaplus ulaplus0(
|
||||
.rst_n(usrrst_n),
|
||||
.rst_n(n_rstcpu),
|
||||
.clk28(clk28),
|
||||
.en(up_en),
|
||||
|
||||
@ -484,77 +478,46 @@ asmi asmi0(
|
||||
|
||||
|
||||
/* MEMORY CONTROLLER */
|
||||
reg romreq, ramreq, ramreq_wr;
|
||||
always @(posedge clk28 or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
romreq = 1'b0;
|
||||
ramreq = 1'b0;
|
||||
ramreq_wr = 1'b0;
|
||||
end
|
||||
else begin
|
||||
romreq = bus.mreq && !bus.rfsh && bus.a[14] == 0 && bus.a[15] == 0 &&
|
||||
(magic_map || (!div_ram && div_map) || (!div_ram && !port_dffd_d4 && !port_1ffd[0]));
|
||||
ramreq = bus.mreq && !bus.rfsh && !romreq;
|
||||
ramreq_wr = ramreq && bus.wr && div_ramwr_mask == 0;
|
||||
end
|
||||
end
|
||||
memcontrol memcontrol0(
|
||||
.rst_n(rst_n),
|
||||
.clk28(clk28),
|
||||
.bus(bus),
|
||||
.va(va),
|
||||
.vd(vd),
|
||||
.n_vrd(n_vrd),
|
||||
.n_vwr(n_vwr),
|
||||
|
||||
assign n_vrd = ((((ramreq || romreq) && bus.rd) || screen_fetch) && !rom2ram_ram_wren)? 1'b0 : 1'b1;
|
||||
assign n_vwr = ((ramreq_wr && bus.wr && !screen_fetch) || rom2ram_ram_wren)? 1'b0 : 1'b1;
|
||||
.machine(machine),
|
||||
.screenpage(screenpage),
|
||||
.screen_fetch(screen_fetch),
|
||||
.snow(snow),
|
||||
.screen_addr(screen_addr),
|
||||
.magic_map(magic_map),
|
||||
.rampage128(rampage128),
|
||||
.rompage128(rompage128),
|
||||
.port_1ffd(port_1ffd),
|
||||
.port_dffd(port_dffd),
|
||||
.rampage_ext(rampage_ext),
|
||||
.divmmc_en(divmmc_en != DIVMMC_OFF),
|
||||
.div_ram(div_ram),
|
||||
.div_map(div_map),
|
||||
.div_ramwr_mask(div_ramwr_mask),
|
||||
.div_page(div_page),
|
||||
|
||||
/* VA[18:13] map
|
||||
* 00xxxx 128Kb of roms
|
||||
* 00111x 16Kb of magic ram
|
||||
* 01xxxx 128Kb of divmmc memory
|
||||
* 10xxxx 128Kb of extended ram (via port dffd)
|
||||
* 11xxxx 128Kb of main ram
|
||||
*/
|
||||
|
||||
reg [18:13] ram_a;
|
||||
always @(posedge clk28) begin
|
||||
ram_a <=
|
||||
magic_map & bus.a[15] & bus.a[14]? {2'b00, 3'b111, bus.a[13]} :
|
||||
magic_map? {3'b111, screenpage, bus.a[14:13]} :
|
||||
div_map & ~bus.a[14] & ~bus.a[15] & bus.a[13]? {2'b01, div_page} :
|
||||
div_map & ~bus.a[14] & ~bus.a[15]? {2'b01, 4'b0011} :
|
||||
port_dffd_d3 & bus.a[15]? {2'b11, bus.a[14], bus.a[15], bus.a[14], bus.a[13]} :
|
||||
port_dffd_d3 & bus.a[14]? {1'b1, ~rampage_ext[0], rampage128, bus.a[13]} :
|
||||
(port_1ffd[2] == 1'b0 && port_1ffd[0] == 1'b1)? {2'b11, port_1ffd[1], bus.a[15], bus.a[14], bus.a[13]} :
|
||||
(port_1ffd == 3'b101)? {2'b11, ~(bus.a[15] & bus.a[14]), bus.a[15], bus.a[14]} :
|
||||
(port_1ffd == 3'b111)? {2'b11, ~(bus.a[15] & bus.a[14]), (bus.a[15] | bus.a[14]), bus.a[14]} :
|
||||
bus.a[15] & bus.a[14]? {1'b1, ~rampage_ext[0], rampage128, bus.a[13]} :
|
||||
{2'b11, bus.a[14], bus.a[15], bus.a[14], bus.a[13]} ;
|
||||
end
|
||||
|
||||
reg [16:14] rom_a;
|
||||
always @(posedge clk28) begin
|
||||
rom_a <=
|
||||
magic_map? 3'd2 :
|
||||
div_map? 3'd3 :
|
||||
(rom_plus3 && port_1ffd[2] == 1'b0 && rompage128 == 1'b0)? 3'd4 :
|
||||
(rom_plus3 && port_1ffd[2] == 1'b0 && rompage128 == 1'b1)? 3'd5 :
|
||||
(rom_plus3 && port_1ffd[2] == 1'b1 && rompage128 == 1'b0)? 3'd6 :
|
||||
(rompage128 == 1'b1 && rom_alt48 == 1'b1)? 3'd7 :
|
||||
(rompage128 == 1'b1)? 3'd1 :
|
||||
3'd0;
|
||||
end
|
||||
|
||||
assign va[18:0] =
|
||||
rom2ram_ram_wren? {2'b00, rom2ram_ram_address} :
|
||||
screen_fetch && snow? {3'b111, screenpage, screen_addr[14:8], {8{1'bz}}} :
|
||||
screen_fetch? {3'b111, screenpage, screen_addr} :
|
||||
romreq? {2'b00, rom_a[16:14], bus.a[13], {13{1'bz}}} :
|
||||
{ram_a[18:13], {13{1'bz}}};
|
||||
|
||||
assign vd[7:0] =
|
||||
~n_vrd? {8{1'bz}} :
|
||||
rom2ram_ram_wren? rom2ram_dataout :
|
||||
up_dout_active? up_dout :
|
||||
div_dout_active? div_dout :
|
||||
turbosound_dout_active? turbosound_dout :
|
||||
ports_dout_active? ports_dout :
|
||||
~n_wr? {8{1'bz}} :
|
||||
8'hFF;
|
||||
.rom2ram_ram_address(rom2ram_ram_address),
|
||||
.rom2ram_ram_wren(rom2ram_ram_wren),
|
||||
.rom2ram_dataout(rom2ram_dataout),
|
||||
.magic_dout_active(magic_dout_active),
|
||||
.magic_dout(magic_dout),
|
||||
.up_dout_active(up_dout_active),
|
||||
.up_dout(up_dout),
|
||||
.div_dout_active(div_dout_active),
|
||||
.div_dout(div_dout),
|
||||
.turbosound_dout_active(turbosound_dout_active),
|
||||
.turbosound_dout(turbosound_dout),
|
||||
.ports_dout_active(ports_dout_active),
|
||||
.ports_dout(ports_dout)
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
|
@ -166,6 +166,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE ../rtl/ports.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE ../rtl/magic.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE ../rtl/divmmc.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE ../rtl/cpucontrol.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE ../rtl/memcontrol.sv
|
||||
set_global_assignment -name VERILOG_FILE ../rtl/chroma_gen.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE ../rtl/turbosound.sv
|
||||
set_global_assignment -name VHDL_FILE ../rtl/ym2149.vhd
|
||||
|
@ -5,6 +5,7 @@ SRC_T80=./t80/t80n_pack.vhd ./t80/t80n.vhd ./t80/t80n_alu.vhd ./t80/t80n_mcode.v
|
||||
all: testbench_zx_ula
|
||||
|
||||
testbench_zx_ula: IVFLAGS+=-I./az80/ -I./t80/ -I../rtl/
|
||||
testbench_zx_ula: VLOGFLAGS+=+define+TESTBENCH
|
||||
testbench_zx_ula: testbench_zx_ula.v ../rtl/common.sv $(wildcard stubs/*.v ../rtl/*.vhd ../rtl/*.v ../rtl/*.sv)
|
||||
testbench_zx_ula: ${SRC_T80}
|
||||
testbench_zx_ula: rom.mem
|
||||
|
@ -1,26 +1,19 @@
|
||||
DEVICE ZXSPECTRUM48
|
||||
|
||||
ORG #0000
|
||||
ORG #8000 // mapped #0000
|
||||
Start:
|
||||
nop
|
||||
jp Main
|
||||
jp #1000
|
||||
|
||||
ORG #0038
|
||||
ORG #8038
|
||||
Int1:
|
||||
jp #1ff8
|
||||
ORG #00FF
|
||||
DB #38
|
||||
reti
|
||||
|
||||
ORG #0066
|
||||
ORG #8066
|
||||
Nmi:
|
||||
jp #1ffa
|
||||
push af
|
||||
ld a, #08
|
||||
out (#ff), a
|
||||
pop af
|
||||
retn
|
||||
|
||||
ORG #1000
|
||||
ORG #9000
|
||||
Main:
|
||||
im 2
|
||||
ei
|
||||
@ -46,15 +39,8 @@ Main:
|
||||
jp #1fff
|
||||
Loop:
|
||||
halt
|
||||
jp Loop
|
||||
jr Loop
|
||||
|
||||
ORG #1FF8 // DivROM exit vector
|
||||
reti
|
||||
ORG #1FFA // DivROM exit vector
|
||||
retn
|
||||
ORG #1FFF // DivROM exit vector
|
||||
nop
|
||||
jp #3D00
|
||||
|
||||
ORG #C000 // mapped #0000
|
||||
DivROM_Start:
|
||||
|
@ -1,4 +1,4 @@
|
||||
`timescale 100ps/10ps
|
||||
`timescale 1ns/100ps
|
||||
module testbench_zx_ula();
|
||||
|
||||
reg rst_n;
|
||||
@ -6,7 +6,8 @@ reg clk28;
|
||||
|
||||
|
||||
/* CPU */
|
||||
wire rstcpu_n;
|
||||
wire clkcpu;
|
||||
wire n_rstcpu;
|
||||
wire [15:0] a_cpu, a_cpu_cpu;
|
||||
wire [7:0] d_cpu_o, d_cpu_i;
|
||||
wire n_rd, n_rd_cpu;
|
||||
@ -19,7 +20,7 @@ wire n_int;
|
||||
wire n_nmi;
|
||||
|
||||
T80na cpu1(
|
||||
.RESET_n(rstcpu_n),
|
||||
.RESET_n(n_rstcpu),
|
||||
.CLK_n(clkcpu),
|
||||
.WAIT_n(1'b1),
|
||||
.INT_n(n_int),
|
||||
@ -72,7 +73,7 @@ wire sd_mosi_miso;
|
||||
zx_ula zx_ula1(
|
||||
.clk_in(clk28),
|
||||
.clkcpu(clkcpu),
|
||||
.n_rstcpu(rstcpu_n),
|
||||
.n_rstcpu(n_rstcpu),
|
||||
.a(a_cpu[15:13]),
|
||||
.vd(vd),
|
||||
.va(va),
|
||||
@ -138,51 +139,63 @@ assign d_cpu_i = vd;
|
||||
// assign a_cpu = a_cpu_cpu;
|
||||
|
||||
/* CPU SIGNALS (Z84C0020 timings) */
|
||||
assign #400 n_rd = n_rd_cpu; //TdCf(RDf)
|
||||
assign #400 n_wr = n_wr_cpu; //TdCf(WRf)
|
||||
assign #400 n_iorq = n_iorq_cpu; //TdCr(IORQf)
|
||||
assign #400 n_mreq = n_mreq_cpu; //TdCf(MREQf)
|
||||
assign #450 n_m1 = n_m1_cpu; //TdCr(M1f)
|
||||
assign #600 n_rfsh = n_rfsh_cpu; //TdCr(RFSHf)
|
||||
assign #570 a_cpu = a_cpu_cpu; //TdCr(A)
|
||||
assign #40 n_rd = n_rd_cpu; //TdCf(RDf)
|
||||
assign #40 n_wr = n_wr_cpu; //TdCf(WRf)
|
||||
assign #40 n_iorq = n_iorq_cpu; //TdCr(IORQf)
|
||||
assign #40 n_mreq = n_mreq_cpu; //TdCf(MREQf)
|
||||
assign #45 n_m1 = n_m1_cpu; //TdCr(M1f)
|
||||
assign #60 n_rfsh = n_rfsh_cpu; //TdCr(RFSHf)
|
||||
assign #57 a_cpu = a_cpu_cpu; //TdCr(A)
|
||||
|
||||
/* CPU SIGNALS (Z84C0008 timings) */
|
||||
// assign #700 n_rd = n_rd_cpu; //TdCf(RDf)
|
||||
// assign #600 n_wr = n_wr_cpu; //TdCf(WRf)
|
||||
// assign #550 n_iorq = n_iorq_cpu; //TdCr(IORQf)
|
||||
// assign #600 n_mreq = n_mreq_cpu; //TdCf(MREQf)
|
||||
// assign #700 n_m1 = n_m1_cpu; //TdCr(M1f)
|
||||
// assign #950 n_rfsh = n_rfsh_cpu; //TdCr(RFSHf)
|
||||
// assign #800 a_cpu = a_cpu_cpu; //TdCr(A)
|
||||
//assign #70 n_rd = n_rd_cpu; //TdCf(RDf)
|
||||
//assign #60 n_wr = n_wr_cpu; //TdCf(WRf)
|
||||
//assign #55 n_iorq = n_iorq_cpu; //TdCr(IORQf)
|
||||
//assign #60 n_mreq = n_mreq_cpu; //TdCf(MREQf)
|
||||
//assign #70 n_m1 = n_m1_cpu; //TdCr(M1f)
|
||||
//assign #95 n_rfsh = n_rfsh_cpu; //TdCr(RFSHf)
|
||||
//assign #80 a_cpu = a_cpu_cpu; //TdCr(A)
|
||||
|
||||
/* CPU SIGNALS (Z84C0004 timings) */
|
||||
// assign #850 n_rd = n_rd_cpu; //TdCf(RDf)
|
||||
// assign #800 n_wr = n_wr_cpu; //TdCf(WRf)
|
||||
// assign #750 n_iorq = n_iorq_cpu; //TdCr(IORQf)
|
||||
// assign #850 n_mreq = n_mreq_cpu; //TdCf(MREQf)
|
||||
// assign #1000 n_m1 = n_m1_cpu; //TdCr(M1f)
|
||||
// assign #1300 n_rfsh = n_rfsh_cpu; //TdCr(RFSHf)
|
||||
// assign #1100 a_cpu = a_cpu_cpu; //TdCr(A)
|
||||
// assign #85 n_rd = n_rd_cpu; //TdCf(RDf)
|
||||
// assign #80 n_wr = n_wr_cpu; //TdCf(WRf)
|
||||
// assign #75 n_iorq = n_iorq_cpu; //TdCr(IORQf)
|
||||
// assign #85 n_mreq = n_mreq_cpu; //TdCf(MREQf)
|
||||
// assign #100 n_m1 = n_m1_cpu; //TdCr(M1f)
|
||||
// assign #130 n_rfsh = n_rfsh_cpu; //TdCr(RFSHf)
|
||||
// assign #110 a_cpu = a_cpu_cpu; //TdCr(A)
|
||||
|
||||
|
||||
/* SIMULATION SIGNALS */
|
||||
initial begin
|
||||
n_magic = 1;
|
||||
#50000
|
||||
// n_magic = 0;
|
||||
#50000
|
||||
n_magic = 1;
|
||||
end
|
||||
|
||||
|
||||
/* CLOCKS & RESET */
|
||||
initial begin
|
||||
rst_n = 0;
|
||||
#3000 rst_n = 1;
|
||||
#300 rst_n = 1;
|
||||
end
|
||||
|
||||
always begin
|
||||
clk28 = 0;
|
||||
#178 clk28 = 1;
|
||||
#179;
|
||||
#17.8 clk28 = 1;
|
||||
#17.9;
|
||||
end
|
||||
|
||||
|
||||
/* TESTBENCH CONTROL */
|
||||
initial begin
|
||||
$dumpfile("testbench_zx_ula.vcd");
|
||||
$dumpvars();
|
||||
#5000000 $finish;
|
||||
// #200000000 $finish;
|
||||
$dumpvars;
|
||||
#500_000 $finish;
|
||||
// #21_000_000 $finish;
|
||||
// #41_000_000 $finish;
|
||||
end
|
||||
|
||||
|
||||
|
35
rom/Makefile
35
rom/Makefile
@ -1,12 +1,23 @@
|
||||
all:
|
||||
cat 128-0.rom \
|
||||
128-1.rom \
|
||||
../rom_src/main.bin \
|
||||
ESXMMC.BIN ESXMMC.BIN \
|
||||
dvmen3e0.rom \
|
||||
dvmen3e1.rom \
|
||||
dvmen3e2.rom \
|
||||
opense.rom \
|
||||
>sizif.bin
|
||||
objcopy --input-target=binary --output-target=ihex sizif.bin sizif.hex
|
||||
rm sizif.bin
|
||||
# Each bank = 16Kb
|
||||
bank00=128-0.rom # 0x00000
|
||||
bank01=128-1.rom # 0x04000
|
||||
bank02=../rom_src/main.bin # 0x08000
|
||||
bank03=ESXMMC.BIN ESXMMC.BIN # 0x0C000
|
||||
bank04=dvmen3e0.rom # 0x10000
|
||||
bank05=dvmen3e1.rom # 0x14000
|
||||
bank06=dvmen3e2.rom # 0x18000
|
||||
bank07=zero8k.bin zero8k.bin # 0x1C000
|
||||
|
||||
sizif.rom: ${bank00} ${bank01} ${bank02} ${bank03} ${bank04} ${bank05} ${bank06} ${bank07}
|
||||
|
||||
%.rom:
|
||||
cat $+ > $@
|
||||
|
||||
%.hex: %.rom
|
||||
objcopy --input-target=binary --output-target=ihex $< $@
|
||||
|
||||
.DEFAULT_GOAL := all
|
||||
all: sizif.hex
|
||||
|
||||
clean:
|
||||
rm -f sizif.rom sizif.hex
|
||||
|
BIN
rom/opense.rom
BIN
rom/opense.rom
Binary file not shown.
BIN
rom/zero8k.bin
Normal file
BIN
rom/zero8k.bin
Normal file
Binary file not shown.
@ -1,6 +1,7 @@
|
||||
export PATH:=/cygdrive/c/Hwdev/sjasmplus/:/cygdrive/c/Dev/srec/:${PATH}
|
||||
|
||||
SJOPTS='-DSIZIFXXS'
|
||||
REV=D
|
||||
SJOPTS=-DSIZIFXXS
|
||||
|
||||
.PHONY: all clean .FORCE
|
||||
.FORCE:
|
||||
|
@ -1,35 +1,45 @@
|
||||
POWERON_DELAY EQU 40 ; *20ms, for ps/2 keyboard initialization
|
||||
|
||||
MENU_ENTER_DELAY EQU 40 ; 400ms
|
||||
MENU_LEAVE_DELAY EQU 2 ; 20ms
|
||||
MENU_HOLDCHECK_DELAY EQU 7
|
||||
|
||||
MENU_WIDTH EQU 20
|
||||
MENU_HEIGHT EQU MENU_ITEMS+2
|
||||
|
||||
MENU_X EQU (32-MENU_WIDTH)/2
|
||||
MENU_Y EQU (24-MENU_HEIGHT)/2
|
||||
|
||||
MENU_HEADER_ATTR EQU #47
|
||||
MENU_BODY_ATTR EQU #78
|
||||
MENU_SELECT_ATTR EQU #68
|
||||
|
||||
INPUT_REPEAT EQU 2
|
||||
INPUT_REPEAT_FIRST EQU 11
|
||||
INPUT_BEEP_DELAY EQU 255
|
||||
|
||||
MENU_WIDTH EQU 20
|
||||
MENU_X EQU (32-MENU_WIDTH)/2
|
||||
MENU_HEADER_ATTR EQU #47
|
||||
MENU_BODY_ATTR EQU #78
|
||||
MENU_SELECT_ATTR EQU #68
|
||||
|
||||
PAUSE_WIDTH EQU 7
|
||||
PAUSE_HEIGHT EQU 3 ; see pause.asm to really change
|
||||
PAUSE_X EQU (32-PAUSE_WIDTH)/2
|
||||
PAUSE_Y EQU (24-PAUSE_HEIGHT)/2
|
||||
PAUSE_BODY_ATTR EQU #00
|
||||
PAUSE_TEXT_ATTR EQU #C7
|
||||
|
||||
STRUCT CFG_T
|
||||
_reserv0 DB 0
|
||||
_reserv1 DB 0
|
||||
timings DB 0
|
||||
machine DB 3
|
||||
clock DB 0
|
||||
panning DB 0
|
||||
plus3 DB 0
|
||||
panning DB 1
|
||||
custom_rom DB 0
|
||||
rom48 DB 0
|
||||
joystick DB 0
|
||||
ram DB 0
|
||||
divmmc DB 1
|
||||
_reserv2 DB 0
|
||||
divmmc DB 2
|
||||
ulaplus DB 1
|
||||
dac DB 3
|
||||
ENDS
|
||||
|
||||
STRUCT CFGEXT_T
|
||||
tsfm DB 1
|
||||
saa DB 1
|
||||
gs DB 1
|
||||
ENDS
|
||||
|
||||
CFG_DEFAULT CFG_T
|
||||
CFGEXT_DEFAULT CFGEXT_T
|
||||
|
@ -125,7 +125,7 @@ print_char:
|
||||
print_string:
|
||||
ld a, (hl) ; A = *string
|
||||
or a ; if (A == 0) - exit
|
||||
jr z, .return ; ...
|
||||
ret z ; ...
|
||||
push bc
|
||||
push hl
|
||||
call print_char
|
||||
@ -134,7 +134,6 @@ print_string:
|
||||
inc hl ; string++
|
||||
inc c ; column++
|
||||
jr print_string
|
||||
.return:
|
||||
ret
|
||||
|
||||
|
||||
@ -151,7 +150,7 @@ print_string:
|
||||
print_string_rev:
|
||||
ld a, (hl) ; A = *string
|
||||
or a ; if (A == 0) - exit
|
||||
jr z, .return ; ...
|
||||
ret z ; ...
|
||||
push bc
|
||||
push hl
|
||||
call print_char
|
||||
@ -160,7 +159,6 @@ print_string_rev:
|
||||
dec hl ; string--
|
||||
dec c ; column--
|
||||
jr print_string_rev
|
||||
.return:
|
||||
ret
|
||||
|
||||
|
||||
@ -280,22 +278,23 @@ draw_menu:
|
||||
push hl ; IX = menu first item addr
|
||||
pop ix ; ...
|
||||
.line_loop:
|
||||
ld l, (ix+0) ; HL = menu_t.textaddr
|
||||
ld h, (ix+1) ; ...
|
||||
ld l, (ix+MENUENTRY_T.text_addr+0) ; HL = menuentry_t.textaddr
|
||||
ld h, (ix+MENUENTRY_T.text_addr+1) ; ...
|
||||
ld a, h ; if (HL == 0) - exit
|
||||
or l ; ...
|
||||
jr z, .return ; ...
|
||||
push bc
|
||||
ret z ; ...
|
||||
push de
|
||||
push bc
|
||||
push ix
|
||||
call print_string ; print menu item text
|
||||
pop ix
|
||||
pop de
|
||||
pop bc
|
||||
pop de
|
||||
dec sp ; DE will be restored in .skip_val
|
||||
dec sp ; ...
|
||||
.print_val:
|
||||
push de ; will be restored in .skip_val
|
||||
ld l, (ix+2) ; HL = menu_t.value_cb_addr
|
||||
ld h, (ix+3) ; ...
|
||||
ld l, (ix+MENUENTRY_T.value_cb_addr+0) ; HL = menuentry_t.value_cb_addr
|
||||
ld h, (ix+MENUENTRY_T.value_cb_addr+1) ; ...
|
||||
ld a, h ; if (HL == 0) - skip value print
|
||||
or l ; ...
|
||||
jr z, .skip_val ; ...
|
||||
@ -313,7 +312,7 @@ draw_menu:
|
||||
ld a, b ; row += 8
|
||||
add a, 8 ; ...
|
||||
ld b, a ; ...
|
||||
ld de, MENU_T ; IX = IX + sizeof(menu_t)
|
||||
ld de, MENUENTRY_T ; IX = IX + sizeof(menuentry_t)
|
||||
add ix, de ; ...
|
||||
pop de ; restore E - columns
|
||||
jr .line_loop
|
||||
@ -332,17 +331,16 @@ draw_menu:
|
||||
; OUT - B - garbage
|
||||
; OUT - E - garbage
|
||||
; OUT - HL - garbage
|
||||
draw_menu_item_line:
|
||||
draw_attribute_line:
|
||||
call coords_to_attribute_address ; HL = attribute address
|
||||
.loop:
|
||||
ld a, e ; if (columns == 0) - exit
|
||||
or a ; ...
|
||||
jr z, .return ; ...
|
||||
ret z ; ...
|
||||
ld (hl), d ; write attribute
|
||||
inc hl ; column++
|
||||
dec e ; columns--
|
||||
jr .loop
|
||||
.return:
|
||||
ret
|
||||
|
||||
|
||||
|
@ -721,13 +721,13 @@ font_latin_small_letter_g:
|
||||
DG --###---
|
||||
|
||||
font_latin_small_letter_h:
|
||||
DG --------
|
||||
DG -#------
|
||||
DG -#------
|
||||
DG -####---
|
||||
DG -#---#--
|
||||
DG -#---#--
|
||||
DG -#---#--
|
||||
DG -#---#--
|
||||
DG --------
|
||||
|
||||
font_latin_small_letter_i:
|
||||
|
@ -14,7 +14,7 @@ input_read:
|
||||
in a, (#1f) ; ...
|
||||
bit 7, a ; detect presence by 7th bit
|
||||
jr nz, .enter ; ...
|
||||
and #1f ; mask useless bits
|
||||
and #3f ; mask useless bits
|
||||
ld b, a ; ...
|
||||
.enter:
|
||||
ld a, #bf ; read keys
|
||||
@ -85,9 +85,16 @@ input_read:
|
||||
ret
|
||||
.sinclair_09876_6:
|
||||
bit 4, a ; handle 6 (LEFT) key
|
||||
jr nz, .return ; ...
|
||||
jr nz, .sinclair_ssmnb ; ...
|
||||
set 1, b ; ...
|
||||
ret
|
||||
.sinclair_ssmnb:
|
||||
ld a, #7f ; read keys
|
||||
in a, (#fe) ; ...
|
||||
bit 2, a ; handle M (EXIT) key (in Sinclair mode sega C button is mapped to M)
|
||||
jr nz, .return ; ...
|
||||
set 5, b ; ...
|
||||
ret
|
||||
.space_break:
|
||||
ld a, #7f ; read keys
|
||||
in a, (#fe) ; ...
|
||||
@ -128,7 +135,7 @@ input_read:
|
||||
; OUT - BC - garbage
|
||||
input_beep:
|
||||
or a
|
||||
jr z, .return
|
||||
ret z
|
||||
IFDEF TEST_BUILD
|
||||
ld a, #10 ; blink border
|
||||
out (#fe), a ; ...
|
||||
@ -142,7 +149,6 @@ input_beep:
|
||||
ld a, 1 ; blink border back
|
||||
ld bc, #01ff ; ...
|
||||
out (c), a ; ...
|
||||
.return:
|
||||
ret
|
||||
|
||||
|
||||
|
326
rom_src/main.asm
326
rom_src/main.asm
@ -4,11 +4,15 @@
|
||||
app_begin:
|
||||
; Startup handler
|
||||
ORG #0000
|
||||
ex de, hl ; EB opcode used by CPLD to determine magic ROM presence
|
||||
ex de, hl ; ...
|
||||
jp startup_handler
|
||||
DB 0,"Sizif Magic ROM",0
|
||||
|
||||
; NMI handler
|
||||
ORG #0066
|
||||
ex de, hl ; EB opcode used by CPLD to determine magic ROM presence
|
||||
ex de, hl ; ...
|
||||
jp nmi_handler
|
||||
|
||||
; INT IM1 handler
|
||||
@ -35,8 +39,23 @@ startup_handler:
|
||||
ld ix, #5800 ; draw 4 rygb boxes on left top corner to indicate boot
|
||||
ld (ix+0), #D2 ; r
|
||||
ld (ix+1), #F6 ; y
|
||||
call init_config
|
||||
call check_initialized
|
||||
jr z, .warm_boot
|
||||
im 1 ; wait for ps/2 keyboard ready
|
||||
ld b, POWERON_DELAY ; ...
|
||||
.loop ; ...
|
||||
ei ; ...
|
||||
halt ; ...
|
||||
djnz .loop ; ...
|
||||
call init_default_config
|
||||
call detect_sd_card
|
||||
call detect_ext_board
|
||||
call check_custom_rom
|
||||
.warm_boot:
|
||||
call load_config
|
||||
call init_cpld
|
||||
call save_initialized
|
||||
call mute_saa1099 ; saa1099 does not have reset pin
|
||||
ld (ix+2), #E4 ; g
|
||||
ld (ix+3), #C9 ; b
|
||||
ld hl, 0
|
||||
@ -55,18 +74,25 @@ nmi_handler:
|
||||
ld (var_magic_enter_cnt), a
|
||||
ld (var_magic_leave_cnt), a
|
||||
.loop:
|
||||
call check_magic_delay
|
||||
call check_magic_hold ; A == 1 if we are entering menu, A == 2 if we are leaving to...
|
||||
call check_entering_pause ; A[1] == 1 if pause button is pressed
|
||||
bit 1, a ; ...
|
||||
jp nz, enter_pause ; ...
|
||||
call delay_10ms ;
|
||||
call check_entering_menu ; A == 1 if we are entering menu, A == 2 if we are leaving to...
|
||||
bit 0, a ; ...default nmi handler, A == 0 otherwise
|
||||
jp nz, main ; ...
|
||||
jp nz, enter_menu ; ...
|
||||
bit 1, a ; ...
|
||||
jr z, .loop ; ...
|
||||
.leave:
|
||||
xor a ; disable border
|
||||
ld bc, #01ff ; ...
|
||||
out (c), a ; ...
|
||||
ld hl, #0066 ; jump to default nmi handler
|
||||
jp exit_with_jp ; ...
|
||||
ld bc, #ffff ; if divmmc paged - just do retn
|
||||
in a, (c) ; ...
|
||||
bit 3, a ; ...
|
||||
jr nz, exit_with_ret ; ...
|
||||
ld hl, #0066 ; otherwise jump to default nmi handler
|
||||
jr exit_with_jp ; ...
|
||||
|
||||
|
||||
; IN - HL - jump address
|
||||
@ -90,40 +116,43 @@ exit_with_ret:
|
||||
jp Exit_vector-1
|
||||
|
||||
|
||||
init_config:
|
||||
ld hl, cfg_initialized ; if (cfg_initialized == "magic word") {restore cfg} else {default cfg}
|
||||
check_initialized:
|
||||
ld hl, cfg_initialized ; if (cfg_initialized == "magic word") Z = 0, else Z = 1
|
||||
ld a, #B1 ; ...
|
||||
cpi ; ... hl++
|
||||
jr nz, .init_default ; ...
|
||||
ret nz ; ...
|
||||
ld a, #5B ; ...
|
||||
cpi ; ... hl++
|
||||
jr nz, .init_default ; ...
|
||||
ret nz ; ...
|
||||
ld a, #00 ; ...
|
||||
cpi ; ... hl++
|
||||
jr nz, .init_default ; ...
|
||||
ret nz ; ...
|
||||
ld a, #B5 ; ...
|
||||
cpi ; ... hl++
|
||||
jr nz, .init_default ; ...
|
||||
jr .restore ; ...
|
||||
.init_default:
|
||||
ld bc, CFG_T ; cfg_saved = cfg_default
|
||||
ld de, cfg_saved ; ...
|
||||
ld hl, CFG_DEFAULT ; ...
|
||||
ldir ; ...
|
||||
.restore:
|
||||
ld bc, CFG_T ; cfg = cfg_saved
|
||||
ld de, cfg ; ...
|
||||
ld hl, cfg_saved ; ...
|
||||
ldir ; ...
|
||||
.save_magic:
|
||||
ret
|
||||
|
||||
save_initialized:
|
||||
ld hl, #5BB1 ; cfg_initialized = "magic word"
|
||||
ld (cfg_initialized+0), hl ; ...
|
||||
ld hl, #B500 ; ...
|
||||
ld (cfg_initialized+2), hl ; ...
|
||||
ret
|
||||
|
||||
init_default_config:
|
||||
ld bc, CFG_T+CFGEXT_T ; cfg_saved = cfg_default
|
||||
ld de, cfg_saved ; ...
|
||||
ld hl, CFG_DEFAULT ; ...
|
||||
ldir ; ...
|
||||
|
||||
load_config:
|
||||
ld bc, CFG_T+CFGEXT_T ; cfg = cfg_saved
|
||||
ld de, cfg ; ...
|
||||
ld hl, cfg_saved ; ...
|
||||
ldir ; ...
|
||||
ret ; ...
|
||||
|
||||
save_config:
|
||||
ld bc, CFG_T ; cfg_saved = cfg
|
||||
ld bc, CFG_T+CFGEXT_T ; cfg_saved = cfg
|
||||
ld de, cfg_saved ; ...
|
||||
ld hl, cfg ; ...
|
||||
ldir ; ...
|
||||
@ -131,22 +160,28 @@ save_config:
|
||||
|
||||
|
||||
init_cpld:
|
||||
.check_ram48k:
|
||||
ld a, (cfg.ram) ; if ram == 48K - run basic48
|
||||
cp 1 ; ...
|
||||
jr nz, .check_plus3_disabled ; ...
|
||||
.check_alt48rom:
|
||||
ld a, (cfg.rom48) ; if alternative 48k rom enabled - disable 128 menu
|
||||
or a ; ... this is required because 128 menu isn't compatible
|
||||
jr z, .check_7ffd_disabled ; ... with currently used Looking Glass 48K rom
|
||||
ld a, (cfg.machine) ; ... however +3e works with looking glass flawlessly
|
||||
cp 2 ; ...
|
||||
jr z, .check_7ffd_disabled ; ...
|
||||
ld a, #10 ; ...
|
||||
ld bc, #7ffd ; ...
|
||||
out (c), a ; ...
|
||||
ld a, #4 ; ...
|
||||
ld bc, #1ffd ; ...
|
||||
.check_7ffd_disabled:
|
||||
ld a, (cfg.machine) ; if machine == 48 - set 7ffd rom to basic48
|
||||
or a ; ... this is required for case when machine will be
|
||||
jr nz, .check_1ffd_disabled ; ... changed later by magic menu - this prevents
|
||||
ld a, #10 ; ... hang if user changes machine while basic48 active
|
||||
ld bc, #7ffd ; ...
|
||||
out (c), a ; ...
|
||||
jr .do_load
|
||||
.check_plus3_disabled:
|
||||
ld a, (cfg.plus3) ; if plus3 disabled - set 1ffd rom to basic48
|
||||
or a ; ... this is required for case when plus3 will be
|
||||
jr nz, .do_load ; ... activated later by magic menu - this prevents
|
||||
ld a, #4 ; ... hang if user activating plus3 while basic48 active
|
||||
.check_1ffd_disabled:
|
||||
ld a, (cfg.machine) ; if machine != +3 - set 1ffd rom to basic48
|
||||
cp 2 ; ... this is required for case when +3 will be
|
||||
jr z, .do_load ; ... activated later by magic menu - this prevents
|
||||
ld a, #4 ; ... hang if user activate +3 while basic48 active
|
||||
ld bc, #1ffd ; ...
|
||||
out (c), a ; ...
|
||||
.do_load:
|
||||
@ -154,16 +189,120 @@ init_cpld:
|
||||
ld c, #ff ;
|
||||
ld hl, cfg+CFG_T-1 ; HL = &cfg[registers count-1]
|
||||
otdr ; do { b--; out(bc, *hl); hl--; } while(b)
|
||||
.do_load_ext: ; same for extension board
|
||||
ld d, CFGEXT_T ; ...
|
||||
ld b, #e1 ; ...
|
||||
ld c, #ff ; ...
|
||||
ld hl, cfgext ; ...
|
||||
.do_load_ext_loop: ; ...
|
||||
ld a, (hl) ; ...
|
||||
out (c), a ; ...
|
||||
inc hl ; ...
|
||||
inc b ; ...
|
||||
dec d ; ...
|
||||
jr nz, .do_load_ext_loop ; ...
|
||||
ret
|
||||
|
||||
|
||||
detect_sd_card:
|
||||
ld a, #ff ; read sd_cd state in bit 2 of #FFFF port
|
||||
in a, (#ff) ; ...
|
||||
bit 2, a ; check sd_cd == 0 (card is insert)
|
||||
jr z, .is_insert ; yes?
|
||||
.no_card:
|
||||
xor a ; divmmc = OFF
|
||||
ld (cfg_saved.divmmc), a ; ...
|
||||
ret
|
||||
.is_insert:
|
||||
ld a, 1 ; divmmc = ON
|
||||
ld (cfg_saved.divmmc), a ; ...
|
||||
ret
|
||||
|
||||
|
||||
; OUT - A = 1 if ext board present, 0 otherwise
|
||||
; OUT - F - garbage
|
||||
; OUT - BC - garbage
|
||||
detect_ext_board:
|
||||
ld b, #e0 ; read port #e0ff
|
||||
ld c, #ff ; ...
|
||||
in a, (c) ; ...
|
||||
ld b, a ; if (result & 0xF0 != 0) - return
|
||||
and #f0 ; ...
|
||||
jr z, .detected ; ...
|
||||
.not_detected:
|
||||
xor a
|
||||
ld (var_ext_presence), a
|
||||
ret
|
||||
.detected
|
||||
ld a, 1
|
||||
ld (var_ext_presence), a
|
||||
xor a
|
||||
bit 0, b ; check TSFM jumper
|
||||
jr z, .cfg_tsfm
|
||||
ld a, 1
|
||||
.cfg_tsfm:
|
||||
ld (cfgext_saved.tsfm), a
|
||||
xor a
|
||||
bit 1, b ; check SAA jumper
|
||||
jr z, .cfg_saa
|
||||
ld a, 1
|
||||
.cfg_saa:
|
||||
ld (cfgext_saved.saa), a
|
||||
xor a
|
||||
bit 2, b ; check GS jumper
|
||||
jr z, .cfg_gs
|
||||
ld a, 1
|
||||
.cfg_gs:
|
||||
ld (cfgext_saved.gs), a
|
||||
ret
|
||||
|
||||
|
||||
; Check if user holds 1/2/3/4 key on poweron. If true - boot with custom rom
|
||||
check_custom_rom:
|
||||
ld a, #f7 ; read 1-5 keys
|
||||
in a, (#fe) ; ...
|
||||
bit 0, a ; check key 1 pressed
|
||||
jr z, .key1 ; ...
|
||||
bit 1, a ; check key 2 pressed
|
||||
jr z, .key2 ; ...
|
||||
bit 2, a ; check key 3 pressed
|
||||
jr z, .key3 ; ...
|
||||
bit 3, a ; check key 4 pressed
|
||||
jr z, .key4 ; ...
|
||||
ret
|
||||
.key1:
|
||||
ld a, #80 ; rom #0
|
||||
jr .reconfig
|
||||
.key2:
|
||||
ld a, #81 ; rom #1
|
||||
jr .reconfig
|
||||
.key3:
|
||||
ld a, #82 ; rom #2
|
||||
jr .reconfig
|
||||
.key4:
|
||||
ld a, #83 ; rom #3
|
||||
.reconfig:
|
||||
ld (cfg_saved.custom_rom), a ; set custom rom
|
||||
xor a
|
||||
ld (cfg_saved.divmmc), a ; disable divmmc
|
||||
ld (cfg_saved.ulaplus), a ; disable ula+
|
||||
ret
|
||||
|
||||
|
||||
; OUT - A bit 1 if we are entering pause, 0 otherwise
|
||||
check_entering_pause:
|
||||
ld a, #ff ; read pause key state in bit 1 of #FFFF port
|
||||
in a, (#ff) ; ...
|
||||
ret
|
||||
|
||||
|
||||
; OUT - A = 1 if we are entering menu, A = 2 if we are leaving menu, A = 0 otherwise
|
||||
; OUT - F - garbage
|
||||
check_magic_hold:
|
||||
ld a, #ff ; read magic key state in bit 7 of #FE port
|
||||
in a, (#fe) ; ...
|
||||
bit 7, a ; check key is hold
|
||||
jr z, .is_hold ; yes?
|
||||
check_entering_menu:
|
||||
ld a, #ff ; read magic key state in bit 0 of #FFFF port
|
||||
in a, (#ff) ; ...
|
||||
bit 0, a ; check key is hold
|
||||
jr nz, .is_hold ; yes?
|
||||
.not_hold:
|
||||
ld a, (var_magic_leave_cnt) ; leave_counter++
|
||||
inc a ; ...
|
||||
@ -187,15 +326,21 @@ check_magic_hold:
|
||||
|
||||
; OUT - AF - garbage
|
||||
; OUT - BC - garbage
|
||||
check_magic_delay:
|
||||
ld c, MENU_HOLDCHECK_DELAY
|
||||
delay_10ms:
|
||||
ld c, 7
|
||||
ld a, (cfg.clock)
|
||||
or a
|
||||
jr z, .loop
|
||||
ld c, MENU_HOLDCHECK_DELAY*2
|
||||
ld c, 9
|
||||
dec a
|
||||
jr z, .loop
|
||||
ld c, MENU_HOLDCHECK_DELAY*4
|
||||
ld c, 11
|
||||
dec a
|
||||
jr z, .loop
|
||||
ld c, 7*2
|
||||
dec a
|
||||
jr z, .loop
|
||||
ld c, 7*4
|
||||
.loop:
|
||||
ld a, c
|
||||
.loop_outer:
|
||||
@ -223,14 +368,27 @@ get_im2_handler:
|
||||
ret
|
||||
|
||||
|
||||
save:
|
||||
.mute_saa1099:
|
||||
mute_saa1099:
|
||||
ld bc, #ffff ; select saa register
|
||||
ld a, #1c ; ...
|
||||
out (c), a ; ...
|
||||
ld b, #fe ; mute
|
||||
xor a ; ...
|
||||
out (c), a ; ...
|
||||
ret
|
||||
|
||||
save:
|
||||
.mute_gs:
|
||||
ld a, (var_ext_presence) ; if (no_ext_pcb || gs_is_disabled) - skip gs
|
||||
or a ; ...this is required to be compatible with DivIDE
|
||||
jr z, .mute_saa1099 ; ...which uses same port #bb
|
||||
ld a, (cfgext.gs) ; ...
|
||||
or a ; ...
|
||||
jr z, .mute_saa1099 ; ...
|
||||
ld a, #fa ; send command Out zero_to_zero
|
||||
out (#bb), a ; ...
|
||||
.mute_saa1099:
|
||||
call mute_saa1099
|
||||
.save_ay:
|
||||
ld hl, var_save_ay ; select first AY chip in TurboSound
|
||||
ld a, #ff ; ...
|
||||
@ -292,6 +450,15 @@ restore:
|
||||
ld hl, var_save_ay ; select first AY chip in TurboSound
|
||||
ld a, #ff ; ...
|
||||
call .restore_ay_sub
|
||||
.restore_gs:
|
||||
ld a, (var_ext_presence) ; if (no_ext_pcb || gs_is_disabled) - skip gs
|
||||
or a ; ...this is required to be compatible with DivIDE
|
||||
jr z, .restore_ret ; ...which uses same port #bb
|
||||
ld a, (cfgext.gs) ; ...
|
||||
or a ; ...
|
||||
jr z, .restore_ret ; ...
|
||||
ld a, #60 ; send command Get Song Position
|
||||
out (#bb), a ; ...
|
||||
.restore_ret:
|
||||
ret
|
||||
|
||||
@ -313,6 +480,16 @@ restore:
|
||||
ret
|
||||
|
||||
|
||||
enter_pause:
|
||||
ld a, 1
|
||||
ld (var_pause_flag), a
|
||||
jr main
|
||||
|
||||
enter_menu:
|
||||
xor a
|
||||
ld (var_pause_flag), a
|
||||
jr main
|
||||
|
||||
; Main program
|
||||
main:
|
||||
push de
|
||||
@ -330,23 +507,45 @@ main:
|
||||
ld (var_input_key), a
|
||||
ld (var_input_key_last), a
|
||||
ld (var_input_key_hold_timer), a
|
||||
ld (var_pause_is_released), a
|
||||
ld (var_menu_current_item), a
|
||||
ld (var_menu_animate_cnt), a
|
||||
|
||||
call save
|
||||
call menu_init
|
||||
ld a, (var_pause_flag)
|
||||
or a
|
||||
jr z, .menu_init
|
||||
|
||||
.loop:
|
||||
.pause_init:
|
||||
call pause_init
|
||||
.pause_loop:
|
||||
ei
|
||||
halt
|
||||
call pause_process
|
||||
ld a, (var_exit_flag)
|
||||
or a
|
||||
jr z, .pause_loop
|
||||
jr .wait_for_keys_release
|
||||
|
||||
.menu_init:
|
||||
call check_initialized
|
||||
jr z, .menu_init1
|
||||
call init_default_config
|
||||
call detect_ext_board
|
||||
call load_config
|
||||
call save_initialized
|
||||
.menu_init1:
|
||||
call menu_init
|
||||
.menu_loop:
|
||||
ei
|
||||
halt
|
||||
call input_process ; B = 32 if exit key pressed
|
||||
bit 5, b
|
||||
jr nz, .wait_for_keys_release
|
||||
|
||||
call menu_process
|
||||
ld a, (var_exit_flag)
|
||||
or a
|
||||
jr z, .loop
|
||||
jr z, .menu_loop
|
||||
|
||||
.wait_for_keys_release:
|
||||
ei
|
||||
@ -355,6 +554,10 @@ main:
|
||||
xor a
|
||||
or b
|
||||
jr nz, .wait_for_keys_release
|
||||
ld a, #ff ; read magic/pause keys state
|
||||
in a, (#ff) ; ...
|
||||
and #03 ; ...
|
||||
jr nz, .wait_for_keys_release
|
||||
|
||||
.leave:
|
||||
call save_config
|
||||
@ -389,6 +592,7 @@ main:
|
||||
include config.asm
|
||||
include draw.asm
|
||||
include input.asm
|
||||
include pause.asm
|
||||
include menu.asm
|
||||
include menu_structure.asm
|
||||
include font.asm
|
||||
@ -406,23 +610,7 @@ Readout_vector EQU #F008
|
||||
ORG #D500
|
||||
var_save_screen: .6912 DB 0
|
||||
ORG #F020
|
||||
var_save_ay: .32 DB 0
|
||||
var_save_ulaplus: DB 0
|
||||
var_sp_reg: DW 0
|
||||
var_int_vector: DW 0
|
||||
var_magic_enter_cnt: DB 0
|
||||
var_magic_leave_cnt: DB 0
|
||||
var_exit_flag: DB 0
|
||||
var_exit_reboot: DB 0
|
||||
var_input_key: DB 0
|
||||
var_input_key_last: DB 0
|
||||
var_input_key_hold_timer: DB 0
|
||||
var_menu_current_item: DB 0
|
||||
var_menu_animate_cnt: DB 0
|
||||
|
||||
cfg CFG_T
|
||||
cfg_saved CFG_T
|
||||
cfg_initialized: DB #B1, #5B, #00, #B5
|
||||
include variables.asm
|
||||
|
||||
ORG #FFBE
|
||||
Stack_top:
|
||||
|
@ -31,8 +31,9 @@ app_begin:
|
||||
call menu_process
|
||||
ld a, #01
|
||||
out #fe, a
|
||||
jr .loop
|
||||
|
||||
ld a, (var_exit_flag)
|
||||
or a
|
||||
jr z, .loop
|
||||
|
||||
save_variables:
|
||||
ret
|
||||
@ -42,24 +43,14 @@ includes:
|
||||
include config.asm
|
||||
include draw.asm
|
||||
include input.asm
|
||||
include pause.asm
|
||||
include menu.asm
|
||||
include menu_structure.asm
|
||||
include font.asm
|
||||
include strings.asm
|
||||
|
||||
variables:
|
||||
var_exit_flag: DB 0
|
||||
var_exit_reboot: DB 0
|
||||
var_input_key: DB 0
|
||||
var_input_key_last: DB 0
|
||||
var_input_key_hold_timer: DB 0
|
||||
var_menu_current_item: DB 0
|
||||
var_menu_animate_cnt: DB 0
|
||||
|
||||
cfg CFG_T
|
||||
cfg_saved CFG_T
|
||||
cfg_initialized: DB #B1, #5B, #00, #B5
|
||||
|
||||
include variables.asm
|
||||
|
||||
DISPLAY "Application size: ",/D,$-app_begin
|
||||
CSPECTMAP "main_test.map"
|
||||
|
@ -1,16 +1,29 @@
|
||||
menu_init:
|
||||
ld b, MENU_Y
|
||||
ld bc, MENU_T ; if (ext board present) var_menu = menuext; else var_menu = menu;
|
||||
ld de, var_menu ; ...
|
||||
ld hl, menu ; ...
|
||||
ld a, (var_ext_presence) ; ...
|
||||
or a ; ...
|
||||
jr z, .set_menu ; ...
|
||||
ld hl, menuext ; ...
|
||||
.set_menu: ; ...
|
||||
ldir ; ...
|
||||
|
||||
ld ix, var_menu
|
||||
ld b, (ix+MENU_T.y_row)
|
||||
ld c, MENU_X
|
||||
ld d, MENU_HEIGHT
|
||||
ld d, (ix+MENU_T.height)
|
||||
ld e, MENU_WIDTH
|
||||
call draw_box
|
||||
|
||||
ld ix, var_menu
|
||||
ld hl, str_sizif
|
||||
ld b, MENU_Y*8
|
||||
ld b, (ix+MENU_T.y_pixel)
|
||||
ld c, MENU_X
|
||||
call print_string
|
||||
|
||||
ld b, MENU_Y*8
|
||||
ld ix, var_menu
|
||||
ld b, (ix+MENU_T.y_pixel)
|
||||
ld c, MENU_X+MENU_WIDTH-6
|
||||
ld e, 0
|
||||
call draw_logo
|
||||
@ -49,7 +62,8 @@ menu_animate_logo:
|
||||
ld a, 4 ; ...
|
||||
sub e ; ...
|
||||
ld e, a ; ...
|
||||
ld b, MENU_Y*8 ; draw logo
|
||||
ld ix, var_menu ;
|
||||
ld b, (ix+MENU_T.y_pixel) ; draw logo
|
||||
ld c, MENU_X+MENU_WIDTH-6 ; ...
|
||||
call draw_logo ; ...
|
||||
.return:
|
||||
@ -60,7 +74,9 @@ menu_animate_logo:
|
||||
; OUT - BC - garbage
|
||||
; OUT - DE - garbage
|
||||
; OUT - HL - garbage
|
||||
; OUT - IX - garbage
|
||||
menu_handle_updown:
|
||||
ld ix, var_menu
|
||||
call input_key_get ; A = current_pressed_key
|
||||
.down: ;
|
||||
bit 2, a ; down?
|
||||
@ -68,11 +84,10 @@ menu_handle_updown:
|
||||
ld a, (var_menu_current_item) ;
|
||||
ld d, MENU_BODY_ATTR ; fill selected item with background color
|
||||
call menu_draw_selected_item ; ...
|
||||
cp a, MENU_ITEMS-1 ; if (current_item == max) current_item = 0
|
||||
jr nz, .down_increment ; ...
|
||||
ld a, 255 ; ...
|
||||
.down_increment ; ...
|
||||
inc a ; current_item++
|
||||
cp a, (ix+MENU_T.items) ; if (current_item == max) current_item = 0
|
||||
jr nz, .return_save ; ...
|
||||
ld a, 0 ; ...
|
||||
jr .return_save ;
|
||||
.up: ;
|
||||
bit 3, a ; up?
|
||||
@ -82,7 +97,7 @@ menu_handle_updown:
|
||||
call menu_draw_selected_item ; ...
|
||||
or a ; if (current_item == 0) current_item = max
|
||||
jr nz, .up_decrement ; ...
|
||||
ld a, MENU_ITEMS ; ...
|
||||
ld a, (ix+MENU_T.items)
|
||||
.up_decrement ; ...
|
||||
dec a ; current_item--
|
||||
.return_save: ;
|
||||
@ -104,17 +119,20 @@ menu_handle_action_left_right:
|
||||
ld d, a
|
||||
and #13 ; action/left/right?
|
||||
jr z, .return
|
||||
ld a, d
|
||||
ld ix, var_menu ; IX = &menu
|
||||
ld c, (ix+MENU_T.addr+0) ; IX = &menu_entry
|
||||
ld b, (ix+MENU_T.addr+1) ; ...
|
||||
ld ixl, c ; ...
|
||||
ld ixh, b ; ...
|
||||
ld a, (var_menu_current_item) ; A = selected item index
|
||||
sla a ; A*8 (one menu entry - 8 bytes)
|
||||
sla a ; ...
|
||||
sla a ; ...
|
||||
ld ix, menu ; IX = &menu
|
||||
ld c, a ; IX = menu[index]
|
||||
ld c, a ; IX = &menu_entry[index].callback
|
||||
ld b, 0 ; ...
|
||||
add ix, bc ; ...
|
||||
ld l, (ix+4) ; HL = menu[index].callback
|
||||
ld h, (ix+5) ; ...
|
||||
ld l, (ix+MENUENTRY_T.callback+0) ; HL = menu_entry[index].callback
|
||||
ld h, (ix+MENUENTRY_T.callback+1) ; ...
|
||||
ld a, h ; if (HL == 0) - exit
|
||||
or l ; ...
|
||||
jr z, .return ; ...
|
||||
@ -132,23 +150,30 @@ menu_handle_action_left_right:
|
||||
; OUT - BC - garbage
|
||||
; OUT - E - garbage
|
||||
; OUT - HL - garbage
|
||||
; OUT - IX - garbage
|
||||
menu_draw_selected_item:
|
||||
push af
|
||||
ld b, MENU_Y+1
|
||||
ld ix, var_menu
|
||||
ld b, (ix+MENU_T.y_row)
|
||||
inc b
|
||||
add b
|
||||
ld b, a
|
||||
ld c, MENU_X
|
||||
ld e, MENU_WIDTH
|
||||
call draw_menu_item_line
|
||||
call draw_attribute_line
|
||||
pop af
|
||||
ret
|
||||
|
||||
|
||||
menu_draw_menu:
|
||||
ld b, MENU_Y*8+8
|
||||
ld ix, var_menu
|
||||
ld a, (ix+MENU_T.y_pixel)
|
||||
add a, 8
|
||||
ld b, a
|
||||
ld c, MENU_X+1
|
||||
ld e, MENU_WIDTH
|
||||
ld hl, menu
|
||||
ld l, (ix+MENU_T.addr+0)
|
||||
ld h, (ix+MENU_T.addr+1)
|
||||
call draw_menu
|
||||
ret
|
||||
|
||||
|
@ -1,34 +1,63 @@
|
||||
STRUCT MENU_T
|
||||
addr DW
|
||||
items DB
|
||||
height DB
|
||||
y_row DB
|
||||
y_pixel DB
|
||||
ENDS
|
||||
|
||||
STRUCT MENUENTRY_T
|
||||
text_addr DW
|
||||
value_cb_addr DW
|
||||
callback DW
|
||||
reserved DW
|
||||
ENDS
|
||||
|
||||
menu:
|
||||
MENU_T str_timings menu_timings_value_cb menu_timins_cb
|
||||
MENU_T str_cpu menu_clock_value_cb menu_clock_cb
|
||||
MENU_T str_panning menu_panning_value_cb menu_panning_cb
|
||||
MENU_T str_dac menu_dac_value_cb menu_dac_cb
|
||||
MENU_T str_joystick menu_joystick_value_cb menu_joystick_cb
|
||||
MENU_T str_ram menu_ram_value_cb menu_ram_cb
|
||||
MENU_T str_rom48 menu_rom48_value_cb menu_rom48_cb
|
||||
MENU_T str_plus3 menu_plus3_value_cb menu_plus3_cb
|
||||
MENU_T str_divmmc menu_divmmc_value_cb menu_divmmc_cb
|
||||
MENU_T str_ulaplus menu_ulaplus_value_cb menu_ulaplus_cb
|
||||
MENU_T str_exit menu_exit_value_cb menu_exit_cb
|
||||
MENU_T 0
|
||||
MENU_ITEMS EQU ($-menu)/MENU_T-1
|
||||
MACRO MENUDESCR label_addr, items
|
||||
MENU_T (label_addr) (items) (items+2) ((24-(items+2))/2) (((24-(items+2))/2)*8)
|
||||
ENDM
|
||||
|
||||
.menu:
|
||||
MENUENTRY_T str_machine menu_machine_value_cb menu_machine_cb
|
||||
MENUENTRY_T str_cpu menu_clock_value_cb menu_clock_cb
|
||||
MENUENTRY_T str_panning menu_panning_value_cb menu_panning_cb
|
||||
MENUENTRY_T str_joystick menu_joystick_value_cb menu_joystick_cb
|
||||
IFNDEF SIZIFXXS
|
||||
MENUENTRY_T str_rom48 menu_rom48_value_cb menu_rom48_cb
|
||||
ENDIF
|
||||
MENUENTRY_T str_divmmc menu_divmmc_value_cb menu_divmmc_cb
|
||||
MENUENTRY_T str_ulaplus menu_ulaplus_value_cb menu_ulaplus_cb
|
||||
MENUENTRY_T str_dac menu_dac_value_cb menu_dac_cb
|
||||
MENUENTRY_T str_exit menu_exit_value_cb menu_exit_cb
|
||||
MENUENTRY_T 0
|
||||
!menu: MENUDESCR .menu, ($-.menu)/MENUENTRY_T-1
|
||||
|
||||
.menuext:
|
||||
MENUENTRY_T str_machine menu_machine_value_cb menu_machine_cb
|
||||
MENUENTRY_T str_cpu menu_clock_value_cb menu_clock_cb
|
||||
MENUENTRY_T str_panning menu_panning_value_cb menu_panning_cb
|
||||
MENUENTRY_T str_joystick menu_joystick_value_cb menu_joystick_cb
|
||||
MENUENTRY_T str_rom48 menu_rom48_value_cb menu_rom48_cb
|
||||
MENUENTRY_T str_divmmc menu_divmmc_value_cb menu_divmmc_cb
|
||||
MENUENTRY_T str_ulaplus menu_ulaplus_value_cb menu_ulaplus_cb
|
||||
MENUENTRY_T str_dac menu_dac_value_cb menu_dac_cb
|
||||
MENUENTRY_T str_tsfm menu_tsfm_value_cb menu_tsfm_cb
|
||||
MENUENTRY_T str_saa menu_saa_value_cb menu_saa_cb
|
||||
MENUENTRY_T str_gs menu_gs_value_cb menu_gs_cb
|
||||
MENUENTRY_T str_exit menu_exit_value_cb menu_exit_cb
|
||||
MENUENTRY_T 0
|
||||
!menuext: MENUDESCR .menuext, ($-.menuext)/MENUENTRY_T-1
|
||||
|
||||
|
||||
menu_timings_value_cb:
|
||||
menu_machine_value_cb:
|
||||
ld ix, .values_table
|
||||
ld a, (cfg.timings)
|
||||
ld a, (cfg.machine)
|
||||
jp menu_value_get
|
||||
.values_table:
|
||||
DW str_timings_pentagon_end-2
|
||||
DW str_timings_48_end-2
|
||||
DW str_timings_128_end-2
|
||||
DW str_machine_48_end-2
|
||||
DW str_machine_128_end-2
|
||||
DW str_machine_3e_end-2
|
||||
DW str_machine_pentagon_end-2
|
||||
|
||||
menu_clock_value_cb:
|
||||
ld ix, .values_table
|
||||
@ -36,17 +65,32 @@ menu_clock_value_cb:
|
||||
jp menu_value_get
|
||||
.values_table:
|
||||
DW str_cpu_35_end-2
|
||||
DW str_cpu_44_end-2
|
||||
DW str_cpu_52_end-2
|
||||
DW str_cpu_7_end-2
|
||||
DW str_cpu_14_end-2
|
||||
|
||||
menu_panning_value_cb:
|
||||
ld ix, .values_table
|
||||
ld a, (var_ext_presence) ; if (ext_board && tsfm) - use ABC instead of ACB panning
|
||||
or a ; ...
|
||||
jr z, .no_tsfm ; ...
|
||||
ld a, (cfgext.tsfm) ; ...
|
||||
or a ; ...
|
||||
jr z, .no_tsfm ; ...
|
||||
ld a, (cfg.panning)
|
||||
cp a, 2 ; if (panning == acb) panning = abc
|
||||
jr c, .get ; ...
|
||||
dec a ; ...
|
||||
.get
|
||||
jp menu_value_get
|
||||
.no_tsfm:
|
||||
ld a, (cfg.panning)
|
||||
jp menu_value_get
|
||||
.values_table:
|
||||
DW str_panning_mono_end-2
|
||||
DW str_panning_abc_end-2
|
||||
DW str_panning_acb_end-2
|
||||
DW str_panning_mono_end-2
|
||||
|
||||
menu_joystick_value_cb:
|
||||
ld ix, .values_table
|
||||
@ -56,41 +100,14 @@ menu_joystick_value_cb:
|
||||
DW str_joystick_kempston_end-2
|
||||
DW str_joystick_sinclair_end-2
|
||||
|
||||
menu_ram_value_cb:
|
||||
ld ix, .values_table
|
||||
ld a, (cfg.ram)
|
||||
or a
|
||||
jr nz, .less_than_512K
|
||||
ld a, (cfg.divmmc) ; 256K with divmmc
|
||||
or a ; ...
|
||||
jr z, .is_512K ; ...
|
||||
ld a, 3 ; ...
|
||||
jp menu_value_get
|
||||
.is_512K:
|
||||
xor a
|
||||
.less_than_512K:
|
||||
jp menu_value_get
|
||||
.values_table:
|
||||
DW str_ram_512_end-2
|
||||
DW str_ram_48_end-2
|
||||
DW str_ram_128_end-2
|
||||
DW str_ram_256_end-2
|
||||
|
||||
menu_rom48_value_cb:
|
||||
ld ix, .values_table
|
||||
ld a, (cfg.rom48)
|
||||
jp menu_value_get
|
||||
.values_table:
|
||||
DW str_rom48_default_end-2
|
||||
DW str_rom48_alt_end-2
|
||||
|
||||
menu_plus3_value_cb:
|
||||
ld ix, .values_table
|
||||
ld a, (cfg.plus3)
|
||||
jp menu_value_get
|
||||
.values_table:
|
||||
DW str_off_end-2
|
||||
DW str_on_end-2
|
||||
DW str_rom48_lg_end-2
|
||||
DW str_rom48_opense_end-2
|
||||
|
||||
menu_divmmc_value_cb:
|
||||
ld ix, .values_table
|
||||
@ -99,6 +116,7 @@ menu_divmmc_value_cb:
|
||||
.values_table:
|
||||
DW str_off_end-2
|
||||
DW str_on_end-2
|
||||
DW str_divmmc_noos_end-2
|
||||
|
||||
menu_ulaplus_value_cb:
|
||||
ld ix, .values_table
|
||||
@ -118,6 +136,31 @@ menu_dac_value_cb:
|
||||
DW str_dac_sd_end-2
|
||||
DW str_dac_covoxsd_end-2
|
||||
|
||||
menu_tsfm_value_cb:
|
||||
ld ix, .values_table
|
||||
ld a, (cfgext.tsfm)
|
||||
jp menu_value_get
|
||||
.values_table:
|
||||
DW str_off_end-2
|
||||
DW str_on_end-2
|
||||
|
||||
menu_saa_value_cb:
|
||||
ld ix, .values_table
|
||||
ld a, (cfgext.saa)
|
||||
jp menu_value_get
|
||||
.values_table:
|
||||
DW str_off_end-2
|
||||
DW str_on_end-2
|
||||
|
||||
menu_gs_value_cb:
|
||||
ld ix, .values_table
|
||||
ld a, (cfgext.gs)
|
||||
jp menu_value_get
|
||||
.values_table:
|
||||
DW str_off_end-2
|
||||
DW str_on_end-2
|
||||
|
||||
|
||||
menu_exit_value_cb:
|
||||
ld ix, .values_table
|
||||
ld a, (var_exit_reboot)
|
||||
@ -136,18 +179,18 @@ menu_value_get:
|
||||
ret
|
||||
|
||||
|
||||
menu_timins_cb:
|
||||
ld a, (cfg.timings)
|
||||
ld c, 2
|
||||
menu_machine_cb:
|
||||
ld a, (cfg.machine)
|
||||
ld c, 3
|
||||
call menu_handle_press
|
||||
ld (cfg.timings), a
|
||||
ld (cfg.machine), a
|
||||
ld bc, #02ff
|
||||
out (c), a
|
||||
ret
|
||||
|
||||
menu_clock_cb:
|
||||
ld a, (cfg.clock)
|
||||
ld c, 2
|
||||
ld c, 4
|
||||
call menu_handle_press
|
||||
ld (cfg.clock), a
|
||||
ld bc, #03ff
|
||||
@ -155,8 +198,19 @@ menu_clock_cb:
|
||||
ret
|
||||
|
||||
menu_panning_cb:
|
||||
ld a, (var_ext_presence) ; if (ext_board && tsfm) - do not allow to set ACB panning
|
||||
or a ; ...
|
||||
jr z, .no_tsfm ; ...
|
||||
ld a, (cfgext.tsfm) ; ...
|
||||
or a ; ...
|
||||
jr z, .no_tsfm ; ...
|
||||
ld a, (cfg.panning) ; ...
|
||||
ld c, 1 ; ...
|
||||
jr .load
|
||||
.no_tsfm:
|
||||
ld a, (cfg.panning)
|
||||
ld c, 2
|
||||
.load:
|
||||
call menu_handle_press
|
||||
ld (cfg.panning), a
|
||||
ld bc, #04ff
|
||||
@ -172,36 +226,22 @@ menu_joystick_cb:
|
||||
out (c), a
|
||||
ret
|
||||
|
||||
menu_ram_cb:
|
||||
ld a, (cfg.ram)
|
||||
ld c, 2
|
||||
call menu_handle_press
|
||||
ld (cfg.ram), a
|
||||
ld bc, #08ff
|
||||
out (c), a
|
||||
ret
|
||||
|
||||
menu_rom48_cb:
|
||||
ld a, (cfg.rom48)
|
||||
IFDEF REV_C
|
||||
ld c, 1
|
||||
ELSE
|
||||
ld c, 2
|
||||
ENDIF
|
||||
call menu_handle_press
|
||||
ld (cfg.rom48), a
|
||||
ld bc, #06ff
|
||||
out (c), a
|
||||
ret
|
||||
|
||||
menu_plus3_cb:
|
||||
ld a, (cfg.plus3)
|
||||
ld c, 1
|
||||
call menu_handle_press
|
||||
ld (cfg.plus3), a
|
||||
ld bc, #05ff
|
||||
out (c), a
|
||||
ret
|
||||
|
||||
menu_divmmc_cb:
|
||||
ld a, (cfg.divmmc)
|
||||
ld c, 1
|
||||
ld c, 2
|
||||
call menu_handle_press
|
||||
ld (cfg.divmmc), a
|
||||
ld bc, #09ff
|
||||
@ -226,6 +266,33 @@ menu_dac_cb:
|
||||
out (c), a
|
||||
ret
|
||||
|
||||
menu_tsfm_cb:
|
||||
ld a, (cfgext.tsfm)
|
||||
ld c, 1
|
||||
call menu_handle_press
|
||||
ld (cfgext.tsfm), a
|
||||
ld bc, #e1ff
|
||||
out (c), a
|
||||
ret
|
||||
|
||||
menu_saa_cb:
|
||||
ld a, (cfgext.saa)
|
||||
ld c, 1
|
||||
call menu_handle_press
|
||||
ld (cfgext.saa), a
|
||||
ld bc, #e2ff
|
||||
out (c), a
|
||||
ret
|
||||
|
||||
menu_gs_cb:
|
||||
ld a, (cfgext.gs)
|
||||
ld c, 1
|
||||
call menu_handle_press
|
||||
ld (cfgext.gs), a
|
||||
ld bc, #e3ff
|
||||
out (c), a
|
||||
ret
|
||||
|
||||
menu_exit_cb:
|
||||
bit 4, d ; action?
|
||||
jr nz, .exit
|
||||
@ -253,8 +320,8 @@ menu_handle_press:
|
||||
jr nz, .decrement
|
||||
ret
|
||||
.increment:
|
||||
cp c ; if (value == max) value = 0
|
||||
jr z, .increment_roll ; ...
|
||||
cp c ; if (value >= max) value = 0
|
||||
jr nc, .increment_roll ; ...
|
||||
inc a ; else value++
|
||||
ret
|
||||
.increment_roll:
|
||||
|
33
rom_src/pause.asm
Normal file
33
rom_src/pause.asm
Normal file
@ -0,0 +1,33 @@
|
||||
pause_init:
|
||||
ld d, PAUSE_BODY_ATTR
|
||||
ld c, PAUSE_X
|
||||
ld b, PAUSE_Y
|
||||
ld e, PAUSE_WIDTH
|
||||
call draw_attribute_line
|
||||
ld b, PAUSE_Y+2
|
||||
ld e, PAUSE_WIDTH
|
||||
call draw_attribute_line
|
||||
ld d, PAUSE_TEXT_ATTR
|
||||
ld b, PAUSE_Y+1
|
||||
ld e, PAUSE_WIDTH
|
||||
call draw_attribute_line
|
||||
ld b, (PAUSE_Y+1)<<3
|
||||
ld hl, str_pause
|
||||
call print_string
|
||||
ret
|
||||
|
||||
pause_process:
|
||||
ld a, #ff ; read pause key state in bit 1 of #FFFF port
|
||||
in a, (#ff) ; ...
|
||||
bit 1, a ; check key is hold
|
||||
jr nz, .is_hold ; yes?
|
||||
ld a, 1
|
||||
ld (var_pause_is_released), a
|
||||
ret
|
||||
.is_hold:
|
||||
ld a, (var_pause_is_released) ; if key wasnt released - do nothing
|
||||
or a ; ...
|
||||
ret z ; ...
|
||||
ld a, 1 ; otherwise - var_exit_flag = 1
|
||||
ld (var_exit_flag), a ; ...
|
||||
ret
|
@ -10,6 +10,9 @@ str_sizif: DB "SIZIF-512",0
|
||||
str_sizif_end:
|
||||
ENDIF
|
||||
|
||||
str_pause DB " PAUSE ",0
|
||||
str_pause_end:
|
||||
|
||||
str_exit: DB "Exit",0
|
||||
str_exit_end:
|
||||
|
||||
@ -25,17 +28,20 @@ str_on_end:
|
||||
str_off: DB " OFF",0
|
||||
str_off_end:
|
||||
|
||||
str_timings: DB "Timings",0
|
||||
str_timings_end:
|
||||
str_machine: DB "Machine",0
|
||||
str_machine_end:
|
||||
|
||||
str_timings_pentagon: DB "Pentagon",0
|
||||
str_timings_pentagon_end:
|
||||
str_machine_48: DB " 48",0
|
||||
str_machine_48_end:
|
||||
|
||||
str_timings_128: DB " 128",0
|
||||
str_timings_128_end:
|
||||
str_machine_128: DB " 128",0
|
||||
str_machine_128_end:
|
||||
|
||||
str_timings_48: DB " 48",0
|
||||
str_timings_48_end:
|
||||
str_machine_3e: DB " +3e",0
|
||||
str_machine_3e_end:
|
||||
|
||||
str_machine_pentagon: DB "Pentagon",0
|
||||
str_machine_pentagon_end:
|
||||
|
||||
str_cpu: DB "CPU freq",0
|
||||
str_cpu_end:
|
||||
@ -43,6 +49,12 @@ str_cpu_end:
|
||||
str_cpu_35: DB "3.5MHz",0
|
||||
str_cpu_35_end:
|
||||
|
||||
str_cpu_44: DB "4.4MHz",0
|
||||
str_cpu_44_end:
|
||||
|
||||
str_cpu_52: DB "5.2MHz",0
|
||||
str_cpu_52_end:
|
||||
|
||||
str_cpu_7: DB " 7MHz",0
|
||||
str_cpu_7_end:
|
||||
|
||||
@ -76,29 +88,17 @@ str_rom48_end:
|
||||
str_rom48_default: DB "Default",0
|
||||
str_rom48_default_end:
|
||||
|
||||
str_rom48_alt: DB " Alt",0
|
||||
str_rom48_alt_end:
|
||||
str_rom48_lg: DB " LG",0
|
||||
str_rom48_lg_end:
|
||||
|
||||
str_plus3: DB "+3",0
|
||||
str_plus3_end:
|
||||
str_rom48_opense: DB " OpenSE",0
|
||||
str_rom48_opense_end:
|
||||
|
||||
str_divmmc: DB "DivMMC",0
|
||||
str_divmmc_end:
|
||||
|
||||
str_ram: DB "RAM",0
|
||||
str_ram_end:
|
||||
|
||||
str_ram_48: DB " 48K",0
|
||||
str_ram_48_end:
|
||||
|
||||
str_ram_128: DB "128K",0
|
||||
str_ram_128_end:
|
||||
|
||||
str_ram_256: DB "256K",0
|
||||
str_ram_256_end:
|
||||
|
||||
str_ram_512: DB "512K",0
|
||||
str_ram_512_end:
|
||||
str_divmmc_noos: DB "NO OS",0
|
||||
str_divmmc_noos_end:
|
||||
|
||||
str_ulaplus: DB "ULA+",0
|
||||
str_ulaplus_end
|
||||
@ -109,8 +109,17 @@ str_dac_end
|
||||
str_dac_covox: DB " Covox",0
|
||||
str_dac_covox_end
|
||||
|
||||
str_dac_sd: DB "SounDrive",0
|
||||
str_dac_sd: DB " SD",0
|
||||
str_dac_sd_end
|
||||
|
||||
str_dac_covoxsd: DB " Covox+SD",0
|
||||
str_dac_covoxsd: DB "Covox+SD",0
|
||||
str_dac_covoxsd_end
|
||||
|
||||
str_tsfm: DB "TSFM+MIDI",0
|
||||
str_tsfm_end
|
||||
|
||||
str_saa: DB "SAA1099",0
|
||||
str_saa_end
|
||||
|
||||
str_gs: DB "GS",0
|
||||
str_gs_end
|
||||
|
23
rom_src/variables.asm
Normal file
23
rom_src/variables.asm
Normal file
@ -0,0 +1,23 @@
|
||||
var_save_ay: .32 DB 0
|
||||
var_save_ulaplus: DB 0
|
||||
var_sp_reg: DW 0
|
||||
var_int_vector: DW 0
|
||||
var_magic_enter_cnt: DB 0
|
||||
var_magic_leave_cnt: DB 0
|
||||
var_exit_flag: DB 0
|
||||
var_exit_reboot: DB 0
|
||||
var_input_key: DB 0
|
||||
var_input_key_last: DB 0
|
||||
var_input_key_hold_timer: DB 0
|
||||
var_pause_flag: DB 0
|
||||
var_pause_is_released: DB 0
|
||||
var_menu_current_item: DB 0
|
||||
var_menu_animate_cnt: DB 0
|
||||
var_menu: MENU_T
|
||||
var_ext_presence: DB 1
|
||||
|
||||
cfg CFG_T
|
||||
cfgext CFGEXT_T
|
||||
cfg_saved CFG_T
|
||||
cfgext_saved CFGEXT_T
|
||||
cfg_initialized: DB #B1, #5B, #00, #B5
|
Reference in New Issue
Block a user