forum speccy.pl

ZX Spectrum => PROGRAMOWANIE => Wątek zaczęty przez: pgru w 2018.04.26, 21:15:44

Tytuł: Problem z odczytem joysticka.
Wiadomość wysłana przez: pgru w 2018.04.26, 21:15:44
W Fuse wszystko działa. Natomiast jak testuję na realnym sprzęcie(Elwro 800 Jr, bez problemu radzi sobie z innymi grami i joystick działa) nie mogę poprawnie odczytać:
pętla zwalniająca -  w trakcie której powinien nastąpić odczyt danych i przerwanie, jeśli następuje ruch postacią:
int petlazwalniajaca(long int n){
long int nk,nl;
int nb;
char klawsz;
nl=1;
/*
for(nk=0;nk<n;nk++)
{nb=nb*(nb+1);
//przerwanie petli zwalniającej w czasie ruchu gracza
if(joystick()!=0) return;
};
*/
for(nk=0;nk<n;nk++)
{
if(joystick()!=0) return;
//scanf("%c",klawsz);
// printf("c %c ",klawsz);
if(klawiatura()==5) printf("kursor w prawo");
};

}

Odczyt joysticka

int joystick(){
/*int k;
int n;
n=0; */
/*
while(1){k=joystickK();
if(k!=n)
{n=k;
printf(" %d ", k);
}}; */
// zwracamy wartości
// zwrotny 1 - przycisk - w Spectrum 16
// zwrotny 2 - góra - w Spectrum 8
// zwrotny 3 - lewo - w Spectrum 2
// zwrotny 4 - dół - w Spectrum 4
// zwrotny 5 - prawo - w Spectrum 1

if (joystickK()==16) return 1;
if (joystickK()==8) return 2;
if (joystickK()==2) return 3;
if (joystickK()==4) return 4;
if (joystickK()==1) return 5;
return 0;

}

Właściwa funkcja w asemblerze odczytująca port:
int __FASTCALL__ joystickK(unsigned p){
//sprawdza i zwraca wartość w 0x1f - interfejs joysticka od Atari - Kempston

#asm
// sprawdzenie 0x1f, dziesiętnie 31, jest to port więc korzystamy z in   
    ld a,$00
    in a,(31)
    //żeby zwrócić wartość trzeba ją umieścić w hl
    //h może być 0 bo a ma mniejszą wartość
    ld h,$00
    //ld hl, a
    ld l,a
ret

#endasm

}
Do kompilacji używam z88dk.
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: trojacek w 2018.04.26, 21:25:24
A tak zapytam, po co robisz  ld a,$00 zaraz przed in a,(31)?

W języku C z pętli to się chyba wychodzi przez break, a nie return.

Ogólnie, w Twoim kodzie jest tyle brzydkich rzeczy, że chyba najlepiej, jakbyś sobie odświeżył znajomość języka C z jakiegoś samouczka online.

Przy odczycie joysticka brakuje obsługi skosów oraz fire+kierunek, ale rozumiem, że to uproszczenie w początkowej fazie eksperymentu.
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: trojacek w 2018.04.26, 22:13:46
Po mojemu byłoby tak (nie mam jak sprawdzić, czy działa):

int petlazwalniajaca(long int n){

for(int nk=0;nk<n;nk++)
{
  if(joystick()!=0) break;
  if(klawiatura()==5) printf("kursor w prawo");
}

}



int joystick(){

// zwracamy wartości
// zwrotny 1 - przycisk - w Spectrum 16
// zwrotny 2 - góra - w Spectrum 8
// zwrotny 3 - lewo - w Spectrum 2
// zwrotny 4 - dół - w Spectrum 4
// zwrotny 5 - prawo - w Spectrum 1

int retCode = 0;

switch(joystickK()) {
  case 16: retCode = 1; break;
  case 8: retCode = 2; break;
  case 2: retCode = 3; break;
  case 4: retCode = 4; break;
  case 1: retCode= 5; break;
  default: retCode = 0;
}
return retCode;

}


int __FASTCALL__ joystickK(unsigned p){
//sprawdza i zwraca wartość w 0x1f - interfejs joysticka od Atari - Kempston

#asm
// sprawdzenie 0x1f, dziesiętnie 31, jest to port więc korzystamy z in   
    xor a
    ld h, a
    in a,(31)
    ld l,a
    ret

#endasm

}


Pewnie można to zrobić lepiej :)
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: Tygrys w 2018.04.27, 10:08:34
Poniższy przykład jest zły, dlatego że działa tylko i wyłącznie wtedy, kiedy naciśnięty jest jedynie jeden kierunek  lub fire. W przeciwnym razie procedura nie wykryje kompletnie nic.

Zamiast liczb 1...5 należy użyć chociażby operacji na bitach jako zwracany stan 'manipulatora'.

Cytuj
{
  retCode = 0;
  if (kierunek & bit_kontrolera_lewo) retCode |= BIT_STEROWANIA_LEWO;
  if (kierunek & bit_kontrolera_lewo) retCode |= BIT_STEROWANIA_PRAWO;

  itp...

  return retCode;
}

gdzie bit_kontrolera_lewo to wartość jaka pojawia się kiedy zostanie naciśnięty kierunek,
zaś BIT_STEROWANIE_LEWO to nasza lokalna definicja kierunków.
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: RafalM w 2018.04.27, 10:49:13
Ja u siebie zawsze robię tak i mi działa ;)

LD BC,31
IN A,(C)


Z tego co kojarzę to IN A,(C) to tak naprawdę IN A, (BC) - czytamy z portu który ma tak naprawdę szesnastobitowy adres.

A jeśli robimy IN A,(31) to też jakbyśmy robili IN A,(BC) gdzie C=31 a B jest cóż, takie jak w danej chwili B czyli w ogólnym przypadku losowe.

Tutaj znalezłem link gdzie o tym trochę jest, to jest trochę bardziej skomplikowane:
https://electronics.stackexchange.com/questions/92466/confused-about-in-out-architecture-of-z80-chip

Co do czytania kierunków to tak naprawdę wszystko zależy od tego co chcemy osiągnąć w grze czy innym programie. Czy poruszamy się po skosach czy nie? Co ma się stać jeśli człowiek wciśnie lewo i prawo naraz? Ale zgodzę się że najlepiej jest testować bity i zależnie od ich kombinacji wykonywać określone akcje.

Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: pear w 2018.04.27, 10:56:49
A jeśli robimy IN A,(31) to też jakbyśmy robili IN A,(BC) gdzie C=31 a B jest cóż, takie jak w danej chwili B czyli w ogólnym przypadku losowe.
W IN A,(n) dolna połówka adresu to n, a górna to aktualna zawartość A.
Jeśli interfejsy dekodują tylko dolne 8 bitów, to zerowanie akumulatora można pominąć.
W innym przypadku jest to jak najbardziej prawidłowe działanie.
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: RafalM w 2018.04.27, 11:47:45
Dzięki Pear. Człowiek uczy się całe życie ;)

Może jeszcze mógłbyś potwierdzić albo zaprzeczyć czy joystick Kempston sprawdza górny bajt adresu?

( podejrzewam że to może być rózne zaimplementowane w róznych emulatorach stąd u Pgru rozjechały
 się emulacja i rzeczywisty sprzęt)
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: pear w 2018.04.27, 11:58:30
Kempston w większości wykonań dekoduje tylko bit A5.
Inną sprawą jest czy w systemie znajdują się inne interfejsy, dla których istotne jest pełne adresowanie.
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: pgru w 2018.04.27, 12:00:45
- Zasadniczo do tej gry są potrzebne 2 kierunki i przycisk. Dolnego używam tylko do sprawdzania punktów, dla tych graczy którzy chcą wiedzieć ile zdobyli.
- Ładowanie akumulatora 0 to taka kiepska(z mojej strony) próba naprawy sytuacji - nie wiedziałem czy nie pojawiały się tam jakieś losowe wartości :-(
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: Tygrys w 2018.04.27, 12:01:29
aby sprawdzić jak w Juniorze (i nie tylko) odczytywana jest wartość z portu, wystarczy odpalić prosty program:


Cytuj
10 PRINT AT 0,0;IN 31;"      "
20 GO TO 20

on powie dlaczego działa pod emulatorem, a dlaczego może nie działać na J.
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: pgru w 2018.04.27, 13:17:59
Wartości dzięki programowi Tygrysa(dziękuję):
- brak ruchu - 64
- prawo - 65
- dół - 68
- lewo - 66
- góra - 72

z przyciskiem
- brak ruchu - 80
- prawo - 81
- dół - 84
- lewo - 82
- góra - 88

co by miało sens bo wg. książki o CP/J manipulator jest podłączony do linii portu A układu transmisji równoległej MCY 7855

Trzeba było to robić na bitach, ale spróbuję poprawić na razie prowizorycznie program :-)
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: trojacek w 2018.04.27, 13:28:42
W asemblerze, po "in a, (31)" dodaj "and 1fh".
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: pgru w 2018.04.27, 13:49:07
Na szybko poprawiłem i działa. Zmieniłem też instrukcję wychodzenia z pętli. Dziękuję Wszystkim za odpowiedzi.

Zaraz sprawdzę to z dodawaniem do asemblera - bo jak rozumiem(nie wiem czy dobrze) ta instrukcja z and powinna obciąć różne inne wartości z różnych interfejsów?
Tytuł: Odp: Problem z odczytem joysticka.
Wiadomość wysłana przez: matofesi w 2018.04.27, 13:57:02
@pgru nie. To, że w stanie "idle" dostajesz 64 oznacza, że twój interface joysticka po prostu wystawia na szóstym bicie (liczone od zera) na stałe jedynkę (być może jest to jakiś znacznik, który pozwala odczytać coś specyficznego a być może po prostu błąd konstrukcyjny interface'u) - "and 1fh" z pobranego bajtu po prostu wyzeruje wszystko powyżej piątego bitu.