Загрузчик кода в формате .TAP

 

Иногда нужно быстро сделать загрузчик интро в формате .TAP. Удобнее всего использовать ассемблер Pasmo, ввести 

start

;тут код

end start

и скомпилировать  pasmo - tape src.asm

А если понадобится свой загрузчик с печатью текста и установкой цвета? Как вариант - использовать две утилиты bas2tap и bin2tap

Вчера убил целый день чтобы сделать готовый код в sjasmplus. Основная заморочка - подсчет контрольных сумм заголовков и блоков на кассете.

В версии 1.20.3 есть нужная команда:

;tape for sjasmplus v1.20.3
 DEFINE relname "Chess" ; name of release
 DEFINE tapname "chess.tap" ; .TAP filename
device zxspectrum48
        ORG #6000
begin
ld hl,$4000
ld b,$18
ld a,$aa
ch:
ld (hl),a
inc l
jr nz,ch
cpl
inc h
djnz ch
ret
end
basicb:
 db 0,10 ;line number
 dw line10e-line10b ; length of line10
line10b:
 db 253; clear
 db 176; val
 db 34
; db "24575"
 LUA ALLPASS
 ss=string.format("%05d",tostring( sj.get_label("begin")-1 ) )
 for i=1,5,1 do
  sj.add_byte(tonumber(string.byte(string.sub(ss,i,i))))
 end
 ENDLUA
 db 34,":"
 db 239;load
 db 34,34; ""
 db 175,13 ; code
line10e:
 db 0,20 ;line number
 dw line20e-line20b ; length of line20
line20b:
 db 249 ; randomize
 db 192 ; usr
 db 176 ; val
 db 34
; db "24576"
 LUA ALLPASS
 ss=string.format("%05d",tostring( sj.get_label("begin") ) )
 for i=1,5,1 do
  sj.add_byte(tonumber(string.byte(string.sub(ss,i,i))))
 end
ENDLUA
 db 34,13
line20e:
basice:
 EMPTYTAP tapname
 SAVETAP tapname,BASIC,relname,basicb,basice-basicb,10
 SAVETAP tapname,CODE,relname,begin,end-begin
display /d,line10e-line10b;end-begin
; savesna "!void.sna",begin

Здесь все просто - задать имена для tap-ки, имя файла и добавить код интро. Но версия ассемблера определяется как вирус и я решил переписать под старую версию. Сформировал готовые заголовки/блоки и перешел к подсчету контрольных сумм на случай, если  что-то изменится. И тут пришел тупик - Lua не понимает XOR.

Заменил. Позже, после отдыха переписал фрагменты Lua, заработало.

 DEFINE relname "Chess" ; name of release
 OUTPUT code.tap ; filename
  LUA ALLPASS
  function tcs(l1,l2,c)
-- local c=0
 for i=l1,l2,1 do --start from 255
 local b=sj.get_byte(i)
  local r=0
  local w=1
--calc not supported XOR
for j=0,7,1 do
  b1=b-2*math.floor(b/2)
  b2=c-2*math.floor(c/2)
-- r=math.floor(r/2)+128*math.abs(b1-b2)
  r=r+w*math.abs(b1-b2)
  w=w*2
  b=math.floor(b/2)
  c=math.floor(c/2)
end
 c=r
 end
 sj.add_byte(c)
  end

function name_add()
local ss=sj.get_define("relname")
ss=string.gsub(ss,'"',"")
while string.len(ss)<10 do
ss=ss.." "
end
 for i=1,10,1 do
  sj.add_byte(tonumber(string.byte(string.sub(ss,i,i))))
 end
end

function n2s(numba)
 ss=string.format("%05d",tostring( numba ) )
 for i=1,5,1 do
  sj.add_byte(tonumber(string.byte(string.sub(ss,i,i))))
 end
end

ENDLUA

device zxspectrum48
; OUTPUT code.tap

;basic
;remove that comments
;13 00<--header length
;00<--always 0 standard header
;00<--always 0 program header
;43 68 65 73 73 20 20 20 20 20 <-padded filename
;22 00<--data length
;0A 00<--autostart line
;22 00<--program length
;64<-----checksum byte
;24 00<--length of second block+2
;FF<---flag byte:0 for headers,FF-data block
;00 0A 0F 00 FD B0 22 32 34 35 37 35 22 3A EF 22 22 AF 0D 00 14 0B 00 F9 C0 B0 22 32 34 35 37 36 22 0D -Basic program
;58<--checksum
org 0
 db $13,0
hdr2b:
 db 0,0
  LUA ALLPASS
  name_add()
ENDLUA

 dw basice-basicb ; data length
 db 10,0 ; autostart
 dw basice-basicb ; program length
hdr2e:
; db $64 ; checksum byte
 LUA ALLPASS
 tcs(sj.get_label("hdr2b"),sj.get_label("hdr2e"),0)
 ENDLUA

 dw basice-basicb+2 ; data length
 db $FF ; flag 'data block'
basicb:
 db 0,10 ;line number
 dw line10e-line10b ; length of line10
line10b:
 db 253; clear
 db 176; val
 db 34
; db "24575"
 LUA ALLPASS
 n2s(sj.get_label("begin")-1)
 ENDLUA
 db 34,":"
 db 239;load
 db 34,34; ""
 db 175,13 ; code
line10e:

 db 0,20 ;line number
 dw line20e-line20b ; length of line20
line20b:
 db 249 ; randomize
 db 192 ; usr
 db 176 ; val
 db 34
; db "24576"
 LUA ALLPASS
 n2s(sj.get_label("begin"))
 ENDLUA

 db 34,13
line20e:
basice:
; db $58 ;checksum byte
 LUA ALLPASS
 tcs(sj.get_label("basicb")-1,sj.get_label("basice"),0)
 ENDLUA
;header for code
;13 00<--header length
;00<--always 0 standard header
;03<--always 3 code header
;43 68 65 73 73 20 20 20 20 20<-padded filename
;10 00<--data length
;00 60<--code start
;00 80<--program length
;9D<-----checksum byte
;12 00<--length of second block+2
;FF<---flag byte:0 for headers,FF-data block
;21 00 40 06 18 3E AA 77 2C 20 FC 2F 24 10 F8 C9
;B9<-----checksum

;code
 db $13,00;<--header length
hdr1b:
 db 00;<--always 0 standard header
 db 03;<--always 3 code header
;43 68 65 73 73 20 20 20 20 20<-padded filename
  LUA ALLPASS
  name_add()
ENDLUA
 dw end-begin;10 00<--data length
 dw begin;00 60<--code start
 dw $8000;00 80<--program length
hdr1e:
; db $9D;<-----checksum byte

 LUA ALLPASS
 tcs(sj.get_label("hdr1b"),sj.get_label("hdr1e"),0)
 ENDLUA

 dw end-begin+2;12 00<--length of second block+2
 db $FF;<---flag byte:0 for headers,FF-data block
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;code starts here ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        ORG #6000
begin
ld hl,$4000
ld b,$18
ld a,$aa
ch:
ld (hl),a
inc l
jr nz,ch
cpl
inc h
djnz ch
ret
end

; db $B9;<-----checksum
 LUA ALLPASS
 tcs(sj.get_label("begin")-1,sj.get_label("end"),255)
 ENDLUA

В ближайшем времени собираюсь испытать свои изыски и надеюсь, что заработает.

Комментарии