diff --git a/fpga/rtl/common.sv b/fpga/rtl/common.sv index 69ec6c7..91218f5 100755 --- a/fpga/rtl/common.sv +++ b/fpga/rtl/common.sv @@ -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 diff --git a/fpga/rtl/cpucontrol.sv b/fpga/rtl/cpucontrol.sv index 5a469e2..27e11fd 100755 --- a/fpga/rtl/cpucontrol.sv +++ b/fpga/rtl/cpucontrol.sv @@ -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 diff --git a/fpga/rtl/divmmc.sv b/fpga/rtl/divmmc.sv index 4cf24ea..71ae4b3 100755 --- a/fpga/rtl/divmmc.sv +++ b/fpga/rtl/divmmc.sv @@ -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; diff --git a/fpga/rtl/magic.sv b/fpga/rtl/magic.sv index c08efd1..b54a556 100755 --- a/fpga/rtl/magic.sv +++ b/fpga/rtl/magic.sv @@ -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 diff --git a/fpga/rtl/memcontrol.sv b/fpga/rtl/memcontrol.sv new file mode 100644 index 0000000..fa03bc6 --- /dev/null +++ b/fpga/rtl/memcontrol.sv @@ -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 diff --git a/fpga/rtl/ports.sv b/fpga/rtl/ports.sv index 7553a23..3c8f7ec 100755 --- a/fpga/rtl/ports.sv +++ b/fpga/rtl/ports.sv @@ -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; diff --git a/fpga/rtl/ps2.v b/fpga/rtl/ps2.v index 4c3dceb..38646ed 100644 --- a/fpga/rtl/ps2.v +++ b/fpga/rtl/ps2.v @@ -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; diff --git a/fpga/rtl/screen.sv b/fpga/rtl/screen.sv index 3333075..9c10593 100755 --- a/fpga/rtl/screen.sv +++ b/fpga/rtl/screen.sv @@ -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,28 +263,42 @@ 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 if (blank) {g, r, b} = 0; 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]; + g = pixel? up_ink0[7:5] : up_paper0[7:5]; + r = pixel? up_ink0[4:2] : up_paper0[4:2]; + 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; diff --git a/fpga/rtl/top.sv b/fpga/rtl/top.sv index a16b92d..1b72c54 100755 --- a/fpga/rtl/top.sv +++ b/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 diff --git a/fpga/syn/zx_ula.qsf b/fpga/syn/zx_ula.qsf index 3df8dbf..f54d91b 100755 --- a/fpga/syn/zx_ula.qsf +++ b/fpga/syn/zx_ula.qsf @@ -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 diff --git a/fpga/tb/Makefile b/fpga/tb/Makefile index 7afba23..47f2039 100644 --- a/fpga/tb/Makefile +++ b/fpga/tb/Makefile @@ -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 diff --git a/fpga/tb/rom.asm b/fpga/tb/rom.asm index 6fdf9aa..6b54a52 100644 --- a/fpga/tb/rom.asm +++ b/fpga/tb/rom.asm @@ -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: diff --git a/fpga/tb/testbench_zx_ula.v b/fpga/tb/testbench_zx_ula.v index 8b9501d..747adca 100644 --- a/fpga/tb/testbench_zx_ula.v +++ b/fpga/tb/testbench_zx_ula.v @@ -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 diff --git a/rom/Makefile b/rom/Makefile index 95ff91c..20dc345 100644 --- a/rom/Makefile +++ b/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 diff --git a/rom/opense.rom b/rom/opense.rom deleted file mode 100644 index 267b78d..0000000 Binary files a/rom/opense.rom and /dev/null differ diff --git a/rom/zero8k.bin b/rom/zero8k.bin new file mode 100644 index 0000000..6d17cf9 Binary files /dev/null and b/rom/zero8k.bin differ diff --git a/rom_src/Makefile b/rom_src/Makefile index 95e089d..cf6bdae 100644 --- a/rom_src/Makefile +++ b/rom_src/Makefile @@ -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: diff --git a/rom_src/config.asm b/rom_src/config.asm index f84e82c..fa96241 100644 --- a/rom_src/config.asm +++ b/rom_src/config.asm @@ -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 -clock DB 0 -panning DB 0 -plus3 DB 0 -rom48 DB 0 -joystick DB 0 -ram DB 0 -divmmc DB 1 -ulaplus DB 1 -dac DB 3 +_reserv0 DB 0 +_reserv1 DB 0 +machine DB 3 +clock DB 0 +panning DB 1 +custom_rom DB 0 +rom48 DB 0 +joystick DB 0 +_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 diff --git a/rom_src/draw.asm b/rom_src/draw.asm index 7581f83..6f8f972 100644 --- a/rom_src/draw.asm +++ b/rom_src/draw.asm @@ -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 diff --git a/rom_src/font.asm b/rom_src/font.asm index c3390e5..d4d00d3 100644 --- a/rom_src/font.asm +++ b/rom_src/font.asm @@ -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: diff --git a/rom_src/input.asm b/rom_src/input.asm index ef15fdd..1cd719e 100644 --- a/rom_src/input.asm +++ b/rom_src/input.asm @@ -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 diff --git a/rom_src/main.asm b/rom_src/main.asm index f4e8661..cb5ec65 100644 --- a/rom_src/main.asm +++ b/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... - bit 0, a ; ...default nmi handler, A == 0 otherwise - jp nz, main ; ... - bit 1, a ; ... - jr z, .loop ; ... + 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, 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,80 +116,193 @@ 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 de, cfg_saved ; ... - ld hl, cfg ; ... - ldir ; ... + ld bc, CFG_T+CFGEXT_T ; cfg_saved = cfg + ld de, cfg_saved ; ... + ld hl, cfg ; ... + ldir ; ... ret init_cpld: -.check_ram48k: - ld a, (cfg.ram) ; if ram == 48K - run basic48 - cp 1 ; ... - jr nz, .check_plus3_disabled ; ... - ld a, #10 ; ... - ld bc, #7ffd ; ... - out (c), a ; ... - ld a, #4 ; ... - ld bc, #1ffd ; ... - 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 - ld bc, #1ffd ; ... - out (c), a ; ... +.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 ; ... +.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 ; ... +.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: ld b, CFG_T ; B = registers count 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 ; ... @@ -287,11 +445,20 @@ restore: ldir .restore_ay: ld hl, var_save_ay+16 ; select second AY chip in TurboSound - ld a, #fe ; ... + ld a, #fe ; ... call .restore_ay_sub - ld hl, var_save_ay ; select first AY chip in TurboSound - ld a, #ff ; ... + 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: diff --git a/rom_src/main_test.asm b/rom_src/main_test.asm index 9cb8660..5cf0fef 100644 --- a/rom_src/main_test.asm +++ b/rom_src/main_test.asm @@ -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" diff --git a/rom_src/menu.asm b/rom_src/menu.asm index 53e68fb..0355fb3 100644 --- a/rom_src/menu.asm +++ b/rom_src/menu.asm @@ -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 diff --git a/rom_src/menu_structure.asm b/rom_src/menu_structure.asm index 7e03a32..24e593d 100644 --- a/rom_src/menu_structure.asm +++ b/rom_src/menu_structure.asm @@ -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) - ld c, 1 + 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: diff --git a/rom_src/pause.asm b/rom_src/pause.asm new file mode 100644 index 0000000..2f9e33b --- /dev/null +++ b/rom_src/pause.asm @@ -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 diff --git a/rom_src/strings.asm b/rom_src/strings.asm index bc4bb00..82afee5 100644 --- a/rom_src/strings.asm +++ b/rom_src/strings.asm @@ -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: @@ -19,23 +22,26 @@ str_exit_reboot_end: str_exit_no_reboot: DB " ",0 str_exit_no_reboot_end: -str_on: DB " ON",0 +str_on: DB " ON",0 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 @@ -106,11 +106,20 @@ str_ulaplus_end str_dac: DB "DAC",0 str_dac_end -str_dac_covox: DB " Covox",0 +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 diff --git a/rom_src/variables.asm b/rom_src/variables.asm new file mode 100644 index 0000000..26114a9 --- /dev/null +++ b/rom_src/variables.asm @@ -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