Devilmarkus Geschrieben 3. August 2012 Geschrieben 3. August 2012 Hallo zusammen, momentan beschäftige ich mit einer kleinen Portierung von C zu Java. Dabei bin ich auf ein kleines Problem gestossen: Eine Routine erreicht in meinem Code leider nicht die Punkte "set channel interrupt" und "stop channel". Ist das eventuell ein Fehler, der Aufgrund von Berechnungen erfolgt? Hier die Codebeispiele: C code (Original) void ASIC_DMA_ExecuteCommand(int ChannelIndex) { Z80_WORD Command; int CommandOpcode; int Addr; ASIC_DMA_CHANNEL *pChannel = &ASIC_Data.DMAChannel[ChannelIndex]; Addr = ASIC_Data.DMA[ChannelIndex].Addr.Addr_W; Command = ASIC_DMA_GetOpcode((Z80_WORD)(Addr & 0x0fffe)); CommandOpcode = (Command & 0x07000)>>12; Addr = Addr+2; if (CommandOpcode == 0) { /* LOAD R,D */ int Register; int Data; int PreviousRegisterSelected; /* PSG register */ Register = (Command>>8) & 0x0f; /* data to write */ Data = (Command & 0x0ff); /* store current selected PSG address register */ PreviousRegisterSelected = PSG_GetSelectedRegister(); /* select new register */ PSG_RegisterSelect(Register); /* write data */ PSG_WriteData(Data); /* select previous register again - not to upset other code */ PSG_RegisterSelect(PreviousRegisterSelected); } else { if (CommandOpcode & 0x01) { /* PAUSE n */ /* pause of 0 is equivalent to a NOP */ int PauseCount = Command & 0x0fff; if (PauseCount-1!=0) { pChannel->PauseCount = PauseCount-1; pChannel->PrescaleCount = ASIC_Data.DMA[ChannelIndex].Prescale; pChannel->PauseActive = TRUE; } } if (CommandOpcode & 0x02) { /* REPEAT n */ /* store repeat count */ pChannel->RepeatCount = Command & 0x0fff; /* set next instruction as loop start */ pChannel->LoopStart = Addr & 0x0ffff; } if (CommandOpcode & 0x04) { /* NOP, LOOP, INT, STOP */ if (Command & 0x0001) { /* LOOP */ /* if loop count is 0, this acts like a NOP */ /* check repeat count */ if (pChannel->RepeatCount!=0) { /* decrement count */ pChannel->RepeatCount--; /* reload channel addr from stored loop start */ Addr = pChannel->LoopStart; } } if (Command & 0x0010) { /* INT */ /* set channel interrupt */ ASIC_Data.InternalDCSR|=1<<(6-ChannelIndex); } if (Command & 0x0020) { /* STOP */ /* stop channel */ ASIC_Data.InternalDCSR&=~(1<<ChannelIndex); } } } ASIC_DMA_WriteChannelAddr(ChannelIndex, Addr); /* ASIC_Data.DMA[ChannelIndex].Addr.Addr_W=(unsigned short)Addr; */ ASIC_UpdateRAMWithInternalDCSR(); } Hier meine abgewandelte Java-Version: void ASIC_DMA_ExecuteCommand(int ChannelIndex) { // ASIC_DMA_CHANNEL pChannel[] = this.pChannel; int Command; int CommandOpcode; int Addr; Addr = DMA[ChannelIndex].Addr.getAddr_W(); Command = ASIC_DMA_GetOpcode((Addr & 0x0fffe)); CommandOpcode = (Command & 0x07000) >> 12; Addr = Addr + 2; if (CommandOpcode == 0) { /* * LOAD R,D */ int Register; int Data; int PreviousRegisterSelected; /* * PSG register */ Register = (Command >> 8) & 0x0f; /* * data to write */ Data = (Command & 0x0ff); /* * store current selected PSG address register */ PreviousRegisterSelected = psg.getSelectedRegister(); /* * select new register */ psg.setSelectedRegister(Register); /* * write data */ psg.writeData(Data); /* * select previous register again - not to upset other code */ psg.setSelectedRegister(PreviousRegisterSelected); } else { if ((CommandOpcode & 0x01) != 0) { /* * PAUSE n */ /* * pause of 0 is equivalent to a NOP */ int PauseCount = Command & 0x0fff; if (PauseCount - 1 != 0) { pChannel[ChannelIndex].PauseCount = PauseCount - 1; pChannel[ChannelIndex].PrescaleCount = 0;//ASIC_Data.DMA[ChannelIndex].Prescale; pChannel[ChannelIndex].PauseActive = true; } } if ((CommandOpcode & 0x02) != 0) { /* * REPEAT n */ /* * store repeat count */ pChannel[ChannelIndex].RepeatCount = Command & 0x0fff; /* * set next instruction as loop start */ pChannel[ChannelIndex].LoopStart = Addr & 0x0ffff; } if ((CommandOpcode & 0x04) != 0) { /* * NOP, LOOP, INT, STOP */ if ((Command & 0x0001) != 0) { /* * LOOP */ /* * if loop count is 0, this acts like a NOP */ /* * check repeat count */ if (pChannel[ChannelIndex].RepeatCount != 0) { /* * decrement count */ pChannel[ChannelIndex].RepeatCount--; /* * reload channel addr from stored loop start */ Addr = pChannel[ChannelIndex].LoopStart; } } if ((CommandOpcode & 0x0010) != 0) { /* * INT */ /* * set channel interrupt */ ASIC_Data.InternalDCSR |= 1 << (6 - ChannelIndex); } if ((CommandOpcode & 0x0020) != 0) { /* * STOP */ /* * stop channel */ ASIC_Data.InternalDCSR &= ~(1 << ChannelIndex); } } } ASIC_DMA_WriteChannelAddr(ChannelIndex, Addr); ASIC_UpdateRAMWithInternalDCSR(); } public class ASIC_ADDR { public addrb Addr_B = new addrb(); public void writeAddr_W(int word) { Addr_B.l = (word & 0xff); Addr_B.h = ((word >> 8) & 0x0ff); } class addrb { public int l; public int h; } public int getAddr_W() { return (Addr_B.l & 0xff) | ((Addr_B.h << 8) & 0xff00); } } Addr_B.l und Addr_B.h werden korrekt gesetzt (nicht hier im Code enthalten, da hierfür unwichtig) Gibt es zwischen C und Java mathematische Differenzen, welche ich hier nicht richtig berücksichtigt habe? Die "psg.setSelectedRegister" und - .writeData funktionieren auch korrekt! Es sieht aus, als ob der ChannelOpcode nicht richtig berechnet wird... Ich hoffe, mir kann hier jemand helfen Zitieren
flashpixx Geschrieben 3. August 2012 Geschrieben 3. August 2012 Ist das eventuell ein Fehler, der Aufgrund von Berechnungen erfolgt? Wie soll das hier jemand beantworten können !? Es sieht aus, als ob der ChannelOpcode nicht richtig berechnet wird... Dann solltest Du ihn vielleicht richtig berechnen. Warum benutzt Du keinen Debugger? Zitieren
Klotzkopp Geschrieben 3. August 2012 Geschrieben 3. August 2012 In den letzten beiden if-Anweisungen benutzt du in Java CommandOpcode, während in C Command benutzt wird. Zitieren
Devilmarkus Geschrieben 3. August 2012 Autor Geschrieben 3. August 2012 Ok... Ein Versuch: Wie kann ich in Java "unsigned short" simulieren? (Es ist tatsächlich abhängig davon!) Zitieren
Devilmarkus Geschrieben 3. August 2012 Autor Geschrieben 3. August 2012 Waaaahhhhh!!! Klotzkopp!!! Du bist mein Held!!!! Das war es!!! *knutsch* (Manchmal sieht man den Wald vor lauter Bäumen nicht) Zitieren
Devilmarkus Geschrieben 3. August 2012 Autor Geschrieben 3. August 2012 Paar Fehler sind zwar noch irgendwo versteckt (hat nichts mit diesem Thema zu tun), aber dank Klotzkopp funktioniert nun schon einiges mehr. Zum Testen: (Amstrad CPC+ Emulation) JavaCPC games site Im Menü die Standardversion und dann die Amstrad Plus Variante auswählen. Leertaste und Cursortasten fürs Menü. Joystick (im Spiel) liegt auf den Ziffernblocktasten bei Num-Lock ein. Die Raster (Interruptgeschaltet) verwalten hier die Farbbalken und Bildschirmanordnung. Ohne diesen Bugfix sah es Katastrophal aus!!! Also Danke nochmal an Klotzkopp!!! Zitieren
Gast runtimeterror Geschrieben 3. August 2012 Geschrieben 3. August 2012 Die Frage ist recht allgemein und so auch meine Antwort. Je nach Anwendungsfall: - einfach int verwenden und bei den Berechnungen auf die unteren 16 Bits beschränken - short verwenden und entsprechende Vorsicht und Korrekturmaßnahmen bei den Berechnungen anwenden. Ich hatte seinerzeit mal einen x86-Interpreter in Java verfasst und die erste Variante dafür verwendet - die ist weniger schmerzhaft. Falls du einen konkreten Anwendungsfall hast, kann man dir vielleicht gezielter helfen. Zitieren
Devilmarkus Geschrieben 3. August 2012 Autor Geschrieben 3. August 2012 Das Hauptproblem liegt leider darin, dass ich von der Original Hardware keinen Schimmer habe. Also weiss ich nicht, wann, wo in welchem Fall, welche Komponente einen Interrupt erzeugen soll / löschen soll. Ausserdem besteht der Emulator, welchen ich bearbeite, aus 'Mischcode'. Der Emulatorkern ist von 2002-2004 und seitdem kaum noch vom Originalautor überarbeitet worden. Im Prinzip bügel ich nur die Fehler aus, und verbessere die Emulation so gut ich kann, hier & da. Die "CPC Plus" Emulation ist dabei völliges Neuland für mich, und da adaptiere ich den Code, soweit ich ihn verstehe, von einem völlig anderen Emulator, welcher halt in C geschrieben wurde. Selbstverständlich habe ich Erlaubnis von allen Seiten, den Code zu verwenden und zu ändern. Der Rest basiert auf Trial- & Error... Zitieren
Gast runtimeterror Geschrieben 3. August 2012 Geschrieben 3. August 2012 Schreib einfach bei welchem konkreten C-Fragment du Probleme bei der Übersetzung zu Java hast. Bei dem Grundverständnis von dem, was du da tust kann dir wahrscheinlich nur jemand helfen, der in das Projekt involviert ist. Zitieren
metux Geschrieben 6. August 2012 Geschrieben 6. August 2012 Gibts dafür irgendwo eine git-repo ? Vielleicht find ich mal die Zeit, etwas tiefer reinzuschauen. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.