diff --git a/.gitignore b/.gitignore index 814466f..b222e70 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,5 @@ snap/ *.zip *.cue *.iso -*.mcd \ No newline at end of file +*.mcd +*.rom diff --git a/frontend/config.c b/frontend/config.c index dbbba4b..4b92243 100644 --- a/frontend/config.c +++ b/frontend/config.c @@ -77,7 +77,7 @@ void psxe_cfg_destroy(psxe_config_t* cfg) { } void psxe_cfg_load_defaults(psxe_config_t* cfg) { - cfg->bios = NULL; + cfg->bios = "bios.bin"; cfg->bios_search = "bios"; cfg->exe = NULL; cfg->help_model = 0; @@ -91,6 +91,7 @@ void psxe_cfg_load_defaults(psxe_config_t* cfg) { cfg->log_level = LOG_FATAL; cfg->quiet = 0; cfg->cd_path = NULL; + cfg->exp_path = NULL; } void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) { @@ -111,6 +112,7 @@ void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) { const char* region = NULL; const char* psxe_version = NULL; const char* cd_path = NULL; + const char* exp_path = NULL; static const char *const usages[] = { "psxe [options] path-to-cdrom", @@ -124,15 +126,16 @@ void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) { OPT_BOOLEAN ('v', "version" , &version , "Display version and build information", NULL, 0, 0), OPT_GROUP("Basic options"), OPT_BOOLEAN ('a', "use-args" , &use_args , "Ignore settings file, use CLI args instead", NULL, 0, 0), - OPT_STRING ('b', "bios" , &bios , "Use this BIOS file (ignores -B, -M)", NULL, 0, 0), + OPT_STRING ('b', "bios" , &bios , "Specify a BIOS file (ignores -B, -M)", NULL, 0, 0), OPT_BOOLEAN ('B', "bios-folder" , &bios_search , "Specify a BIOS search folder", NULL, 0, 0), OPT_STRING ('c', "console-source", &console_source, "Select console source (auto, null, kernel, atcons)"), + OPT_STRING ('e', "exp-rom" , &exp_path , "Specify an expansion ROM file"), OPT_INTEGER ('L', "log-level" , &log_level , "Set log level"), OPT_STRING ('M', "model" , &model , "Specify console model (SPCH-XXXX)", NULL, 0, 0), OPT_STRING ('r', "region" , ®ion , "Specify console region"), OPT_STRING ('S', "settings-file" , &settings_path , "Specify settings file path", NULL, 0, 0), OPT_BOOLEAN ('q', "quiet" , &quiet , "Silence all logs (ignores -L)"), - OPT_STRING ('x', "exe" , &exe , "Boot this PS-X EXE file"), + OPT_STRING ('x', "exe" , &exe , "Launch a PS-X EXE file"), OPT_STRING (0 , "cdrom" , &cd_path , "Specify a CDROM image"), OPT_END() }; @@ -274,6 +277,9 @@ void psxe_cfg_load(psxe_config_t* cfg, int argc, const char* argv[]) { if (psxe_version) cfg->psxe_version = psxe_version; + + if (exp_path) + cfg->exp_path = exp_path; } // To-do: Implement BIOS searching diff --git a/frontend/config.h b/frontend/config.h index 8169a0b..047b81c 100644 --- a/frontend/config.h +++ b/frontend/config.h @@ -24,6 +24,7 @@ typedef struct { const char* region; const char* psxe_version; const char* cd_path; + const char* exp_path; } psxe_config_t; psxe_config_t* psxe_cfg_create(); diff --git a/frontend/main.c b/frontend/main.c index 0f496cd..1c66ae2 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -34,7 +34,7 @@ int main(int argc, const char* argv[]) { log_set_level(cfg->log_level); psx_t* psx = psx_create(); - psx_init(psx, cfg->bios); + psx_init(psx, cfg->bios, cfg->exp_path); psx_cdrom_t* cdrom = psx_get_cdrom(psx); diff --git a/frontend/screen.c b/frontend/screen.c index 76c2eaf..4159751 100644 --- a/frontend/screen.c +++ b/frontend/screen.c @@ -52,13 +52,10 @@ void psxe_screen_init(psxe_screen_t* screen, psx_t* psx) { screen->texture_height = PSX_GPU_FB_HEIGHT; SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); - SDL_SetHint("SDL_HINT_RENDER_SCALE_QUALITY", "0"); SDL_SetRenderDrawColor(screen->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); } void psxe_screen_reload(psxe_screen_t* screen) { - SDL_SetHint("SDL_HINT_RENDER_SCALE_QUALITY", "0"); - if (screen->texture) SDL_DestroyTexture(screen->texture); if (screen->renderer) SDL_DestroyRenderer(screen->renderer); if (screen->window) SDL_DestroyWindow(screen->window); @@ -81,7 +78,7 @@ void psxe_screen_reload(psxe_screen_t* screen) { SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen->width * screen->scale, screen->height * screen->scale, - SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI + 0 ); screen->renderer = SDL_CreateRenderer( @@ -90,6 +87,8 @@ void psxe_screen_reload(psxe_screen_t* screen) { SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC ); + SDL_SetHint("SDL_HINT_RENDER_SCALE_QUALITY", "linear"), + screen->texture = SDL_CreateTexture( screen->renderer, screen->format, @@ -97,6 +96,8 @@ void psxe_screen_reload(psxe_screen_t* screen) { screen->texture_width, screen->texture_height ); + SDL_SetTextureScaleMode(screen->texture, screen->bilinear); + // Check for retina displays int width = 0, height = 0; @@ -130,19 +131,23 @@ void psxe_screen_toggle_debug_mode(psxe_screen_t* screen) { } void psxe_screen_update(psxe_screen_t* screen) { - void* display_buf = screen->debug_mode ? - psx_get_vram(screen->psx) : psx_get_display_buffer(screen->psx); + // void* vram = psx_get_vram(screen->psx); - // // Update texture with Lock/UnlockTexture - // int pitch; - // uint8_t* ptr = NULL; + // if (screen->field & 2) { + // for (int y = screen->field & 1; y < 512; y += 2) { + // memcpy( + // ((uint8_t*)screen->buf) + (y * PSX_GPU_FB_STRIDE), + // ((uint8_t*)vram) + (y * PSX_GPU_FB_STRIDE), + // PSX_GPU_FB_STRIDE + // ); + // } + // } - // SDL_LockTexture(screen->texture, NULL, &ptr, &pitch); + // screen->field += 1; + // screen->field &= 3; - // for (int y = 0; y < screen->texture_height; y++) - // memcpy(ptr + (y * pitch), display_buf + (y * PSX_GPU_FB_STRIDE), pitch); - - // SDL_UnlockTexture(screen->texture); + void* display_buf = screen->debug_mode ? + psx_get_vram(screen->psx) : psx_get_display_buffer(screen->psx); SDL_UpdateTexture(screen->texture, NULL, display_buf, PSX_GPU_FB_STRIDE); SDL_RenderClear(screen->renderer); @@ -212,6 +217,12 @@ void psxe_screen_update(psxe_screen_t* screen) { } break; case SDLK_F4: { + screen->bilinear = !screen->bilinear; + + psxe_gpu_dmode_event_cb(screen->psx->gpu); + } break; + + case SDLK_F11: { screen->fullscreen = !screen->fullscreen; SDL_SetWindowFullscreen( @@ -237,6 +248,14 @@ void psxe_screen_update(psxe_screen_t* screen) { uint16_t mask = screen_get_button(event.key.keysym.sym); psx_pad_button_press(screen->pad, 0, mask); + + if (event.key.keysym.sym == SDLK_RETURN) { + psx_exp2_atcons_put(screen->psx->exp2, 13); + } + } break; + + case SDL_TEXTINPUT: { + psx_exp2_atcons_put(screen->psx->exp2, event.text.text[0]); } break; case SDL_KEYUP: { @@ -280,8 +299,11 @@ void psxe_gpu_dmode_event_cb(psx_gpu_t* gpu) { screen->texture_height = PSX_GPU_FB_HEIGHT; } else { if (screen->fullscreen) { - screen->width = 1920; - screen->height = 1080; + SDL_DisplayMode dm; + SDL_GetCurrentDisplayMode(0, &dm); + + screen->width = dm.w; + screen->height = dm.h; if (screen->vertical_mode) { screen->image_width = screen->height; @@ -331,6 +353,8 @@ void psxe_gpu_dmode_event_cb(psx_gpu_t* gpu) { screen->texture_width, screen->texture_height ); + SDL_SetTextureScaleMode(screen->texture, screen->bilinear); + SDL_SetWindowSize(screen->window, screen->width, screen->height); } diff --git a/frontend/screen.h b/frontend/screen.h index 1b777bd..d238444 100644 --- a/frontend/screen.h +++ b/frontend/screen.h @@ -23,6 +23,7 @@ typedef struct { unsigned int format; unsigned int texture_width, texture_height; + int bilinear; int fullscreen; int vertical_mode; int debug_mode; diff --git a/psx/bus.c b/psx/bus.c index 9feb1a8..3f66c7b 100644 --- a/psx/bus.c +++ b/psx/bus.c @@ -48,6 +48,7 @@ uint32_t psx_bus_read32(psx_bus_t* bus, uint32_t addr) { HANDLE_READ(ram, 32); HANDLE_READ(dma, 32); HANDLE_READ(exp1, 32); + HANDLE_READ(exp2, 32); HANDLE_READ(mc1, 32); HANDLE_READ(mc2, 32); HANDLE_READ(mc3, 32); @@ -82,6 +83,7 @@ uint16_t psx_bus_read16(psx_bus_t* bus, uint32_t addr) { HANDLE_READ(ram, 16); HANDLE_READ(dma, 16); HANDLE_READ(exp1, 16); + HANDLE_READ(exp2, 16); HANDLE_READ(mc1, 16); HANDLE_READ(mc2, 16); HANDLE_READ(mc3, 16); @@ -112,6 +114,7 @@ uint8_t psx_bus_read8(psx_bus_t* bus, uint32_t addr) { HANDLE_READ(ram, 8); HANDLE_READ(dma, 8); HANDLE_READ(exp1, 8); + HANDLE_READ(exp2, 8); HANDLE_READ(mc1, 8); HANDLE_READ(mc2, 8); HANDLE_READ(mc3, 8); @@ -146,6 +149,7 @@ void psx_bus_write32(psx_bus_t* bus, uint32_t addr, uint32_t value) { HANDLE_WRITE(ram, 32); HANDLE_WRITE(dma, 32); HANDLE_WRITE(exp1, 32); + HANDLE_WRITE(exp2, 32); HANDLE_WRITE(mc1, 32); HANDLE_WRITE(mc2, 32); HANDLE_WRITE(mc3, 32); @@ -178,6 +182,7 @@ void psx_bus_write16(psx_bus_t* bus, uint32_t addr, uint16_t value) { HANDLE_WRITE(ram, 16); HANDLE_WRITE(dma, 16); HANDLE_WRITE(exp1, 16); + HANDLE_WRITE(exp2, 16); HANDLE_WRITE(mc1, 16); HANDLE_WRITE(mc2, 16); HANDLE_WRITE(mc3, 16); @@ -206,6 +211,7 @@ void psx_bus_write8(psx_bus_t* bus, uint32_t addr, uint8_t value) { HANDLE_WRITE(ram, 8); HANDLE_WRITE(dma, 8); HANDLE_WRITE(exp1, 8); + HANDLE_WRITE(exp2, 8); HANDLE_WRITE(mc1, 8); HANDLE_WRITE(mc2, 8); HANDLE_WRITE(mc3, 8); @@ -239,6 +245,10 @@ void psx_bus_init_exp1(psx_bus_t* bus, psx_exp1_t* exp1) { bus->exp1 = exp1; } +void psx_bus_init_exp2(psx_bus_t* bus, psx_exp2_t* exp2) { + bus->exp2 = exp2; +} + void psx_bus_init_mc1(psx_bus_t* bus, psx_mc1_t* mc1) { bus->mc1 = mc1; } diff --git a/psx/bus_init.h b/psx/bus_init.h index ea68105..bd3434f 100644 --- a/psx/bus_init.h +++ b/psx/bus_init.h @@ -5,6 +5,7 @@ #include "dev/ram.h" #include "dev/dma.h" #include "dev/exp1.h" +#include "dev/exp2.h" #include "dev/mc1.h" #include "dev/mc2.h" #include "dev/mc3.h" @@ -22,6 +23,7 @@ struct psx_bus_t { psx_ram_t* ram; psx_dma_t* dma; psx_exp1_t* exp1; + psx_exp2_t* exp2; psx_mc1_t* mc1; psx_mc2_t* mc2; psx_mc3_t* mc3; @@ -41,6 +43,7 @@ void psx_bus_init_bios(psx_bus_t*, psx_bios_t*); void psx_bus_init_ram(psx_bus_t*, psx_ram_t*); void psx_bus_init_dma(psx_bus_t*, psx_dma_t*); void psx_bus_init_exp1(psx_bus_t*, psx_exp1_t*); +void psx_bus_init_exp2(psx_bus_t*, psx_exp2_t*); void psx_bus_init_mc1(psx_bus_t*, psx_mc1_t*); void psx_bus_init_mc2(psx_bus_t*, psx_mc2_t*); void psx_bus_init_mc3(psx_bus_t*, psx_mc3_t*); diff --git a/psx/dev/bios.c b/psx/dev/bios.c index 5285576..0cf4c6e 100644 --- a/psx/dev/bios.c +++ b/psx/dev/bios.c @@ -15,8 +15,6 @@ void psx_bios_init(psx_bios_t* bios) { bios->io_base = PSX_BIOS_BEGIN; bios->io_size = PSX_BIOS_SIZE; bios->bus_delay = 18; - - bios->buf = (uint8_t*)malloc(PSX_BIOS_SIZE); } void psx_bios_load(psx_bios_t* bios, const char* path) { @@ -28,7 +26,21 @@ void psx_bios_load(psx_bios_t* bios, const char* path) { exit(1); } - if (!fread(bios->buf, 1, PSX_BIOS_SIZE, file)) { + // Almost all PS1 BIOS ROMs are 512 KiB in size. + // There's (at least) one exception, and that is SCPH-5903. + // This is a special asian model PS1 that had built-in support + // for Video CD (VCD) playback. Its BIOS is double the normal + // size + fseek(file, 0, SEEK_END); + + size_t size = ftell(file); + + fseek(file, 0, SEEK_SET); + + bios->buf = malloc(size); + bios->io_size = size; + + if (!fread(bios->buf, 1, size, file)) { perror("Error reading BIOS file"); exit(1); diff --git a/psx/dev/cdrom.c b/psx/dev/cdrom.c index 455aba2..d3da463 100644 --- a/psx/dev/cdrom.c +++ b/psx/dev/cdrom.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "cdrom.h" #include "../log.h" @@ -21,6 +22,106 @@ Modchip:Audio/Mode1 INT3(stat) INT2(02h,00h, 00h,00h, 53h,43h,45h,4xh) */ +msf_t cdrom_get_track_addr(psx_cdrom_t* cdrom, msf_t msf) { + uint32_t lba = msf_to_address(msf); + + int num_tracks, track; + + psx_disc_get_track_count(cdrom->disc, &num_tracks); + + for (track = 1; track < num_tracks - 1; track++) { + msf_t curr, next; + + psx_disc_get_track_addr(cdrom->disc, &curr, track); + psx_disc_get_track_addr(cdrom->disc, &next, track + 1); + + uint32_t curr_lba = msf_to_address(curr); + uint32_t next_lba = msf_to_address(next); + + printf("lba=%02u:%02u:%02u (%08x) curr=%02u:%02u:%02u (%08x) next=%02u:%02u:%02u (%08x)\n", + msf.m, + msf.s, + msf.f, + lba, + curr.m, + curr.s, + curr.f, + curr_lba, + next.m, + next.s, + next.f, + next_lba + ); + + if ((lba >= curr_lba) && (lba < next_lba)) + break; + } + + msf_t track_msf; + + psx_disc_get_track_addr(cdrom->disc, &track_msf, track); + + return track_msf; +} + +void cdrom_fetch_video_sector(psx_cdrom_t* cdrom) { + while (true) { + if (psx_disc_seek(cdrom->disc, cdrom->seek_msf)) + return; + + psx_disc_read_sector(cdrom->disc, cdrom->dfifo); + + // printf("%02u:%02u:%02u - file=%02x channel=%02x sm=%02x (%u%u%u%u%u%u%u%u) ci=%02x... ", + // cdrom->seek_msf.m, + // cdrom->seek_msf.s, + // cdrom->seek_msf.f, + // cdrom->dfifo[0x10], + // cdrom->dfifo[0x11], + // cdrom->dfifo[0x12], + // (cdrom->dfifo[0x12] & 0x80) != 0, + // (cdrom->dfifo[0x12] & 0x40) != 0, + // (cdrom->dfifo[0x12] & 0x20) != 0, + // (cdrom->dfifo[0x12] & 0x10) != 0, + // (cdrom->dfifo[0x12] & 0x08) != 0, + // (cdrom->dfifo[0x12] & 0x04) != 0, + // (cdrom->dfifo[0x12] & 0x02) != 0, + // (cdrom->dfifo[0x12] & 0x01) != 0, + // cdrom->dfifo[0x13] + // ); + + msf_add_f(&cdrom->seek_msf, 1); + + // Check RT and Video/Data bit + uint8_t sm = cdrom->dfifo[0x12] & 4; + + if (sm) { + // printf("Not sent (Unfiltered)\n"); + + 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)) { + // printf("Sent (Unfiltered)\n"); + return; + } + + // 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) { + // printf("Sent (Filtered)\n"); + return; + } + + // printf("Not sent (Filtered)\n"); + } +} + #define GETID_RESPONSE_SIZE 8 #define GETID_RESPONSE_END (GETID_RESPONSE_SIZE - 1) @@ -157,10 +258,18 @@ void cdrom_cmd_unimplemented(psx_cdrom_t* cdrom) { exit(1); } void cdrom_cmd_getstat(psx_cdrom_t* cdrom) { - cdrom->delayed_command = CDL_NONE; - switch (cdrom->state) { case CD_STATE_RECV_CMD: { + if (cdrom->ongoing_read_command) { + cdrom->status |= STAT_BUSYSTS_MASK; + // printf("command=%02x\n", cdrom->ongoing_read_command); + cdrom->state = CD_STATE_SEND_RESP2; + cdrom->delayed_command = cdrom->ongoing_read_command; + cdrom->irq_delay = DELAY_1MS; + + return; + } + if (cdrom->pfifo_index) { log_fatal("CdlGetStat: Expected exactly 0 parameters"); @@ -183,12 +292,15 @@ void cdrom_cmd_getstat(psx_cdrom_t* cdrom) { RESP_PUSH( GETSTAT_MOTOR | (cdrom->cdda_playing ? GETSTAT_PLAY : 0) | + // (cdrom->ongoing_read_command ? GETSTAT_READ : 0) | (cdrom->disc ? 0 : GETSTAT_TRAYOPEN) ); - if (cdrom->read_ongoing) { + if (cdrom->ongoing_read_command) { + cdrom->status |= STAT_BUSYSTS_MASK; + // printf("command=%02x\n", cdrom->ongoing_read_command); cdrom->state = CD_STATE_SEND_RESP2; - cdrom->delayed_command = CDL_READN; + cdrom->delayed_command = cdrom->ongoing_read_command; cdrom->irq_delay = DELAY_1MS; } else { cdrom->delayed_command = CDL_NONE; @@ -216,16 +328,6 @@ void cdrom_cmd_setloc(psx_cdrom_t* cdrom) { return; } - //if (!cdrom->read_ongoing) { - cdrom->irq_delay = DELAY_1MS; - cdrom->delayed_command = CDL_SETLOC; - cdrom->state = CD_STATE_SEND_RESP1; - // } else { - // cdrom->irq_delay = DELAY_1MS; - // cdrom->delayed_command = CDL_READN; - // cdrom->state = CD_STATE_SEND_RESP2; - // } - int f = PFIFO_POP; int s = PFIFO_POP; int m = PFIFO_POP; @@ -240,26 +342,40 @@ void cdrom_cmd_setloc(psx_cdrom_t* cdrom) { return; } - cdrom->seek_ff = f; - cdrom->seek_ss = s; - cdrom->seek_mm = m; + cdrom->seek_msf.m = m; + cdrom->seek_msf.s = s; + cdrom->seek_msf.f = f; + + msf_from_bcd(&cdrom->seek_msf); + + cdrom->cdda_msf = cdrom->seek_msf; cdrom->seek_pending = 1; log_fatal("setloc: %02x:%02x:%02x", - cdrom->seek_mm, - cdrom->seek_ss, - cdrom->seek_ff + cdrom->seek_msf.m, + cdrom->seek_msf.s, + cdrom->seek_msf.f ); + + cdrom->irq_delay = DELAY_1MS; + cdrom->delayed_command = CDL_SETLOC; + cdrom->state = CD_STATE_SEND_RESP1; } break; case CD_STATE_SEND_RESP1: { - cdrom->delayed_command = CDL_NONE; - SET_BITS(ifr, IFR_INT, IFR_INT3); RESP_PUSH(GETSTAT_MOTOR); - cdrom->state = CD_STATE_RECV_CMD; + if (cdrom->ongoing_read_command) { + // printf("command=%02x\n", cdrom->ongoing_read_command); + cdrom->state = CD_STATE_SEND_RESP2; + cdrom->delayed_command = cdrom->ongoing_read_command; + cdrom->irq_delay = DELAY_1MS; + } else { + cdrom->delayed_command = CDL_NONE; + cdrom->state = CD_STATE_RECV_CMD; + } } break; // Read ongoing @@ -269,7 +385,7 @@ void cdrom_cmd_setloc(psx_cdrom_t* cdrom) { int m = PFIFO_POP; if (!(VALID_BCD(m) && VALID_BCD(s) && VALID_BCD(f) && (f < 0x75))) { - cdrom->read_ongoing = false; + cdrom->ongoing_read_command = false; cdrom->irq_delay = DELAY_1MS; cdrom->delayed_command = CDL_ERROR; cdrom->state = CD_STATE_ERROR; @@ -279,9 +395,9 @@ void cdrom_cmd_setloc(psx_cdrom_t* cdrom) { return; } - cdrom->seek_ff = f; - cdrom->seek_ss = s; - cdrom->seek_mm = m; + cdrom->seek_msf.m = m; + cdrom->seek_msf.s = s; + cdrom->seek_msf.f = f; } break; } } @@ -316,9 +432,9 @@ void cdrom_cmd_play(psx_cdrom_t* cdrom) { msf_to_bcd(&cdrom->cdda_msf); cdrom->cdda_track = track; - cdrom->seek_mm = cdrom->cdda_msf.m; - cdrom->seek_ss = cdrom->cdda_msf.s; - cdrom->seek_ff = cdrom->cdda_msf.f; + cdrom->seek_msf.m = cdrom->cdda_msf.m; + cdrom->seek_msf.s = cdrom->cdda_msf.s; + cdrom->seek_msf.f = cdrom->cdda_msf.f; cdrom->seek_pending = 1; } @@ -326,24 +442,17 @@ void cdrom_cmd_play(psx_cdrom_t* cdrom) { if (cdrom->seek_pending) { cdrom->seek_pending = 0; - cdrom->cdda_msf.m = cdrom->seek_mm; - cdrom->cdda_msf.s = cdrom->seek_ss; - cdrom->cdda_msf.f = cdrom->seek_ff; + printf("Seeked to location\n"); - // Convert seek to I - msf_t msf = cdrom->cdda_msf; - - msf_from_bcd(&msf); + cdrom->cdda_msf = cdrom->seek_msf; // Seek to that address and read sector - psx_disc_seek(cdrom->disc, msf); + psx_disc_seek(cdrom->disc, cdrom->cdda_msf); psx_disc_read_sector(cdrom->disc, cdrom->cdda_buf); // Increment sector - msf_add_f(&msf, 1); - msf_to_bcd(&msf); + msf_add_f(&cdrom->cdda_msf, 1); - cdrom->cdda_msf = msf; cdrom->cdda_sector_offset = 0; } @@ -361,7 +470,7 @@ void cdrom_cmd_play(psx_cdrom_t* cdrom) { } void cdrom_cmd_readn(psx_cdrom_t* cdrom) { cdrom->delayed_command = CDL_NONE; - cdrom->read_ongoing = 1; + cdrom->ongoing_read_command = CDL_READN; switch (cdrom->state) { case CD_STATE_RECV_CMD: { @@ -377,17 +486,8 @@ void cdrom_cmd_readn(psx_cdrom_t* cdrom) { SET_BITS(ifr, IFR_INT, IFR_INT3); RESP_PUSH(GETSTAT_MOTOR); - msf_t msf; - - msf.m = cdrom->seek_mm; - msf.s = cdrom->seek_ss; - msf.f = cdrom->seek_ff; - - msf_from_bcd(&msf); - - cdrom->xa_msf = msf; - if (cdrom->mode & MODE_XA_ADPCM) { + cdrom->xa_msf = cdrom->seek_msf; cdrom->xa_playing = 1; SET_BITS(status, STAT_ADPBUSY_MASK, STAT_ADPBUSY_MASK); @@ -402,7 +502,7 @@ void cdrom_cmd_readn(psx_cdrom_t* cdrom) { ); } - int err = psx_disc_seek(cdrom->disc, msf); + int err = psx_disc_seek(cdrom->disc, cdrom->seek_msf); if (err) { log_set_quiet(0); @@ -420,34 +520,6 @@ void cdrom_cmd_readn(psx_cdrom_t* cdrom) { psx_disc_read_sector(cdrom->disc, cdrom->dfifo); - msf_t sector_msf; - - sector_msf.m = cdrom->dfifo[0x0c]; - sector_msf.s = cdrom->dfifo[0x0d]; - sector_msf.f = cdrom->dfifo[0x0e]; - - int correct_msf = (cdrom->seek_mm == sector_msf.m) && - (cdrom->seek_ss == sector_msf.s) && - (cdrom->seek_ff == sector_msf.f); - - // Most probably audio sector: - // Purposefully constructed audio data could - // circumvent this detection code, but it will work - // for most intents and purposes - if (!correct_msf) { - log_set_quiet(0); - log_fatal("CdlReadN: Audio read"); - log_set_quiet(1); - - cdrom->irq_delay = DELAY_1MS * 600; - cdrom->delayed_command = CDL_ERROR; - cdrom->state = CD_STATE_ERROR; - cdrom->error = ERR_SEEK; - cdrom->error_flags = GETSTAT_SEEKERROR; - - return; - } - int double_speed = cdrom->mode & MODE_SPEED; cdrom->irq_delay = double_speed ? READ_DOUBLE_DELAY : READ_SINGLE_DELAY; @@ -461,44 +533,31 @@ void cdrom_cmd_readn(psx_cdrom_t* cdrom) { } break; case CD_STATE_SEND_RESP2: { - log_fatal("CdlReadN: CD_STATE_SEND_RESP2"); - - msf_t msf; - - msf.m = cdrom->seek_mm; - msf.s = cdrom->seek_ss; - msf.f = cdrom->seek_ff; - - msf_from_bcd(&msf); + log_fatal("CdlReadS: CD_STATE_SEND_RESP2"); - psx_disc_seek(cdrom->disc, msf); - psx_disc_read_sector(cdrom->disc, cdrom->dfifo); + // Returning only non-ADPCM sectors causes desync for some + // reason. I'll keep returning all sectors for now - // printf("Sector header: msf=%02x:%02x:%02x, mode=%02x, subheader=%02x,%02x,%02x,%02x\n", - // cdrom->dfifo[0x0c], - // cdrom->dfifo[0x0d], - // cdrom->dfifo[0x0e], - // cdrom->dfifo[0x0f], - // cdrom->dfifo[0x10], - // cdrom->dfifo[0x11], - // cdrom->dfifo[0x12], - // cdrom->dfifo[0x13] - // ); - - if (cdrom->dfifo[0x12] & 0x20) { - log_fatal("Unimplemented XA Form2 Sector"); + if (cdrom->mode & MODE_XA_ADPCM) { + // printf("ReadS fetching non ADPCM sector...\n"); + cdrom_fetch_video_sector(cdrom); + + printf("%02u:%02u:%02u - file=%02x channel=%02x sm=%02x ci=%02x\n", + cdrom->seek_msf.m, + cdrom->seek_msf.s, + cdrom->seek_msf.f, + cdrom->dfifo[0x10], + cdrom->dfifo[0x11], + cdrom->dfifo[0x12], + cdrom->dfifo[0x13] + ); + } else { + psx_disc_seek(cdrom->disc, cdrom->seek_msf); + psx_disc_read_sector(cdrom->disc, cdrom->dfifo); - // exit(1); + msf_add_f(&cdrom->seek_msf, 1); } - cdrom->seek_ff++; - - if ((cdrom->seek_ff & 0xF) == 10) { cdrom->seek_ff += 0x10; cdrom->seek_ff &= 0xF0; } - if (cdrom->seek_ff == 0x75) { cdrom->seek_ss++; cdrom->seek_ff = 0; } - if ((cdrom->seek_ss & 0xF) == 10) { cdrom->seek_ss += 0x10; cdrom->seek_ss &= 0xF0; } - if (cdrom->seek_ss == 0x60) { cdrom->seek_mm++; cdrom->seek_ss = 0; } - if ((cdrom->seek_mm & 0xF) == 10) { cdrom->seek_mm += 0x10; cdrom->seek_mm &= 0xF0; } - int double_speed = cdrom->mode & MODE_SPEED; cdrom->irq_delay = double_speed ? READ_DOUBLE_DELAY : READ_SINGLE_DELAY; @@ -516,7 +575,7 @@ void cdrom_cmd_motoron(psx_cdrom_t* cdrom) { switch (cdrom->state) { case CD_STATE_RECV_CMD: { - cdrom->read_ongoing = 0; + cdrom->ongoing_read_command = CDL_NONE; cdrom->cdda_playing = 0; cdrom->irq_delay = DELAY_1MS; @@ -549,18 +608,17 @@ void cdrom_cmd_stop(psx_cdrom_t* cdrom) { switch (cdrom->state) { case CD_STATE_RECV_CMD: { - cdrom->read_ongoing = 0; + cdrom->ongoing_read_command = CDL_NONE; cdrom->cdda_playing = 0; cdrom->irq_delay = DELAY_1MS; cdrom->state = CD_STATE_SEND_RESP1; cdrom->delayed_command = CDL_STOP; - cdrom->seek_ff = 0; - cdrom->seek_ss = 0; - cdrom->seek_mm = 0; - cdrom->cdda_msf.m = 0; - cdrom->cdda_msf.s = 0; - cdrom->cdda_msf.f = 0; + cdrom->seek_msf.m = 0; + cdrom->seek_msf.s = 0; + cdrom->seek_msf.f = 0; + + cdrom->cdda_msf = cdrom->seek_msf; } break; case CD_STATE_SEND_RESP1: { @@ -588,7 +646,7 @@ void cdrom_cmd_pause(psx_cdrom_t* cdrom) { switch (cdrom->state) { case CD_STATE_RECV_CMD: { - cdrom->read_ongoing = 0; + cdrom->ongoing_read_command = CDL_NONE; cdrom->cdda_playing = 0; cdrom->xa_playing = 0; @@ -627,20 +685,20 @@ void cdrom_cmd_init(psx_cdrom_t* cdrom) { cdrom->irq_delay = DELAY_1MS; cdrom->state = CD_STATE_SEND_RESP1; cdrom->delayed_command = CDL_INIT; - cdrom->read_ongoing = 0; + cdrom->ongoing_read_command = CDL_NONE; cdrom->mode = 0; cdrom->dfifo_index = 0; cdrom->dfifo_full = 0; cdrom->pfifo_index = 0; cdrom->rfifo_index = 0; - cdrom->seek_mm = 0; - cdrom->seek_ss = 0; - cdrom->seek_ff = 0; + cdrom->seek_msf.m = 0; + cdrom->seek_msf.s = 2; + cdrom->seek_msf.f = 0; } break; case CD_STATE_SEND_RESP1: { SET_BITS(ifr, IFR_INT, 3); - RESP_PUSH(cdrom->stat); + RESP_PUSH(GETSTAT_MOTOR); cdrom->irq_delay = DELAY_1MS; cdrom->state = CD_STATE_SEND_RESP2; @@ -649,7 +707,7 @@ void cdrom_cmd_init(psx_cdrom_t* cdrom) { case CD_STATE_SEND_RESP2: { SET_BITS(ifr, IFR_INT, 2); - RESP_PUSH(cdrom->stat); + RESP_PUSH(GETSTAT_MOTOR); cdrom->state = CD_STATE_RECV_CMD; cdrom->delayed_command = CDL_NONE; @@ -682,8 +740,15 @@ void cdrom_cmd_unmute(psx_cdrom_t* cdrom) { SET_BITS(ifr, IFR_INT, IFR_INT3); RESP_PUSH(cdrom->stat); - cdrom->delayed_command = CDL_NONE; - cdrom->state = CD_STATE_RECV_CMD; + if (cdrom->ongoing_read_command) { + // printf("command=%02x\n", cdrom->ongoing_read_command); + cdrom->state = CD_STATE_SEND_RESP2; + cdrom->delayed_command = cdrom->ongoing_read_command; + cdrom->irq_delay = DELAY_1MS; + } else { + cdrom->delayed_command = CDL_NONE; + cdrom->state = CD_STATE_RECV_CMD; + } } break; } } @@ -718,6 +783,12 @@ void cdrom_cmd_setfilter(psx_cdrom_t* cdrom) { SET_BITS(ifr, IFR_INT, IFR_INT3); RESP_PUSH(cdrom->stat); + if (cdrom->ongoing_read_command) { + cdrom->irq_delay = DELAY_1MS; + cdrom->delayed_command = cdrom->ongoing_read_command; + cdrom->state = CD_STATE_SEND_RESP2; + } + cdrom->state = CD_STATE_RECV_CMD; } break; } @@ -755,7 +826,13 @@ void cdrom_cmd_setmode(psx_cdrom_t* cdrom) { cdrom->delayed_command = CDL_NONE; SET_BITS(ifr, IFR_INT, IFR_INT3); - RESP_PUSH(GETSTAT_MOTOR | GETSTAT_PLAY); + RESP_PUSH(GETSTAT_MOTOR); + + if (cdrom->ongoing_read_command) { + cdrom->irq_delay = DELAY_1MS; + cdrom->delayed_command = cdrom->ongoing_read_command; + cdrom->state = CD_STATE_SEND_RESP2; + } cdrom->state = CD_STATE_RECV_CMD; } break; @@ -795,17 +872,24 @@ void cdrom_cmd_getlocl(psx_cdrom_t* cdrom) { case CD_STATE_SEND_RESP1: { SET_BITS(ifr, IFR_INT, IFR_INT3); - RESP_PUSH(0x00); - RESP_PUSH(0x00); - RESP_PUSH(0x00); - RESP_PUSH(0x00); - RESP_PUSH(0x00); - RESP_PUSH(0x00); - RESP_PUSH(0x01); - RESP_PUSH(0xff); - - cdrom->delayed_command = CDL_NONE; - cdrom->state = CD_STATE_RECV_CMD; + RESP_PUSH(cdrom->dfifo[0x13]); + RESP_PUSH(cdrom->dfifo[0x12]); + RESP_PUSH(cdrom->dfifo[0x11]); + RESP_PUSH(cdrom->dfifo[0x10]); + RESP_PUSH(cdrom->dfifo[0x0f]); + RESP_PUSH(cdrom->dfifo[0x0e]); + RESP_PUSH(cdrom->dfifo[0x0d]); + RESP_PUSH(cdrom->dfifo[0x0c]); + + // if (cdrom->ongoing_read_command) { + // // printf("command=%02x\n", cdrom->ongoing_read_command); + // cdrom->state = CD_STATE_SEND_RESP2; + // cdrom->delayed_command = cdrom->ongoing_read_command; + // cdrom->irq_delay = DELAY_1MS; + // } else { + cdrom->delayed_command = CDL_NONE; + cdrom->state = CD_STATE_RECV_CMD; + // } } break; } } @@ -818,18 +902,59 @@ 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 relative = absolute; + msf_t track_msf = cdrom_get_track_addr(cdrom, absolute); + + relative.m -= track_msf.m; + relative.s -= track_msf.s; + relative.f -= track_msf.f; + + msf_adjust_sub(&relative); + + // printf("abs=%02u:%02u:%02u tra=%02u:%02u:%02u rel=%02u:%02u:%02u\n", + // absolute.m, + // absolute.s, + // absolute.f, + // track_msf.m, + // track_msf.s, + // track_msf.f, + // relative.m, + // relative.s, + // relative.f + // ); + + msf_to_bcd(&absolute); + msf_to_bcd(&relative); + + // printf("getlocp 01 01 %02x:%02x:%02x %02x:%02x:%02x\n", + // relative.m, + // relative.s, + // relative.f, + // absolute.m, + // absolute.s, + // absolute.f + // ); + SET_BITS(ifr, IFR_INT, IFR_INT3); - RESP_PUSH(0x00); - RESP_PUSH(0x00); - RESP_PUSH(0x00); - RESP_PUSH(0x00); - RESP_PUSH(0x00); - RESP_PUSH(0x00); + RESP_PUSH(absolute.f); + RESP_PUSH(absolute.s); + RESP_PUSH(absolute.m); + RESP_PUSH(relative.f); + RESP_PUSH(relative.s); + RESP_PUSH(relative.m); + RESP_PUSH(0x01); RESP_PUSH(0x01); - RESP_PUSH(0xff); - cdrom->delayed_command = CDL_NONE; - cdrom->state = CD_STATE_RECV_CMD; + if (cdrom->ongoing_read_command) { + //// printf("command=%02x\n", cdrom->ongoing_read_command); + cdrom->state = CD_STATE_SEND_RESP2; + cdrom->delayed_command = cdrom->ongoing_read_command; + cdrom->irq_delay = DELAY_1MS; + } else { + cdrom->delayed_command = CDL_NONE; + cdrom->state = CD_STATE_RECV_CMD; + } } break; } } @@ -877,7 +1002,7 @@ void cdrom_cmd_gettn(psx_cdrom_t* cdrom) { return; } - cdrom->irq_delay = DELAY_1MS; + cdrom->irq_delay = DELAY_1MS * 2; cdrom->delayed_command = CDL_GETTN; cdrom->state = CD_STATE_SEND_RESP1; } break; @@ -903,7 +1028,7 @@ void cdrom_cmd_gettd(psx_cdrom_t* cdrom) { switch (cdrom->state) { case CD_STATE_RECV_CMD: { if (cdrom->pfifo_index != 1) { - log_fatal("CdlGetTD: Expected exactly 0 parameters"); + log_fatal("CdlGetTD: Expected exactly 1 parameter"); cdrom->irq_delay = DELAY_1MS; cdrom->delayed_command = CDL_ERROR; @@ -916,13 +1041,23 @@ void cdrom_cmd_gettd(psx_cdrom_t* cdrom) { cdrom->gettd_track = PFIFO_POP; + if (!VALID_BCD(cdrom->gettd_track)) { + cdrom->irq_delay = DELAY_1MS; + cdrom->delayed_command = CDL_ERROR; + cdrom->state = CD_STATE_ERROR; + cdrom->error = ERR_INVSUBF; + cdrom->error_flags = GETSTAT_ERROR; + + return; + } + int err = psx_disc_get_track_addr(cdrom->disc, NULL, cdrom->gettd_track); if (err) { cdrom->irq_delay = DELAY_1MS; cdrom->delayed_command = CDL_ERROR; cdrom->state = CD_STATE_ERROR; - cdrom->error = ERR_PCOUNT; + cdrom->error = ERR_INVSUBF; cdrom->error_flags = GETSTAT_ERROR; return; @@ -978,15 +1113,7 @@ void cdrom_cmd_seekl(psx_cdrom_t* cdrom) { cdrom->state = CD_STATE_SEND_RESP2; cdrom->delayed_command = CDL_SEEKL; - msf_t msf; - - msf.m = cdrom->seek_mm; - msf.s = cdrom->seek_ss; - msf.f = cdrom->seek_ff; - - msf_from_bcd(&msf); - - psx_disc_seek(cdrom->disc, msf); + psx_disc_seek(cdrom->disc, cdrom->seek_msf); cdrom->seek_pending = 0; } break; @@ -1030,15 +1157,7 @@ void cdrom_cmd_seekp(psx_cdrom_t* cdrom) { cdrom->state = CD_STATE_SEND_RESP2; cdrom->delayed_command = CDL_SEEKP; - msf_t msf; - - msf.m = cdrom->seek_mm; - msf.s = cdrom->seek_ss; - msf.f = cdrom->seek_ff; - - msf_from_bcd(&msf); - - psx_disc_seek(cdrom->disc, msf); + psx_disc_seek(cdrom->disc, cdrom->seek_msf); cdrom->seek_pending = 0; } break; @@ -1087,12 +1206,13 @@ void cdrom_cmd_test(psx_cdrom_t* cdrom) { case CD_STATE_SEND_RESP1: { cdrom->delayed_command = CDL_NONE; - + + // 95h,05h,16h,C1h SET_BITS(ifr, IFR_INT, IFR_INT3); - RESP_PUSH(0xc0); - RESP_PUSH(0x19); - RESP_PUSH(0x09); - RESP_PUSH(0x94); + RESP_PUSH(0xc1); + RESP_PUSH(0x16); + RESP_PUSH(0x05); + RESP_PUSH(0x95); cdrom->state = CD_STATE_RECV_CMD; } break; @@ -1163,7 +1283,7 @@ void cdrom_cmd_getid(psx_cdrom_t* cdrom) { } void cdrom_cmd_reads(psx_cdrom_t* cdrom) { cdrom->delayed_command = CDL_NONE; - cdrom->read_ongoing = 1; + cdrom->ongoing_read_command = CDL_READS; switch (cdrom->state) { case CD_STATE_RECV_CMD: { @@ -1174,27 +1294,19 @@ void cdrom_cmd_reads(psx_cdrom_t* cdrom) { } break; case CD_STATE_SEND_RESP1: { + printf("CdlReadS: CD_STATE_SEND_RESP1\n"); log_fatal("CdlReadS: CD_STATE_SEND_RESP1"); SET_BITS(ifr, IFR_INT, IFR_INT3); RESP_PUSH(GETSTAT_MOTOR); - msf_t msf; - - msf.m = cdrom->seek_mm; - msf.s = cdrom->seek_ss; - msf.f = cdrom->seek_ff; - - msf_from_bcd(&msf); - - cdrom->xa_msf = msf; - if (cdrom->mode & MODE_XA_ADPCM) { + cdrom->xa_msf = cdrom->seek_msf; cdrom->xa_playing = 1; SET_BITS(status, STAT_ADPBUSY_MASK, STAT_ADPBUSY_MASK); - printf("Play XA-ADPCM encoded song at %02u:%02u:%02u, filter=%u, file=%02x, channel=%02x\n", + printf("Play XA-ADPCM encoded song at %02u:%02u:%02u, filter=%u, file=%02x, channel=%02x (ReadS)\n", cdrom->xa_msf.m, cdrom->xa_msf.s, cdrom->xa_msf.f, @@ -1205,17 +1317,19 @@ void cdrom_cmd_reads(psx_cdrom_t* cdrom) { int double_speed = cdrom->mode & MODE_SPEED; - cdrom->irq_delay = double_speed ? READ_DOUBLE_DELAY : READ_SINGLE_DELAY; + cdrom->irq_delay = DELAY_1MS * 2; cdrom->state = CD_STATE_SEND_RESP2; cdrom->delayed_command = CDL_READS; - if (cdrom->spin_delay) { - cdrom->irq_delay += cdrom->spin_delay; - cdrom->spin_delay = 0; - } + // if (cdrom->spin_delay) { + // cdrom->irq_delay += cdrom->spin_delay; + // cdrom->spin_delay = 0; + // } + + return; } - int err = psx_disc_seek(cdrom->disc, msf); + int err = psx_disc_seek(cdrom->disc, cdrom->seek_msf); if (err) { log_fatal("CdlReadS: Out of bounds seek"); @@ -1244,52 +1358,117 @@ void cdrom_cmd_reads(psx_cdrom_t* cdrom) { case CD_STATE_SEND_RESP2: { log_fatal("CdlReadS: CD_STATE_SEND_RESP2"); - msf_t msf; - - msf.m = cdrom->seek_mm; - msf.s = cdrom->seek_ss; - msf.f = cdrom->seek_ff; - - msf_from_bcd(&msf); - - psx_disc_seek(cdrom->disc, msf); - psx_disc_read_sector(cdrom->disc, cdrom->dfifo); + // Returning only non-ADPCM sectors causes desync for some + // reason. I'll keep returning all sectors for now - cdrom->seek_ff++; + if (cdrom->mode & MODE_XA_ADPCM) { + // printf("ReadS fetching non ADPCM sector...\n"); + cdrom_fetch_video_sector(cdrom); + + // printf("%02u:%02u:%02u - file=%02x channel=%02x sm=%02x ci=%02x\n", + // cdrom->seek_msf.m, + // cdrom->seek_msf.s, + // cdrom->seek_msf.f, + // cdrom->dfifo[0x10], + // cdrom->dfifo[0x11], + // cdrom->dfifo[0x12], + // cdrom->dfifo[0x13] + // ); + } else { + psx_disc_seek(cdrom->disc, cdrom->seek_msf); + psx_disc_read_sector(cdrom->disc, cdrom->dfifo); - if ((cdrom->seek_ff & 0xF) == 10) { cdrom->seek_ff += 0x10; cdrom->seek_ff &= 0xF0; } - if (cdrom->seek_ff == 0x75) { cdrom->seek_ss++; cdrom->seek_ff = 0; } - if ((cdrom->seek_ss & 0xF) == 10) { cdrom->seek_ss += 0x10; cdrom->seek_ss &= 0xF0; } - if (cdrom->seek_ss == 0x60) { cdrom->seek_mm++; cdrom->seek_ss = 0; } - if ((cdrom->seek_mm & 0xF) == 10) { cdrom->seek_mm += 0x10; cdrom->seek_mm &= 0xF0; } + msf_add_f(&cdrom->seek_msf, 1); + } int double_speed = cdrom->mode & MODE_SPEED; - cdrom->irq_delay = double_speed ? READ_DOUBLE_DELAY : READ_SINGLE_DELAY; + cdrom->irq_delay = DELAY_1MS * 2; cdrom->state = CD_STATE_SEND_RESP2; cdrom->delayed_command = CDL_READS; cdrom->dfifo_index = 0; - if (cdrom->mode & MODE_XA_ADPCM) { - int double_speed = cdrom->mode & MODE_SPEED; + SET_BITS(ifr, IFR_INT, IFR_INT1); + RESP_PUSH(GETSTAT_MOTOR | GETSTAT_READ); + } break; + } +} +void cdrom_cmd_readtoc(psx_cdrom_t* cdrom) { + switch (cdrom->state) { + case CD_STATE_RECV_CMD: { + cdrom->status |= STAT_BUSYSTS_MASK; + cdrom->irq_delay = DELAY_1MS * 1000; + cdrom->state = CD_STATE_SEND_RESP1; + cdrom->delayed_command = CDL_READTOC; + } break; - if (cdrom->dfifo[0x12] & 4) { - cdrom->irq_delay = 10; - cdrom->irq_delay = double_speed ? READ_DOUBLE_DELAY : READ_SINGLE_DELAY; - cdrom->state = CD_STATE_SEND_RESP2; - cdrom->delayed_command = CDL_READS; - // cdrom->irq_disable = 1; + case CD_STATE_SEND_RESP1: { + cdrom->status &= ~STAT_BUSYSTS_MASK; + SET_BITS(ifr, IFR_INT, 3); + RESP_PUSH(GETSTAT_MOTOR | GETSTAT_READ); - return; - } + cdrom->irq_delay = DELAY_1MS * 1000; + cdrom->state = CD_STATE_SEND_RESP2; + cdrom->delayed_command = CDL_READTOC; + } break; + + case CD_STATE_SEND_RESP2: { + SET_BITS(ifr, IFR_INT, 2); + RESP_PUSH(GETSTAT_MOTOR); + + cdrom->state = CD_STATE_RECV_CMD; + cdrom->delayed_command = CDL_NONE; + } break; + } +} +void cdrom_cmd_videocd(psx_cdrom_t* cdrom) { + switch (cdrom->state) { + case CD_STATE_RECV_CMD: { + cdrom->irq_delay = DELAY_1MS; + cdrom->state = CD_STATE_SEND_RESP1; + cdrom->delayed_command = CDL_VIDEOCD; + cdrom->pfifo_index = 0; + } break; + + case CD_STATE_SEND_RESP1: { + printf("VideoCD task %02x\n", cdrom->pfifo[4]); + SET_BITS(ifr, IFR_INT, 3); + + switch (cdrom->pfifo[4]) { + case 0: { + RESP_PUSH(0x00); + RESP_PUSH(0x00); + RESP_PUSH(0x00); + RESP_PUSH(0x00); + RESP_PUSH(0x00); + RESP_PUSH(GETSTAT_MOTOR); + } break; + + case 1: { + RESP_PUSH(0x00); + RESP_PUSH(0x00); + RESP_PUSH(0x00); + RESP_PUSH(0x00); + RESP_PUSH(0x81); + RESP_PUSH(GETSTAT_MOTOR); + } break; + + case 2: { + RESP_PUSH(0x00); + RESP_PUSH(0x00); + RESP_PUSH(0x00); + RESP_PUSH(0x00); + RESP_PUSH(0x05); + RESP_PUSH(GETSTAT_MOTOR); + } break; } - SET_BITS(ifr, IFR_INT, IFR_INT1); - RESP_PUSH(GETSTAT_MOTOR | GETSTAT_READ); + cdrom->irq_delay = DELAY_1MS; + cdrom->state = CD_STATE_RECV_CMD; + cdrom->delayed_command = CDL_NONE; } break; } } -void cdrom_cmd_readtoc(psx_cdrom_t* cdrom) { log_fatal("readtoc: Unimplemented"); exit(1); } typedef void (*cdrom_cmd_t)(psx_cdrom_t*); @@ -1325,7 +1504,7 @@ const char* g_psx_cdrom_command_names[] = { "CdlUnimplemented", "CdlUnimplemented", "CdlReadtoc", - "CdlUnimplemented" + "CdlVideoCD" }; cdrom_cmd_t g_psx_cdrom_command_table[] = { @@ -1360,6 +1539,7 @@ cdrom_cmd_t g_psx_cdrom_command_table[] = { cdrom_cmd_unimplemented, cdrom_cmd_unimplemented, cdrom_cmd_readtoc, + cdrom_cmd_videocd, // Actually an unimplemented command, we use this // index for CD error handling @@ -1418,8 +1598,7 @@ void cdrom_write_status(psx_cdrom_t* cdrom, uint8_t value) { } void cdrom_write_cmd(psx_cdrom_t* cdrom, uint8_t value) { - // log_set_quiet(0); - // log_fatal("%s(%02x) %u params=[%02x, %02x, %02x, %02x, %02x, %02x]", + // printf("%s(%02x) %u params=[%02x, %02x, %02x, %02x, %02x, %02x]\n", // g_psx_cdrom_command_names[value], // value, // cdrom->pfifo_index, @@ -1430,7 +1609,6 @@ void cdrom_write_cmd(psx_cdrom_t* cdrom, uint8_t value) { // cdrom->pfifo[4], // cdrom->pfifo[5] // ); - // log_set_quiet(1); cdrom->command = value; cdrom->state = CD_STATE_RECV_CMD; @@ -1577,6 +1755,10 @@ void psx_cdrom_init(psx_cdrom_t* cdrom, psx_ic_t* ic) { memset(cdrom->xa_left_resample_buf, 0, (XA_STEREO_RESAMPLE_SIZE * 2) * sizeof(int16_t)); 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->seek_msf.m = 0; + cdrom->seek_msf.s = 2; + cdrom->seek_msf.f = 0; } uint32_t psx_cdrom_read32(psx_cdrom_t* cdrom, uint32_t offset) { @@ -1730,7 +1912,16 @@ void cdrom_check_cd_type(psx_cdrom_t* cdrom) { void psx_cdrom_open(psx_cdrom_t* cdrom, const char* path) { cdrom->disc = psx_disc_create(); - int ext = cdrom_get_extension(path); + int len = strlen(path); + + char* lower = malloc(len + 1); + + for (int i = 0; i < len; i++) + lower[i] = tolower(path[i]); + + lower[len] = '\0'; + + int ext = cdrom_get_extension(lower); int error = 0; switch (ext) { @@ -1739,6 +1930,7 @@ void psx_cdrom_open(psx_cdrom_t* cdrom, const char* path) { psxd_cue_init_disc(cue, cdrom->disc); psxd_cue_init(cue); + error = psxd_cue_load(cue, path); if (error) @@ -1768,6 +1960,8 @@ void psx_cdrom_open(psx_cdrom_t* cdrom, const char* path) { } break; } + free(lower); + if (error) { log_fatal("Error loading file \'%s\'", path); @@ -1963,13 +2157,8 @@ void psx_cdrom_get_cdda_samples(psx_cdrom_t* cdrom, void* buf, int size, psx_spu return; } - // Convert seek to I - msf_t msf = cdrom->cdda_msf; - - msf_from_bcd(&msf); - // Seek to that address and read sector - if (psx_disc_seek(cdrom->disc, msf)) + if (psx_disc_seek(cdrom->disc, cdrom->cdda_msf)) cdrom->cdda_playing = 0; psx_disc_read_sector(cdrom->disc, cdrom->cdda_buf); @@ -1977,11 +2166,7 @@ void psx_cdrom_get_cdda_samples(psx_cdrom_t* cdrom, void* buf, int size, psx_spu ++cdrom->cdda_sectors_played; // Increment sector - msf_add_f(&msf, 1); - msf_to_bcd(&msf); - - // Assign to CDDA MSF - cdrom->cdda_msf = msf; + msf_add_f(&cdrom->cdda_msf, 1); memcpy(buf, cdrom->cdda_buf, size); diff --git a/psx/dev/cdrom.h b/psx/dev/cdrom.h index 3aaa514..9dd18a9 100644 --- a/psx/dev/cdrom.h +++ b/psx/dev/cdrom.h @@ -58,7 +58,8 @@ enum { #define CDL_RESET 0x1c #define CDL_GETQ 0x1d #define CDL_READTOC 0x1e -#define CDL_ERROR 0x1f +#define CDL_VIDEOCD 0x1f +#define CDL_ERROR 0x20 #define STAT_INDEX_MASK 0x3 #define STAT_ADPBUSY_MASK 0x4 @@ -178,7 +179,7 @@ typedef struct { int tray_open; // Setloc - uint8_t seek_ss, seek_mm, seek_ff; + msf_t seek_msf; uint32_t seek_offset; int seek_pending; @@ -195,7 +196,7 @@ typedef struct { int spin_delay; uint8_t error; uint8_t error_flags; - int read_ongoing; + int ongoing_read_command; int gettd_track; // CDDA @@ -318,5 +319,6 @@ void cdrom_cmd_test(psx_cdrom_t*); void cdrom_cmd_getid(psx_cdrom_t*); void cdrom_cmd_reads(psx_cdrom_t*); void cdrom_cmd_readtoc(psx_cdrom_t*); +void cdrom_cmd_videocd(psx_cdrom_t*); #endif \ No newline at end of file diff --git a/psx/dev/dma.c b/psx/dev/dma.c index 50f10ec..8e6474d 100644 --- a/psx/dev/dma.c +++ b/psx/dev/dma.c @@ -165,19 +165,28 @@ void psx_dma_do_mdec_in(psx_dma_t* dma) { if (!CHCR_BUSY(mdec_in)) return; + // printf("dma mdec in size=%04x bcnt=%04x step=%u madr=%08x\n", + // BCR_SIZE(mdec_in), + // BCR_BCNT(mdec_in), + // CHCR_STEP(mdec_in), + // dma->mdec_in.madr + // ); + size_t size = BCR_SIZE(mdec_in) * BCR_BCNT(mdec_in); + int step = CHCR_STEP(mdec_in) ? -4 : 4; + for (int i = 0; i < size; i++) { uint32_t data = psx_bus_read32(dma->bus, dma->mdec_in.madr); psx_bus_write32(dma->bus, 0x1f801820, data); - dma->mdec_in.madr += CHCR_STEP(mdec_in) ? -4 : 4; + dma->mdec_in.madr += step; } dma->mdec_in_irq_delay = size; - dma->mdec_in.chcr &= ~(CHCR_BUSY_MASK | CHCR_TRIG_MASK); + dma->mdec_in.chcr = 0; dma->mdec_in.bcr = 0; } @@ -185,6 +194,15 @@ void psx_dma_do_mdec_out(psx_dma_t* dma) { if (!CHCR_BUSY(mdec_out)) return; + // printf("dma mdec out size=%04x bcnt=%04x step=%u madr=%08x\n", + // BCR_SIZE(mdec_out), + // BCR_BCNT(mdec_out), + // CHCR_STEP(mdec_out), + // dma->mdec_out.madr + // ); + + // printf("mdec out transfer\n"); + size_t size = BCR_SIZE(mdec_out) * BCR_BCNT(mdec_out); for (int i = 0; i < size; i++) { @@ -293,8 +311,7 @@ void psx_dma_do_cdrom(psx_dma_t* dma) { if (!CHCR_BUSY(cdrom)) return; - // log_set_quiet(0); - // log_fatal("CDROM DMA transfer: madr=%08x, dir=%s, sync=%s (%u), step=%s, size=%x", + // printf("CDROM DMA transfer: madr=%08x, dir=%s, sync=%s (%u), step=%s, size=%x\n", // dma->cdrom.madr, // CHCR_TDIR(cdrom) ? "to device" : "to RAM", // g_psx_dma_sync_type_name_table[CHCR_SYNC(cdrom)], CHCR_SYNC(cdrom), @@ -302,13 +319,12 @@ void psx_dma_do_cdrom(psx_dma_t* dma) { // BCR_SIZE(cdrom) // ); - // log_fatal("DICR: force=%u, en=%02x, irqen=%u, flags=%02x", + // printf("DICR: force=%u, en=%02x, irqen=%u, flags=%02x\n", // (dma->dicr >> 15) & 1, // (dma->dicr >> 16) & 0x7f, // (dma->dicr >> 23) & 1, // (dma->dicr >> 24) & 0x7f // ); - // log_set_quiet(1); uint32_t size = BCR_SIZE(cdrom); diff --git a/psx/dev/exp1.c b/psx/dev/exp1.c index 4921063..789d4f5 100644 --- a/psx/dev/exp1.c +++ b/psx/dev/exp1.c @@ -9,7 +9,7 @@ psx_exp1_t* psx_exp1_create() { return (psx_exp1_t*)malloc(sizeof(psx_exp1_t)); } -void psx_exp1_init(psx_exp1_t* exp1, psx_mc1_t* mc1) { +void psx_exp1_init(psx_exp1_t* exp1, psx_mc1_t* mc1, const char* path) { memset(exp1, 0, sizeof(psx_exp1_t)); exp1->io_base = PSX_EXP1_BEGIN; @@ -19,6 +19,23 @@ void psx_exp1_init(psx_exp1_t* exp1, psx_mc1_t* mc1) { exp1->rom = (uint8_t*)malloc(PSX_EXP1_SIZE); memset(exp1->rom, 0xff, PSX_EXP1_SIZE); + + if (path) + psx_exp1_load(exp1, path); +} + +void psx_exp1_load(psx_exp1_t* exp1, const char* path) { + FILE* file = fopen(path, "rb"); + + if (!file) { + perror("Error opening expansion ROM file \'%s\'"); + + exit(1); + } + + fread(exp1->rom, 1, PSX_EXP1_SIZE, file); + + fclose(file); } uint32_t psx_exp1_read32(psx_exp1_t* exp1, uint32_t offset) { diff --git a/psx/dev/exp1.h b/psx/dev/exp1.h index 64c2411..99aa4de 100644 --- a/psx/dev/exp1.h +++ b/psx/dev/exp1.h @@ -18,7 +18,8 @@ typedef struct { } psx_exp1_t; psx_exp1_t* psx_exp1_create(); -void psx_exp1_init(psx_exp1_t*, psx_mc1_t*); +void psx_exp1_init(psx_exp1_t*, psx_mc1_t*, const char*); +void psx_exp1_load(psx_exp1_t*, const char*); uint32_t psx_exp1_read32(psx_exp1_t*, uint32_t); uint16_t psx_exp1_read16(psx_exp1_t*, uint32_t); uint8_t psx_exp1_read8(psx_exp1_t*, uint32_t); diff --git a/psx/dev/exp2.c b/psx/dev/exp2.c new file mode 100644 index 0000000..c92b47c --- /dev/null +++ b/psx/dev/exp2.c @@ -0,0 +1,80 @@ +#include +#include +#include + +#include "../log.h" +#include "exp2.h" + +psx_exp2_t* psx_exp2_create() { + return (psx_exp2_t*)malloc(sizeof(psx_exp2_t)); +} + +void psx_exp2_init(psx_exp2_t* exp2, exp2_tty_tx atcons_tx, exp2_tty_tx duart_tx) { + memset(exp2, 0, sizeof(psx_exp2_t)); + + exp2->io_base = PSX_EXP2_BEGIN; + exp2->io_size = PSX_EXP2_SIZE; + exp2->atcons_tx = atcons_tx; + exp2->duart_tx = duart_tx; +} + +void psx_exp2_atcons_put(psx_exp2_t* exp2, char c) { + exp2->atc_stat |= 0x10; + exp2->atc_rx = c; +} + +void psx_exp2_duart_put(psx_exp2_t* exp2, char c) { + /* To-do */ +} + +uint32_t psx_exp2_read32(psx_exp2_t* exp2, uint32_t offset) { + return 0; +} + +uint16_t psx_exp2_read16(psx_exp2_t* exp2, uint32_t offset) { + return 0; +} + +uint8_t psx_exp2_read8(psx_exp2_t* exp2, uint32_t offset) { + switch (offset) { + case EXP2_DTL_ATC_STAT: + return exp2->atc_stat | 8; + + case EXP2_DTL_ATC_DATA: + exp2->atc_stat &= 0xef; + return exp2->atc_rx; + } + + return 0; +} + +void psx_exp2_write32(psx_exp2_t* exp2, uint32_t offset, uint32_t value) { + log_warn("Unhandled 32-bit EXP2 write at offset %08x (%08x)", offset, value); +} + +void psx_exp2_write16(psx_exp2_t* exp2, uint32_t offset, uint16_t value) { + log_warn("Unhandled 16-bit EXP2 write at offset %08x (%04x)", offset, value); +} + +void psx_exp2_write8(psx_exp2_t* exp2, uint32_t offset, uint8_t value) { + switch (offset) { + case EXP2_DTL_ATC_DATA: + if (exp2->atcons_tx) + exp2->atcons_tx(exp2->atcons_udata, value); + return; + break; + + case EXP2_LED: + case EXP2_POST: + case EXP2_POST2: + // To-do: Do something with this data + return; + break; + } + + log_warn("Unhandled 8-bit EXP2 write at offset %08x (%02x)", offset, value); +} + +void psx_exp2_destroy(psx_exp2_t* exp2) { + free(exp2); +} \ No newline at end of file diff --git a/psx/dev/exp2.h b/psx/dev/exp2.h new file mode 100644 index 0000000..86bbe36 --- /dev/null +++ b/psx/dev/exp2.h @@ -0,0 +1,48 @@ +#ifndef EXP2_H +#define EXP2_H + +#include + +#define PSX_EXP2_BEGIN 0x1f802000 +#define PSX_EXP2_SIZE 0x1fe000 +#define PSX_EXP2_END 0x1f9fffff + +#define EXP2_DTL_ATC_STAT 0x00 // 1f802000 +#define EXP2_DTL_ATC_DATA 0x02 // 1f802002 +#define EXP2_DTL_HDATA 0x04 // 1f802004 +#define EXP2_DTL_SEC_IRQ10 0x30 // 1f802030 +#define EXP2_DTL_IRQ_CTRL 0x32 // 1f802032 +#define EXP2_DTL_BOOT_DIP 0x40 // 1f802040 +#define EXP2_POST 0x41 // 1f802041 +#define EXP2_LED 0x42 // 1f802042 +#define EXP2_POST2 0x70 // 1f802070 + +typedef void (*exp2_tty_tx)(void*, uint8_t); + +typedef struct { + uint32_t bus_delay; + uint32_t io_base, io_size; + + void* duart_udata; + void* atcons_udata; + + exp2_tty_tx duart_tx; + exp2_tty_tx atcons_tx; + + uint8_t atc_stat; + uint8_t atc_rx; +} psx_exp2_t; + +psx_exp2_t* psx_exp2_create(); +void psx_exp2_init(psx_exp2_t*, exp2_tty_tx atcons_tx, exp2_tty_tx duart_tx); +void psx_exp2_atcons_put(psx_exp2_t*, char); +void psx_exp2_duart_put(psx_exp2_t*, char); +uint32_t psx_exp2_read32(psx_exp2_t*, uint32_t); +uint16_t psx_exp2_read16(psx_exp2_t*, uint32_t); +uint8_t psx_exp2_read8(psx_exp2_t*, uint32_t); +void psx_exp2_write32(psx_exp2_t*, uint32_t, uint32_t); +void psx_exp2_write16(psx_exp2_t*, uint32_t, uint16_t); +void psx_exp2_write8(psx_exp2_t*, uint32_t, uint8_t); +void psx_exp2_destroy(psx_exp2_t*); + +#endif \ No newline at end of file diff --git a/psx/dev/gpu.c b/psx/dev/gpu.c index ac853c7..87d25e8 100644 --- a/psx/dev/gpu.c +++ b/psx/dev/gpu.c @@ -1683,6 +1683,8 @@ void psx_gpu_set_udata(psx_gpu_t* gpu, int index, void* udata) { void gpu_hblank_event(psx_gpu_t* gpu) { gpu->line++; + psx_ic_irq(gpu->ic, IC_TIMER2); + if (gpu->line < GPU_SCANS_PER_VDRAW_NTSC) { if (gpu->line & 1) { gpu->gpustat |= 1 << 31; @@ -1701,8 +1703,8 @@ void gpu_hblank_event(psx_gpu_t* gpu) { } else if (gpu->line == GPU_SCANS_PER_FRAME_NTSC) { if (gpu->event_cb_table[GPU_EVENT_VBLANK_END]) gpu->event_cb_table[GPU_EVENT_VBLANK_END](gpu); - - // psx_ic_irq(gpu->ic, IC_SPU); + + psx_ic_irq(gpu->ic, IC_SPU); gpu->line = 0; } @@ -1726,6 +1728,9 @@ void psx_gpu_update(psx_gpu_t* gpu, int cyc) { } else if (prev_hblank && !curr_hblank) { if (gpu->event_cb_table[GPU_EVENT_HBLANK_END]) gpu->event_cb_table[GPU_EVENT_HBLANK_END](gpu); + + //psx_ic_irq(gpu->ic, IC_SPU); + // psx_ic_irq(gpu->ic, IC_SPU); gpu->cycles -= (float)GPU_CYCLES_PER_SCANL_NTSC; } diff --git a/psx/dev/mdec.c b/psx/dev/mdec.c index 97eeecb..9ebb24e 100644 --- a/psx/dev/mdec.c +++ b/psx/dev/mdec.c @@ -282,6 +282,13 @@ void psx_mdec_init(psx_mdec_t* mdec) { uint32_t psx_mdec_read32(psx_mdec_t* mdec, uint32_t offset) { switch (offset) { case 0: { + // printf("mdec data read\n"); + // mdec->output_empty = 1; + // mdec->output_index = 0; + // mdec->output_request = 0; + + // return 0xaaaaaaaa; + if (mdec->output_words_remaining) { --mdec->output_words_remaining; @@ -291,6 +298,7 @@ uint32_t psx_mdec_read32(psx_mdec_t* mdec, uint32_t offset) { return ((uint32_t*)mdec->output)[mdec->output_index++]; } else { + // printf("no read words remaining\n"); mdec->output_empty = 0; mdec->output_index = 0; mdec->output_request = 0; @@ -299,6 +307,7 @@ uint32_t psx_mdec_read32(psx_mdec_t* mdec, uint32_t offset) { } } break; case 4: { + //printf("mdec status read\n"); uint32_t status = 0; status |= mdec->words_remaining; @@ -334,12 +343,14 @@ uint8_t psx_mdec_read8(psx_mdec_t* mdec, uint32_t offset) { void psx_mdec_write32(psx_mdec_t* mdec, uint32_t offset, uint32_t value) { switch (offset) { case 0: { + //printf("mdec data write\n"); if (mdec->words_remaining) { mdec->input[mdec->input_index++] = value; --mdec->words_remaining; if (!mdec->words_remaining) { + //printf("no words remaining\n"); mdec->output_empty = 0; mdec->input_full = 1; mdec->input_request = 0; @@ -367,6 +378,7 @@ void psx_mdec_write32(psx_mdec_t* mdec, uint32_t offset, uint32_t value) { //log_set_quiet(0); switch (mdec->cmd >> 29) { case MDEC_CMD_NOP: { + //printf("mdec nop\n"); mdec->busy = 0; mdec->words_remaining = 0; @@ -374,15 +386,17 @@ void psx_mdec_write32(psx_mdec_t* mdec, uint32_t offset, uint32_t value) { } break; case MDEC_CMD_DECODE: { + //printf("mdec decode\n"); mdec->words_remaining = mdec->cmd & 0xffff; - printf("MDEC %08x: decode macroblock %04x\n", - mdec->cmd, - mdec->words_remaining - ); + // printf("MDEC %08x: decode macroblock %04x\n", + // mdec->cmd, + // mdec->words_remaining + // ); } break; case MDEC_CMD_SET_QT: { + //printf("mdec setqt\n"); mdec->recv_color = mdec->cmd & 1; mdec->words_remaining = mdec->recv_color ? 32 : 16; @@ -393,6 +407,7 @@ void psx_mdec_write32(psx_mdec_t* mdec, uint32_t offset, uint32_t value) { } break; case MDEC_CMD_SET_ST: { + //printf("mdec setst\n"); mdec->words_remaining = 32; log_fatal("MDEC %08x: set scale table %04x", @@ -404,7 +419,7 @@ void psx_mdec_write32(psx_mdec_t* mdec, uint32_t offset, uint32_t value) { // log_set_quiet(1); if (mdec->words_remaining) { - mdec->input_request = mdec->enable_dma0; + mdec->input_request = 1; mdec->input_size = mdec->words_remaining * sizeof(uint32_t); mdec->input_full = 0; mdec->input_index = 0; @@ -413,6 +428,7 @@ void psx_mdec_write32(psx_mdec_t* mdec, uint32_t offset, uint32_t value) { } break; case 4: { + //printf("mdec status write\n"); mdec->enable_dma0 = (value & 0x40000000) != 0; mdec->enable_dma1 = (value & 0x20000000) != 0; diff --git a/psx/dev/old/cdrom.c b/psx/dev/old/cdrom.c index 7af01de..0e9fd8a 100644 --- a/psx/dev/old/cdrom.c +++ b/psx/dev/old/cdrom.c @@ -93,9 +93,9 @@ void cdrom_cmd_getstat(psx_cdrom_t* cdrom) { SET_BITS(ifr, IFR_INT, IFR_INT3); RESP_PUSH(GETSTAT_MOTOR | (cdrom->disc ? 0 : GETSTAT_TRAYOPEN)); - if (cdrom->read_ongoing) { + if (cdrom->ongoing_read_command) { cdrom->state = CD_STATE_SEND_RESP2; - cdrom->delayed_command = CDL_READN; + cdrom->delayed_command = cdrom->ongoing_read_command; cdrom->irq_delay = DELAY_1MS; } else { cdrom->delayed_command = CDL_NONE; @@ -121,13 +121,13 @@ void cdrom_cmd_setloc(psx_cdrom_t* cdrom) { return; } - if (!cdrom->read_ongoing) { + if (!cdrom->ongoing_read_command) { cdrom->irq_delay = DELAY_1MS; cdrom->delayed_command = CDL_SETLOC; cdrom->state = CD_STATE_SEND_RESP1; } else { cdrom->irq_delay = DELAY_1MS; - cdrom->delayed_command = CDL_READN; + cdrom->delayed_command = cdrom->ongoing_read_command; cdrom->state = CD_STATE_SEND_RESP2; } @@ -174,7 +174,7 @@ void cdrom_cmd_setloc(psx_cdrom_t* cdrom) { int m = PFIFO_POP; if (!(VALID_BCD(m) && VALID_BCD(s) && VALID_BCD(f) && (f < 0x75))) { - cdrom->read_ongoing = false; + cdrom->ongoing_read_command = CDL_NONE; cdrom->irq_delay = DELAY_1MS; cdrom->delayed_command = CDL_ERROR; cdrom->state = CD_STATE_ERROR; @@ -257,7 +257,7 @@ void cdrom_cmd_play(psx_cdrom_t* cdrom) { } void cdrom_cmd_readn(psx_cdrom_t* cdrom) { cdrom->delayed_command = CDL_NONE; - cdrom->read_ongoing = 1; + cdrom->ongoing_read_command = 1; switch (cdrom->state) { case CD_STATE_RECV_CMD: { @@ -396,7 +396,7 @@ void cdrom_cmd_motoron(psx_cdrom_t* cdrom) { switch (cdrom->state) { case CD_STATE_RECV_CMD: { - cdrom->read_ongoing = 0; + cdrom->ongoing_read_command = CDL_NONE; cdrom->cdda_playing = 0; cdrom->irq_delay = DELAY_1MS; @@ -429,7 +429,7 @@ void cdrom_cmd_stop(psx_cdrom_t* cdrom) { switch (cdrom->state) { case CD_STATE_RECV_CMD: { - cdrom->read_ongoing = 0; + cdrom->ongoing_read_command = CDL_NONE; cdrom->cdda_playing = 0; cdrom->irq_delay = DELAY_1MS; @@ -468,7 +468,7 @@ void cdrom_cmd_pause(psx_cdrom_t* cdrom) { switch (cdrom->state) { case CD_STATE_RECV_CMD: { - cdrom->read_ongoing = 0; + cdrom->ongoing_read_command = CDL_NONE; cdrom->cdda_playing = 0; cdrom->irq_delay = DELAY_1MS; @@ -504,7 +504,7 @@ void cdrom_cmd_init(psx_cdrom_t* cdrom) { cdrom->irq_delay = DELAY_1MS; cdrom->state = CD_STATE_SEND_RESP1; cdrom->delayed_command = CDL_INIT; - cdrom->read_ongoing = 0; + cdrom->ongoing_read_command = CDL_NONE; cdrom->mode = 0; cdrom->dfifo_index = 0; cdrom->dfifo_full = 0; @@ -965,7 +965,7 @@ void cdrom_cmd_getid(psx_cdrom_t* cdrom) { } void cdrom_cmd_reads(psx_cdrom_t* cdrom) { cdrom->delayed_command = CDL_NONE; - cdrom->read_ongoing = 1; + cdrom->ongoing_read_command = 1; switch (cdrom->state) { case CD_STATE_RECV_CMD: { diff --git a/psx/dev/timer.c b/psx/dev/timer.c index 7f3e0a9..624c977 100644 --- a/psx/dev/timer.c +++ b/psx/dev/timer.c @@ -26,6 +26,32 @@ #define T2_PAUSED timer->timer[2].paused #define T2_IRQ_FIRED timer->timer[2].irq_fired +// bool should_I_pause_the_timer(psx_timer_t* timer) { +// if ((timer->mode & 1) == 0) return false; +// switch ((timer->mode >> 1) & 3) { +// case 0: return gpu.isXblank(); +// case 1: return false; +// case 2: return !gpu.isXblank(); +// case 3: return gpu.gotXblankOnce(); +// } +// } + +// bool did_timer_reach_target(Timer timer) { +// if ((timer.mode & 8) == 1) return timer.value >= timer.target; +// return timer.value >= 0xffff; +// } + +// bool should_I_reset_the_timer(Timer timer) { +// if (did_timer_reach_target(timer)) return true; +// if ((timer.mode & 1) == 0) return false; +// switch ((timer.mode >> 1) & 3) { +// case 1: +// case 2: +// return gpu.isXBlank(); +// } +// return false; +// } + const char* g_psx_timer_reg_names[] = { "counter", 0, 0, 0, "mode", 0, 0, 0, @@ -45,12 +71,16 @@ void psx_timer_init(psx_timer_t* timer, psx_ic_t* ic) { timer->ic = ic; } +int t1_counter = 0; + uint32_t psx_timer_read32(psx_timer_t* timer, uint32_t offset) { int index = offset >> 4; int reg = offset & 0xf; switch (reg) { - case 0: return timer->timer[index].counter; + case 0: { + return timer->timer[index].counter; + } break; case 4: { timer->timer[index].mode &= 0xffffe7ff; diff --git a/psx/disc/cue.c b/psx/disc/cue.c index e18586a..05aa27d 100644 --- a/psx/disc/cue.c +++ b/psx/disc/cue.c @@ -444,21 +444,23 @@ int psxd_cue_get_track_addr(void* udata, msf_t* msf, int track) { track = BTOI(track); + if (track > cue->num_tracks) + return DISC_ERR_TRACK_OUT_OF_BOUNDS; + if (!msf) return 0; if (!track) { msf->m = cue->end.m; msf->s = cue->end.s; + msf->f = 0; return 0; } - if (track > cue->num_tracks) - return DISC_ERR_TRACK_OUT_OF_BOUNDS; - msf->m = cue->track[track - 1]->disc_offset.m; msf->s = cue->track[track - 1]->disc_offset.s; + msf->f = 0; return 0; } diff --git a/psx/msf.c b/psx/msf.c index 9f5176a..6435f89 100644 --- a/psx/msf.c +++ b/psx/msf.c @@ -31,6 +31,24 @@ void msf_adjust(msf_t* msf) { } } +void msf_adjust_sub(msf_t* msf) { + if ((int)msf->f < 0) { + int f = ((int)msf->f) * -1; + int s = (f / 60) + 1; + + msf->s -= s; + msf->f += CD_SECTORS_PS * f; + } + + if ((int)msf->s < 0) { + int s = ((int)msf->s) * -1; + int m = (s / 60) + 1; + + msf->m -= m; + msf->s += 60 * m; + } +} + void msf_to_bcd(msf_t* msf) { msf->m = ITOB(msf->m); msf->s = ITOB(msf->s); diff --git a/psx/msf.h b/psx/msf.h index e210c69..950531c 100644 --- a/psx/msf.h +++ b/psx/msf.h @@ -89,6 +89,7 @@ typedef struct { void msf_copy(msf_t*, msf_t); void msf_adjust(msf_t*); +void msf_adjust_sub(msf_t*); void msf_to_bcd(msf_t*); void msf_from_bcd(msf_t*); uint32_t msf_to_address(msf_t); diff --git a/psx/psx.c b/psx/psx.c index 8eed4f0..c996103 100644 --- a/psx/psx.c +++ b/psx/psx.c @@ -108,13 +108,18 @@ double psx_get_display_aspect(psx_t* psx) { return aspect; } -void psx_init(psx_t* psx, const char* bios_path) { +void atcons_tx(void* udata, char c) { + putchar(c); +} + +void psx_init(psx_t* psx, const char* bios_path, const char* exp_path) { memset(psx, 0, sizeof(psx_t)); psx->bios = psx_bios_create(); psx->ram = psx_ram_create(); psx->dma = psx_dma_create(); psx->exp1 = psx_exp1_create(); + psx->exp2 = psx_exp2_create(); psx->mc1 = psx_mc1_create(); psx->mc2 = psx_mc2_create(); psx->mc3 = psx_mc3_create(); @@ -135,6 +140,7 @@ void psx_init(psx_t* psx, const char* bios_path) { psx_bus_init_ram(psx->bus, psx->ram); psx_bus_init_dma(psx->bus, psx->dma); psx_bus_init_exp1(psx->bus, psx->exp1); + psx_bus_init_exp2(psx->bus, psx->exp2); psx_bus_init_mc1(psx->bus, psx->mc1); psx_bus_init_mc2(psx->bus, psx->mc2); psx_bus_init_mc3(psx->bus, psx->mc3); @@ -155,7 +161,8 @@ void psx_init(psx_t* psx, const char* bios_path) { psx_mc3_init(psx->mc3); psx_ram_init(psx->ram, psx->mc2); psx_dma_init(psx->dma, psx->bus, psx->ic); - psx_exp1_init(psx->exp1, psx->mc1); + psx_exp1_init(psx->exp1, psx->mc1, exp_path); + psx_exp2_init(psx->exp2, atcons_tx, NULL); psx_ic_init(psx->ic, psx->cpu); psx_scratchpad_init(psx->scratchpad); psx_gpu_init(psx->gpu, psx->ic); @@ -167,6 +174,10 @@ void psx_init(psx_t* psx, const char* bios_path) { psx_cpu_init(psx->cpu, psx->bus); } +void psx_load_expansion(psx_t* psx, const char* path) { + psx_exp1_init(psx->exp1, psx->mc1, path); +} + void psx_hard_reset(psx_t* psx) { log_fatal("Hard reset not yet implemented"); @@ -231,6 +242,10 @@ psx_exp1_t* psx_get_exp1(psx_t* psx) { return psx->exp1; } +psx_exp2_t* psx_get_exp2(psx_t* psx) { + return psx->exp2; +} + psx_mc1_t* psx_get_mc1(psx_t* psx) { return psx->mc1; } diff --git a/psx/psx.h b/psx/psx.h index 8f04681..3f37a81 100644 --- a/psx/psx.h +++ b/psx/psx.h @@ -12,6 +12,7 @@ typedef struct { psx_ram_t* ram; psx_dma_t* dma; psx_exp1_t* exp1; + psx_exp2_t* exp2; psx_mc1_t* mc1; psx_mc2_t* mc2; psx_mc3_t* mc3; @@ -28,7 +29,8 @@ typedef struct { } psx_t; psx_t* psx_create(); -void psx_init(psx_t*, const char*); +void psx_init(psx_t*, const char*, const char*); +void psx_load_expansion(psx_t*, const char*); void psx_load_bios(psx_t*, const char*); void psx_hard_reset(psx_t*); void psx_soft_reset(psx_t*); @@ -51,6 +53,7 @@ psx_bios_t* psx_get_bios(psx_t*); psx_ram_t* psx_get_ram(psx_t*); psx_dma_t* psx_get_dma(psx_t*); psx_exp1_t* psx_get_exp1(psx_t*); +psx_exp2_t* psx_get_exp2(psx_t*); psx_mc1_t* psx_get_mc1(psx_t*); psx_mc2_t* psx_get_mc2(psx_t*); psx_mc3_t* psx_get_mc3(psx_t*); diff --git a/working.txt b/working.txt new file mode 100644 index 0000000..b7c08b4 --- /dev/null +++ b/working.txt @@ -0,0 +1,11 @@ +Atari Anniversary Edition Redux (USA) +Harmful Park (Japan) +Kyuiin (Japan) +NASCAR 98 Collector''s Edition (USA) +Panzer Bandit (Japan) +Puzzle Bobble 4 (Japan) +World Soccer Jikkyou Winning Eleven 3 - World Cup France '98 (Japan) (Taikenban) +Worms (USA) +San Francisco Rush - Extreme Racing (USA) +Samurai Shodown III - Blades of Blood (USA) +Time Crisis - Project Titan (USA) \ No newline at end of file