SIDE SDX: FATFS (FAT16+FAT32).

Flashjazzcat opublikował na Atari Age betę nowego fdisk.exe, która pozwala dodać/podlinkować partycje FAT16 do APT-a i przypisać jej napęd. Utworzyłem FAT32 dla loadera Side, oraz FAT16 z myślą o FATFS w Sparta Dos X i zadziałało od kopa. Po załadowaniu sterownika FATFS.SYS pod przypisanym w fdisku napędem pojawia się partycja FAT16 (read only). Druga partycja (FAT32) działa w side loaderze.

Dzięki temu kopiowanie danych na partycje SDX nie wymaga Sio2PC. Wystarczy kartę CF wetknąć do czytnika kart :). Trochę to mi ułatwi testowanie programów pod SDX.

VBXE + Action! Wczytywanie obrazu w overlay.

No i jest, pierwszy eksperyment w Action! + VBXE: obrazek w tle:

set 14=$8000
set $491=$8000

include "H1:RUNTIME.ACT"

proc CIOVE=$E4DF(byte areg, xreg)

proc delay()
 card i
 for i=0 to 30000 do od
return

proc main()

 byte vc=$D640
 int i byte memcont=$D65E, membank=$D65F
 byte psel=$D645, csel=$D644, cr=$D646, cg=$D647, cb=$D648
 byte xdla0=$D641, xdla1=$D642, xdla2=$D643
 byte blt0=$D650, blt1=$D651, blt2=$D652, bltst=$D653
 byte bkg=710, curinh=752
 byte iocb1cmd=850
 card iocb1buf=852, iocb1len=856

 byte array xdl=[98 136 219 0 2 0 64 1 17 223]

 ;clrscr blitterlist
 byte array clrscr=
   [ 0 0 0  ;src addr
     0 0    ;src step y
     0      ;src step x
     0 0 0  ;dst addr ($0000 up)
     64 1   ;dst step y (320)
     1      ;dst step x
     63 1   ;width (320-1)
     239    ;height (240-1)
     0      ;and mask
     0      ;xor mask
     0      ;collision and mask
     0      ;zoom
     0      ;pattern
     0 ]    ;control

 if vc<>$10 then
  printe("No VBXE FX found")
  delay()
  [$4C $C2AA] ;warm reset
 fi

 memcont=$A8  ;memac at $A000, cpu access
 membank=128+20
 moveblock($A000, xdl, 10)
 xdla0=0 xdla1=64 xdla2=1

 moveblock($A100, clrscr, 21)
 blt0=0 blt1=65 blt2=1
 bltst=1 ;blitter start will clear scr
 while bltst <> 0 do od ;let's wait till
                        ;blitter finishes
 graphics(0)
 bkg=0 curinh=1 put(31)

 close(1)
 open(1,"D1:AN.PAL",4,0)
 psel=1 csel=0
 for i=0 to 255 do
  cr=getd(1) cg=getd(1) cb=getd(1)
 od
 close(1)

 open(1,"D1:AN.PIC",4,0)
 iocb1cmd=7
 iocb1buf=$A000
 iocb1len=$1000

 for i=2 to 18 do
  membank=128+i
  CIOVE(0,$10)
 od
 close(1)

 vc=3
 printe("Hej czesc! Daj cos zjesc!")
 do od
return

test

Więcej informacji w tym wątku:

http://atarionline.pl/forum/comments.php?DiscussionID=2623&page=1#Item_15

Z moich przemyśleń dodam tylko uwagę na temat adresu overlay w xdl. Adres overlay w tym przykładzie to 0 2 0, czyli 2^9=512. Obrazek kopiujemy od adresu $2000=8192 i jeśli ustawiłbym  overlay na 0 32 0 to obraz wyświetlany byłby od samej góry, brzydko trochę, nie? Przy pierwszym podejściu ustawiałem ten adres na 0 0 0 i zastanawiałem się, czemu obrazek jest przesunięty? Po dwóch tygodniach naszła mnie właściwa myśl… Otóż, adres overlay musi być taki, aby 8192-adres było podzielne przez 320 (tada!). Czyli np. jeśli chcemy przed obrazkiem 24 linie, to 8192-24*320=512. W powyższym przykładzie blitter zeruje pamięć od $0000 więc mamy ładną ramkę przed i po obrazku.

VBXE2.

No i doczekałem się. Instalacja przysporzyła mi sporo frajdy i nawiasem mówiąc jeszcze się nie skończyła. Pierwsze uruchomienie – czarny ekran i tylko audio sugerujące, że coś jeszcze żyje.
Drugie, trzecie i trzechsetne, to samo. Trzeci wieczór eksperymentów przyniósł odkrycie: po odpaleniu FC.COM, a jest to program do zarządzania pamięcią flash karty, który umożliwia nam ładowanie różnych rdzeni (mamy do wykorzystania 12 banków pamięci na różne rdzenie) pozwala również taki rdzeń zbootować. Enter na banku bootuje wybrany rdzeń i „tada!” magicznie pojawia się na ekranie obraz z VBXE. Ni cholery nie wiem czemu ona się sama nie bootuje. Wydaje mi się, że jak podociskałem wczoraj kartę do adaptera/podstawki, to na chwilę samo działało, więc prawdopodobnie gdzieś coś nie styka. Podstawka i adapter do Antic to najsłabszy moim zdaniem punkt tej konstrukcji.

Dziś nawet wymieniłem podstawkę precyzyjną na płycie, bo myślałem, że to przez nią te „luzy”.

Nie jestem specjalnie dumny z wykonania, ale ważne, że póki co żaden element komputera nie poszedł z dymem. Co do jakości obrazu, szczerze powiem, że wielkiej przepaści nie ma względem oryginalnego obrazu na wyjściu monitorowym atari800xe (co może być komplementem w stronę nielubianych 800xe, mój był wyjątkowo udany).

UPDATE1: Finish. Przelutowałem VBXE do 130XE i działa. Wymieniłem też zasilacz na impulsowy.

UPDATE2: Dwa razy się zdarzyło, że adapter VBXE wyskoczył z podstawki w płycie. Nie dawało mi to spokoju i przelutowałem podstawkę w adapterze na taką typu carrier:

Adapter wlutowałem bezpośrednio w płytę, po przeniesieniu C31 na drugą stronę. Wydaje mi się, że ten carrier ma nieco dłuższe piny, w każdym razie wszystko idealnie spasowało. Najbardziej rzuca się  w oczy prawdziwy czerwony, którego stare Atari nie potrafiło wyświetlić 🙂

Competition Pro – Joystick idealny.

Kupiłem kiedyś na Allegro za przysłowiowych „pare złotych” joystick Competition Pro Star (jak na obrazku). Okazało się, że mikrostyki nie bardzo działają, więc przeleżał w szufladzie pół roku. Zaglądnąłem do niego i okazało się, że w środku są sprytnie zamontowane mikroprzełączniki przemysłowe.

images

Wymiana (mocowanie przełącznika to jedna śrubka, złączka jest wsuwana, bez lutowania)  zajęła jakieś 5 minut i Competition Pro działa po prostu rewelacyjnie. Zawsze miałem joysticki mikrostykowe, ale nie takie :). To jest konstrukcja nie do zdarcia. Nawet przyciski są na tych samych mikro przełącznikach, których pełno w automatyce, a mają wytrzymałość (np. Omron serii V) rzędu kilku milionów załączeń w cenie kilku, maks. kilkunastu złotych za sztukę.

PMG w Action!

Najwyższy czas na coś nowego. Poniżej pierwszy przykład PMG w Action! na podstawie „Atari Graphics and Arcade Game Design”. Do zerowania pamięci użyłem funkcji zero(), a do kopiowania danych moveblock() z Runtime Action!  Przy przesuwie pionowym duszka dane kopiujemy za pomocą wskaźników (tak btw, to lubię wskaźniki w Action!).


byte array p1data = [0 0 153 153 189 189 255 255 189 189 153 153 0 0]
card spot
byte pointer p1, p2

proc delay()
 int i for i=0 to 1000 do od
return

proc moveup()
 int i
 p1=spot p2=p1-1
 for i=0 to 13 do
  p2^=p1^
  p1==+1 p2==+1
 od
 spot==-1
return

proc movedown()
 int i
 p1=spot+13 p2=p1+1
 for i=0 to 13 do
  p2^=p1^
  p1==-1 p2==-1
 od
 spot==+1
return

proc main()
 byte pm=106, dmactl=559, gractl=53277, apmbase=54279,
      p1size=53256, p1hpos=53248, p1col=704, p1chpos,
      stick0
 card pmbase

 graphics(1+16)
 pm==-8
 pmbase=pm*256
 dmactl=62
 gractl=3
 apmbase=pm
 p1hpos=50 p1chpos=50
 p1size=1
 p1col=88
 spot=pmbase+1024+50

 zero(pmbase+1024, 256)
 moveblock(spot, p1data, 14)

 do
  stick0=stick(0)
  if stick0=11 then
   p1chpos==-1 p1hpos=p1chpos
  elseif stick0=7 then
   p1chpos==+1 p1hpos=p1chpos
  elseif stick0=14 then
   moveup()
  elseif stick0=13 then
   movedown()
 fi
 delay()
od

return

Jako ciekawostkę polecam zakomentować delay(). Action jest chyba jednak dość szybkie…

VBI finescroll + DLI rainbow (ASM)

Od piątku leżę w szpitalnym łóżku (spokojnie, to tylko kolejne badania moich szwankujących mięśni) i pomimo tego, że sobotę i niedzielę spędziłem z dzieciakami w domu (przypomina mi się seria „Wielkie ucieczki” na TVN), trochę mi się nudzi. Dzisiaj mnie biopsnęli w nogę, więc może trochę pod wpływem anestetyków postanowiłem dokończyć mój ulubiony (ad nauseam) scroll poziomy w VBI i „rainbow effect” w DLI, tym razem w assemblerze i tym razem w lewo.

hscrol = 54276
sdmctl = $022F
dlist = 560
nmien = $D40E
vvblkd = $0224
xitvbv = $E462
scount = $8000
colt = $D017
indx = $8002
wsync = $D40A
vdslist = $0200

      org $4000

init  ldy #0
      sty sdmctl                                ; wyłącz antic
      lda <ndl                                  ; ustaw adres tablicy ndl jako dliste
      sta dlist
      lda >ndl
      sta dlist+1
      lda #16
      sta scount                                ; wyzeruj liczniki
      sty chrno
      sty indx
      lda #64
      sta 88
      lda #156
      sta 89

      ; vbi+dli
      lda <scroll                               ; ustaw scroll w opóźnionym vblank interrupt
      sta vvblkd
      lda >scroll
      sta vvblkd+1
      lda <dli                                  ; ustaw adres procedury dli
      sta vdslist
      lda >dli
      sta vdslist+1
      lda #42
      sta sdmctl                                ; włącz antic
      lda #$c0                                  ; włącz przerwania dli
      sta nmien
      ; kolory i napisy
      lda #0
      sta 710
      posxy #2, #5
      putline #txt1
      lda #50
      sta 88
      lda #155
      sta 89
      posxy #0, #0
      putline #txt2

loop  jmp loop

scroll ldy scount
       dey
       sty hscrol
       beq @+
       sty scount
       jmp xitvbv
@      ldy chrno
       iny
       cpy #30
       bne chmem
       lda #25
       ldx #0
       stx chrno
       sta ndl[28],x
       lda #155
       sta ndl[29],x
       ldx #16
       stx scount
       jmp xitvbv
chmem
       clc
       sty chrno
       ldx #0
       lda ndl[28],x
       adc #2
       sta ndl[28],x
       lda ndl[29],x
       adc #0
       sta ndl[29],x
       ldy #15
       sty hscrol
       iny
       sty scount
       jmp xitvbv

dli    pha
       txa
       pha
       tya
       pha
       inc indx
       ldx #7
@      lda #1
       sta wsync
       lda indx
       cmp #30
       beq @+
       dex
       cpx #0
       beq ret
       clc
       adc vcount
       sta colt
       jmp @-
@      ldy #0
       sty indx
       jmp @-1
ret    pla
       tay
       pla
       tax
       pla
       rti

scount .by 0
chrno .by 0

.array ndl [33] .byte
 112, 112, 112, 66, 64, 156, 2, 2, 2, 2, 6, 2, 2
 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 130, 86, 30, 155
 65, 32, 156
.enda

txt1  .by 'test finescroll!' $9b
txt2  .by 'mads compiler!' $9b

.link 'putline.obx'
.link 'posxy.obx'

a2

Powyższy przykład przesuwa druga z linii w trybie Antic 6/GR. 1, ale sporo zabawy zajęło mi uzyskanie prawidłowego finescroll w Antic 2 / GR. 0. Z tego co udało mi się wyeksperymentować, w trybie GR. 0 jeden piksel potrzebuje pół cyklu koloru, skoro tych pikseli jest 8, do przesunięcia jednego znaku potrzeba 4 zmiany rejestru finescroll (1 cykl koloru = 1 finescroll). Analogicznie w trybie GR. 1 / Antic 6, jeden piksel potrzebuje jeden cykl koloru, znak ma 8 pikseli szerokości, więc mamy finescroll o 8 per znak.

Warto wspomnieć o jeszcze jednym zjawisku. W przykładach w Action! i assemblerze scroll działał prawidłowo, ale tylko w prawo i tylko o 16 punktów. Wydawało mi się to dziwne i długo nie dawało spokoju dlaczego tak się dzieje, że przy finescroll o 8 widać coś jakby szarpnięcie o jeden znak. Zjawisko brało się stąd, że zmieniałem adres pamięci w display liście i wychodziłem z procedury, a zmiana rejestru hscroll na odpowiadający nowemu położeniu znaków na ekranie, następowała dopiero przy następnym vblank interrupt (czyli hscroll był nadal 0, a ANTIC przez chwilę do następnego vbi wyświetlał znak przesunięty po zmianie adresu). Zmiana adresu pamięci i jednoczesne ustawienie hscroll przed jmp xitvbv usunęło problem i wszystko działa tak jak w książce…

Reasumując, Mads jest moim ulubionym cross-assemblerem i pewne jego cechy i funkcje bardzo mnie zachęcają do dalszych eksperymentów, jednak coraz większy widzę sens w programowaniu w Action! Przede wszystkim czytelność kodu jest o wiele większa i na pierdoły nie traci się wiele czasu (tutaj ten sam efekt w Action!). Ciekaw jestem jak sprawdzi się Action! + VBXE.

PS: putline i posxy pochodzą z LIBRARIES/stdio/lib mads. Możnaby jeszcze wyzerować pamięć obrazu, ale… X /C w SDX zrobi to za mnie ;).

Action! Jedno RUNTIME, wiele modułów.

To już chyba ostatni wpis  z „linkowaniem” za pomocą type lub cat, który jednak pokaże do czego może się przydać Symbol Table Lister.  Załóżmy, że sklejamy kilka kawałków/modułów w Action! Fajnie byłoby aby Runtime było dołączane tylko raz – wymyśliłem sobie, że skoro STL pokaże mi adresy procedur w Runtime, to można zrobić tak:

  • Uruchomić w monitorze R: „H1:STL.ACT”
  • Otworzyć w edytorze Ctrl+Shift+R H1:RUNTIME.ACT i dodać np. set 14=$8000 set $491=$8000
  • Przejść do monitora Ctrl+Shift+M, skompilować C, zapisać W „H1:RUNTIME.OBX”

W LISTING.TXT (patrz poprzedni wpis o STL) znajdziemy adresy:

PrintE……… $822C PROC(BYTE ARRAY)
PrintF……… $8430 PROC(BYTE ARRAY, CARD, CARD, CARD, CARD, CARD)

Więc w naszym programie możemy zdefiniować:

set 14=$8739
set $491=$8739

proc printf=$8430(byte array a, card b, card c,
                  card d, card e, card f)
proc printe=$822C(byte array a)

proc main()
   printf("%S%E", "Test")
   printe("Runtime")
   do od

Kompilujemy i zapisujemy np. jako TESTRT.OBX
Potem sklejamy cat RUNTIME.OBX TESTRT.OBX > TESTRT.XEX

Dzięki temu każdy z dołączanych kawałków binarnych będzie mniejszy, a dodatkowo kompilacja będzie trwać krócej, bo RT kompilowane będzie tylko raz. Szkoda, że kompilatora uruchomionego w emulatorze nie da się odpalać w skrypcie. Można by do tego napisać makefile albo skrypt w bashu…

Action! Kompilacja do pliku.

CMPTODSK.ACT z Action! wiki ma jeden mały błąd w linii

IF c>'Z THEN c = c & $5F FI

a brakujący include BLKIO.ACT za niedługo może być trudny do znalezienia. Wrzucam tu dla porządku, bo kompilacja do pliku to przydatna rzecz.

MODULE ; CMPTODSK.ACT
; Copyright (c) 1983
; by Action Computer Services
; All Rights Reserved
; version 1.0
; last modified October 22, 1984
; Compile to disk for ACTION!
; compiler. Note that all ARRAY
; declarations that generate storage
; must be before the first procedure
; declaration or else the address of
; the storage will not be setup
; correctly (all dimensioned ARRAYs
; which are not assigned an initial
; value except BYTE/CHAR arrays of
; size 256 or less). Local ARRAY
; declarations in the main PROC (last
; procedure in program) are also
; allowed. Note: there must be at
; least one PROC/FUNC in program.

; Output file name will be same name
; as program being compiled with
; extention .OBJ

; IF AN ERROR OCCURS DURING
; COMPILATION, YOU SHOULD USE
; "/" to close all open files:
; >/
; change dev in SPLEnd below to direct
; output to printer.

DEFINE STRING = "CHAR ARRAY"
DEFINE JMP = "$4C" ; JMP addr16
TYPE INSTR=[BYTE op CARD addr]
INSTR Segvec=$4C6
INSTR SPLvec=$4DD
INSTR MonCmd=$4FB
INSTR OldMon
BYTE oldDevice, curBank=$4C9
BYTE pf, Zop=$8A, tZop, dev
CARD curproc=$8E, code=$E
CARD codeBase=$491, codeSize=$493
CARD codeOff=$B5
CARD globals, gsize
CARD totalSize, codeStart
CHAR ARRAY cmdLine(0)=$590
BYTE ARRAY bank(0)=$D500
BYTE ARRAY zpage(32), temps(16)

PROC InitMon()
 ; add "/" command to monitor which
 ; closes channels 1-5 and warm
 ; starts cartridge.
 CHAR cmdchar=$591
 BYTE i, WARMST=$8
 DEFINE JMPI="$6C"
 ; make sure right command
 IF cmdchar#'/ THEN [JMP OldMon] FI
 bank(0) = 0 ; init library routines
 FOR i = 1 TO 5 DO
  Close(i)
 OD
 WARMST = 1
 [JMPI $BFFA] ; warm start cart.

INCLUDE "H1:BLKIO.ACT"

PROC Save()
 ; save state of variables used by
 ; both compiler and library routines
 bank(0) = 0 ; init library routines
 tZop = Zop
 MoveBlock(zpage, $B0, $1B) ; to $CA
 MoveBlock(temps, $5F0, 16)
RETURN

PROC Restore()
 ; restore state of variables used by
 ; both compiler and library routines
 CARD tcodeOff
 Zop = tZop
 tcodeOff = codeOff
 MoveBlock($B0, zpage, $1B) ; to $CA
 MoveBlock($5F0, temps, 16)
 codeOff = tcodeOff
 bank(curBank) = 0
RETURN

PROC WriteHdr()
 PutCD(5, $FFFF)
 PutCD(5, codeStart)
 PutCD(5, codeStart+totalSize-1)
 WriteBlock(5, globals, gsize)
RETURN

PROC WriteCode()
 codeSize = code - codeBase
 PrintD(dev, curproc)
 PrintD(dev, ": ")
 PrintCDE(dev, codeSize)
 totalSize = totalSize + codeSize
 WriteBlock(5, codeBase, codeSize)
 code = codeBase
 codeOff = codeOff + codeSize
RETURN

PROC SegEnd()
 Save()
 IF pf THEN ; print locals
  WriteCode()
 ELSE
  pf = 1
  globals = codeBase
  gsize = code - codeBase
  codeBase = code
  totalSize = gsize
  codeStart = globals + codeOff
  WriteHdr()
 FI
 Restore()
RETURN

PROC SPL() ; dummy proc for call below

PROC SPLEnd()
 CHAR c
 BYTE nxttoken=$D3, i, n, buf=$9B^
 CARD nxtaddr=$C9, start=$2E2
 STRING inbuf(0)=$5C8, name
 STRING out(17)
 DEFINE PLA = "$68",
 STA = "$8D"
 Save()
 dev = 0
 ; to get output to printer:
 ; dev = 4
 ; Close(4) Open(4, "P:", 8, 0)
 ; get output name
 IF nxttoken=30 THEN ; command line
  name = nxtaddr
 ELSE ; editor buffer
  name = inbuf
 FI
 ; see if device needed
 n = 0
 IF name(2)#': AND name(3)#': THEN
  out(1) = 'D out(2) = ': n = 2
 FI
 ; get name without extension
 FOR i = 1 TO name(0) DO
  c = name(i)
  IF c='. THEN EXIT FI
  IF c>'Z THEN c = c & $5F FI
  out(i+n) = c
 OD
 ; add extension
 out(i+n) = '.
 out(i+n+1) = 'O
 out(i+n+2) = 'B
 out(i+n+3) = 'J
 out(0) = i + n + 3
 PutE()
 Print("output file is ")
 PrintE(out)
 PutE()
 Close(5) Open(5, out, 8, 0)
 buf = 0 ; clear buf used by Open
 pf = 0 ; no proc decl yet
 ; JSR for return so that we come
 ; back here after compilation
 [
  PLA
  STA SPL+1
  PLA
  STA SPL+2
 ]
 SPL = SPL + 1 ; get right address
 Restore()
 SPL()
 Save()
 ; ignore space for arrays
 code = codeBase + codeSize
 WriteCode()
 PutCD(5, $2E2)
 PutCD(5, $2E3)
 PutCD(5, start)
 Close(5)
 Open(5, out, $C, 0)
 WriteHdr()
 Close(5)
 PutDE(dev)
 PrintCD(dev, totalSize)
 PrintDE(dev, " bytes of code")
 Restore()
 codeOff = 0
RETURN

; only code generated before Init is
; allocated space. Init will be
; garbage collected (well kind of).

PROC Init()
 CARD codeBlock, bsize, csize, nBlock
 CARD POINTER cur, next
 ; link in our routines
 Segvec.op = JMP
 Segvec.addr = SegEnd
 SPLvec.op = JMP
 SPLvec.addr = SPLEnd
 OldMon.op = MonCmd.op
 OldMon.addr = MonCmd.addr
 MonCmd.op = JMP
 MonCmd.addr = InitMon
 ; allocate our routine so it won't
 ; go away.
 codeBlock = codeBase - 4
 next = $80 ; AFbase
 DO
  cur = next
  next = next^
 UNTIL next=0 OR next=codeBlock OD
 IF next=0 THEN
  PutE() Put($FD)
  PrintE("I can't allocate space for your code")
  PrintE("You better Boot and try again!")
  RETURN
 FI
 ; assume we can split block
 csize = @codeBlock-codeBlock
 nBlock = next^
 bsize = next(1) - csize
 next = @codeBlock
 cur^ = next
 next^ = nBlock
 next(1) = bsize
 codeBase = next + 4
RETURN
MODULE ; BLKIO.ACT
; Copyright (c) 1983, 1984, 1985
; by Action Computer Services (ACS)
; This software may be incorporated in
; other software packages providing
; that this copyright notice is also
; incorporated as well.
; version 1.1
; last modified May 8, 1985
BYTE CIO_status
CHAR FUNC CIO=*(BYTE dev, CARD addr,
 size, BYTE cmd, aux1, aux2)
; see hardware manual for description
; of CIOV.
; IOCB# = dev
; ICCOM = cmd
; ICBA = addr
; ICBL = size
; ICAX1 = aux1
; ICAX2 = aux2
; ICAX1 and ICAX2 are not set if aux1=0
; The first byte of addr is passed to
; CIO in the A register. The status
; on return from CIO is stored in
; CIO_status. If status=$88 then
; EOF(dev) is set to a non-zero value.
; No other error checking is performed
; and the result of the CIOV call is
; returned as the result of this FUNC.
[$29$F$85$A0$86$A1$A$A$A$A$AA$A5$A5
$9D$342$A5$A3$9D$348$A5$A4$9D$349
$A5$A6$F0$8$9D$34A$A5$A7$9D$34B$98
$9D$345$A5$A1$9D$344$20$E456
$8C CIO_status$C0$88$D0$6$98$A4$A0
$99 EOF$A085$60]
CARD FUNC ReadBlock=*(BYTE dev,
 CARD addr, size)
; Reads size bytes from dev into addr.
; Returns number of bytes read (may
; be < size if EOF). Set EOF flag if
; EOF is encountered. Status is
; saved in CIO_status.
[$48$A9$7$85$A5$A9$0$85$A6$A5$A3$5$A4
$D0$6$85$A0$85$A1$68$60$68$20 CIO
$BD$348$85$A0$BD$349$85$A1$60]
PROC WriteBlock=*(BYTE dev,
 CARD addr, size)
; Writes size bytes from addr to dev.
; Status is saved in CIO_status.
[$48$A9$B$85$A5$A9$0$85$A6$A5$A3$5$A4
$D0$2$68$60$68$4C CIO]
PROC PutCD=*(BYTE chan, CARD n)
 BYTE c=$AA, lo=$AB, hi=$AC
; save args
 [
 $85 c
 $86 lo
 $84 hi
 ]
; PutD(c, lo)
; PutD(c, hi)
 CIO(c,lo,0,11,0)
 CIO(c,hi,0,11,0)
RETURN
CARD FUNC GetCD(BYTE chan)
 CARD out
 BYTE lo=out, hi=out+1
; lo = GetD(chan)
; hi = GetD(chan)
 lo = CIO(chan,0,0,7,0)
 hi = CIO(chan,0,0,7,0)
RETURN(out)
MODULE ; for user

Działa to podobnie jak symbol table lister:

  • uruchamiamy CMPTODSK.ACT w monitorze (bez ładowania do edytora):
    Ctrl+Shift+M, R „H1:CMPTODSK.ACT”
  • wychodzimy do edytora, ładujemy nasz program Ctrl+Shift+R, H1:PLIK.ACT
  • kompilujemy Ctrl+Shift+M, C
  • skompilowany plik binarny zostaje zapisany pod nazwą H1:PLIK.OBJ

Teoretycznie to kolejny sposób na małą ilość pamięci i kompilowanie większych kawałków kodu Action!

Dyskietka auto-bootująca.

Wymyśliłem sobie, żeby z poziomu modułu głównego programu dogrywać kolejne fragmenty programu lub wręcz uruchamiać kolejne binarki. Wszystko super, loader z poprzedniego wpisu po wskazaniu odpowiedniego initad działał, ale zacząłem się zastanawiać jak zrobić obraz atr, w którym taki loader będzie automatycznie startował. Znalazłem sporo programów które to umożliwiają, żaden nie zadziałał. Nawet picoboot poległ na pliku złożonym z kilku sklejonych catem segmentów.

Rozwiązanie okazuje się banalnie proste.

Sparta Dos 3.2:

  • tworzymy pusty obraz dyskietki w emulatorze
  • inicjujemy DOS za pomocą XINIT
  • kopiujemy loader.xex na tą dyskietkę jako AUTORUN.SYS
  • kopiujemy xexy doładowywane przez loader/autorun.sys

Uruchomienie Sparty jest jednak dość powolne, a idealnie sprawdził się tutaj TurboDos XE:

  • tworzymy pusty obraz dyskietki w emulatorze
  • formatujemy np: FMD 2:  tu jest ściągawka
  • przechodzimy na 2: i kopiujemy pliki systemowe za pomocą INI
  • kopiujemy loader jako AUTORUN.SYS
  • kopiujemy programy ładowane przez loader

Co ciekawe taki autorun startuje naprawdę błyskawicznie.