mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-22 09:01:57 -05:00
PS1: Manually implement transferring launcher framebuffer to VRAM
This commit is contained in:
parent
e93c9336dd
commit
591e31bea6
2 changed files with 72 additions and 2 deletions
30
misc/ps1/ps1defs.h
Normal file
30
misc/ps1/ps1defs.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
enum dma_chrc_flags {
|
||||||
|
CHRC_STATUS_BUSY = (1 << 24),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dma_chrc_CMD {
|
||||||
|
CHRC_FROM_RAM = (1 << 0),
|
||||||
|
CHRC_BEGIN = (1 << 24),
|
||||||
|
CHRC_MODE_SLICE = (1 << 9)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum gpu_status_flags {
|
||||||
|
GPU_STATUS_CMD_READY = (1 << 26),
|
||||||
|
GPU_STATUS_DMA_RECV_READY = (1 << 28),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum gp0_cmd_type {
|
||||||
|
GP0_CMD_CLEAR_VRAM_CACHE = 0x01000000,
|
||||||
|
GP0_CMD_TRANSFER_TO_VRAM = 0xA0000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum gp1_cmd_type {
|
||||||
|
GP1_CMD_DMA_MODE = 0x04000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum gp1_dma_mode {
|
||||||
|
GP1_DMA_NONE = 0,
|
||||||
|
GP1_DMA_CPU_TO_GP0 = 2,
|
||||||
|
};
|
|
@ -20,6 +20,7 @@
|
||||||
#include <psxgte.h>
|
#include <psxgte.h>
|
||||||
#include <psxgpu.h>
|
#include <psxgpu.h>
|
||||||
#include <psxpad.h>
|
#include <psxpad.h>
|
||||||
|
#include "../misc/ps1/ps1defs.h"
|
||||||
|
|
||||||
#define SCREEN_XRES 320
|
#define SCREEN_XRES 320
|
||||||
#define SCREEN_YRES 240
|
#define SCREEN_YRES 240
|
||||||
|
@ -170,12 +171,51 @@ void Gamepads_Process(float delta) {
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*------------------------------------------------------Framebuffer--------------------------------------------------------*
|
*------------------------------------------------------Framebuffer--------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
|
#define wait_while(cond) while (cond) { __asm__ volatile(""); }
|
||||||
|
|
||||||
void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) {
|
void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) {
|
||||||
bmp->scan0 = (BitmapCol*)Mem_Alloc(width * height, BITMAPCOLOR_SIZE, "window pixels");
|
bmp->scan0 = (BitmapCol*)Mem_Alloc(width * height, BITMAPCOLOR_SIZE, "window pixels");
|
||||||
bmp->width = width;
|
bmp->width = width;
|
||||||
bmp->height = height;
|
bmp->height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DMA_BLOCK_SIZE 16 // max block size per Nocash PSX docs
|
||||||
|
static void TransferToVRAM(const RECT* r, void* pixels) {
|
||||||
|
unsigned num_words = (r->w * r->h) / 2; // number of uint16s -> uint32s
|
||||||
|
unsigned num_blocks = num_words / DMA_BLOCK_SIZE;
|
||||||
|
|
||||||
|
// Wait until GPU is ready to receive a command
|
||||||
|
wait_while(!(GPU_GP1 & GPU_STATUS_CMD_READY));
|
||||||
|
|
||||||
|
GPU_GP1 = GP1_CMD_DMA_MODE | GP1_DMA_NONE;
|
||||||
|
GPU_GP0 = GP0_CMD_CLEAR_VRAM_CACHE;
|
||||||
|
|
||||||
|
// Write GPU command for transferring RAM to VRAM
|
||||||
|
GPU_GP0 = GP0_CMD_TRANSFER_TO_VRAM;
|
||||||
|
GPU_GP0 = r->x | (r->y << 16);
|
||||||
|
GPU_GP0 = r->w | (r->h << 16);
|
||||||
|
|
||||||
|
GPU_GP1 = GP1_CMD_DMA_MODE | GP1_DMA_CPU_TO_GP0;
|
||||||
|
|
||||||
|
// Wait until any prior DMA to GPU has finished
|
||||||
|
wait_while((DMA_CHCR(DMA_GPU) & CHRC_STATUS_BUSY));
|
||||||
|
// Wait until GPU is ready to receive DMA data
|
||||||
|
wait_while(!(GPU_GP1 & GPU_STATUS_DMA_RECV_READY));
|
||||||
|
|
||||||
|
DMA_MADR(DMA_GPU) = (uint32_t)pixels;
|
||||||
|
DMA_BCR(DMA_GPU) = DMA_BLOCK_SIZE | (num_blocks << 16);
|
||||||
|
DMA_CHCR(DMA_GPU) = CHRC_BEGIN | CHRC_MODE_SLICE | CHRC_FROM_RAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WaitUntilFinished(void) {
|
||||||
|
// Wait until DMA to GPU has finished
|
||||||
|
wait_while((DMA_CHCR(DMA_GPU) & CHRC_STATUS_BUSY));
|
||||||
|
// Wait until GPU is ready to receive DMA data again
|
||||||
|
wait_while(!(GPU_GP1 & GPU_STATUS_DMA_RECV_READY));
|
||||||
|
// Wait until GPU is ready to receive commands again
|
||||||
|
wait_while(!(GPU_GP1 & GPU_STATUS_CMD_READY));
|
||||||
|
}
|
||||||
|
|
||||||
void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) {
|
void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) {
|
||||||
RECT rect;
|
RECT rect;
|
||||||
rect.x = 0;
|
rect.x = 0;
|
||||||
|
@ -183,8 +223,8 @@ void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) {
|
||||||
rect.w = SCREEN_XRES;
|
rect.w = SCREEN_XRES;
|
||||||
rect.h = SCREEN_YRES;
|
rect.h = SCREEN_YRES;
|
||||||
|
|
||||||
LoadImage(&rect, bmp->scan0);
|
TransferToVRAM(&rect, bmp->scan0);
|
||||||
DrawSync(0);
|
WaitUntilFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window_FreeFramebuffer(struct Bitmap* bmp) {
|
void Window_FreeFramebuffer(struct Bitmap* bmp) {
|
||||||
|
|
Loading…
Reference in a new issue