├── README.md ├── Makefile ├── Makefile.win32 ├── gopt.h ├── gopt.c └── u64aap.c /README.md: -------------------------------------------------------------------------------- 1 | # u64aap 2 | N64 video mode patcher 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: u64aap 2 | 3 | 4 | usb2snes: 5 | gcc -static u64aap.c gopt.c -o u64aap 6 | 7 | clean: 8 | rm u64aap 9 | -------------------------------------------------------------------------------- /Makefile.win32: -------------------------------------------------------------------------------- 1 | all: u64aap 2 | 3 | OBJS = u64aap.c gopt.c 4 | 5 | usb2snes: $(OBJS) 6 | gcc -static $(OBJS) -Wall -Wextra -o2 -o u64aap 7 | 8 | clean: 9 | rm u64aap.exe 10 | -------------------------------------------------------------------------------- /gopt.h: -------------------------------------------------------------------------------- 1 | /* gopt.h version 8.1: tom.viza@gmail.com PUBLIC DOMAIN 2003-8 */ 2 | /* 3 | I, Tom Vajzovic, am the author of this software and its documentation and 4 | permanently abandon all copyright and other intellectual property rights in 5 | them, including the right to be identified as the author. 6 | 7 | I am fairly certain that this software does what the documentation says it 8 | does, but I cannot guarantee that it does, or that it does what you think it 9 | should, and I cannot guarantee that it will not have undesirable side effects. 10 | 11 | You are free to use, modify and distribute this software as you please, but 12 | you do so at your own risk. If you remove or hide this warning then you are 13 | responsible for any problems encountered by people that you make the software 14 | available to. 15 | 16 | Before modifying or distributing this software I ask that you would please 17 | read http://www.purposeful.co.uk/tfl/ 18 | */ 19 | 20 | #ifndef GOPT_H_INCLUDED 21 | #define GOPT_H_INCLUDED 22 | 23 | #define GOPT_ONCE 0 24 | #define GOPT_REPEAT 1 25 | #define GOPT_NOARG 0 26 | #define GOPT_ARG 2 27 | 28 | #define gopt_start(...) (const void*)( const struct { int k; int f; const char *s; const char*const*l; }[]){ __VA_ARGS__, {0}} 29 | #define gopt_option(k,f,s,l) { k, f, s, l } 30 | #define gopt_shorts( ... ) (const char*)(const char[]){ __VA_ARGS__, 0 } 31 | #define gopt_longs( ... ) (const char**)(const char*[]){ __VA_ARGS__, NULL } 32 | 33 | 34 | void *gopt_sort( int *argc, const char **argv, const void *opt_specs ); 35 | /* returns a pointer for use in the following calls 36 | * prints to stderr and call exit() on error 37 | */ 38 | size_t gopt( const void *opts, int key ); 39 | /* returns the number of times the option was specified 40 | * which will be 0 or 1 unless GOPT_REPEAT was used 41 | */ 42 | size_t gopt_arg( const void *opts, int key, const char **arg ); 43 | /* returns the number of times the option was specified 44 | * writes a pointer to the option argument from the first (or only) occurance to *arg 45 | */ 46 | const char *gopt_arg_i( const void *opts, int key, size_t i ); 47 | /* returns a pointer to the ith (starting at zero) occurance 48 | * of the option, or NULL if it was not specified that many times 49 | */ 50 | size_t gopt_args( const void *opts, int key, const char **args, size_t args_len ); 51 | /* returns the number of times the option was specified 52 | * writes pointers to the option arguments in the order of occurance to args[]. 53 | * writes at most args_len pointers 54 | * if the return value is less than args_len, also writes a null pointer 55 | */ 56 | void gopt_free( void *opts ); 57 | /* releases memory allocated in the corresponding call to gopt_sort() 58 | * opts can no longer be used 59 | */ 60 | #endif /* GOPT_H_INCLUDED */ 61 | -------------------------------------------------------------------------------- /gopt.c: -------------------------------------------------------------------------------- 1 | /* gopt.c version 8.1: tom.viza@gmail.com PUBLIC DOMAIN 2003-8 */ 2 | /* 3 | I, Tom Vajzovic, am the author of this software and its documentation and 4 | permanently abandon all copyright and other intellectual property rights in 5 | them, including the right to be identified as the author. 6 | 7 | I am fairly certain that this software does what the documentation says it 8 | does, but I cannot guarantee that it does, or that it does what you think it 9 | should, and I cannot guarantee that it will not have undesirable side effects. 10 | 11 | You are free to use, modify and distribute this software as you please, but 12 | you do so at your own risk. If you remove or hide this warning then you are 13 | responsible for any problems encountered by people that you make the software 14 | available to. 15 | 16 | Before modifying or distributing this software I ask that you would please 17 | read http://www.purposeful.co.uk/tfl/ 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include "gopt.h" 24 | 25 | #ifdef USE_SYSEXITS 26 | #include 27 | #else 28 | #define EX_OSERR EXIT_FAILURE 29 | #define EX_USAGE EXIT_FAILURE 30 | #endif 31 | 32 | struct opt_spec_s { 33 | int key; 34 | int flags; 35 | const char *shorts; 36 | const char* const *longs; 37 | }; 38 | typedef struct opt_spec_s opt_spec_t; 39 | 40 | struct opt_s { 41 | int key; 42 | const char *arg; 43 | }; 44 | typedef struct opt_s opt_t; 45 | 46 | void *gopt_sort( int *argc, const char **argv, const void *opt_specs ){ 47 | void *opts; 48 | {{{ 49 | const char* const *arg_p= argv + 1; 50 | size_t opt_count= 1; 51 | for( ; *arg_p; ++arg_p ) 52 | if( '-' == (*arg_p)[0] && (*arg_p)[1] ) 53 | if( '-' == (*arg_p)[1] ) 54 | if( (*arg_p)[2] ) 55 | ++opt_count; 56 | else 57 | break; 58 | else { 59 | const opt_spec_t *opt_spec_p= opt_specs; 60 | for( ; opt_spec_p-> key; ++opt_spec_p ) 61 | if( strchr( opt_spec_p-> shorts, (*arg_p)[1] )){ 62 | opt_count+= opt_spec_p-> flags & GOPT_ARG ? 1 : strlen( (*arg_p) + 1 ); 63 | break; 64 | } 65 | } 66 | opts= malloc( opt_count * sizeof(opt_t) ); 67 | }}} 68 | { 69 | const char **arg_p= argv + 1; 70 | const char **next_operand= arg_p; 71 | opt_t *next_option= opts; 72 | 73 | if( ! opts ){ 74 | perror( argv[0] ); 75 | exit( EX_OSERR ); 76 | } 77 | for( ; *arg_p; ++arg_p ) 78 | if( '-' == (*arg_p)[0] && (*arg_p)[1] ) 79 | if( '-' == (*arg_p)[1] ) 80 | if( (*arg_p)[2] ) 81 | {{{ 82 | const opt_spec_t *opt_spec_p= opt_specs; 83 | const char* const *longs= opt_spec_p-> longs; 84 | next_option-> key= 0; 85 | while( *longs ){ 86 | const char *option_cp= (*arg_p) + 2; 87 | const char *name_cp= *longs; 88 | while( *option_cp && *option_cp == *name_cp ){ 89 | ++option_cp; 90 | ++name_cp; 91 | } 92 | if( '=' == *option_cp || !*option_cp ){ 93 | if( *name_cp ){ 94 | if( next_option-> key ){ 95 | fprintf( stderr, "%s: --%.*s: abbreviated option is ambiguous\n", argv[0], (int)( option_cp -( (*arg_p) + 2 )), (*arg_p) + 2 ); 96 | free( opts ); 97 | exit( EX_USAGE ); 98 | } 99 | next_option-> key= opt_spec_p-> key; 100 | } 101 | else { 102 | next_option-> key= opt_spec_p-> key; 103 | goto found_long; 104 | } 105 | } 106 | if( !*++longs ){ 107 | ++opt_spec_p; 108 | if( opt_spec_p-> key ) 109 | longs= opt_spec_p-> longs; 110 | } 111 | } 112 | if( ! next_option-> key ){ 113 | fprintf( stderr, "%s: --%.*s: unknown option\n", argv[0], (int)strcspn( (*arg_p) + 2, "=" ), (*arg_p) + 2 ); 114 | free( opts ); 115 | exit( EX_USAGE ); 116 | } 117 | for( opt_spec_p= opt_specs; opt_spec_p-> key != next_option-> key; ++opt_spec_p ); 118 | found_long: 119 | 120 | if( !( opt_spec_p-> flags & GOPT_REPEAT )){ 121 | const opt_t *opt_p= opts; 122 | for( ; opt_p != next_option; ++opt_p ) 123 | if( opt_p-> key == opt_spec_p-> key ){ 124 | fprintf( stderr, "%s: --%.*s: option may not be repeated (in any long or short form)\n", argv[0], (int)strcspn( (*arg_p) + 2, "=" ), (*arg_p) + 2 ); 125 | free( opts ); 126 | exit( EX_USAGE ); 127 | } 128 | } 129 | if( opt_spec_p-> flags & GOPT_ARG ){ 130 | next_option-> arg= strchr( (*arg_p) + 2, '=' ) + 1; 131 | if( (char*)0 + 1 == next_option-> arg ){ 132 | ++arg_p; 133 | if( !*arg_p || '-' == (*arg_p)[0] && (*arg_p)[1] ){ 134 | fprintf( stderr, "%s: --%s: option requires an option argument\n", argv[0], (*(arg_p-1)) + 2 ); 135 | free( opts ); 136 | exit( EX_USAGE ); 137 | } 138 | next_option-> arg= *arg_p; 139 | } 140 | } 141 | else { 142 | if( strchr( (*arg_p) + 2, '=' )){ 143 | fprintf( stderr, "%s: --%.*s: option may not take an option argument\n", argv[0], (int)strcspn( (*arg_p) + 2, "=" ), (*arg_p) + 2 ); 144 | free( opts ); 145 | exit( EX_USAGE ); 146 | } 147 | next_option-> arg= NULL; 148 | } 149 | ++next_option; 150 | }}} 151 | else { 152 | for( ++arg_p; *arg_p; ++arg_p ) 153 | *next_operand++= *arg_p; 154 | break; 155 | } 156 | else 157 | {{{ 158 | const char *short_opt= (*arg_p) + 1; 159 | for( ;*short_opt; ++short_opt ){ 160 | const opt_spec_t *opt_spec_p= opt_specs; 161 | 162 | for( ; opt_spec_p-> key; ++opt_spec_p ) 163 | if( strchr( opt_spec_p-> shorts, *short_opt )){ 164 | if( !( opt_spec_p-> flags & GOPT_REPEAT )){ 165 | const opt_t *opt_p= opts; 166 | for( ; opt_p != next_option; ++opt_p ) 167 | if( opt_p-> key == opt_spec_p-> key ){ 168 | fprintf( stderr, "%s: -%c: option may not be repeated (in any long or short form)\n", argv[0], *short_opt ); 169 | free( opts ); 170 | exit( EX_USAGE ); 171 | } 172 | } 173 | next_option-> key= opt_spec_p-> key; 174 | 175 | if( opt_spec_p-> flags & GOPT_ARG ){ 176 | if( short_opt[1] ) 177 | next_option-> arg= short_opt + 1; 178 | 179 | else { 180 | ++arg_p; 181 | if( !*arg_p || '-' == (*arg_p)[0] && (*arg_p)[1] ){ 182 | fprintf( stderr, "%s: -%c: option requires an option argument\n", argv[0], *short_opt ); 183 | free( opts ); 184 | exit( EX_USAGE ); 185 | } 186 | next_option-> arg= *arg_p; 187 | } 188 | ++next_option; 189 | goto break_2; 190 | } 191 | next_option-> arg= NULL; 192 | ++next_option; 193 | goto continue_2; 194 | } 195 | fprintf( stderr, "%s: -%c: unknown option\n", argv[0], *short_opt ); 196 | free( opts ); 197 | exit( EX_USAGE ); 198 | continue_2: 0; 199 | } 200 | break_2: 0; 201 | }}} 202 | else 203 | *next_operand++= *arg_p; 204 | 205 | next_option-> key= 0; 206 | *next_operand= NULL; 207 | *argc= next_operand - argv; 208 | } 209 | return opts; 210 | } 211 | 212 | size_t gopt( const void *vptr_opts, int key ){ 213 | const opt_t *opts= vptr_opts; 214 | size_t count= 0; 215 | for( ; opts-> key; ++opts ) 216 | count+= opts-> key == key; 217 | 218 | return count; 219 | } 220 | 221 | size_t gopt_arg( const void *vptr_opts, int key, const char **arg ){ 222 | const opt_t *opts= vptr_opts; 223 | size_t count= 0; 224 | 225 | for( ; opts-> key; ++opts ) 226 | if( opts-> key == key ){ 227 | if( ! count ) 228 | *arg= opts-> arg; 229 | ++count; 230 | } 231 | return count; 232 | } 233 | 234 | const char *gopt_arg_i( const void *vptr_opts, int key, size_t i ){ 235 | const opt_t *opts= vptr_opts; 236 | 237 | for( ; opts-> key; ++opts ) 238 | if( opts-> key == key ){ 239 | if( ! i ) 240 | return opts-> arg; 241 | --i; 242 | } 243 | return NULL; 244 | } 245 | 246 | size_t gopt_args( const void *vptr_opts, int key, const char **args, size_t args_len ){ 247 | const char **args_stop= args + args_len; 248 | const char **args_ptr= args; 249 | const opt_t *opts= vptr_opts; 250 | 251 | for( ; opts-> key; ++opts ) 252 | if( opts-> key == key ){ 253 | if( args_stop == args_ptr ) 254 | return args_len + gopt( opts, key ); 255 | 256 | *args_ptr++= opts-> arg; 257 | } 258 | if( args_stop != args_ptr ) 259 | *args_ptr= NULL; 260 | return args_ptr - args; 261 | } 262 | 263 | void gopt_free( void *vptr_opts ){ 264 | free( vptr_opts ); 265 | } 266 | -------------------------------------------------------------------------------- /u64aap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "./gopt.h" 6 | #include "./n64.h" 7 | 8 | #define MAJOR_VERSION 0 9 | #define MINOR_VERSION 4 10 | #define BUGFIX_VERSION 4 11 | 12 | 13 | 14 | #ifdef __unix__ 15 | //unix 16 | #include 17 | #elif defined _WIN32 || defined _WIN64 18 | //windows 19 | #include 20 | #else 21 | #error "unknown platform" 22 | #endif 23 | 24 | 25 | void *options; 26 | long fsize; 27 | int verbosity=0; 28 | int vl_level=0; 29 | unsigned char *rom_blob; 30 | typedef unsigned int u32; 31 | typedef unsigned char u8; 32 | 33 | 34 | 35 | u32 getReg_ctrl(Vi_Mode *modep){ 36 | // printf( "ctrl %08x\n", modep->comRegs.ctrl); 37 | return modep->comRegs.ctrl; 38 | } 39 | 40 | u32 getReg_width(Vi_Mode *modep){ 41 | // printf( "width %08x\n", modep->comRegs.width); 42 | return modep->comRegs.width; 43 | } 44 | 45 | u32 getReg_burst(Vi_Mode *modep){ 46 | // printf( "burst %08x\n", modep->comRegs.burst); 47 | return modep->comRegs.burst; 48 | } 49 | u32 getReg_vSync(Vi_Mode *modep){ 50 | // printf( "vSync %08x\n", modep->comRegs.vSync); 51 | return modep->comRegs.vSync; 52 | } 53 | u32 getReg_hSync(Vi_Mode *modep){ 54 | // printf( "hSync %08x\n", modep->comRegs.hSync); 55 | return modep->comRegs.hSync; 56 | } 57 | u32 getReg_leap(Vi_Mode *modep){ 58 | // printf( "leap %08x\n", modep->comRegs.leap); 59 | return modep->comRegs.leap; 60 | } 61 | u32 getReg_hStart(Vi_Mode *modep){ 62 | // printf( "hStart %08x\n", modep->comRegs.hStart); 63 | return modep->comRegs.hStart; 64 | } 65 | u32 getReg_xScale(Vi_Mode *modep){ 66 | // printf( "xScale %08x\n", modep->comRegs.xScale); 67 | return modep->comRegs.xScale; 68 | } 69 | u32 getReg_vCurrent(Vi_Mode *modep){ 70 | // printf( "vCurrent %08x\n", modep->comRegs.vCurrent); 71 | return modep->comRegs.vCurrent; 72 | } 73 | 74 | 75 | 76 | u8 patchDitherFilter_Testing(){ 77 | 78 | u8 found=0; 79 | u32 offset=0; 80 | u32 prev_stop=0; 81 | u32 first_const_offset=0; 82 | u32 first_const_offset_real=0; 83 | u32 inner_offset_start=0; 84 | u32 inner_offset_start_real=0; 85 | u32 inner_offset_start_alt=0; 86 | u32 inner_offset_start_alt_real=0; 87 | u32 inner_offset_end=0; 88 | u32 diff=0; 89 | u32 last_const_nr=0; 90 | 91 | /* 92 | ANDI -- Bitwise and immediate 93 | Encoding: 94 | 0011 00ss ssst tttt iiii iiii iiii iiii 95 | andi t7 t6 4 0 96 | 97 | andi $t7, $t6, 0x40 98 | */ 99 | 100 | /* 101 | li: 24 REGISTER lower_bytes_a lower_bytes_b 102 | 103 | 24 01 FF EF 104 | li $1 0xFFFFFFEF 105 | 106 | 107 | /* 108 | li 0xFFFFFFF7 24 XX FF F7 ->start file offset 88640 109 | li 0xFFFFFFFB 24 XX FF FB 110 | 111 | andi 0x10 112 | andi 0x20 113 | li 0xFFFFFFEF 24 XX FF EF 114 | -> andi 40 3X XX 00 40 -> 3X XX 00 71 115 | li 0xFFFFFCFF 24 XX FC FF 116 | (li 0cFFFEFFFF 34 XX FF FF) -> end file offset 8871C = 0xDC -> 220 bytes (mario golf) 117 | 118 | star fox -> 22884 - 22784 = 0x100 -> 256 bytes 119 | duke nuken 71c34 - 71b34 = 0x100 -> 256 bytes 120 | 121 | */ 122 | 123 | unsigned char const nop[4] = { 0x00, 0x00, 0x00, 0x00 }; 124 | unsigned char const FFF7[2] = { 0xFF, 0xF7 }; 125 | unsigned char const FFFB[2] = { 0xFF, 0xFB }; 126 | unsigned char const FFEF[2] = { 0xFF, 0xEF }; 127 | unsigned char const FCFF[2] = { 0xFC, 0xFF }; 128 | unsigned char const FFFF[2] = { 0xFF, 0xFF }; 129 | unsigned char const _0040[2] = { 0x00, 0x40 }; 130 | unsigned char const _0000[2] = { 0x00, 0x00 }; 131 | unsigned char const _24XX[1] = { 0x24 }; 132 | unsigned char const _34XX[1] = { 0x24 }; 133 | 134 | 135 | for(offset=0; offset < fsize; ++offset){ 136 | if(!memcmp(FFF7, rom_blob + offset, 2)){ 137 | if(!memcmp(_24XX, rom_blob + offset-2, 1)){ 138 | // maybe first const in setViSpecialFeatures found 139 | if(verbosity >= 1) 140 | printf("osViSetSpecialFeatures const 1 found?\n"); 141 | last_const_nr=1; 142 | if(verbosity >= 2) 143 | printf("diff: 0, offset=%x\n",offset); 144 | prev_stop=offset; 145 | first_const_offset=offset; 146 | 147 | for(offset=offset; offset < fsize; ++offset){ 148 | if(last_const_nr==4) break; 149 | 150 | if(!memcmp(FFFB, rom_blob + offset, 2)){ 151 | if(!memcmp(_24XX, rom_blob + offset-2, 1)){ 152 | if(verbosity >= 1) 153 | printf("osViSetSpecialFeatures const 2 found?\n"); 154 | last_const_nr=2; 155 | 156 | diff=offset-prev_stop; 157 | if(verbosity >= 2) 158 | printf("diff: %d\n",diff); 159 | 160 | inner_offset_start_alt=offset; 161 | if(verbosity >= 2) 162 | printf("inner_offset_start_alt: %x\n",offset); 163 | 164 | //not found const to is too far away 165 | if(diff>100){ //76 166 | if(verbosity >= 1) 167 | printf("diff too far\n"); 168 | offset=prev_stop; 169 | break; 170 | }else{ 171 | prev_stop=offset; 172 | } 173 | 174 | for(offset=offset; offset < fsize; ++offset){ 175 | if(last_const_nr==4) break; 176 | 177 | if(!memcmp(FFEF, rom_blob + offset, 2)){ 178 | if(!memcmp(_24XX, rom_blob + offset-2, 1)){ 179 | if(verbosity >= 1) 180 | printf("osViSetSpecialFeatures const 3 found?\n"); 181 | last_const_nr=3; 182 | 183 | diff=offset-prev_stop; 184 | if(verbosity >= 2) 185 | printf("diff: %d\n",offset-prev_stop); 186 | 187 | inner_offset_start=offset; //0x40 between const 3 and const 4 188 | 189 | //not found const to is too far away 190 | if(diff>100){ //76 191 | if(verbosity >= 1) 192 | printf("diff too far\n"); 193 | offset=prev_stop; 194 | break; 195 | }else{ 196 | prev_stop=offset; 197 | } 198 | 199 | 200 | for(offset=offset; offset < fsize; ++offset){ 201 | if(!memcmp(FCFF, rom_blob + offset, 2)){ 202 | if(!memcmp(_24XX, rom_blob + offset-2, 1)){ 203 | if(verbosity >= 1) 204 | printf("osViSetSpecialFeatures const 4 found?\n"); 205 | last_const_nr=4; 206 | diff=offset-prev_stop; 207 | if(verbosity >= 2) 208 | printf("diff: %d\n",offset-prev_stop); 209 | //prev_stop=offset; 210 | 211 | //not found const to is too far away 212 | if(diff>100){ //76 213 | if(verbosity >= 1) 214 | printf("diff too far\n"); 215 | offset=prev_stop; 216 | break; 217 | }else{ 218 | prev_stop=offset; 219 | if(verbosity >= 2) 220 | printf("inner end offset found?\n"); 221 | inner_offset_start_alt_real=inner_offset_start_alt; 222 | inner_offset_start_real=inner_offset_start; 223 | first_const_offset_real=first_const_offset; 224 | inner_offset_end=offset; //0x40 between const 3 and const 4 225 | break; 226 | } 227 | 228 | 229 | } 230 | 231 | } 232 | 233 | } 234 | 235 | } 236 | 237 | } 238 | 239 | } 240 | 241 | 242 | 243 | } 244 | 245 | } 246 | 247 | } 248 | } 249 | 250 | 251 | } 252 | } 253 | 254 | 255 | if(verbosity >= 1) 256 | printf("\n\nstage 1 - bitmask\n"); 257 | 258 | if(verbosity >= 2) 259 | printf("inner_offset_start_real %x\n",inner_offset_start_real); 260 | if(verbosity >= 2) 261 | printf("inner_offset_end %x\n",inner_offset_end); 262 | //near search 263 | if(inner_offset_start_real!=0){ 264 | 265 | for(offset=inner_offset_start_real; offset < inner_offset_end; ++offset){ 266 | // printf("+"); 267 | if(!memcmp(_0040, rom_blob + offset, 2)){ 268 | //fixme additionmal check 269 | 270 | unsigned char test[4] = { 271 | 0x00, 0x00, 0x00, 0x00 272 | }; 273 | 274 | memcpy(test, rom_blob + offset-2, 4); 275 | if(verbosity >= 2) 276 | printf("-->> read test: %02x %02x %02x %02x \n", test[0], test[1], test[2], test[3]); 277 | 278 | if((test[0] & 0xFC) == 0x30){ 279 | if(verbosity >= 2) 280 | printf("patchoffset found! @%x\n", offset); 281 | found=1; 282 | } 283 | else{ 284 | if(verbosity >= 2){ 285 | printf("patchoffset not found! @%x\n", offset); 286 | printf("testing alternative spot :/\n"); 287 | } 288 | } 289 | 290 | break; 291 | 292 | 293 | 294 | 295 | } 296 | } 297 | 298 | 299 | //30 8C 00 40 300 | if(found!=1) 301 | for(offset=inner_offset_start_alt_real; offset < inner_offset_end; ++offset){ 302 | if(!memcmp(_0040, rom_blob + offset, 2)){ 303 | 304 | unsigned char test[4] = { 305 | 0x00, 0x00, 0x00, 0x00 306 | }; 307 | 308 | memcpy(test, rom_blob + offset-2, 4); 309 | if(verbosity >= 2){ 310 | printf("-->> alt offset: %x\n", offset); 311 | printf("-->> read test alt: %02x %02x %02x %02x \n", test[0], test[1], test[2], test[3]); 312 | } 313 | // printf("bitshift: c==%x\n",test[0]>>2); 314 | 315 | if((test[0] & 0xFC) == 0x30){ 316 | //if(test[0]>>2 == 0xc){ 317 | if(verbosity >= 1) 318 | printf("patchoffset found alt! @%x\n", offset); 319 | found=1; 320 | } 321 | else{ 322 | if(verbosity >= 1) 323 | printf("patchoffset not found! @%x\n", offset); 324 | } 325 | 326 | break; 327 | } 328 | 329 | } 330 | 331 | } 332 | 333 | 334 | 335 | if(found==1){ 336 | if(verbosity >= 1) 337 | printf(" ### patching dither filter bitmask...\n"); 338 | memcpy(rom_blob + offset, _0000, 2); 339 | } 340 | 341 | 342 | 343 | //stage 2 344 | 345 | 346 | 347 | if(inner_offset_start_real!=0 && found==1){ 348 | 349 | 350 | u8 branch_offset_found=0; 351 | 352 | u8 b=0; 353 | u32 branch[8]={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; 354 | 355 | if(verbosity >= 1) 356 | printf("\n\nstage 2 - branch\n"); 357 | //for(offset=inner_offset_end+2; offset < inner_offset_end+64; offset+=4){ 358 | for(offset=first_const_offset_real+2-64; offset < inner_offset_end+64; offset+=4){ 359 | 360 | unsigned char test[4] = { 0x00, 0x00, 0x00, 0x00 }; 361 | 362 | memcpy(test, rom_blob + offset, 4); 363 | 364 | 365 | // printf("-->> beqz offset: %x\n", offset); 366 | // printf("-->> beqz/beqzl read test: %02x %02x %02x %02x \n", test[0], test[1], test[2], test[3]); 367 | 368 | //[ 000100]01 10000000 00000000 00001011 369 | //beqz 0x100 370 | if((test[0] & 0xFC) == 0x10){ //beqz 371 | if((test[1] & 0x1F) == 0x00){ 372 | if(verbosity >= 2) 373 | printf("-->> beqz/beqzl read: %02x %02x %02x %02x \n", test[0], test[1], test[2], test[3]); 374 | if(verbosity >= 2) 375 | printf("++ next beqz found!\n"); 376 | branch_offset_found=offset; 377 | branch[b++]=offset; 378 | // break; 379 | 380 | } 381 | } 382 | 383 | if((test[0] & 0xFC) == 0x50){ //beqzl 384 | if((test[1] & 0x1F) == 0x00){ // zero 385 | if(verbosity >= 2) 386 | printf("-->> beqz/beqzl read: %02x %02x %02x %02x \n", test[0], test[1], test[2], test[3]); 387 | if(verbosity >= 2) 388 | printf("++ next beqzl found!\n"); 389 | branch_offset_found=offset; 390 | branch[b++]=offset; 391 | // break; 392 | 393 | } 394 | } 395 | 396 | 397 | } 398 | 399 | if(verbosity >= 2) 400 | printf("branches (%d/8)\n",b); 401 | 402 | /* 403 | 404 | noop branch to activate 405 | zero 's' to deactivate 406 | 407 | 408 | Gamma correction ON/OF 409 | 0 VI_GAMMA_ON a 410 | 1 VI_GAMMA_OFF c 411 | 412 | Gamma dithering ON/OFF 413 | 2 VI_GAMMA_DITHER_ON b 414 | 3 VI_GAMMA_DITHER_OFF g 415 | 416 | DIVOT ON/OFF 417 | 4 VI_DIVOT_ON e 418 | 5 VI_DIVOT_OFF d 419 | 420 | Dither filter ON/OFF 421 | 6 VI_DITHER_FILTER_ON j 422 | 7 _VI_DITHER_FILTER_OFF f 423 | */ 424 | 425 | //0x00 don't touch 0x01 on 0x02 off 426 | u8 setting[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 427 | 428 | printf("\nGamma correction:\t"); 429 | if( gopt( options, 'a' ) ){ setting[0]=0x01; setting[1]=0x02; printf("ON");} 430 | else 431 | if( gopt( options, 'c' ) ){ setting[0]=0x02; setting[1]=0x01; printf("OFF");} 432 | else printf("untouched"); 433 | printf("\n"); 434 | 435 | printf("Gamma dithering:\t"); 436 | if( gopt( options, 'b' ) ){ setting[2]=0x01; setting[3]=0x02; printf("ON");} 437 | else 438 | if( gopt( options, 'g' ) ){ setting[2]=0x02; setting[3]=0x01; printf("OFF");} 439 | else printf("untouched"); 440 | printf("\n"); 441 | 442 | printf("DIVOT:\t\t\t"); 443 | if( gopt( options, 'e' ) ){ setting[4]=0x01; setting[5]=0x02; printf("ON");} 444 | else 445 | if( gopt( options, 'd' ) ){ setting[4]=0x02; setting[5]=0x01; printf("OFF");} 446 | else printf("untouched"); 447 | printf("\n"); 448 | 449 | printf("Dither filter:\t\t"); 450 | if( gopt( options, 'j' ) ){ setting[6]=0x01; setting[7]=0x02; printf("ON");} 451 | else 452 | if( gopt( options, 'f' ) ){ setting[6]=0x02; setting[7]=0x01; printf("OFF");} 453 | else printf("untouched"); 454 | printf("\n\n"); 455 | 456 | 457 | if(verbosity >= 1) 458 | printf(" ### patching branches...\n"); 459 | if(branch_offset_found!=0){ 460 | //nop out 461 | u8 z=0; 462 | for(z=0;z<8;z++){ 463 | 464 | if(setting[z]==0x1){ 465 | //noop branche 466 | memcpy(rom_blob + branch[z], nop, 4); 467 | if(verbosity >= 2) 468 | printf("-->> nop: %02x %02x %02x %02x \n", nop[0], nop[1], nop[2], nop[3]); 469 | }else if(setting[z]==0x02){ 470 | //zero s 471 | unsigned char rom_branch[2] = { 0x00, 0x00}; 472 | memcpy(rom_branch, rom_blob + branch[z], 2); 473 | rom_branch[0]&=0xFC; 474 | rom_branch[1]&=0x1F; 475 | memcpy(rom_blob + branch[z], rom_branch, 2); 476 | if(verbosity >= 2) 477 | printf("-->> rb: %02x %02x \n", rom_branch[0], rom_branch[1]); 478 | } 479 | 480 | } 481 | 482 | found=2; 483 | } 484 | 485 | /* 486 | if(branch_offset_found!=0){ 487 | //nop out 488 | printf(" ### patching branch...\n"); 489 | memcpy(rom_blob + offset, nop, 4); 490 | found=2; 491 | } 492 | */ 493 | 494 | 495 | 496 | } 497 | /* 498 | pokemon 499 | beqzl (zero) t9 label 500 | 53 20 00 0F 501 | 0101 0011 0010 0000 0000 0000 000 01111 502 | 0001 00ss ssst tttt iiii iiii iiii iiii 503 | 504 | beqz (zero) t4 label 505 | 11 80 00 0B 506 | 0001 0001 1000 0000 0000 0000 0000 1011 507 | 0001 00ss ssst tttt iiii iiii iiii iiii 508 | 509 | mario 510 | beqz 511 | 10 40 00 0C 512 | 0001 0000 0100 0000 0000 0000 0000 1100 513 | 0001 00ss ssst tttt iiii iiii iiii iiii 514 | 515 | 516 | after 0xFFFFFCFF in +4bytes sections for the next branch 517 | 518 | search for beqz 519 | 0001 00ss sss0 0000 iiii iiii iiii iiii 520 | 521 | search for beqzl 522 | 0101 00ss sss0 0000 iiii iiii iiii iiii 523 | 524 | before 0xFFFEFFFF 525 | 526 | */ 527 | 528 | 529 | 530 | return found; 531 | } 532 | 533 | 534 | 535 | 536 | size_t patchCtrl(u8 mode, u32 offset){ 537 | 538 | unsigned char value[4] = { 539 | // 0x00, 0x00, 0x31, 0x1e 540 | 0x00, 0x00, 0x00, 0x00 541 | }; 542 | 543 | u32 val = getReg_ctrl(&Vi_ModeTable[mode]); 544 | value[0]=val>>24; value[1]=val>>16; value[2]=val>>8; value[3]=val; 545 | 546 | //printf("offset->: %08x\n",offset); 547 | //printf("value->: %08x\n",value[3]); 548 | 549 | memcpy(rom_blob + offset, value, 4); 550 | 551 | unsigned char value2[4] = { 552 | // 0x00, 0x00, 0x31, 0x1e 553 | 0x00, 0x00, 0x00, 0x00 554 | }; 555 | 556 | // memcpy(value2, rom_blob + offset, 4); 557 | // printf("-->> read test: %x %x %x %x \n", value2[0], value2[1], value2[2], value2[3]); 558 | 559 | return 1; 560 | } 561 | 562 | 563 | 564 | 565 | size_t searchOffset_vl(u8 level, u8 ucode){ 566 | 567 | size_t offset = 0; 568 | 569 | unsigned char testme[4] = { 570 | // 0x00, 0x00, 0x31, 0x1e 571 | // 0x00, 0x00, 0x00, 0x00 572 | 0xB9, 0x00, 0x03, 0x1D //fast3d e.g. sm64 573 | }; 574 | 575 | if(ucode==1){ //F3DEX2 e.g. zelda 576 | testme[0]==0xE2; 577 | } 578 | 579 | 580 | if(verbosity >= 1) 581 | printf("\nsearching vl entries...\n"); 582 | //search for video list offset in rom 583 | 584 | // u32 reg = getReg_ctrl(&Vi_ModeTable[scanmode]); 585 | //testme[0]=reg>>24; testme[1]=reg>>16; testme[2]=reg>>8; testme[3]=reg; 586 | 587 | for(offset=0; offset < fsize; ++offset) 588 | { 589 | if(!memcmp(testme, rom_blob + offset, 4)) //__font_data+array_offset single_character 590 | { 591 | 592 | if(verbosity >= 1) 593 | printf("vl entry %02x->", offset, rom_blob[offset + 7] );//&= ~5); 594 | 595 | if(verbosity >= 2) 596 | printf("vl entry at pos: 0x%x\t%02x->", offset, rom_blob[offset + 7] );//&= ~5); 597 | 598 | if(level>4){ //patch all location 599 | rom_blob[offset + 7] &= ~0x8; 600 | } 601 | else{ 602 | 603 | if(level>0){ 604 | 605 | if(rom_blob[offset + 7]==0x78) 606 | rom_blob[offset + 7] &= ~0x8; 607 | } 608 | 609 | 610 | 611 | if(level>1){ 612 | 613 | if(rom_blob[offset + 7]==0x48) 614 | rom_blob[offset + 7] &= ~0x8; 615 | } 616 | 617 | if(level>2){ 618 | 619 | if(rom_blob[offset + 7]==0x58) 620 | rom_blob[offset + 7] &= ~0x8; 621 | } 622 | 623 | 624 | 625 | if(level>3){ 626 | 627 | if(rom_blob[offset + 7]==0xd8) 628 | rom_blob[offset + 7] &= ~0x8; 629 | } 630 | 631 | 632 | 633 | } 634 | 635 | 636 | if(verbosity >= 1) 637 | printf("%02x\n", rom_blob[offset + 7] );//&= ~5); 638 | // rom_blob[offset + 7]=rom_blob[offset + 7] 639 | 640 | /* 641 | int count=0; 642 | reg = getReg_width(&Vi_ModeTable[scanmode]); 643 | testme[0]=reg>>24; testme[1]=reg>>16; testme[2]=reg>>8; testme[3]=reg; 644 | if(!memcmp(testme, rom_blob + offset+4, 4)){ 645 | */ 646 | // printf("vt width at pos: 0x%x\n", offset+4); 647 | // count++; 648 | 649 | /* 650 | if(count>=3){ 651 | if(count==8){ 652 | if(verbosity >= 1) 653 | printf("vt entry found!\n"); 654 | }else{ 655 | if(verbosity >= 2){ 656 | printf("vt entry maybe found! (%d/8)\n",count); 657 | printf("try anyway :D\n"); 658 | } 659 | } 660 | break; 661 | } 662 | */ 663 | 664 | // else{ 665 | // printf("vt not found!\n"); 666 | // } 667 | 668 | 669 | } 670 | 671 | } 672 | 673 | return offset; 674 | } 675 | 676 | 677 | 678 | 679 | 680 | size_t searchOffset(u8 scanmode){ 681 | 682 | size_t offset = 0; 683 | 684 | unsigned char testme[4] = { 685 | // 0x00, 0x00, 0x31, 0x1e 686 | 0x00, 0x00, 0x00, 0x00 687 | }; 688 | 689 | if(verbosity >= 1) 690 | printf("\nsearching...\n"); 691 | //search for video table offset in rom 692 | 693 | u32 reg = getReg_ctrl(&Vi_ModeTable[scanmode]); 694 | testme[0]=reg>>24; testme[1]=reg>>16; testme[2]=reg>>8; testme[3]=reg; 695 | 696 | for(offset=0; offset < fsize; ++offset) 697 | { 698 | if(!memcmp(testme, rom_blob + offset, 4)) //__font_data+array_offset single_character 699 | { 700 | //printf("vt ctrl at pos: 0x%x\n", offset); 701 | 702 | int count=0; 703 | reg = getReg_width(&Vi_ModeTable[scanmode]); 704 | testme[0]=reg>>24; testme[1]=reg>>16; testme[2]=reg>>8; testme[3]=reg; 705 | if(!memcmp(testme, rom_blob + offset+4, 4)){ 706 | // printf("vt width at pos: 0x%x\n", offset+4); 707 | count++; 708 | } 709 | reg = getReg_burst(&Vi_ModeTable[scanmode]); 710 | testme[0]=reg>>24; testme[1]=reg>>16; testme[2]=reg>>8; testme[3]=reg; 711 | if(!memcmp(testme, rom_blob + offset+8, 4)){ 712 | // printf("vt burst at pos: 0x%x\n", offset+8); 713 | count++; 714 | } 715 | reg = getReg_vSync(&Vi_ModeTable[scanmode]); 716 | testme[0]=reg>>24; testme[1]=reg>>16; testme[2]=reg>>8; testme[3]=reg; 717 | if(!memcmp(testme, rom_blob + offset+12, 4)){ 718 | // printf("vt vSync at pos: 0x%x\n", offset+12); 719 | count++; 720 | } 721 | reg = getReg_hSync(&Vi_ModeTable[scanmode]); 722 | testme[0]=reg>>24; testme[1]=reg>>16; testme[2]=reg>>8; testme[3]=reg; 723 | if(!memcmp(testme, rom_blob + offset+16, 4)){ 724 | // printf("vt hSync at pos: 0x%x\n", offset+16); 725 | count++; 726 | } 727 | reg = getReg_leap(&Vi_ModeTable[scanmode]); 728 | testme[0]=reg>>24; testme[1]=reg>>16; testme[2]=reg>>8; testme[3]=reg; 729 | if(!memcmp(testme, rom_blob + offset+20, 4)){ 730 | // printf("vt leap at pos: 0x%x\n", offset+20); 731 | count++; 732 | } 733 | reg = getReg_hStart(&Vi_ModeTable[scanmode]); 734 | testme[0]=reg>>24; testme[1]=reg>>16; testme[2]=reg>>8; testme[3]=reg; 735 | if(!memcmp(testme, rom_blob + offset+24, 4)){ 736 | // printf("vt hStart at pos: 0x%x\n", offset+24); 737 | count++; 738 | } 739 | reg = getReg_xScale(&Vi_ModeTable[scanmode]); 740 | testme[0]=reg>>24; testme[1]=reg>>16; testme[2]=reg>>8; testme[3]=reg; 741 | if(!memcmp(testme, rom_blob + offset+28, 4)){ 742 | // printf("vt xScale at pos: 0x%x\n", offset+28); 743 | count++; 744 | } 745 | reg = getReg_vCurrent(&Vi_ModeTable[scanmode]); 746 | testme[0]=reg>>24; testme[1]=reg>>16; testme[2]=reg>>8; testme[3]=reg; 747 | if(!memcmp(testme, rom_blob + offset+32, 4)){ 748 | // printf("vt vCurrent at pos: 0x%x\n", offset+32); 749 | count++; 750 | } 751 | 752 | if(count>=3){ 753 | if(count==8){ 754 | if(verbosity >= 1) 755 | printf("vt entry found!\n"); 756 | }else{ 757 | if(verbosity >= 2){ 758 | printf("vt entry maybe found! (%d/8)\n",count); 759 | printf("try anyway :D\n"); 760 | } 761 | } 762 | break; 763 | } 764 | else{ 765 | // printf("vt not found!\n"); 766 | } 767 | 768 | } 769 | 770 | } 771 | 772 | return offset; 773 | } 774 | 775 | 776 | 777 | size_t patchMode(u8 from_mode, u8 to_mode){ 778 | 779 | if(verbosity >= 1) 780 | printf("search for mode: %d\n",from_mode); 781 | 782 | u32 offset = searchOffset(from_mode); 783 | 784 | if(offset == fsize){ 785 | if(verbosity >= 1) 786 | printf("error: mode: %d no VT offset found\n", from_mode); 787 | return -1; 788 | } 789 | 790 | if(verbosity >= 2) 791 | printf(" found at offset: %08x\n",offset); 792 | 793 | //u32 res0 = getReg_ctrl(&Vi_ModeTable[from_mode]); 794 | //printf("lan1 ctrl: %08x\n",lan1); 795 | 796 | //u32 res1 = getReg_ctrl(&Vi_ModeTable[to_mode]); 797 | //printf("lpn1 ctrl: %08x\n",lpn1); 798 | 799 | size_t tmp; 800 | tmp = patchCtrl(to_mode, offset); 801 | 802 | return 0; 803 | } 804 | 805 | 806 | 807 | int main(int argc, const char **argv) 808 | { 809 | 810 | printf("-== N64 AA-patcher ==- by saturnu\n\n"); 811 | 812 | 813 | 814 | options = gopt_sort( & argc, argv, gopt_start( 815 | gopt_option( 'h', 0, gopt_shorts( 'h' ), gopt_longs( "help" )), 816 | gopt_option( 'z', 0, gopt_shorts( 'z' ), gopt_longs( "version" )), 817 | gopt_option( 'v', GOPT_REPEAT, gopt_shorts( 'v' ), gopt_longs( "verbose" )), 818 | 819 | gopt_option( 'a', 0, gopt_shorts( 'a' ), gopt_longs( "gc-on" )), 820 | gopt_option( 'c', 0, gopt_shorts( 'c' ), gopt_longs( "gc-off" )), 821 | 822 | gopt_option( 'b', 0, gopt_shorts( 'b' ), gopt_longs( "gd-on" )), 823 | gopt_option( 'g', 0, gopt_shorts( 'g' ), gopt_longs( "gd-off" )), 824 | 825 | gopt_option( 'e', 0, gopt_shorts( 'e' ), gopt_longs( "di-on" )), 826 | gopt_option( 'd', 0, gopt_shorts( 'd' ), gopt_longs( "di-off" )), 827 | 828 | gopt_option( 'j', 0, gopt_shorts( 'j' ), gopt_longs( "df-on" )), 829 | gopt_option( 'f', 0, gopt_shorts( 'f' ), gopt_longs( "df-off" )), 830 | 831 | gopt_option( 'q', 0, gopt_shorts( 'q' ), gopt_longs( "dummy" )), 832 | //gopt_option( 't', 0, gopt_shorts( 't' ), gopt_longs( "no-table" )), 833 | //gopt_option( 'l', 0, gopt_shorts( 'l' ), gopt_longs( "videolist" )), 834 | gopt_option( 'l', GOPT_REPEAT, gopt_shorts( 'l' ), gopt_longs( "videolist" )), 835 | 836 | gopt_option( 'k', 0, gopt_shorts( 'k' ), gopt_longs( "fast3d" )), 837 | gopt_option( '2', 0, gopt_shorts( '2' ), gopt_longs( "f3dex2" )), 838 | 839 | gopt_option( 's', 0, gopt_shorts( 's' ), gopt_longs( "swap" )), 840 | gopt_option( 'n', 0, gopt_shorts( 'n' ), gopt_longs( "no-anti-aliasing" )), 841 | 842 | gopt_option( 'o', GOPT_ARG, gopt_shorts( 'o' ), gopt_longs( "output" )), 843 | gopt_option( 'i', GOPT_ARG, gopt_shorts( 'i' ), gopt_longs( "input" )) )); 844 | 845 | 846 | 847 | if( gopt( options, 'h' ) ){ 848 | 849 | #ifdef __unix__ 850 | //unix 851 | fprintf( stdout, "Syntax: u64aap [options] -i input.z64 -o output.z64\n\n"); 852 | #elif defined _WIN32 || defined _WIN64 853 | //windows 854 | fprintf( stdout, "Syntax: u64aap [options] -i input.z64 -o output.z64\n\n"); 855 | #else 856 | #error "unknown platform" 857 | #endif 858 | 859 | 860 | fprintf( stdout, "u64aap - -== N64 AA-patcher ==-\n" ); 861 | fprintf( stdout, "by saturnu \n\n" ); 862 | 863 | printf("Input/Output: (required)\n"); 864 | fprintf( stdout, " -i, --input=filename.z64\tN64 Rom in z64 format\n" ); 865 | fprintf( stdout, " -o, --output=filename.z64\tN64 Rom in z64 format\n" ); 866 | 867 | 868 | printf("\nFilter options: (default: untouched)\n"); 869 | fprintf( stdout, " -a, --gc-on\t\tset Gamma correction ON\n" ); 870 | fprintf( stdout, " -c, --gc-off\t\tset Gamma correction OFF\n" ); 871 | 872 | fprintf( stdout, " -b, --gd-on\t\tset Gamma dithering ON\n" ); 873 | fprintf( stdout, " -g, --gd-off\t\tset Gamma dithering OFF\n" ); 874 | 875 | fprintf( stdout, " -e, --di-on\t\tset DIVOT ON\n" ); 876 | fprintf( stdout, " -d, --di-off\t\tset DIVOT OFF\n" ); 877 | 878 | fprintf( stdout, " -j, --df-on\t\tset Dither filter ON\n" ); 879 | fprintf( stdout, " -f, --df-off\t\tset Dither filter OFF\n" ); 880 | 881 | printf("\nExtra options:\n"); 882 | fprintf( stdout, " -q, --dummy\t\tjust test - don't output file\n" ); 883 | fprintf( stdout, " -s, --swap\t\tswap VideoTable region (new experimental)\n" ); 884 | fprintf( stdout, " -n, --no-anti-aliasing\tdisable AA in VideoTable, too\n" ); 885 | //fprintf( stdout, " -t, --no-table\t\tdon't touch VideoTable at all\n" ); 886 | fprintf( stdout, " -k, --fast3d\t\tsearch F3D SETOTHERMODE_L (highly experimental)\n" ); 887 | fprintf( stdout, " -2, --f3dex2\t\tsearch F3DEX2 SETOTHERMODE_L (highly experimental)\n" ); 888 | fprintf( stdout, " -l, --videolist\tpatch VideoList - [stackable] (highly experimental)\n" ); 889 | 890 | 891 | printf("\nInformation:\n"); 892 | fprintf( stdout, " -h, --help\t\tdisplay this help and exit\n" ); 893 | fprintf( stdout, " -v, --verbose\t\tverbose\n" ); 894 | fprintf( stdout, " -z, --version\t\tversion info\n" ); 895 | 896 | return 0; 897 | } 898 | 899 | 900 | if( gopt( options, 'z' ) ){ 901 | 902 | fprintf( stdout, "u64aap version v%d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, BUGFIX_VERSION ); 903 | return 0; 904 | } 905 | 906 | /* 907 | if(argv[1]==NULL){ 908 | printf("error: please use a z64 rom as parameter\n"); 909 | return 0; 910 | } 911 | */ 912 | 913 | if( !gopt( options, 'i' ) ){ 914 | //needed every time 915 | printf("input file missing! use 'u64aap -h' for help\n"); 916 | return 0; 917 | } 918 | 919 | if( !gopt( options, 'o' ) ){ 920 | //needed every time 921 | printf("output file missing! use 'u64aap -h' for help\n"); 922 | return 0; 923 | } 924 | 925 | 926 | if( gopt( options, 'l' ) > 0){ 927 | 928 | if( !(gopt( options, 'k' ) || gopt( options, '2' )) ){ 929 | 930 | printf("uCode flag missing! use 'u64aap -h' for help\n"); 931 | return 0; 932 | } 933 | 934 | 935 | } 936 | 937 | 938 | if( gopt( options, 'a' ) && gopt( options, 'c' )){ 939 | 940 | fprintf( stdout, "error: could not set Gamma correction ON and OFF at the same time\n" ); 941 | return 0; 942 | } 943 | 944 | if( gopt( options, 'b' ) && gopt( options, 'g' )){ 945 | 946 | fprintf( stdout, "error: could not set Gamma dithering ON and OFF at the same time\n" ); 947 | return 0; 948 | } 949 | 950 | if( gopt( options, 'e' ) && gopt( options, 'd' )){ 951 | 952 | fprintf( stdout, "error: could not set DIVOT ON and OFF at the same time\n" ); 953 | return 0; 954 | } 955 | 956 | if( gopt( options, 'j' ) && gopt( options, 'f' )){ 957 | 958 | fprintf( stdout, "error: could not set Dither filter ON and OFF at the same time\n" ); 959 | return 0; 960 | } 961 | 962 | if(gopt( options, 'v' ) < 10) 963 | verbosity = gopt( options, 'v' ); 964 | else verbosity = 9; 965 | 966 | if(gopt( options, 'l' ) < 10) 967 | vl_level = gopt( options, 'l' ); 968 | else vl_level = 9; 969 | 970 | 971 | if( verbosity > 1 ) 972 | fprintf( stderr, "being really verbose\n" ); 973 | 974 | else if( verbosity ) 975 | fprintf( stderr, "being verbose\n" ); 976 | 977 | 978 | 979 | 980 | //int fsize; 981 | const char *filename_input; 982 | const char *filename_output; 983 | 984 | if( gopt( options, 'i' ) ){ 985 | 986 | if( gopt_arg( options, 'i', & filename_input ) && strcmp( filename_input, "-" ) ){ 987 | 988 | FILE *f; 989 | f=fopen(filename_input, "rb"); 990 | 991 | if (f == NULL) { 992 | printf("error: Faild to open rom\n"); 993 | return 0; 994 | }else{ 995 | printf("%s found\n", filename_input); 996 | } 997 | 998 | fseek(f, 0, SEEK_END); 999 | fsize = ftell(f); 1000 | fseek(f, 0, SEEK_SET); 1001 | 1002 | if(verbosity >= 2) 1003 | printf("Rom size: %d\n",fsize); 1004 | 1005 | rom_blob = malloc(fsize + 1); 1006 | fread(rom_blob, fsize, 1, f); 1007 | fclose(f); 1008 | 1009 | } 1010 | 1011 | } 1012 | 1013 | 1014 | int patch_counter=0; 1015 | 1016 | 1017 | if( vl_level ){ 1018 | 1019 | if( gopt( options, 'k' ) ){ 1020 | printf("\n\nFast3D: \n"); 1021 | searchOffset_vl(vl_level, 0); 1022 | } 1023 | 1024 | if( gopt( options, '2' ) ){ 1025 | printf("F3DEX2: \n"); 1026 | searchOffset_vl(vl_level, 1); 1027 | } 1028 | } 1029 | 1030 | if( gopt( options, 'o' ) ){ 1031 | 1032 | if(verbosity >= 1) 1033 | printf("\n\nstage 0 - video table\n"); 1034 | 1035 | 1036 | if( gopt( options, 'n' ) ){ 1037 | //disable anti aliasing 1038 | 1039 | if( !gopt( options, 's' ) ){ 1040 | 1041 | if(verbosity >= 1) 1042 | printf("\n\nstage 0 - disable aa in video table\n"); 1043 | 1044 | 1045 | if(patchMode(N_LAN1, N_LPN1)==0) patch_counter++; 1046 | if(patchMode(N_LAF1, N_LPF1)==0) patch_counter++; 1047 | if(patchMode(N_LAN2, N_LPN2)==0) patch_counter++; 1048 | if(patchMode(N_LAF2, N_LPF2)==0) patch_counter++; 1049 | if(patchMode(N_HAN1, N_HPN1)==0) patch_counter++; 1050 | if(patchMode(N_HAF1, N_HPF1)==0) patch_counter++; 1051 | 1052 | if(patchMode(P_LAN1, P_LPN1)==0) patch_counter++; 1053 | if(patchMode(P_LAF1, P_LPF1)==0) patch_counter++; 1054 | if(patchMode(P_LAN2, P_LPN2)==0) patch_counter++; 1055 | if(patchMode(P_LAF2, P_LPF2)==0) patch_counter++; 1056 | if(patchMode(P_HAN1, P_HPN1)==0) patch_counter++; 1057 | if(patchMode(P_HAF1, P_HPF1)==0) patch_counter++; 1058 | 1059 | if(patchMode(MP_LAN1, MP_LPN1)==0) patch_counter++; 1060 | if(patchMode(MP_LAF1, MP_LPF1)==0) patch_counter++; 1061 | if(patchMode(MP_LAN2, MP_LPN2)==0) patch_counter++; 1062 | if(patchMode(MP_LAF2, MP_LPF2)==0) patch_counter++; 1063 | if(patchMode(MP_HAN1, MP_HPN1)==0) patch_counter++; 1064 | if(patchMode(MP_HAF1, MP_HPF1)==0) patch_counter++; 1065 | 1066 | 1067 | } 1068 | else //swap video tables, too 1069 | { 1070 | 1071 | if(verbosity >= 1){ 1072 | printf("tage 0 - disable aa in video table + region swap\n"); 1073 | printf("stage 0.1 ntsc->pal\n"); 1074 | } 1075 | if(patchMode(N_LAN1, P_LPN1)==0) patch_counter++; 1076 | if(patchMode(N_LAF1, P_LPF1)==0) patch_counter++; 1077 | if(patchMode(N_LAN2, P_LPN2)==0) patch_counter++; 1078 | if(patchMode(N_LAF2, P_LPF2)==0) patch_counter++; 1079 | if(patchMode(N_HAN1, P_HPN1)==0) patch_counter++; 1080 | if(patchMode(N_HAF1, P_HPF1)==0) patch_counter++; 1081 | 1082 | 1083 | if(verbosity >= 1) 1084 | printf("stage 0.2 pal->ntsc\n"); 1085 | if(patchMode(P_LAN1, N_LPN1)==0) patch_counter++; 1086 | if(patchMode(P_LAF1, N_LPF1)==0) patch_counter++; 1087 | if(patchMode(P_LAN2, N_LPN2)==0) patch_counter++; 1088 | if(patchMode(P_LAF2, N_LPF2)==0) patch_counter++; 1089 | if(patchMode(P_HAN1, N_HPN1)==0) patch_counter++; 1090 | if(patchMode(P_HAF1, N_HPF1)==0) patch_counter++; 1091 | 1092 | if(verbosity >= 1) 1093 | printf("tage 0.3 - mpal->pal\n"); 1094 | if(patchMode(MP_LAN1, P_LPN1)==0) patch_counter++; 1095 | if(patchMode(MP_LAF1, P_LPF1)==0) patch_counter++; 1096 | if(patchMode(MP_LAN2, P_LPN2)==0) patch_counter++; 1097 | if(patchMode(MP_LAF2, P_LPF2)==0) patch_counter++; 1098 | if(patchMode(MP_HAN1, P_HPN1)==0) patch_counter++; 1099 | if(patchMode(MP_HAF1, P_HPF1)==0) patch_counter++; 1100 | } 1101 | 1102 | 1103 | 1104 | //end disable ant aliasing 1105 | }else{ 1106 | //normal swap 1107 | if( gopt( options, 's' ) ){ 1108 | 1109 | if(verbosity >= 1){ 1110 | printf("region swap only\n"); 1111 | printf("stage 0.1 ntsc->pal\n"); 1112 | } 1113 | if(patchMode(N_LAN1, P_LAN1)==0) patch_counter++; 1114 | if(patchMode(N_LAF1, P_LAF1)==0) patch_counter++; 1115 | if(patchMode(N_LAN2, P_LAN2)==0) patch_counter++; 1116 | if(patchMode(N_LAF2, P_LAF2)==0) patch_counter++; 1117 | if(patchMode(N_HAN1, P_HAN1)==0) patch_counter++; 1118 | if(patchMode(N_HAF1, P_HAF1)==0) patch_counter++; 1119 | 1120 | if(verbosity >= 1) 1121 | printf("stage 0.2 pal->ntsc\n"); 1122 | 1123 | if(patchMode(P_LAN1, N_LAN1)==0) patch_counter++; 1124 | if(patchMode(P_LAF1, N_LAF1)==0) patch_counter++; 1125 | if(patchMode(P_LAN2, N_LAN2)==0) patch_counter++; 1126 | if(patchMode(P_LAF2, N_LAF2)==0) patch_counter++; 1127 | if(patchMode(P_HAN1, N_HAN1)==0) patch_counter++; 1128 | if(patchMode(P_HAF1, N_HAF1)==0) patch_counter++; 1129 | 1130 | if(verbosity >= 1) 1131 | printf("stage 0.3 mpal->pal\n"); 1132 | if(patchMode(MP_LAN1, P_LAN1)==0) patch_counter++; 1133 | if(patchMode(MP_LAF1, P_LAF1)==0) patch_counter++; 1134 | if(patchMode(MP_LAN2, P_LAN2)==0) patch_counter++; 1135 | if(patchMode(MP_LAF2, P_LAF2)==0) patch_counter++; 1136 | if(patchMode(MP_HAN1, P_HAN1)==0) patch_counter++; 1137 | if(patchMode(MP_HAF1, P_HAF1)==0) patch_counter++; 1138 | }//end swap only 1139 | 1140 | } 1141 | if(verbosity >= 1) 1142 | printf("=>> %d/18 modes patched!\n\n", patch_counter); 1143 | 1144 | } 1145 | 1146 | if(patch_counter>=1) 1147 | printf("\nVideo Table:\t\tpatched\n"); 1148 | else 1149 | printf("\nVideo Table:\t\tuntouched\n"); 1150 | 1151 | u8 patches=patchDitherFilter_Testing(); 1152 | if(patches>1) { 1153 | 1154 | 1155 | /* int ret = rename(argv[1], "data.bak"); 1156 | 1157 | if(ret==-1){ 1158 | printf("error: backup error\n"); 1159 | } 1160 | */ 1161 | 1162 | 1163 | 1164 | if( gopt( options, 'o' ) ){ 1165 | 1166 | if( gopt_arg( options, 'o', & filename_output ) && strcmp( filename_output, "-" ) ){ 1167 | 1168 | if( !gopt( options, 'q' ) ){ 1169 | FILE *fpw; 1170 | fpw=fopen(filename_output, "wb"); 1171 | 1172 | fwrite(rom_blob, 1, fsize, fpw); 1173 | fclose(fpw); 1174 | } 1175 | 1176 | } 1177 | } 1178 | 1179 | 1180 | 1181 | 1182 | //printf("video table patches (%d/18)\n", patch_counter); 1183 | //if(verbosity >= 1) 1184 | if( gopt( options, 'q' ) ) 1185 | printf("result: dummy mode - file patched!\n"); 1186 | else 1187 | printf("result: file patched!\n"); 1188 | 1189 | } 1190 | else{ 1191 | printf("\n\nresult: file not patched!\n"); 1192 | } 1193 | 1194 | //if(verbosity >= 1) 1195 | printf("done...\n"); 1196 | 1197 | 1198 | 1199 | 1200 | return 0; 1201 | } 1202 | --------------------------------------------------------------------------------