mirror of
https://github.com/MiSTer-devel/CDi_MiSTer.git
synced 2026-05-17 03:03:25 +00:00
FMV: Fixed timing of frame events and parameters
- Decoupled SEQ event from GOP event. Now behaves like real VMPEG hardware - Fixes Lost Ride gameplay after vehicle charge intro - Fixes timing accuracy of temp ref and time code Measurable with mv_status()
This commit is contained in:
11
CDi.sdc
11
CDi.sdc
@@ -34,4 +34,13 @@ set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|latched_window_offs
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|latched_window_offset_x*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|frameplayer:frameplayer|window_x_clkddr*}
|
||||
|
||||
# protection not required because of context
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|fmv_slow_motion*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|slow_motion_clkddr*}
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|fmv_slow_motion*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|slow_motion_clkddr*}
|
||||
|
||||
# protected by latency between latch_frame_for_display and latch_frame_for_display_clk_mpeg
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|display_timecode*}
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|display_tempref*}
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|display_width*}
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|display_height*}
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|first_intra_frame_of_gop_clk30}
|
||||
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|first_intra_frame_of_seq_clk30}
|
||||
|
||||
|
||||
2
CDi.sv
2
CDi.sv
@@ -230,7 +230,7 @@ module emu (
|
||||
"P2F1,ROM,Replace Boot ROM;",
|
||||
"P2O[2],Disable Audio Att.,No,Yes;",
|
||||
"P2O[3],UART Fake Space,No,Yes;",
|
||||
"P2O[7:6],Force Video Plane,Original,A,B;",
|
||||
"P2O[7:6],Force Video Plane,Original,A,B,DVC;",
|
||||
"P2O[12],SERVO Audio CD,No,Yes;",
|
||||
"P2O[17],Disable VCD pixel clock,No,Yes;",
|
||||
"P2O[18],Activate VCD filter,Yes,No;",
|
||||
|
||||
@@ -188,6 +188,8 @@ by emulation errors but are also present on the real machine.
|
||||
* During the intro of "The Ultimate Noah's Ark", the Mike Wilks artwork has repeated pixels on the bottom and right edge.
|
||||
* This looks wrong but real hardware does that too.
|
||||
* There is also a weirdly wrong column of pixels during the title page on the left inside the black frame
|
||||
* "Marlboro – Follow Your Dreams" is not booting and hangs on a cyan screen
|
||||
* You are probably using NTSC mode. Being made by a German publisher, this title was probably only tested on European models. It behaves like this on real hardware as well
|
||||
|
||||
## Simulation
|
||||
|
||||
|
||||
@@ -223,3 +223,13 @@ cat log | grep 'FMV INT\|XFER\|DVC Read e04062\|PIC2\|GOP' > log2
|
||||
|
||||
1 Overclock input device No, Yes
|
||||
(it is rather long. It could be shorter?)
|
||||
|
||||
|
||||
Lost Ride:
|
||||
|
||||
Syscall @ ded9b2 8e I$SetStt 00000006 00000122 00000002 00000900 0000ab00 00001999 0000bca0 00000000 00df9340 00000000 00d0d1d8 00dffd90 00d0bc98 00d0bb26 00d08000 00dfd428 SetStt MA_Loop
|
||||
Syscall @ deda82 8e I$SetStt 00000006 00000124 00000002 00000000 0000bd00 00000000 0000ffff 00000000 00df9340 00040e20 00d0d1d8 00dffd90 00d03b56 00d0bb26 00d08000 00dfd428 SetStt MA_Play
|
||||
FMA Write Stream Number 1804 0000
|
||||
FMA IER 180e 013d
|
||||
FMA CMD 1800 0002
|
||||
Syscall @ ded8c6 8e I$SetStt 00000006 00000120 00000002 00800080 f5020000 00000000 0000bca0 00000000 00df9340 00000000 00d0d1d8 00dffd90 00d0bc98 00d0bb26 00d08000 00dfd428 SetStt MA_Cntrl
|
||||
|
||||
@@ -385,7 +385,8 @@ module cditop (
|
||||
.ddrif
|
||||
);
|
||||
|
||||
assign vidout = mcd212_vsd ? fmv_video_out : mcd212_video_out;
|
||||
wire force_dvc_video = debug_force_video_plane == 2'b11;
|
||||
assign vidout = (mcd212_vsd || force_dvc_video) ? fmv_video_out : mcd212_video_out;
|
||||
|
||||
`ifndef DISABLE_MAIN_CPU
|
||||
wire reset68k;
|
||||
|
||||
@@ -1353,7 +1353,7 @@ module mcd212 (
|
||||
|
||||
vsd = backdrop_pixel && image_coding_method_register.ev;
|
||||
`ifdef VERILATOR
|
||||
// vsd = 1;
|
||||
//vsd = 1;
|
||||
`endif
|
||||
end
|
||||
|
||||
|
||||
@@ -55,6 +55,11 @@ module mpeg_audio (
|
||||
event_frame_decoded <= 0;
|
||||
event_underflow <= 0;
|
||||
|
||||
if (fifo_full) begin
|
||||
$display("AUDIO FIFO FULL");
|
||||
$finish();
|
||||
end
|
||||
|
||||
if (reset || reset_input_fifo) begin
|
||||
mpeg_stream_fifo_write_adr <= 0;
|
||||
mpeg_stream_bit_index <= 0;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,12 +37,16 @@ module mpeg_video (
|
||||
output event_buffer_underflow,
|
||||
output bit event_picture_starts_display,
|
||||
output event_last_picture_starts_display,
|
||||
output bit event_first_intra_frame_starts_display,
|
||||
output bit event_first_intra_frame_gop_starts_display,
|
||||
output bit event_first_intra_frame_seq_starts_display,
|
||||
output [4:0] pictures_in_fifo,
|
||||
|
||||
output bit [10:0] decoder_width,
|
||||
output bit [ 8:0] decoder_height,
|
||||
output bit [ 7:0] decoder_tempref,
|
||||
output bit [10:0] display_width,
|
||||
output bit [ 8:0] display_height,
|
||||
output bit [ 7:0] display_tempref,
|
||||
output bit [31:0] display_timecode,
|
||||
output bit [15:0] decoder_frameperiod_90khz,
|
||||
output bit [ 7:0] decoder_frameperiod_rawhdr
|
||||
);
|
||||
@@ -594,6 +598,12 @@ module mpeg_video (
|
||||
if (dmem_cmd_payload_address_1[15:0] == 16'h3038) begin
|
||||
just_decoded.tempref <= dmem_cmd_payload_data_1[7:0];
|
||||
end
|
||||
if (dmem_cmd_payload_address_1[15:0] == 16'h3044) begin
|
||||
just_decoded.timecode <= dmem_cmd_payload_data_1;
|
||||
end
|
||||
if (dmem_cmd_payload_address_1[15:0] == 16'h3048) begin
|
||||
just_decoded.first_intra_frame_of_seq <= dmem_cmd_payload_data_1[0];
|
||||
end
|
||||
|
||||
if (dmem_cmd_payload_address_1[15:0] == 16'h2010) begin
|
||||
has_sequence_header <= dmem_cmd_payload_data_1[0];
|
||||
@@ -638,8 +648,8 @@ module mpeg_video (
|
||||
bit [23:0] playback_frame_cnt;
|
||||
|
||||
bit latch_frame_until_vblank = 0;
|
||||
bit first_intra_frame_of_gop_in_prep;
|
||||
bit first_intra_frame_of_gop_clk30;
|
||||
bit first_intra_frame_of_seq_clk30;
|
||||
|
||||
bit vblank_q1;
|
||||
bit vblank_q2;
|
||||
@@ -658,14 +668,18 @@ module mpeg_video (
|
||||
.flag_out_clk_b(just_decoded_commit_clk30)
|
||||
);
|
||||
|
||||
|
||||
always_ff @(posedge clk30) begin
|
||||
vblank_q1 <= vblank;
|
||||
vblank_q2 <= vblank_q1;
|
||||
|
||||
if (latch_frame_for_display) begin
|
||||
decoder_width <= for_display.width;
|
||||
decoder_height <= for_display.height;
|
||||
decoder_tempref <= for_display.tempref;
|
||||
display_width <= for_display.width;
|
||||
display_height <= for_display.height;
|
||||
display_tempref <= for_display.tempref;
|
||||
display_timecode <= for_display.timecode;
|
||||
first_intra_frame_of_gop_clk30 <= for_display.first_intra_frame_of_gop;
|
||||
first_intra_frame_of_seq_clk30 <= for_display.first_intra_frame_of_seq;
|
||||
end
|
||||
|
||||
if (just_decoded_commit_clk30) begin
|
||||
@@ -680,16 +694,18 @@ module mpeg_video (
|
||||
decoder_width <= 0;
|
||||
decoder_height <= 0;
|
||||
frame_period <= 0;
|
||||
decoder_tempref <= 0;
|
||||
display_tempref <= 0;
|
||||
display_timecode <= 0;
|
||||
decoder_frameperiod_90khz <= 0;
|
||||
decoder_frameperiod_rawhdr <= 0;
|
||||
end
|
||||
|
||||
for_display_valid <= for_display_valid_clk_mpeg;
|
||||
first_intra_frame_of_gop_clk30 <= for_display.first_intra_frame_of_gop;
|
||||
|
||||
|
||||
event_picture_starts_display <= 0;
|
||||
event_first_intra_frame_starts_display <= 0;
|
||||
event_first_intra_frame_gop_starts_display <= 0;
|
||||
event_first_intra_frame_seq_starts_display <= 0;
|
||||
event_last_picture_starts_display <= 0;
|
||||
|
||||
latch_frame_for_display <= 0;
|
||||
@@ -697,7 +713,8 @@ module mpeg_video (
|
||||
if (latch_frame_until_vblank && !vblank && vblank_q1 && vblank_q2) begin
|
||||
latch_frame_until_vblank <= 0;
|
||||
event_picture_starts_display <= 1;
|
||||
event_first_intra_frame_starts_display <= first_intra_frame_of_gop_in_prep;
|
||||
event_first_intra_frame_gop_starts_display <= first_intra_frame_of_gop_clk30;
|
||||
event_first_intra_frame_seq_starts_display <= first_intra_frame_of_seq_clk30;
|
||||
event_last_picture_starts_display <= !for_display_valid;
|
||||
end
|
||||
|
||||
@@ -708,16 +725,14 @@ module mpeg_video (
|
||||
|
||||
if (playback_frame_cnt >= frame_period - 1) playback_frame_cnt <= 0;
|
||||
if (playback_frame_cnt == 0 && for_display_valid) begin
|
||||
latch_frame_for_display <= 1;
|
||||
latch_frame_for_display <= 1;
|
||||
latch_frame_until_vblank <= 1;
|
||||
first_intra_frame_of_gop_in_prep <= first_intra_frame_of_gop_clk30;
|
||||
end
|
||||
end
|
||||
|
||||
if (single_step) begin
|
||||
latch_frame_until_vblank <= 1;
|
||||
latch_frame_for_display <= 1;
|
||||
first_intra_frame_of_gop_in_prep <= first_intra_frame_of_gop_clk30;
|
||||
latch_frame_for_display <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -6,9 +6,11 @@ typedef struct {
|
||||
bit [28:0] u_adr;
|
||||
bit [28:0] v_adr;
|
||||
bit first_intra_frame_of_gop;
|
||||
bit first_intra_frame_of_seq;
|
||||
bit [10:0] width;
|
||||
bit [8:0] height;
|
||||
bit [7:0] tempref;
|
||||
bit [31:0] timecode;
|
||||
} planar_yuv_s;
|
||||
|
||||
typedef struct packed {
|
||||
@@ -18,7 +20,6 @@ typedef struct packed {
|
||||
bit [7:0] factor_l2l;
|
||||
} linear_volume_s;
|
||||
|
||||
|
||||
function [31:0] ones_mask(bit [4:0] n);
|
||||
begin
|
||||
ones_mask = (32'h1 << n) - 1; // n ones at LSB
|
||||
|
||||
56
rtl/vmpeg.sv
56
rtl/vmpeg.sv
@@ -106,10 +106,8 @@ module vmpeg (
|
||||
|
||||
wire fmv_event_picture_starts_display;
|
||||
wire fmv_event_last_picture_starts_display;
|
||||
wire fmv_event_first_intra_frame_starts_display;
|
||||
wire fmv_event_sequence_header = fmv_event_first_intra_frame_starts_display;
|
||||
wire fmv_event_group_of_pictures = fmv_event_first_intra_frame_starts_display;
|
||||
wire fmv_event_picture = fmv_event_picture_starts_display;
|
||||
wire fmv_event_first_intra_frame_seq_starts_display;
|
||||
wire fmv_event_first_intra_frame_gop_starts_display;
|
||||
// TIMECD @ 00E04058
|
||||
// example 0x07800280 -> 10:00:30.0
|
||||
// mv_info() would have MD_TimeCd=0x0a001e00
|
||||
@@ -117,7 +115,7 @@ module vmpeg (
|
||||
// [27:22] 6 Bit Seconds. Not BCD
|
||||
// [5:0] 6 Bit Minutes. Not BCD
|
||||
// [10:6] 5 Bits Hours. Not BCD
|
||||
wire [31:0] fmv_timecode;
|
||||
wire [31:0] fmv_display_timecode;
|
||||
bit fmv_playback_active;
|
||||
bit fmv_single_step;
|
||||
wire fmv_event_sequence_end;
|
||||
@@ -163,11 +161,15 @@ module vmpeg (
|
||||
.event_buffer_underflow(fmv_event_buffer_underflow),
|
||||
.event_picture_starts_display(fmv_event_picture_starts_display),
|
||||
.event_last_picture_starts_display(fmv_event_last_picture_starts_display),
|
||||
.event_first_intra_frame_starts_display(fmv_event_first_intra_frame_starts_display),
|
||||
.event_first_intra_frame_gop_starts_display(fmv_event_first_intra_frame_gop_starts_display),
|
||||
.event_first_intra_frame_seq_starts_display(fmv_event_first_intra_frame_seq_starts_display),
|
||||
.pictures_in_fifo(fmv_pictures_in_fifo),
|
||||
.decoder_width(fmv_decoder_width),
|
||||
.decoder_height(fmv_decoder_height),
|
||||
.decoder_tempref(fmv_decoder_tempref),
|
||||
.display_width(fmv_display_width),
|
||||
.display_height(fmv_display_height),
|
||||
.display_tempref(fmv_display_tempref),
|
||||
.display_timecode(fmv_display_timecode),
|
||||
.decoder_frameperiod_90khz(fmv_decoder_frameperiod_90khz),
|
||||
.decoder_frameperiod_rawhdr(fmv_decoder_frameperiod_rawhdr)
|
||||
);
|
||||
@@ -182,18 +184,6 @@ module vmpeg (
|
||||
end
|
||||
end
|
||||
|
||||
mpeg_video_start_code_decoder startcode (
|
||||
.clk,
|
||||
.reset,
|
||||
.mpeg_data(mpeg_data),
|
||||
.data_valid(fmv_data_valid && fmv_packet_body),
|
||||
.event_sequence_header(),
|
||||
.event_group_of_pictures(),
|
||||
.event_picture(),
|
||||
.tmpref(),
|
||||
.timecode(fmv_timecode)
|
||||
);
|
||||
|
||||
wire signed [32:0] fma_system_clock_reference_start_time;
|
||||
wire fma_system_clock_reference_start_time_valid;
|
||||
wire signed [32:0] fmv_system_clock_reference_start_time;
|
||||
@@ -398,7 +388,10 @@ module vmpeg (
|
||||
|
||||
wire [10:0] fmv_decoder_width;
|
||||
wire [ 8:0] fmv_decoder_height;
|
||||
wire [ 7:0] fmv_decoder_tempref;
|
||||
wire [10:0] fmv_display_width;
|
||||
wire [ 8:0] fmv_display_height;
|
||||
|
||||
wire [ 7:0] fmv_display_tempref;
|
||||
wire [15:0] fmv_decoder_frameperiod_90khz;
|
||||
wire [ 7:0] fmv_decoder_frameperiod_rawhdr;
|
||||
|
||||
@@ -468,14 +461,16 @@ module vmpeg (
|
||||
15'h2001: dout = image_width; // 00E04002 ?? Written then Read
|
||||
15'h2002: dout = image_height; // 00E04004 ?? Written then Read
|
||||
15'h2003: dout = image_rt; // 00E04006 ??
|
||||
15'h2004: dout = fmv_timecode[31:16]; // 00E04008 Temporal time code High. During scan
|
||||
15'h2005: dout = fmv_timecode[15:0]; // 00E0400C Temporal time code Low. During scan
|
||||
15'h2029: dout = {5'b0, fmv_decoder_width}; // e04052 Picture Width ?? Only read
|
||||
15'h202a: dout = {7'b0, fmv_decoder_height}; // e04054 Picture Height ?? Only read
|
||||
15'h2004:
|
||||
dout = fmv_display_timecode[15:0]; // 00E04008 Temporal time code High. During scan
|
||||
15'h2005:
|
||||
dout = fmv_display_timecode[31:16]; // 00E0400C Temporal time code Low. During scan
|
||||
15'h2029: dout = {5'b0, fmv_display_width}; // e04052 Picture Width ?? Only read
|
||||
15'h202a: dout = {7'b0, fmv_display_height}; // e04054 Picture Height ?? Only read
|
||||
15'h202b: dout = {8'b0, fmv_decoder_frameperiod_rawhdr}; // e04056 Pic Rt ??
|
||||
15'h202c: dout = fmv_timecode[31:16]; // 00E04058 Time Code High ??
|
||||
15'h202d: dout = fmv_timecode[15:0]; // 00E0405A Time Code Low ??
|
||||
15'h202e: dout = {6'b0, fmv_decoder_tempref, 2'b0}; // 00E0405C TMP REF?? SYS_VSR?
|
||||
15'h202c: dout = fmv_display_timecode[15:0]; // 00E04058 Time Code High ??
|
||||
15'h202d: dout = fmv_display_timecode[31:16]; // 00E0405A Time Code Low ??
|
||||
15'h202e: dout = {6'b0, fmv_display_tempref, 2'b0}; // 00E0405C TMP REF?? SYS_VSR?
|
||||
15'h202f: dout = fmv_fifo_full ? 0 : 16'h2000; // 00E0405E ? SYS_STS
|
||||
15'h2030: dout = fmv_interrupt_enable_register; // 0E04060
|
||||
15'h2031: dout = fmv_interrupt_status_register; // 0E04062
|
||||
@@ -613,12 +608,13 @@ module vmpeg (
|
||||
end
|
||||
end
|
||||
|
||||
if (fmv_event_sequence_header) begin
|
||||
if (fmv_event_first_intra_frame_seq_starts_display) begin
|
||||
fmv_interrupt_status_register.seq <= 1;
|
||||
$display("Cause FMV Seq Event");
|
||||
end
|
||||
if (fmv_event_group_of_pictures) fmv_interrupt_status_register.gop <= 1;
|
||||
if (fmv_event_picture) begin
|
||||
if (fmv_event_first_intra_frame_gop_starts_display)
|
||||
fmv_interrupt_status_register.gop <= 1;
|
||||
if (fmv_event_picture_starts_display) begin
|
||||
fmv_interrupt_status_register.pic <= 1;
|
||||
|
||||
image_width <= {5'b0, fmv_decoder_width};
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#define SCC68070
|
||||
#define SLAVE
|
||||
// #define TRACE
|
||||
#define TRACE
|
||||
// #define SIMULATE_RC5
|
||||
|
||||
#define PL_MPEG_IMPLEMENTATION
|
||||
@@ -888,7 +888,7 @@ class CDi {
|
||||
dut.rootp->emu__DOT__cditop__DOT__fdrvs1_static = cpu_a[2];
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
executing_dvc_rom_instructions = m_pc >= 0xe40000 && m_pc < 0xe7ffff;
|
||||
#endif
|
||||
if (print_instructions || executing_dvc_rom_instructions) {
|
||||
@@ -929,6 +929,7 @@ class CDi {
|
||||
// PAL
|
||||
// space_ace_pal();
|
||||
// braindead13_pal();
|
||||
lost_ride_pal();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -971,9 +972,9 @@ class CDi {
|
||||
}
|
||||
|
||||
// Simulate Audio
|
||||
if (dut.rootp->emu__DOT__cditop__DOT__sample_tick44) {
|
||||
int16_t sample_l = dut.rootp->emu__DOT__cditop__DOT__vmpeg_inst__DOT__audio__DOT__fifo_out_left;
|
||||
int16_t sample_r = dut.rootp->emu__DOT__cditop__DOT__vmpeg_inst__DOT__audio__DOT__fifo_out_right;
|
||||
if (dut.rootp->emu__DOT__cditop__DOT__cdic_inst__DOT__sample_tick) {
|
||||
int16_t sample_l = dut.rootp->emu__DOT__cditop__DOT__cdic_inst__DOT__adpcm__DOT__fifo_out_left;
|
||||
int16_t sample_r = dut.rootp->emu__DOT__cditop__DOT__cdic_inst__DOT__adpcm__DOT__fifo_out_right;
|
||||
fwrite(&sample_l, 2, 1, f_audio_left);
|
||||
fwrite(&sample_r, 2, 1, f_audio_right);
|
||||
}
|
||||
@@ -1306,7 +1307,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
switch (machineindex) {
|
||||
case 0:
|
||||
f_cd_bin = fopen("images/braindead13.bin", "rb");
|
||||
f_cd_bin = fopen("images/nonis2.bin", "rb");
|
||||
break;
|
||||
case 1:
|
||||
f_cd_bin = fopen("images/braindead13.bin", "rb");
|
||||
|
||||
@@ -10,7 +10,7 @@ main:
|
||||
move.w #$0000,$303FFE ; Data buffer
|
||||
|
||||
move.w #$0002,$E03000 ; FMA CMD - On
|
||||
move.w #$0006,$E03008 ; FMA Stream
|
||||
move.w #$0000,$E03008 ; FMA Stream
|
||||
|
||||
move.w #$2000,$E040C0 ; FMV SYSCMD - Decoder off
|
||||
nop
|
||||
@@ -56,7 +56,7 @@ main:
|
||||
move.w #$0100,$303C06 ; File Register
|
||||
move.l #$ffffffff,$303C08 ; Channel Register
|
||||
move.w #$0000,$303C0C ; Audio Channel Register
|
||||
move.l #$01133900,$303C02 ; Timer Register
|
||||
move.l #$00323400,$303C02 ; Timer Register
|
||||
move.w #$C000,$303FFE ; Start the Read by setting bit 15 of the data buffer
|
||||
|
||||
move.l #0,$0E0407C ;FMV_DECOFF
|
||||
@@ -68,7 +68,7 @@ main:
|
||||
; But I feel lazy and use the number of pics instead
|
||||
waitforpics:
|
||||
jsr WaitForSectorAndUse
|
||||
cmp.w #4,$00E040A4 ; Compare 5 against pictures in FIFO
|
||||
cmp.w #2,$00E040A4 ; Compare 5 against pictures in FIFO
|
||||
bmi waitforpics
|
||||
|
||||
move.w #$0008,$E040C0 ; FMV SYSCMD - Play
|
||||
|
||||
@@ -30,6 +30,9 @@ struct frame_display_fifo
|
||||
uint32_t temporal_ref; // @0x10003038 Write only
|
||||
uint32_t slow_motion; // @0x1000303c Read only
|
||||
uint32_t commit_frame; // @0x10003040 Write only
|
||||
uint32_t timecode; // @0x10003044 Write only
|
||||
uint32_t first_intra_frame_of_seq; // @0x10003048 Write only
|
||||
|
||||
};
|
||||
|
||||
struct io_fifo_control *const fifo_ctrl = (struct io_fifo_control *)0x10002000;
|
||||
|
||||
@@ -30,6 +30,7 @@ void print_str(const char *p);
|
||||
void stop_verilator();
|
||||
|
||||
// #define SOFT_CONVOLVE
|
||||
int seq_hdr_latched;
|
||||
|
||||
#define PL_MPEG_IMPLEMENTATION
|
||||
#define PLM_NO_STDIO
|
||||
@@ -109,10 +110,14 @@ static void push_frame(plm_frame_t *frame)
|
||||
{
|
||||
first_intra_frame_of_gop_occured = true;
|
||||
frame_display_fifo->first_intra_frame_of_gop = 1;
|
||||
|
||||
frame_display_fifo->first_intra_frame_of_seq = seq_hdr_latched;
|
||||
seq_hdr_latched = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_display_fifo->first_intra_frame_of_gop = 0;
|
||||
frame_display_fifo->first_intra_frame_of_seq = 0;
|
||||
}
|
||||
|
||||
frame_display_fifo->width = frame->width;
|
||||
@@ -124,6 +129,7 @@ static void push_frame(plm_frame_t *frame)
|
||||
frame_display_fifo->frameperiod_90khz = period90khz;
|
||||
frame_display_fifo->frameperiod_rawhdr = seq_hdr_conf.frameperiod;
|
||||
frame_display_fifo->temporal_ref = frame->temporal_ref;
|
||||
frame_display_fifo->timecode = frame->timecode;
|
||||
|
||||
if (frame_display_fifo->pictures_in_fifo < 3)
|
||||
{
|
||||
|
||||
@@ -186,6 +186,8 @@ typedef struct plm_video_t plm_video_t;
|
||||
typedef struct plm_audio_t plm_audio_t;
|
||||
|
||||
|
||||
int seq_hdr_latched;
|
||||
|
||||
// Demuxed MPEG PS packet
|
||||
// The type maps directly to the various MPEG-PES start codes. PTS is the
|
||||
// presentation time stamp of the packet in seconds. Note that not all packets
|
||||
@@ -229,6 +231,7 @@ typedef struct {
|
||||
plm_plane_t cb;
|
||||
int picture_type;
|
||||
int temporal_ref;
|
||||
int timecode;
|
||||
} plm_frame_t;
|
||||
|
||||
|
||||
@@ -1504,6 +1507,7 @@ static const int PLM_START_SLICE_LAST = 0xAF;
|
||||
static const int PLM_START_PICTURE = 0x00;
|
||||
static const int PLM_START_EXTENSION = 0xB5;
|
||||
static const int PLM_START_USER_DATA = 0xB2;
|
||||
static const int PLM_START_GROUP_OF_PICTURES = 0xB8;
|
||||
|
||||
#define PLM_START_IS_SLICE(c) \
|
||||
(c >= PLM_START_SLICE_FIRST && c <= PLM_START_SLICE_LAST)
|
||||
@@ -1985,6 +1989,7 @@ struct plm_video_t {
|
||||
int start_code;
|
||||
int picture_type;
|
||||
int temporal_ref;
|
||||
int timecode; // from GOP
|
||||
|
||||
plm_video_motion_t motion_forward;
|
||||
plm_video_motion_t motion_backward;
|
||||
@@ -2022,6 +2027,7 @@ static inline uint8_t plm_clamp(int n) {
|
||||
return n;
|
||||
}
|
||||
|
||||
int plm_video_decode_group_of_pictures(plm_video_t *self);
|
||||
int plm_video_decode_sequence_header(plm_video_t *self);
|
||||
void plm_video_init_frame(plm_video_t *self, plm_frame_t *frame);
|
||||
void plm_video_decode_picture(plm_video_t *self);
|
||||
@@ -2155,6 +2161,9 @@ plm_frame_t *plm_video_decode(plm_video_t *self) {
|
||||
}
|
||||
plm_video_decode_sequence_header(self);
|
||||
}
|
||||
else if (self->start_code == PLM_START_GROUP_OF_PICTURES){
|
||||
plm_video_decode_group_of_pictures(self);
|
||||
}
|
||||
else if (self->start_code == -1) {
|
||||
// If we reached the end of the file and the previously decoded
|
||||
// frame was a reference frame, we still have to return it.
|
||||
@@ -2176,7 +2185,6 @@ plm_frame_t *plm_video_decode(plm_video_t *self) {
|
||||
|
||||
|
||||
} while (!frame);
|
||||
|
||||
OUT_DEBUG = 15;
|
||||
|
||||
frame->time = self->time;
|
||||
@@ -2205,6 +2213,24 @@ int plm_video_has_header(plm_video_t *self) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int plm_video_decode_group_of_pictures(plm_video_t *self) {
|
||||
if (!plm_dma_buffer_has(self->buffer, 11+2+12)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// skip drop frame flag
|
||||
plm_dma_buffer_skip(self->buffer, 1);
|
||||
|
||||
uint32_t hours_minutes = plm_dma_buffer_read(self->buffer, 11);
|
||||
|
||||
// skip marker
|
||||
plm_dma_buffer_skip(self->buffer, 1);
|
||||
|
||||
uint32_t seconds_frame = plm_dma_buffer_read(self->buffer, 12);
|
||||
|
||||
self->timecode = (hours_minutes<<12) | seconds_frame;
|
||||
}
|
||||
|
||||
int plm_video_decode_sequence_header(plm_video_t *self) {
|
||||
int max_header_size = 64 + 2 * 64 * 8; // 64 bit header + 2x 64 byte matrix
|
||||
if (!plm_dma_buffer_has(self->buffer, max_header_size)) {
|
||||
@@ -2273,6 +2299,8 @@ int plm_video_decode_sequence_header(plm_video_t *self) {
|
||||
plm_video_init_frame(self, &self->frame_forward);
|
||||
plm_video_init_frame(self, &self->frame_backward);
|
||||
}
|
||||
__asm volatile("": : :"memory");
|
||||
seq_hdr_latched=1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -2361,10 +2389,10 @@ void plm_video_decode_picture(plm_video_t *self) {
|
||||
|
||||
// Decode all slices
|
||||
plm_video_init_frame(self, &self->frame_current);
|
||||
|
||||
self->frame_current.picture_type = self->picture_type;
|
||||
self->frame_current.temporal_ref = self->temporal_ref;
|
||||
|
||||
self->frame_current.timecode = self->timecode;
|
||||
|
||||
while (PLM_START_IS_SLICE(self->start_code)) {
|
||||
OUT_DEBUG = 7;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user