forum speccy.pl
ZX Spectrum => PROGRAMOWANIE => Wątek zaczęty przez: siudym w 2021.10.22, 13:26:24
-
Mam kolejny problem z przepisaniem kodu 6502 na Z80 :)
Pod adresem ram $0300-$06FF (addrLO,addrHI) mam kopię 1-kilobajtowego (1024b) ekranu NES, użyty jest rejestr indexowy Y
aby wyliczyć numer kafelka/tilesa jaki znajduję sie pod wskazanym przez LDA adresie (przykładowo mam tam $20)
Niestety mam problem aby to przepisac na kod Z80, poniewaz nie ma tam rejestrow idexowych dzialajacych na podobnej zasadzie
oraz chyba nie ma takiego typu adresowania bezwglednego ?
Aha i w Z80 adres kopii ekranu wielkosci 1024bajtow bedzie startowac w $C000-$C3FF (zapewne zaladowanie najpierw do LD HL,$C000 ale co dalej to juz mam problem, bo skopiowanie pewnej tablicy to wiem, ale juz takie skanowanie bajtow nie mam pojecia jak ugryzc)
edit: maly błąd w 6502 uzyte adresowanie "pośredne strony zerowej postindeksowane Y (Indirect zero-page post-indexed Y)"
LDA #$20 ; laduje do aku $20 (przykladowo, bo moze byc wyliczona wczesniej wartosc dodowolna)
TAY ; przenosze akumulator do rejestru indexowego Y
; (adresowania bezwzglednego mozna tylko odczytywac z rejestrem Y nie X)
LDA [addrLO],Y ; odczytuje adres w ram zwiekszony o Y
TAY ; odczytana wartosc leci znowu do rejestru Y
LDA TileBits,Y ; teraz odczytuje jaki TYP kafelka znajduje sie pod tym adresem (bedzie odcztana wartosc stalej Air (00) Solid (01)
; teraz w akumulatorze mam potrzebna wartosc 00 lub 01 bo tylko takie typy kafelkow ustawione sa w stalych
;################################################################################
TileBits: ; tablica 256 bajtów
.db AirTile ;00 ; air tile
.db SolidTile ;01 ; solid tile
.db SolidTile ;02
.db SolidTile ;03
.db SolidTile ;04
.db SolidTile ;05
.db SolidTile ;06
.db SolidTile ;07
.db SolidTile ;08
.db SolidTile ;09
.db SolidTile ;0A
.db SolidTile ;0B
.db SolidTile ;0C
.db SolidTile ;0D
.db SolidTile ;0E
.db SolidTile ;0F
.db AirTile ;10
.db AirTile ;11
.db AirTile ;12
.db AirTile ;13
.db SolidTile ;14
.db SolidTile ;15
.db SolidTile ;16
.db SolidTile ;17
.db SolidTile ;18
.db SolidTile ;19
.db SolidTile ;1A
.db SolidTile ;1B
.db SolidTile ;1C
.db SolidTile ;1D
.db SolidTile ;1E
.db SolidTile ;1F
.db AirTile ;20
.db AirTile ;21
.db AirTile ;22
.db AirTile ;23
.db SolidTile ;24
.db SolidTile ;25
.db SolidTile ;26
.db SolidTile ;27
.db SolidTile ;28
.db SolidTile ;29
.db SolidTile ;2A
.db SolidTile ;2B
.db SolidTile ;2C
.db SolidTile ;2D
.db SolidTile ;2E
.db SolidTile ;2F
(...) etc etc (czyli 30,40,50,60,70,80,90,A0,B0,C0,D0....)
.db SolidTile ;E0
.db SolidTile ;E1
.db SolidTile ;E2
.db SolidTile ;E3
.db SolidTile ;E4
.db SolidTile ;E5
.db SolidTile ;E6
.db SolidTile ;E7
.db SolidTile ;E8
.db SolidTile ;E9
.db SolidTile ;EA
.db SolidTile ;EB
.db SolidTile ;EC
.db SolidTile ;ED
.db SolidTile ;EE
.db SolidTile ;EF
.db SolidTile ;F0
.db SolidTile ;F1
.db SolidTile ;F2
.db SolidTile ;F3
.db SolidTile ;F4
.db SolidTile ;F5
.db SolidTile ;F6
.db SolidTile ;F7
.db SolidTile ;F8
.db SolidTile ;F9
.db SolidTile ;FA
.db SolidTile ;FB
.db SolidTile ;FC
.db SolidTile ;FD
.db SolidTile ;FE
.db SolidTile ;FF ; tile $FF (#255)
;################################################################################
AirTile equ 0 ; stale okreslajace typy tilesow, mozna dodac wiecej
SolidTile equ 1
-
Jedno z wielu możliwych rozwiązań:
indeks equ 3
org $8000
ld hl,dane ; albo ld h,hi(dane)
ld l,indeks ; uproszczenie możliwe dzięki align $100 :)
ld a,(hl)
ret
align $100
dane:
db 0, 1, 2, 3, 4, 5, 6, 7
db 8, 9,10,11,12,13,14,15
; db ...
-
@steev chyba nie... Tam jest jakieś podwójne pobieranie danych - najpierw z tablicy a potem chyba na tej podstawie z TileBits. Czyli jeszcze przed ret'em musiałoby być przeładowanie a do hl i drugi odczyt...
Ale może ja się nie znam. A na pewno nie znam się na 6502 ;)
-
Owszem, ale zasada jest ta sama.
Jakoś trzeba wziąć adres bazowy tablicy i dodać indeks.
Rozwiązań na to jest w Z80 co najmniej kilka, dałem przykład jednego (i niekoniecznie najlepszego :)
-
Nawet dobry trop przydatny :)
-
Jeszcze mam taki problem - musze dodac do adresu wartosc zmiennej w temp 4x i zrobic to samo w kodzie Z80:
LDY #$04
TileCalc_Loop:
LDA <addrLO ; add the number of rows to the address 4 times
CLC
ADC <temp
STA <addrLO
LDA <addrHI
ADC #0
STA <addrHI
DEY
BNE TileCalc_Loop
dla Z80:
LD HL,$C000
LD A,(temp)
ADD A,L ; A = A+L
LD L,A ; L = A+L
ADC A,H ; A = A+L+H+carry
SUB L ; A = H+carry
LD H,A ; H = H+carry
- nie wiem czy jest poprawnie teraz no i musze zrobic dodanie wartosci ze zmiennej temp do adresu w HL 4x (musi tak byc z pewnych wzgledow)
bo to chyba nie jest poprawnie?
ld a,(temp)
ld hl,$C000
add a,(hl)
add a,(hl)
add a,(hl)
add a,(hl)
-
Moim zdaniem lepiej (szybciej) jest wartość dodawaną najpierw przemnożyć przez 4, używając przesuwania bitowego.
Pytanie, jaki zakres ma mieć ta "zmienna", bo jak 0..255, to trzeba przesuwać na 16 bitach, by nic nie zgubić.
-
W sensie, dodajesz wartość zmiennej temp cztery razy do adresu w HL?
Nie bój się 16 bitów.
ld a,(temp)
ld d,0
ld e,a ; de = (temp)
add hl,de
add hl,de
add hl,de
add hl,de ; lame, ale proste do złapania
-
Moim zdaniem lepiej (szybciej) jest wartość dodawaną najpierw przemnożyć przez 4, używając przesuwania bitowego.
Pytanie, jaki zakres ma mieć ta "zmienna", bo jak 0..255, to trzeba przesuwać na 16 bitach, by nic nie zgubić.
Dokladnie, jak przekroczy 255 to zwiekszy wyzszy bajt adresu. Jak w przykladzie 6502 - jak dodawanie przekroczy wartosc bajtu LO to zwiekszy HI o jeden.
W sensie, dodajesz wartość zmiennej temp cztery razy do adresu w HL?
Nie bój się 16 bitów.
Dokładnie, a gdy przekroczy LO zwieksza wyzszy bajt adresu o jeden. No wlasnie ja probuje ogarniac jakos te wyliczenia 16bitowe w Z80 ale na to trzeba czasu.
-
No wlasnie ja probuje ogarniac jakos te wyliczenia 16bitowe w Z80 ale na to trzeba czasu.
Ja za to podziwiam ludzi robiących na 6502... Jak wy sobie radzicie bez normalnych 16bitowych rejestrów i arytmetyki na nich? To wszystko się nadrabia tymi dziwnymi trybami adresowania i faktem, że w zasadzie wszystkie rozkazy są szybkie jak skurczybyk? ;)
Chyba bym tak nie umiał ;)
-
Ja w sumie malo kiedy w swoich grach uzywam 16-bitow :) Moze kilka przypadkow gdy kopiowane sa jakies wieksze tablice :D
ld hl,$C000
ld a,(temp)
ld d,0
ld e,a ; de = (temp)
add hl,de
add hl,de
add hl,de
add hl,de ; lame, ale proste do złapania
kurcze nie dziala, cokolwiek zaladuje w temp to pod adresem C000 mam 00
-
A, jednak się nie dogadaliśmy.
Czy zmienna pod adresem $c000 jest 8 czy 16-bit?
(sugeruję zapisywać problem w pseudokodzie, c, pascalu, basicu... łatwiej dotrze do ludzi nie łapiących 65xx :) )
-
A, jednak się nie dogadaliśmy.
Czy zmienna pod adresem $c000 jest 8 czy 16-bit?
(sugeruję zapisywać problem w pseudokodzie, c, pascalu, basicu... łatwiej dotrze do ludzi nie łapiących 65xx :) )
EDIT. To ja tez ciala dalem, bo przeciez w taki sposob nie bede mial nic w komorce pamieci C000 :D Mozliwe kod jest ok, tylko jak teraz sprawdzic jaki adres ma w sobie HL? Musze jakos w debbugerze sprawdzic.
EDIT2: Ok wszystko gra, dzieki wielkie. Zapisalem sobie adres HL do innej komorki pamieci aby miec wizualizacje i widze jest ok :) Podglad wartosci rejestru HL takze pokazuje poprawnie wszystko. Sam sie zakrecilem... ;)
ld a,$20 ;testowo wartosc 20
ld (temp),a
LD HL,$C000
ld a,(temp)
ld d,0
ld e,a ; de = (temp)
add hl,de
add hl,de
add hl,de
add hl,de
ld ($C020),HL ; sprawdzilem wynik i bylo w ram zapisane C080 wiec gra, zwiekszenie 8x mialem wynik C100 wiec HI zwiekszone takze
-
Wracając do pytania z pierwszego postu - chyba powinno być ok, ale nie jest testowane (dzięki Dizzy9 za kod)
LD A,$20
LD D,0
LD E,A ; teraz w de bedzie $20 czyli wartosc jaka znajdować będzie sie na początku w Aku
ADD HL,DE
LD A,(HL)
LD D,E ;wrzucamy a do e, żeby mieć go w zapasie
LD HL,TileBits ;wrzucamy adres tablicy do hl
ADD HL,DE ;uzylismy de bo w d juz mamy zero z poprzedniego działania, oszczędzając cpu i rom
LD A,(HL) ;pobraliśmy bajt z tablicy TileBits
Pytanko jak w WLA-DX zdefiniować podobnie dzialajaca tablice "TileBits" zawierajaca zestaw STAŁYCH?
.define AirTile $00
.define SolidTile $01...
?
TileBits:
.byte AirTile
.byte SolidTile
.byte SolidTile...etc
-
<mode name="nokia-lumia">
Nie wiem jak w WLA_DX, ale w każdym w miarę normalnym assemblerze :
AirTile equ $00
SolidTil equ $01
TileBits:
db AirTile,AirTile,AirTile,SolidTil
db AirTile,SolidTil,SolidTil,AirTile
db AirTile,SolidTil,AirTile,SolidTil
db SolidTil,AirTile,AirTile,AirTile
db AirTile
db AirTile
db SolidTil
db AirTile
db AirTile
db SolidTil
db SolidTil
A w takim np. ZASM możesz nawet :
#define AirTile $00
#define SolidTile $01
TileBits:
.byte AirTile
.byte SolidTile
.byte SolidTile
</mode>
-
LD D,E ;wrzucamy a do e, żeby mieć go w zapasie
A nie powinno być aby:
LD E,A ;wrzucamy a do e, żeby mieć go w zapasie
?
-
Wiec raczej literowka i bedzie LD E,A jak zauwazyles. Nie testowalem jeszcze.
-
Szukałem wątku porównującego 6502 do Z80, to wkleję tu ciekawą dyskusję o tych prockach po angielsku:
https://retrocomputing.stackexchange.com/questions/5748/comparing-raw-performance-of-the-z80-and-the-6502