--- fceu-orig/src/x6502.c 2005-04-13 13:54:28.000000000 +0300 +++ fceu/src/x6502.c 2005-10-02 03:42:55.000000000 +0300 @@ -32,6 +32,8 @@ uint32 timestamp; void FP_FASTAPASS(1) (*MapIRQHook)(int a); +#define BISQWIT_ROCKMAN_DEBUGGATION + #define _PC X.PC #define _A X.A #define _X X.X @@ -53,6 +55,15 @@ timestamp+=__x; \ } +#ifdef BISQWIT_ROCKMAN_DEBUGGATION + static char Write0D; + int RockmanBonus1 = -1; // Generateds. $3B=no bonus, $3C.. = bonus. $3F=BINGO + int RockmanBonus2 = -1; // Generateds. $3B=no bonus, $3C.. = bonus. $3F=BINGO + int RockmanHurt = 0; // 1 = hurt + int RockmanItem = -1; // Fetchds. + int RockmanKill = 0; // nonzero = type of enemy +#endif + static INLINE uint8 RdMemNorm(unsigned int A) { return(_DB=ARead[A](A)); @@ -60,6 +71,9 @@ static INLINE void WrMemNorm(unsigned int A, uint8 V) { +#ifdef BISQWIT_ROCKMAN_DEBUGGATION + if(A == 0x0D) { Write0D=1;} +#endif BWrite[A](A,V); } @@ -93,6 +107,9 @@ static INLINE void WrRAMFast(unsigned int A, uint8 V) { +#ifdef BISQWIT_ROCKMAN_DEBUGGATION + if(A == 0x0D) { Write0D=1; } +#endif RAM[A]=V; } @@ -564,6 +581,10 @@ } +#ifdef BISQWIT_ROCKMAN_DEBUGGATION + static unsigned LastWrite0D; +#endif + static void X6502_RunNormal(int32 cycles) { #define RdRAM RdRAMFast @@ -649,6 +670,179 @@ } _PI=_P; +#ifdef BISQWIT_ROCKMAN_DEBUGGATION + { + const unsigned FrameUpd = 0xD57D; + const unsigned RandomFunc = 0xC5AB; + const unsigned CreateDrop = 0xBF25; + const unsigned HurtFunc = 0xA231; + const unsigned GotItem = 0xC833; + const unsigned KillFunc = 0xC219; + const unsigned EnemyKill = 0xBEEC; + + if(_PC == CreateDrop) + { if(RockmanBonus1 == -1) RockmanBonus1 = X.Y; else RockmanBonus2 = X.Y; } + if(_PC == HurtFunc) RockmanHurt = 1; + if(_PC == KillFunc) RockmanHurt = 2; + if(_PC == GotItem) RockmanItem = X.A; + if(_PC == EnemyKill) RockmanKill = X.A; + + if(_PC == FrameUpd) + //if(_PC == RandomFunc) + { + static unsigned Last0DList[16]; + static unsigned Last0DCount = 0; + + #if 0 + const unsigned char RandomSeed = RdMem(0x46); + const unsigned char TempVar13 = RdMem(0x0D); + const unsigned char FrameCounter=RdMem(0x23); + const unsigned char WeaponSelect=RdMem(0x5F)%8; + const unsigned char WeaponFiring=RdMem(0x60); + const unsigned char BlinkState =RdMem(0x55); + + static const unsigned char ObjectsPerWeapon[8] = + { + // P C I B F E G M + 1,4,0,0,8,0,0,0 + + // I'm not killing anything with Ice + // Nor with Bombs (slow) + // Nor with Elec (unpredictable and laggy) + // Nor with Guts or Magnet + }; + + unsigned char NewSeed; + unsigned a,Shoot; + + enum { MaxBingo = 30, MaxShoot = 80 }; + + unsigned bingo[1+MaxBingo][1+MaxShoot]; + unsigned bingocount[1+MaxBingo] = { 0 }; + + if(RandomSeed & 0x80) fprintf(stderr, "******************\n"); + + const char* items[] = {"air","score","wpn","nrj","**WPN**","NRJ","1UP"}; + #define index(n) \ + (n>=99 ? 6 : (n>=97 ? 5 : (n>=95 ? 4 : (n>=80 ? 3 : (n>=65 ? 2 : (n>=12)))))) + fprintf(stderr, "Frame %02X, temp=%02X, seed=%02X, firing=%02X [%s]\n", + FrameCounter, TempVar13, RandomSeed, WeaponFiring, + items[index(RandomSeed%100)] + ); + + for(Shoot=0; Shoot 0) --BlinkTmp; + const char RockmanIsVisible = (BlinkTmp&2)==0; + + if(RockmanIsVisible && !RockmanWasVisible) TempTemp += 40; + if(RockmanWasVisible && !RockmanIsVisible) TempTemp -= 40; + + NewSeed ^= TempTemp; + NewSeed += NewCounter; // ignore overflow + NewSeed >>= 1; + //f(a == 1) fprintf(stderr, " (next %02X)", NewSeed); + + in = index(NewSeed%100); + if(in == 4 + && a >= Shoot) + { + if(a == 0 && !WeaponFiring) continue; + if(a == 2 && WeaponFiring) continue; + + bingo[a][bingocount[a]++] = Shoot; + break; + } + } + } + for(a=1; a<=MaxBingo; ++a) + { + unsigned b,c = bingocount[a]; + if(c > 0) + { + fprintf(stderr, "- Bingo in %u if shoot ", a); + for(b=0; b 6) break; + } + fprintf(stderr, "\n"); + } + } + #endif + + #if 0 + {unsigned wasnew=1;for(a=0; a":""); + if(wasnew) fprintf(stderr, " - New: %04X", LastWrite0D); + fprintf(stderr, "\n");} + #endif + + /* + A0E4: + vertical-skrollaukseen liittyen + - temp on aina tällöin 0 + D6AD: + silloin kun nametableja kirjoitetaan uusiksi, + eli skrollaukseen liittyen + - temp on aina tällöin 1 + D04C: + while scrolling vertically + - temp on aina tällöin 2 + D69B: + silloin kun nametableja kirjoitetaan uusiksi, + eli skrollaukseen liittyen + myös asetta vaihdettaessa + - temp on aina tällöin 3 + B1E5: + kun asevalintadialogi aktivoituu + - ei muuta temppiä + D2A3, D3E9: + vuorotellen jatkuvasti + D252: + silloin kun lagittaa... + + */ + + LastWrite0D = 0x0000; + } + Write0D = 0; + } + unsigned BackupPC=_PC; +#endif b1=RdMem(_PC); //printf("$%04x, $%02x\n",_PC,b1); ADDCYC(CycTable[b1]); @@ -666,6 +860,10 @@ { #include "ops.h" } +#ifdef BISQWIT_ROCKMAN_DEBUGGATION + if(Write0D) LastWrite0D = BackupPC; +#endif + } #undef _PC --- fceu-orig/src/drivers/pc/input.c 2005-04-13 13:55:02.000000000 +0300 +++ fceu/src/drivers/pc/input.c 2005-10-03 10:09:44.150651969 +0300 @@ -19,6 +19,9 @@ */ #include +#include /* rand() */ +#include +#include #include "main.h" #include "dface.h" @@ -26,6 +29,229 @@ #include "../common/cheat.h" +#define BISQWIT_ROCKMAN_DEBUGGATION + + + int RockmanDisableVideo=0; +#ifdef BISQWIT_ROCKMAN_DEBUGGATION + // these externs are updated by x6502.c + extern int RockmanBonus1; // $3B=no bonus, $3C.. = bonus. $3F=BINGO + extern int RockmanBonus2; // $3B=no bonus, $3C.. = bonus. $3F=BINGO + extern int RockmanItem; // $3B=no bonus, $3C.. = bonus. $3F=BINGO + extern int RockmanHurt; // 1 = hurt + extern int RockmanKill; // nonzero = type of enemy + + /* Maximum length of the sequence */ + #define ROCKMAN_SEQMAX 120+1 + /* The item we want */ + #define ROCKMAN_BINGO 0x3B//0x3F + #define ROCKMAN_NOTHING 0x3B*0 + /* The number of those items we want */ + #define ROCKMAN_BINGONEED 1 + /* Maximum height of a jump in frames */ + #define MAX_JMPLEN 8 + + static struct RockmanMode + { + unsigned char Seq[ROCKMAN_SEQMAX]; + int BingoCount; + int SeqPos; + int Fastest; + } RockmanMode = { {}, -1, -1, -1 }; + + static const unsigned char RockmanRandomTable[] = + { + // 0x01=A, 0x02=B, 0x40=left, 0x80=right + 0x00,0x01, + 0x40,0x41, + 0x80,0x81, + + 0x01,0x41,0x81, + 0x01,0x41,0x81, + 0x01,0x41,0x81, + }; + void RockmanGenInput() + { + unsigned char input = 0x00; + static unsigned char LastInput = 0x00; + static unsigned jmplen = 0; + + if(!(rand()%20)) input |= 2; // shoot + if(!(rand()%20)) LastInput = RockmanRandomTable[rand()%sizeof(RockmanRandomTable)]; +#if 0 + if(RockmanMode.SeqPos < 20) { LastInput = 0x80; input = 0x00; } + else if(RockmanMode.SeqPos < 38) { LastInput = (LastInput & 0x3F) | 0x80; } + if(!(rand()%80)) input &= ~0xC0; /* clear movement */ + //if(!(rand()%40)) input ^= 0x40; +#endif + if(LastInput & 1) ++jmplen; else jmplen=0; + if(jmplen > MAX_JMPLEN) { jmplen=0; LastInput &= ~1; } + +#if 0 + if(RockmanMode.SeqPos < 23) { input |= 0x80; input &= ~0x40; } +#endif + + input |= LastInput; + RockmanMode.Seq[RockmanMode.SeqPos] = input; + } + void RockmanMsg(const char*fmt, ...) + { + FILE*fp; + + va_list ap; + va_start(ap,fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + fp = fopen("rockman.log", "at"); + if(!fp) fp = fopen("rockman.log", "wt"); + + va_start(ap,fmt); + vfprintf(fp, fmt, ap); + va_end(ap); + + fclose(fp); + } + void RockmanReset() + { + RockmanBonus1 = -1; + RockmanBonus2 = -1; + RockmanHurt = 0; + RockmanKill = 0; + RockmanItem = -1; + RockmanMode.SeqPos = 0; + RockmanMode.BingoCount = 0; + } + void RockmanStart() + { + fprintf(stderr,"RockmanStart\n"); + FCEUI_SelectState(1, 1); + FCEUI_SaveState(NULL); + if(!FCEUI_EmulationPaused()) FCEUI_ToggleEmulationPause(); + RockmanReset(); + RockmanGenInput(); + RockmanMode.Fastest = ROCKMAN_SEQMAX-1; + RockmanDisableVideo=1; + RockmanMsg("--------------- New run ------------------ \n"); + srand(time(NULL)); + } + void RockmanEnd() + { + fprintf(stderr,"RockmanEnd\n"); + RockmanMode.SeqPos = -1; + RockmanDisableVideo=0; + } + void RockmanStateDump() + { + fprintf(stderr,"\rRockmanIter, Fastest=%3d,SeqPos=%3d,Hurt=%02X,Bonus=%02X+%02X,Item=%02X,Kill=%02X", + RockmanMode.Fastest, + RockmanMode.SeqPos, + (unsigned char)RockmanHurt, + (unsigned char)RockmanBonus1, + (unsigned char)RockmanBonus2, + (unsigned char)RockmanItem, + (unsigned char)RockmanKill + ); + } + + void RockmanIter() + { + if(RockmanMode.SeqPos < 0) return; + + if(RockmanHurt + || RockmanItem >= 0 + || (RockmanBonus1 >= 0 + && RockmanBonus1 != ROCKMAN_BINGO + && RockmanBonus1 != ROCKMAN_NOTHING + ) + || (RockmanBonus2 >= 0 + && RockmanBonus2 != ROCKMAN_BINGO + && RockmanBonus2 != ROCKMAN_NOTHING + ) + || RockmanMode.SeqPos+1 > RockmanMode.Fastest) + { + //RockmanStateDump(); +Restart: + fprintf(stderr, "\r"); + FCEUI_LoadState(NULL); + fprintf(stderr, "\r"); // LoadState will display a line. + RockmanReset(); + } + else + ++RockmanMode.SeqPos; + +#if 1 + /* wait for item drops */ + if(RockmanBonus1 == ROCKMAN_BINGO + || RockmanBonus2 == ROCKMAN_BINGO) +#else + /* wait for a kill (for the bubblemachine fight) */ + if(RockmanKill > 0) +#endif + { + /* Got what we wanted. */ + RockmanStateDump(); + +#if 1 + /* wait for item drops */ + unsigned count = 0; + if(RockmanBonus1 == ROCKMAN_BINGO) ++count; + if(RockmanBonus2 == ROCKMAN_BINGO) ++count; +#else + /* wait for a kill (for the bubblemachine fight) */ + unsigned count = 1; +#endif + + RockmanMode.BingoCount += count; + if(RockmanMode.BingoCount >= ROCKMAN_BINGONEED) + { + /* Got enough of them. Report how we got there. */ + unsigned a; + RockmanMsg("\n***  Found %u*bingo in %u frames:\n", + RockmanMode.BingoCount, + RockmanMode.SeqPos); + for(a=0; a= 0) + { + FCEUI_SelectState(WillLoadState, 1); + FCEUI_LoadState(NULL); + WillLoadState = -1; +#ifdef BISQWIT_ROCKMAN_DEBUGGATION + unsigned a; + for(a=0; a<20; ++a) IncreaseEmulationSpeed(); + RockmanStart(); +#endif + } keys=GetKeyboard(); @@ -148,15 +418,18 @@ is_shift = KEY(LEFTSHIFT) | KEY(RIGHTSHIFT); is_alt = KEY(LEFTALT) | KEY(RIGHTALT); + is_ctrl = KEY(LEFTCONTROL) | KEY(RIGHTCONTROL); if(keyonly(F4)) { if(is_shift) FCEUI_SetRenderDisable(-1, 2); else FCEUI_SetRenderDisable(2, -1); } +#if 0 #ifdef SDL if(keyonly(ENTER) && is_alt) ToggleFS(); #endif +#endif NoWaiting&=~1; if(KEY(GRAVE)) @@ -175,23 +448,37 @@ if(keyonly(F2)) DoCheatSeq(); #endif - if(keyonly(1) && is_shift) + if(keyonly(1)) { + if(is_shift) + { char Buf[4096]; - fprintf(stderr, "Which file to create? (empty to cancel): "); fflush(stderr); + fprintf(stderr, "Which movie file to create? (empty to cancel): "); fflush(stderr); fgets(Buf, sizeof Buf, stdin); strtok(Buf, "\r\n"); if(*Buf) { - FCEUI_SaveMovie(Buf, 0, NULL); + char Buf2[16]; + int flag = 0; + fprintf(stderr, "From poweron? (Y/N, default Y): "); fflush(stderr); + fgets(Buf2, sizeof Buf2, stdin); + strtok(Buf2, "\r\n"); + if(tolower(*Buf2) != 'n') flag |= MOVIE_FLAG_FROM_RESET; + + FCEUI_SaveMovie(Buf, flag, NULL); } else fprintf(stderr, "Cancelled\n"); + } + else + keyonce[MKK(1)] = 0; } - if(keyonly(2) && is_shift) + if(keyonly(2)) { + if(is_shift) + { char Buf[4096]; - fprintf(stderr, "Which file to load? (empty to cancel): "); fflush(stderr); + fprintf(stderr, "Which movie file to load? (empty to cancel): "); fflush(stderr); fgets(Buf, sizeof Buf, stdin); strtok(Buf, "\r\n"); if(*Buf) @@ -200,29 +487,71 @@ } else fprintf(stderr, "Cancelled\n"); + } + else + keyonce[MKK(2)] = 0; } - if(keyonly(3) && is_shift) + if(keyonly(3)) { - FCEUI_StopMovie(); + if(is_shift) + FCEUI_StopMovie(); + else + keyonce[MKK(3)] = 0; // postpone to savestate check } + if(keyonly(5)) + { + if(is_shift) + { + unsigned a; + ComposeMode = !ComposeMode; + AnnounceComposeMode(); + for(a=0; a<4; ++a) + ComposeMasks[a] = 0; + } + else + keyonce[MKK(5)] = 0; // postpone to savestate check + } + +#ifdef BISQWIT_ROCKMAN_DEBUGGATION + if(keyonly(K)) + { + if(RockmanMode.SeqPos < 0) + RockmanStart(); + else + RockmanEnd(); + } + else RockmanIter(); +#endif if(keyonly(F5) || keyonly(S)) { FCEUI_SaveState(NULL); + if(ComposeMode) AnnounceComposeMode(); } +/**/ if(keyonly(F7) || keyonly(F)) { FCEUI_LoadState(NULL); + if(ComposeMode) AnnounceComposeMode(); } +/**/ } if(keyonly(F1)) FCEUI_ToggleTileView(); - if(keyonly(MINUS)) DecreaseEmulationSpeed(); - if(keyonly(EQUAL)) IncreaseEmulationSpeed(); + if(keyonly(KP_MINUS) || keyonly(N)) DecreaseEmulationSpeed(); + if(keyonly(KP_PLUS) || keyonly(M)) IncreaseEmulationSpeed(); if(keyonly(BACKSPACE)) FCEUI_MovieToggleFrameDisplay(); - if(keyonly(BACKSLASH)) FCEUI_ToggleEmulationPause(); - if(keyonly(RIGHTCONTROL)) FCEUI_FrameAdvance(); + if(keyonly(ENTER)) + { + FCEUI_ToggleEmulationPause(); + if(ComposeMode) AnnounceComposeMode(); + } + if(keyonly(QUOTE)) + { + FCEUI_FrameAdvance(); + if(ComposeMode) AnnounceComposeMode(); + } if(keyonly(F10)) FCEUI_ResetNES(); if(keyonly(F11)) FCEUI_PowerNES(); @@ -235,6 +564,7 @@ if(KEY(F12) || KEY(ESCAPE)) CloseGame(); #endif +#if 0 if(gametype==GIT_VSUNI) { if(keyonly(F8)) FCEUI_VSUniCoin(); @@ -254,6 +584,7 @@ if(keyonly(8)) FCEUI_VSUniToggleDIP(7); } else +#endif { static uint8 bbuf[32]; static int bbuft; @@ -291,6 +622,8 @@ } } DIPSless: + if(is_alt && !is_shift && !is_ctrl) + { if(keyonly(0)) SSM(0); if(keyonly(1)) SSM(1); if(keyonly(2)) SSM(2); @@ -301,6 +634,7 @@ if(keyonly(7)) SSM(7); if(keyonly(8)) SSM(8); if(keyonly(9)) SSM(9); + } #undef SSM } } @@ -315,27 +649,86 @@ ButtConfig GamePadConfig[4][10]={ /* Gamepad 1 */ { - MK(KP3),MK(KP2), - MK(TAB),MK(ENTER), + MK(D),MK(A), + MK(H),MK(P), - MK(W),MK(Z), - MK(A),MK(S), + MK(CURSORUP),MK(CURSORDOWN), + MK(CURSORLEFT),MK(CURSORRIGHT), /* arrows */ MKZ(), MKZ() }, /* Gamepad 2 */ - GPZ(), + { + /* gp2 A,B */ + MK(E),MK(Q), + /* gp2 select,start */ + MK(U),MK(O), + + /* gp2 arrows */ + MK(I),MK(K), + MK(J),MK(L), + }, /* Gamepad 3 */ - GPZ(), + { + /* gp1 alt A,B */ + MK(C),MK(Z), + MK(H),MK(P), + + MK(KP8),MK(KP2), + MK(KP4),MK(KP6) + }, /* Gamepad 4 */ GPZ() }; +static __inline__ unsigned char inportb(const unsigned short port) +{ + unsigned char _v; + __asm__ volatile ("inb %1,%0" + :"=a" (_v) + :"d" ((unsigned short)port)); + return _v; +} +static __inline__ void outportb(const unsigned short port, + const unsigned char value) +{ + __asm__ volatile ("outb %0,%1" + ::"a" ((char) value),"d" ((unsigned short) port)); +} +int IOPERM_Status=0; +static unsigned char ReadLPTport() +{ + static unsigned lptport=0x278; + unsigned a; + unsigned char ret = 0x00; + struct timespec delay; + + if(IOPERM_Status < 0) return 0; + + outportb(lptport,15); + delay.tv_sec = 0; + delay.tv_nsec = 1000; + + for(a=0; a<8; a++) + { + register int b; + + outportb(lptport, 3); + outportb(lptport, 1); + + b = ((signed char)inportb(lptport+1)) < 0; + ret |= (b << a); + + nanosleep(&delay, NULL); + } + return ret; +} + static void UpdateGamepad(void) { static int rapid=0; @@ -345,24 +738,56 @@ rapid^=1; + if(ComposeMode) + { + int press = 0; + for(wg=0;wg<4;wg++) + { + int ctrl = wg & 1; + for(x=0; x<8; ++x) + if(_keyonly(GamePadConfig[wg][x].ButtonNum[0])) + { + ++press; + ComposeMasks[ctrl] ^= 1 << x; + } + } + if(press) AnnounceComposeMode(); + for(wg=0;wg<4;wg++) + { + JS |= ComposeMasks[wg] << (wg << 3); + } + } +#ifdef BISQWIT_ROCKMAN_DEBUGGATION + if(RockmanMode.SeqPos >= 0) + JS |= RockmanMode.Seq[RockmanMode.SeqPos]; +#endif + for(wg=0;wg<4;wg++) { + int ctrl = wg & 1; for(x=0;x<8;x++) if(DTestButton(&GamePadConfig[wg][x])) - JS|=(1<=40){Frame=0;}else goto DisableVideo; + } +#endif if(BlitBuf) TmpScreen=BlitBuf; else TmpScreen=screen; @@ -416,9 +424,16 @@ } SDL_UpdateRect(screen, xo, yo, NWIDTH*exs, tlines*eys); + +#if NESVIDEOS_TRACKING + TILE_TrackFrame(screen->pixels, 256, tlines); +#endif + if(screen->flags&SDL_DOUBLEBUF) SDL_Flip(screen); + +DisableVideo:; } uint32 PtoV(uint16 x, uint16 y)