Autor Wątek: Skopiowanie większej ilości danych do RAM  (Przeczytany 2034 razy)

siudym

  • *
  • Wiadomości: 32
Skopiowanie większej ilości danych do RAM
« dnia: 2021.10.19, 00:36:58 »
Witam :) Jestem nowy w temacie Z80 i sprawia mi on sporo problemów...
Chciałbym skopiować pewną ilość bajtów do RAM, ale dosyć nietypowo bo muszą być skopiowane co drugie bajty. Plik binarny INCBIN ma rozmiar 2KB, ale w ram będzie zajmował 1KB czyli kopiowane będą tylko parzyste bajty licząc od pierwszego. Np. 00,02,04,06,08 itd itd.
Kombinuje i nic za bardzo nie działa, kopiowany jest tylko jeden bajt z incbin do ram.
Adres w pamieci np. D000 do D3FF czyli 1024bajty w RAM zajete.

CopyNT:
ld hl,NameTable ; Location of tile data
ld bc,NameTableSize ; Counter for number of bytes to write
CopyNT_Loop:
ld a,(hl) ; Get data byte
ld ($D000),a ; Wram address
inc hl ; Point to next tile
inc hl ; 2x inc hl to skip every other byte and copy to wram only every (even) first byte of the tile (1KB)
dec bc
dec bc
ld a,b
or c
jr nz,CopyNT_Loop
ret

NameTable: ; 2KB nametable binary
.incbin "nametable.bin" fsize NameTableSize

opcja 2, tez nie dziala:

copy:
        ld hl,NameTable
        ld bc,NameTableSize
        ld de, $D000
copy_loop:
        ldi
        inc hl
        inc hl
        jp po,copy_loop
        ret


steev

  • *****
  • Wiadomości: 1214
  • Miejsce pobytu:
    inode 42
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #1 dnia: 2021.10.19, 01:59:03 »
Spróbuj :

    org 32768
    ld hl, 0       ; źródło
    ld de, 16384   ; cel
    ld bc, 2048    ; licznik
loop:
    ldi
    inc hl
    ld a,b
    or c
    jr nz,loop
    ret
Machines should work. People should think.

siudym

  • *
  • Wiadomości: 32
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #2 dnia: 2021.10.19, 10:36:10 »
Dziala, dzieki! :) Sam system inny niz ZX Spectrum bo Sega Mark III.


    ld hl,NameTable       ; źródło
    ld de,$C000   ; cel
    ld bc,NameTableSize    ; licznik
loop:
    ldi
    inc hl
    ld a,b
    or c
    jr nz,loop

Dalthon

  • ****
  • Wiadomości: 410
  • Miejsce pobytu:
    TriCity
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #3 dnia: 2021.10.25, 17:29:35 »
Mała podpowiedź czemu nie działa:

Cytuj
   ld a,(hl)               ; Get data byte
   ld ($D000),a   

Nie ma prawa zadziałać bo zapisujesz każdą pobraną wartość w jedno i to samo miejsce pamięci $d000

Cytuj
copy_loop:
        ldi
        inc hl
        inc hl
        jp po,copy_loop

Tutaj problemem jest to że warunkowy skok odnosi się do zwiększania HL - co też nie ma prawa zadziałać ;)
ZX Spectrum +2 Grey | ZX Spectrum Next | Commodore 64 | Commodore +4 | Atari 520 STF | Amiga 1200

siudym

  • *
  • Wiadomości: 32
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #4 dnia: 2021.10.25, 21:47:26 »
Tak, już wcześniej przeanalizowałem kod :) Powoli ogarniam 16-bitowe rejestry, tylko trzeba szukać przykładów bo goła teoria jakoś słabo mi wchodzi.

Phonex

  • *****
  • Wiadomości: 1221
  • Miejsce pobytu:
    Warszawa
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #5 dnia: 2021.10.25, 22:06:39 »

Cytuj
copy_loop:
        ldi
        inc hl
        inc hl
        jp po,copy_loop

Tutaj problemem jest to że warunkowy skok odnosi się do zwiększania HL - co też nie ma prawa zadziałać ;)

Racji nie masz, młody padawanie, nie dlatego nie działa :P
Skok warunkowy odnosi się do LDI, tylko warunek jest źle dobrany.
I za dużo zwiększania HL, instrukcja LDI sama już raz zwiększa.
Tak jest dobrze:
copy_loop:
        LDI
        INC HL
        JP PE, copy_loop
        RET

Dalthon

  • ****
  • Wiadomości: 410
  • Miejsce pobytu:
    TriCity
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #6 dnia: 2021.10.26, 13:47:30 »
Racji nie masz, młody padawanie, nie dlatego nie działa :P
oj tam, oj tam ;) ale dziękuję - nie pamiętam już by ktoś mnie nazwał "młody" :D
ZX Spectrum +2 Grey | ZX Spectrum Next | Commodore 64 | Commodore +4 | Atari 520 STF | Amiga 1200

siudym

  • *
  • Wiadomości: 32
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #7 dnia: 2021.10.29, 11:36:16 »
Jeszcze bym prosil o weryfikacje kodu:

NameTable to bedzie plik incbin o wielkosci do 1024bajtow, ale ze wzgledu, ze nie bedzie zawsze tej samej wielkosci bedzie ograniczony bajtem o wartosci FF w "srodku". Czyli kopiujemy dane pod adres $C100 i skopiuje sie tyle ile pozwoli ustawiony w pliku $FF:

CopyNT:

LD HL,NameTable ; kopiujemy do HL adres zrodla
LD DE,$C100 ; kopiujemy do DE adres docelowy

CopyNT_Loop:

LD A,(HL) ; ladujemy do A wartosc spod adresu wskazanego w HL
CP $FF ; sprawdzamy czy wartosc w A = FF
JR Z,CopyNT_End ; jak wartosc sie zgadza skok zakonczyc funkcje a jak nie to wykonaj "LD (DE),(HL)" nizej instrukcja LDI
LDI ; ("LD (DE),(HL)", then increments DE and HL, and decrements BC)
JR CopyNT_Loop ; skocz zapetlic operacje

CopyNT_End:


trojacek

  • *****
  • Wiadomości: 6190
  • Miejsce pobytu:
    Warszawa
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #8 dnia: 2021.10.29, 12:04:00 »
Wygląda całkiem OK.
Jedyne, do czego bym się przyczepił, to brak "bezpiecznika". Jeśli z jakichś przyczyn pętla nie znajdzie kodu #FF, to się zrobi nieprzewidywalna (w skrajnym przypadku może kopiować bajty nawet aż do "przekręcenia licznika" i znalezienia jakiegoś #FF w pamięci ROM, a w międzyczasie m.in. zamazać stos). Warto więc pierwszy bajt po buforze ustawić na #FF.

matofesi

  • *****
  • Wiadomości: 1899
  • Miejsce pobytu:
    Toruń/Poland
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #9 dnia: 2021.10.29, 12:08:16 »
@trojacek Yhym... Pytanie tylko jak to sobie wyobrażasz? Zakładam, że "bezpiecznik" jest dlatego, że dane będą wczytywane "skądś" czyli jakieś I/O albo coś więc co do zasady nie wiesz ile ich będzie ciężko więc postawić znacznik w odpowiednim miejscu. Trzeba by wypełniać cały bufor FFami przed wczytaniem danych albo zmienić procedurę wczytywania żeby dopisywała znacznik.

Z drugiej strony jeśli dane są faktycznie wczytywane statycznie poprzez incbin przy kompilacji to cała koncepcja jest zupełnie bez sensu bo wtedy dokładnie wiemy ile jest tych danych i wystarczy zrobić LDIRa.

ld hl,NameTable
ld de,$c100
ld bc,NameTableEnd-NameTable
ldir

...

NameTable: incbin "plik.bin"
NameTableEnd:


siudym

  • *
  • Wiadomości: 32
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #10 dnia: 2021.10.29, 12:17:12 »
Wlasnie BC nie moge uzyc jako koniec wskaznika wielkosci pliku. Moze nie opisalem dokladnie: Wskaznik FF bedzie zawsze w srodku pliku. Myk jest taki, ze plik binarny bedzie zawsze 1024 bajty (kwestia edytora, ktory taki bin wypluje), a skopiowane dane beda MAX 768 bajtow LUB MNIEJ (768 bo tyle tilesow 8x8 bedzie na ekranie w Sega Master System [256x192=768 - lub mniej). Wskaznik FF tym sterowac bedzie :) Aha i nie bedzie opcji aby wartosc FF byla jakos dodatkowo w innym miejscu bo ten 1kb to pamiec tilesow ekranu i FF to ostatni TILES ekranu zarezerwowany do tego celu (uzyty tylko raz w tym celu i nigdy w innym).

BC i NameTableEnd uzywalem wczesniej, ale szkoda mi bylo zajmowac bezsensu RAM na nieuzywane dane 768b+

matofesi

  • *****
  • Wiadomości: 1899
  • Miejsce pobytu:
    Toruń/Poland
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #11 dnia: 2021.10.29, 13:05:31 »
OK. Ale... nie możesz na ten moment odłożyć BC na stos? Całość z LDIRem i tak będzie szybsza niż pętla sprawdzająca znacznik.

siudym

  • *
  • Wiadomości: 32
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #12 dnia: 2021.10.29, 21:56:53 »
W sumie to funkcja dziala ok, ale zawsze warto dopytac o alternatywy i analize :)

Pytanie o odpowiednik EOR z 6502, widze w Z80 jest instrukcja XOR - nie wiem czy poprawnie zapisalem kod Z80:

6502:

LDA zmienna
EOR #$1D ; EOR (bitwise Exclusive OR)
STA zmienna     ; zapisz wynik



LD A,(zmienna)
XOR $1D ; czy teraz XOR wykona sie na A ?
LD (zmienna),A ; i mozna zapisac do zmiennej wynik?



« Ostatnia zmiana: 2021.10.29, 23:19:14 wysłana przez siudym »

tapy

  • ***
  • Wiadomości: 119
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #13 dnia: 2021.10.29, 23:36:18 »
Dobrze. Warto też zapamiętać, że XOR A jest często używany do zerowania akumulatora.

siudym

  • *
  • Wiadomości: 32
Odp: Skopiowanie większej ilości danych do RAM
« Odpowiedź #14 dnia: 2021.10.30, 12:03:48 »

LDA zmienna
LSR A
LSR A
LSR A
STA wynik


Wartosc w zmienna jest w zakresie 00-FF, wykonujemy logiczne przesuniecie w prawo aby wywalic 3 nizsze bity.
Efektem bedzie "zaokraglenie" pewnych zakresow wartosci do jednej np:

- $00-$07 zapisze do wynik $00
- $08-$0F zapisze do wynik $01
- $10-$17 zapisze do wynik $02
- $18-$1F zapisze do wynik $03
- $20-$27 zapisze do wynik $04
(...)
- $E0-$E7 zapisze do wynik $1C
- $E8-$EF zapisze do wynik $1D
- $F0-$F7 zapisze do wynik $1E
- $F8-$FF zapisze do wynik $1F

W kodzie Z80 mam problem bo wyniki sa totalnie inne, domyslam sie, ze bit0 przenosi sie do bit7 czego nie ma w przypadku 6502
gdzie wypada i nie przenosi sie do bit7.
Probowalem uzyc rozkazu kasujacego znacznik C ale nic nie daje, z tego co czytam CCF nie kasuje ale robi invert C, niby OR A kasuje C
ale dalej nic nie zmienia - pewnie powodem sa same rozkazy shift right w Z80, ktore automatycznie przenosza bit0 do bit7??



LD A,(zmienna)
;CCF ? OR A - nic nie zmieniaja
RRC A
RRC A
RRC A
LD (wynik),A


EDIT: hmm teraz dziala - czy to jedyna metoda aby uzyskac ten sam efekt?

   LD A,(zmienna)
   RR A
   OR A
   RR A
   OR A
   RR A
   OR A
   LD (wynik),A

wychodzi na to, ze musze za kazdym RR zerowac C aby bit0 nie wlazil w bit7 ?