X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fpsxbios.c;h=a41cf54ec6b211b9d0b8c1b8382c5e47c1403d56;hb=46fe949677745250de387994657de2004fe3b29b;hp=c5a439deff362cea8ae48ef6b9aeab43c7b8ad0b;hpb=0a50313e5c9a6470e37e1dab99022eb481b6b5f7;p=pcsx_rearmed.git diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index c5a439de..a41cf54e 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (C) 2019 Ryan Schultz, PCSX-df Team, PCSX team, gameblabla, * - * dmitrysmagin, senquack * + * dmitrysmagin, senquack * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -38,10 +38,6 @@ #include "psxinterpreter.h" #include -#if (defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__) -#pragma GCC diagnostic ignored "-Wpointer-sign" -#endif - #ifndef PSXBIOS_LOG //#define PSXBIOS_LOG printf #define PSXBIOS_LOG(...) @@ -296,8 +292,10 @@ static u32 floodchk; #define A_HEAP_BASE 0x9000 #define A_HEAP_SIZE 0x9004 #define A_HEAP_END 0x9008 -#define A_HEAP_FLAG 0x900c +#define A_HEAP_INIT_FLG 0x900c #define A_RND_SEED 0x9010 +#define A_HEAP_FRSTCHNK 0xb060 +#define A_HEAP_CURCHNK 0xb064 #define A_CONF_TCB 0xb940 #define A_CONF_EvCB 0xb944 #define A_CONF_SP 0xb948 @@ -1218,114 +1216,98 @@ void psxBios_qsort() { // 0x31 pc0 = ra; } -// this isn't how the real bios works, but maybe good enough +static int malloc_heap_grow(u32 size) { + u32 heap_addr, heap_end, heap_addr_new; + + heap_addr = loadRam32(A_HEAP_BASE); + heap_end = loadRam32(A_HEAP_END); + heap_addr_new = heap_addr + 4 + size; + if (heap_addr_new >= heap_end) + return -1; + storeRam32(A_HEAP_BASE, heap_addr_new); + storeRam32(heap_addr - 4, size | 1); + storeRam32(heap_addr + size, ~1); // terminator + return 0; +} + static void psxBios_malloc() { // 0x33 - u32 *heap_addr, *heap_end; - u32 *chunk, *newchunk = NULL; - unsigned int dsize = 0, csize, cstat; - int colflag; - PSXBIOS_LOG("psxBios_%s %x\n", biosA0n[0x33], a0); - heap_addr = loadRam32ptr(A_HEAP_BASE); - heap_end = loadRam32ptr(A_HEAP_END); - if (heap_addr >= heap_end) { - v0 = 0; - pc0 = ra; - return; - } + u32 size = (a0 + 3) & ~3; + u32 limit = 32*1024; + u32 tries = 2, i; + u32 ret; - // scan through heap and combine free chunks of space - chunk = heap_addr; - colflag = 0; - while(chunk < heap_end) { - // get size and status of actual chunk - csize = ((u32)*chunk) & 0xfffffffc; - cstat = ((u32)*chunk) & 1; - - // most probably broken heap descriptor - // this fixes Burning Road - if (*chunk == 0) { - newchunk = chunk; - dsize = ((uptr)heap_end - (uptr)chunk) - 4; - colflag = 1; - break; + PSXBIOS_LOG("psxBios_%s %d\n", biosA0n[0x33], a0); + + if (!loadRam32(A_HEAP_INIT_FLG)) { + u32 heap_addr = loadRam32(A_HEAP_BASE); + storeRam32(heap_addr, ~1); + storeRam32(A_HEAP_FRSTCHNK, heap_addr); + storeRam32(A_HEAP_CURCHNK, heap_addr); + storeRam32(A_HEAP_BASE, heap_addr + 4); + if (malloc_heap_grow(size)) { + PSXBIOS_LOG("malloc: init OOM\n"); + mips_return_c(0, 20); + return; } + storeRam32(A_HEAP_INIT_FLG, 1); + } - // it's a free chunk - if(cstat == 1) { - if(colflag == 0) { - newchunk = chunk; - dsize = csize; - colflag = 1; // let's begin a new collection of free memory + for (i = 0; tries > 0 && i < limit; i++) + { + u32 chunk = loadRam32(A_HEAP_CURCHNK); + u32 chunk_hdr = loadRam32(chunk); + u32 next_chunk = chunk + 4 + (chunk_hdr & ~3); + u32 next_chunk_hdr = loadRam32(next_chunk); + use_cycles(20); + //printf(" c %08x %08x\n", chunk, chunk_hdr); + if (chunk_hdr & 1) { + // free chunk + if (chunk_hdr > (size | 1)) { + // split + u32 p2size = (chunk_hdr & ~3) - size - 4; + storeRam32(chunk + 4 + size, p2size | 1); + chunk_hdr = size | 1; } - else dsize += (csize+4); // add the new size including header + if (chunk_hdr == (size | 1)) { + storeRam32(chunk, size); + break; + } + // chunk too small + if (next_chunk_hdr & 1) { + // merge + u32 msize = (chunk_hdr & ~3) + 4 + (next_chunk_hdr & ~3); + storeRam32(chunk, msize | 1); + continue; + } + } + if (chunk_hdr == ~1) { + // last chunk + if (tries == 2) + storeRam32(A_HEAP_CURCHNK, loadRam32(A_HEAP_FRSTCHNK)); + tries--; } - // not a free chunk: did we start a collection ? else { - if(colflag == 1) { // collection is over - colflag = 0; - *newchunk = SWAP32(dsize | 1); - } + // go to the next chunk + storeRam32(A_HEAP_CURCHNK, next_chunk); } - - // next chunk - chunk = (u32*)((uptr)chunk + csize + 4); } - // if neccessary free memory on end of heap - if (colflag == 1) - *newchunk = SWAP32(dsize | 1); - - chunk = heap_addr; - csize = ((u32)*chunk) & 0xfffffffc; - cstat = ((u32)*chunk) & 1; - dsize = (a0 + 3) & 0xfffffffc; - // exit on uninitialized heap - if (chunk == NULL) { - printf("malloc %x,%x: Uninitialized Heap!\n", v0, a0); - v0 = 0; - pc0 = ra; - return; + if (i == limit) + ret = 0; + else if (tries == 0 && malloc_heap_grow(size)) + ret = 0; + else { + u32 chunk = loadRam32(A_HEAP_CURCHNK); + storeRam32(chunk, loadRam32(chunk) & ~3); + ret = chunk + 4; } - // search an unused chunk that is big enough until the end of the heap - while ((dsize > csize || cstat==0) && chunk < heap_end ) { - chunk = (u32*)((uptr)chunk + csize + 4); - - // catch out of memory - if(chunk >= heap_end) { - printf("malloc %x,%x: Out of memory error!\n", - v0, a0); - v0 = 0; pc0 = ra; - return; - } - - csize = ((u32)*chunk) & 0xfffffffc; - cstat = ((u32)*chunk) & 1; - } - - // allocate memory - if(dsize == csize) { - // chunk has same size - *chunk &= 0xfffffffc; - } else if (dsize > csize) { - v0 = 0; pc0 = ra; - return; - } else { - // split free chunk - *chunk = SWAP32(dsize); - newchunk = (u32*)((uptr)chunk + dsize + 4); - *newchunk = SWAP32(((csize - dsize - 4) & 0xfffffffc) | 1); - } - - // return pointer to allocated memory - v0 = ((uptr)chunk - (uptr)psxM) + 4; - v0|= 0x80000000; - //printf ("malloc %x,%x\n", v0, a0); - pc0 = ra; + PSXBIOS_LOG(" -> %08x\n", ret); + mips_return_c(ret, 40); } static void psxBios_free() { // 0x34 - PSXBIOS_LOG("psxBios_%s %x (%x bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4)); + PSXBIOS_LOG("psxBios_%s %x (%d bytes)\n", biosA0n[0x34], a0, loadRam32(a0 - 4)); storeRam32(a0 - 4, loadRam32(a0 - 4) | 1); // set chunk to free mips_return_void_c(5); } @@ -1380,7 +1362,7 @@ static void psxBios_InitHeap() { // 0x39 storeRam32(A_HEAP_BASE, a0); storeRam32(A_HEAP_SIZE, a1); storeRam32(A_HEAP_END, a0 + (a1 & ~3) + 4); - storeRam32(A_HEAP_FLAG, 0); + storeRam32(A_HEAP_INIT_FLG, 0); storeRam32(a0, 0); mips_return_void_c(14); @@ -2596,7 +2578,7 @@ static void bufile(const u8 *mcd_data, u32 dir_) { } for (; nfile <= 15; nfile++, blocks++) { const u8 *data2 = mcd_data + 128 * nfile; - const char *name = data2 + 0x0a; + const char *name = (const char *)data2 + 0x0a; if ((data2[0] & 0xF0) != 0x50 || name[0]) break; } @@ -2629,11 +2611,11 @@ static void psxBios_firstfile() { // 42 if (!strncmp(pa0, "bu00", 4)) { // firstfile() calls _card_read() internally, so deliver it's event DeliverEvent(0xf0000011, 0x0004); - bufile(Mcd1Data, a1); + bufile((u8 *)Mcd1Data, a1); } else if (!strncmp(pa0, "bu10", 4)) { // firstfile() calls _card_read() internally, so deliver it's event DeliverEvent(0xf0000011, 0x0004); - bufile(Mcd2Data, a1); + bufile((u8 *)Mcd2Data, a1); } } @@ -2649,9 +2631,9 @@ void psxBios_nextfile() { // 43 v0 = 0; if (!strncmp(ffile, "bu00", 4)) - bufile(Mcd1Data, a0); + bufile((u8 *)Mcd1Data, a0); else if (!strncmp(ffile, "bu10", 4)) - bufile(Mcd2Data, a0); + bufile((u8 *)Mcd2Data, a0); pc0 = ra; } @@ -3316,6 +3298,7 @@ void psxBiosSetupBootState(void) void psxBiosInit() { u32 *ptr, *ram32, *rom32; + char *romc; int i; uLongf len; @@ -3656,10 +3639,11 @@ void psxBiosInit() { rom32 = (u32 *)psxR; rom32[0x100/4] = SWAP32(0x19951204); rom32[0x104/4] = SWAP32(3); - strcpy(psxR + 0x108, "PCSX authors"); - strcpy(psxR + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo - strcpy(psxR + 0x7ff32, "System ROM Version 2.2 12/04/95 A"); - strcpy(psxR + 0x7ff54, "GPL-2.0-or-later"); + romc = (char *)psxR; + strcpy(romc + 0x108, "PCSX authors"); + strcpy(romc + 0x12c, "CEX-3000 PCSX HLE"); // see psxBios_GetSystemInfo + strcpy(romc + 0x7ff32, "System ROM Version 2.2 12/04/95 A"); + strcpy(romc + 0x7ff54, "GPL-2.0-or-later"); // fonts len = 0x80000 - 0x66000; @@ -3774,18 +3758,14 @@ void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) { } #define psxBios_PADpoll(pad) { \ + int i, more_data = 0; \ PAD##pad##_startPoll(pad); \ - pad_buf##pad[0] = 0; \ - pad_buf##pad[1] = PAD##pad##_poll(0x42); \ - if (!(pad_buf##pad[1] & 0x0f)) { \ - bufcount = 32; \ - } else { \ - bufcount = (pad_buf##pad[1] & 0x0f) * 2; \ - } \ - PAD##pad##_poll(0); \ + pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \ + pad_buf##pad[0] = more_data ? 0 : 0xff; \ + PAD##pad##_poll(0, &more_data); \ i = 2; \ - while (bufcount--) { \ - pad_buf##pad[i++] = PAD##pad##_poll(0); \ + while (more_data) { \ + pad_buf##pad[i++] = PAD##pad##_poll(0, &more_data); \ } \ } @@ -3970,7 +3950,6 @@ void hleExcPadCard1(void) if (loadRam32(A_PAD_IRQR_ENA)) { u8 *pad_buf1 = loadRam8ptr(A_PAD_INBUF + 0); u8 *pad_buf2 = loadRam8ptr(A_PAD_INBUF + 4); - int i, bufcount; psxBios_PADpoll(1); psxBios_PADpoll(2);