;------------------ ;Ara video digitizer, disassembled May 2010 by nocash ;------------------ 0040 ;defs 7D0h*200 ;collapsed VRAM copy (via COPY key) 4000 ;defs 4000h ;second VRAM block 8000 ;code: entryoint (re-used as xlat_buf after initialization) 8100 ;code: "resident" code region (not destroyed by xlat_buf) 4000 ;defs C000h ;first VRAM block ;------------------ .align 100h xlat_buf: 8000 defs 100h ;VRAM xlat for mode 0/1 (init via x8AE8) ;--- xlat_mode0: ;translate 256 incoming values to 64 other values ;each byte contains 2 pixels with 3bit color depth each ;--- ;(ie. while the CPC supports 4bit color depth, ;the digitizer does supply only 3bit color depth) ;this could have TWO different reasons: ; 1) maybe the digitize hardware supports only 3bit, ; 2) the CPC's 27-color palette barely supports more ; than 8 suitable colors, so digitizer might support ; 16 grayscale levels, but the software supports only 8. ;--- ; ara digitizer cpc vram actual meaning ; bit0 bit4 bit2 (MSB) of pixel1 (right-most) ; bit1 bit7 bit0 (LSB) of pixel0 (left-most) ; bit2 bit6 bit0 (LSB) of pixel1 (right-most) ; bit3 N/A N/A (not used by ARA.BIN software) ; bit4 bit2 bit1 (MID) of pixel1 (right-most) ; bit5 N/A N/A (not used by ARA.BIN software) ; bit6 bit3 bit1 (MID) of pixel0 (left-most) ; bit7 bit5 bit2 (MSB) of pixel0 (left-most) ;--- 8000 00 10 80 90 db 00,10,80,90,40,50,C0,D0 8008 00 10 80 90 db 00,10,80,90,40,50,C0,D0 8010 04 14 84 94 db 04,14,84,94,44,54,C4,D4 8018 04 14 84 94 db 04,14,84,94,44,54,C4,D4 8020 00 10 80 90 db 00,10,80,90,40,50,C0,D0 8028 00 10 80 90 db 00,10,80,90,40,50,C0,D0 8030 04 14 84 94 db 04,14,84,94,44,54,C4,D4 8038 04 14 84 94 db 04,14,84,94,44,54,C4,D4 8040 08 18 88 98 db 08,18,88,98,48,58,C8,D8 8048 08 18 88 98 db 08,18,88,98,48,58,C8,D8 8050 0C 1C 8C 9C db 0C,1C,8C,9C,4C,5C,CC,DC 8058 0C 1C 8C 9C db 0C,1C,8C,9C,4C,5C,CC,DC 8060 08 18 88 98 db 08,18,88,98,48,58,C8,D8 8068 08 18 88 98 db 08,18,88,98,48,58,C8,D8 8070 0C 1C 8C 9C db 0C,1C,8C,9C,4C,5C,CC,DC 8078 0C 1C 8C 9C db 0C,1C,8C,9C,4C,5C,CC,DC 8080 20 30 A0 B0 db 20,30,A0,B0,60,70,E0,F0 8088 20 30 A0 B0 db 20,30,A0,B0,60,70,E0,F0 8090 24 34 A4 B4 db 24,34,A4,B4,64,74,E4,F4 8098 24 34 A4 B4 db 24,34,A4,B4,64,74,E4,F4 80A0 20 30 A0 B0 db 20,30,A0,B0,60,70,E0,F0 80A8 20 30 A0 B0 db 20,30,A0,B0,60,70,E0,F0 80B0 24 34 A4 B4 db 24,34,A4,B4,64,74,E4,F4 80B8 24 34 A4 B4 db 24,34,A4,B4,64,74,E4,F4 80C0 28 38 A8 B8 db 28,38,A8,B8,68,78,E8,F8 80C8 28 38 A8 B8 db 28,38,A8,B8,68,78,E8,F8 80D0 2C 3C AC BC db 2C,3C,AC,BC,6C,7C,EC,FC 80D8 2C 3C AC BC db 2C,3C,AC,BC,6C,7C,EC,FC 80E0 28 38 A8 B8 db 28,38,A8,B8,68,78,E8,F8 80E8 28 38 A8 B8 db 28,38,A8,B8,68,78,E8,F8 80F0 2C 3C AC BC db 2C,3C,AC,BC,6C,7C,EC,FC 80F8 2C 3C AC BC db 2C,3C,AC,BC,6C,7C,EC,FC ;--- xlat_mode1: ;translate 256 incoming values to 256 other values ;each byte contains 4 pixels with 2bit color depth each ;--- ; ara digitizer cpc vram actual meaning ; bit0 bit6 bit0 (LSB) of pixel1 (middle-left) ; bit1 bit0 bit1 (MSB) of pixel3 (right-most) ; bit2 bit4 bit0 (LSB) of pixel3 (right-most) ; bit3 bit7 bit0 (LSB) of pixel0 (left-most) ; bit4 bit5 bit0 (LSB) of pixel2 (middle-right) ; bit5 bit3 bit1 (MSB) of pixel0 (left-most) ; bit6 bit1 bit1 (MSB) of pixel2 (middle-right) ; bit7 bit2 bit1 (MSB) of pixel1 (middle-left) ;--- 8000 00 40 01 41 db 00,40,01,41,10,50,11,51 8008 80 C0 81 C1 db 80,C0,81,C1,90,D0,91,D1 8010 20 60 21 61 db 20,60,21,61,30,70,31,71 8018 A0 E0 A1 E1 db A0,E0,A1,E1,B0,F0,B1,F1 8020 08 48 09 49 db 08,48,09,49,18,58,19,59 8028 88 C8 89 C9 db 88,C8,89,C9,98,D8,99,D9 8030 28 68 29 69 db 28,68,29,69,38,78,39,79 8038 A8 E8 A9 E9 db A8,E8,A9,E9,B8,F8,B9,F9 8040 02 42 03 43 db 02,42,03,43,12,52,13,53 8048 82 C2 83 C3 db 82,C2,83,C3,92,D2,93,D3 8050 22 62 23 63 db 22,62,23,63,32,72,33,73 8058 A2 E2 A3 E3 db A2,E2,A3,E3,B2,F2,B3,F3 8060 0A 4A 0B 4B db 0A,4A,0B,4B,1A,5A,1B,5B 8068 8A CA 8B CB db 8A,CA,8B,CB,9A,DA,9B,DB 8070 2A 6A 2B 6B db 2A,6A,2B,6B,3A,7A,3B,7B 8078 AA EA AB EB db AA,EA,AB,EB,BA,FA,BB,FB 8080 04 44 05 45 db 04,44,05,45,14,54,15,55 8088 84 C4 85 C5 db 84,C4,85,C5,94,D4,95,D5 8090 24 64 25 65 db 24,64,25,65,34,74,35,75 8098 A4 E4 A5 E5 db A4,E4,A5,E5,B4,F4,B5,F5 80A0 0C 4C 0D 4D db 0C,4C,0D,4D,1C,5C,1D,5D 80A8 8C CC 8D CD db 8C,CC,8D,CD,9C,DC,9D,DD 80B0 2C 6C 2D 6D db 2C,6C,2D,6D,3C,7C,3D,7D 80B8 AC EC AD ED db AC,EC,AD,ED,BC,FC,BD,FD 80C0 06 46 07 47 db 06,46,07,47,16,56,17,57 80C8 86 C6 87 C7 db 86,C6,87,C7,96,D6,97,D7 80D0 26 66 27 67 db 26,66,27,67,36,76,37,77 80D8 A6 E6 A7 E7 db A6,E6,A7,E7,B6,F6,B7,F7 80E0 0E 4E 0F 4F db 0E,4E,0F,4F,1E,5E,1F,5F 80E8 8E CE 8F CF db 8E,CE,8F,CF,9E,DE,9F,DF 80F0 2E 6E 2F 6F db 2E,6E,2F,6F,3E,7E,3F,7F 80F8 AE EE AF EF db AE,EE,AF,EF,BE,FE,BF,FF ;------------------ 8100 ... ;------------------ key_list: 95C0 31 32 33 34 db '123456789' ;-Brightness (1=lower, 9=higher) db 'SDFGHJKL' ;-Dithering (S=lower=no dithering, L=higher) db 'ERTY' ;-Contrast (E=lower,Y=higher) db '@' ;-at (toggle video mode) 95D6 F0 F1 F2 F3 db F0,F1,F2,F3 ;-cursor UP,DN,LT,RT (vhold small/big steps) key_list_end: ;------------------ 95DA ... ;------------------ digitize_function: ;in: ix = A4C0h (=data pool) ;to get here, press "D" (=digitize) in the screen saying ;ENTREE : DIGITIZE ;(entree is french-cuisine-slang for "begin with", ;namely, it does NOT mean to press ENTER) ;--- mainloop: ;- - - - - - ------ ; PART 1 - Keyboard controls in digitize function... ;- - - - - - ------ @@keylop: 99C8 CD 19 BD call mc_wait_flyback ;\ 99CB CD 1B BB call km_read_key ; wait for keystroke 99CE 38 09 jr c,@@key_down ;/ 99D0 DD CB 39 46 bit 0,[ix+39h] ;\animated auto-scan 99D4 C2 6A 9A jp nz,@@start_scan ;/ 99D7 18 EF jr @@keylop ;--- @@key_down: 99D9 FE E0 cmp a,0E0h ;COPY ;\key COPY... 99DB 20 05 jr nz,@@not_copy ; copy VRAM at C000h or 4000h (MOD) 99DD CD 00 91 call x9100 ;copy VRAM to buf ; to buffer at 0040h 99E0 18 E6 jr @@keylop ; and collapse scanline ;--- ; size from 800h to 7D0h @@not_copy: ;/ 99E2 FE 0D cmp a,0Dh ;ENTER ;\key ENTER... 99E4 CA 33 8A jp z,x8A33 ;------> ;/exit (back to main menu) 99E7 FE 5E cmp a,5Eh ;"^" ;\ 99E9 20 07 jr nz,@@not_accent ; 99EB DD 36 39 01 ld [ix+39h],01h ; key ^ 99EF C3 6A 9A jp @@start_scan ; enable animated ;--- ; video auto-scan @@not_accent: ;/ 99F2 FE 20 cmp a,20h ;SPACE ;\ 99F4 20 15 jr nz,@@not_space ; 99F6 DD CB 39 46 bit 0,[ix+39h] ; 99FA 28 6E jr z,@@start_scan ; 99FC DD 77 39 ld [ix+39h],a ;=20h ;bit0=0 ; key SPACE @@flush_space_lop: ; disable animated 99FF CD 1B BB call km_read_key ; video auto-scan 9A02 3E 2F ld a,2Fh ;row5,bit7 = SPACE ; 9A04 CD 1E BB call km_test_key ; 9A07 20 F6 jr nz,@@flush_space_lop ; 9A09 18 BD jr @@keylop ; ;--- ; @@not_space: ;/ 9A0B FE 55 cmp a,55h ;"U" ;\ 9A0D 20 05 jr nz,@@not_u ; key U (undo) 9A0F CD 20 9B call swap_vram_buffers ; swap from buffers, 9A12 18 B4 jr @@keylop ; without scanning, ;--- ; ie. "undo" last scan @@not_u: ;/ 9A14 06 1A ld b,1Ah ;\ 9A16 21 D9 95 ld hl,key_list_end-1 ; @@key_table_lop: ; 9A19 BE cmp a,[hl] ; further keys.... 9A1A 2B dec hl ; 9A1B 28 04 jr z,@@key_found ; 9A1D 10 FA djnz @@key_table_lop ; 9A1F 18 A7 jr @@keylop ; ;--- ; @@key_found: ;/ 9A21 78 ld a,b ;\ 9A22 3D dec a ;01h..1Ah --> 00h..19h ; 9A23 FE 09 cmp a,09h ; 9A25 30 06 jr nc,@@not_123456789 ; keys 1,2,3,4,5,6,7,8,9 9A27 3C inc a ;00h..08h --> 01h..09h ; Brightness (1=lower, 9=higher) 9A28 DD 77 35 ld [ix+35h],a ; 9A2B 18 3D jr @@start_scan ; ;--- ; @@not_123456789: ;in: A=09h..19h ;/ 9A2D FE 11 cmp a,11h ;\ 9A2F 30 07 jr nc,@@not_SDFGHJKL ; 9A31 D6 09 sub a,09h ;09h..10h --> 00h..07h; keys S,D,F,G,H,J,K,L 9A33 DD 77 37 ld [ix+37h],a ; Dithering (S=lower=no dithering, L=higher) 9A36 18 32 jr @@start_scan ; ;--- ; @@not_SDFGHJKL: ;in: A=11h..19h ;/ 9A38 D6 15 sub a,15h ;11h..19h --> -4..+4 ;\ 9A3A 30 07 jr nc,@@not_ERTY ; 9A3C C6 04 add a,04h ;-4..-1 --> 00h..03h ; keys E,R,T,Y 9A3E DD 77 36 ld [ix+36h],a ; Contrast (E=lower,Y=higher) 9A41 18 27 jr @@start_scan ; ;--- ; @@not_ERTY: ;A=0..4, ZF ;/ 9A43 20 0D jr nz,@@not_at ;\ 9A45 DD 7E 34 ld a,[ix+34h] ;vmode ; key @... 9A48 EE 01 xor a,01h ;ZF ; toggle video mode 9A4A DD 77 34 ld [ix+34h],a ;vmode ;ZF ; and rebuild 9A4D CD E8 8A call x8AE8 ;new_xlat_buf ;in: ZF ; VRAM xlat_buf 9A50 18 18 jr @@start_scan ; ;--- ; @@not_at: ;in: A=1..4 ;/ 9A52 E6 03 and a,03h ;1,2,3,4 --> 1,2,3,0 ;\ 9A54 0F rora ;\ ; cursor keys 9A55 0F rora ; --> 20h,40h,60h,00h; keys UP,DN,LT,RT 9A56 0F rora ;/ ; vertical time (vhold) 9A57 D6 30 sub a,30h ; --> F0h,10h,30h,D0h; 9A59 06 40 ld b,40h ;min ; DN/UP = small +/- 10h 9A5B DD 86 38 add a,[ix+38h] ;delay count ; LT/RT = big +/- 30h 9A5E B8 cmp a,b ; 9A5F 38 05 jr c,@@do_clip ; 9A61 06 C0 ld b,0C0h ;max ; 9A63 B8 cmp a,b ; 9A64 38 01 jr c,@@dont_clip ; @@do_clip: ; 9A66 78 ld a,b ;clip to min/max ; @@dont_clip: ; 9A67 DD 77 38 ld [ix+38h],a ;delay count ;/ @@start_scan: ;- - - - - - ------ ; PART 2 - The actual hardware-wise digitize function... ;- - - - - - ------ 9A6A F3 di 9A6B 01 F5 F9 ld bc,F9F5h ;\reset 10bit config to zero 9A6E ED 79 out [bc],a ;[F9F5h] ;/ 9A70 DD 7E 34 ld a,[ix+34h] ;bit0=vmode 9A73 0F rora ;bit7=vmode 9A74 0F rora ;bit6=vmode 9A75 EE 40 xor a,40h ;bit6=not vmode 9A77 5F ld e,a ;bit6=not vmode 9A78 DD 66 37 ld h,[ix+37h] ;bit8-15=SDFGHJKL (dither) 9A7B DD 7E 36 ld a,[ix+36h] ;bit0-1=ERTY (contrast) 9A7E 57 ld d,a ;bit0-1=ERTY 9A7F EE 03 xor a,03h ;bit0-1=not ERTY ;\ 9A81 07 rola ;bit1-2=not ERTY ; Brightness 9A82 DD 86 35 add a,[ix+35h] ;123456789 ; bit2-5 = not 123456789 9A85 3D dec a ;123456789-1 ; also adjusted 9A86 07 rola ; by/for ERTY (contrast) 9A87 07 rola ; 9A88 EE 3C xor a,3Ch ;/ 9A8A B2 or a,d ;-bit0-1 = ERTY (contrast) 9A8B B3 or a,e ;-bit6 = not vmode 9A8C 07 rola ;\ 9A8D CB 3C shr h ; bit7-9 = SDFGHJKL (dither) 9A8F 1F rcra ;/ 9A90 6F ld l,a ;the 10bit config value in HL is: ; 0-1 Contrast ; 2-5 Brightness ; 6 Mode (0=320x200x4, 1=160x200x16) ; 7-9 Dither 9A91 04 inc b ;b=FAh ;\ @@config_lop: ; 9A92 ED 79 out [bc],a ;[FAF5h] ; output 10bit config 9A94 2B dec hl ; (write HL times to 9A95 7D ld a,l ; use setting HL) 9A96 B4 or a,h ; 9A97 20 F9 jr nz,@@config_lop ;/ 9A99 06 F8 ld b,0F8h ;\ @@vsync_redo: ; @@vsync_lop1: ;\ ; wait for vsync 9A9B ED 78 in a,[bc] ;[F8F5h] ; ; (long sync pulse) 9A9D 0F rora ; ; 9A9E 38 FB jr c,@@vsync_lop1 ;/ ; 9AA0 1E 00 ld e,00h ;count ;\ ; @@vsync_lop2: ; ; 9AA2 ED 78 in a,[bc] ;[F8F5h] ; ; 9AA4 1C inc e ;count ; ; 9AA5 0F rora ; ; 9AA6 30 FA jr nc,@@vsync_lop2 ;/ ; 9AA8 7B ld a,e ;count ;\ ; 9AA9 FE 0C cmp a,0Ch ;short=hsync; ; 9AAB 38 EE jr c,@@vsync_redo ;/ ;/ 9AAD DD 46 38 ld b,[ix+38h] ;delay count ;\ @@vhold_lop: ; 9AB0 E3 ex [sp],hl ;19+1+4 ;24 ; delay with variable 9AB1 E3 ex [sp],hl ;19+1+4 ;24 ; parameter [ix+38h] 9AB2 E3 ex [sp],hl ;19+1+4 ;24 ; (vhold) 9AB3 E3 ex [sp],hl ;19+1+4 ;24 ; vertical picture pos 9AB4 29 add hl,hl ;11+1 ;12 ; 9AB5 10 F9 djnz @@vhold_lop ;13+3 ;16 ;/ ;above seems to be intended as 100 clocks per loop cycle, ;ie. the programmer being unaware of CPC/Z80 waitstates, ;which result in actual time of 124 clocks per loop cycle ;(anyways the incoming "vhold" value is choosen so that ;it works despite of that mistake) 9AB7 06 F8 ld b,0F8h ;\ @@hsync_lop1: ;\ ; 9AB9 ED 78 in a,[bc] ;[F8F5h] ; ; wait for hsync 9ABB 0F rora ; ; 9ABC 30 FB jr nc,@@hsync_lop1 ;/ ; @@hsync_lop2: ;\ ; 9ABE ED 78 in a,[bc] ;[F8F5h] ; ; 9AC0 0F rora ; ; 9AC1 38 FB jr c,@@hsync_lop2 ;/ ;/ 9AC3 06 FB ld b,0FBh ;\invoke capture 9AC5 ED 79 out [bc],a ;[FBF5h] ;/ 9AC7 21 00 0A ld hl,0A00h ;=2560 decimal ;\ @@wait_capture_lop: ; 9ACA 2B dec hl ;6+2 ;8 ; hardcoded delay (71680 clks) 9ACB 7C ld a,h ;4 ;4 ; (capture duration) 9ACC B5 or a,l ;4 ;4 ; 9ACD 20 FB jr nz,@@wait_capture_lop ;12 ;/ ;above was probably done thinking that DEC HL takes ;only 6 clks (ie. without the waitstates), and the ;programmer seems to have had a full 312-lines frame ;in mind, although the scanning should take only ;around 200 lines (maybe a bit more if the WHOLE ;16384 bytes are used, not just 16000 bytes), either ;way, the above 71680 delay is probably a good bit ;longer than required (around 44000 might be enough) ;- - - - - - ------ 9ACF 21 00 B8 ld hl,0C000h-800h ;dest-800h ;\ 9AD2 D9 exx ; 9AD3 C5 push bc ;push BC' ; init registers 9AD4 01 F5 FA ld bc,0FAF5h ;BC'=port_addr ; for main data 9AD7 16 80 ld d,xlat_buf/100h ;D'=msb ; transfer 9AD9 D9 exx ; 9ADA E5 push hl ;\ iy=hl = dest-800h ; 9ADB FD E1 pop iy ;/ ;/ 9ADD 1E 19 ld e,19h ;charline count ;\ @@ylop: ; 9ADF 16 08 ld d,08h ;scanline count ; @@yylop: ; scanline/charline 9AE1 FD E5 push iy ;\ hl=iy ;\ ; loop start... 9AE3 E1 pop hl ;/ ; ; 9AE4 7C ld a,h ;dest+800h... ; ; 9AE5 C6 08 add a,0800h/100h ; ; 9AE7 CB F7 set 6,a ;\ force staying in ; ; 9AE9 CB FF set 7,a ;/ same 16K bank ; ; <--- MOD 9AEB 67 ld h,a ; ; 9AEC E5 push hl ;\ iy=hl ; ; 9AED FD E1 pop iy ;/ ;/ ;/ 9AEF 06 50 ld b,50h ;\ @@xlop: ; 9AF1 D9 exx ; read and xlat 9AF2 ED 58 in e,[bc] ;e=[FAF5h] ; one scanline 9AF4 1A ld a,[de] ;a=[xlat_buf+[FAF5h]]; 9AF5 D9 exx ; 9AF6 77 ld [hl],a ;[dest]=a ; 9AF7 23 inc hl ;dest=dest+1 ; 9AF8 10 F7 djnz @@xlop ;/ 9AFA 15 dec d ;scanline count ;\ 9AFB 20 E4 jr nz,@@yylop ; 9AFD E5 push hl ;\ iy=hl=dest+50h ; loop next 9AFE FD E1 pop iy ;/ ; scanlines & charlines 9B00 1D dec e ;charline count ; 9B01 20 DC jr nz,@@ylop ;/ ;- - - - - - ------ 9B03 D9 exx ;\ 9B04 C1 pop bc ;pop BC' ; 9B05 D9 exx ;/ 9B06 FB ei 9B07 DD 7E 34 ld a,[ix+34h] ;vmode ;\ 9B0A 32 FC 9E ld [9EFC],a ; 9B0D DD 77 2C ld [ix+2Ch],a ;/ 9B10 DD E5 push ix 9B12 CD 00 9C call x9C00 ;do some excessive stuff... 9B15 DD E1 pop ix 9B17 CD 19 BD call mc_wait_flyback 9B1A CD 20 9B call swap_vram_buffers 9B1D C3 C8 99 jp mainloop ;------------------ swap_vram_buffers: 9B20 CD C4 9E call scr_base_c000h <---- MOD ;calls scr_set_base with A=40h or C0h 9B23 3A EA 9A ld a,[9AEA] ;\ 9B26 EE 40 xor a,40h ;\ ; 9B28 32 EA 9A ld [9AEA],a ; ;/ 9B2B E6 40 and a,40 ; ;\ 9B2D 07 rola ;/ ; modify VRAM src addr in 9B2E EE C0 xor a,C0h ; x9100 function 9B30 32 02 91 ld [x9100+2],a ;/ 9B33 3A 21 9B ld a,[9B20+1] ;\modify the above 9B36 EE 0E xor a,(scr_base_4000h XOR scr_base_c000h) ; call scr_base_xxx 9B38 32 21 9B ld [9B20+1],a ;/ 9B3B C9 ret ;------------------ ... ;------------------ scr_base_c000h: 9EC4 3E C0 ld a,0C0h 9EC6 CD 08 BC call scr_set_base 9EC9 C9 ret ;------------------ scr_base_4000h: 9ECA 3E 40 ld a,40h 9ECC CD 08 BC call scr_set_base 9ECF C9 ret ;------------------