dreamcast/holly/framebuffer.cpp
Zack Buhman d25b5c1392 holly: add framebuffer
This will eventually replace video_output.
2025-07-16 13:02:33 -05:00

186 lines
5.4 KiB
C++

#include "holly/holly.hpp"
#include "holly/core_bits.hpp"
#include "framebuffer.hpp"
namespace framebuffer {
struct framebuffer framebuffer;
void init(int px_width,
int px_height,
uint32_t framebuffer_start)
{
framebuffer.px_width = px_width;
framebuffer.px_height = px_height;
int x_size = framebuffer.px_width;
int y_size = framebuffer.px_height;
// write
holly.FB_X_CLIP
= fb_x_clip::fb_x_clip_max(x_size - 1)
| fb_x_clip::fb_x_clip_min(0);
holly.FB_Y_CLIP
= fb_y_clip::fb_y_clip_max(y_size - 1)
| fb_y_clip::fb_y_clip_min(0);
holly.FB_R_SIZE
= fb_r_size::fb_modulus(1)
| fb_r_size::fb_y_size(y_size - 1)
| fb_r_size::fb_x_size((x_size * bytes_per_pixel) / 4 - 1);
holly.FB_R_SOF1
= framebuffer_start;
uint32_t vclk_div = (px_width >= 640) ? fb_r_ctrl::vclk_div::pclk_vclk_1
: fb_r_ctrl::vclk_div::pclk_vclk_2;
holly.FB_R_CTRL
= vclk_div
| fb_r_ctrl::fb_depth::_565_rgb_16bit
| fb_r_ctrl::fb_enable;
}
void scaler_init()
{
holly.Y_COEFF
= y_coeff::coefficient_1(0x80)
| y_coeff::coefficient_0_2(0x40);
// in 6.10 fixed point; 0x0400 is 1x vertical scale
holly.SCALER_CTL = scaler_ctl::vertical_scale_factor(0x0400);
holly.FB_BURSTCTRL
= fb_burstctrl::wr_burst(0x09)
| fb_burstctrl::vid_lat(0x3f)
| fb_burstctrl::vid_burst(0x39);
}
void spg_set_mode_720x480_vga()
{
holly.SPG_CONTROL
= spg_control::sync_direction::output;
holly.SPG_LOAD
= spg_load::vcount(525 - 1) // number of lines per field
| spg_load::hcount(858 - 1); // number of video clock cycles per line
holly.SPG_HBLANK
= spg_hblank::hbend(117) // H Blank ending position
| spg_hblank::hbstart(837); // H Blank starting position
holly.SPG_VBLANK
= spg_vblank::vbend(40) // V Blank ending position
| spg_vblank::vbstart(520); // V Blank starting position
holly.SPG_WIDTH
= spg_width::eqwidth(16 - 1) // Specify the equivalent pulse width (number of video clock cycles - 1)
| spg_width::bpwidth(794 - 1) // Specify the broad pulse width (number of video clock cycles - 1)
| spg_width::vswidth(3) // V Sync width (number of lines)
| spg_width::hswidth(64 - 1); // H Sync width (number of video clock cycles - 1)
holly.VO_STARTX
= vo_startx::horizontal_start_position(117);
holly.VO_STARTY
= vo_starty::vertical_start_position_on_field_2(40)
| vo_starty::vertical_start_position_on_field_1(40);
holly.VO_CONTROL
= vo_control::pclk_delay(22);
holly.SPG_HBLANK_INT
= spg_hblank_int::line_comp_val(837);
holly.SPG_VBLANK_INT
= spg_vblank_int::vblank_out_interrupt_line_number(21)
| spg_vblank_int::vblank_in_interrupt_line_number(520);
}
void spg_set_mode_640x480_vga()
{
holly.SPG_CONTROL
= spg_control::sync_direction::output;
holly.SPG_LOAD
= spg_load::vcount(525 - 1) // number of lines per field
| spg_load::hcount(858 - 1); // number of video clock cycles per line
holly.SPG_HBLANK
= spg_hblank::hbend(126) // H Blank ending position
| spg_hblank::hbstart(837); // H Blank starting position
holly.SPG_VBLANK
= spg_vblank::vbend(40) // V Blank ending position
| spg_vblank::vbstart(520); // V Blank starting position
holly.SPG_WIDTH
= spg_width::eqwidth(16 - 1) // Specify the equivalent pulse width (number of video clock cycles - 1)
| spg_width::bpwidth(794 - 1) // Specify the broad pulse width (number of video clock cycles - 1)
| spg_width::vswidth(3) // V Sync width (number of lines)
| spg_width::hswidth(64 - 1); // H Sync width (number of video clock cycles - 1)
holly.VO_STARTX
= vo_startx::horizontal_start_position(168);
holly.VO_STARTY
= vo_starty::vertical_start_position_on_field_2(40)
| vo_starty::vertical_start_position_on_field_1(40);
holly.VO_CONTROL
= vo_control::pclk_delay(22);
holly.SPG_HBLANK_INT
= spg_hblank_int::line_comp_val(837);
holly.SPG_VBLANK_INT
= spg_vblank_int::vblank_out_interrupt_line_number(21)
| spg_vblank_int::vblank_in_interrupt_line_number(520);
}
void spg_set_mode_320x240_ntsc_ni()
{
holly.SPG_CONTROL
= spg_control::sync_direction::output
| spg_control::ntsc;
holly.SPG_LOAD
= spg_load::vcount(263 - 1)
| spg_load::hcount(858 - 1);
holly.SPG_HBLANK
= spg_hblank::hbend(126)
| spg_hblank::hbstart(837);
holly.SPG_VBLANK
= spg_vblank::vbend(18)
| spg_vblank::vbstart(258);
holly.SPG_WIDTH
= spg_width::eqwidth(16 - 1)
| spg_width::bpwidth(794 - 1)
| spg_width::vswidth(3)
| spg_width::hswidth(64 - 1);
holly.VO_STARTX
= vo_startx::horizontal_start_position(164);
holly.VO_STARTY
= vo_starty::vertical_start_position_on_field_2(18)
| vo_starty::vertical_start_position_on_field_1(17);
holly.VO_CONTROL
= vo_control::pclk_delay(22)
| vo_control::pixel_double;
holly.SPG_HBLANK_INT
= spg_hblank_int::line_comp_val(837);
holly.SPG_VBLANK_INT
= spg_vblank_int::vblank_out_interrupt_line_number(21)
| spg_vblank_int::vblank_in_interrupt_line_number(258);
}
}