Ngiyithole kanjani idatha ngefomethi engaziwa kutheyiphu kazibuthe

prehistory

Njengomthandi we-retro hardware, ngake ngathenga i-ZX Spectrum+ kumthengisi wase-UK. Kuhlanganiswe nekhompyutha ngokwayo, ngithole amakhasethi alalelwayo amaningana anemidlalo (ephaketheni lokuqala elineziqondiso), kanye nezinhlelo eziqoshwe kumakhasethi ngaphandle kokumaka okukhethekile. Ngokumangalisayo, idatha evela kumakhasethi aneminyaka engu-40 ubudala yayifundeka kahle futhi ngakwazi ukulanda cishe yonke imidlalo nezinhlelo kuzo.

Ngiyithole kanjani idatha ngefomethi engaziwa kutheyiphu kazibuthe

Nokho, kwamanye amakhasethi ngathola ukuqoshwa okucacile ukuthi ayenziwanga ikhompyutha ye-ZX Spectrum. Bazwakala behluke ngokuphelele futhi, ngokungafani nokuqoshwa okuvela kukhompyutha eshiwo, abazange baqale nge-bootloader emfushane ye-BASIC, evame ukuba khona ekurekhodweni kwazo zonke izinhlelo nemidlalo.

Okwesikhathi esithile lokhu kwangiphatha kabi - ngangifuna ngempela ukuthola ukuthi yini eyayifihlwe kuzo. Uma ukwazi ukufunda isignali yomsindo njengokulandelana kwamabhayithi, ungabheka izinhlamvu nanoma yini ebonisa umsuka wesiginali. Uhlobo lwe-retro-archaeology.

Manje njengoba ngihambe yonke indlela futhi ngibheka amalebula amakhasethi ngokwawo, ngimamatheka ngoba

impendulo yayiphambi kwamehlo ami njalo
Kwilebula yekhasethi lesobunxele kunegama lekhompyutha ye-TRS-80, futhi ngezansi nje kwegama lomkhiqizi: β€œIkhiqizwe iRadio Shack e-USA”

(Uma ufuna ukugcina uzungu kuze kube sekugcineni, ungangeni ngaphansi komchithi)

Ukuqhathaniswa kwezimpawu zomsindo

Okokuqala, masifake okurekhodiwe kwidijithali. Ungalalela ukuthi kuzwakala kanjani:


Futhi njengokujwayelekile ukuqoshwa okuvela kukhompyutha ye-ZX Spectrum kuzwakala:


Kuzo zombili izimo, ekuqaleni kokuqoshwa kukhona okuthiwa ithoni yomshayeli - umsindo wemvamisa efanayo (ekurekhodweni kokuqala kufushane kakhulu <isekhondi elingu-1, kodwa liyahlukaniseka). Ithoni yokuhlola ikhombisa ikhompuyutha ukuthi ilungiselele ukwamukela idatha. Njengomthetho, ikhompyutha ngayinye ibona kuphela ithoni yomshayeli "eyayo" ngokuma kwesiginali kanye nemvamisa yayo.

Kuyadingeka ukusho okuthile ngesimo sesignali ngokwayo. Isibonelo, ku-ZX Spectrum ukwakheka kwayo kungunxande:

Ngiyithole kanjani idatha ngefomethi engaziwa kutheyiphu kazibuthe

Uma kutholwa ithoni yokushayela, i-ZX Spectrum ibonisa amabha abomvu naluhlaza ashintshana emngceleni wesikrini ukukhombisa ukuthi isignali iboniwe. Ithoni yokushayela iyaphela i-synchro pulse, okubonisa ikhompuyutha ukuthi iqale ukwamukela idatha. Ibonakala ngobude besikhathi obufushane (uma kuqhathaniswa nethoni yokuhlola kanye nedatha elandelayo) (bona umfanekiso)

Ngemuva kokuthi i-pulse yokuvumelanisa yamukelwe, ikhompuyutha irekhoda ukuphakama/ukwehla ngakunye kwesignali, ikala ubude bayo. Uma ubude besikhathi bungaphansi komkhawulo othile, ibhithi elingu-1 libhalwa enkumbulweni, ngaphandle kwalokho 0. Amabhithi aqoqwa abe amabhayithi futhi inqubo iphindaphindiwe kuze kube yilapho kutholwa amabhayithi angu-N. Inombolo N ivamise ukuthathwa enhlokweni yefayela elilandiwe. Ukulandelana kokulayisha imi kanje:

  1. ithoni yomshayeli
  2. unhlokweni (ubude obulungisiwe), uqukethe usayizi wedatha elandiwe (N), igama lefayela nohlobo
  3. ithoni yomshayeli
  4. idatha ngokwayo

Ukuqinisekisa ukuthi idatha ilayishwe ngendlela efanele, i-ZX Spectrum ifunda okuthiwa i-parity byte (ibhayithi yokulinganisa), ebalwa lapho ulondoloza ifayela ngo-XORing wonke amabhayithi edatha ebhaliwe. Lapho ufunda ifayela, ikhompuyutha ibala i-parity byte kusuka kudatha etholiwe futhi, uma umphumela uhlukile kulowo ogciniwe, ubonisa umlayezo wephutha "Iphutha lokulayisha i-R Tape". Uma sikhuluma ngokuqinile, ikhompuyutha ingakhipha lo mlayezo kusenesikhathi uma, lapho ifunda, ingakwazi ukubona ukushaya kwenhliziyo (okugejiwe noma ubude bayo bungahambisani nemikhawulo ethile)

Ngakho-ke, manje ake sibone ukuthi isignali engaziwa ibukeka kanjani:

Ngiyithole kanjani idatha ngefomethi engaziwa kutheyiphu kazibuthe

Lena ithoni yomshayeli. Ukuma kwesignali kuhluke kakhulu, kodwa kusobala ukuthi isignali iqukethe ukuphindaphinda ama-pulses amafushane wemvamisa ethile. Kumvamisa yesampula engu-44100 Hz, ibanga eliphakathi kokuthi "iziqongo" cishe lingamasampuli angu-48 (elihambisana nemvamisa engu-~918 Hz). Masikhumbule lesi sibalo.

Manje ake sibheke ucezu lwedatha:

Ngiyithole kanjani idatha ngefomethi engaziwa kutheyiphu kazibuthe

Uma sikala ibanga phakathi kwama-pulses angawodwana, kuvela ukuthi ibanga eliphakathi kwama-pulses "amade" lisengamasampuli angu-~48, futhi phakathi kwamafushane - ~ 24. Uma ngibheka phambili kancane, ngizosho ukuthi ekugcineni kwavela ukuthi ama-pulses "reference" anemvamisa ye-918 Hz alandela ngokuqhubekayo, kusukela ekuqaleni kuze kube sekupheleni kwefayela. Kungacatshangwa ukuthi lapho kudluliswa idatha, uma i-pulse eyengeziwe ihlangatshezwana nama-pulses ereferensi, sikubheka njenge-bit 1, ngaphandle kwalokho u-0.

Kuthiwani nge-sync pulse? Ake sibheke ekuqaleni kwedatha:

Ngiyithole kanjani idatha ngefomethi engaziwa kutheyiphu kazibuthe

Ithoni yokuhlola iyaphela futhi idatha iqala ngokushesha. Kamuva, ngemva kokuhlaziya okurekhodiwe okuhlukahlukene okuhlukahlukene, sikwazile ukuthola ukuthi ibhayithi yokuqala yedatha ihlezi ifana (10100101b, A5h). Ikhompyutha ingase iqale ukufunda idatha ngemva kokuyithola.

Ungakwazi futhi ukunaka ukuguquka kokushaya kwesithenjwa kokuqala ngokushesha ngemva kokokugcina kubhayithi yokuvumelanisa. Kutholwe kamuva kakhulu kunqubo yokuthuthukisa uhlelo lokuqaphela idatha, lapho idatha ekuqaleni kwefayela ingakwazi ukufundwa ngokuzinzile.

Manje ake sizame ukuchaza i-algorithm ezocubungula ifayela elilalelwayo futhi ilayishe idatha.

Ilayisha Idatha

Okokuqala, ake sibheke ukuqagela okumbalwa ukuze sigcine i-algorithm ilula:

  1. Sizocabangela kuphela amafayela ngefomethi ye-WAV;
  2. Ifayela lomsindo kufanele liqale ngethoni yokuhlola futhi akufanele liqukathe ukuthula ekuqaleni
  3. Ifayela elingumthombo kufanele libe nesilinganiso sesampula esingu-44100 Hz. Kulokhu, ibanga eliphakathi kwama-reference pulses amasampula angu-48 selinqunyiwe kakade futhi asikho isidingo sokulibala ngokohlelo;
  4. Ifomethi yesampula ingaba yinoma yimaphi (amabhithi angu-8/16/iphuzu elintantayo) - kusukela lapho sifunda singayiguqulela kule esiyifunayo;
  5. Sicabanga ukuthi ifayela lomthombo lijwayelekile nge-amplitude, okufanele izinze umphumela;

I-algorithm yokufunda izoba kanje:

  1. Sifunda ifayela enkumbulweni, ngesikhathi esifanayo siguqule ifomethi yesampula kumabhithi angu-8;
  2. Nquma indawo ye-pulse yokuqala kudatha yomsindo. Ukuze wenze lokhu, udinga ukubala inombolo yesampula nge-amplitude enkulu. Ukwenza kube lula, sizoyibala kanye mathupha. Masiyigcine kokuguquguqukayo prev_pos;
  3. Engeza u-48 endaweni yokushaya kokugcina (pos := prev_pos + 48)
  4. Njengoba ukwandisa isikhundla ngo-48 akuqinisekisi ukuthi sizofika endaweni ye-pulse yereferensi elandelayo (ukukhubazeka kwe-tape, ukusebenza okungazinzile komshini we-tape drive, njll.), sidinga ukulungisa isikhundla se-pos pulse. Ukuze wenze lokhu, thatha idatha encane (pos-8;pos+8) futhi uthole inani eliphezulu le-amplitude kuyo. Indawo ehambisana nobukhulu izogcinwa ku-pos. Lapha i-8 = 48/6 iyisimo esitholwe ngokuhlolwa, esiqinisekisa ukuthi sizonquma ubukhulu obulungile futhi ngeke sithinte eminye imifuziselo engase ibe seduze. Ezimweni ezimbi kakhulu, lapho ibanga eliphakathi kwama-pulses lingaphansi kakhulu noma lingaphezulu kuka-48, ungasebenzisa ukusesha okuphoqelekile kwe-pulse, kodwa ngaphakathi kwe-athikili ngeke ngikuchaze lokhu ku-algorithm;
  5. Esinyathelweni sangaphambilini, kuzodingeka futhi ukuthi uhlole ukuthi i-pulse yereferensi itholakele nhlobo. Okusho ukuthi, uma umane ubheka ubukhulu, lokhu akuqinisekisi ukuthi umfutho ukhona kule ngxenye. Ekuqaliseni kwami ​​​​kwakamuva kohlelo lokufunda, ngibheka umehluko phakathi kwamanani aphezulu kanye nobuncane be-amplitude engxenyeni, futhi uma yeqa umkhawulo othile, ngibala ukuba khona komfutho. Umbuzo futhi ukuthi yini okufanele uyenze uma i-pulse yereferensi ingatholakali. Kunezinketho ezi-2: kungenzeka ukuthi idatha iphelile futhi ukuthula kuyalandela, noma lokhu kufanele kuthathwe njengephutha lokufunda. Nokho, sizokweqa lokhu ukuze senze i-algorithm ibe lula;
  6. Esinyathelweni esilandelayo, sidinga ukunquma ubukhona be-data pulse (bit 0 noma 1), kulokhu sithatha indawo ephakathi nesegimenti (prev_pos;pos) middle_pos elingana ne-middle_pos := (prev_pos+pos)/2 futhi endaweni ethile ye-middle_pos kwisegimenti (maphakathi_pos-8;maphakathi_pos +8) ake sibale ubukhulu nobuncane be-amplitude. Uma umehluko phakathi kwazo ungaphezu kuka-10, sibhala kancane u-1 kumphumela, ngaphandle kwalokho u-0. 10 uwukutholwa njalo kokuhlolwa;
  7. Londoloza indawo yamanje kokuthi prev_pos (prev_pos := pos)
  8. Phinda uqale kusukela esinyathelweni sesi-3 size silifunde lonke ifayela;
  9. Umphumela wohlelo lwebhithi kufanele ulondolozwe njengesethi yamabhayithi. Njengoba asizange sinake i-byte yokuvumelanisa lapho sifunda, inani lamabhithi lingase lingabi ukuphindaphinda kuka-8, futhi i-bit offset edingekayo nayo ayaziwa. Ekusetshenzisweni kokuqala kwe-algorithm, bengingazi ngobukhona be-byte yokuvumelanisa ngakho-ke ngimane ngilondoloze amafayela ayi-8 anezinombolo ezihlukene zama-offset bits. Enye yazo ibiqukethe idatha elungile. Ku-algorithm yokugcina, ngivele ngisuse zonke izingcezu kuze kufike ku-A5h, okungivumela ukuthi ngithole ngokushesha ifayela eliphumayo elilungile.

I-algorithm ku-Ruby, eyalabo abanentshisekelo
Ngikhethe uRuby njengolimi lokubhala uhlelo, ngoba... Ngihlela kuyo isikhathi esiningi. Inketho akuyona ukusebenza okuphezulu, kodwa umsebenzi wokwenza isivinini sokufunda ngokushesha ngangokunokwenzeka awufanelekile.

# Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ gem 'wavefile'
require 'wavefile'

reader = WaveFile::Reader.new('input.wav')
samples = []
format = WaveFile::Format.new(:mono, :pcm_8, 44100)

# Π§ΠΈΡ‚Π°Π΅ΠΌ WAV Ρ„Π°ΠΉΠ», ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Mono, 8 bit 
# Массив samples Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΡΡ‚ΠΎΡΡ‚ΡŒ ΠΈΠ· Π±Π°ΠΉΡ‚ со значСниями 0-255
reader.each_buffer(10000) do |buffer|
  samples += buffer.convert(format).samples
end

# ΠŸΠΎΠ·ΠΈΡ†ΠΈΡ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΈΠΌΠΏΡƒΠ»ΡŒΡΠ° (вмСсто 0)
prev_pos = 0
# РасстояниС ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΈΠΌΠΏΡƒΠ»ΡŒΡΠ°ΠΌΠΈ
distance = 48
# Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ расстояния для окрСстности поиска локального максимума
delta = (distance / 6).floor
# Π‘ΠΈΡ‚Ρ‹ Π±ΡƒΠ΄Π΅ΠΌ ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ Π² Π²ΠΈΠ΄Π΅ строки ΠΈΠ· "0" ΠΈ "1"
bits = ""

loop do
  # РассчитываСм ΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ ΠΈΠΌΠΏΡƒΠ»ΡŒΡΠ°
  pos = prev_pos + distance
  
  # Π’Ρ‹Ρ…ΠΎΠ΄ΠΈΠΌ ΠΈΠ· Ρ†ΠΈΠΊΠ»Π° Ссли Π΄Π°Π½Π½Ρ‹Π΅ Π·Π°ΠΊΠΎΠ½Ρ‡ΠΈΠ»ΠΈΡΡŒ 
  break if pos + delta >= samples.size

  # ΠšΠΎΡ€Ρ€Π΅ΠΊΡ‚ΠΈΡ€ΡƒΠ΅ΠΌ ΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ pos ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ΠΌ максимума Π½Π° ΠΎΡ‚Ρ€Π΅Π·ΠΊΠ΅ [pos - delta;pos + delta]
  (pos - delta..pos + delta).each { |p| pos = p if samples[p] > samples[pos] }

  # Находим сСрСдину ΠΎΡ‚Ρ€Π΅Π·ΠΊΠ° [prev_pos;pos]
  middle_pos = ((prev_pos + pos) / 2).floor

  # Π‘Π΅Ρ€Π΅ΠΌ ΠΎΠΊΡ€Π΅ΡΡ‚Π½ΠΎΡΡ‚ΡŒ Π² сСрСдинС 
  sample = samples[middle_pos - delta..middle_pos + delta]

  # ΠžΠΏΡ€Π΅Π΄Π΅Π»ΡΠ΅ΠΌ Π±ΠΈΡ‚ ΠΊΠ°ΠΊ "1" Ссли Ρ€Π°Π·Π½ΠΈΡ†Π° ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΌ ΠΈ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ Π½Π° ΠΎΡ‚Ρ€Π΅Π·ΠΊΠ΅ ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ°Π΅Ρ‚ 10
  bit = sample.max - sample.min > 10
  bits += bit ? "1" : "0"
end

# ΠžΠΏΡ€Π΅Π΄Π΅Π»ΡΠ΅ΠΌ синхро-Π±Π°ΠΉΡ‚ ΠΈ замСняСм всС ΠΏΡ€Π΅Π΄ΡˆΠ΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ Π±ΠΈΡ‚Ρ‹ Π½Π° 256 Π±ΠΈΡ‚ Π½ΡƒΠ»Π΅ΠΉ (согласно спСцификации Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π°) 
bits.gsub! /^[01]*?10100101/, ("0" * 256) + "10100101"

# БохраняСм Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠΉ Ρ„Π°ΠΉΠ», упаковывая Π±ΠΈΡ‚Ρ‹ Π² Π±Π°ΠΉΡ‚Ρ‹
File.write "output.cas", [bits].pack("B*")

Umphumela

Ngemva kokuzama ukuhlukahluka okuningana kwe-algorithm nama-constants, ngaba nenhlanhla yokuthola okuthile okuthakazelisa kakhulu:

Ngiyithole kanjani idatha ngefomethi engaziwa kutheyiphu kazibuthe

Ngakho-ke, ukwahlulela ngezintambo zomlingiswa, sinohlelo lokuhlela amagrafu. Nokho, awekho amagama angukhiye embhalweni wohlelo. Wonke amagama angukhiye abhalwe ngekhodi njengamabhayithi (inani ngalinye > 80h). Manje sidinga ukuthola ukuthi iyiphi ikhompyutha evela kuma-80s engagcina izinhlelo ngale fomethi.

Eqinisweni, ifana kakhulu nohlelo lwe-BASIC. Ikhompiyutha ye-ZX Spectrum igcina izinhlelo ngefomethi efanayo kumemori futhi igcina izinhlelo ukuze iqoshwe. Uma kwenzeka, ngihlole amagama angukhiye ngokumelene itafula. Nokho, umphumela ngokusobala wawumubi.

Ngiphinde ngahlola amagama angukhiye we-BASIC we-Atari ethandwayo, i-Commodore 64 namanye amakhompiyutha amaningana angaleso sikhathi, engikwazile ukuthola imibhalo, kodwa ngaphandle kwempumelelo - ulwazi lwami lwezinhlobo zamakhompiyutha we-retro aluzange lube lubanzi kangako.

Ngabe senginquma ukuhamba uhlu, futhi amehlo ami awela egameni lomkhiqizi weRadio Shack kanye nekhompyutha ye-TRS-80. Lawa amagama ayebhalwe emalebula amakhasethi ayebekwe etafuleni lami! Ngangingawazi la magama ngaphambilini futhi ngangingayazi ikhompuyutha ye-TRS-80, ngakho kwabonakala kimi ukuthi iRadio Shack ingumkhiqizi wamakhasethi alalelwayo afana ne-BASF, i-Sony noma i-TDK, futhi i-TRS-80 kwakuyisikhathi sokudlala. Kungani kungenjalo?

I-Computer Tandy/Radio Shack TRS-80

Kungenzeka kakhulu ukuthi ukurekhodwa komsindo okukhulunywa ngakho, engikunike njengesibonelo ekuqaleni kwesihloko, kwenziwa kukhompuyutha kanje:

Ngiyithole kanjani idatha ngefomethi engaziwa kutheyiphu kazibuthe

Kwavela ukuthi le khompyutha nezinhlobonhlobo zayo (Imodeli I / Imodeli III / Imodeli IV, njll.) yayithandwa kakhulu ngesikhathi esisodwa (yebo, hhayi eRussia). Kuyaphawuleka ukuthi iprosesa ababeyisebenzisa yayiyi-Z80. Kule khompyutha ungathola ku-inthanethi ulwazi oluningi. Ngawo-80s, ulwazi lwekhompiyutha lwasatshalaliswa omagazini. Okwamanje kukhona eziningana ama-emulators amakhompyutha ezinkundla ezahlukene.

Ngilande i-emulator trs80gp futhi ngokokuqala ngqa ngakwazi ukubona ukuthi le khompyutha isebenza kanjani. Vele, ikhompuyutha ayizange isekele ukuphuma kombala; ukulungiswa kwesikrini kwakungamaphikseli angu-128x48 kuphela, kodwa kwakukhona izandiso eziningi nokuguqulwa okungakhuphula ukulungiswa kwesikrini. Kwakukhona nezinketho eziningi zezinhlelo zokusebenza zale khompuyutha kanye nezinketho zokwenza ulimi lwe-BASIC (okuyinto, ngokungafani ne-ZX Spectrum, kwamanye amamodeli azange "akhanye" ku-ROM futhi noma iyiphi inketho ingalayishwa ku-floppy disk, njenge i-OS ngokwayo)

Nami ngithole usizo ukuguqula okurekhodiwe okulalelwayo kube ifomethi ye-CAS, esekelwa izilingisi, kodwa ngesizathu esithile akukwazanga ukufunda okurekhodiwe kumakhasethi ami ngiwasebenzisa.

Ngemva kokuthola ifomethi yefayela le-CAS (okuvele kwaba ikhophi kancane-kancane yedatha evela kutheyiphu engangivele nginayo, ngaphandle kwesihloko esinobukhona bebhayithi yokuvumelanisa), ngenze izinguquko ezimbalwa kuhlelo lwami futhi ngakwazi ukukhipha ifayela elisebenzayo le-CAS elisebenze kusifanisi (TRS-80 Model III):

Ngiyithole kanjani idatha ngefomethi engaziwa kutheyiphu kazibuthe

Ngiklame inguqulo yakamuva yensiza yokuguqula ngokunquma okuzenzakalelayo kwe-pulse yokuqala kanye nebanga phakathi kwama-reference pulses njengephakheji ye-GEM, ikhodi yomthombo iyatholakala kokuthi I-Github.

isiphetho

Indlela esiye sayihamba yaphenduka yaba uhambo oluthakazelisayo lwesikhathi esidlule, futhi ngiyajabula ngokuthi ekugcineni ngiyitholile impendulo. Phakathi kwezinye izinto, mina:

  • Ngithole ifomethi yokulondoloza idatha ku-ZX Spectrum futhi ngafunda imizila ye-ROM eyakhelwe ngaphakathi yokugcina/ukufunda idatha kumakhasethi alalelwayo.
  • Ngajwayelana nekhompiyutha ye-TRS-80 nezinhlobonhlobo zayo, ngafunda uhlelo lokusebenza, ngabheka izinhlelo zesampula futhi ngathola nethuba lokwenza ukulungisa iphutha kumakhodi omshini (phela, wonke ama-mnemonics e-Z80 ajwayelekile kimi)
  • Ubhale insiza ephelele yokuguqula okurekhodiwe komsindo kube ifomethi ye-CAS, engafunda idatha engaziwa insiza "esemthethweni"

Source: www.habr.com

Engeza amazwana