Login
Back to forumSee the full topicGo to last reply

Posted By

BSZ
on 2021-06-07
06:46:57
 Re: Let’s JoyTest! :)

Ígértem pár kiegészítést a témához…

Először is: elég konzisztensnek tűnik a „hibás” TED-ek viselkedése. De ez egy olyan teszt, ahol nincs „deadline”! Nevezni ér ám a későbbiekben is bármikor! happy Viszont… A kérdés az, hogy most akkor mindenki álljon neki a meglevő programokat „patch”-elgetni, hogy működjenek a „hibás” TED-es gépeken is? Szerintem NE! Régen nagyon sok olyan C16-os / plus/4-es felhasználó volt, akinek egyáltalán nem volt Joystick-je (talán a „szabványos” csatlakozónak hála… happy ), emiatt szerintem inkább az a fontos, hogy a játékoknak legyen csak billentyűzettel is játszható üzemmódja. Persze ha valaki maximalista, felkészítheti a programját ennek a szituációnak a kezelésére is, de ez azért ne legyen elvárás. grin

Itt feljebb már kitárgyalódott happy a lényeg, ami ugye az, hogy a „rossz” TED nem csak az $FF08-as regiszter írásakor tárolja a bemenetein jelen levő adatot, hanem minden memóriaciklusban megteszi ezt. (Erről – ha valakit érdekel – esetleg írhatok bővebben.) Ha a CPU dupla órajelen jár, akkor az előző ciklus az pont az olvasó utasításban szereplő ($FF08-as) cím felső BYTE-ja, tehát $FF lesz, ami nem választja ki egyik Joy-t sem. Az egyszeres órajellel pont ide sikerül „becsempészni” egy olyan BYTE-ot, ami a kívánt Joy-t ki tudja választani. Annyi viszont fontos, hogy itt a TED-nek ne legyen „más dolga”, mert akkor azt fogja olvasni a kívánt adat helyett. Ezt a „más dolgot” úgy lehet a legkönnyebben elkerülni, ha egyrészt a kép alsó/felső keretén fut a rutinunk, másrészt a rasztersoron belül is elkerüljük a kép jobb szélét (azt, ahol éppen kezdődik a keret az aktív tartalomnál). Ehhez én egy egyszerű rutint csináltam. A lekérdező rutin megszakításban fut, $0D0 raszterpozícióra van az időpont állítva, ahol (a megfelelő előkészületek után) az alábbi program indul el:

        LDA #%11111111
        STA $FD30
        LDA $FF13
        PHA
        ORA #%00000010
        STA $FF13
        STA $FF3F
        LDA $FFFF
        PHA

Ez kitiltja a billentyűzet összes sorát, hogy annak a nyomkodása ne okozzon Joystick-irány érzékelést. (Ezt a nyitó posztban említettem; több (megfelelő) gomb lenyomásával még így is lehet „fantom” Joy irányt produkálni, de ez nem a „hibás” TED lekérdezésének a mellékterméke, a „jó” verzió ugyanígy működik.) Aztán 1×-es órajelre kapcsol a kód, meg bekapcsolja a RAM-elérést. (A TED, amikor azt a memóriacímet olvassa, amit itt használatban van, azt ugyanabból a memóriából teszi, mint a CPU is tenné.) Illetve állapotot ment, hogy a végén majd vissza lehessen állítani. Utána jöhet az olvasás:

        LDX #%11111011  ;Joy Lo
        LDY #%11111101  ;Joy Hi
        LDA $FF1D
.W1  CMP $FF1D
        BEQ .W1
        STX $FFFF
        STX $FF08
        LDA $FF08
        STA $0C00
        STY $FFFF
        STY $FF08
        LDA $FF08
        STA $0C01  All: 32 single clock cycles

Ez a rutin megvár egy új rasztersort, ekkor a programfutás biztosan a sor elején van, „messze van még” a sor vége (ahol a TED-nek „más dolga van”, memóriát frissít, nem $FFFF-et olvas). Utána $FFFF-be és $FF08-ba is be van írva a Joy kiválasztó BYTE, utána az így vagy úgy tárolt érték van visszaolvasva $FF08-ból. Amennyiben a TED „jó”, akkor az $FF08-ra íráskor tárolt változat lesz $FF08-ban, ha a TED „rossz”, akkor az előző ciklus, de ott is ugyanaz a Joy van kiválasztva. Azaz: ez a rutin mind a „rossz”, mind a „jó” TED-nél a megfelelő adatot adja vissza. A rasztersorban elvileg belefér mindkét Joy állapotának a lekérdezése, a beolvasott állapotok itt a képernyő tetejére íródnak ki.

A Joy-ok lekérdezése ennyi, viszont itt fontos megemlíteni egy dolgot. A „rossz” TED-nél a működési mód miatt előfordulhat az az eset, hogy a billentyűzet lekérdezésébe a Joy mozgatása „fantom” billentyű-lenyomásokat produkál. (Ha a lekérdezés alatt a CPU-t egyszeres órajelre kapcsolja a TED, akkor az általa olvasott adat engedélyezheti a billentyűzet mellett az egyik/mindkét Joy-t is!) Tehát ha egy program egy időben akar Joy-t és billentyűzetet is vizsgálni, akkor a billentyűzet lekérdezését is ennek megfelelően kell megcsinálni! Erre itt a folytatás:

        LDA #%00000000  ;Double Clock mode selected
        STA $FF13
        LDX #%11111111  ;No Joy line selected
        LDA $FF1D
.W2   CMP $FF1D
        BEQ .W2
        LDA #%01111111
        STA $FD30
        STX $FF08
        LDA $FF08
        STA $0C28
        LDA #%10111111
        STA $FD30
        STX $FF08
        LDA $FF08
        STA $0C29
        LDA #%11011111
        STA $FD30
        STX $FF08
        LDA $FF08
        STA $0C2A
        LDA #%11101111
        STA $FD30
        STX $FF08
        LDA $FF08
        STA $0C2B  ;4 All: 72 double clock cycles

Ez először visszakapcsolja a dupla-órajelet, majd vár egy új rasztersorra. A kereten így közel dupla annyi órajel lesz mint egyszeres módban, emiatt egy rasztersorba 4 billentyűsor lekérdezése is belefér. Az LDA $FF08 utasításoknál így mindig a cím felső BYTE-ja (azaz $FF) lesz a buszon az olvasást megelőző ciklusban, így egyik Joy sem lesz aktív a lekérdezésnél. Hogy ez a feltétel teljesüljön a „jó” TED esetén is, ezért minden egyes sor vizsgálatánál $FF van $FF08-ba írva! A fenti sorok 4 billentyűsort olvasnak be (és az eredményt kirakják a képernyőre jelenleg), a másik 4 sor lekérdezése ugyanez, kezdve az új sor várásával. (Értelemszerűen az $FD30-ba írandó értékek mások.)

A fenti kódból a nem vizsgálandó Joy-ok / billentyűsorok tetszés szerint elhagyhatók. Ezután már csak az „elrontott dolgok” visszaállítása van hátra:

        PLA
        STA $FFFF  ;IRQ vector restore
        PLA
        STA $ff13  ;Chargen. address + speed restore
        AND #%00000001
        BEQ .RAM
        STA $FF3E  ;ROM/RAM restore
.RAM RTS

Itt az elrontott megszakítás vektor / $FF13 / ROM/RAM van visszaállítva a kiindulási állapotra. Remélem nem kavartam el semmit. A fenti kódból csináltam egy letölthető / próbálgatható változatot:

http://bsz.amigaspirit.hu/hidtest/CBM264/JoyBKQuery_for_badTED.zip

Ez – a mostani tesztelésem szerint – működik, de remélem a fentiekben sem írtam el semmit.

 Re: Let’s JoyTest! :)

I promised some supplementary information...

First of all, the behaviour of "failing" TEDs seems to be quite consistent. However, this is a test without deadline. Feel free to "enter the competition" whenever it is convenient for you in the future. happy Now the question is if everybody should start patching their programs to run of machines with "failing" TEDs? In my opinion NOT. Back in the old days, there were a lot of C16 and plus/4 users who had no joystick whatsoever, thanks to the "standard" connector maybe happy, therefore it is more important to have keyboard control in games IMHO. Perfectionists should feel free to prepare their programs to deal with such a situation but that shouldn't be a requirement. grin

The important details are already been discussed here above happy, namely that "broken" TEDs store input data not only at the writes of register $FF08 but at every memory cycle. If there is interest in this topic I may write up some more details about. When the CPU runs at double clock then the preceding cycle will be exactly the high byte of the read instruction's address ($FF08) which does not select any joysticks. It is possible to "foist" a byte suitable to select the desired joystick here while running at single clock. It is very important that TED should have no other task because that will interfere with reading the necessary data. It is the easiest to avoid any so called other tasks by running the code in the top or bottom border while avoiding the right side of the screen, that is the part where border starts in the open screen area. I wrote a simple routine for that. The query runs in interrupts triggered at raster position $0D0 where after the necessary preparations the following code runs:

LDA #%11111111
STA $FD30
LDA $FF13
PHA
ORA #%00000010
STA $FF13
STA $FF3F
LDA $FFFF
PHA

This deselects all keyboard line so key presses won't cause interference in detecting joystick directions. I already wrote in the OP that pressing some (appropriate) keys at the same time allows generating "phantom" joystick directions independent of the TED being "broken" or "good". The the code sets single clock and pages away the ROM. The address in use in this code is read from the same source the CPU would be reading it. Furthermore, it saves some states to be restored later. Next comes the querying:

LDX #%11111011 ;Joy Lo
LDY #%11111101 ;Joy Hi
LDA $FF1D
.W1 CMP $FF1D
BEQ .W1
STX $FFFF
STX $FF08
LDA $FF08
STA $0C00
STY $FFFF
STY $FF08
LDA $FF08
STA $0C01 All: 32 single clock cycles

This routine waits for the next raster line to make sure that the end of the line, where TED has the different task of refreshing memory instead of reading $FFFF, is still "far away". After that joystick selection byte is written into $FFFF and $FF08, after which the value store in one of the previous ways will be read out from $FF08. If TED is "good" then the one stored at the time of writing $FF08 otherwise the one from the preceding cycle as both select the same joystick. This routine returns the proper data independent of if TED is "good" or "broken". Theoretically it is possible to read the state of both joysticks in one single raster line; the result of which being written to the top of the screen in the routine.

That is all about querying the joysticks but it is important mentioning another thing. The mode of operation in case of a "broken" TED may result in joystick movement generating "phantom" key presses when querying the keys. If TED sets single clock for the CPU during querying it may cause enabling one or both joysticks as a side effect of the read data. So if a programme wants to query both the joysticks and the keyboard at the same time then querying the keyboard must be written accordingly. For that, here is the continuation of the code:

LDA #%00000000 ;Double Clock mode selected
STA $FF13
LDX #%11111111 ;No Joy line selected
LDA $FF1D
.W2 CMP $FF1D
BEQ .W2
LDA #%01111111
STA $FD30
STX $FF08
LDA $FF08
STA $0C28
LDA #%10111111
STA $FD30
STX $FF08
LDA $FF08
STA $0C29
LDA #%11011111
STA $FD30
STX $FF08
LDA $FF08
STA $0C2A
LDA #%11101111
STA $FD30
STX $FF08
LDA $FF08
STA $0C2B ;4 All: 72 double clock cycles

First it restores double clock then waits for the next raster line. There will be almost twice as muck clock cycles in the border as in single clock mode allowing the query of up to 4 keyboard rows. There will always be the high byte of the address ($FF) of the LDA $FF08 instruction on the data bus in the cycle preceding the keyboard row query, so no joystick will be active during the read. To make this condition met in case of "good" TEDs there is $FF written into $FF08 at every keyboard row queries. The code above reads 4 rows and put the results to the screen at this time. The query of the other 4 rows is the same including the wait for next raster line. The values to be written to $FD30 are obviously different.

You may omit the joysticks and rows not needed to be queried at will. Now all that's left is restoring the things that were messed up:

PLA
STA $FFFF ;IRQ vector restore
PLA
STA $ff13 ;Chargen. address + speed restore
AND #%00000001
BEQ .RAM
STA $FF3E ;ROM/RAM restore
.RAM RTS

Here there are the tampered interrupt vector, $FF13 value and ROM paging state restored to the original state. I hope I didn't mix up anything. grin There is a programme to download and test this routine:

http://bsz.amigaspirit.hu/hidtest/CBM264/JoyBKQuery_for_badTED.zip

That should work or at least that's what my test indicates so far. I hope I didn't make any clerical errors either.



Back to top


Copyright © Plus/4 World Team, 2001-2024