mirror of
https://github.com/ARMSX2/ARMSX1.git
synced 2026-08-24 16:53:35 -07:00
Many fixes
Fixed multiple GPU bugs: poly seam, wrong rect colors, transparent overlap Implemented Namco GunCon support Implemented support from 4MB/8MB RAM
This commit is contained in:
@@ -39,6 +39,7 @@ Time Gal & Ninja Hayate (Japan) (En,Ja) (Disc 2) (Ninja Hayate) *9
|
||||
Tokimeki Memorial 2 (Japan) *1
|
||||
Tomb Raider (USA) *8
|
||||
Tony Hawk's Pro Skater (USA) *10
|
||||
Vib-Ribbon (Japan) *8
|
||||
WipeOut (USA) *7
|
||||
Yu-Gi-Oh! Forbidden Memories (USA) *1
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "../psx/psx.h"
|
||||
#include "../psx/input/sda.h"
|
||||
#include "../psx/input/guncon.h"
|
||||
#include "../psx/disc/cue.h"
|
||||
|
||||
#include "screen.h"
|
||||
@@ -75,6 +76,9 @@ int main(int argc, const char* argv[]) {
|
||||
psx_input_t* input = psx_input_create();
|
||||
psx_input_init(input);
|
||||
|
||||
// psxi_guncon_t* controller = psxi_guncon_create();
|
||||
// psxi_guncon_init(controller);
|
||||
// psxi_guncon_init_input(controller, input);
|
||||
psxi_sda_t* controller = psxi_sda_create();
|
||||
psxi_sda_init(controller, SDA_MODEL_DIGITAL);
|
||||
psxi_sda_init_input(controller, input);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "screen.h"
|
||||
|
||||
#include "input/sda.h"
|
||||
#include "input/guncon.h"
|
||||
|
||||
uint32_t screen_get_button(SDL_Keycode k) {
|
||||
if (k == SDLK_x ) return PSXI_SW_SDA_CROSS;
|
||||
@@ -356,6 +357,46 @@ void psxe_screen_update(psxe_screen_t* screen) {
|
||||
}
|
||||
} break;
|
||||
|
||||
// To-do: GunCon
|
||||
// case SDL_MOUSEMOTION: {
|
||||
// psx_pad_analog_change(screen->pad, 0, PSXI_AX_GUNCON_SX, psx_get_dmode_width(screen->psx));
|
||||
// psx_pad_analog_change(screen->pad, 0, PSXI_AX_GUNCON_SY, psx_get_dmode_height(screen->psx));
|
||||
// psx_pad_analog_change(screen->pad, 0, PSXI_AX_GUNCON_X, event.motion.x * (1.0f / (float)screen->scale));
|
||||
// psx_pad_analog_change(screen->pad, 0, PSXI_AX_GUNCON_Y, event.motion.y * (1.0f / (float)screen->scale));
|
||||
// } break;
|
||||
|
||||
// case SDL_MOUSEBUTTONDOWN: {
|
||||
// switch (event.button.button) {
|
||||
// case SDL_BUTTON_LEFT: {
|
||||
// psx_pad_button_press(screen->pad, 0, PSXI_SW_GUNCON_A);
|
||||
// } break;
|
||||
|
||||
// case SDL_BUTTON_RIGHT: {
|
||||
// psx_pad_button_press(screen->pad, 0, PSXI_SW_GUNCON_B);
|
||||
// } break;
|
||||
|
||||
// case SDL_BUTTON_MIDDLE: {
|
||||
// psx_pad_button_press(screen->pad, 0, PSXI_SW_GUNCON_TRIGGER);
|
||||
// } break;
|
||||
// }
|
||||
// } break;
|
||||
|
||||
// case SDL_MOUSEBUTTONUP: {
|
||||
// switch (event.button.button) {
|
||||
// case SDL_BUTTON_LEFT: {
|
||||
// psx_pad_button_release(screen->pad, 0, PSXI_SW_GUNCON_A);
|
||||
// } break;
|
||||
|
||||
// case SDL_BUTTON_RIGHT: {
|
||||
// psx_pad_button_release(screen->pad, 0, PSXI_SW_GUNCON_B);
|
||||
// } break;
|
||||
|
||||
// case SDL_BUTTON_MIDDLE: {
|
||||
// psx_pad_button_release(screen->pad, 0, PSXI_SW_GUNCON_TRIGGER);
|
||||
// } break;
|
||||
// }
|
||||
// } break;
|
||||
|
||||
case SDL_TEXTINPUT: {
|
||||
psx_exp2_atcons_put(screen->psx->exp2, event.text.text[0]);
|
||||
} break;
|
||||
|
||||
@@ -104,6 +104,12 @@ uint16_t psx_bus_read16(psx_bus_t* bus, uint32_t addr) {
|
||||
if (addr == 0x1f801054)
|
||||
return 0x05;
|
||||
|
||||
if (addr == 0x1f400004)
|
||||
return 0xc0;
|
||||
|
||||
if (addr == 0x1f400006)
|
||||
return 0x1fe0;
|
||||
|
||||
printf("Unhandled 16-bit read from %08x:%08x\n", vaddr, addr);
|
||||
|
||||
// exit(1);
|
||||
|
||||
+21
-11
@@ -73,23 +73,24 @@ void cdrom_fetch_video_sector(psx_cdrom_t* cdrom) {
|
||||
|
||||
msf_add_f(&cdrom->seek_msf, 1);
|
||||
|
||||
return;
|
||||
// Check RT and Video/Data bit
|
||||
// if (cdrom->dfifo[0x12] & 4)
|
||||
// continue;
|
||||
|
||||
// If we get here it means this is a real-time video sector.
|
||||
// If the XA filter is disabled, we're done
|
||||
if (!(cdrom->mode & MODE_XA_FILTER))
|
||||
return;
|
||||
// if (!(cdrom->mode & MODE_XA_FILTER))
|
||||
// return;
|
||||
|
||||
// Else check XA file/channel
|
||||
int file_eq = cdrom->dfifo[0x10] == cdrom->xa_file;
|
||||
int channel_eq = cdrom->dfifo[0x11] == cdrom->xa_channel;
|
||||
// // Else check XA file/channel
|
||||
// int file_eq = cdrom->dfifo[0x10] == cdrom->xa_file;
|
||||
// int channel_eq = cdrom->dfifo[0x11] == cdrom->xa_channel;
|
||||
|
||||
// If they are equal to our filter values, we're done
|
||||
// else keep searching
|
||||
if (file_eq && channel_eq)
|
||||
return;
|
||||
// // If they are equal to our filter values, we're done
|
||||
// // else keep searching
|
||||
// if (file_eq && channel_eq)
|
||||
// return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -921,7 +922,7 @@ void cdrom_cmd_getlocp(psx_cdrom_t* cdrom) {
|
||||
} break;
|
||||
|
||||
case CD_STATE_SEND_RESP1: {
|
||||
msf_t absolute = cdrom->xa_playing ? cdrom->xa_msf : cdrom->seek_msf;
|
||||
msf_t absolute = cdrom->seek_msf;
|
||||
msf_t relative = absolute;
|
||||
msf_t track_msf = cdrom_get_track_addr(cdrom, absolute);
|
||||
|
||||
@@ -963,7 +964,7 @@ void cdrom_cmd_getlocp(psx_cdrom_t* cdrom) {
|
||||
RESP_PUSH(relative.s);
|
||||
RESP_PUSH(relative.m);
|
||||
RESP_PUSH(0x01);
|
||||
RESP_PUSH(0x01);
|
||||
RESP_PUSH(0x15);
|
||||
|
||||
if (cdrom->ongoing_read_command) {
|
||||
printf("getlocp command=%02x\n", cdrom->ongoing_read_command);
|
||||
@@ -1804,6 +1805,15 @@ void psx_cdrom_init(psx_cdrom_t* cdrom, psx_ic_t* ic) {
|
||||
memset(cdrom->xa_right_resample_buf, 0, (XA_STEREO_RESAMPLE_SIZE * 2) * sizeof(int16_t));
|
||||
memset(cdrom->xa_mono_resample_buf, 0, (XA_MONO_RESAMPLE_SIZE * 2) * sizeof(int16_t));
|
||||
|
||||
cdrom->vol[0] = 0x80;
|
||||
cdrom->vol[1] = 0x00;
|
||||
cdrom->vol[2] = 0x80;
|
||||
cdrom->vol[3] = 0x00;
|
||||
cdrom->vapp[0] = 0x80;
|
||||
cdrom->vapp[1] = 0x00;
|
||||
cdrom->vapp[2] = 0x80;
|
||||
cdrom->vapp[3] = 0x00;
|
||||
|
||||
cdrom->seek_msf.m = 0;
|
||||
cdrom->seek_msf.s = 2;
|
||||
cdrom->seek_msf.f = 0;
|
||||
|
||||
+69
-43
@@ -6,6 +6,8 @@
|
||||
#include "gpu.h"
|
||||
#include "../log.h"
|
||||
|
||||
#define SE10(v) ((int16_t)((v) << 5) >> 5)
|
||||
|
||||
int g_psx_gpu_dither_kernel[] = {
|
||||
-4, +0, -3, +1,
|
||||
+2, -2, +3, -1,
|
||||
@@ -176,6 +178,9 @@ uint16_t gpu_fetch_texel(psx_gpu_t* gpu, uint16_t tx, uint16_t ty, uint32_t tpx,
|
||||
}
|
||||
}
|
||||
|
||||
#define TL(z, a, b) \
|
||||
((z < 0) || ((z == 0) && ((b.y > a.y) || ((b.y == a.y) && (b.x < a.x)))))
|
||||
|
||||
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;
|
||||
|
||||
@@ -216,7 +221,7 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
int xmax = max3(a.x, b.x, c.x);
|
||||
int ymax = max3(a.y, b.y, c.y);
|
||||
|
||||
if (((xmax - xmin) > 2048) || ((ymax - ymin) > 1024))
|
||||
if (((xmax - xmin) > 2048) || ((ymax - ymin) > 1024))
|
||||
return;
|
||||
|
||||
float area = EDGE(a, b, c);
|
||||
@@ -233,24 +238,27 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
p.y = y;
|
||||
|
||||
float z0 = EDGE(b, c, p);
|
||||
|
||||
if (TL(z0, b, c))
|
||||
continue;
|
||||
|
||||
float z1 = EDGE(c, a, p);
|
||||
|
||||
if (TL(z1, c, a))
|
||||
continue;
|
||||
|
||||
float z2 = EDGE(a, b, p);
|
||||
|
||||
int e = ((z0 < 0) || (z1 < 0) || (z2 < 0));
|
||||
|
||||
if (transp && edge)
|
||||
e = ((z0 < 0) || (z1 <= 0) || (z2 < 0));
|
||||
|
||||
if (e)
|
||||
if (TL(z2, a, b))
|
||||
continue;
|
||||
|
||||
uint16_t color = 0;
|
||||
uint32_t mod = 0;
|
||||
|
||||
if (data.attrib & PA_SHADED) {
|
||||
int cr = (z0 * ((a.c >> 0) & 0xff) + z1 * ((b.c >> 0) & 0xff) + z2 * ((c.c >> 0) & 0xff)) / area;
|
||||
int cg = (z0 * ((a.c >> 8) & 0xff) + z1 * ((b.c >> 8) & 0xff) + z2 * ((c.c >> 8) & 0xff)) / area;
|
||||
int cb = (z0 * ((a.c >> 16) & 0xff) + z1 * ((b.c >> 16) & 0xff) + z2 * ((c.c >> 16) & 0xff)) / area;
|
||||
float cr = (z0 * ((a.c >> 0) & 0xff) + z1 * ((b.c >> 0) & 0xff) + z2 * ((c.c >> 0) & 0xff)) / area;
|
||||
float cg = (z0 * ((a.c >> 8) & 0xff) + z1 * ((b.c >> 8) & 0xff) + z2 * ((c.c >> 8) & 0xff)) / area;
|
||||
float cb = (z0 * ((a.c >> 16) & 0xff) + z1 * ((b.c >> 16) & 0xff) + z2 * ((c.c >> 16) & 0xff)) / area;
|
||||
|
||||
int dy = (y - ymin) & 3;
|
||||
int dx = (x - xmin) & 3;
|
||||
@@ -262,11 +270,15 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
cb += dither;
|
||||
|
||||
// Saturate (clamp) to 00-ff
|
||||
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 = (cb << 16) | (cg << 8) | cr;
|
||||
unsigned int ucr = roundf(cr);
|
||||
unsigned int ucg = roundf(cg);
|
||||
unsigned int ucb = roundf(cb);
|
||||
|
||||
uint32_t rgb = (ucb << 16) | (ucg << 8) | ucr;
|
||||
|
||||
mod = rgb;
|
||||
} else {
|
||||
@@ -274,15 +286,15 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
}
|
||||
|
||||
if (data.attrib & PA_TEXTURED) {
|
||||
uint32_t tx = ((z0 * a.tx) + (z1 * b.tx) + (z2 * c.tx)) / area;
|
||||
uint32_t ty = ((z0 * a.ty) + (z1 * b.ty) + (z2 * c.ty)) / area;
|
||||
uint32_t tx = roundf(((z0 * a.tx) + (z1 * b.tx) + (z2 * c.tx)) / area);
|
||||
uint32_t ty = roundf(((z0 * a.ty) + (z1 * b.ty) + (z2 * c.ty)) / area);
|
||||
|
||||
uint16_t texel = gpu_fetch_texel(gpu, tx, ty, tpx, tpy, clutx, cluty, depth);
|
||||
|
||||
if (!texel)
|
||||
continue;
|
||||
|
||||
if (transp)
|
||||
if ((data.attrib & PA_TRANSP) != 0)
|
||||
transp = (texel & 0x8000) != 0;
|
||||
|
||||
if (data.attrib & PA_RAW) {
|
||||
@@ -304,9 +316,9 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
cg = (cg >= 255.0f) ? 255.0f : ((cg <= 0.0f) ? 0.0f : cg);
|
||||
cb = (cb >= 255.0f) ? 255.0f : ((cb <= 0.0f) ? 0.0f : cb);
|
||||
|
||||
unsigned int ucr = cr;
|
||||
unsigned int ucg = cg;
|
||||
unsigned int ucb = cb;
|
||||
unsigned int ucr = roundf(cr);
|
||||
unsigned int ucg = roundf(cg);
|
||||
unsigned int ucb = roundf(cb);
|
||||
|
||||
uint32_t rgb = ucr | (ucg << 8) | (ucb << 16);
|
||||
|
||||
@@ -355,9 +367,9 @@ void gpu_render_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2,
|
||||
cg = (cg >= 255.0f) ? 255.0f : ((cg <= 0.0f) ? 0.0f : cg);
|
||||
cb = (cb >= 255.0f) ? 255.0f : ((cb <= 0.0f) ? 0.0f : cb);
|
||||
|
||||
unsigned int ucr = cr;
|
||||
unsigned int ucg = cg;
|
||||
unsigned int ucb = cb;
|
||||
unsigned int ucr = roundf(cr);
|
||||
unsigned int ucg = roundf(cg);
|
||||
unsigned int ucb = roundf(cb);
|
||||
|
||||
uint32_t rgb = ucr | (ucg << 8) | (ucb << 16);
|
||||
|
||||
@@ -431,7 +443,7 @@ void gpu_render_rect(psx_gpu_t* gpu, rect_data_t data) {
|
||||
if (!texel)
|
||||
goto skip;
|
||||
|
||||
if (transp)
|
||||
if ((data.attrib & RA_TRANSP) != 0)
|
||||
transp = (texel & 0x8000) != 0;
|
||||
|
||||
float tr = ((texel >> 0 ) & 0x1f) << 3;
|
||||
@@ -446,9 +458,13 @@ void gpu_render_rect(psx_gpu_t* gpu, rect_data_t data) {
|
||||
float cg = (tg * mg) / 128.0f;
|
||||
float cb = (tb * mb) / 128.0f;
|
||||
|
||||
unsigned int ucr = cr;
|
||||
unsigned int ucg = cg;
|
||||
unsigned int ucb = 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);
|
||||
|
||||
unsigned int ucr = roundf(cr);
|
||||
unsigned int ucg = roundf(cg);
|
||||
unsigned int ucb = roundf(cb);
|
||||
|
||||
uint32_t rgb = ucr | (ucg << 8) | (ucb << 16);
|
||||
|
||||
@@ -495,9 +511,9 @@ void gpu_render_rect(psx_gpu_t* gpu, rect_data_t data) {
|
||||
cg = (cg >= 255.0f) ? 255.0f : ((cg <= 0.0f) ? 0.0f : cg);
|
||||
cb = (cb >= 255.0f) ? 255.0f : ((cb <= 0.0f) ? 0.0f : cb);
|
||||
|
||||
unsigned int ucr = cr;
|
||||
unsigned int ucg = cg;
|
||||
unsigned int ucb = cb;
|
||||
unsigned int ucr = roundf(cr);
|
||||
unsigned int ucg = roundf(cg);
|
||||
unsigned int ucb = roundf(cb);
|
||||
|
||||
uint32_t rgb = ucr | (ucg << 8) | (ucb << 16);
|
||||
|
||||
@@ -851,8 +867,8 @@ void gpu_rect(psx_gpu_t* gpu) {
|
||||
int size_offset = 2 + textured;
|
||||
|
||||
rect.v0.c = gpu->buf[0] & 0xffffff;
|
||||
rect.v0.x = gpu->buf[1] & 0xffff;
|
||||
rect.v0.y = gpu->buf[1] >> 16;
|
||||
rect.v0.x = SE10(gpu->buf[1] & 0xffff);
|
||||
rect.v0.y = SE10(gpu->buf[1] >> 16);
|
||||
rect.v0.tx = (gpu->buf[2] >> 0) & 0xff;
|
||||
rect.v0.ty = (gpu->buf[2] >> 8) & 0xff;
|
||||
rect.clut = gpu->buf[2] >> 16;
|
||||
@@ -903,18 +919,28 @@ void gpu_poly(psx_gpu_t* gpu) {
|
||||
poly.clut = gpu->buf[2] >> 16;
|
||||
poly.texp = gpu->buf[texp_offset] >> 16;
|
||||
|
||||
// Undocumented behavior?
|
||||
// Fixes Mortal Kombat II, Bubble Bobble, Driver 1 & 2
|
||||
if (textured) {
|
||||
gpu->texp_x = (poly.texp & 0xf) << 6;
|
||||
gpu->texp_y = (poly.texp & 0x10) << 4;
|
||||
gpu->texp_d = (poly.texp >> 7) & 0x3;
|
||||
gpu->gpustat &= 0xfffffe00;
|
||||
gpu->gpustat |= poly.texp & 0x1ff;
|
||||
}
|
||||
|
||||
poly.v[0].c = gpu->buf[0+0*color_offset] & 0xffffff;
|
||||
poly.v[1].c = gpu->buf[0+1*color_offset] & 0xffffff;
|
||||
poly.v[2].c = gpu->buf[0+2*color_offset] & 0xffffff;
|
||||
poly.v[3].c = gpu->buf[0+3*color_offset] & 0xffffff;
|
||||
poly.v[0].x = gpu->buf[1+0*vert_offset] & 0xffff;
|
||||
poly.v[1].x = gpu->buf[1+1*vert_offset] & 0xffff;
|
||||
poly.v[2].x = gpu->buf[1+2*vert_offset] & 0xffff;
|
||||
poly.v[3].x = gpu->buf[1+3*vert_offset] & 0xffff;
|
||||
poly.v[0].y = gpu->buf[1+0*vert_offset] >> 16;
|
||||
poly.v[1].y = gpu->buf[1+1*vert_offset] >> 16;
|
||||
poly.v[2].y = gpu->buf[1+2*vert_offset] >> 16;
|
||||
poly.v[3].y = gpu->buf[1+3*vert_offset] >> 16;
|
||||
poly.v[0].x = SE10(gpu->buf[1+0*vert_offset] & 0xffff);
|
||||
poly.v[1].x = SE10(gpu->buf[1+1*vert_offset] & 0xffff);
|
||||
poly.v[2].x = SE10(gpu->buf[1+2*vert_offset] & 0xffff);
|
||||
poly.v[3].x = SE10(gpu->buf[1+3*vert_offset] & 0xffff);
|
||||
poly.v[0].y = SE10(gpu->buf[1+0*vert_offset] >> 16);
|
||||
poly.v[1].y = SE10(gpu->buf[1+1*vert_offset] >> 16);
|
||||
poly.v[2].y = SE10(gpu->buf[1+2*vert_offset] >> 16);
|
||||
poly.v[3].y = SE10(gpu->buf[1+3*vert_offset] >> 16);
|
||||
poly.v[0].tx = gpu->buf[2+0*texc_offset] & 0xff;
|
||||
poly.v[1].tx = gpu->buf[2+1*texc_offset] & 0xff;
|
||||
poly.v[2].tx = gpu->buf[2+2*texc_offset] & 0xff;
|
||||
@@ -925,7 +951,7 @@ 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, 0);
|
||||
gpu_render_triangle(gpu, poly.v[0], poly.v[1], poly.v[2], poly, 1);
|
||||
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, 0);
|
||||
@@ -1647,8 +1673,8 @@ void psx_gpu_update_cmd(psx_gpu_t* gpu) {
|
||||
gpu->draw_y2 = (gpu->buf[0] >> 10) & 0x1ff;
|
||||
} break;
|
||||
case 0xe5: {
|
||||
gpu->off_x = ((int32_t)((gpu->buf[0] >> 0 ) & 0x7ff) << 21) >> 21;
|
||||
gpu->off_y = ((int32_t)((gpu->buf[0] >> 11) & 0x7ff) << 21) >> 21;
|
||||
gpu->off_x = ((int32_t)(((gpu->buf[0] >> 0 ) & 0x7ff) << 21)) >> 21;
|
||||
gpu->off_y = ((int32_t)(((gpu->buf[0] >> 11) & 0x7ff) << 21)) >> 21;
|
||||
} break;
|
||||
case 0xe6: {
|
||||
/* To-do: Implement mask bit thing */
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ 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*, 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 void (*psx_input_on_analog_change_t)(void*, uint32_t, uint16_t);
|
||||
typedef int (*psx_input_query_fifo_t)(void*);
|
||||
|
||||
struct psx_input_t {
|
||||
|
||||
+1
-1
@@ -262,7 +262,7 @@ void psx_pad_button_release(psx_pad_t* pad, int slot, uint32_t data) {
|
||||
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) {
|
||||
void psx_pad_analog_change(psx_pad_t* pad, int slot, uint32_t stick, uint16_t data) {
|
||||
psx_input_t* selected_slot = pad->joy_slot[slot];
|
||||
|
||||
if (selected_slot)
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ 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, 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_analog_change(psx_pad_t*, int, uint32_t, uint16_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*);
|
||||
|
||||
+12
-9
@@ -9,50 +9,53 @@ psx_ram_t* psx_ram_create(void) {
|
||||
return (psx_ram_t*)malloc(sizeof(psx_ram_t));
|
||||
}
|
||||
|
||||
void psx_ram_init(psx_ram_t* ram, psx_mc2_t* mc2) {
|
||||
void psx_ram_init(psx_ram_t* ram, psx_mc2_t* mc2, int size) {
|
||||
memset(ram, 0, sizeof(psx_ram_t));
|
||||
|
||||
ram->io_base = PSX_RAM_BEGIN;
|
||||
ram->io_size = PSX_RAM_SIZE;
|
||||
|
||||
ram->mc2 = mc2;
|
||||
ram->buf = (uint8_t*)malloc(PSX_RAM_SIZE);
|
||||
ram->buf = (uint8_t*)malloc(RAM_SIZE);
|
||||
|
||||
memset(ram->buf, 0xee, PSX_RAM_SIZE);
|
||||
if (size & 0x1ffff)
|
||||
size = RAM_SIZE_2MB;
|
||||
|
||||
memset(ram->buf, RAM_INIT_FILL, size);
|
||||
}
|
||||
|
||||
uint32_t psx_ram_read32(psx_ram_t* ram, uint32_t offset) {
|
||||
offset &= 0x1fffff;
|
||||
offset &= RAM_SIZE - 1;
|
||||
|
||||
return *((uint32_t*)(ram->buf + offset));
|
||||
}
|
||||
|
||||
uint16_t psx_ram_read16(psx_ram_t* ram, uint32_t offset) {
|
||||
offset &= 0x1fffff;
|
||||
offset &= RAM_SIZE - 1;
|
||||
|
||||
return *((uint16_t*)(ram->buf + offset));
|
||||
}
|
||||
|
||||
uint8_t psx_ram_read8(psx_ram_t* ram, uint32_t offset) {
|
||||
offset &= 0x1fffff;
|
||||
offset &= RAM_SIZE - 1;
|
||||
|
||||
return ram->buf[offset];
|
||||
}
|
||||
|
||||
void psx_ram_write32(psx_ram_t* ram, uint32_t offset, uint32_t value) {
|
||||
offset &= 0x1fffff;
|
||||
offset &= RAM_SIZE - 1;
|
||||
|
||||
*((uint32_t*)(ram->buf + offset)) = value;
|
||||
}
|
||||
|
||||
void psx_ram_write16(psx_ram_t* ram, uint32_t offset, uint16_t value) {
|
||||
offset &= 0x1fffff;
|
||||
offset &= RAM_SIZE - 1;
|
||||
|
||||
*((uint16_t*)(ram->buf + offset)) = value;
|
||||
}
|
||||
|
||||
void psx_ram_write8(psx_ram_t* ram, uint32_t offset, uint8_t value) {
|
||||
offset &= 0x1fffff;
|
||||
offset &= RAM_SIZE - 1;
|
||||
|
||||
ram->buf[offset] = value;
|
||||
}
|
||||
|
||||
+7
-2
@@ -6,11 +6,16 @@
|
||||
#include "../log.h"
|
||||
#include "mc2.h"
|
||||
|
||||
//#define PSX_RAM_SIZE 0x200000
|
||||
#define RAM_SIZE 0x200000
|
||||
#define PSX_RAM_SIZE 0x1f000000
|
||||
#define PSX_RAM_BEGIN 0x00000000
|
||||
//#define PSX_RAM_END 0x001fffff
|
||||
#define PSX_RAM_END 0x1effffff
|
||||
#define RAM_INIT_FILL 0
|
||||
|
||||
#define RAM_SIZE_2MB 0x200000
|
||||
#define RAM_SIZE_4MB 0x400000
|
||||
#define RAM_SIZE_8MB 0x800000
|
||||
|
||||
typedef struct {
|
||||
uint32_t bus_delay;
|
||||
@@ -22,7 +27,7 @@ typedef struct {
|
||||
} psx_ram_t;
|
||||
|
||||
psx_ram_t* psx_ram_create(void);
|
||||
void psx_ram_init(psx_ram_t*, psx_mc2_t*);
|
||||
void psx_ram_init(psx_ram_t*, psx_mc2_t*, int size);
|
||||
uint32_t psx_ram_read32(psx_ram_t*, uint32_t);
|
||||
uint16_t psx_ram_read16(psx_ram_t*, uint32_t);
|
||||
uint8_t psx_ram_read8(psx_ram_t*, uint32_t);
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
This file is part of the PSXE Emulator Project
|
||||
|
||||
Sony PlayStation Standard Digital/Analog Controller Emulator
|
||||
*/
|
||||
|
||||
#include "guncon.h"
|
||||
#include "../log.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
const char* states[] = {
|
||||
"HIZ",
|
||||
"IDL",
|
||||
"IDH",
|
||||
"SWL",
|
||||
"SWH",
|
||||
"XPL",
|
||||
"XPH",
|
||||
"YPL",
|
||||
"YPH"
|
||||
};
|
||||
|
||||
psxi_guncon_t* psxi_guncon_create(void) {
|
||||
return (psxi_guncon_t*)malloc(sizeof(psxi_guncon_t));
|
||||
}
|
||||
|
||||
void psxi_guncon_init(psxi_guncon_t* guncon) {
|
||||
memset(guncon, 0, sizeof(psxi_guncon_t));
|
||||
|
||||
guncon->tx_data = 0xff;
|
||||
guncon->tx_data_ready = 1;
|
||||
guncon->state = GUNCON_STATE_TX_HIZ;
|
||||
guncon->sw = 0xffff;
|
||||
guncon->x = 0x4d;
|
||||
guncon->y = 0x19;
|
||||
guncon->sx = 384;
|
||||
guncon->sy = 240;
|
||||
}
|
||||
|
||||
uint32_t psxi_guncon_read(void* udata) {
|
||||
psxi_guncon_t* guncon = (psxi_guncon_t*)udata;
|
||||
|
||||
switch (guncon->state) {
|
||||
case GUNCON_STATE_TX_HIZ: guncon->tx_data = 0xff; break;
|
||||
case GUNCON_STATE_TX_IDL: guncon->tx_data = GUNCON_IDL; break;
|
||||
case GUNCON_STATE_TX_IDH: guncon->tx_data = GUNCON_IDH; break;
|
||||
case GUNCON_STATE_TX_SWL: guncon->tx_data = guncon->sw & 0xff; break;
|
||||
case GUNCON_STATE_TX_SWH: guncon->tx_data = guncon->sw >> 8; break;
|
||||
case GUNCON_STATE_TX_XPL: guncon->tx_data = guncon->x & 0xff; break;
|
||||
case GUNCON_STATE_TX_XPH: guncon->tx_data = guncon->x >> 8; break;
|
||||
case GUNCON_STATE_TX_YPL: guncon->tx_data = guncon->y & 0xff; break;
|
||||
case GUNCON_STATE_TX_YPH: {
|
||||
// printf("guncon: read state %u (%s) -> %02x\n", guncon->state, states[guncon->state], guncon->y >> 8);
|
||||
|
||||
guncon->tx_data_ready = 0;
|
||||
guncon->state = GUNCON_STATE_TX_HIZ;
|
||||
|
||||
return guncon->y >> 8;
|
||||
} break;
|
||||
}
|
||||
|
||||
// printf("guncon: read state %u (%s) -> %02x\n", guncon->state, states[guncon->state], guncon->tx_data);
|
||||
|
||||
guncon->tx_data_ready = 1;
|
||||
guncon->state++;
|
||||
|
||||
return guncon->tx_data;
|
||||
}
|
||||
|
||||
void psxi_guncon_write(void* udata, uint16_t data) {
|
||||
psxi_guncon_t* guncon = (psxi_guncon_t*)udata;
|
||||
|
||||
// printf("guncon: write %02x\n", data);
|
||||
|
||||
(void)guncon;
|
||||
}
|
||||
|
||||
void psxi_guncon_on_button_press(void* udata, uint32_t data) {
|
||||
psxi_guncon_t* guncon = (psxi_guncon_t*)udata;
|
||||
|
||||
guncon->sw &= ~data;
|
||||
}
|
||||
|
||||
void psxi_guncon_on_button_release(void* udata, uint32_t data) {
|
||||
psxi_guncon_t* guncon = (psxi_guncon_t*)udata;
|
||||
|
||||
guncon->sw |= data;
|
||||
}
|
||||
|
||||
void psxi_guncon_on_analog_change(void* udata, uint32_t axis, uint16_t data) {
|
||||
psxi_guncon_t* guncon = (psxi_guncon_t*)udata;
|
||||
|
||||
switch (axis) {
|
||||
case PSXI_AX_GUNCON_X: {
|
||||
data *= (461.0f - 77.0f) / (float)guncon->sx;
|
||||
data += 77;
|
||||
|
||||
guncon->x = data;
|
||||
} break;
|
||||
|
||||
case PSXI_AX_GUNCON_Y: {
|
||||
data *= (248.0f - 25.0f) / (float)guncon->sy;
|
||||
data += 25;
|
||||
|
||||
guncon->y = data;
|
||||
} break;
|
||||
|
||||
case PSXI_AX_GUNCON_SX: {
|
||||
guncon->sx = data;
|
||||
} break;
|
||||
|
||||
case PSXI_AX_GUNCON_SY: {
|
||||
guncon->sy = data;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
int psxi_guncon_query_fifo(void* udata) {
|
||||
psxi_guncon_t* guncon = (psxi_guncon_t*)udata;
|
||||
|
||||
return guncon->tx_data_ready;
|
||||
}
|
||||
|
||||
void psxi_guncon_init_input(psxi_guncon_t* guncon, psx_input_t* input) {
|
||||
input->udata = guncon;
|
||||
input->write_func = psxi_guncon_write;
|
||||
input->read_func = psxi_guncon_read;
|
||||
input->on_button_press_func = psxi_guncon_on_button_press;
|
||||
input->on_button_release_func = psxi_guncon_on_button_release;
|
||||
input->on_analog_change_func = psxi_guncon_on_analog_change;
|
||||
input->query_fifo_func = psxi_guncon_query_fifo;
|
||||
}
|
||||
|
||||
void psxi_guncon_destroy(psxi_guncon_t* guncon) {
|
||||
free(guncon);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
This file is part of the PSXE Emulator Project
|
||||
|
||||
Namco GunCon emulation
|
||||
*/
|
||||
|
||||
#ifndef GUNCON_H
|
||||
#define GUNCON_H
|
||||
|
||||
#include "../dev/input.h"
|
||||
|
||||
/*
|
||||
__Halfword 0 (Controller Info)___________________
|
||||
0-15 Controller Info (5A63h=Namco Lightgun; GunCon/Cinch Type)
|
||||
__Halfword 1 (Buttons)___________________________
|
||||
0-2 Not used (All bits always 1)
|
||||
3 Button A (Left Side) (0=Pressed, 1=Released) ;aka Joypad Start
|
||||
4-12 Not used (All bits always 1)
|
||||
13 Trigger Button (0=Pressed, 1=Released) ;aka Joypad O-Button
|
||||
14 Button B (Right Side) (0=Pressed, 1=Released) ;aka Joypad X-Button
|
||||
15 Not used (All bits always 1)
|
||||
__Halfword 2 (X)_________________________________
|
||||
0-15 8MHz clks since HSYNC (01h=Error, or 04Dh..1CDh)
|
||||
__Halfword 3 (Y)_________________________________
|
||||
0-15 Scanlines since VSYNC (05h/0Ah=Error, PAL=20h..127h, NTSC=19h..F8h)
|
||||
*/
|
||||
|
||||
#define GUNCON_IDL 0x63
|
||||
#define GUNCON_IDH 0x5a
|
||||
|
||||
#define PSXI_SW_GUNCON_A 0x00000008
|
||||
#define PSXI_SW_GUNCON_TRIGGER 0x00002000
|
||||
#define PSXI_SW_GUNCON_B 0x00004000
|
||||
#define PSXI_AX_GUNCON_X 0x00010000
|
||||
#define PSXI_AX_GUNCON_Y 0x00020000
|
||||
#define PSXI_AX_GUNCON_SX 0x00030000
|
||||
#define PSXI_AX_GUNCON_SY 0x00040000
|
||||
|
||||
enum {
|
||||
GUNCON_STATE_TX_HIZ = 0,
|
||||
GUNCON_STATE_TX_IDL,
|
||||
GUNCON_STATE_TX_IDH,
|
||||
GUNCON_STATE_TX_SWL,
|
||||
GUNCON_STATE_TX_SWH,
|
||||
GUNCON_STATE_TX_XPL,
|
||||
GUNCON_STATE_TX_XPH,
|
||||
GUNCON_STATE_TX_YPL,
|
||||
GUNCON_STATE_TX_YPH
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int state;
|
||||
uint16_t sw;
|
||||
uint8_t tx_data;
|
||||
int tx_data_ready;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint16_t sx;
|
||||
uint16_t sy;
|
||||
} psxi_guncon_t;
|
||||
|
||||
psxi_guncon_t* psxi_guncon_create(void);
|
||||
void psxi_guncon_init(psxi_guncon_t*);
|
||||
void psxi_guncon_init_input(psxi_guncon_t*, psx_input_t*);
|
||||
void psxi_guncon_destroy(psxi_guncon_t*);
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -122,7 +122,7 @@ void psxi_sda_on_button_release(void* udata, uint32_t data) {
|
||||
}
|
||||
|
||||
// To-do: Implement analog mode
|
||||
void psxi_sda_on_analog_change(void* udata, uint32_t axis, uint8_t data) {
|
||||
void psxi_sda_on_analog_change(void* udata, uint32_t axis, uint16_t data) {
|
||||
// Suppress warning until we implement analog mode
|
||||
psxi_sda_t* sda = (psxi_sda_t*)udata;
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ void psx_init(psx_t* psx, const char* bios_path, const char* exp_path) {
|
||||
psx_mc1_init(psx->mc1);
|
||||
psx_mc2_init(psx->mc2);
|
||||
psx_mc3_init(psx->mc3);
|
||||
psx_ram_init(psx->ram, psx->mc2);
|
||||
psx_ram_init(psx->ram, psx->mc2, RAM_SIZE_2MB);
|
||||
psx_dma_init(psx->dma, psx->bus, psx->ic);
|
||||
psx_exp1_init(psx->exp1, psx->mc1, exp_path);
|
||||
psx_exp2_init(psx->exp2, atcons_tx, NULL);
|
||||
|
||||
Reference in New Issue
Block a user