libpcsxcore/misc.o libpcsxcore/plugins.o libpcsxcore/ppf.o libpcsxcore/psxbios.o \
libpcsxcore/psxcommon.o libpcsxcore/psxcounters.o libpcsxcore/psxdma.o \
libpcsxcore/psxhw.o libpcsxcore/psxinterpreter.o libpcsxcore/psxmem.o libpcsxcore/r3000a.o \
- libpcsxcore/sio.o libpcsxcore/spu.o
+ libpcsxcore/sio.o libpcsxcore/spu.o libpcsxcore/gpu.o
OBJS += libpcsxcore/gte.o libpcsxcore/gte_nf.o libpcsxcore/gte_divider.o
ifeq ($(DEBUG), 1)
#include "../libpcsxcore/cdriso.h"
#include "../libpcsxcore/cheat.h"
#include "../libpcsxcore/r3000a.h"
+#include "../libpcsxcore/gpu.h"
#include "../plugins/dfsound/out.h"
#include "../plugins/dfsound/spu_config.h"
#include "cspace.h"
.pl_vout_close = vout_close,
.mmap = pl_mmap,
.munmap = pl_munmap,
+ .gpu_state_change = gpu_state_change,
/* from psxcounters */
.gpu_hcnt = &hSyncCount,
.gpu_frame_count = &frame_counter,
#include "psemu_plugin_defs.h"
#include "../libpcsxcore/new_dynarec/new_dynarec.h"
#include "../libpcsxcore/psxmem_map.h"
+#include "../libpcsxcore/gpu.h"
#define HUD_HEIGHT 10
.mmap = pl_mmap,
.munmap = pl_munmap,
.pl_set_gpu_caps = pl_set_gpu_caps,
+ .gpu_state_change = gpu_state_change,
};
/* watchdog */
void pl_timing_prepare(int is_pal);
void pl_frame_limit(void);
+// for communication with gpulib
struct rearmed_cbs {
void (*pl_get_layer_pos)(int *x, int *y, int *w, int *h);
int (*pl_vout_open)(void);
// only used by some frontends
void (*pl_vout_set_raw_vram)(void *vram);
void (*pl_set_gpu_caps)(int caps);
+ // emulation related
+ void (*gpu_state_change)(int what);
// some stats, for display by some plugins
int flips_per_sec, cpu_usage;
float vsps_cur; // currect vsync/s
$(CORE_DIR)/r3000a.c \
$(CORE_DIR)/sio.c \
$(CORE_DIR)/spu.c \
+ $(CORE_DIR)/gpu.c \
$(CORE_DIR)/gte.c \
$(CORE_DIR)/gte_nf.c \
$(CORE_DIR)/gte_divider.c
--- /dev/null
+/***************************************************************************
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ ***************************************************************************/
+
+#include "gpu.h"
+#include "psxdma.h"
+
+void gpu_state_change(int what)
+{
+ enum psx_gpu_state state = what;
+ switch (state)
+ {
+ case PGS_VRAM_TRANSFER_START:
+ HW_GPU_STATUS &= ~SWAP32(PSXGPU_nBUSY);
+ break;
+ case PGS_VRAM_TRANSFER_END:
+ HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY);
+ break;
+ case PGS_PRIMITIVE_START:
+ HW_GPU_STATUS &= ~SWAP32(PSXGPU_nBUSY);
+ GPUDMA_INT(200); // see gpuInterrupt
+ break;
+ }
+}
HW_GPU_STATUS |= SWAP32(GPU_readStatus() & ~PSXGPU_TIMING_BITS); \
}
+enum psx_gpu_state {
+ PGS_VRAM_TRANSFER_START,
+ PGS_VRAM_TRANSFER_END,
+ PGS_PRIMITIVE_START, // for non-dma only
+};
+
+void gpu_state_change(int what);
+
#endif /* __GPU_H__ */
HW_DMA2_MADR = SWAPu32(madr + words_copy * 4);
+ // careful: gpu_state_change() also messes with this
+ HW_GPU_STATUS &= SWAP32(~PSXGPU_nBUSY);
// already 32-bit word size ((size * 4) / 4)
GPUDMA_INT(words / 4);
return;
HW_DMA2_MADR = SWAPu32(madr);
+ // careful: gpu_state_change() also messes with this
+ HW_GPU_STATUS &= SWAP32(~PSXGPU_nBUSY);
// already 32-bit word size ((size * 4) / 4)
GPUDMA_INT(words / 4);
return;
DMA_INTERRUPT(2);
}
+// note: this is also (ab)used for non-dma prim command
+// to delay gpu returning to idle state, see gpu_state_change()
void gpuInterrupt() {
if (HW_DMA2_CHCR == SWAP32(0x01000401) && !(HW_DMA2_MADR & SWAP32(0x800000)))
{
#include <stdlib.h> /* for calloc */
#include "gpu.h"
+#include "../../libpcsxcore/gpu.h" // meh
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#ifdef __GNUC__
log_io("start_vram_transfer %c (%d, %d) %dx%d\n", is_read ? 'r' : 'w',
gpu.dma.x, gpu.dma.y, gpu.dma.w, gpu.dma.h);
+ if (gpu.gpu_state_change)
+ gpu.gpu_state_change(PGS_VRAM_TRANSFER_START);
}
static void finish_vram_transfer(int is_read)
renderer_update_caches(gpu.dma_start.x, gpu.dma_start.y,
gpu.dma_start.w, gpu.dma_start.h, 0);
}
+ if (gpu.gpu_state_change)
+ gpu.gpu_state_change(PGS_VRAM_TRANSFER_END);
}
static void do_vram_copy(const uint32_t *params)
return count - pos;
}
-static void flush_cmd_buffer(void)
+static noinline void flush_cmd_buffer(void)
{
int left = do_cmd_buffer(gpu.cmd_buffer, gpu.cmd_len);
if (left > 0)
memmove(gpu.cmd_buffer, gpu.cmd_buffer + gpu.cmd_len - left, left * 4);
- gpu.cmd_len = left;
+ if (left != gpu.cmd_len) {
+ if (!gpu.dma.h && gpu.gpu_state_change)
+ gpu.gpu_state_change(PGS_PRIMITIVE_START);
+ gpu.cmd_len = left;
+ }
}
void GPUwriteDataMem(uint32_t *mem, int count)
gpu.mmap = cbs->mmap;
gpu.munmap = cbs->munmap;
+ gpu.gpu_state_change = cbs->gpu_state_change;
// delayed vram mmap
if (gpu.vram == NULL)
(int *x, int *y, int *w, int *h, int *vram_h);
void *(*mmap)(unsigned int size);
void (*munmap)(void *ptr, unsigned int size);
+ void (*gpu_state_change)(int what); // psx_gpu_state
};
extern struct psx_gpu gpu;