Autor Wątek: Pierwsze kroki w Pasmo  (Przeczytany 107065 razy)

ikci

  • *****
  • Wiadomości: 1216
  • Miejsce pobytu:
    Kraków
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #75 dnia: 2015.04.26, 13:03:16 »
Programowanie czyli czynność umysłowa, w odróżnieniu od czynności fizycznych wymienionych przez Ciebie, wymaga
odrobiny teorii, a najlepszym źródłem tej teorii jest właśnie analiza programu dokonana przez jego twórcę.
ZX Spectrum 48K, ZX Spectrum +, ZX Spectrum 128K, ZX Spectrum +2, ZX Spectrum +2B, ZX Spectrum +3, TIMEX TC2048, UNIPOLBRIT Komputer 2068, Didaktik Gama 80kB, 
Amstrad/Schneider CPC6128, Schneider CPC464, Commodore C64, Atari 800XL, 65XE 130XE, A500+, A600, A1200, ATARI 1040 STF

RafalM

  • *****
  • Wiadomości: 1133
  • Miejsce pobytu:
    Sulejówek
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #76 dnia: 2015.04.26, 13:17:19 »
Zabierasz się jak pies do jeża.

Ale jeśli tak chcesz, uczyć się na sucho, ze słabego kodu i jeszcze przy tym jakieś cudze emocje analizować to cóż, rób po swojemu ;)

ikci

  • *****
  • Wiadomości: 1216
  • Miejsce pobytu:
    Kraków
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #77 dnia: 2015.04.26, 13:22:56 »
Dziękuję za radę.
ZX Spectrum 48K, ZX Spectrum +, ZX Spectrum 128K, ZX Spectrum +2, ZX Spectrum +2B, ZX Spectrum +3, TIMEX TC2048, UNIPOLBRIT Komputer 2068, Didaktik Gama 80kB, 
Amstrad/Schneider CPC6128, Schneider CPC464, Commodore C64, Atari 800XL, 65XE 130XE, A500+, A600, A1200, ATARI 1040 STF

tdu

  • *****
  • Wiadomości: 926
  • Miejsce pobytu:
    Gdansk
    • Nasze Wędrowanie
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #78 dnia: 2015.04.26, 21:47:03 »
Kolejny problem,
w akumulatorze jest jakaś liczba
jak ją dziesiętnie wyświetlić na ekranie

kombinuje od godziny, ale to chyba strata czasu
są na to pewnie jakieś gotowce
ZX81/ZX 48k/Zx48k+/ZX +2/ZX +2A/+3/TC2048/FDD3000/FDD5000/3"/3,5'/5,25'/Beta 48k Apina/D+/GP50s/DIVIDE CF/Masterface/Polbasic SamCoupe QL CPC6128/N100 MSX-SVI738  MSX2-VG8235

RafalM

  • *****
  • Wiadomości: 1133
  • Miejsce pobytu:
    Sulejówek
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #79 dnia: 2015.04.26, 21:59:55 »
Cytuj
Kolejny problem,
w akumulatorze jest jakaś liczba
jak ją dziesiętnie wyświetlić na ekranie

kombinuje od godziny, ale to chyba strata czasu
są na to pewnie jakieś gotowce

Z użyciem procedur ROMU czy bez?

Jest w ROMIE jakiś gotowiec, mogę spróbować odszukać w plikach

Jeśli robisz samemu, to jest to  już trochę trudniejszy temat.

Generalnie robisz tak (zapis w pseudokodzie)

cyfra1=0,cyfra2=0,cyfra3=0
 while (A>100)
{
cyfra1=cyfra1+1
A=A-100
}
while (A>10)
{
cyfra2=cyfra2+1
A=A-10
}
cyfra3=A

Dochodzi kwestia czy pisać liczby w formacie 005 gdzie z przodu są zera czy pomijać te zera


tdu

  • *****
  • Wiadomości: 926
  • Miejsce pobytu:
    Gdansk
    • Nasze Wędrowanie
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #80 dnia: 2015.04.26, 22:29:57 »
Pisze na ZX więc z ROM można korzystać
a zera, są mile widziane ale niekoniecznie

W języku wysokiego poziomu to nie problem,
ale jak to przetłumaczyć na kod ?

W końcu każda gra zawiera liczniki, życia czasu itp.
więc jest to już jakoś rozwiązane.
ZX81/ZX 48k/Zx48k+/ZX +2/ZX +2A/+3/TC2048/FDD3000/FDD5000/3"/3,5'/5,25'/Beta 48k Apina/D+/GP50s/DIVIDE CF/Masterface/Polbasic SamCoupe QL CPC6128/N100 MSX-SVI738  MSX2-VG8235

Phonex

  • *****
  • Wiadomości: 1261
  • Miejsce pobytu:
    Warszawa
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #81 dnia: 2015.04.26, 23:49:29 »
Korzystając z ROMu, najkrócej można napisać procedurę piszącą bez zer.
        LD C, A
        LD B, $00
        CALL $1A1B
        RET
Oczywiście wysyła do bieżącego otwartego kanału.
Żeby pisała z zerami, trzeba by ją przepisać, zamieniając LD E, $FF na LD E,$30 (kod znaku 0). To jest procedura pisząca Basicowy numer linii, więc po zmianie na drukowanie zer, będzie pisać liczby czterocyfrowe np. 0003.

I przy okazji: zamiast DEFB "P", "r", .... można napisać DEFM "Program" (przynajmniej w GENSie tak jest).

tdu

  • *****
  • Wiadomości: 926
  • Miejsce pobytu:
    Gdansk
    • Nasze Wędrowanie
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #82 dnia: 2015.04.27, 07:21:42 »
Wiem ze mozna uzyc defm ale chciałem uzyskać efekt kolejno pokazujących się liter.
Co zresztą jest widoczne.

A rozwiazanie problemu licznika chyba znalazłem, przyśniło mi się w nocy.
Każdej cyfrze, liczby  licznika przypisujemy osobny bajt pamięci.

Robimy dwa podprgramy, jeden incrementuje poszczególne bajty, do 10.
Drugi wyświetla ich stan przez RST 16.
Implementacja nie powinna być trudna, dzisiaj ja zrobię.
ZX81/ZX 48k/Zx48k+/ZX +2/ZX +2A/+3/TC2048/FDD3000/FDD5000/3"/3,5'/5,25'/Beta 48k Apina/D+/GP50s/DIVIDE CF/Masterface/Polbasic SamCoupe QL CPC6128/N100 MSX-SVI738  MSX2-VG8235

ssr86

  • *
  • Wiadomości: 37
  • Miejsce pobytu:
    Bydgoszcz
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #83 dnia: 2015.04.27, 09:27:25 »
Cytuj
w akumulatorze jest jakaś liczba
jak ją dziesiętnie wyświetlić na ekranie

W https://chuntey.wordpress.com/2013/09/08/how-to-write-zx-spectrum-games-chapter-10/ (polecam w sumie wszystkie części, bo fajnie się to czyta) jest taki kod (zwróć uwagę, że wyświetla zera na początku), na wyświetlenie liczby w hl:
; Show number passed in hl, right-justified.

shwnum ld a,48 (or 32)     ; leading zeroes (or spaces).
       ld de,10000         ; ten thousands column.
       call shwdg          ; show digit.
       ld de,1000          ; thousands column.
       call shwdg          ; show digit.
       ld de,100           ; hundreds column.
       call shwdg          ; show digit.
       ld de,10            ; tens column.
       call shwdg          ; show digit.
       or 16               ; last digit is always shown.
       ld de,1             ; units column.
shwdg  and 48              ; clear carry, clear digit.
shwdg1 sbc hl,de           ; subtract from column.
       jr c,shwdg0         ; nothing to show.
       or 16               ; something to show, make it a digit.
       inc a               ; increment digit.
       jr shwdg1           ; repeat until column is zero.
shwdg0 add hl,de           ; restore total.
       push af
       rst 16              ; show character.
       pop af
       ret

Osobiście, do zrobienia procedury wyświetlającej punkty (ten sam problem), korzystałem z artykułu na cpcwiki: http://www.cpcwiki.eu/index.php/Programming:Display_and_update_Scores - części z BCD, bo z tego co tu wypisują są 3 metody: powyższa (podana wcześniej rzez RafalM), taka używająca BCD i zapis każdej cyfry w osobnym bajcie...
« Ostatnia zmiana: 2015.04.27, 09:46:01 wysłana przez ssr86 »
"Kto zawsze tylko żył w pustyni..."

tdu

  • *****
  • Wiadomości: 926
  • Miejsce pobytu:
    Gdansk
    • Nasze Wędrowanie
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #84 dnia: 2015.04.27, 11:16:54 »
Postanowiłem doprowadzić do końca moją procedurę z nocnych koszmarów

wynik działania w załączniku

Więc mamy główną pętle:

ld a,0
ld hl,50005  ;jednosci
ld (hl),a

ld a,0
ld hl,50006  ;dziesiatki
ld (hl),a

start

call wyswietl
call zwieksz
call time

jp start

I procedury:

procedura wyswietl - wyświetla aktualny stan licznika
procedura zwieksz zwiększa jego stan o 1
procedura time - spowalnia działanie programu

WYSWIETL
ld hl,50006  ;dziesiatki
ld a,(hl)
add a,48
rst 16

ld hl,50005  ;jednosci
ld a,(hl)
add a,48
rst 16

ZWIEKSZ
ld a,(50005)
cp 9
jp z,zw1
inc a
ld (50005),a
ret

zw1
ld a,0
ld (50005),a
ld a,(50006)
inc a
cp 10
jp z,stop
ld (50006),a

no i procedura END zmienia border na żółty żeby pokazać że licznik doszedł do końca

PS dalej nie potrafię wyświetlić więcej niż jednego bajta na raz DEFB, DEFM też nie działa.
No i problemem jest ustawienie miejsca wyświetlania, osiągam to przez znaki sterujące, cofanie kursora, enter, spacja.
Przez zmienną systemową 23566/7 nie działa.
ZX81/ZX 48k/Zx48k+/ZX +2/ZX +2A/+3/TC2048/FDD3000/FDD5000/3"/3,5'/5,25'/Beta 48k Apina/D+/GP50s/DIVIDE CF/Masterface/Polbasic SamCoupe QL CPC6128/N100 MSX-SVI738  MSX2-VG8235

matofesi

  • *****
  • Wiadomości: 2049
  • Miejsce pobytu:
    Toruń/Poland
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #85 dnia: 2015.04.27, 11:47:12 »
No to po kolei... Drukowanie pojedynczych znaków przy użyciu procedur z ROMu jest stosunkowo prostą sprawą - można tam używać znaków kontrolnych w tym również kodu 22 - AT, po którym dwa kolejne bajty to odpowiednik BASICowego PRINT AT w,k;

Czyli:
ld a,22
rst 16
ld a,10
rst 16
ld a,12
rst 16
ld a,48
rst 16

To odpowiednik
PRINT AT 10,12;"0";

Używając procedur z ROMu dobrze jest pamiętać, że niekoniecznie na początku programu musi być otwarty kanał 2 odpowiadający za pisanie w głównej części ekranu i dobrze jest go najpierw otworzyć:
ld a,2
call $1601

Użycie DB/DM do przechowywania tekstów wymaga albo znajomości długości tekstu albo postawienia znacznika na końcu.
Jedna z prostych metod jest taka:
ld hl,tekst_do_wydrukowania
call drukuj

...

drukuj
ld a,(hl)
or a
ret z
push hl
rst 16
pop hl
inc hl
jr drukuj

tekst_do_wydrukowania:
db 22,10,10
dm "Tekst"
db 0

Można też użyć procedury PO-MSG ($0C0A) z ROMu, ale wymaga ona trochę zachodu na starcie, bo jest zasadniczo przeznaczona do czego innego niż proste drukowanie tekstu:
ld de,tekst
xor a
call $0C0A

tekst: db 128
db "Tekst do wydrukowani"
db "a"+128

Skomplikowanie wynika stąd, że kod jest przeznaczony do drukowania tekstów z tabeli - komunikatów o błędach, tokenów BASICa itp. DE na wejściu zawiera początek tabeli w której pierwszy znak to 128 - jest przez procedurę po-msg przeskakiwany. Dalej następują kolejne teksty w każdym z nich ostatni znak ma ustawiony najstarszy bit (+128). A zawiera indeks do tekstu, który chcemy wydrukować - 0 (XOR a) znaczy pierwszy tekst. Jeśli mamy więcej tekstów, to można je wszystkie wrzucić w jednym ciągu i drukować wołając po-msg z różnymi A dla tego samego DE.

RafalM

  • *****
  • Wiadomości: 1133
  • Miejsce pobytu:
    Sulejówek
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #86 dnia: 2015.04.27, 11:51:12 »
Nie mam teraz czasu wszystkiego przeanalizować ale aż się prosi

zamiast

ld a,0
ld hl,50005  ;jednosci
ld (hl),a

ld a,0
ld hl,50006  ;dziesiatki
ld (hl),a

użyć:

xor a
ld hl,50005
ld (hl),a
inc hl
ld (hl),a

W tej chwili możesz to uznać za mniej czytelne, ale jest to krótsze, szybsze i powszechnie stosowane :)


matofesi

  • *****
  • Wiadomości: 2049
  • Miejsce pobytu:
    Toruń/Poland
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #87 dnia: 2015.04.27, 12:02:26 »
A jeśli chodzi o drukowanie "normalnych" liczb dwubajtowych, to można to zrobić np. tak:
ld hl,liczba
ld a,0
call print_16

...

print_16
ld (was_digit),a
        ld de,10000
        call print_one
        ld de,1000
        call print_one
        ld de,100
        call print_one
        ld de,10
        call print_one
        ld a,l
print_digit   
        add a,"0"
        push de 
        push hl 
        rst 16   
        pop hl   
        pop de   
        ret     

print_one
        xor a
print_one1   
        sbc hl,de
        jr c,print_one2
        inc a
        jr print_one1
print_one2
        add hl,de
        or a
        jr nz,print_one3
        ex af,af'
        ld a,(was_digit)
        or a
        ret z
        ld a,1
        ld (was_digit),a
        ex af,af'
print_one3
        ex af,af'
        ld a,1   
        ld (was_digit),a
        ex af,af'
        jr print_digit
was_digit:
        db 0

Procedura print_16 jako parametry przyjmuje liczbę do wydrukowania w HL i status drukowania zer wiodących w A. Jeśli A zawiera 0 to procedura wydrukuje liczbę bez zer na początku, jeśli coś innego, to z zerami. Jeśli zamiast zer mają być spacje to trzeba zmienić w print_digit add a,"0" na add a," ".

Procedura działa "na rympał" i oczywiście psuje HL a do tego A i DE. Działanie jest proste - cztery razy wołana jest procedura print_one, która "dzieli" HL przez DE dając wynik w A a następnie zależnie od znacznika "was_digit" drukuje bądź nie (jeśli was_digit zawiera 0 i wynikiem jest 0) kolejne cyfry używając print_digit. Na koniec zawartość L (czyli ostatnia cyfra po podzieleniu przez 10) przepisywana jest do A i drukowana niezależenie od stanu was_digit - jeśli w HL było 0 to ma się ono wydrukować.

Całość jest niezbyt szybka, ma nierówny czas wykonania ale za to jest stosunkowo łatwa (mam nadzieję) do zrozumienia ;)

edit: Tak się zapędziłem, że nie zwróciłem uwagi, że @ssr86 cytował w zasadzie identyczne rozwiązanie drukowania liczb ;)
« Ostatnia zmiana: 2015.04.27, 12:12:59 wysłana przez matofesi »

Phonex

  • *****
  • Wiadomości: 1261
  • Miejsce pobytu:
    Warszawa
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #88 dnia: 2015.04.27, 12:13:20 »
Też długo używałem takiego sposobu żeby zmienić pozycję, ale nie podobał mi się.
ld a,22
rst 16
ld a,10
rst 16
ld a,12
rst 16
ld a,48
rst 16

To odpowiednik
PRINT AT 10,12;"0";


Przez modyfikację zmiennych systemowych nie udawało się nic osiągnąć, więc w końcu przeanalizowałem problem. Tak można ustawić tą samą pozycję co wyżej, krócej i (przynajmniej dla mnie) elegancko:
LD BC,$0E15   ;B=24-y, C=33-x
CALL $0DD9

matofesi

  • *****
  • Wiadomości: 2049
  • Miejsce pobytu:
    Toruń/Poland
Odp: Pierwsze kroki w Pasmo
« Odpowiedź #89 dnia: 2015.04.27, 12:18:26 »
@Phonex Oczywiście, że robienie tego ciągiem LD A,n, RST 16 jest brzydkie i bez sensu ;) Jak już robię takie rzeczy to raczej wstawiam kody sterujące na początek właściwego tekstu i wołam PO-MSG albo inną stosowną procedurę drukującą tekst. Jest spójniej i krócej niż osobne ustawianie pozycji :)