radastan escribió:Bonus track...
Oh! qué chulo! Como pantalla estática es muy bonita. Voy a usar de todas formas la del anime ya que tiene colores planos... Bueno, usaré las dos, porque los desplazamientos laterales a 2bpp se verán "mejor" con imágenes fotorealísticas, o al menos que tengan algo de grano, como ésta. Te aviso que la gestión de pantalla en este caso está siendo más ardua (cosa que me imaginaba) y los resultados, más leeeeeentos. Para empezar, he tenido que bajar el reloj de la CPU a 3.5MHz para quitarme parte de la contienda, y aún no me la he quitado del todo, así que he tenido que subir el reloj de la sección de video, para que este circuito tenga más oportunidades para "cazar" su siguiente byte de memoria antes de que la CPU vuelva a reclamarla.
radastan escribió:Te digo yo que con este modo se pueden hacer cosas muy monas, mucho más sencillo que meter color y más fácilmente aprovechable.
Sí, pero a costa de enlentecer algunos procesos. El Z80 funciona muy bien con resoluciones de 1bpp y de 4bpp, porque para ambas tiene formas de trabajar (para 4bpp puedes usar muchas de las instrucciones de BCD para operar con píxeles individuales), pero para 2bpp lo único que puedes hacer es repetir dos veces lo que haces con 1bpp y eso es más lento sí o sí.
Para que te hagas una idea: este es el cuerpo del bucle que se repite 192 veces (una por cada scan de pantalla) para desplazarla 1 pixel a la derecha en el modo de 1bpp:
Código: Seleccionar todo
BucLinea ld d,h
ld e,l
ld a,(hl)
rept 32
rr (hl)
inc hl
endm
rra
ld (de),a
djnz BucLinea
Como ves, es basicamente un bloque que se repite 32 veces (vamos, un bucle desenrrollado) y dentro del bucle lo que hay son dos instrucciones.
La misma rutina para 2bpp tiene que procesar no 32, sino 64 bytes por scan (el doble). Y esos 64 bytes han de desplazarse dos bits, no uno, así que no es el doble de trabajo, ¡es el cuádruple! Bueno, en realidad un poco más del cuádruple de tiempo, ya que dentro del bucle que da 64 vueltas (desenrrollado) hay más de dos instrucciones. Es así:
Código: Seleccionar todo
push hl
ld c,(hl)
rept 64
ld a,(hl)
rra
ld (de),a
inc hl
inc de
endm
ld a,c
rra
ld (Buffer),a
pop de
ld hl,Buffer
push de
ld c,(hl)
rept 64
ld a,(hl)
rra
ld (de),a
inc hl
inc de
endm
pop hl
ld a,c
rra
ld (hl),a
ex de,hl
dec b
jp nz,BucLinea
La complejidad extra (el uso de un buffer off-screen para rotar una línea de pantalla) es porque si hago la rotación directamente en la memoria de pantalla (como de hecho hago en el caso 1bpp), al ser esta rotación necesariamente de 1 bit cada vez, se verían artefactos extraños en la imagen en forma de píxeles con colores falseados, producto de haber desalineado los bits que componen un pixel. Leo de pantalla, voy rotando lo que leo, y lo guardo en el buffer. Luego leo el buffer, roto lo que voy leyendo, y guardo de nuevo en pantalla. De esa forma no hay píxeles equivocados.
Rotar este tipo de pantalla dos píxeles a izquierda o derecha sin embargo es más rápido que rotarla 1 pixel, ya que para rotar dos píxeles necesito rotar 4 bytes, y ahí ya puedo ayudarme del manejo BCD del Z80 (concretamente la instrucción RLD)
En resumen: que para pantallas estáticas queda muy chulo, pero no sé yo si permitirá mover gráficos con soltura. Este nuevo circuito de video de 2bpp es más "memory-starving": necesita acceder a memoria el doble de veces que el original de 1bpp. Si subiendo el reloj de video a 14MHz no consigo mejorar la cosa (UPDATE: sí, mejora la cosa), creo que tiraré por la otra forma de hacer que la memoria dé datos más rápidamente: usar dos memorias en paralelo (con lo que doblo la anchura del bus de datos y consigo leer no uno sino dos bytes en el mismo ciclo de reloj, y de posiciones diferentes). Esto implica que la disposición de la pantalla ya no puede ser chunky, sino por bitplanes. De hecho, el invento de los bitplanes se hizo precisamente para poner cada uno en una memoria física diferente y así conseguir que el circuito de video tenga a su disposición un ancho de banda de memoria mayor que el de la CPU.