//====================================================================
// renderer_2d.v - 2D渲染器
// 第25课：精灵渲染与图层合成
//====================================================================
module renderer_2d #(
    parameter COORD_WIDTH = 16,
    parameter COLOR_WIDTH = 24,
    parameter FB_WIDTH    = 640,
    parameter FB_HEIGHT   = 480,
    parameter MAX_SPRITES = 16,
    parameter FRAC_BITS   = 12
)(
    input  wire                          clk, rst_n,
    // 精灵控制接口
    input  wire                          sprite_valid,
    input  wire [3:0]                    sprite_id,
    input  wire [COORD_WIDTH-1:0]        sprite_x, sprite_y,
    input  wire [COORD_WIDTH-1:0]        sprite_w, sprite_h,
    input  wire [7:0]                    sprite_alpha,
    input  wire [COORD_WIDTH-1:0]        sprite_tex_base,
    output reg                           sprite_ready,
    // 帧缓冲接口
    output reg                           fb_wen,
    output reg  [COORD_WIDTH-1:0]        fb_x, fb_y,
    output reg  [COLOR_WIDTH-1:0]        fb_color,
    // 纹理RAM接口
    output reg  [13:0]                   tex_addr,
    input  wire [COLOR_WIDTH-1:0]        tex_data,
    output reg                           tex_read
);
/* verilator lint_off WIDTHEXPAND */
/* verilator lint_off WIDTHTRUNC */
/* verilator lint_off CASEOVERLAP */
/* verilator lint_off CMPCONST */
/* verilator lint_off UNSIGNED */
/* verilator lint_off WIDTHCONCAT */

    reg [COORD_WIDTH-1:0] spr_x [0:MAX_SPRITES-1];
    reg [COORD_WIDTH-1:0] spr_y [0:MAX_SPRITES-1];
    reg [COORD_WIDTH-1:0] spr_w [0:MAX_SPRITES-1];
    reg [COORD_WIDTH-1:0] spr_h [0:MAX_SPRITES-1];
    reg [7:0]              spr_alpha [0:MAX_SPRITES-1];
    reg [COORD_WIDTH-1:0] spr_tex [0:MAX_SPRITES-1];
    reg [3:0]              cur_sprite;
    reg [COORD_WIDTH-1:0]  draw_x, draw_y;
    localparam S_IDLE=3'd0, S_SETUP=3'd1, S_DRAW=3'd2, S_FETCH=3'd3, S_BLEND=3'd4, S_NEXT=3'd5;
    reg [2:0] state;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin state<=S_IDLE; sprite_ready<=1; fb_wen<=0; tex_read<=0; end
        else begin
            fb_wen <= 0; tex_read <= 0;
            case (state)
                S_IDLE: begin
                    sprite_ready <= 1;
                    if (sprite_valid) begin
                        sprite_ready <= 0;
                        spr_x[sprite_id] <= sprite_x; spr_y[sprite_id] <= sprite_y;
                        spr_w[sprite_id] <= sprite_w; spr_h[sprite_id] <= sprite_h;
                        spr_alpha[sprite_id] <= sprite_alpha;
                        spr_tex[sprite_id] <= sprite_tex_base;
                    end
                    cur_sprite <= 0; draw_x <= 0; draw_y <= 0;
                    state <= S_SETUP;
                end
                S_SETUP: begin
                    draw_x <= spr_x[cur_sprite]; draw_y <= spr_y[cur_sprite];
                    state <= S_DRAW;
                end
                S_DRAW: begin
                    if (draw_y < spr_y[cur_sprite] + spr_h[cur_sprite]) begin
                        if (draw_x < spr_x[cur_sprite] + spr_w[cur_sprite]) begin
                            tex_addr <= spr_tex[cur_sprite] + (draw_y - spr_y[cur_sprite]) * spr_w[cur_sprite] + (draw_x - spr_x[cur_sprite]);
                            tex_read <= 1; state <= S_FETCH;
                        end else begin
                            draw_x <= spr_x[cur_sprite]; draw_y <= draw_y + 1;
                        end
                    end else state <= S_NEXT;
                end
                S_FETCH: begin state <= S_BLEND; end
                S_BLEND: begin
                    fb_x <= draw_x; fb_y <= draw_y;
                    fb_color <= tex_data; // 简化：不做alpha混合
                    fb_wen <= 1; draw_x <= draw_x + 1; state <= S_DRAW;
                end
                S_NEXT: begin
                    if (cur_sprite < MAX_SPRITES - 1) begin
                        cur_sprite <= cur_sprite + 1; state <= S_SETUP;
                    end else state <= S_IDLE;
                end
                default: state <= S_IDLE;
            endcase
        end
    end
endmodule