CGA má ještě jednu, nedokumentovanou, paletu ve složení červená, modrá, bílá. Dělá se to tak. že se zavolá INT 10h/AX=5
Služba je určená pro černobílé monitory.
Nicméně, pokud se na originální CGA kartě zavolá s barevným monitorem, tak se zobrazí právě červená, modrá, bílá.
Nepříjemné je, že pozdější karty (EGA, VGA) tuto fičuru nemají.
Více info např. zde:
http://dos.cyningstan.org.uk/post/194/cga-graphics-not-all-cyan-and-magenta
diky, to musim prozkoumat. Hlavne co to dela na urovni ridicich registru CGA (protoze me moc nenapada, ktery bit to nastavuje, aby se paleta prepnula)
Jinak - přímý výběr palety pomoc ovládání portů je samozřejmě možný, ale většina lidí by asi zavolala BIOS (alespoň já to tak dělával):
INT 10h
AH = 0Bh
BH = 01h
BL = palette ID
00h background, green, red, and brown/yellow
01h background, cyan, magenta, and white
pravda, ono je to pres BIOS bezpecnejsi, on si totiz vsechny ridici registry uklada nekam do nulteho segmentu (zpetne totiz nejdou precist). Ale zase kdyz je to o ovladani CGA, tak neni na skodu jit trosku do hloubky a zjistit, ze to ma doslova jen nekolik bitu, kterymi se to ovlada (+ CRTC registry, o tech vice priste, kdyz budeme hackovat textovy rezim)
11. 7. 2024, 12:53 editováno autorem komentáře
Já před devíti lety docela čuměl, jak internetem proletělo:
"CGA in 1024 Colors - a New Mode: the Illustrated Guide"
https://int10h.org/blog/2015/04/cga-in-1024-colors-new-mode-illustrated/
Nějak jsem to ale nezkoumal. To už je tak vzdálená historie, že k tomu nemám už moc vztah. XTčka jsem sice zažil, ale nikdy neměl. To už víc nostalgicky vzpomínám na 8bitové Atari, které jsem měl.
jj to je možný s NTSC (Never The Same Colors) monitorem. Zkusim se o tom zminit, protoze takto se dal delat rezim 160x200x16 barev (jenze se to muzelo porad ladit) a znovu = malokdo mel kompozitni monitor
Kompozitní výstup (jas+sync) s NTSC časováním jsem používal s černobílým monitorem. Že by v tom byla schovaná i barva nebylo nikde poznat, color subcarrier jde vidět jako šum.
na cernobilem by to melo byt videt jako normalni mod 640x200. Pokud to tedy nebude trosku "rozmazle", protoze nektere monitory tu pixel frekvenci uplne nestihaly.
Ja CGA moc nezazil vyjma nejakych prumyslovych XT co mel tata v praci.
Spis jsem si hral s herculesem ( ten byl na tech xt teda hodne) a pak uz vyrobci levnych PC/XT davali EGA nebo nejakou velmi zakladni VGA. Desky musely byt nastavene propojkami aby se obesla inicializace CGA/MDA. Novejsi XTcka mela uz nejaky ten graficky setup biosu a XT desky byla spis odrbana ATcka urcena na psani a kancl veci. U klonu uz ani nebyval socket na koprocesor.
11. 7. 2024, 14:48 editováno autorem komentáře
CGA ale bola v ČSSR vcelku relevantná aj z pohľadu tunajších klonov (PP06, TNS HC-16), kde bola práve tá pajcnutá.
Jeden z faktorov mohla byť aj dostupnosť vhodných monitorov v rámci RVHP, MDA/Hercules sú na kvalitu monitora náročnejšie (rozlíšenie, hsync f.).
Já byl hrdým majitelem PP06, vybaveného EGA kartou a patřičným monitorem LogoSTAR.
Ten monitor se vyznačoval tím, že ve vysokofrekvenční části byl zesilovací tranzistor, který se přehříval tak, že se roztavil cín, který ho pojil k desce, a když odkápl, za mohutného záblesku tranzistor odešel do křemíkového nebe. Když se mi to stalo, šikovný kamarád sehnal ve škole 14 vadných stejných monitorů: 13 mělo stejnou závadu, poslední někomu spadl ze stolu, takže tranzistor byl v pořádku. Při nahrazování ho nejen pořádně připájel, ale vybavil chladičem a pro jistotu k té desce i přinýtoval! ;o)
Pak to fungovalo dalších několik let...
docela dlouho se pouzivaly takove "lepsi CGA" karty, ktere umely rozliseni 640x400 (monochrom) a hlavne mely hezci textove rezimy prave se 400 radky (a ne tech hroznych 200). Na 100% to pouzivaly pocitace Olivetti, ktere byvaly levne a prodavaly se u nas jeste v devadesatkach. Takze to byla +- klasicka CGA (bez snezeni), ale mela herci textovy rezim a ten novy graficky.
Mimochodem, pokud si pamatuju (a asi si to pamatuju dobre), tento rezim umel i T602, coz zase znamenalo, ze ty Olivetti byvaly rozlezle v kaclech docela dlouho.
jinak doplnění k obrázku na https://www.root.cz/clanky/hratky-s-barvovou-paletou-a-vykresleni-jednotlivych-pixelu-kartou-cga/#k16 (a dalšímu): to, že je na náhledu vidět šedá, dělá jen algoritmus zmenšení obrázku. takže to vypadá mnohem lépe, než na originál CGAčku :-) Stačí kliknout pro zvětšenou verzi.
trochu z jineho soudku;
p. Tisnovsky, rad sleduji vase clanky, ale obrazek pro dnesni dil mne emocne velmi potesil.
zaroven, s problematikou probiranou v tomto serialu obeznamen(z mladi) jsem, ale, celkove vzato, je to super retro poctenicko.
za sebe, moc moc dekuji. preji silu a zdravi
11. 7. 2024, 10:16 editováno autorem komentáře
Proc se ten serial kam ten clanek spada jmenuje Seriál: Unixové vykopávky? Ja vim ze trochu rypu, mozna by ale stacilo jen Pocitacove vykopavky, nebo tak neco...
Tyjo...
Otevřu Roota, a zírá na mě uvítací obrazovka z Golden Axe. Sice ji znám spíš v nějaké EGA podobě, ale závan nostalgie se nepochybně dostavil...
Jenom ze zvědavosti nahlédnu, jasně pan Tišnovský, ale stejně to bude spíš nějaká suchá archeologie... whoa! Assembler! A v lidské notaci, jmenovitě nasm, příležitostně můj oblíbený!
Kdo dneska ještě píše články, s netriviálními příklady v Assembleru?
Respect :-) a klobouček!
naivni implementace vykresleni obrazku v GWBASICu:
10 CLS
20 SCREEN 1
30 OPEN "R",#1,"IMAGE.BIN",1
40 FIELD #1,1 AS C$
50 DEF SEG=&HB800
60 P=0
70 FOR J=0 TO 99
80 O=0
90 FOR K=0 TO 1
100 T=P+O
110 FOR I=0 TO 79
120 GET #1
130 POKE T,ASC(C$)
140 T=T+1
150 NEXT I
160 O=8192
170 NEXT K
180 P=P+80
190 NEXT J
200 CLOSE #1
pekne, stare dobre POKE
(jinak je zvlastni, ze je to nakonec na radky radove stejne dlouhe, jako ten assembler ;)
Tak ono na tom není asi moc co vymýšlet, spíše je veselé, že ten assembler je, alespoň pro mě, srozumitelnější, než ten neodsazený, ořádkovaný BASIC.
Bol som zvedavý, jednak ako bude mať tá ručne vyčačkaná ASM frame copy implementácia vo vzťahu k naivným C-čkovým a dvak, ako to pobeži na reálnom hw.:
https://pastebin.com/6fu6Bi7D
Prekladal som to prekladačom z TC++ 3.0 v DOSBoxe, pre porovnanie je tam inlajnutá aj tá Pavlova implementácia.
Na najstaršom funkčnom PC čo mám momentálne po ruke (Amstrad PPC 640, NEC V30 @ 8Mhz, 1987) to vyzerá takto:
C assign b far: 3.4 fps, 0.2 Mpxps C assign w far: 5.2 fps, 0.3 Mpxps C assign l far: 5.7 fps, 0.4 Mpxps C assign w near: 5.5 fps, 0.3 Mpxps C assign l near: 6.4 fps, 0.4 Mpxps C fmemcpy: 19.2 fps, 1.2 Mpxps ASM movsw: 22.3 fps, 1.4 Mpxps
(fmemcpy je interne implementovaná tiež pomocou rep movsw
, len teda šaškovanie so zásobníkom pri jej volaní zožerie nejaké cykly na každý riadok)
V30 je upgradnutá 8086, ak by to niekto chcel testnúť na niečom ešte bližšom pôvodnému XT s 8088 @ 4,77MHz, môžem posunúť binárku.
Díky za doplnění!
Jak vlastně vypadá výstup v assembleru z toho TC++? Podle benchmarků to nebude nic moc (to mě překvapuje popravdě). Nepomůžou nějaký triky typu modifikátor "registry", přepis smyček tak, aby se explicitně pracovalo přes pointry (a ne jakoby šlo o pole) atd.?
(je asi blbé, že se ptám. TC jsem hodně používal, učil jsem se na tom céčko, ale už ho nemám)
divoko, vútorné x-ové slučky vyzerajú takto:
frame_copy_movb()
0000351D 8B1EB006 mov bx,[0x6b0] 00003521 8A00 mov al,[bx+si] 00003523 C41EAB00 les bx,[0xab] 00003527 268801 mov [es:bx+di],al 0000352A 46 inc si 0000352B 47 inc di 0000352C FE46FF inc byte [bp-0x1] 0000352F 807EFF50 cmp byte [bp-0x1],0x50 00003533 72E8 jc 0x351d
frame_copy_movw_near()
0000367D 8BC6 mov ax,si 0000367F D1E0 shl ax,1 00003681 8B1EB006 mov bx,[0x6b0] 00003685 03D8 add bx,ax 00003687 8B07 mov ax,[bx] 00003689 8BD7 mov dx,di 0000368B D1E2 shl dx,1 0000368D 8B1EAB00 mov bx,[0xab] 00003691 03DA add bx,dx 00003693 268907 mov [es:bx],ax 00003696 46 inc si 00003697 47 inc di 00003698 FE46FF inc byte [bp-0x1] 0000369B 807EFF28 cmp byte [bp-0x1],0x28 0000369F 72DC jc 0x367d
frame_copy_movl_near() je už úplná divočina s 25 inštr. a plejádou push/pop v každej it. (aj tak je ale o chlp rýchlejší než ten movw, keďže presunie 32b na it.)
a hej, keď sa array indexovanie nahradí čisto ptr aritmetikou:
void frame_copy_movw_near_ptr() { unsigned char x, y, b; unsigned int _es *screen_p; unsigned int *buf_p; _ES = FP_SEG(screen); for (b = 0; b < SCR_BANKS; b++) { screen_p = &screen[b * SCR_BANK_OFFSET]; buf_p = &buf[b * SCR_LINE_OFFSET]; for (y = 0; y < SCR_H / SCR_BANKS; y++) { for (x = 0; x < SCR_LINE_OFFSET / 2; x++) { *screen_p++ = *buf_p++; } buf_p += SCR_LINE_OFFSET / 2; // skip even/odd line of src } } }
vedie to k relatívne decentnému výsledku:
000036FC 8B04 mov ax,[si] 000036FE 268905 mov [es:di],ax 00003701 83C602 add si,byte +0x2 00003704 83C702 add di,byte +0x2 00003707 FE46FF inc byte [bp-0x1] 0000370A 807EFF28 cmp byte [bp-0x1],0x28 0000370E 72EC jc 0x36fc
škoda akurát tej loop premennej v stack frame namiesto registra a add si/di, 8b neviem či je optimálnejšie než 2x inc
Nie som teraz pri tom Amstrade, no v DOSBoxe je toto zhruba 1,7-krát efektívnejšie než najrýchlejší z tých array index prístupov.
pre tú kritickú loop premennú sa dá vynútiť register explicitne:
for (_CL = SCR_LINE_OFFSET / 2; _CL > 0; _CL--) { *screen_p++ = *buf_p++; }
potom je to:
000036FA 8B04 mov ax,[si] 000036FC 268905 mov [es:di],ax 000036FF 83C602 add si,byte +0x2 00003702 83C702 add di,byte +0x2 00003705 FEC9 dec cl 00003707 0AC9 or cl,cl 00003709 77EF ja 0x36fa
a aj toho OR CL, CL testu by sa asi dalo zbaviť prepisom na while{} alebo do{}while. Tu robí hneď na úvod JMP na ten OR test, aby otestoval, či náhodou už úvodné SCR_LINE_OFFSET / 2 nie je rovné 0 (hoci je to v tomto prípade nenulová konštanta). To už potom ale človek ohýba to C-čko takmer na assembler... :D