Loader:
in most cases during Speccy conversions I make a jump from the entry point of the program to initialization part, it is not needed, but I like keeping codes used by the converted program in the beginning of loader.
;Create macro for EXOS calls, which is the name of "special command" of Enterprise eXpandable Operating System.
macro exos,n
rst 030h
defb n
endm
;next 16 byte is the EXOS file header, 2nd byte specify EXOS header 5, which means the program will be loaded to 100h automatically, 3rd and 4th byte is the length of the code, EXOS header is not counted to File length.
org 00f0h
db 00,05 ;EXOS file header
dw fillen
db 00,00,00,00,00,00,00,00,00,00,00,00
startpr ld sp,0100h ;loader starts at 100h, stack pointer must be set here or interrupts must disabled, because the 1st EXOS interrupt would hang the program, because the stack pointer points to EXOS stack address.
jp contin ;jump to loader initialization
hiba di ;soft reset routine
ld sp,0100h
ld a,0ffh
out (0b2h),a
ld c,40h
exos 0
ld a,01h
out (0b3h), a
ld a,06h
jp 0c00dh
hibalng equ $-hiba
isr push af ;interrupt routine
ld a,30h ;reset video interrupt counter, and activate video interrupt (it has to be done at each interrupt, otherwise Enterprise will remain a forever interrupt loop)
out (0b4h),a ;interrupt register
contisr ld a,04h ;check if any of function key is pressed
out (0b5h),a
in a,(0b5h)
cpl
jr z,nofkey ;function key is not pressed
rlca
jr nc,nof1
ld a,21h ;F1 pressed (cheat on)
jr writevl
nof1 rlca
jr nc,nofkey
ld a,32h ;F2 pressed (cheat off)
writevl ld (6f0ah),a
nofkey pop af
ei
ret
keybrd out (0b5h),a ;select keyboard row (A contains the row 00-09h
in a,(0b5h) ;read a keyboard row
ret
keybrd1 out (0b5h),a ;it is invoked from 1 place and A = 3
in a,(0b5h) ;read keyboard row 3 ( esc , 2 , 3 , 5 , 4 , 6 , 1 , 7)
and 05h ;store only keys 6 and 7
ld c,a
ld a,05h
out (0b5h),a ; b7 b6 b5 b4 b3 b2 b1 b0
in a,(0b5h) ;read keyboard row 5 ( xxx , erase , ^ , 0 , - , 9 , xxx , 8 )
rlca
and 2ah
or c
ret
joystck push hl ;read external joysticks
push bc
ld c,01h ;read ext joy1 without fire
call joystc2
ld h,l
inc c ;read ext joy2 without fire
call joystc2
ld a,l
and h
cpl
ld l,a ;store the states of 2 joyticks
ld a,07h ;read internal joystick
out (0b5h),a
in a,(0b5h) ; alt , enter , int left , hold , int up, int right , int down , stop
rrca
rrca
jr c,nodwn
set 2,l
nodwn rrca
jr c,norgt
set 0,l
norgt rrca
jr c,noup
set 3,l
noup rrca
rrca
jr c,noleft
set 1,l
noleft pop bc
ld c,l
pop hl
ret
joystc2 ld l,0ffh
ld b,04h
joystc1 ld a,c
out (0b5h),a ;bit 0 of each line gives back a value of ext joy
in a,(0b6h) ; line0 line1 line2 line3 line4 line5 line6 line7 line8 line9
rrca ; fire1 up1 dwn1 lft1 rgt1 fire2 up2 dwn2 lft2 rgt2
rl l
inc c
djnz joystc1
ret
joyfire ld a,08h ;check state of fire (for internal joystick space is selected)
out (0b5h),a
in a,(0b5h) ; ins , space , rgt shift, . , / ,",", del , m
cpl
bit 6,a ;check space
ret nz
xor a
out (0b5h),a
in a,(0b6h)
cpl
bit 0,a ;check ext1 joy fire
ret nz
ld a,05h
out (0b5h),a
in a,(0b6h)
cpl
bit 0,a ;check ext2 joy fire
ret
memaddr ld de,0000h ;calculate Nick address of video page, input in A, output in HL
rra
rr d
rra
rr d
ex de,hl
ret
;szeg exos 24
; jp nz,hiba
; ld a,c
; ret
defs 200h-$
epcols db 73,217,219,162,166,93,37,21,73,217,219,162,166;,93,37,21
;data for LPT creation, LPT defines the attributes of screen
;256-255 defines 1 raster line
;14h defines: 2 colour (bit5-6), attribute mode (bit1-3), full vertical resolution (bit4)
;left margin 15 and right margin 2fh defines a 32 character wide screen
;byte 4-5 is filled during building of LPT, Nick address of Attribute memory will be here
;byte 6-7 is filled during building of LPT, Nick address of Bitmap memory will be here
line db 255,14h,15,2fh,0,0,0,0 ;192 (1 raster line for definition of speccy screen)
tabl db 00h,19h,92h,0dbh,24h,6dh,0b6h,0ffh ;here is the bright palette for speccy screen)
sync db 0cah,2,3fh,0,0,0,0,0 ;video synchron starts here
db 00,00,00,00,00,00,00,00 ;39
db 0fdh,0,3fh,0,0,0,0,0
db 00,00,00,00,00,00,00,00 ;3
db 0fch,0,6,3fh,0,0,0,0
db 00,00,00,00,00,00,00,00 ;4
db 0ffh,90h,3fh,20h,0,0,0,0
db 00,00,00,00,00,00,00,00 ;1
db 0fch,2,6,3fh,6,0,0,0
db 00,00,00,00,00,00,00,00 ;4
db 0cah,03,3fh,0,0,0,0,0
db 00,00,00,00,00,00,00,00 ;40 sum 312
hossz equ $-sync
vid ld hl,stack ;request a video memory segment (0fch-0ffh segments)
ld (hl),0
ker exos 24
jr z,namivan
cp 7fh
jp nz,hiba
namivan ex af,af'
ld a,c
cp 0fch
jr nc,nemker
inc hl
ld (hl),c
jr ker
nemker ex af,af'
push bc
push af
vissza ld c,(hl)
exos 25
dec hl
jr z,vissza
pop af
pop bc
cp 7fh
ld a,c ;a contains the page
jp z,hiba
ret
;initialization of RAM Settings, generate Speccy like screen, Border colour, Bias colour, and later conversion routines
contin ld hl,hiba ;set address of soft reset routine
ld (0bff8h),hl
ld bc,100h+28 ;EXOS variable 28
ld d,192 ;set bias 192, this specify colour 8-15 ( it will be used for speccy dark colours )
exos 16
ld bc,100h+27 ;EXOS variable 27
ld d,00h ;set border black
exos 16
;allocate video memory, and get the Nick address of allocated video Segments
call vid ;allocate video segment for screen, and store video segment at SCR+1
ld (scr+1),a
call memaddr ;get Nick address of video segment
ld (vidcim1),hl ;address of screen
call vid ;alloc video segment for LPT
nemhiba out (0b1h),a
out (0b3h),a
cont call memaddr ;get Nick address of LPT segment
ld (vidcim2),hl ;address of screen
;build Speccy like screen (create LPT)
ld a,0c0h ;create lpt, Speccy bitmap will be visible 4000-57ffh, attribute will be visible 5800-5affh
ld de,(vidcim2) ;Nick address of LPT
res 7,d
set 6,d ;convert Nick address to z80 address, since the page paged in into page1
push de
exx
ld de,(vidcim1) ;Nick address of Screen
ld ix,vidcim1
pop hl
inc hl
inc hl
inc hl
inc hl
ld bc,000dh
l1 ex af,af'
exx
ld hl,line ;copy a pixel line of speccy screen ( it will be done 192 times )
ld bc,0010h
ldir
exx
ld (hl),e ;store low value of Nick address of attribute for each pixel line
inc hl
ld a,d
rra
rra
rra
and 03h
or 18h
or (ix+1)
ld (hl),a ;store high value of Nick address of attribute for each pixel line
inc hl
ld (hl),e ;store low value of Nick address of bitmap for each pixel line
inc hl
ld (hl),d ;store high value of Nick address of bitmap for each pixel line
add hl,bc
inc d
ld a,d
and 07h
jr nz,l2
ld a,e
add a,20h
ld e,a
ccf
sbc a,a
and 0f8h
add a,d
ld d,a
l2 ex af,af'
dec a
jr nz,l1
exx
ld hl,sync ;copy remaining LPT data ( EP logo, and VSYNC )
ld bc,hossz
ldir ;end of lpt creation
;Allocate other 32K memory if 48 K speccy program is going to be converted
; call szeg ;allocate a 16K segment and page in it to page2 (it is needed if a 48K speccy program is going to be converted)
; out (0b2h),a
; call szeg ;allocate a 16K segment and page in it to page3 (it is needed if a 48K speccy program is going to be converted)
; out (0b3h),a
scr ld a,00h ;page in screen memory to page1
out (0b1h),a
;load screen file
xor a ;open file A is the channel number (it can be nearly any value, except the reserved channel numbers)
ld de,scrn ;file name
exos 1 ;open file
jp nz,hiba ;if not zero, file could not be opened, jump to soft reset
ld de,4000h ;A channel number (zero), DE target
ld bc,1b00h ;BC length
exos 6 ;load file
xor a ;A channel number
exos 3 ;close channel
;convert attributes of speccy screen
ld hl,5800h
chatt1 call chngatt ;convert screen attributes
ld a,h
cp 5bh
jr nz,chatt1
;activate our LPT (Display Speccy Screen)
di
xor a ;activate our LPT (speccy screen)
ld hl,vidcim2+1
rrd
rlca
rlca
rlca
rlca ;LPT Base pointer = Nick address of LPT / 10h + 0c000h
out (82h),a ;low part of LPT base pointer
dispscr or 0c0h
rrd
out (83h),a ;high part of LPT base pointer
;Load program file int it's place
xor a ;open file
ld de,pr1 ;file name
exos 1
jp nz,hiba ;jump if error
ld de,5b00h ;target address
ld bc,2000h ;lebgth
exos 6 ;load file
xor a
exos 3 ;close file
;Set dave registers for beeper sound play back, and set our interrupt routine (this game did not use interrupts, if a game uses interrupt in most cases it uses IM 2, remove IM 2 interrupt definitions, and IM 2 table, and set up the ISR routine and insert the interrupt code into it.
ld bc,00afh ;reset Dave registers
dave00 out (c),b
dec c
bit 4,c
jr z,dave00
di
ld a,3fh ;sound setting
out (0a8h),a ;set left volume of channel 0 to max
out (0ach),a ;set right volume of channel 0 to max
ld a,30h ;enable interrupt video interrupt
out (0b4h),a
ld a,0ch ;no delay (enable max speed if the code runs and makes I/O in normal RAM (not VRAM))
out (0bfh),a
ld a,0c3h ;setup interrupt (IM 1)
ld hl,isr ;load interrupt call to 0038h
ld (0038h),a
ld (0039h),hl
;Conversion of speccy program is done here
call convert ;convert program, and attributes
;wait a key from row 8 for start the program
ei
waitkey ld a,08h ;wait a key from row 8
out (0b5h),a
in a,(0b5h)
halt
inc a
jr z,waitkey
jp 06c7bh ;start program
scrn db 12,"ARMAGEDD.ONS"
pr1 db 12,"ARMAGEDD.ONP"
vidcim1 dw 0
vidcim2 dw 0
chngatt ;convert speccy attributes to EP attributes
nxtbyte ld a,(hl)
ld de,dark
bit 6,a
jr z,dark1
ld de,bright
dark1 push de
and 07h
add a,e
ld e,a
ld a,(de)
ld c,a
ld a,(hl)
pop de
and 38h
rra
rra
rra
add a,e
ld e,a
ld a,(de)
rla
rla
rla
rla
or c
ld (hl),a
inc hl
ret
bright db 00h,04h,01h,05h,02h,06h,03h,07h
dark db 00h,0ch,09h,0dh,0ah,0eh,0bh,0fh
convert ld hl,69f3h-7*40h ;patch Joystick text to INT/EXT
ld de,joyst
ld c,08h
char2 ld b,06h
char1 push bc
ld a,(de)
ld (hl),a
inc de
ld bc,0008h
add hl,bc
pop bc
djnz char1
push bc
ld bc,0010h
add hl,bc
pop bc
dec c
jr nz,char2 ;end of joystick text patch
ld hl,startc
call convprg ;convert code
ld hl,6c71h ;convert attributes
ld b,09h
convatt push bc
call chngatt
pop bc
djnz convatt
ld hl,6c7ch
call chngatt
ld hl,6d16h
call chngatt
ld hl,6de8h
call chngatt
ld hl,6df7h
call chngatt
ld hl,6e09h
call chngatt
ld hl,6e8dh
call chngatt
ld hl,7034h
call chngatt
ld hl,703ch
call chngatt
ld hl,71cdh
call chngatt
ld hl,73c1h
call chngatt
ld hl,74eeh
call chngatt
ret
convprg ld e,(hl) ;convert code
inc hl
ld d,(hl)
inc hl
ld c,(hl)
inc hl
ld b,(hl)
inc hl
ldir
ld a,(hl)
inc a
jr nz,convprg
inc hl
ld a,(hl)
dec hl
inc a
jr nz,convprg
ret
joyst db 00h,00h,00h,00h,00h,00h
db 7fh,08h,08h,08h,08h,08h ;t
db 42h,24h,18h,18h,24h,42h ;x
db 7eh,40h,7ch,40h,40h,7eh ;e
db 02h,04h,08h,10h,20h,40h ;/
db 7fh,08h,08h,08h,08h,08h ;t
db 42h,62h,52h,4ah,46h,42h ;n 69b3
db 3eh,08h,08h,08h,08h,3eh ;i 69f3 every 8th
startc ;6c6e number of lives remaining, 6c6d number of attacks
dw 6cb6h,6cbfh-6cb6h
ad6cb6 ld a,03h
ad6cb9 call keybrd ;[ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] 01234
ad6cbb and 7ah
ad6cbd cp 7ah
dw 6cc8h,6cd1h-6cc8h
ad6cc8 ld a,03h
ad6cca call keybrd1 ;[ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 0 ] 43210
ad6ccd and 2fh
ad6ccf cp 2fh
dw 6e06h,02h
and 0f0h ;convert attribute
dw 6ce3h,02h
out (0a7h),a ;music
dw 6ce9h,02h
out (0a7h),a ;music
dw 6e34h,02h
or 08h ;convert attribute to Dark
dw 6e41h,02h
or 08h ;convert attribute to Dark
dw 6e50h,02h
or 08h ;convert attribute to Dark
dw 6e5dh,02h
or 08h ;convert attribute to Dark
dw 6eb1h,6eb5h-6eb1h
bit 3,a ;check attribute
jr z,$+0ah ;6ebdh ;check if a town is damaged
dw 6ec0h,6ec4h-6ec0h
bit 3,a ;check attribute
jr nz,$-0dh ;6eb5h
dw 6f54h,02h
out (0a7h),a ;music
dw 6fdch,02h
out (0a7h),a ;music
dw 6fafh,6fb3h-6fafh
and 08h ;check if attribute is bright
jr nz,$+0eh ;6fbfh
dw 6fe9h,02h
out (0a7h),a ;music
dw 6fefh,02h
out (0a7h),a ;music
dw 7015h,02h
out (0a7h),a ;music
dw 701bh,02h
out (0a7h),a ;music
dw 7055h,02h
ld c,4ah
dw 707eh,02h
out (0a7h),a ;music
dw 708dh,02h
out (0a7h),a ;music
dw 715ah,02h
out (0a7h),a ;music
dw 7168h,02h
out (0a7h),a ;music
dw 7171h,7175h-7171h
and 08h
jr z,$+19h ;718ch
dw 7242h,07h
ld a,01h
call keybrd ;s
bit 5,a
dw 724ch,07h
ld a,00h
call keybrd ;x
bit 5,a
dw 7256h,07h
ld a,00h
call keybrd ;n
bit 0,a
dw 7260h,07h
ld a,08h
call keybrd ;m
bit 0,a
dw 726ch,03h
call joystck
dw 72fch,07h
ld a,01h
call keybrd ;a
bit 6,a
dw 730bh,04h
call joyfire ;fire
nop
dw 73a1h,0fh
ld a,01h
call keybrd ;h
bit 0,a
ret nz
ld a,01h
call keybrd ;s
bit 5,a
dw 74ebh,02h
and 0f0h ;convert attribute
end1 dw 0ffffh
stack
fillen equ $-startpr
end