ZXNet эхоконференция «hardware.zx»


тема: ОЗУ с адреса #0000



от: Valerij Kozhevnikoff
кому: All
дата: 14 Sep 2002
Здравствуй, All! Как в доработанных Пентагонах компах сделано сабж? Только кеш через #FB и все? Есть какие-то варианты? А ВГ на прямой доступ ка включают? Копаясь в доках нашел вот такое, оно у многих есть? ······------====== Стеклорез мониторный ======------······ Порт #EFF7. bit 0 - pежим экpана 256*192, байт цвета на байт точек. В #6000-#77FF лежат атpубуты, они стандаpтные, за исключением битов 6 и 7. Тут это paper bright и ink bright соответственно. bit 1 - pежим экpана 512*192, ч/б. Hу это всем понятно. bit 2 - блокиpовка ОЗУ свыше 128К. Также этот бит управляет назначением бита 5 в #7ffd. 1 - ОЗУ свыше 128к заблокировано, бит 5 в #7ffd работает стандартной защелкой "48k only". 0 - доступна верхняя память, а бит 5 в #7ffd служит для управления памятью свыше 512к, иначе называемой "метр по-пентагоновски". bit 3 - включение TURBO. (планиpовалось, имхо ни у кого не pеализовано) Hекоторые юзали этот бит как "разрешение записи" в стат. ОЗУ, подключаемое битом 6. bit 4 - GIGASCREEN. Аппаратный интерлейс. Как известно, Спек имеет два экрана, и в каждом из них по 192 строки. Цикл работы интерлейса занимает два кадра. В первом на экран выводятся четные строки из нулевого экрана и нечетные из первого, во втором -- нечетные из нулевого и четные из первого. Эффект схож с тем, когда каждое прерывание переключают экран, но без явно выраженного мерцания. У мя есть, в Скорпе делается на одной ЛП5. Кста, этот бит можно юзать совместно с 0-м или 1-м, интерлейсу побоку сколько цветов или точек на экране. bit 5 - включение ПЗУ DOS и портов ВГ на прямой доступ из ОЗУ. _Это у многих сделано?_ bit 6 - блокиpовка ПЗУ и подключение дpугого, или 16k стат. ОЗУ. В 1998 году было так, в эти 16k статики люди заливали нужную версию доса и юзали ее. Потом кто-то предлагал переключать этим битом половинки Cache-32, хотя переключение этих половинок вроде уже тогда устаканили на #7ffd bit 4. Позднее этот бит заняли под графику 384х304 без бордюра. Видимо Cache RAM, включаемая вместо ПЗУ по IN #FB оказалась удобнее. bit 7 - включение доступа к часам. Имхо, нафиг не нужно прятать часы. ······------====== Стеклорез мониторный ======------······ WBR, Jason. /*e-mail: jason2000(собака страшная)yandex.ru ICQ: 62235830*/ /np:/ *silence*

от: Kirill Frolov
кому: Valerij Kozhevnikoff
дата: 17 Sep 2002
Hемедленно нажми на RESET, Valerij! 14 Sep 02 17:15, Valerij Kozhevnikoff wrote to All: VK> Как в доработанных Пентагонах компах сделано сабж? Каких пентагонах? VK> Только кеш через #FB и все? Вроде только так. VK> А ВГ на прямой доступ ка включают? Hикак. Или через кеш (jp #3dxx и тр-дос включен). VK> Копаясь в доках нашел вот такое, оно у многих есть? Тут много чего у всех отсутствует или сделано по-разному. VK> bit 1 - pежим экpана 512*192, ч/б. VK> Hу это всем понятно. VK> -------------------------------------------------------------- VK> bit 2 - блокиpовка ОЗУ свыше 128К. VK> Также этот бит управляет назначением бита 5 в #7ffd. VK> 1 - ОЗУ свыше 128к заблокировано, бит 5 в #7ffd работает VK> стандартной защелкой "48k only". VK> 0 - доступна верхняя память, а бит 5 в #7ffd служит для VK> управления памятью свыше 512к, иначе называемой "метр VK> по-пентагоновски". VK> -------------------------------------------------------------- VK> bit 4 - GIGASCREEN. VK> Аппаратный интерлейс. VK> Как известно, Спек имеет два экрана, и в каждом из них по 192 VK> строки. Цикл работы интерлейса занимает два кадра. В первом на VK> экран выводятся четные строки из нулевого экрана и нечетные из VK> первого, во втором -- нечетные из нулевого и четные из первого. VK> Эффект схож с тем, когда каждое прерывание переключают экран, но VK> без явно выраженного мерцания. VK> У мя есть, в Скорпе делается на одной ЛП5. VK> Кста, этот бит можно юзать совместно с 0-м или 1-м, интерлейсу VK> побоку сколько цветов или точек на экране. VK> -------------------------------------------------------------- VK> bit 7 - включение доступа к часам. Эти четыре более-менее присутствуют. VK> Имхо, нафиг не нужно прятать часы. Даже вредно. Запись в регистр #eff7 меняет содержимое других битов... VK> -------------------------------------------------------------- VK> bit 5 - включение ПЗУ DOS и портов ВГ на прямой доступ из ОЗУ. VK> _Это у многих сделано?_ Hет. Забей. Я вообще не понимаю зачем нужен прямой доступ на пентагоне. Для флопика желательно, но не обязательно, иметь в ПЗУ ТР-ДОС по адресу #3ff3 команды IN A,(C): RET. Драйвер флопика (баги есть): === Cut === *Include floppy.inc === Cut === ; mode mask and bits mmfm equ 01h ; 1=mfm (*) bmfm equ 0 mcside equ 02h ; 1=check side (*) bcside equ 1 mwrdel equ 04h ; 1=write delay (for slow drives) bwrdel equ 2 mauto equ 08h ; 1=auto disk change bauto equ 3 mrdonl equ 80h ; 1=readonly (*) -- used in betadisk module brdonl equ 7 ; IY+var -- drive variables drive equ 0 ; physical drive 0..3 sspeed equ 1 ; seek speed 0..3 dmode equ 2 ; mode bits track equ 3 ; track 0xff = undefined side equ 4 ; side 0=bottom, 1=top chflag equ 5 ; write protect status(call fdchange) changed equ 6 ; 1=disk changed reservx equ 7 ; reserved dpbsize equ 8 ; size of drive vars. ; error codes efdok equ 0 ; no errors efdfail equ 1 ; hardware failure efdwprot equ 2 ; write protect efdnosec equ 3 ; sector not found efdcrc equ 4 ; crc error efdtout equ 5 ; timeout === Cut === *Include betadisk.inc === Cut === ; IY=Drive Parameters Block pointer global fdreset ; reset controller global fdstop ; stop all drives global fdready ; check drive ready/not -> CF=0 if ready global fdindex ; return INDEX state -> CF=0 if active global fdchange ; -> CF=1 disk changed global fdpresent ; -> CF=1 drive not present global fdctl ; call it first for new drive! global fdside ; set side A?0:1 global fdtrack ; set heads to track A -> CF=1 on error global fdrdsec ; read sector A \n global fdwrsec ; write sector A | global fdrdadr ; read address mark > CF=1 on error, A=status bits global fdrdtrk ; read track | buffer=(HL++) global fdwrtrk ; write track / === Cut === rsttime equ 1000 ; controller io registers rgcmd equ 1fh ; write only -- command register rgstat equ 1fh ; read only -- status register rgtrk equ 3fh ; track register rgsec equ 5fh ; sector register rgdata equ 7fh ; data register rgctl equ 0ffh ; write only -- external controller register ; command modifiers cs0 equ 01h ; head moving speed bit 0 cJ0 equ 01h ; interrupt command modifier, see below ca0 equ 01h ; special sector mark, not used cs1 equ 02h ; head moving speed bit 1 cJ1 equ 02h cC equ 02h ; check side (for read/write commands) cV equ 04h ; read and verify head position (for seek, step and reset commands) cE equ 04h ; delay before reading/writing? cJ2 equ 04h ch equ 08h ; load head (for seek, step and reset commands) cS equ 08h ; disk side (for read/write commands, used only if cC=1) cJ3 equ 08h cI equ 10h ; modify or not rgtrk, used only for step commands cm equ 10h ; multisector operation (for read/write sector commands only) ; command interrupt bits ci_noi equ 0 ; stop command execution but don't interrupt host (INTRQ signal) ci_rdy equ cJ0 ; stop command execution when DRDY is active (drive ready) ci_off equ cJ1 ; stop command execution when DRDY is inactive (drive not ready) ci_idx equ cJ2 ; stop command execution when INDEX impulse detected ci_imm equ cJ3 ; stop command execution now and set INTRQ ; commands creset equ 00 ; reset controller, seek track 0 cseek equ 10 ; seek track in rgdata cstep equ 20 ; repeat last cfstep or cbstep cfstep equ 40 ; forward step (from track 0) cbstep equ 60 ; back step (to track 0) crdsec equ 80 ; read sector(s) cwrsec equ 0a0h ; write sector(s) crdadr equ 0c0h ; read address mark (6 bytes) crdtrk equ 0e0h ; read whole track with all address marks, etc... cwrtrk equ 0f0h ; write whole track (format track) cint equ 0d0h ; interrupt command execution ; status bits sbusy equ 01h ; 1=controller busy (command executed) sdrq equ 02h ; 1=data read/write requested sidx equ 02h ; 1=index impulse strk0 equ 04h ; 1=heads at track 0 sover equ 04h ; 1=data overrun scrc equ 08h ; 1=crc failed, sector corrupted sseek equ 10h ; 1=seek failed snosec equ 10h ; 1=sector not found shead equ 20h ; 1=head loaded serase equ 20h ; 1=special sector mark, not used swfail equ 20h ; 1=write failed swprot equ 40h ; 1=write protected disk sdrdy equ 80h ; 1=drive ready (really it's HEAD/MOTOR signal indicator) ; control register bits dd0 equ 01h ; drive number bit 0 dd1 equ 02h ; drive number bit 1 dreset equ 04h ; 0=reset controller ddrdy equ 08h ; 1=floppy drive ready (emulation of real DRDY signal) dside equ 10h ; 1=bottom size(0), 0=upper side(1) dmfm equ 20h ; 1=double density (MFM method), 0=single density (FM) for 8" floppy ; interrupt bits idrq equ 40h ; 1=active only if data read/write requested iintrq equ 80h ; 1=active after execution of all commands trentr equ 3d2fh ; tr-dos entry point troutc equ 2a53h ; out(c),a trintr equ 3fcah ; wait for intrq !set C to rgtrk, rgsec or rgdata only! trread equ 3fd5h ; reading routine address trwrite equ 3fbah ; writing routine address trstat equ 2470h ; read status trssv equ 5d04h ; word trsst equ 5ccdh ; byte trshl equ 5d02h ; word trsjp equ 5cc2h ; byte trsadr equ 5cc3h ; word ; get STATUS REGISTER in A fdstat: ld a, (trsjp) push af ld hl, (trsadr) push hl ld hl, (trssv) push hl ld a, (trsst) push af ld hl, trsjp ld (hl), 0c3h ; JP instruction ld hl, fdstret ld (trsadr), hl ld d, (iy+track) ld hl, trstat push hl ld hl, (trshl) jp trentr ; 2740: in a,(1fh) ; ld (5ccdh),a ; ld e,d ; push de ; ld a,e ; out (7fh),a ; ld a,18h ; call 3d9ah ; ; 3d9a: out (1fh),a ; push hl ; rst 20h ; dw 1f54h ; ; 0020: jp 2f72h ; ; 2f72: ld (5d02h),hl ; ld (5d04h),de ; pop hl ; ld e,(hl) ; inc hl ; ld d,(hl) ; inc hl ; push hl ; ld hl,3d2fh ; push hl ; push de ; ld hl,5cc2h ; push hl ; ld hl,(5d02h) ; ld de,(5d04h) ; ret fdstret: ; pop hl ; 1f54h ; pop hl ; 3d2fh ; pop hl ; rst 20h ... ; pop hl ; push hl ; pop hl ; call 3d9ah ... ; pop hl ; de ld hl, 12 add hl, sp ld sp, hl ; restore stack ld a, (trsst) ; e = rgstat ld e,a pop af ld (trsst), a pop hl ld (trssv), hl pop hl ld (trsadr), hl pop af ld (trsjp), a ld a, e ret ; write command A to COMMAND REGISTER fdcmd: ld c, rgcmd ; jp fdwreg ; write A to register C fdwreg: ld hl, troutc push hl jp trentr ; write command A to COMMAND REGISTER and wait INTRQ fdcserv: call fdcmd ld c, rgtrk ; jp fdwait ; wait for INTRQ !DANGER may never return! fdwait: ld hl, trintr push hl jp trentr ; jump to READ proc. hl=data fdjpread: ld c, rgdata push hl ld hl, trread ex (sp), hl jp trentr ; jump to WRITE proc. hl=data fdjpwrite: ld c, rgdata push hl ld hl, trwrite ex (sp), hl jp trentr ; reset controller fdreset: ld c, rgctl xor a call fdwreg ld bc, rsttime fdres1: dec bc ld a, b or c jr nz, fdres1 call fdctl call fdcserv call fdtrack0 xor a ret ; turn off motor fdstop: ld a, (iy+track) ld c, rgdata call fdwreg ld a, cseek ld c, rgcmd jp fdcserv ; set head to track 0 -> CF=1 on error fdtrack0: ld a, creset+ch or (iy+sspeed) ld c, rgcmd call fdcserv call fdstat ld (iy+track), 0 and strk0 ld a, 0 ret nz ; all ok scf ld (iy+track), 0ffh ; reset failed! ret ; set head to track A -> CF=1 on error fdtrack: or a jr z, fdtrack0 ld b, (iy+track) cp b ret z push af inc b jr nz, fdtrack_1 call fdtrack0 pop bc ret c push bc fdtrack_1: pop af ld b, (iy+track) ld (iy+track), a ld c, rgdata call fdwreg ld a, b ld c, rgtrk call fdwreg ld a, cseek+ch or (iy+sspeed) ld c, rgcmd call fdcserv xor a ret ; check if drive ready (HEAD/MOTOR is active?) and start it -> CF=0 if ready fdready: call fdstat and sdrdy ret nz scf ret ; return index state -> CF=0 - INDEX fdindex: call fdstat and sidx ret nz scf ret ; check if disk changed? CF=1 if changed fdchange: call fdstat push af and sdrdy jr nz, fdch1 call fdstop ; stop drive if it is inactive fdch1: pop af and swprot xor (iy+chflag) ret z xor (iy+chflag) ld (iy+chflag), a scf ret ; check if drive present? CF=1 drive not present fdpresent: call fdtrack0 ret c ld a, 1 call fdtrack call fdstat and strk0 ret z ; all ok, drive present ld (iy+track), 0ffh ; no drive! scf ret ; set side A fdside: and 01h ld (iy+side), a ; jp fdctl ; set control register(s) fdctl: ld a, (iy+drive) and dd0+dd1 ; hack... why? bit bmfm, (iy+dmode) jr z, fdctl1 or dmfm fdctl1: bit 0, (iy+side) jr nz, fdctl2 or dside fdctl2: or ddrdy+dreset ld c, rgctl call fdwreg ld a, (iy+track) ; 0xff... bug? ld c, rgtrk jp fdwreg ; read sector A from current track to (HL++) !DANGER: NO SECTOR SIZE CHECKING! ; return CF=1 if error, A=status bits fdrdsec: push hl ld c, rgsec call fdwreg bit bcside, (iy+dmode) ld a, crdsec jr z, frds1 or cC bit 0, (iy+side) jr z, frds1 or cS frds1: ld c, rgcmd call fdwreg pop hl call fdjpread jp z, fdtout ; timeout! call fdstat and sover+scrc+snosec ret z ; all ok jp fderror ; write sector A to current track from (HL++) !WARNING: NO SECTOR SIZE CHECKING! ; return CF=1 if error, A=error code fdwrsec: bit brdonl, (iy+dmode) jr z, fdwrs0 ld a, efdwprot scf ret fdwrs0: push hl ld c, rgsec call fdwreg bit bcside, (iy+dmode) ld a, crdsec jr z, fwrs1 or cC bit 0, (iy+side) jr z, fwrs1 or cS fwrs1: ld c, rgcmd call fdwreg pop hl call fdjpwrite jr z, fdtout ; timeout! call fdstat and sover+scrc+snosec+swfail+swprot ret z ; all ok jr fderror ; read address mark to (HL++) 6 bytes. ; return CF=1 if error, A=error code fdrdadr: push hl ld a, crdadr ld c, rgcmd call fdwreg pop hl call fdjpread jr z, fdtout ; timeout! call fdstat and sover+scrc ret z ; all ok jr fderror ; read track to (HL++) ~7kb max. ; return CF=1 if error, A=error code fdrdtrk: push hl ld a, crdtrk ld c, rgcmd call fdwreg pop hl call fdjpread jr z, fdtout ; timeout! call fdstat and sover ret z ; all ok jr fderror ; write track from (HL++) ~7kb max. ; return CF=1 if error, A=error code fdwrtrk: bit brdonl, (iy+dmode) jr z, fdwrt0 ld a, efdwprot scf ret fdwrt0: push hl ld a, cwrtrk ld c, rgcmd call fdwreg pop hl call fdjpwrite jr z, fdtout ; timeout! call fdstat and sover+swfail+swprot ret z ; all ok and 0ffh-swprot ld a, efdwprot scf ret z ; error A=status jr fderror ; read/write sector/track/addressmark error fderror: ld c, a and swprot ld a, efdwprot scf ret nz ld a, c and snosec ld a, efdnosec scf ret nz ld a, c and scrc ld a, efdcrc scf ret nz ld a, efdfail ret ; read/write sector/track/addressmark timeout fdtout: ld a, cint+ci_imm ; stop command execution call fdcmd ld a, creset or (iy+sspeed) ; stop drive, move heads to track 0 call fdcmd ld (iy+track), 0ffh ld a, efdtout ; return error status scf ret end === Cut === Кеш диска (баги есть): === Cut === global bdread ; bc=blockno, a=devno -> NO ERRORS! global bdwrite global sleeplocked ; store ix, bc, de global sleepnofree ; store bc, de global bread ; a=devno, bc=blockno -> hl=bufptr global bfree ; hl=bufptr, e=dirty flag global bufsync ; a=devno/0xff global bufinit ; hl=memptr, de=maxsize, bc=blocksize ; -> hl=unused memptr, bc=blocks in cache ; globals null equ 0 ; ----------------------- global routines ----------------------------------- ; create buffers cache ; HL=mem ptr, DE=max.size, BC=blocksize ; -> HL=unused mem ptr, BC=blocks bufinit: ld (bhash), hl ld (blocksize), bc ; blocks=(cashesize-hashsize)/(blocksize+bdscsize) ex de, hl ld de, hashsize*2 xor a sbc hl, de jr c, cr_nomem ld de, bdscsize cr_count: sbc hl, de jr c, cr_endmem1 sbc hl, bc jr c, cr_endmem2 inc a jr cr_count cr_nomem: ld bc, 0 scf ret cr_endmem2: add hl, bc cr_endmem1: add hl, de or a jr z, cr_nomem ld de, (bhash) add hl, de push hl ; ptr to free mem ld (cachesize), a ld l, a ld h, 0 push hl ; cache size ; clear hash table ex de, hl ld b, hashsize*2 xor a cr_hash: ld (hl), a inc hl djnz cr_hash ; clear block descr. table and create free-links push hl pop ix ld hl, (blocksize) ld bc, bdscsize add ix, bc ld (bdata), ix ld (bfreefirst), ix ; ix=first block descr. ptr add hl, bc ex de, hl pop bc push bc ld b, c ; blocks ld hl, null cr_desc: ld (ix+bstatus), b_unused ld (ix+bfreeprev), l ld (ix+bfreeprev+1), h djnz cr_last push ix add ix, de push ix pop hl pop ix ld (ix+bfreenext), l ld (ix+bfreenext+1), h push ix ex (sp), hl pop ix jr cr_desc cr_last: ld (ix+bfreenext), b ld (ix+bfreenext+1), b ld (bfreelast), ix pop bc pop hl ret ;-------------------------------------------------------------------------- ;; write out all modified blocks for device A=0..0xfe or all devices A=0xff.; bufsync: ld ix, (bdata) ; ix=first block data/descriptor ld hl, cachesize ld b, (hl) ld hl, (blocksize) ld de, bdscsize add hl, de ex de, hl bsyncheck: push af cp 0xff jr z, bsynch1 cp (ix+bdevno) jr nz, bsynnext bsynch1: bit bit_unwritten, (ix+bstatus) jr z, bsynnext push bc push de ld a, (ix+bdevno) ld c, (ix+bblockno) ld b, (ix+bblockno+1) push ix push ix pop hl call bdwrite pop ix res bit_unwritten, (ix+bstatus) pop de pop bc bsynnext: pop af add ix, de djnz bsyncheck ret ;bread(devno,blockno,rewrite) : block ptr // INTERRUPTS DISABLED! ;{ ; if (block found in hash chain) ; { ; while (block locked) sleep? ; ; lock block ; ; exclude block from free-blocks chain ; ; } ; else ; { ; while (free-blocks chain is empty) sleep? ; ; lock block ; ; exclude first block from free-blocks chain ; ; if (first free block is unwritten) write block ; ; exclude block from hash chain ; ; set new devno and blockno ; ; if (rewrite==0) read block ; ; insert block in hash chain ; ; } ;} ; ; A=devno, BC=blockno, E=rewrite flag -> HL=bufptr bread: ld d, a push de call hashptr ; de=first block desc. in hash chain. ex af, af' ; devno ld e, (hl) inc hl ld d, (hl) ; de=first block desc. in chain ex de, hl pop de ; D=devno ; find block in hash chain ghashcomp: push hl pop ix ; ix=block desc. ld a, d cp (ix+bdevno) jr nz, ghashnext ; check devno, blockno and lock ld a, c cp (ix+bblockno) jr nz, ghashnext ld a, b cp (ix+bblockno+1) jr nz, ghashnext ; sleep while block is locked ghashsleep: bit bit_locked, (ix+bstatus) jp z, ghashfind call sleeplocked jr ghashsleep ghashnext: ex af, af' ld l, (ix+bhashnext) ld h, (ix+bhashnext+1) ld a, h or l jr nz, ghashcomp ; block not found in hash chain -- find any free block or sleep gfindfree: ld hl, (bfreefirst) ld a, h or l jr z, gisfree call sleepnofree jr gfindfree ; found free block gisfree: push hl pop ix set bit_locked, (ix+bstatus) push bc push de call excl_free bit bit_unwritten, (ix+bstatus) jr z, gnewblock ; write old block to disk // MAY BE INTERRUPTED ld a, (ix+bdevno) ld c, (ix+bblockno) ld b, (ix+bblockno+1) push ix push ix pop hl call bdwrite pop ix res bit_unwritten, (ix+bstatus) pop de pop bc ; data not valid -- set blockno, devno, add block to hash chain gnewblock: pop de pop bc ld (ix+bdevno), d ld (ix+bblockno), c ld (ix+bblockno+1), b dec e jr z, gnewread ; fill block with zeroes push ix pop hl ld e, l ld d, h inc de ld bc, (blocksize) dec bc ld (hl), 0 ldir jr gnewrewrite ; read from disk, d=devno, bc=blockno // MAY BE INTERRUPTED gnewread: ld a, d push ix push ix pop hl call bdread pop ix gnewrewrite: call hashptr ld e, (hl) inc hl ld d, (hl) push de ; get old ptr to first block push ix pop de ld (hl), d ; set new ptr to first block dec hl ld (hl), e pop ix ; ix=first block desc. in chain (old) ex de, hl ; hl=curr. block desc. ld (ix+bhashprev), l ld (ix+bhashprev+1), h push ix ex (sp), hl ; hl=next. ptr pop ix ; ix=curr. ptr ld (ix+bhashprev), 0 ld (ix+bhashprev+1), 0 ld (ix+bhashnext), l ld (ix+bhashnext+1), h push ix pop hl ret ; found block in hash chain and it is not locked ghashfind: set bit_locked, (ix+bstatus) call excl_free push ix pop hl ret ;bfree(blockptr,dirty) // INTERRUPTS DISABLED! ;{ ; if (dirty=1) set unwritten flag ; if (dirty<2) insert block to end of free-blocks chain ; ; else { ; write block ; ; insert block to begin of free-blocks chain ; ; } ; unlock block ; ;} ; free block HL=block ptr, E=dirty flag (0=unchanged, 1=write, 2=immend.write) bfree: push hl pop ix ld a, e or e jr z, bretoend ; block unchanged set bit_unwritten, (ix+bstatus) dec a jr z, bretoend ; write later ; immendiatelly write block // MAY BE INTERRUPTED ; hl=data ptr block must be locked! ld a, (ix+bdevno) ld c, (ix+bblockno) ld b, (ix+bblockno+1) push ix call bdwrite pop ix res bit_unwritten, (ix+bstatus) ; select strategy -- uncomment it ;; jr bretoend ; add block to begin of free-blocks chain bretobegin: res bit_locked, (ix+bstatus) ld hl, (bfreefirst) ld (bfreefirst), ix push hl push ix push ix ex (sp), hl ; hl=curr. pop ix ; ix=first in chain (old) ld (ix+bfreeprev), l ld (ix+bfreeprev+1), h pop ix ; hl=first in chain (old) pop hl ; ix=curr. ld (ix+bfreenext), l ld (ix+bfreenext+1), h ld (ix+bfreeprev), 0 ld (ix+bfreeprev+1), 0 ret ; add block to end of free-blocks chain bretoend: res bit_locked, (ix+bstatus) ld hl, (bfreelast) ld (bfreelast), ix push hl push ix push ix ex (sp), hl ; hl=curr. pop ix ; ix=last in chain (old) ld (ix+bfreenext), l ld (ix+bfreenext+1), h pop ix ; hl=last in chain (old) pop hl ; ix=curr. ld (ix+bfreeprev), l ld (ix+bfreeprev+1), h ld (ix+bfreenext), 0 ld (ix+bfreenext+1), 0 ret ;------------------- local subroutines and variables ----------------------- ; exclude block from free-blocks chain IX=descriptor excl_free: ld l, (ix+bfreenext) ld h, (ix+bfreenext+1) ; hl=next block desc. ld e, (ix+bfreeprev) ld d, (ix+bfreeprev+1) ; de=prev block desc. push ix ; if (prev exist) prev.next=next else firstlink=next; ld a, d or e jr z, exfnoprev push de pop ix ld (ix+bfreenext), l ld (ix+bfreenext+1), h jr exfchnext exfnoprev: ld (bfreefirst), hl ; if (next exist) next.prev=prev else lastlink=prev; exfchnext: ld a, h or l jr z, exfnonext push hl pop ix ld (ix+bfreeprev), e ld (ix+bfreeprev+1), d jr exfchend exfnonext: ld (bfreelast), de exfchend: pop ix ret ; get first block desc. ptr in hash chain ; A=devno, BC=blockno -> HL=pointer to chain start A,B,C must be unchanged! hashsize equ 16 ; 4-bit hash hashptr: push af xor b xor c and hashsize-1 ; calculate hash ld e, a ld d, 0 ld hl, bhash add hl, de pop af ret ; ! hashsize : 7-bit value! ; ! blocks : 8-bit value! ; ! blocksize : word ; ! devno : one byte ! ; blocks = cashesize/(blocksize+bdscsize+2/bhashcap) ; hashsize = blocks/bhashcap ; status b_unused equ 0 ; status=0 if blockno and devno is invalid ! bit_locked equ 0 bit_unwritten equ 1 bit_valid equ 7 ; buffers cache struct: ;bdata equ 0..blocksize-1 bdevno equ -1 bstatus equ -2 bblockno equ -4 bhashprev equ -6 bhashnext equ -8 bfreeprev equ -0ah bfreenext equ -0ch bdscsize equ 0ch blocksize: dw 0 ; size of data in one block cachesize: db 0 ; 01..FF blocks in cache bfreefirst: dw 0 ; pointer to first free block bfreelast: dw 0 ; pointer to last free block bhash: dw 0 ; pointer to start of hash array bdata: dw 0 ; pointer to start of cache data end === Cut ===




Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
ZX-Обоз - Обзор электронной прессы: ZX-News 47, Don News 7, Buzz 17.
Demo Party - результаты CC.999.999
Paracels speaking - новости от: Rain Group, Raww Arse, Remedy, Skrju, Studio Stall, Techno Lab, 4D, Triebkraft, Wlodeck Black.
От авторов - традиционное вступление.
Железо - схема расширения памяти Пентагона до 256кб.

В этот день...   7 мая