Beiträge von mceric

    Ich habe was für Fortgeschrittene:

    Habe hier ein Board mit einer Anschlussleiste mit 2.0mm(?) Pins.

    Wie bekomme ich die ,wenn überhaupt, an 2,54mm Standard Jumperkabel adaptiert?

    Die Frage ist: Was soll an die Pins angeschlossen werden? Ist es eine noch kleinere Konkurrenz zum Raspberry Pi? Oder sollen da vielleicht besonders kleine Festplatten dran? Oder irgendwas total anderes? Letztendlich gibts Anschlussleisten in vielen Rastern, 1,27, 2,0, 2,54, 3,81, 5,08 und so weiter, hängt halt immer vom Anwendungsfall ab :)

    Habe jetzt mal Bank 2 komplett geleert. Leider kein Unterschied. ...


    Meint Ihr ich könnte mal versuchen, ein anderes Rom einzusetzen?

    Also ich sehe da keine Gründe, ROMs zu wechseln, aber du hast genug ZA1250 um eine Bank komplett damit zu bestücken und die restlichen Chips inkl. dem, der es vermutlich nicht überlebt hat, falschherum eingebaut gewesen zu sein (bitte markieren!) für einen Test alle auszubauen.


    Wie man dann welche Jumper setzen muss, wenn z.B. Bank 1 leer ist und Bank 0 voller ZA1250s, wissen sicher andere hier besser.


    Ob du komplette Bänke rein und raus stecken kannst ohne dass ggf. antike Beinchen zu sehr verbogen werden, kann ich auch schlecht einschätzen. Wenn man es vorsichtig macht, sollte es eigentlich kein Problem sein. Auch aufpassen mit statischer Aufladung - zumindest erst mal die Masse vom PC / Board anfassen, bevor man die Chips anfasst?

    Chip richtig herum einstecken würde nicht schaden ja :D


    Auf den meisten Chips steht 1501834 RTI 8531 oder 8530, aber es gibt auch eine Reihe ZA1250NL (evtl. AP) 8514 (selten 8518) KA... und ein einzelnes KM4128-15. Aus der Perspektive kann ich auch nicht gut erkennen, ob alle Chips gut im Sockel sind und ob da jeweils 1 Chip drin ist oder evtl. je 2 gestapelte, was mich wundern würde?


    https://forum.vcfed.org/index.…eads/mk4128-dram.1239270/ klingt allerdings so als ob es tatsächlich gestapelte Chiptyp-Paare gibt!


    Das Foto auf https://www.minuszerodegrees.net/memory/41128.htm sieht so aus als ob KM4128U-15 gleich gestapelt geliefert wurden. Was es nicht alles gibt, man lernt nie aus! Und ZA1250NL sind wohl kompatibel - stehen in der gleichen Tabelle, 128k x 1 bit, 150ns, verbreitet auf IBM 5170.


    PS: Mir gefällt nicht, dass ALLE 1501834 in Bank 0 sind, aber EIN Chip in Bank 0 durch ZA1250NL ersetzt worden ist. In Bank 1 sind alle Chips entweder ZA1250NL oder KM4128-15, die man wahrscheinlich durchaus kombinieren kann. Aber die in Bank 0 könnten einheitlich anders sein und nicht mit dem ZA1250NL mischbar?

    Krass, dass es mal derart grosse Widerstandsnetze gab! Auch seltsam, dass das (Keramik?) Gehäuse zerbricht. Mechanik? Hitze? Und alle Widerstände sind trotz Riss gleich? Aber das mit den Tantals könnte eine Spur sein, vielleicht schliesst jetzt ein kaputter Tantal die Stromversorgung kurz? Letztendlich ist das aber nur geraten von mir.

    Hast du die Messungen gemacht während das Board lief? Wenn das Board aus war sollte das eigentlich nicht so schlimm sein, die Diodenmessung und Widerstandsmessung von Multimetern hält sich normal zurück mit dem Strom und die höhere Spannung müsste bei abgeschaltetem Board erträglich sein, aber ich lasse mich da auch gerne belehren.


    Und hast du ein Bild von dem Riss? Ich hatte auch mal ein Board was einfach NIX gemacht hat weil ein RAM-Modul einen Kurzschluss hatte. Das Netztteil konnte dann die Spannungen nicht hochfahren und hat es auch zum Glück nicht mit Gewalt versucht.

    Das ist eine spannende Frage! SBEMU bzw VSBHDA arbeitet auch mit virtuellen I/O Ports, da könnte sich was gegenseitig in den Weg geraten.

    Schau auch mal nach Optionen für verbesserte Kompatibilität, die dein EMM386 anbieten könnte.

    Bei CuteMouse funktionieren auch die Scrollrad-Optionen je nach Version ganz unterschiedlich, siehe CTMOUSE /? und Doku ;)

    Und CuteMouse 1.9 arbeitet sowieso immer im Rad-losen Modus, soweit ich mich erinnere.

    Laut Doku ist Cutemouse 2.0a für PS/2 eher direkt auf die (8042) Hardware orientiert,

    Cutemouse 2.1 (neueste dort: 2.1b4) arbeitet mit PS/2 BIOS und

    Cutemouse 1.9 (neueste da: 1.9.1 mit Kompatibilitäts-Verbesserungen im Vergleich zu 1.9) ist auch eher Hardware- statt BIOS-orientiert.

    Die 2.x Versionen unterstützen auch das Scrollrad der Maus.


    Das könnte bedeuten, dein PS/2 BIOS Support ist zu schlecht und du brauchst das Scrollrad?


    Sowas kann übrigens auch bei USB legacy support im BIOS passieren: Teilweise ist der besser darin, einen 8042 Controller zu simulieren als darin, PS/2 BIOS Funktionen für USB Mäuse zu unterstützen.

    Also ich würde annehmen, dass normalerweise PS/2 jeweils 1 serielle Schnittstelle anbietet und das BIOS damit rechnet, dass die Maus am Maus-Anschluss und die Tastatur-Anschluss ist und nicht umgekehrt. Ich erinnere mich auch vage an "1 PS/2 Gerät nach Wahl" Anschlüsse. Für 2 Geräte an 1 Buchse bräuchte man aber denke ich eine erweiterte Anschlussbelegung (ähnlich wie "MIDI Signale liegen an sonst freien Pins der Joystick-Buchse" bei bestimmten Soundkarten) und an sowas erinnere ich mich bei PS/2 nicht.

    im Assembler Bereich langt // XYZ /* XYZ */ im C/c++ teil müssen die lästigen ; immer zum trennen rein.

    Muss ich noch auf 8 ändern.

    Im C/C++ müssen die ; ans Ende von Befehlen, ja, aber in normalem Assembler macht man Kommentare mit ";" und nicht mit "//" oder "/* */", daher die Frage.

    Interessant dass in Assembler-Blöcken in Borland Kommentare im C/C++ Stil erlaubt sind.

    Das ist jetzt angenehm wenig Assembler in XMScopy :)


    Die [10] kannst du denke ich auf [8] reduzieren.


    Braucht Borland diese Kombination "; // Kommentar" oder reicht da ein "; Kommentar" in Assembler-Blöcken?


    In C++ Code wäre es "// Kommentar" und in C "/* Kommentar */" aber oft ist C++ Stil auch in C erlaubt.


    Das mit XMStest und XMSfehler ist irgendwie noch nicht optimal, ist aber nicht so schlimm.


    Hilfreicher wäre wahrscheinlich, den 8 nur in XMScopy verwendeten XMSxyz Variablen und Parametern vielsagendere Namen zu geben. Insbesondere weniger kurze.

    Als Static funktioniert es.

    Ansonsten tut der Assembler teil so als ob das Array nicht existiert, weder lesen noch schreiben, aber auch keine Fehler Meldung.

    Sehr schön, dann wird es mit static schon mal übersichtlicher :)


    Was genau meinst du mit "Assembler tut als ob Array nicht existiert"?


    Woran merkst du das?

    Wie sieht der Assembler-Teil jetzt aus, wie sieht die ganze XMScopy jetzt aus?

    Machst du diese

    Code
    XMSsi[0] = XMSbl;
    // etc.

    etc. Sachen jetzt endlich in C? :)


    Bevor du die 64000 Texturen fertig zeichnest, würde ich auch gerne nochmal nach Optimierungsgelegenheiten für die FPS gucken ;)

    Wenn ich jetzt XMSsi in die Funktion packe funktioniert der Code nicht, habe ich grad festgestellt.

    Auch nicht wenn du es static machst?


    Wenn du es dort lässt wo du es ursprünglich hattest, funktioniert es dann wenigstens, einen Teil des Assembler-Krams wie vorgeschlagen durch C zu ersetzen?


    Und wenn irgendwas in irgendeiner Situation nicht funktioniert, kannst du dann das nicht funktionieren genauer beschreiben oder debuggen? Was genau geht wie schief?

    Code
    mov si,offset XMSsi //<<< Pointer zu einem Array welches gross genug für di Daten ist unsigned int[10]!

    SI ist ein Zeiger Register... Pointer zu einem Array welches die korrekte grösse hat es sind im Grunde 10x 16bit ...

    Also wenn der Array nicht "far" ist, müsste es so deutlich besser funktionieren, weil du jetzt SI auf eine definierte und dafür gedachte Stelle für deine Daten zeigen lässt :)


    Aber: Wieso machst du XMSsi global und zehn 16-Bit Worte (unsigned int) lang? Eigentlich müssten 8 statt 10 reichen.


    Für die Lesbarkeit solltest du XMSsi wenigstens innerhalb von XMScopy definieren, sogar wenn es im globalen RAM bleiben muss. Dann steht es wenigstens im Quelltext an der richtigen Stelle und ist nur innerhalb von XMScopy ansprechbar und nicht mehr global:


    Code
    int XMScopy(unsigned int XMSqh ,unsigned int XMSqo,unsigned int XMSqs,unsigned int XMSzh,unsigned int XMSzo,unsigned int XMSzs,unsigned long XMSb ){
        static unsigned int near XMSsi[8];
    ...


    Das ausdrückliche "near" ist wahrscheinlich unnötig.


    Wenn bei dir Stack Segment = Daten Segment ist, kannst du den XMSsi Array sogar ganz in die XMScopy Funktion verschieben, statt ihn global zu machen.


    Eigentlich spricht absolut nichts dagegen, die Variable im C-Code zu befüllen. Das ist viel lesbarer als die ganzen "mov ax, VARIABLE" und "mov word ptr OFFSET[si]" Zeilen:

    Code
    XMSsi[0] = XMSbl; // untere 16 bit Laenge
    XMSsi[1] = XMSbh; // obere 16 bit Laenge
    XMSsi[2] = XMSqh; // Quellhandle
    XMSsi[3] = XMSqo; // Quelloffset (DOS) oder untere 16 bit davon (XMS)
    XMSsi[4] = XMSqs; // Quellsegment (DOS) oder obere 16 bit des Offsets (XMS)
    XMSsi[5] = XMSzh; // Zielhandle
    XMSsi[6] = XMSzo; // Zieloffset (DOS) oder untere 16 bit davon (XMS)
    XMSsi[7] = XMSzs; // Zielsegment (DOS) oder obere 16 bit des Offsets (XMS)


    Du solltest die Variable aber sowieso auch nicht XMSsi nennen. Sie hat keinerlei besondere Beziehung zu SI. Nenne sie lieber EMMstructure oder so ähnlich.


    SI ist nicht immer ein Zeiger-Register, aber du übergibst dem XMS Treiber einen far Zeiger auf die EMM Datenstruktur mit Informationen über die zu kopierenden XMS Bereiche in DS:SI, also wird es in dem Moment als Zeiger verwendet. Wenn die Variable far wäre, müsstest du also auch noch ds = seg XMSsi machen, aber das gibt ggf. einen Konflikt mit der Art, in der du call XMSvec machst. Also mach sie lieber nicht far ;)

    Also ich würde trotzdem sagen:

    Zusätzlich solltest du DS und SI auf einen Ort zeigen lassen, von dem du SICHER weisst, dass du dort deine EMM Structure hinschreiben darfst...



    Ich würde dir sehr empfehlen, den ganzen Zirkus rund um die EMM Structure in den C-Anteil von XMScopy zu verschieben. Also ganz gemütlich die komplette EMM Structure in C produzieren und dann dem asm-Block nur noch die Adresse der EMM Structure übergeben statt der vielen kleinen Variablen die du jetzt alle einzeln in Assembler dort rein bastelst. Das in C zu machen spart eine Menge Stress und potentieller Bugs.

    Bisher wird SI irgendwie überhaupt nicht gesetzt, das kommt mir sehr verdächtig vor. Und in C ist die ganze XMScopy Sache einfach sehr viel einfacher.


    Je nach Compiler kann man sich oft sparen, AX zu sichern. Bei GNU C kann man sogar ganze Funktionen in Assembler schreiben und dann angeben, welcher Parameter/Argument in welchem Register übergeben werden soll, inklusive dem Rückgabewert. Das spart oft zusätzliche Zwischenlager in Variablen.

    wenn ich im Compiler Register Variables auf none stelle, dann funktioniert es auch.


    Ist das zufall oder hat hier der Compiler meine Variable geschreddert?

    Eher umgekehrt. Wenn du dem Compiler sagst, er kann Register für Variablen und Zwischenergebnisse verwenden, dann musst du auch mit ihm darüber kommunizieren, wer wann welche Register wofür verwendet. DX und AX werden eigentlich immer als "enthalten irgendwas was man in dem Moment berechnet" verwendet, also fast nie um längere Zeit irgendwelche Variablen aufzubewahren. Die kannst du in asm-Blöcken ziemlich hemmungslos verwenden.


    Der asm-Code von XMScopy verändert aber auch BX (eigentlich nur BL) und geht davon aus, dass SI auf irgendeinen Speicherbereich zeigt, in dem du deine EMM Structure zusammenbauen kannst. Das ist schlecht. Dein asm-Code sollte mit PUSH BX und PUSH SI anfangen und mit POP SI und POP BX aufhören, damit er nicht BX und SI verändert, die vielleicht gerade vom Compiler anderen Zwecken zugewiesen worden sind.


    Zusätzlich solltest du DS und SI auf einen Ort zeigen lassen, von dem du SICHER weisst, dass du dort deine EMM Structure hinschreiben darfst. Sonst kann DS:[SI] bis inkl. DS:[SI+15] (oder in Borland Stil: word ptr 14[SI] irgendwelche völlig anderen Daten oder sogar Code enthalten, die du jedes Mal zerstörst, wenn du XMScopy benutzt.


    Du könntest zum Beispiel einen Array von acht 16-Bit Worten namens EMMstructure anlegen, wahlweise global oder auf dem Stack, und dann in deinem asm-Block DS und SI auf die Adresse dieses Arrays einstellen. Je nach Speichermodell musst du zusätzlich unbedingt darauf achten, dass der Compiler die Segmente nicht durcheinanderbringt.


    Aktuell erwähnst du für XMStest, XMSfehler und die ganzen an XMScopy übergebenen Sachen nie ein Segment und für die Struktur ab DS:SI auch nicht. Also nimmst du wahrscheinlich an, dass sie alle im gleichen Segment sind. Das funktioniert nur in einem Speichermodell, in dem fast alle Variablen near sind und sich mit dem Stack die gleichen 64 kB teilen. Vielleicht kümmert sich auch der Compiler selbst teilweise darum, indem er deinen asm-Code um passende DS: oder ES: oder SS: Angaben ergänzt, aber wie Borland das handhabt, weiss ich nicht. Jedenfalls muss deine Struktur auf DS:SI entweder so liegen, dass sie das gleiche DS hat wie XMStest, XMSfehler und die Argumente von XMScopy, oder du müsstest überall explizit mit den verschiedenen Segmenten umgehen und ein PUSH DS und POP DS am Anfang und Ende von deinem asm-Block ergänzen.


    Ich würde dir sehr empfehlen, den ganzen Zirkus rund um die EMM Structure in den C-Anteil von XMScopy zu verschieben. Also ganz gemütlich die komplette EMM Structure in C produzieren und dann dem asm-Block nur noch die Adresse der EMM Structure übergeben statt der vielen kleinen Variablen die du jetzt alle einzeln in Assembler dort rein bastelst. Das in C zu machen spart eine Menge Stress und potentieller Bugs.

    Ich schlage vor, du lässt XMScopy die tatsächlich empfangenen Werte anzeigen, damit du drüber schauen kannst, ob sich irgendwo irgendwas verrechnet.


    Statt unsigned int könntest du auch einen extra zu dem Zweck definierten uint16 Typ verwenden, um deutlicher zu machen, was wo übergeben wird.


    XMScopy könnte statt ZWEI 16-bit Werten (entweder Segment und Offset im DOS Speicher oder obere und untere 16 Bit des XMS-Offsets) auch EINEN 32-bit Wert annehmen. Far Pointer sind sowieso 32 Bit und der 32 Bit Offset auch. Dann sparst du dir in beiden Fällen die Umrechnung. Noch eleganter wäre eine union, die die gleichen 4 Bytes einmal als 16 Bit DOS Segment und 16 Bit DOS Offset und einmal als einen 32 Bit Offset interpretiert, für bessere Lesbarkeit.


    Code
    unsigned int XMSbl=XMSb;
    unsigned int XMSbh=XMSb>>16;

    Das ist eine eher unleserliche Methode, 32 Bit "XMSb" zu zerstückeln. Lass das lieber an einem 32 Bit Stück. Ich vermisse auch ein XMSbl = XMSb & 0xffff um zumindest explizit zu machen, dass die oberen 16 Bit der 32 Bit Variable bewusst verworfen werden, wenn du die unteren in eine 16 Bit Variable rüberkopierst.


    Es ist natürlich auch ein wenig eine Glaubensfrage, aber willst du dir wirklich den Schmerz mit den vielen 16-Bit Stücken von 32-Bit Variablen antun, damit dein Spiel auf 286 lauffähig bleibt? Wenn du einen 386 als Mindestanforderung nimmst, kannst du bequem 32 Bit am Stück in einem Register wie EAX transportieren. Und auf älteren als 286 PC läuft das Spiel sowieso nicht, weil es dort kein XMS geben kann. Mal ganz abgesehen von der Geschwindigkeit ;)


    Code
    ... (DCa<<16)>>16,DCa>>16, ...

    Auch hier würde ich wieder sagen: Übergib lieber 32 Bit am Stück, statt den DCa (seltsamer Name für "Quelloffset der gewünschten Textur im XMS Block") auf seltsame Weise in zwei 16-Bit Teile zu zerlegen. Und wieso machst du diesmal "32 Bit Variable um 16 Bit nach links schieben, dann wieder 16 Bit nach rechts, dann in 16 Bit Argument kopieren", während du bei XMSbl überhaupt nicht geschoben hast? Anders gesagt, du könntest es so machen:

    Code
    ... DCa & 0xffff, DCa >> 16, ...

    oder eben noch besser mit weniger, aber dafür 32 Bit Argumenten:


    Dass dein XMS Handle den festgelegten Wert 1 genau in dem Moment bekommt, zu dem getsprite ihn wissen will, kann eigentlich auch nicht sein. Der Handle sollte vom Treiber beantragt werden, Handle 1 kann wer weiss was sein. Wenn du den Eindruck hast, dass der Handle Wert manchmal verloren geht, mach lieber was in der Richtung von "if XMShandle < 1 then gibt Fehlermeldung aus, dass XMS Handle auf einmal auf DOS Speicher zeigt, und bricht das Programm an der Stelle ganz ab, oder brich wenigstens getsprite ab".


    Wegen diesem "Buche den Handle bevor die Borland IDE startet und gib ihn dann wieder frei, damit das Spiel ihn verwenden kann", kannst du ja trotzdem deine "Besorge dir einen 4 MB XMS Handle" Funktion zu Testzwecken immer 1 returnen lassen, aber die 1 (oder besser ein einstellbarer Wert, evtl. per Command Line Argument deines Spiels einstellbar) sollte nur an dieser einen einzigen Stelle im Quelltext vorkommen und nicht erst mitten in getsprite auftauchen.


    Wie ist in dem Zusammenhang das hier gemeint?

    Code
    if (XMShandle!=1) Xprint(28,10,14,"XMSHANDLE");//Speicherbedarf am Anfang anzeigen
    if (XMShandle!=1) Xprint(28,30,12,TNr);//Speicherbedarf am Anfang anzeigen

    Es scheint in die Richtung von "wenn XMShandle noch nicht gebucht ist, gib irgendwas aus" zu gehen, aber das ist wie gesagt gar nicht die richtige Stelle, um den Handle zu buchen. Ausserdem ist es seltsam, dass Xprint sowohl Strings als auch Integers wie TNr ausgeben kann, wie macht es das?


    Wenn ich als Quelle den richtigen Handle wähle und als ersten Byte im Speicher 142614 >> müsste dann Offset 11542 / Segment 2 sein. Dann tritt der Fehler auf. Bei niedrigeren Adressen und teilweise bei höheren tritt der Fehler nicht auf.

    Merkwürdig das der Fehler auftritt wenn ich die Quelladresse ändere, die Zieladresse bleibt immer gleich. Also dürfte ja eigentlich nichts überschrieben werden, weil ich ja nur wo anders lese.


    Merkwürdig ist, wenn ich die Variable XMShandle später initialisiere (ein Array von 909 Chars habe ich jetzt einfach davor zuteilen lassen) dann tritt der Fehler nicht auf.

    Hierdurch ändert sich ja die Adresse der Variable... also scheint irgendwas die Adresse gezielt zu überschreiben.

    Also zunächst mal... wenn du XMSBlock[142614] zugreifen willst, ist 142614 einfach ein 32-bit Offset. Die obere Hälfte ist dann kein Segment, sondern nur die oberen 16 Bit vom 32-bit Wert.


    Ich zitiere mal aus RBIL, Int 2F Funktion 4310 etc. XMS:



    Interessanterweise sind die real-mode Adressen dabei allerdings normale Far Pointer. Wenn du also Arbeitsspeicher[142614] zugreifen willst, also Arbeitsspeicher[0x22d16] dann wäre das Handle 0 und "Offset" 0x22d10006 damit es als Far Pointer 0x22d1:0x0006 interpretiert wird. Wie du den Pointer "normalisierst" ist dabei dir überlassen, "Offset" 0x20002d16 zeigt auf die gleiche Speicheradresse.


    XMSBlock[142614] musst du andererseits als Handle XMSHandle, Offset 0x00022d16 ansprechen, also untere 16 Bit 0x2d16, obere 16 Bit 0x0002.


    Es könnte auch interessant sein, deinem Programm einen Nicht-Grafik-Testmodus zu geben, bei dem der PC im Textmodus bleibt (die Zugriffe auf den Grafikspeicher auf 0xa000:nnnn laufen dann halt ins Leere) damit du viele wissenswerte Debug-Meldungen über printf ausgeben kannst. Zum Beispiel die Parameter der XMS-Zugriffe, um zu sehen, ob sie deinen Erwartungen entsprechen.


    Sich versehentlich irgendwelche Speicherinhalte zu zerstören ist leider in C-Programmen ein häufiges Problem. Du könntest zwar Breakpoints setzen und dann per Debugger Speicherinhalte anschauen oder schrittweise durch die Assembler- bzw. Maschinencode-Befehle gehen, um zu sehen, wo Dinge schiefgehen, aber da verzettelt man sich sehr schnell. Ein paar Zeilen C-Code können sehr viele Zeilen Assembler sein.


    Wenn deine IDE bzw. dein Debugger genügend Power haben, kannst du auch logische Breakpoints setzen. Sowas wie "Programm anhalten und anzeigen, wo im Quelltext es gerade war, sobald der Wert von XMSHandle sich ändert". Das Programm läuft dann zwar sehr langsam, während der Debugger es beobachtet, aber es bleibt dann exakt an der Stelle stehen, an der dein XMSHandle zerstört wird.


    Man kann das Programm so nicht von den meisten compilern starten, weil diese während der Ausführung meist selber den kompletten speicher reservieren!

    Du meinst nicht Compiler, sondern du meinst glaube ich IDE? Und du meinst nicht die meisten, du meinst nur die von Borland, nehme ich an? ;)

    Jetzt musst du den Sprite-Anzeigecode so lange optimieren, bis der XMS doch zum Flaschenhals wird ;)


    Je nach Compiler ist es auch immer interessant, Profiling zu machen. Dazu kompiliert man das Programm in einer speziellen Profiling-Version, benutzt es eine Weile, und bekommt am Ende Statistiken in eine Datei, wie viel Prozent der Zeit es in welchen Funktionen verbraucht hat und welche Funktionen wie oft aufgerufen wurden :)


    Man kann das Profiling ggf. auf exakt (verlangsamt das Programm evtl. merklich) oder auf Stichproben einstellen. Bei Stichproben wird in regelmässigen Abständen geschaut, welche Funktion in dem Moment läuft, was das Programm während dem Testlauf kaum verlangsamt.