DPTP motor: ...
DPTP motor: ...
Írjunk játékot SEGA MEGA DRIVE konzolra - 5. Inicializálás
Blog
2019-09-11 10:34
don_peter
Írások: 13
SEGA Inicializálása

A SEGA programozásának egyik legátláthatatlanabb és egyben a megfelelő dokumentációjának hiánya miatt, a legbonyolultabb rész is egyben a minden hiba visszajelzést mellőző legelső vektorállomány inicializálása. Teljesen én sem értem, és nem is találtam kielégítő leírást róla ezért én ezt a részt át is ugrom, illetve csak néhány mondat erejéig foglalkozom a témával. Már az elején jeleztem, hogy sok mindent én is csak a blog sorozat írása közben tapasztalok meg és sok mindent ezen sorok írása közben kell megértsek és valamelyest átadjak. Kezdjük is el szépen lassan.

A SEGA konzolunk indulásnál egy blokk vektor és header állományt kell betöltsön, amelyek az egyes hardverrészeket (ha úgy tetszik külön dedikált IC-ket vagy különböző vegyes diszkrét elemeket) konfigurál fel alapértelmezett beállításokkal. Ezek az alapértelmezett beállítások a háttérben, minden előzetes és utólagos hibaüzenet nélkül hajtódnak végre, melyeket nem lehet ellenőrizni, illetve maximum csak szkóp vagy esetleg logikai analizátorokkal. Mivel mind kettő esetében szét kell szerelnünk a konzolt és fizikailag is turkálnunk kell a hardver bugyraiban ezt a lehetőséget kizártam és nem is szerettem volna vele több időt eltölteni. Illetve tévedtem a hibaüzenettel kapcsolatban, mert egy azért akad, még pedig, ha valamilyen oknál fogva a vektor vagy header állományunkat nem sikerült a megfelelő módon megadni és vagy betölteni a konzolnak, akkor az a hiba, hogy nincs hiba, cserébe kép és egyéb jelenséget sem fog produkálni a konzolunk. Feltehetitek a kérdést magatokba, hogy akkor még is, hogy búbánatba fogjátok ezt a vektor és header állományt elkészíteni, hogy minden a megfelelő keppen működjön. Sehogy, de szerencsénkre nem is nagyon kell vele foglalkozni, mert az okosok megszerezték az alap vektor és header állományt és így nekünk csak be kell másolnunk és elvileg minden a helyére is kerül. Persze a header állmonyunkat mi is piszkálhatjuk, főként mert fontos infókat írhatunk be a fejlesztéssel kapcsolatba.

Nézzük meg elsőnek a vektorállományt.:
;==========
; CPU VECTOR TÁBLA (M68K)
;==========
    dc.l 0x00FFE000             ; Kezdeti veremmutató értéke
    dc.l CPU_EntryPoint         ; A program indítása
    dc.l CPU_Exception          ; Busz hiba
    dc.l CPU_Exception          ; Cím hiba
    dc.l CPU_Exception          ; Illegális utasítások
    dc.l CPU_Exception          ; Osztás nullával
    dc.l CPU_Exception          ; CHK CPU_Exception
    dc.l CPU_Exception          ; TRAPV CPU_Exception
    dc.l CPU_Exception          ; Jogosultságok megsértése
    dc.l INT_Null               ; TRACE kivétel
    dc.l INT_Null               ; Line-A emulátor
    dc.l INT_Null               ; Line-F emulátor
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Hamis kivétel
    dc.l INT_Null               ; IRQ 1. szint
    dc.l INT_Null               ; IRQ 2. szint
    dc.l INT_Null               ; IRQ 3. szint
    dc.l INT_HInterrupt         ; IRQ 4. szint (vízszintes visszavonás megszakítása)
    dc.l INT_Null               ; IRQ 5. szint
    dc.l INT_VInterrupt         ; IRQ 6. szint (függőleges visszavonás megszakítás)
    dc.l INT_Null               ; IRQ 7. szint
    dc.l INT_Null               ; TRAP #00 kivétel
    dc.l INT_Null               ; TRAP #01 kivétel
    dc.l INT_Null               ; TRAP #02 kivétel
    dc.l INT_Null               ; TRAP #03 kivétel
    dc.l INT_Null               ; TRAP #04 kivétel
    dc.l INT_Null               ; TRAP #05 kivétel
    dc.l INT_Null               ; TRAP #06 kivétel
    dc.l INT_Null               ; TRAP #07 kivétel
    dc.l INT_Null               ; TRAP #08 kivétel
    dc.l INT_Null               ; TRAP #09 kivétel
    dc.l INT_Null               ; TRAP #10 kivétel
    dc.l INT_Null               ; TRAP #11 kivétel
    dc.l INT_Null               ; TRAP #12 kivétel
    dc.l INT_Null               ; TRAP #13 kivétel
    dc.l INT_Null               ; TRAP #14 kivétel
    dc.l INT_Null               ; TRAP #15 kivétel
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)
    dc.l INT_Null               ; Nincs használatban (fenntartva)


Mint látható (persze amennyire ez látható), azért próbáltam utána járni és amennyire megértettem, úgy kommenteltem is az egyes sorokat. Ez a vektorállomány -gyakorlatilag- az egyes ugrási pontokat és a már foglalt memória ugrásokat hivatott előre megadni illetve néhány olyan beállítást is elvégez, amelyek a CPU és annak perifériájához köthető. A lényeg, hogy ennek az állománynak mint a következőnek is, minden SEGA indulásnál meg kell lennie.

Header állománnyal folytatjuk.:
;==========
; SEGA MEGA DRIVE ROM Fejléc
;==========
    dc.b "SEGA MEGA DRIVE "                                 ; Konzol neve
    dc.b "DPTP System 2019"                                 ; Szerzői jog tulajdonosa,kiadási dátuma
    dc.b "DPTP SYSTEM - PELDA PROGRAM                     " ; Hazai név
    dc.b "DPTP SYSTEM - PELDA PROGRAM                     " ; Nemzetközi név
    dc.b "GM XXXXXXXX-XX"                                   ; Verziószám
    dc.w 0x0000                                             ; ellenőrző szám
    dc.b "J               "                                 ; I/O támogatás
    dc.l ROM_Start                                          ; A ROM kezdő címe
    dc.l ROM_End-1                                          ; A ROM végcíme
    dc.l 0x00FF0000                                         ; A RAM kezdő címe
    dc.l 0x00FF0000+0x0000FFFF                              ; A RAM végső címe
    dc.l 0x00000000                                         ; Az SRAM engedélyezve van
    dc.l 0x00000000                                         ; Felhasználatlan
    dc.l 0x00000000                                         ; Az SRAM kezdő címe
    dc.l 0x00000000                                         ; Az SRAM vég címe
    dc.l 0x00000000                                         ; Nincs használatban
    dc.l 0x00000000                                         ; Nincs használatban
    dc.b "                                        "         ; Megjegyzések (Nincs használva)
    dc.b "  E             "                                 ; Országkódok

A kommentekből azt hiszem egyértelműen kiderül, hogy még is melyik sor mit is csinál, itt amit lehet és biztonsággal módosíthat mindenki, az a hazai és a nemzetközi név és a szerzői jog neve részt. A többit nem ajánlom módosítani illetve a kezdetekben ne módosítsd, ameddig nem tudod pontosan mit is csinál az egyes beállítás. Később lesz majd szerepük a most nem piszkált soroknak.

Mikor a header és vektor tábla a helyére került, megkezdőzhet az első programunk vagy fejlesztői környezetünk összeállítása. Nem hiába írtam így, hogy környezet. Ahhoz, hogy egy olyan kis program, mint pl. a képernyőnk hátterének színét be tudjuk kedvünk szerint állítani, komoly inicializálás és beállítások kell hogy megelőzze. Ilyen beállításokat mint: VDP beállítása, TMSS regisztráció, Konstansok deklarálása és színpaletta létrehozása. Mind ez így leírva nem sok, de összességében azért nem is kevés.

Kezdjük a VDP beállításokkal.:
;==========
; Kezdeti VDP regiszter értékek
;==========
VDPRegisters:
    dc.b 0x14 ; 0x00: Horizontális megszakítás engedélyezve, paletták engedélyezve
    dc.b 0x74 ; 0x01: Vertikális megszakítás engedélyezve, képernyő be, DMA be, Genesis mód bekapcsolva
    dc.b 0x30 ; 0x02: Minta táblázat az A görgetési síkhoz VRAM 0xC000-ben (3-5 bit = 13-15 bit)
    dc.b 0x00 ; 0x03: (0x34) Minta tábla ablak síkhoz a VRAM 0xD000-on (tiltva) (1-5 bit = 11-15 bit)
    dc.b 0x07 ; 0x04: Minta táblázat a B görgetési síkhoz VRAM 0xE000-nél (0-2 bit = 11-15 bit)
    dc.b 0x78 ; 0x05: Sprite attribútumtáblázat a VRAM 0xF000-ben (0-6 bit = 9-15 bit)
    dc.b 0x00 ; 0x06: Felhasználatlan
    dc.b 0x00 ; 0x07: Háttérszín: 0-3 = bit, 4-5 bit = paletta
    dc.b 0x00 ; 0x08: Felhasználatlan
    dc.b 0x00 ; 0x09: Felhasználatlan
    dc.b 0x08 ; 0x0A: A Horizontális frissítés gyakorisága. Megszakítás a raszterekben. (a katódsugár által vezetett vonalak száma)
    dc.b 0x00 ; 0x0B: Külső megszakítások tiltva, Vertikális laponkénti görgetés, Horizontális oldalankénti görgetés
    dc.b 0x81 ; 0x0C: Árnyékolás és kiemelés kikapcsolva, interlace kikapcsolva, H40 mód (320 x 224 képernyo)
    dc.b 0x3F ; 0x0D: Horiz. görgetési táblázat: VRAM 0xFC00 (0-5 bit)
    dc.b 0x00 ; 0x0E: Felhasználatlan
    dc.b 0x02 ; 0x0F: Automatikus beállítás 2 bájt
    dc.b 0x01 ; 0x10: Görgetési sík mérete: 64x32 csempe (512x256)
    ; Az ablak sík A síkot takarja, X tengelyen 0xA a közép állás, Y tengelyen 0xD, ablak sík max 1120byte, fix
    ; és 0xD000-ás címen van foglalva a memória területe
    dc.b 0x00 ; 0x11: X ablak sík 0 balra (pozíció 0-4, bal / jobb a 7. bitben)
    dc.b 0x00 ; 0x12: Y ablak sík 0 felfelé (pozíció a 0-4 bitben, fel / le a 7. bitben)
 
    dc.b 0xFF ; 0x13: DMA hossza lo bájt
    dc.b 0xFF ; 0x14: DMA hossza hi bájt
    dc.b 0x00 ; 0x15: DMA forráscím lo byte
    dc.b 0x00 ; 0x16: DMA forráscím mid bájt
    dc.b 0x80 ; 0x17: DMA forráscím hi bájt, memória-VRAM mód (6-7 bit)
   
    even ; páros címre igazít


Szépen kommenteltem az alap beállításokat, amelyeket a VDP felkonfigurálásához szükséges. Ezek a regiszterek és értékeiket egy direkt erre írt kicsi kis rutinnal töltjük fel, hogy gyorsabb és egyszerűbb legyen. Ez a rutin az alábbi kódrészletben látható.:
VDP_LoadRegisters:
    ; VDP registerek beállítása
    lea    VDPRegisters, a0                ; Töltse be a regisztertábla címét az a0-ba
    move.w #0x18-1, d0                ; 24 regiszter írásra (-1 a hurokszámlálóra)
    move.w #0x8000, d1                ; 'Regiszter 0' parancs beállítása d1-nek

    @CopyRegLp:
    move.b (a0)+, d1                ; A memória címen tárolt értéknek áthelyezük a d1 alacsonyabb bájtjába (közben a0 címet inkrementáljuk)
    move.w d1, vdp_control                ; Írja a d1-et (parancs) a VDP vezérlőportra
    addi.w #0x0100, d1                ; Hozzá adunk 0x100-at d1-ez
    dbra   d0, @CopyRegLp                ; A d0 csökkentése, és a hurok tetejére ugrás, ha a d0 még mindig >= 0
    rts

A kód szerintem világos lesz midnenkinek, aki az előző bejegyzésemet olvasta, talán csak 1 vagy maximum kettő utasítás lehet ismeretlen, ez vagy ezek a lea és az rts utasítások. Nem kell megijedni tőlük mind kettő rendkívűl egyértelmű, a lea utasítás annyit tesz, hogy a0 cím regiszterünkbe, az előtte lévő címke memóriában elfoglalt helyének címét adja át. Tehát ez esetben ha VDPRegisters a 0x001234-es címen van eltárolva a memóriba, akkor a0 regiszter értéke 0x001234, ugyan is a lea utasítás a cím betöltését jelenti. Az rts utasítás a return rövidítése, amikor ezt a visszatérési utasítást használjuk, akkor az ugrás előtti állapottal tér vissza a program egy jsr vagy is függvény hívás esetén. jsr-ről késöbb lesz majd szó.
Tehát ez a kis rutin azt csinálja, hogy a VDPRegisters cimke alá begépelt adatokat soronként betölti a VDP kontrol regiszterébe, így elérve a megfelelő beállításokat. Még talán annyi, hogy a vdp_control egy konstans változó, amelyet deklarálni kell, ezt mutatom lejjebb.

Konstansok:
;==========
; Konstansok, ÁLLANDÓK
;==========
; Meghatározza az általánosan használt értékek és címek nevét
; a kód olvashatóbb.
;==========

; VDP portcímek
vdp_control             equ 0x00C00004
vdp_data                equ 0x00C00000

; VDP parancsok
vdp_cmd_vram_write        equ 0x40000000
vdp_cmd_cram_write        equ 0xC0000000
vdp_cmd_cram_read        equ 0x8000000
vdp_cmd_vsram_write        equ 0x40000010

; Függoleges kioltó teszt bit
vdp_status_vblank        equ 0x3

; VDP memóriacímek
; a VDP 0x2, 0x4, 0x5 és 0xD regiszterek alapján (lásd a fenti táblázatot)
vram_addr_tiles            equ 0x0000
vram_addr_plane_a        equ 0xC000
vram_addr_window        equ 0xD000
vram_addr_plane_b        equ 0xE000
vram_addr_sprite_table        equ 0xF000       // Sprite-oknak fentartott 4Kb
vram_addr_hscroll        equ 0xFC00
vram_addr_vscroll        equ 0x4FC00

; Hardver verzió címe
hardware_ver_address    equ 0x00A10001

; TMSS
tmss_address            equ 0x00A14000
tmss_signature            equ 'SEGA'

A konstansokról remélem nem kell többet írnom, ezek olyan változók melyek a program futása közben nem változnak, a deklarált értéküket megtartják. A következőben a TMSS védelemmel fogglalkozunk, de csak röviden:
VDP_WriteTMSS:
    ; Be kell tenni a TMSS-t, hogy megjelenítse a "LICENSED BY SEGA ..." üzenetet, és engedje nekünk,
    ; hogy hozzáférünk a VDP memóriához (itt majd egy ellenorzést kell csinálnom, hogy milyen SEGA-val intítják a programot)
    move.b hardware_ver_address, d0            ; Mozgassa a Megadrive hardver verzióját d0-ra
    andi.b #0x0F, d0                ; A verzió az utolsó négy bitben tárolódik, így 0F-el and-eljük
    beq    @SkipTMSS                ; Ha a verzió 0, akkor hagyja ki a TMSS aláírást
    move.l #tmss_signature, tmss_address        ; Mozgassa a "SEGA" karakterláncot 0xA14000-re
    @SkipTMSS:

    ; VDP ellenorzése
    move.w vdp_control, d0                ; Olvassa be a VDP állapotregisztert (ha nincs hozzáférés)
    rts


TMSS rendszerről azt kell tudni, hogy az első SEGA MD1-es verziójában még nem volt, de később tartva a kalozmásolatoktól és a nem liszenszelt fejlesztő csapatok programjaitól, bevezetésre került. Ez a védelem már az MD1-es második verzióját is érintette, de teljessé csak a 2-es módeltől kezdve volt tényleg elterjedt. A védelem egyébként nem más, mint egy megadott regiszterbe betöltött SEGA szó, amely a VDP dedikált hardverét engedélyezi. Ha ezt a TMSS rendszert valaki elfelejti, akkor cserébe a VDP letíltódik és nem lesz hajlandó együtműködni a rnedszer további részével. egyébként kevesen tudják, de elég egysszerűen ki lehet kerülni a TMSS rendszert, de ez már hardveres módosítást igényel és nem is sok értelme van, főleg, hogy programból is könnyedén kiiktatható a védelem.
Utolsóként, de nem utolsó sórban muszáj beállítanunk egy előre elkészített színpaletát is, amelyet a VDP szín memóriájába kell feltöltenünk.

Színpaletta
;-----------------------
;VDP Color Palette
;--------------------
Proba:          ; Egy alap paletta, 15+1 színnel
    dc.w 0x0000 ; Szín 0 - Átlátszó
    dc.w 0x000E ; Szín 1 - Píros
    dc.w 0x00E0 ; Szín 2 - Zöld
    dc.w 0x0E00 ; Szín 3 - Kék
    dc.w 0x0000 ; Szín 4 - Fekete
    dc.w 0x0EEE ; Szín 5 - Fehér
    dc.w 0x00EE ; Szín 6 - Sárga
    dc.w 0x008E ; Szín 7 - Naracs
    dc.w 0x0E0E ; Szín 8 - Rózsaszín
    dc.w 0x0808 ; Szín 9 - Lila
    dc.w 0x0444 ; Szín A - Sötétszürke
    dc.w 0x0888 ; Szín B - Világosszűrke
    dc.w 0x0EE0 ; Szín C - Türkíz
    dc.w 0x000A ; Szín D - Rozsda vörös
    dc.w 0x0600 ; Szín E - Katona kék
    dc.w 0x0060 ; Szín F - Sötét zöld

Itt is a kommentekből egyértelműen kitűnik melyik színhez melyik adat tartozik, ezek beírása pedig a következő képen néz ki:
    ;**********
    ; A csillagok közé írhatjuk a programunkat

    ; Betöltjük a szinpalettát
    move.l #0xC0000003, 0x00C00004    ; VDP CRAM 0x0000 címére írunk
    lea    Palettes, a0        ; Palettánk kezdo címét betöltjuk a0 regiszterbe
    move.w #15, d0            ; ciklus számlálót beállítjuk
    @PalLp:                ; ciklus megkezdése
    move.w (a0)+, vdp_data        ; dpt adat protjára kiírjuk a soron következo adatot és inkrementáljuk a0 címét
    dbra d0, @PalLp   

    move.w #0x8702, vdp_control  ; Beállítunk egy háttérszinet
    ;         ||||
    ;         |||`--------------> Szín
    ;         ||`---------------> Paletta
    ;         ``----------------> 87 = Háttér szín regiszter

    ;**********

Ami ebből a kis kódrészből érdekes lehet az az utolsó sor amely már a SEGA háttérszínét változtatja meg a megadott színűre, esetünkben zöld színűre. Megfelelő kommentekkel elláttam, így sok magyarázatra nem is szorul a dolog. Fontos szerintem megjegyezni, hogy egy jól kommentezett programkód nagyon nagy segítségünkre lesz, főként akkor, ha mondjuk sok idő telik el két programozási napunk közt. Assemblernél meg amúgy is fontos a pontos és jó komment mert nagyon nehéz sokszor értelmezni a korábban megírt programunkat. A bemutatott módon már képesek lennénk össze ollózni egy kész induló projektet, de persze észrevehetően hiányoznak dolgok. Pl.: megszakytást kezelő rutinok, kezdő és végpontok...stb.
A projektet mint fejebb is említettem célszerű funkciókra, és vagy részegységekre bontani, így sokkal könnyebb az áttekintés és értelmezés nem beszélve a jobb struktúralításról. Szebb lesz a kódunk.

Megszakítási rutinok a teljeség igénye érdekében:
;==========
; Megszakítási rutinok
;==========
; Függoleges megszakítás - képkockánkénti futás (50 hz PAL-ban, 60hz NTSC-ben)
INT_VInterrupt:
    ; Nem tesz semmit ebben a demóban
    rte

; Vízszintes megszakítás - N-szkennelés soronként egyszer fut (N = meghatározott VDP regiszterben 0xA)
INT_HInterrupt:
    ; Nem tesz semmit ebben a demóban
    rte

; NULL megszakítás
INT_Null:
    rte

; Kivétel megszakítás - meghívódik, ha hiba történt
CPU_Exception:
    ; Csak akkor állítsa le a CPU-t, ha hiba történt
    stop   #0x2700
    rte
A megszakítási rutinokat a verem táblában dekraláltuk ezért a megfelelő működéshez szükséges hogy a programban is leírásra kerüljenek. Ezek kezelik a külömböző hibákat illetve képernyő frissítésekből adódó ismétlődéseket. Később lesz majd róla szó, mivel a kontroller, képi és audió be és kimeneteinek szerves részét képezik. Most a demó prigramunkba ezeket nem használjük.
Össze állítotam egy kis csomagot, hogy könnyebb legyen mindenkinek kipróbálni az eddig tanultakat és ne kelljen szenvedni a kódok össze illesztésével és a struktúrális kialakítással. Mivel már most is jókorára nőt ennek a bejegyzésnek a mérete, így nem kezdem el kivesézni az egyes részek működését, átteszem ezt egy másik bolgba. A lap alján pedig megtalálod az összeállított becsomagolt itt bemutatott programot.

Most teszteljük le az eddigieket:

DPTP System - Demo

A megírt programunk jól működik mivel a képernyő zöldre váltott. Szuper, innen már tovább lehet indulni. ;) A most megírt programocskának, amúgy az a nagy előnye, hogy szinte minden programunk alapját képezi, szóval ez egy olyan alap amit már csak fejleszteni kell a tudásunknak megfelelően. A projekt amúgy nem csak a programot, de a futtatásához előre elkészített futtatható fájlokat, fordításhoz szükséges fájlot és a teszteléshez szűkséges emulátort is tartalmazza. Csak használni kell és próbálgatni.
Fontos lehet még, hogy 3 indítható fájlunk van amik a következők: r.bat, make.bat és run.bat
Hogy melyik mire való?
r.bat fájlunk a megírt kódunk lefordítja és fórdítás után el is indítja az emulátort.
make.bat fájlunk csak a kódunk lefordításában fog segíteni
run.bat fájlunk pedig csak a már előzőleg lefordított programunkat indítja el az emulátorban

A következő részben kicsit kirészletezem majd a VDP működését és írunk egy olyan makrót is amellyel könnyebben lehet majd a VDP memóriájában lépkedni. Türelmeteket kérem, és addig is jó szórakozást a demó programhoz.

A letölthető oktató demót itt találod: DPTP_oktato.zip
Természetesen ezen cikk végéről sem maradhat le azon link mutatója, ahol feltehetitek kérdéseiteket a témában: Írjunk játékot SEGA MEGA DRIVE konzolra

Az erő legyen veletek.. ;)
DPTP motor: GDPR infomráció!
2018 Május 25.-től hatályba lépett adatvédelmi szabályzatról itt olvashatsz bővebben: Adatvédelmi tájékoztató
Az oldal további használatához el kell olvasnod és fogadnod az adatvédelmi és cookie-k használatával kapcsolatos tájékoztatonkat.

Elfoadom!
Nem fogadom el!