;; codigo maquina para winape de las lineas 250-280 del listado "Overlook Hotel",
;; aparecido en la revista Amstrad Personal n. 10
;; Rutinas firmware llamadas
KL_LOG_EXT equ #BCD1
SCR_DOT_POSITION equ #BC1D
MC_WAIT_FLYBACK equ #BD19
org #8000
;; Inicializar comandos RSX
InitRSX:
ld bc,RSX_Table
ld hl,RSX_4_bytes
call KL_LOG_EXT
ret
RSX_Table:
dw RSX_names
jp RSX_ON
jp RSX_PUTSPRITE
jp RSX_OFF
RSX_4_bytes:
db #FC,#A6,#0A,#80
RSX_names:
db "O",'N' OR #80
db "PUTSPRIT",'E' OR #80
db "OF",'F' OR #80
db 0 ;rsx names end
;; RSX PUTSPRITE |PUTSPRITE,x,y
;; p.e: |PUTSPRITE,35,F
;;
;; Calcula la direccion en memoria de video de las coordenadas recibidas y
;; llama a "RepintaFondoyPintaSprite"
;;
RSX_PUTSPRITE: ;0x8028
ld l,(ix+#00)
ld h,(ix+#01)
ld e,(ix+#02)
ld d,(ix+#03)
call SCR_DOT_POSITION ;IN DE=x-coord HL=y-coord OUT HL=vmem
PutsprEnDireccionHL:
ld (videomem_para_borrar),hl
ld (videomem_para_pasar_a_buffer),hl
ld hl,(sprite_mem_leido_por_rsx_on)
ld (sprite_mem_para_pintar_respetando_fondo),hl
ld (sprite_mem_no_se_usa),hl
ld hl,(sprite_height) ;carga en HL alto y ancho
call MC_WAIT_FLYBACK
call RepintaFondoyPintaSprite
ld hl,(videomem_para_borrar)
ld (videomem_para_restaurar_fondo),hl
ret
;; RSX ON |ON,direccion_de_estructura_sprite,x,y
;; p.e: |ON,&8396,XX-2,35
;; direccion_de_estructura_sprite = dir de memoria de array con altura, anchura y direccion del sprite
;;
;; Calcula la direccion de memoria de video de las coordenadas recibidas y
;; guarda esta direccion en las variables "videomem_para_restaurar_fondo" y
;; "videomem_para_pasar_a_buffer". Accede a la estructura del primer parĂ¡metro
;; y establece con eso las variables "sprite_height", "sprite_width",
;; "sprite_mem_leido_por_rsx_on" y "sprite_mem_para_pintar_respetando_fondo".
;; Luego llama a "GuardaenBufferYPinta" y "PutsprEnDireccionHL".
RSX_ON:
ld l,(ix+#04)
ld h,(ix+#05)
ld a,(hl)
ld (sprite_height),a
inc hl
ld a,(hl)
ld (sprite_width),a
inc hl
ld (sprite_mem_leido_por_rsx_on),hl
ld l,(ix+#00)
ld h,(ix+#01)
ld e,(ix+#02)
ld d,(ix+#03)
call SCR_DOT_POSITION ;IN DE=x-coord HL=y-coord OUT HL=vmem
push hl
ld (videomem_para_restaurar_fondo),hl
ld (videomem_para_pasar_a_buffer),hl
ld hl,(sprite_mem_leido_por_rsx_on)
ld (sprite_mem_para_pintar_respetando_fondo),hl
call GuardaenBufferYPinta
pop hl
jp PutsprEnDireccionHL
;; RepintaFondoyPintaSprite
;;
;; Restaura el fondo desde el buffer en 9000 a vmem y luego pinta sprite sin sobreescribir
;; Recibe en HL el alto y ancho, que guarda en las variables
;; "sprite_height" y "sprite_width". Copia del buffer a la direccion
;; apuntada por "videomem_para_restaurar_fondo".
;; La ejecucion continua en "GuardaenBufferYPinta": Llama a
;; "CopySpriteScreenToBuffer", que copia de la direccion "videomem_para_pasar_a_buffer"
;; al buffer (con ancho "sprite_width" y alto "sprite_height"). Entonces copia el sprite
;; apuntado por "sprite_mem_para_pintar_respetando_fondo" (en formato sprite)
;; a la posicion de pantalla apuntada por "videomem_para_pasar_a_buffer"
;; (formato pantalla), sobreescribiendo solo los bytes que eran 0.
RepintaFondoyPintaSprite:
ld (sprite_height),hl
ld b,l
ld hl,(videomem_para_restaurar_fondo)
ld de,#9000
di
CopiaLinDeBufferAVmem:
push bc
ld a,(sprite_width)
ld b,a
push hl
CopiaByteDeBufferAVmem:
ld a,(de)
ld (hl),a
inc hl
inc de
djnz CopiaByteDeBufferAVmem
pop hl
ld a,h
add #08
ld h,a
jr nc,seguirCopia1
ld bc,#c050
add hl,bc
seguirCopia1:
pop bc
djnz CopiaLinDeBufferAVmem
;la ejecucion countinua en GuardaenBufferYPinta
;;GuardaenBufferYPinta
;; Llama a "CopySpriteScreenToBuffer", que copia de la direccion "videomem_para_pasar_a_buffer"
;; al buffer (con ancho "sprite_width" y alto "sprite_height"). Entonces copia el sprite
;; apuntado por "sprite_mem_para_pintar_respetando_fondo" (en formato sprite)
;; a la posicion de pantalla apuntada por "videomem_para_pasar_a_buffer"
;; (formato pantalla), sobreescribiendo solo los bytes que eran 0.
GuardaenBufferYPinta:
call CopySpriteScreenToBuffer
ld hl,(videomem_para_pasar_a_buffer)
ld de,(sprite_mem_para_pintar_respetando_fondo)
ld a,(sprite_height)
ld b,a
copiaLinea2:
push bc
ld a,(sprite_width)
ld b,a
push hl ;guarda inicio de linea de sprite
copiaByteSiDestinoEs0:
ld a,(hl)
cp #00
jr nz,preparaSigByte
ld a,(de)
ld (hl),a
preparaSigByte:
inc hl
inc de
djnz copiaByteSiDestinoEs0
pop hl ;recupera inicio de linea de sprite
ld a,h
add #08
ld h,a
jr nc,seguirCopia2
ld bc,#c050
add hl,bc
seguirCopia2:
pop bc
djnz copiaLinea2 ;seguir si quedan lineas
ei
ret
;; RSX_OFF |OFF sin parametros
;;
;; Borra (pone a 0) un sprite de la memoria de video.
;; Borra en la direccion apuntada por "videomem_para_borrar"
;; con ancho "sprite_width" y alto "sprite_height"
;;
RSX_OFF:
ld hl,(videomem_para_borrar)
ld a,(sprite_height)
ld b,a
borrarLineaSprVmem:
push bc
push hl
ld a,(sprite_width)
ld b,a
borrarByte:
xor a
ld (hl),a
inc hl
djnz borrarByte
pop hl ;calcular siguiente linea
ld a,h
add #08
ld h,a
jr nc,seguirBorrado
ld bc,#c050
add hl,bc
seguirBorrado:
pop bc
djnz borrarLineaSprVmem
ret
sprite_height: ;#8101
db #1E
sprite_width: ;#8102
db #08
videomem_para_borrar: ;#8103
db #F2,#DB
var_16bit_no_se_usa: ;#8105 No se usa para nada
db #00,#00
sprite_mem_leido_por_rsx_on: ;#8107
db #02,#60
videomem_para_pasar_a_buffer: ;#8109
db #F2,#DB
videomem_para_restaurar_fondo: ;#810B
db #F2,#DB
sprite_mem_no_se_usa: ;#810D Se modifica pero no se consulta
db #02,#60
sprite_mem_para_pintar_respetando_fondo: ;#810F
db #02,#60
;; CopySpriteScreenToBuffer
;;
;; Copia un sprite de la memoria de video a un buffer en 9000 (en formato sprite)
;; copia de la direccion apuntada por "videomem_para_pasar_a_buffer" con
;; ancho "sprite_width" y alto "sprite_height".
;;
CopySpriteScreenToBuffer:
push hl
ld hl,(videomem_para_pasar_a_buffer)
ld de,#9000
ld a,(sprite_height)
ld b,a
CopyScrSprLineToBuffer:
push bc
push hl
ld a,(sprite_width)
ld b,a
CopyScrSprByteToBuffer:
ld a,(hl)
ld (de),a
inc hl
inc de
djnz CopyScrSprByteToBuffer
pop hl
ld a,h
add #08
ld h,a
jr nc,checkIfLastLine
ld bc,#c050
add hl,bc ;corregir si necesario
checkIfLastLine:
pop bc
djnz CopyScrSprLineToBuffer
pop hl
ret