Files
dreamcast-play-mpegs/main.c
T
2026-03-29 10:50:46 -04:00

141 lines
3.7 KiB
C

#include <kos.h>
#include <stdio.h>
#include <dirent.h>
#include <dc/video.h>
#include <dc/biosfont.h>
#define PL_MPEG_IMPLEMENTATION
#include "pl_mpeg.h"
static pvr_ptr_t texture_ptr;
static int video_width = 0;
static int video_height = 0;
static const int tex_size = 512;
void draw_error(const char *msg) {
uint16_t *vram = vram_s;
int x = 20, y = 20;
for(int i = 0; i < 640 * 480; i++) vram[i] = 0x000F;
bfont_draw_str(vram + y * 640 + x, 640, 0, msg);
while(1) {
MAPLE_FOREACH_BEGIN(MAPLE_FUNC_CONTROLLER, cont_state_t, st)
if(st->buttons & CONT_START) return;
MAPLE_FOREACH_END()
}
}
void draw_frame() {
pvr_poly_cxt_t cxt;
pvr_poly_hdr_t hdr;
pvr_vertex_t vert;
pvr_wait_ready();
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
pvr_poly_cxt_txr(&cxt, PVR_LIST_OP_POLY, PVR_TXRFMT_RGB565 | PVR_TXRFMT_NONTWIDDLED,
tex_size, tex_size, texture_ptr, PVR_FILTER_BILINEAR);
pvr_poly_compile(&hdr, &cxt);
pvr_prim(&hdr, sizeof(hdr));
float u_max = (float)video_width / (float)tex_size;
float v_max = (float)video_height / (float)tex_size;
vert.flags = PVR_CMD_VERTEX;
vert.z = 1.0f;
vert.argb = PVR_PACK_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
vert.x = 0; vert.y = 0; vert.u = 0; vert.v = 0;
pvr_prim(&vert, sizeof(vert));
vert.x = 640; vert.y = 0; vert.u = u_max; vert.v = 0;
pvr_prim(&vert, sizeof(vert));
vert.x = 0; vert.y = 480; vert.u = 0; vert.v = v_max;
pvr_prim(&vert, sizeof(vert));
vert.flags = PVR_CMD_VERTEX_EOL;
vert.x = 640; vert.y = 480; vert.u = u_max; vert.v = v_max;
pvr_prim(&vert, sizeof(vert));
pvr_list_finish();
pvr_scene_finish();
}
void list_files_on_screen() {
DIR *dir;
struct dirent *ent;
int x = 20, y = 50;
uint16_t *vram = vram_s;
dir = opendir("/cd");
if (dir == NULL) {
bfont_draw_str(vram + (y * 640) + x, 640, 0, "Error: Could not open /cd");
return;
}
bfont_draw_str(vram + (y * 640) + x, 640, 0, "Files found on /cd:");
y += 20;
while ((ent = readdir(dir)) != NULL) {
char msg[128];
sprintf(msg, " -> %s", ent->d_name);
bfont_draw_str(vram + (y * 640) + x, 640, 0, msg);
y += 20;
if (y > 450) break;
}
closedir(dir);
}
void play_video(const char *filename) {
plm_t *plm = plm_create_with_filename(filename);
if (!plm) {
char err[128];
sprintf(err, "FATAL: Could not open %s", filename);
draw_error(err);
return;
}
video_width = plm_get_width(plm);
video_height = plm_get_height(plm);
while (!plm_has_ended(plm)) {
plm_frame_t *frame = plm_decode_video(plm);
if (frame) {
uint16_t *pix = (uint16_t *)texture_ptr;
uint8_t *y_plane = frame->y.data;
for (int y = 0; y < video_height; y++) {
for (int x = 0; x < video_width; x++) {
uint8_t brightness = y_plane[y * video_width + x];
uint16_t r = (brightness >> 3) & 0x1F;
uint16_t g = (brightness >> 2) & 0x3F;
uint16_t b = (brightness >> 3) & 0x1F;
pix[y * tex_size + x] = (r << 11) | (g << 5) | b;
}
}
draw_frame();
}
MAPLE_FOREACH_BEGIN(MAPLE_FUNC_CONTROLLER, cont_state_t, st)
if(st->buttons & CONT_START) return;
MAPLE_FOREACH_END()
vid_waitvbl();
}
plm_destroy(plm);
}
int main(int argc, char **argv) {
pvr_init_defaults();
texture_ptr = pvr_mem_malloc(tex_size * tex_size * 2);
if (!texture_ptr) return -1;
play_video("/cd/VIDEO.MPG");
pvr_mem_free(texture_ptr);
return 0;
}