diff --git a/HISTORY.txt b/HISTORY.txt index 60ab2af..0fad1fd 100644 --- a/HISTORY.txt +++ b/HISTORY.txt @@ -28,7 +28,7 @@ of samples per frame and keeping PSG & FM chips in sync. * added support for some undocumented mode register bits * added proper emulation of HV Counter latch: fixes Sunset Riders intro * added pixel-accurate emulation of mid-line display on/off (Nigel Mansell World Championship PAL, Ren & Stimpy's Invention PAL,...) -* improved 2-cell vscroll emulation accuracy (left-most column in Gynoug, Cutie Suzuki no Ringside Angel, Formula One, Kawasaki Superbike Challenge) +* improved 2-cell vscroll emulation accuracy, as verified on real hardware (Gynoug, Cutie Suzuki no Ringside Angel, Formula One, Kawasaki Superbike Challenge) * improved FIFO timings accuracy: fixes Sol Deace intro * improved sprite masking accuracy (thanks to Nemesis for his test program) * improved sprites processing accuracy: fixes (un)masked sprites in Mickey Mania (3D level), Sonic 2 (VS mode). diff --git a/source/gx/utils/ehcmodule.elf.o b/source/gx/utils/ehcmodule.elf.o deleted file mode 100644 index f88d988..0000000 Binary files a/source/gx/utils/ehcmodule.elf.o and /dev/null differ diff --git a/source/gx/utils/ehcmodule_elf.h b/source/gx/utils/ehcmodule_elf.h deleted file mode 100644 index e2729ca..0000000 --- a/source/gx/utils/ehcmodule_elf.h +++ /dev/null @@ -1,3 +0,0 @@ -extern const u8 ehcmodule_elf_end[]; -extern const u8 ehcmodule_elf[]; -extern const u32 ehcmodule_elf_size; diff --git a/source/gx/utils/mload.c b/source/gx/utils/mload.c deleted file mode 100644 index 2c6f534..0000000 --- a/source/gx/utils/mload.c +++ /dev/null @@ -1,281 +0,0 @@ -/* mload.c (for PPC) (c) 2009, Hermes - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HW_RVL - -#include -#include -#include -#include -#include -#include -#include "unistd.h" -#include "ehcmodule_elf.h" - -#define MLOAD_MLOAD_THREAD_ID 0x4D4C4400 -#define MLOAD_LOAD_MODULE 0x4D4C4480 -#define MLOAD_RUN_MODULE 0x4D4C4481 -#define MLOAD_RUN_THREAD 0x4D4C4482 - -#define MLOAD_STOP_THREAD 0x4D4C4484 -#define MLOAD_CONTINUE_THREAD 0x4D4C4485 - -#define MLOAD_GET_LOAD_BASE 0x4D4C4490 -#define MLOAD_MEMSET 0x4D4C4491 - -#define MLOAD_GET_EHCI_DATA 0x4D4C44A0 - -#define MLOAD_SET_ES_IOCTLV 0x4D4C44B0 - -#define getbe32(x) ((adr[x]<<24) | (adr[x+1]<<16) | (adr[x+2]<<8) | (adr[x+3])) - -typedef struct -{ - u32 ident0; - u32 ident1; - u32 ident2; - u32 ident3; - u32 machinetype; - u32 version; - u32 entry; - u32 phoff; - u32 shoff; - u32 flags; - u16 ehsize; - u16 phentsize; - u16 phnum; - u16 shentsize; - u16 shnum; - u16 shtrndx; -} elfheader; - -typedef struct -{ - u32 type; - u32 offset; - u32 vaddr; - u32 paddr; - u32 filesz; - u32 memsz; - u32 flags; - u32 align; -} elfphentry; - -typedef struct -{ - void *start; - int prio; - void *stack; - int size_stack; -} data_elf; - -static const char mload_fs[] ATTRIBUTE_ALIGN(32) = "/dev/mload"; -static s32 mload_fd = -1; - -// to init/test if the device is running -int mload_init() -{ - int n; - - if (mload_fd >= 0) - return 0; - - for (n = 0; n < 10; n++) // try 2.5 seconds - { - mload_fd = IOS_Open(mload_fs, 0); - - if (mload_fd >= 0) - break; - - usleep(250 * 1000); - } - - return mload_fd; -} - -// to close the device (remember call it when rebooting the IOS!) -int mload_close() -{ - int ret; - - if (mload_fd < 0) - return -1; - - ret = IOS_Close(mload_fd); - - mload_fd = -1; - - return ret; -} - -// fix starlet address to read/write (uses SEEK_SET, etc as mode) -static int mload_seek(int offset, int mode) -{ - if (mload_init() < 0) - return -1; - return IOS_Seek(mload_fd, offset, mode); -} - -// write bytes from starlet (it update the offset) -static int mload_write(const void * buf, u32 size) -{ - if (mload_init() < 0) - return -1; - return IOS_Write(mload_fd, buf, size); -} - -// fill a block (similar to memset) -static int mload_memset(void *starlet_addr, int set, int len) -{ - int ret; - s32 hid = -1; - - if (mload_init() < 0) - return -1; - - hid = iosCreateHeap(0x800); - - if (hid < 0) - return hid; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_MEMSET, "iii:", starlet_addr, - set, len); - - iosDestroyHeap(hid); - - return ret; -} - -// load a module from the PPC -// the module must be a elf made with stripios -static int mload_elf(void *my_elf, data_elf *data_elf) -{ - int n, m; - int p; - u8 *adr; - u32 elf = (u32) my_elf; - - if (elf & 3) - return -1; // aligned to 4 please! - - elfheader *head = (void *) elf; - elfphentry *entries; - - if (head->ident0 != 0x7F454C46) - return -1; - if (head->ident1 != 0x01020161) - return -1; - if (head->ident2 != 0x01000000) - return -1; - - p = head->phoff; - - data_elf->start = (void *) head->entry; - - for (n = 0; n < head->phnum; n++) - { - entries = (void *) (elf + p); - p += sizeof(elfphentry); - - if (entries->type == 4) - { - adr = (void *) (elf + entries->offset); - - if (getbe32(0) != 0) - return -2; // bad info (sure) - - for (m = 4; m < entries->memsz; m += 8) - { - switch (getbe32(m)) - { - case 0x9: - data_elf->start = (void *) getbe32(m+4); - break; - case 0x7D: - data_elf->prio = getbe32(m+4); - break; - case 0x7E: - data_elf->size_stack = getbe32(m+4); - break; - case 0x7F: - data_elf->stack = (void *) (getbe32(m+4)); - break; - - } - } - } - else if (entries->type == 1 && entries->memsz != 0 && entries->vaddr != 0) - { - - if (mload_memset((void *) entries->vaddr, 0, entries->memsz) < 0) - return -1; - if (mload_seek(entries->vaddr, SEEK_SET) < 0) - return -1; - if (mload_write((void *) (elf + entries->offset), entries->filesz) < 0) - return -1; - } - } - - return 0; -} - -// run one thread (you can use to load modules or binary files) -static int mload_run_thread(void *starlet_addr, void *starlet_top_stack, - int stack_size, int priority) -{ - int ret; - s32 hid = -1; - - if (mload_init() < 0) - return -1; - - hid = iosCreateHeap(0x800); - - if (hid < 0) - return hid; - - ret = IOS_IoctlvFormat(hid, mload_fd, MLOAD_RUN_THREAD, "iiii:", - starlet_addr, starlet_top_stack, stack_size, priority); - - iosDestroyHeap(hid); - - return ret; -} - -bool load_ehci_module() -{ - data_elf my_data_elf; - my_data_elf.start = NULL; - my_data_elf.prio = 0; - my_data_elf.stack = NULL; - my_data_elf.size_stack = 0; - - if(mload_elf((void *) ehcmodule_elf, &my_data_elf) != 0) - return false; - - if (mload_run_thread(my_data_elf.start, my_data_elf.stack, - my_data_elf.size_stack, my_data_elf.prio) < 0) - { - usleep(1000); - if (mload_run_thread(my_data_elf.start, my_data_elf.stack, - my_data_elf.size_stack, 0x47) < 0) - return false; - } - return true; -} - -#endif diff --git a/source/gx/utils/mload.h b/source/gx/utils/mload.h deleted file mode 100644 index db6bb5b..0000000 --- a/source/gx/utils/mload.h +++ /dev/null @@ -1,33 +0,0 @@ -/* mload.c (for PPC) (c) 2009, Hermes - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef __MLOAD_H__ -#define __MLOAD_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -int mload_init(); -bool load_ehci_module(); -int mload_close(); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/render.c b/source/render.c index 7d14a1d..84cfb7b 100644 --- a/source/render.c +++ b/source/render.c @@ -1062,6 +1062,7 @@ static void render_bg_vs(int line, int width) /* common data */ uint32 xscroll = get_hscroll(line); + uint32 yscroll = 0; uint32 pf_col_mask = playfield_col_mask; uint32 pf_row_mask = playfield_row_mask; uint32 pf_shift = playfield_shift; @@ -1080,16 +1081,20 @@ static void render_bg_vs(int line, int width) uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask); #endif + /* left-most column v-scrolling when fine h-scrolling value is applied */ + /* Gynoug, Cutie Suzuki no Ringside Angel, Formula One, Kawasaki Superbike Challenge */ + if (reg[12] & 1) + { + /* only in 40-cell mode, verified on MD2 */ + yscroll = vs[19] & (vs[19] >> 16); + yscroll &= 0x3FF; + } + if(shift) { dst = (uint32 *)&buf[0x10 + shift]; -#ifdef LSB_FIRST - v_line = (line + (vs[19] & 0x3FF)) & pf_row_mask; -#else - v_line = (line + ((vs[19] >> 16) & 0x3FF)) & pf_row_mask; -#endif - + v_line = (line + yscroll) & pf_row_mask; nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)]; v_line = (v_line & 7) << 3; @@ -1153,11 +1158,7 @@ static void render_bg_vs(int line, int width) { dst = (uint32 *)&buf[0x10 + shift + (start<<4)]; -#ifdef LSB_FIRST - v_line = (line + ((vs[19] >> 16) & 0x3FF)) & pf_row_mask; -#else - v_line = (line + (vs[19] & 0x3FF)) & pf_row_mask; -#endif + v_line = (line + yscroll) & pf_row_mask; nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)]; v_line = (v_line & 7) << 3; @@ -1335,6 +1336,7 @@ static void render_bg_im2_vs(int line, int width, int odd) /* common data */ uint32 xscroll = get_hscroll(line); + uint32 yscroll = 0; uint32 pf_col_mask = playfield_col_mask; uint32 pf_row_mask = playfield_row_mask; uint32 pf_shift = playfield_shift; @@ -1353,15 +1355,20 @@ static void render_bg_im2_vs(int line, int width, int odd) uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask); #endif + /* left-most column v-scrolling when fine h-scrolling value is applied */ + /* Gynoug, Cutie Suzuki no Ringside Angel, Formula One, Kawasaki Superbike Challenge */ + if (reg[12] & 1) + { + /* only in 40-cell mode, verified on MD2 */ + yscroll = (vs[19] >> 1) & (vs[19] >> 17); + yscroll &= 0x3FF; + } + if(shift) { dst = (uint32 *)&buf[0x10 + shift]; -#ifdef LSB_FIRST - v_line = (line + ((vs[19] >> 1) & 0x3FF)) & pf_row_mask; -#else - v_line = (line + ((vs[19] >> 17) & 0x3FF)) & pf_row_mask; -#endif + v_line = (line + yscroll) & pf_row_mask; nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)]; v_line = (((v_line & 7) << 1) | odd) << 3; @@ -1423,11 +1430,7 @@ static void render_bg_im2_vs(int line, int width, int odd) { dst = (uint32 *)&buf[0x10 + shift + (start<<4)]; -#ifdef LSB_FIRST - v_line = (line + ((vs[19] >> 17) & 0x3FF)) & pf_row_mask; -#else - v_line = (line + ((vs[19] >> 1) & 0x3FF)) & pf_row_mask; -#endif + v_line = (line + yscroll) & pf_row_mask; nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)]; v_line = (((v_line & 7) << 1) | odd) << 3;