mirror of
https://github.com/ARMSX2/ARMSX1.git
synced 2026-08-24 16:53:35 -07:00
Assorted fixes and improvements
Implemented controller support Implemented SDA analog mode (WIP) Fixed polygon edge seam Fixed SPU note length issue Fixed small XA-ADPCM stutter right when starting playback
This commit is contained in:
@@ -24,6 +24,7 @@ bin/psxe frontend/main.c:
|
||||
|
||||
gcc $(SOURCES) -o bin/psxe \
|
||||
-I"." \
|
||||
-I"psx" \
|
||||
-DOS_INFO="$(OS_INFO)" \
|
||||
-DREP_VERSION="$(VERSION_TAG)" \
|
||||
-DREP_COMMIT_HASH="$(COMMIT_HASH)" \
|
||||
|
||||
@@ -10,6 +10,7 @@ $PSX_DIR = "."
|
||||
mkdir -Force -Path bin > $null
|
||||
|
||||
gcc -I"`"$($PSX_DIR)`"" `
|
||||
-I"`"$($PSX_DIR)\psx`"" `
|
||||
-I"`"$($SDL2_DIR)\include`"" `
|
||||
-I"`"$($SDL2_DIR)\include\SDL2`"" `
|
||||
"psx\*.c" `
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ $PSX_DIR = "."
|
||||
mkdir -Force -Path bin > $null
|
||||
|
||||
gcc -I"`"$($PSX_DIR)`"" `
|
||||
-I"`"$($PSX_DIR)\psx`"" `
|
||||
-I"`"$($SDL2_DIR)\include`"" `
|
||||
-I"`"$($SDL2_DIR)\include\SDL2`"" `
|
||||
"psx\*.c" `
|
||||
@@ -25,6 +26,6 @@ gcc -I"`"$($PSX_DIR)`"" `
|
||||
-m64 -lSDL2main -lSDL2 -Wno-overflow `
|
||||
-Wall -pedantic -DLOG_USE_COLOR `
|
||||
-Wno-address-of-packed-member `
|
||||
-ffast-math -Ofast -g
|
||||
-ffast-math -Ofast -g -flto
|
||||
|
||||
Copy-Item -Path "sdl2-win64/SDL2.dll" -Destination "bin"
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
static const char* g_version_text =
|
||||
#ifdef _WIN32
|
||||
"psxe.exe (" STR(OS_INFO) ") " STR(REP_VERSION) "-" STR(REP_COMMIT_HASH) "\n"
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include "argparse.h"
|
||||
#include "toml.h"
|
||||
#include "psx/log.h"
|
||||
|
||||
typedef struct {
|
||||
int use_args;
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
#include "psx/psx.h"
|
||||
#include "psx/input/sda.h"
|
||||
#include "psx/disc/cue.h"
|
||||
#include "psx.h"
|
||||
#include "input/sda.h"
|
||||
#include "disc/cue.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "config.h"
|
||||
|
||||
+122
-5
@@ -1,6 +1,8 @@
|
||||
#include "screen.h"
|
||||
|
||||
uint16_t screen_get_button(SDL_Keycode k) {
|
||||
#include "input/sda.h"
|
||||
|
||||
uint32_t screen_get_button(SDL_Keycode k) {
|
||||
if (k == SDLK_x ) return PSXI_SW_SDA_CROSS;
|
||||
if (k == SDLK_a ) return PSXI_SW_SDA_SQUARE;
|
||||
if (k == SDLK_w ) return PSXI_SW_SDA_TRIANGLE;
|
||||
@@ -17,10 +19,40 @@ uint16_t screen_get_button(SDL_Keycode k) {
|
||||
if (k == SDLK_3 ) return PSXI_SW_SDA_R2;
|
||||
if (k == SDLK_z ) return PSXI_SW_SDA_L3;
|
||||
if (k == SDLK_c ) return PSXI_SW_SDA_R3;
|
||||
if (k == SDLK_2 ) return PSXI_SW_SDA_ANALOG;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t screen_get_button_joystick(uint8_t b) {
|
||||
if (b == SDL_CONTROLLER_BUTTON_A ) return PSXI_SW_SDA_CROSS;
|
||||
if (b == SDL_CONTROLLER_BUTTON_X ) return PSXI_SW_SDA_SQUARE;
|
||||
if (b == SDL_CONTROLLER_BUTTON_Y ) return PSXI_SW_SDA_TRIANGLE;
|
||||
if (b == SDL_CONTROLLER_BUTTON_B ) return PSXI_SW_SDA_CIRCLE;
|
||||
if (b == SDL_CONTROLLER_BUTTON_START ) return PSXI_SW_SDA_START;
|
||||
if (b == SDL_CONTROLLER_BUTTON_GUIDE ) return PSXI_SW_SDA_SELECT;
|
||||
if (b == SDL_CONTROLLER_BUTTON_DPAD_UP ) return PSXI_SW_SDA_PAD_UP;
|
||||
if (b == SDL_CONTROLLER_BUTTON_DPAD_DOWN ) return PSXI_SW_SDA_PAD_DOWN;
|
||||
if (b == SDL_CONTROLLER_BUTTON_DPAD_LEFT ) return PSXI_SW_SDA_PAD_LEFT;
|
||||
if (b == SDL_CONTROLLER_BUTTON_DPAD_RIGHT ) return PSXI_SW_SDA_PAD_RIGHT;
|
||||
if (b == SDL_CONTROLLER_BUTTON_LEFTSHOULDER ) return PSXI_SW_SDA_L1;
|
||||
if (b == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) return PSXI_SW_SDA_R1;
|
||||
if (b == SDL_CONTROLLER_AXIS_TRIGGERLEFT ) return PSXI_SW_SDA_L2; // Can't map these yet
|
||||
if (b == SDL_CONTROLLER_AXIS_TRIGGERRIGHT ) return PSXI_SW_SDA_R2; // Can't map these yet
|
||||
if (b == SDL_CONTROLLER_BUTTON_LEFTSTICK ) return PSXI_SW_SDA_L3;
|
||||
if (b == SDL_CONTROLLER_BUTTON_RIGHTSTICK ) return PSXI_SW_SDA_R3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_GameController* screen_find_controller() {
|
||||
for (int i = 0; i < SDL_NumJoysticks(); i++)
|
||||
if (SDL_IsGameController(i))
|
||||
return SDL_GameControllerOpen(i);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int screen_get_base_width(psxe_screen_t* screen) {
|
||||
int width = psx_get_dmode_width(screen->psx);
|
||||
|
||||
@@ -51,8 +83,10 @@ void psxe_screen_init(psxe_screen_t* screen, psx_t* psx) {
|
||||
screen->texture_width = PSX_GPU_FB_WIDTH;
|
||||
screen->texture_height = PSX_GPU_FB_HEIGHT;
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER);
|
||||
SDL_SetRenderDrawColor(screen->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
||||
|
||||
screen->controller = screen_find_controller();
|
||||
}
|
||||
|
||||
void psxe_screen_reload(psxe_screen_t* screen) {
|
||||
@@ -152,6 +186,9 @@ void psxe_screen_update(psxe_screen_t* screen) {
|
||||
// screen->psx->gpu->disp_y2 - screen->psx->gpu->disp_y1
|
||||
// );
|
||||
|
||||
if ((screen->psx->gpu->disp_y + screen->texture_height) > 512)
|
||||
display_buf = psx_get_vram(screen->psx);
|
||||
|
||||
SDL_UpdateTexture(screen->texture, NULL, display_buf, PSX_GPU_FB_STRIDE);
|
||||
SDL_RenderClear(screen->renderer);
|
||||
|
||||
@@ -248,12 +285,76 @@ void psxe_screen_update(psxe_screen_t* screen) {
|
||||
} break;
|
||||
}
|
||||
|
||||
uint16_t mask = screen_get_button(event.key.keysym.sym);
|
||||
uint32_t mask = screen_get_button(event.key.keysym.sym);
|
||||
|
||||
psx_pad_button_press(screen->pad, 0, mask);
|
||||
|
||||
if (event.key.keysym.sym == SDLK_RETURN) {
|
||||
if (event.key.keysym.sym == SDLK_RETURN)
|
||||
psx_exp2_atcons_put(screen->psx->exp2, 13);
|
||||
} break;
|
||||
|
||||
case SDL_CONTROLLERDEVICEADDED: {
|
||||
if (!screen->controller)
|
||||
screen->controller = SDL_GameControllerOpen(event.cdevice.which);
|
||||
} break;
|
||||
|
||||
case SDL_CONTROLLERDEVICEREMOVED: {
|
||||
SDL_Joystick* joy = SDL_GameControllerGetJoystick(screen->controller);
|
||||
SDL_JoystickID id = SDL_JoystickInstanceID(joy);
|
||||
|
||||
if (screen->controller && (event.cdevice.which == id)) {
|
||||
SDL_GameControllerClose(screen->controller);
|
||||
|
||||
screen->controller = screen_find_controller();
|
||||
}
|
||||
} break;
|
||||
|
||||
case SDL_CONTROLLERBUTTONDOWN: {
|
||||
SDL_Joystick* joy = SDL_GameControllerGetJoystick(screen->controller);
|
||||
SDL_JoystickID id = SDL_JoystickInstanceID(joy);
|
||||
|
||||
if (screen->controller && (event.cdevice.which == id)) {
|
||||
uint32_t mask = screen_get_button_joystick(event.cbutton.button);
|
||||
|
||||
psx_pad_button_press(screen->pad, 0, mask);
|
||||
}
|
||||
} break;
|
||||
|
||||
case SDL_CONTROLLERBUTTONUP: {
|
||||
SDL_Joystick* joy = SDL_GameControllerGetJoystick(screen->controller);
|
||||
SDL_JoystickID id = SDL_JoystickInstanceID(joy);
|
||||
|
||||
if (screen->controller && (event.cdevice.which == id)) {
|
||||
uint32_t mask = screen_get_button_joystick(event.cbutton.button);
|
||||
|
||||
psx_pad_button_release(screen->pad, 0, mask);
|
||||
}
|
||||
} break;
|
||||
|
||||
case SDL_CONTROLLERAXISMOTION: {
|
||||
SDL_Joystick* joy = SDL_GameControllerGetJoystick(screen->controller);
|
||||
SDL_JoystickID id = SDL_JoystickInstanceID(joy);
|
||||
|
||||
if (screen->controller && (event.cdevice.which == id)) {
|
||||
int mapped_axis = ((int)event.caxis.value + INT16_MAX + 1) / 0x100;
|
||||
|
||||
switch (event.caxis.axis) {
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX:
|
||||
psx_pad_analog_change(screen->pad, 0, PSXI_AX_SDA_RIGHT_HORZ, mapped_axis);
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY:
|
||||
psx_pad_analog_change(screen->pad, 0, PSXI_AX_SDA_RIGHT_VERT, mapped_axis);
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLER_AXIS_LEFTX:
|
||||
psx_pad_analog_change(screen->pad, 0, PSXI_AX_SDA_LEFT_HORZ, mapped_axis);
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLER_AXIS_LEFTY:
|
||||
psx_pad_analog_change(screen->pad, 0, PSXI_AX_SDA_LEFT_VERT, mapped_axis);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -262,7 +363,7 @@ void psxe_screen_update(psxe_screen_t* screen) {
|
||||
} break;
|
||||
|
||||
case SDL_KEYUP: {
|
||||
uint16_t mask = screen_get_button(event.key.keysym.sym);
|
||||
uint32_t mask = screen_get_button(event.key.keysym.sym);
|
||||
|
||||
psx_pad_button_release(screen->pad, 0, mask);
|
||||
} break;
|
||||
@@ -292,6 +393,22 @@ void psxe_screen_destroy(psxe_screen_t* screen) {
|
||||
void psxe_gpu_dmode_event_cb(psx_gpu_t* gpu) {
|
||||
psxe_screen_t* screen = gpu->udata[0];
|
||||
|
||||
// printf("res=(%u,%u) off=(%u,%u) disp=(%u,%u-%u,%u) draw=(%u,%u-%u,%u) vres=%u\n",
|
||||
// screen->texture_width,
|
||||
// screen->texture_height,
|
||||
// screen->psx->gpu->disp_x,
|
||||
// screen->psx->gpu->disp_y,
|
||||
// screen->psx->gpu->disp_x1,
|
||||
// screen->psx->gpu->disp_y1,
|
||||
// screen->psx->gpu->disp_x2,
|
||||
// screen->psx->gpu->disp_y2,
|
||||
// screen->psx->gpu->draw_x1,
|
||||
// screen->psx->gpu->draw_y1,
|
||||
// screen->psx->gpu->draw_x2,
|
||||
// screen->psx->gpu->draw_y2,
|
||||
// screen->psx->gpu->disp_y2 - screen->psx->gpu->disp_y1
|
||||
// );
|
||||
|
||||
screen->format = psx_get_display_format(screen->psx) ?
|
||||
SDL_PIXELFORMAT_RGB24 : SDL_PIXELFORMAT_BGR555;
|
||||
|
||||
|
||||
+4
-1
@@ -1,12 +1,13 @@
|
||||
#ifndef SCREEN_H
|
||||
#define SCREEN_H
|
||||
|
||||
#include "psx/psx.h"
|
||||
#include "psx.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL2/SDL.h"
|
||||
#include "SDL2/SDL_gamecontroller.h"
|
||||
|
||||
typedef struct {
|
||||
SDL_Window* window;
|
||||
@@ -28,6 +29,8 @@ typedef struct {
|
||||
int vertical_mode;
|
||||
int debug_mode;
|
||||
int open;
|
||||
|
||||
SDL_GameController* controller;
|
||||
} psxe_screen_t;
|
||||
|
||||
psxe_screen_t* psxe_screen_create();
|
||||
|
||||
+13
-11
@@ -460,6 +460,7 @@ void cdrom_cmd_readn(psx_cdrom_t* cdrom) {
|
||||
if (cdrom->mode & MODE_XA_ADPCM) {
|
||||
cdrom->xa_msf = cdrom->seek_msf;
|
||||
cdrom->xa_playing = 1;
|
||||
cdrom->xa_remaining_samples = 0;
|
||||
|
||||
SET_BITS(status, STAT_ADPBUSY_MASK, STAT_ADPBUSY_MASK);
|
||||
|
||||
@@ -1311,6 +1312,7 @@ void cdrom_cmd_reads(psx_cdrom_t* cdrom) {
|
||||
if (cdrom->mode & MODE_XA_ADPCM) {
|
||||
cdrom->xa_msf = cdrom->seek_msf;
|
||||
cdrom->xa_playing = 1;
|
||||
cdrom->xa_remaining_samples = 0;
|
||||
|
||||
SET_BITS(status, STAT_ADPBUSY_MASK, STAT_ADPBUSY_MASK);
|
||||
|
||||
@@ -1606,17 +1608,17 @@ void cdrom_write_status(psx_cdrom_t* cdrom, uint8_t value) {
|
||||
}
|
||||
|
||||
void cdrom_write_cmd(psx_cdrom_t* cdrom, uint8_t value) {
|
||||
printf("%s(%02x) %u params=[%02x, %02x, %02x, %02x, %02x, %02x]\n",
|
||||
g_psx_cdrom_command_names[value],
|
||||
value,
|
||||
cdrom->pfifo_index,
|
||||
cdrom->pfifo[0],
|
||||
cdrom->pfifo[1],
|
||||
cdrom->pfifo[2],
|
||||
cdrom->pfifo[3],
|
||||
cdrom->pfifo[4],
|
||||
cdrom->pfifo[5]
|
||||
);
|
||||
// printf("%s(%02x) %u params=[%02x, %02x, %02x, %02x, %02x, %02x]\n",
|
||||
// g_psx_cdrom_command_names[value],
|
||||
// value,
|
||||
// cdrom->pfifo_index,
|
||||
// cdrom->pfifo[0],
|
||||
// cdrom->pfifo[1],
|
||||
// cdrom->pfifo[2],
|
||||
// cdrom->pfifo[3],
|
||||
// cdrom->pfifo[4],
|
||||
// cdrom->pfifo[5]
|
||||
// );
|
||||
|
||||
cdrom->command = value;
|
||||
cdrom->state = CD_STATE_RECV_CMD;
|
||||
|
||||
@@ -346,6 +346,7 @@ void psx_dma_do_cdrom(psx_dma_t* dma) {
|
||||
if (!size) {
|
||||
printf("0 sized CDROM DMA\n");
|
||||
|
||||
return;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
+96
-71
@@ -27,15 +27,15 @@ uint16_t gpu_to_bgr555(uint32_t color) {
|
||||
// #define BGR555(c) gpu_to_bgr555(c)
|
||||
|
||||
int min3(int a, int b, int c) {
|
||||
int m = a <= b ? a : b;
|
||||
int m = (a <= b) ? a : b;
|
||||
|
||||
return m <= c ? m : c;
|
||||
return (m <= c) ? m : c;
|
||||
}
|
||||
|
||||
int max3(int a, int b, int c) {
|
||||
int m = a >= b ? a : b;
|
||||
int m = (a > b) ? a : b;
|
||||
|
||||
return m >= c ? m : c;
|
||||
return (m > c) ? m : c;
|
||||
}
|
||||
|
||||
psx_gpu_t* psx_gpu_create() {
|
||||
@@ -171,7 +171,7 @@ uint16_t gpu_fetch_texel(psx_gpu_t* gpu, uint16_t tx, uint16_t ty, uint32_t tpx,
|
||||
}
|
||||
}
|
||||
|
||||
void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2, poly_data_t data) {
|
||||
void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2, poly_data_t data, int edge) {
|
||||
vertex_t a, b, c, p;
|
||||
|
||||
int tpx = (data.texp & 0xf) << 6;
|
||||
@@ -200,22 +200,16 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
}
|
||||
|
||||
a.x += gpu->off_x;
|
||||
a.y += gpu->off_y;
|
||||
b.x += gpu->off_x;
|
||||
b.y += gpu->off_y;
|
||||
c.x += gpu->off_x;
|
||||
a.y += gpu->off_y;
|
||||
b.y += gpu->off_y;
|
||||
c.y += gpu->off_y;
|
||||
|
||||
int xmin = max(min3(a.x, b.x, c.x), gpu->draw_x1);
|
||||
int ymin = max(min3(a.y, b.y, c.y), gpu->draw_y1);
|
||||
int xmax = min(max3(a.x, b.x, c.x), gpu->draw_x2);
|
||||
int ymax = min(max3(a.y, b.y, c.y), gpu->draw_y2);
|
||||
|
||||
// Hack
|
||||
if (!(data.attrib & PA_TEXTURED)) {
|
||||
++xmax;
|
||||
++ymax;
|
||||
}
|
||||
int xmin = min3(a.x, b.x, c.x);
|
||||
int ymin = min3(a.y, b.y, c.y);
|
||||
int xmax = max3(a.x, b.x, c.x);
|
||||
int ymax = max3(a.y, b.y, c.y);
|
||||
|
||||
float area = EDGE(a, b, c);
|
||||
|
||||
@@ -234,7 +228,12 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
float z1 = EDGE(c, a, p);
|
||||
float z2 = EDGE(a, b, p);
|
||||
|
||||
if ((z0 < 0) || (z1 < 0) || (z2 < 0))
|
||||
int e = ((z0 < 0) || (z1 < 0) || (z2 < 0));
|
||||
|
||||
if (transp && edge)
|
||||
e = ((z0 < 0) || (z1 <= 0) || (z2 < 0));
|
||||
|
||||
if (e)
|
||||
continue;
|
||||
|
||||
uint16_t color = 0;
|
||||
@@ -275,30 +274,33 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
if (!texel)
|
||||
continue;
|
||||
|
||||
if (transp) {
|
||||
if (transp)
|
||||
transp = (texel & 0x8000) != 0;
|
||||
}
|
||||
|
||||
if (data.attrib & PA_RAW) {
|
||||
color = texel;
|
||||
} else {
|
||||
int tr = ((texel >> 0 ) & 0x1f) << 3;
|
||||
int tg = ((texel >> 5 ) & 0x1f) << 3;
|
||||
int tb = ((texel >> 10) & 0x1f) << 3;
|
||||
float tr = ((texel >> 0 ) & 0x1f) << 3;
|
||||
float tg = ((texel >> 5 ) & 0x1f) << 3;
|
||||
float tb = ((texel >> 10) & 0x1f) << 3;
|
||||
|
||||
int mr = (mod >> 0 ) & 0xff;
|
||||
int mg = (mod >> 8 ) & 0xff;
|
||||
int mb = (mod >> 16) & 0xff;
|
||||
float mr = (mod >> 0 ) & 0xff;
|
||||
float mg = (mod >> 8 ) & 0xff;
|
||||
float mb = (mod >> 16) & 0xff;
|
||||
|
||||
int cr = (tr * mr) / 0x80;
|
||||
int cg = (tg * mg) / 0x80;
|
||||
int cb = (tb * mb) / 0x80;
|
||||
float cr = (tr * mr) / 128.0f;
|
||||
float cg = (tg * mg) / 128.0f;
|
||||
float cb = (tb * mb) / 128.0f;
|
||||
|
||||
cr = (cr >= 0xff) ? 0xff : ((cr <= 0) ? 0 : cr);
|
||||
cg = (cg >= 0xff) ? 0xff : ((cg <= 0) ? 0 : cg);
|
||||
cb = (cb >= 0xff) ? 0xff : ((cb <= 0) ? 0 : cb);
|
||||
cr = (cr >= 255.0f) ? 255.0f : ((cr <= 0.0f) ? 0.0f : cr);
|
||||
cg = (cg >= 255.0f) ? 255.0f : ((cg <= 0.0f) ? 0.0f : cg);
|
||||
cb = (cb >= 255.0f) ? 255.0f : ((cb <= 0.0f) ? 0.0f : cb);
|
||||
|
||||
uint32_t rgb = cr | (cg << 8) | (cb << 16);
|
||||
unsigned int ucr = cr;
|
||||
unsigned int ucg = cg;
|
||||
unsigned int ucb = cb;
|
||||
|
||||
uint32_t rgb = ucr | (ucg << 8) | (ucb << 16);
|
||||
|
||||
color = BGR555(rgb);
|
||||
}
|
||||
@@ -306,16 +308,16 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
color = BGR555(mod);
|
||||
}
|
||||
|
||||
int cr = ((color >> 0 ) & 0x1f) << 3;
|
||||
int cg = ((color >> 5 ) & 0x1f) << 3;
|
||||
int cb = ((color >> 10) & 0x1f) << 3;
|
||||
float cr = ((color >> 0 ) & 0x1f) << 3;
|
||||
float cg = ((color >> 5 ) & 0x1f) << 3;
|
||||
float cb = ((color >> 10) & 0x1f) << 3;
|
||||
|
||||
if (transp) {
|
||||
uint16_t back = gpu->vram[x + (y * 1024)];
|
||||
|
||||
int br = ((back >> 0 ) & 0x1f) << 3;
|
||||
int bg = ((back >> 5 ) & 0x1f) << 3;
|
||||
int bb = ((back >> 10) & 0x1f) << 3;
|
||||
float br = ((back >> 0 ) & 0x1f) << 3;
|
||||
float bg = ((back >> 5 ) & 0x1f) << 3;
|
||||
float bb = ((back >> 10) & 0x1f) << 3;
|
||||
|
||||
// Do we use transp or gpustat here?
|
||||
switch (transp_mode) {
|
||||
@@ -341,11 +343,15 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
} break;
|
||||
}
|
||||
|
||||
cr = (cr >= 0xff) ? 0xff : ((cr <= 0) ? 0 : cr);
|
||||
cg = (cg >= 0xff) ? 0xff : ((cg <= 0) ? 0 : cg);
|
||||
cb = (cb >= 0xff) ? 0xff : ((cb <= 0) ? 0 : cb);
|
||||
cr = (cr >= 255.0f) ? 255.0f : ((cr <= 0.0f) ? 0.0f : cr);
|
||||
cg = (cg >= 255.0f) ? 255.0f : ((cg <= 0.0f) ? 0.0f : cg);
|
||||
cb = (cb >= 255.0f) ? 255.0f : ((cb <= 0.0f) ? 0.0f : cb);
|
||||
|
||||
uint32_t rgb = cr | (cg << 8) | (cb << 16);
|
||||
unsigned int ucr = cr;
|
||||
unsigned int ucg = cg;
|
||||
unsigned int ucb = cb;
|
||||
|
||||
uint32_t rgb = ucr | (ucg << 8) | (ucb << 16);
|
||||
|
||||
color = BGR555(rgb);
|
||||
}
|
||||
@@ -355,7 +361,7 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
}
|
||||
}
|
||||
|
||||
#define CLAMP(v, d, u) ((v) < (d)) ? (d) : (((v) >= (u)) ? (u) : (v))
|
||||
#define CLAMP(v, d, u) ((v) <= (d)) ? (d) : (((v) >= (u)) ? (u) : (v))
|
||||
|
||||
void gpu_render_rect(psx_gpu_t* gpu, rect_data_t data) {
|
||||
if ((data.v0.x >= 1024) || (data.v0.y >= 512))
|
||||
@@ -420,35 +426,39 @@ void gpu_render_rect(psx_gpu_t* gpu, rect_data_t data) {
|
||||
if (transp)
|
||||
transp = (texel & 0x8000) != 0;
|
||||
|
||||
int tr = ((texel >> 0 ) & 0x1f) << 3;
|
||||
int tg = ((texel >> 5 ) & 0x1f) << 3;
|
||||
int tb = ((texel >> 10) & 0x1f) << 3;
|
||||
float tr = ((texel >> 0 ) & 0x1f) << 3;
|
||||
float tg = ((texel >> 5 ) & 0x1f) << 3;
|
||||
float tb = ((texel >> 10) & 0x1f) << 3;
|
||||
|
||||
int mr = (data.v0.c >> 0 ) & 0xff;
|
||||
int mg = (data.v0.c >> 8 ) & 0xff;
|
||||
int mb = (data.v0.c >> 16) & 0xff;
|
||||
float mr = (data.v0.c >> 0 ) & 0xff;
|
||||
float mg = (data.v0.c >> 8 ) & 0xff;
|
||||
float mb = (data.v0.c >> 16) & 0xff;
|
||||
|
||||
int cr = (tr * mr) / 0x80;
|
||||
int cg = (tg * mg) / 0x80;
|
||||
int cb = (tb * mb) / 0x80;
|
||||
float cr = (tr * mr) / 128.0f;
|
||||
float cg = (tg * mg) / 128.0f;
|
||||
float cb = (tb * mb) / 128.0f;
|
||||
|
||||
uint32_t rgb = cr | (cg << 8) | (cb << 16);
|
||||
unsigned int ucr = cr;
|
||||
unsigned int ucg = cg;
|
||||
unsigned int ucb = cb;
|
||||
|
||||
uint32_t rgb = ucr | (ucg << 8) | (ucb << 16);
|
||||
|
||||
color = BGR555(rgb);
|
||||
} else {
|
||||
color = BGR555(data.v0.c);
|
||||
}
|
||||
|
||||
int cr = ((color >> 0 ) & 0x1f) << 3;
|
||||
int cg = ((color >> 5 ) & 0x1f) << 3;
|
||||
int cb = ((color >> 10) & 0x1f) << 3;
|
||||
float cr = ((color >> 0 ) & 0x1f) << 3;
|
||||
float cg = ((color >> 5 ) & 0x1f) << 3;
|
||||
float cb = ((color >> 10) & 0x1f) << 3;
|
||||
|
||||
if (transp) {
|
||||
uint16_t back = gpu->vram[x + (y * 1024)];
|
||||
|
||||
int br = ((back >> 0 ) & 0x1f) << 3;
|
||||
int bg = ((back >> 5 ) & 0x1f) << 3;
|
||||
int bb = ((back >> 10) & 0x1f) << 3;
|
||||
float br = ((back >> 0 ) & 0x1f) << 3;
|
||||
float bg = ((back >> 5 ) & 0x1f) << 3;
|
||||
float bb = ((back >> 10) & 0x1f) << 3;
|
||||
|
||||
switch (transp_mode) {
|
||||
case 0: {
|
||||
@@ -473,11 +483,15 @@ void gpu_render_rect(psx_gpu_t* gpu, rect_data_t data) {
|
||||
} break;
|
||||
}
|
||||
|
||||
cr = (cr >= 0xff) ? 0xff : ((cr <= 0) ? 0 : cr);
|
||||
cg = (cg >= 0xff) ? 0xff : ((cg <= 0) ? 0 : cg);
|
||||
cb = (cb >= 0xff) ? 0xff : ((cb <= 0) ? 0 : cb);
|
||||
cr = (cr >= 255.0f) ? 255.0f : ((cr <= 0.0f) ? 0.0f : cr);
|
||||
cg = (cg >= 255.0f) ? 255.0f : ((cg <= 0.0f) ? 0.0f : cg);
|
||||
cb = (cb >= 255.0f) ? 255.0f : ((cb <= 0.0f) ? 0.0f : cb);
|
||||
|
||||
uint32_t rgb = cr | (cg << 8) | (cb << 16);
|
||||
unsigned int ucr = cr;
|
||||
unsigned int ucg = cg;
|
||||
unsigned int ucb = cb;
|
||||
|
||||
uint32_t rgb = ucr | (ucg << 8) | (ucb << 16);
|
||||
|
||||
color = BGR555(rgb);
|
||||
}
|
||||
@@ -901,10 +915,10 @@ void gpu_poly(psx_gpu_t* gpu) {
|
||||
poly.v[3].ty = (gpu->buf[2+3*texc_offset] >> 8) & 0xff;
|
||||
|
||||
if (poly.attrib & PA_QUAD) {
|
||||
gpu_render_triangle(gpu, poly.v[0], poly.v[1], poly.v[2], poly);
|
||||
gpu_render_triangle(gpu, poly.v[1], poly.v[2], poly.v[3], poly);
|
||||
gpu_render_triangle(gpu, poly.v[0], poly.v[1], poly.v[2], poly, 0);
|
||||
gpu_render_triangle(gpu, poly.v[1], poly.v[2], poly.v[3], poly, 1);
|
||||
} else {
|
||||
gpu_render_triangle(gpu, poly.v[0], poly.v[1], poly.v[2], poly);
|
||||
gpu_render_triangle(gpu, poly.v[0], poly.v[1], poly.v[2], poly, 0);
|
||||
}
|
||||
|
||||
gpu->state = GPU_STATE_RECV_CMD;
|
||||
@@ -1483,6 +1497,17 @@ void gpu_cmd_02(psx_gpu_t* gpu) {
|
||||
|
||||
uint16_t color = BGR555(gpu->color);
|
||||
|
||||
// printf("02 draw=(%u,%u-%u,%u) v0=(%u,%u) siz=(%u,%u)\n",
|
||||
// gpu->draw_x1,
|
||||
// gpu->draw_y1,
|
||||
// gpu->draw_x2,
|
||||
// gpu->draw_y2,
|
||||
// gpu->v0.x,
|
||||
// gpu->v0.y,
|
||||
// gpu->xsiz,
|
||||
// gpu->ysiz
|
||||
// );
|
||||
|
||||
for (uint32_t y = gpu->v0.y; y < (gpu->v0.y + gpu->ysiz); y++) {
|
||||
for (uint32_t x = gpu->v0.x; x < (gpu->v0.x + gpu->xsiz); x++) {
|
||||
int bc = (x >= gpu->draw_x1) && (x <= gpu->draw_x2) &&
|
||||
@@ -1597,10 +1622,10 @@ void psx_gpu_update_cmd(psx_gpu_t* gpu) {
|
||||
gpu->texp_d = (gpu->gpustat >> 7) & 0x3;
|
||||
} break;
|
||||
case 0xe2: {
|
||||
gpu->texw_mx = (gpu->buf[0] >> 0 ) & 0x1f;
|
||||
gpu->texw_my = (gpu->buf[0] >> 5 ) & 0x1f;
|
||||
gpu->texw_ox = (gpu->buf[0] >> 10) & 0x1f;
|
||||
gpu->texw_oy = (gpu->buf[0] >> 15) & 0x1f;
|
||||
gpu->texw_mx = ((gpu->buf[0] >> 0 ) & 0x1f) << 3;
|
||||
gpu->texw_my = ((gpu->buf[0] >> 5 ) & 0x1f) << 3;
|
||||
gpu->texw_ox = ((gpu->buf[0] >> 10) & 0x1f) << 3;
|
||||
gpu->texw_oy = ((gpu->buf[0] >> 15) & 0x1f) << 3;
|
||||
} break;
|
||||
case 0xe3: {
|
||||
gpu->draw_x1 = (gpu->buf[0] >> 0 ) & 0x3ff;
|
||||
|
||||
+3
-3
@@ -9,9 +9,9 @@ typedef struct psx_input_t psx_input_t;
|
||||
|
||||
typedef void (*psx_input_write_t)(void*, uint16_t);
|
||||
typedef uint32_t (*psx_input_read_t)(void*);
|
||||
typedef void (*psx_input_on_button_press_t)(void*, uint16_t);
|
||||
typedef void (*psx_input_on_button_release_t)(void*, uint16_t);
|
||||
typedef void (*psx_input_on_analog_change_t)(void*, uint16_t);
|
||||
typedef void (*psx_input_on_button_press_t)(void*, uint32_t);
|
||||
typedef void (*psx_input_on_button_release_t)(void*, uint32_t);
|
||||
typedef void (*psx_input_on_analog_change_t)(void*, uint32_t, uint8_t);
|
||||
typedef int (*psx_input_query_fifo_t)(void*);
|
||||
|
||||
struct psx_input_t {
|
||||
|
||||
+56
-27
@@ -6,19 +6,21 @@
|
||||
#include "../log.h"
|
||||
|
||||
uint32_t pad_read_rx(psx_pad_t* pad) {
|
||||
psx_input_t* joy = pad->joy_slot[(pad->ctrl >> 13) & 1];
|
||||
psx_mcd_t* mcd = pad->mcd_slot[(pad->ctrl >> 13) & 1];
|
||||
int slot = (pad->ctrl >> 13) & 1;
|
||||
|
||||
if (!pad->dest)
|
||||
psx_input_t* joy = pad->joy_slot[slot];
|
||||
psx_mcd_t* mcd = pad->mcd_slot[slot];
|
||||
|
||||
if (!pad->dest[slot])
|
||||
return 0xffffffff;
|
||||
|
||||
if (!(pad->ctrl & CTRL_JOUT) && !(pad->ctrl & CTRL_RXEN))
|
||||
return 0xffffffff;
|
||||
|
||||
switch (pad->dest) {
|
||||
switch (pad->dest[slot]) {
|
||||
case DEST_JOY: {
|
||||
if (!joy) {
|
||||
pad->dest = 0;
|
||||
pad->dest[slot] = 0;
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
@@ -26,14 +28,18 @@ uint32_t pad_read_rx(psx_pad_t* pad) {
|
||||
uint8_t data = joy->read_func(joy->udata);
|
||||
|
||||
if (!joy->query_fifo_func(joy->udata))
|
||||
pad->dest = 0;
|
||||
pad->dest[slot] = 0;
|
||||
|
||||
return data;
|
||||
} break;
|
||||
|
||||
case DEST_MCD: {
|
||||
pad->dest[slot] = 0;
|
||||
|
||||
return 0xff;
|
||||
|
||||
if (!mcd) {
|
||||
pad->dest = 0;
|
||||
pad->dest[slot] = 0;
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
@@ -41,7 +47,7 @@ uint32_t pad_read_rx(psx_pad_t* pad) {
|
||||
uint8_t data = psx_mcd_read(mcd);
|
||||
|
||||
if (!psx_mcd_query(mcd))
|
||||
pad->dest = 0;
|
||||
pad->dest[slot] = 0;
|
||||
|
||||
return data;
|
||||
} break;
|
||||
@@ -51,24 +57,35 @@ uint32_t pad_read_rx(psx_pad_t* pad) {
|
||||
}
|
||||
|
||||
void pad_write_tx(psx_pad_t* pad, uint16_t data) {
|
||||
psx_input_t* joy = pad->joy_slot[(pad->ctrl >> 13) & 1];
|
||||
psx_mcd_t* mcd = pad->mcd_slot[(pad->ctrl >> 13) & 1];
|
||||
int slot = (pad->ctrl >> 13) & 1;
|
||||
// printf("slot=%u dest=%02x write tx data=%02x ", slot, pad->dest[slot], data);
|
||||
|
||||
psx_input_t* joy = pad->joy_slot[slot];
|
||||
psx_mcd_t* mcd = pad->mcd_slot[slot];
|
||||
|
||||
if (!(pad->ctrl & CTRL_TXEN))
|
||||
return;
|
||||
|
||||
if (!pad->dest) {
|
||||
// if (slot == 0)
|
||||
// printf("slot %u (%02x) write %08x\n", slot, pad->dest[slot], data);
|
||||
|
||||
if (!pad->dest[slot]) {
|
||||
if ((data == DEST_JOY) || (data == DEST_MCD)) {
|
||||
pad->dest = data;
|
||||
|
||||
pad->dest[slot] = data;
|
||||
|
||||
// printf(" slot=%u dest=%02x\n", slot, data);
|
||||
|
||||
// if (slot == 0)
|
||||
// printf("dest=%02x\n", data);
|
||||
|
||||
if (pad->ctrl & CTRL_ACIE)
|
||||
pad->cycles_until_irq = 1500;
|
||||
}
|
||||
} else {
|
||||
switch (pad->dest) {
|
||||
switch (pad->dest[slot]) {
|
||||
case DEST_JOY: {
|
||||
if (!joy) {
|
||||
pad->dest = 0;
|
||||
pad->dest[slot] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -76,12 +93,16 @@ void pad_write_tx(psx_pad_t* pad, uint16_t data) {
|
||||
joy->write_func(joy->udata, data);
|
||||
|
||||
if (!joy->query_fifo_func(joy->udata))
|
||||
pad->dest = 0;
|
||||
pad->dest[slot] = 0;
|
||||
} break;
|
||||
|
||||
case DEST_MCD: {
|
||||
pad->dest[slot] = 0;
|
||||
|
||||
return;
|
||||
|
||||
if (!mcd) {
|
||||
pad->dest = 0;
|
||||
pad->dest[slot] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -89,7 +110,7 @@ void pad_write_tx(psx_pad_t* pad, uint16_t data) {
|
||||
psx_mcd_write(mcd, data);
|
||||
|
||||
if (!psx_mcd_query(mcd))
|
||||
pad->dest = 0;
|
||||
pad->dest[slot] = 0;
|
||||
} break;
|
||||
}
|
||||
|
||||
@@ -99,23 +120,24 @@ void pad_write_tx(psx_pad_t* pad, uint16_t data) {
|
||||
}
|
||||
|
||||
uint32_t pad_handle_stat_read(psx_pad_t* pad) {
|
||||
// log_set_quiet(0);
|
||||
// log_fatal("pad stat read");
|
||||
// log_set_quiet(1);
|
||||
return 0x07;
|
||||
// // log_set_quiet(0);
|
||||
// printf("pad stat read\n");
|
||||
// // log_set_quiet(1);
|
||||
// return 0x07;
|
||||
psx_input_t* joy = pad->joy_slot[(pad->ctrl >> 13) & 1];
|
||||
|
||||
if (!joy)
|
||||
return 0x5 | pad->stat;
|
||||
return 0xff;
|
||||
|
||||
return 0x5 | (joy->query_fifo_func(joy->udata) << 1);
|
||||
return 0x7;
|
||||
}
|
||||
|
||||
void pad_handle_ctrl_write(psx_pad_t* pad, uint32_t value) {
|
||||
pad->ctrl = value;
|
||||
|
||||
if (!(pad->ctrl & CTRL_JOUT)) {
|
||||
pad->dest = 0;
|
||||
// pad->dest[0] = 0;
|
||||
// pad->dest[1] = 0;
|
||||
pad->ctrl &= ~CTRL_SLOT;
|
||||
|
||||
psx_mcd_reset(pad->mcd_slot[(pad->ctrl >> 13) & 1]);
|
||||
@@ -210,20 +232,27 @@ void psx_pad_write8(psx_pad_t* pad, uint32_t offset, uint8_t value) {
|
||||
printf("Unhandled 8-bit PAD write at offset %08x (%02x)", offset, value);
|
||||
}
|
||||
|
||||
void psx_pad_button_press(psx_pad_t* pad, int slot, uint16_t data) {
|
||||
void psx_pad_button_press(psx_pad_t* pad, int slot, uint32_t data) {
|
||||
psx_input_t* selected_slot = pad->joy_slot[slot];
|
||||
|
||||
if (selected_slot)
|
||||
selected_slot->on_button_press_func(selected_slot->udata, data);
|
||||
}
|
||||
|
||||
void psx_pad_button_release(psx_pad_t* pad, int slot, uint16_t data) {
|
||||
void psx_pad_button_release(psx_pad_t* pad, int slot, uint32_t data) {
|
||||
psx_input_t* selected_slot = pad->joy_slot[slot];
|
||||
|
||||
if (selected_slot)
|
||||
selected_slot->on_button_release_func(selected_slot->udata, data);
|
||||
}
|
||||
|
||||
void psx_pad_analog_change(psx_pad_t* pad, int slot, uint32_t stick, uint8_t data) {
|
||||
psx_input_t* selected_slot = pad->joy_slot[slot];
|
||||
|
||||
if (selected_slot)
|
||||
selected_slot->on_analog_change_func(selected_slot->udata, stick, data);
|
||||
}
|
||||
|
||||
void psx_pad_attach_joy(psx_pad_t* pad, int slot, psx_input_t* input) {
|
||||
if (pad->joy_slot[slot])
|
||||
psx_pad_detach_joy(pad, slot);
|
||||
|
||||
+4
-25
@@ -13,28 +13,6 @@
|
||||
#define PSX_PAD_SIZE 0x10
|
||||
#define PSX_PAD_END 0x1f80104f
|
||||
|
||||
// Controller/Input IDs
|
||||
#define PSXI_ID_SD 0x5a41
|
||||
#define PSXI_ID_SA_PAD 0x5a73
|
||||
#define PSXI_ID_SA_STICK 0x5a53
|
||||
|
||||
#define PSXI_SW_SDA_SELECT 0x0001
|
||||
#define PSXI_SW_SDA_L3 0x0002
|
||||
#define PSXI_SW_SDA_R3 0x0004
|
||||
#define PSXI_SW_SDA_START 0x0008
|
||||
#define PSXI_SW_SDA_PAD_UP 0x0010
|
||||
#define PSXI_SW_SDA_PAD_RIGHT 0x0020
|
||||
#define PSXI_SW_SDA_PAD_DOWN 0x0040
|
||||
#define PSXI_SW_SDA_PAD_LEFT 0x0080
|
||||
#define PSXI_SW_SDA_L2 0x0100
|
||||
#define PSXI_SW_SDA_R2 0x0200
|
||||
#define PSXI_SW_SDA_L1 0x0400
|
||||
#define PSXI_SW_SDA_R1 0x0800
|
||||
#define PSXI_SW_SDA_TRIANGLE 0x1000
|
||||
#define PSXI_SW_SDA_CIRCLE 0x2000
|
||||
#define PSXI_SW_SDA_CROSS 0x4000
|
||||
#define PSXI_SW_SDA_SQUARE 0x8000
|
||||
|
||||
/*
|
||||
0 TX Ready Flag 1 (1=Ready/Started)
|
||||
1 RX FIFO Not Empty (0=Empty, 1=Not Empty)
|
||||
@@ -136,7 +114,7 @@ typedef struct {
|
||||
int enable_once;
|
||||
int cycles_until_irq;
|
||||
int cycle_counter;
|
||||
int dest;
|
||||
int dest[2];
|
||||
|
||||
uint16_t mode, ctrl, baud, stat;
|
||||
} psx_pad_t;
|
||||
@@ -150,8 +128,9 @@ void psx_pad_write32(psx_pad_t*, uint32_t, uint32_t);
|
||||
void psx_pad_write16(psx_pad_t*, uint32_t, uint16_t);
|
||||
void psx_pad_write8(psx_pad_t*, uint32_t, uint8_t);
|
||||
void psx_pad_destroy(psx_pad_t*);
|
||||
void psx_pad_button_press(psx_pad_t*, int, uint16_t);
|
||||
void psx_pad_button_release(psx_pad_t*, int, uint16_t);
|
||||
void psx_pad_button_press(psx_pad_t*, int, uint32_t);
|
||||
void psx_pad_button_release(psx_pad_t*, int, uint32_t);
|
||||
void psx_pad_analog_change(psx_pad_t*, int, uint32_t, uint8_t);
|
||||
void psx_pad_attach_joy(psx_pad_t*, int, psx_input_t*);
|
||||
void psx_pad_detach_joy(psx_pad_t*, int);
|
||||
void psx_pad_attach_mcd(psx_pad_t*, int, const char*);
|
||||
|
||||
+10
-8
@@ -260,6 +260,8 @@ void spu_handle_adsr(psx_spu_t* spu, int v) {
|
||||
return;
|
||||
}
|
||||
|
||||
adsr_calculate_values(spu, v);
|
||||
|
||||
LEVEL += LEVEL_STEP;
|
||||
|
||||
switch (spu->data[v].adsr_phase) {
|
||||
@@ -319,8 +321,8 @@ void spu_kon(psx_spu_t* spu, uint32_t value) {
|
||||
spu->data[i].playing = 1;
|
||||
spu->data[i].current_addr = spu->voice[i].adsaddr << 3;
|
||||
spu->data[i].repeat_addr = spu->data[i].current_addr;
|
||||
spu->data[i].lvol = (float)(spu->voice[i].volumel << 1) / (float)0x7fff;
|
||||
spu->data[i].rvol = (float)(spu->voice[i].volumer << 1) / (float)0x7fff;
|
||||
spu->data[i].lvol = ((float)(spu->voice[i].volumel) / 32767.0f) * 2.0f;
|
||||
spu->data[i].rvol = ((float)(spu->voice[i].volumer) / 32767.0f) * 2.0f;
|
||||
spu->data[i].adsr_sustain_level = ((spu->voice[i].envctl1 & 0xf) + 1) * 0x800;
|
||||
spu->data[i].envctl = (((uint32_t)spu->voice[i].envctl2) << 16) |
|
||||
(uint32_t)spu->voice[i].envctl1;
|
||||
@@ -335,7 +337,7 @@ void spu_kon(psx_spu_t* spu, uint32_t value) {
|
||||
|
||||
void spu_koff(psx_spu_t* spu, uint32_t value) {
|
||||
for (int i = 0; i < VOICE_COUNT; i++)
|
||||
if ((value & (1 << i)))
|
||||
if (value & (1 << i))
|
||||
adsr_load_release(spu, i);
|
||||
}
|
||||
|
||||
@@ -353,6 +355,9 @@ int spu_handle_write(psx_spu_t* spu, uint32_t offset, uint32_t value) {
|
||||
case SPUR_KOFFL: case SPUR_KOFFH: {
|
||||
int high = (offset & 2) != 0;
|
||||
|
||||
if (!value)
|
||||
return 1;
|
||||
|
||||
spu_koff(spu, value << (16 * high));
|
||||
} return 1;
|
||||
|
||||
@@ -423,7 +428,7 @@ void psx_spu_write16(psx_spu_t* spu, uint32_t offset, uint16_t value) {
|
||||
}
|
||||
|
||||
void psx_spu_write8(psx_spu_t* spu, uint32_t offset, uint8_t value) {
|
||||
log_fatal("Unhandled 8-bit SPU write at offset %08x (%02x)", offset, value);
|
||||
printf("Unhandled 8-bit SPU write at offset %08x (%02x)\n", offset, value);
|
||||
}
|
||||
|
||||
void psx_spu_destroy(psx_spu_t* spu) {
|
||||
@@ -572,14 +577,11 @@ uint32_t psx_spu_get_sample(psx_spu_t* spu) {
|
||||
case 3: {
|
||||
spu->endx |= (1 << v);
|
||||
spu->data[v].current_addr = spu->data[v].repeat_addr;
|
||||
|
||||
adsr_load_release(spu, v);
|
||||
} break;
|
||||
}
|
||||
|
||||
if (spu->data[v].block_flags & 4) {
|
||||
if (spu->data[v].block_flags & 4)
|
||||
spu->data[v].repeat_addr = spu->data[v].current_addr;
|
||||
}
|
||||
|
||||
spu_read_block(spu, v);
|
||||
}
|
||||
|
||||
+72
-7
@@ -19,9 +19,15 @@ void psxi_sda_init(psxi_sda_t* sda, uint16_t model) {
|
||||
|
||||
sda->tx_data = 0xff;
|
||||
sda->tx_data_ready = 1;
|
||||
sda->prev_model = model;
|
||||
sda->model = model;
|
||||
sda->state = SDA_STATE_TX_HIZ;
|
||||
sda->sw = 0xffff;
|
||||
sda->sa_mode = 0;
|
||||
sda->adc0 = 0x80;
|
||||
sda->adc1 = 0x80;
|
||||
sda->adc2 = 0x80;
|
||||
sda->adc3 = 0x80;
|
||||
}
|
||||
|
||||
uint32_t psxi_sda_read(void* udata) {
|
||||
@@ -33,15 +39,38 @@ uint32_t psxi_sda_read(void* udata) {
|
||||
case SDA_STATE_TX_IDH: sda->tx_data = 0x5a; break;
|
||||
case SDA_STATE_TX_SWL: sda->tx_data = sda->sw & 0xff; break;
|
||||
|
||||
// Last state
|
||||
// Digital pad stops sending data here
|
||||
case SDA_STATE_TX_SWH: {
|
||||
sda->tx_data_ready = 0;
|
||||
sda->state = 0;
|
||||
if (sda->sa_mode == SA_MODE_ANALOG) {
|
||||
sda->tx_data_ready = 1;
|
||||
sda->state = SDA_STATE_TX_ADC0;
|
||||
} else {
|
||||
sda->tx_data_ready = 0;
|
||||
sda->state = SDA_STATE_TX_HIZ;
|
||||
}
|
||||
|
||||
return sda->sw >> 8;
|
||||
} break;
|
||||
|
||||
case SDA_STATE_TX_ADC0: sda->tx_data = sda->adc0; break;
|
||||
case SDA_STATE_TX_ADC1: sda->tx_data = sda->adc1; break;
|
||||
case SDA_STATE_TX_ADC2: sda->tx_data = sda->adc2; break;
|
||||
|
||||
// Analog pad stops sending data here
|
||||
case SDA_STATE_TX_ADC3: {
|
||||
sda->tx_data_ready = 0;
|
||||
sda->state = SDA_STATE_TX_HIZ;
|
||||
|
||||
if (sda->model == 0xf3)
|
||||
sda->model = sda->prev_model;
|
||||
|
||||
return sda->adc3;
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
// printf(" sda read %u -> %02x\n", sda->state, sda->tx_data);
|
||||
|
||||
sda->tx_data_ready = 1;
|
||||
sda->state++;
|
||||
|
||||
@@ -49,27 +78,63 @@ uint32_t psxi_sda_read(void* udata) {
|
||||
}
|
||||
|
||||
void psxi_sda_write(void* udata, uint16_t data) {
|
||||
psxi_sda_t* sda = (psxi_sda_t*)udata;
|
||||
|
||||
// To-do: Handle TAP and MOT bytes here
|
||||
if (data == 0x01) {
|
||||
sda->tx_data = 0xff;
|
||||
sda->tx_data_ready = 1;
|
||||
sda->state = SDA_STATE_TX_HIZ;
|
||||
}
|
||||
|
||||
if (data == 0x43) {
|
||||
if (sda->sa_mode == SA_MODE_ANALOG) {
|
||||
sda->prev_model = sda->model;
|
||||
sda->model = 0xf3;
|
||||
} else {
|
||||
sda->tx_data = 0xff;
|
||||
sda->tx_data_ready = 0;
|
||||
sda->state = SDA_STATE_TX_HIZ;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void psxi_sda_on_button_press(void* udata, uint16_t data) {
|
||||
void psxi_sda_on_button_press(void* udata, uint32_t data) {
|
||||
psxi_sda_t* sda = (psxi_sda_t*)udata;
|
||||
|
||||
if (data == PSXI_SW_SDA_ANALOG) {
|
||||
sda->sa_mode ^= 1;
|
||||
|
||||
sda->prev_model = sda->model;
|
||||
sda->model = sda->sa_mode ? SDA_MODEL_ANALOG_STICK : sda->prev_model;
|
||||
|
||||
printf("sda: Switched to %s mode\n", sda->sa_mode ? "analog" : "digital");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sda->sw &= ~data;
|
||||
}
|
||||
|
||||
void psxi_sda_on_button_release(void* udata, uint16_t data) {
|
||||
void psxi_sda_on_button_release(void* udata, uint32_t data) {
|
||||
psxi_sda_t* sda = (psxi_sda_t*)udata;
|
||||
|
||||
sda->sw |= data;
|
||||
}
|
||||
|
||||
// To-do: Implement analog mode
|
||||
void psxi_sda_on_analog_change(void* udata, uint16_t data) {
|
||||
void psxi_sda_on_analog_change(void* udata, uint32_t axis, uint8_t data) {
|
||||
// Suppress warning until we implement analog mode
|
||||
// psxi_sda_t* sda = (psxi_sda_t*)udata;
|
||||
psxi_sda_t* sda = (psxi_sda_t*)udata;
|
||||
|
||||
switch (axis) {
|
||||
case PSXI_AX_SDA_RIGHT_HORZ: sda->adc0 = data; break;
|
||||
case PSXI_AX_SDA_RIGHT_VERT: sda->adc1 = data; break;
|
||||
case PSXI_AX_SDA_LEFT_HORZ: sda->adc2 = data; break;
|
||||
case PSXI_AX_SDA_LEFT_VERT: sda->adc3 = data; break;
|
||||
}
|
||||
}
|
||||
|
||||
int psxi_sda_query_fifo(void* udata) {
|
||||
|
||||
+31
-17
@@ -14,29 +14,38 @@
|
||||
#define SDA_MODEL_ANALOG_PAD 0x73
|
||||
#define SDA_MODEL_ANALOG_STICK 0x53
|
||||
|
||||
#define PSXI_SW_SDA_SELECT 0x0001
|
||||
#define PSXI_SW_SDA_L3 0x0002
|
||||
#define PSXI_SW_SDA_R3 0x0004
|
||||
#define PSXI_SW_SDA_START 0x0008
|
||||
#define PSXI_SW_SDA_PAD_UP 0x0010
|
||||
#define PSXI_SW_SDA_PAD_RIGHT 0x0020
|
||||
#define PSXI_SW_SDA_PAD_DOWN 0x0040
|
||||
#define PSXI_SW_SDA_PAD_LEFT 0x0080
|
||||
#define PSXI_SW_SDA_L2 0x0100
|
||||
#define PSXI_SW_SDA_R2 0x0200
|
||||
#define PSXI_SW_SDA_L1 0x0400
|
||||
#define PSXI_SW_SDA_R1 0x0800
|
||||
#define PSXI_SW_SDA_TRIANGLE 0x1000
|
||||
#define PSXI_SW_SDA_CIRCLE 0x2000
|
||||
#define PSXI_SW_SDA_CROSS 0x4000
|
||||
#define PSXI_SW_SDA_SQUARE 0x8000
|
||||
#define PSXI_SW_SDA_SELECT 0x00000001
|
||||
#define PSXI_SW_SDA_L3 0x00000002
|
||||
#define PSXI_SW_SDA_R3 0x00000004
|
||||
#define PSXI_SW_SDA_START 0x00000008
|
||||
#define PSXI_SW_SDA_PAD_UP 0x00000010
|
||||
#define PSXI_SW_SDA_PAD_RIGHT 0x00000020
|
||||
#define PSXI_SW_SDA_PAD_DOWN 0x00000040
|
||||
#define PSXI_SW_SDA_PAD_LEFT 0x00000080
|
||||
#define PSXI_SW_SDA_L2 0x00000100
|
||||
#define PSXI_SW_SDA_R2 0x00000200
|
||||
#define PSXI_SW_SDA_L1 0x00000400
|
||||
#define PSXI_SW_SDA_R1 0x00000800
|
||||
#define PSXI_SW_SDA_TRIANGLE 0x00001000
|
||||
#define PSXI_SW_SDA_CIRCLE 0x00002000
|
||||
#define PSXI_SW_SDA_CROSS 0x00004000
|
||||
#define PSXI_SW_SDA_SQUARE 0x00008000
|
||||
#define PSXI_SW_SDA_ANALOG 0x00010000
|
||||
#define PSXI_AX_SDA_RIGHT_HORZ 0x00020000
|
||||
#define PSXI_AX_SDA_RIGHT_VERT 0x00030000
|
||||
#define PSXI_AX_SDA_LEFT_HORZ 0x00040000
|
||||
#define PSXI_AX_SDA_LEFT_VERT 0x00050000
|
||||
|
||||
enum {
|
||||
SDA_STATE_TX_HIZ = 0,
|
||||
SDA_STATE_TX_IDL,
|
||||
SDA_STATE_TX_IDH,
|
||||
SDA_STATE_TX_SWL,
|
||||
SDA_STATE_TX_SWH
|
||||
SDA_STATE_TX_SWH,
|
||||
SDA_STATE_TX_ADC0,
|
||||
SDA_STATE_TX_ADC1,
|
||||
SDA_STATE_TX_ADC2,
|
||||
SDA_STATE_TX_ADC3
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -45,12 +54,17 @@ enum {
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t prev_model;
|
||||
uint8_t model;
|
||||
int state;
|
||||
int sa_mode;
|
||||
uint16_t sw;
|
||||
uint8_t tx_data;
|
||||
int tx_data_ready;
|
||||
uint8_t adc0;
|
||||
uint8_t adc1;
|
||||
uint8_t adc2;
|
||||
uint8_t adc3;
|
||||
} psxi_sda_t;
|
||||
|
||||
psxi_sda_t* psxi_sda_create();
|
||||
|
||||
Reference in New Issue
Block a user