Ready64 Forum
Commodore 64 => Programmazione, Grafica e Musica => Topic aperto da: antoniomauro - 11 Ottobre 2016, 10:57:55
-
Salve ragazzi,
volevo aggiungere un piccolo programma scritto con dasm,un caricamento simile a quello che si vedevano nei giochi in cassetta:
- Visualizzazione immagine
- raster bar durante il caricamento
- eventuale musica
Qualcuno può indirizzarmi verso qualche documento/tutorial?
-
Ciao Antonio,
Intanto puoi dare un'occhiata a questo tool (http://csdb.dk/release/?id=118713), ed eventualmente alla relativa discussione (http://csdb.dk/forums/?roomid=12&topicid=98026) nel forum di CSDb. In altenativa c'è quest'altro tool: Dreamload (http://csdb.dk/release/?id=6093) (versione del 2007 (https://sourceforge.net/projects/rrtools/files/dload/), compatibile anche con la SD2IEC). Entrambi i programmi sono provvisti di documentazione esplicativa ed esempi.
-
Avevo visto quei loader ma li avevo scartati perchè non ho ben capito come compilarli (Jam?)
Preferire utilizzare qualcosa compilabile con dasm (tipo ocean freeload) ma se riesco a far andare questi va bene lo stesso! :)
-
Prima di tutto bisogna capire se vuoi caricare da disco o da nastro.
Te lo chiedo perchè, inizialmente parli di tape, poi sembrano interessarti i software che ti ha elencato Raffox, ma poi torni a nominare il Freeload che è un turbo tape...
Fatta chiarezza su questo punto, tieni presente che qualsiasi strada decidi di percorrere, non c'è niente di -facile- o -scontato-: entrambi gli argomenti richiedono una discreta padronanza dell'assembler e conoscenza della macchina.
Se il tuo problema è solo quello di visualizzare dei "colori" ed una schermata grafica durante il load (quindi niente turbo o robe simili), il tutto si può fare abbastanza facilmente in assembly ma, anche qui, devi avere un infarinatura delle routine I/O e sapere, almeno, come si visualizza una schermata grafica (koala o simili...)
-
Innanzi tutto grazie per l'interessamento!
Non mi definisco un guru ma ormai credo di avere una discreta preparazione sulla programmazione assembler (C64/6502)....
Detto questo, mi interesserebbe approfondire principalmente il caricamento "turbo tape" partendo da un sorgente compilato con dasm + exomizer -sfx. Avevo puntato sul Freeload perchè mi sembrava il più adatto ma sono ovviamente aperto a qualsiasi alternativa.
In seconda battuta anche il caricamento da disco dello stesso prg, sfruttando un loader che mi consenta di visualizzare un'immagine, delle raster bar ed eventualmente della musica di sottofondo.
Non mi aspetto una soluzione "facile o scontata" ma vorrei fare un po di chiarezza sull'argomento per poter ottenere il risultato desiderato con cognizione di causa!
-
Ciao!
Per quanto riguarda il nastro, potresti optare per Tape Master Pro (http://csdb.dk/release/?id=147472) di Richard Bayliss. Non so quanto ti convenga imbarcarti nell'impresa di progettare un sistema tutto tuo. Comunque qui trovi una spiegazione approfondita sulle tecniche più usate: Analyzing Loaders (http://c64tapes.org/dokuwiki/doku.php?id=analyzing_loaders) (articolo di Luigi Di Fraia, probabilmente il massimo esperto nazionale in materia). Tempo fa ho dato un'occhiata al famoso Freeload e mi pare di ricordare che per la musica si è costretti ad utilizzare la routine predisposta, il che significa doverla scrivere in modo testuale seguendo la particolare sintassi prevista.
Per il disco non saprei, ma se fossi in te cercherei di adottare un sistema che non tagli fuori i dispositivi IEC generici come la SD2IEC. Ricordo che anni fa apparve su CSDb un loader che utilizzava le routine standard ma consentendo comunque di visualizzare degli effetti durante il caricamento. Ma purtroppo non ricordo il titolo e sarebbe un'impressa ritrovarlo.
-
Ricordo che anni fa apparve su CSDb un loader che utilizzava le routine standard ma consentendo comunque di visualizzare degli effetti durante il caricamento. Ma purtroppo non ricordo il titolo e sarebbe un'impressa ritrovarlo.
Trovato: Testrun by Meta (http://csdb.dk/release/?id=94192) ma manca il sorgente...
-
Perfetto... allora prendiamo il Freelooader che è, originariamente, per DASM.
Faccio qui un discorso abbastanza breve (per quanto possibile), poi dimmi tu cosa approfondire... se ne senti il bisogno.
Partiamo dall'inizio: il freeloader è composto da 2 parti. Il "loader" che può essere multi o single load, e il saver.
Il multiload è "un pezzo in più" rispetto al single... nel senso che serve tutto il necessario per il single load, più un altra porzione di codice con il multiloader da inserire in ciascuna parte del programma che necessita di ulteriori caricamenti dal nastro...
Ma procediamo con ordine... si prende il loader e lo si compila, chiamando il file eseguibile risultante "A".
"A" perchè è sempre il primo file caricato dalla routine di "boot strap" (passami il termine) del loader stesso.
Prima di compilare il loader bisogna settare alcuni parametri:
RESETVECS EQU NO ;should the IO vectors get reset
GAMESTART EQU $080D ;game start here
ONEVAL EQU $37 ;the value that DDR A is set to
SCREENCOL EQU 0 ;screen colour when bitmap is on
BORCUL EQU 0 ;border colour when bitmap is on
LOAD_FLAG EQU 2 ;load in progress flag
MESS EQU $FE ;indirect address of scrolling text
FILE_COUNTER EQU $0100+3 ;which file we are up to
MUSIC_TRIGGER EQU $0101+3 ;music triggering flag
SCROLL_TRIGGER EQU $0102+3 ;scroll triggering flag
SMOOTH_X EQU $0103+3 ;smooth x position for hardware
STACK_LOAD EQU $0112 ;loader's position on stack
REFRESH EQU $B4A3 ;Jon's sound refresh
TUNE EQU $B43E ;Jon's tune initialise
LOADER_MAX EQU $0C40 ;maximum address of loader
...che evito di spiegare uno per uno... se hai dubbi chiedi.
Poi bisogna settare i "files triggers", cioè le azioni che farà il loader dopo aver caricato ogni file:
FILE_TRIGGERS dc.b 00 ;overload (A)
dc.b 02 ;music (C)
dc.b 00 ;colour ram (D)
dc.b 00 ;screen colour (E)
dc.b 01 ;bitmap (F)
dc.b 03 ;code (G)
dc.b 04 ;code (H)
dc.b 00 ;code (I)
dc.b 00 ;code (J)
dc.b 05 ;overload (A)
ROUT_LOOKUP dc.w ROUT_LOOKUP ;dummy
dc.w BITMAP_ON ;01 (this also turns the scroll off)
dc.w TUNE_ON ;02
dc.w BITMAP_OFF ;03
dc.w TUNE_OFF ;04
dc.w FIRE_UP_STACK ;05
dc.w SCROLL_ON ;06
dc.w SCROLL_OFF ;07
Questa sequenza significa:
- carica il primo file e non fare niente (0 = dummy)
- carica il secondo file ed inizializza la musica
- carica terzo e quarto file ma non fare niente
- carica il quinto e visualizza l'immagine
- carica il sesto e "spegni" l'immagine
- carica il settimo e "spegni la musica"
- carica l'ottavo e il nono senza fare niente
- carica il decimo ed esegui.
Eventualmente, più avanti nel codice, c'è lo scrolltext da editare...
Poi bisogna editare il sorgente del saver, per fargli sapere quali files caricare, le zone di memoria che occupano, e l'indirizzo di partenza del LOADER caricato...
I -parametri- si tovano qui:
;-----------------------------------------------------------------------------
; Freeload file data
;
; WHICHDISK & FLNAM are read backwards !
;-----------------------------------------------------------------------------
HOWMANY EQU 14
FILEDATA dc.w $0800,$0C40 ;A Freeloader control software
dc.w $4000,$5000 ;B $D000-$E000
dc.w $0800,$0C40 ;A Overload of control software
dc.w $B43E,$C800 ;C Music
dc.w $4000,$43FF ;D Colram
dc.w $C800,$CBFF ;E Scrcol
dc.w $E000,$FF40 ;F Bitmap
dc.w $0C40,$B43E ;G Game Code
dc.w $C800,$CFFF ;H Game Code
dc.w $E000,$FFFA ;I Game Code
dc.w $0200,$02A6 ;J Stack destroyer
dc.w $0800,$0C40 ;A Overload again !
dc.w $B43E,$C800 ;K Game Code
dc.w $0400,$0C40 ;L Game Code
FLNAM dc.b "LKAJIHGFEDCABA"
WHICHDISK dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0
STARTUP EQU $0800
Nota bene: gli indirizzi di inizio e fine di ciascun file sono ripetuti ogni volta che il file viene caricato. Ogni file ha un nome che corrisponde ad una sola lettera.
L'ordine di caricamento è scritto a FLNAM in ordine INVERSO... cioè "LKAJIHGFEDCABA" significa che verrà caricato il file A (il loader), poi il file "B", poi nuovamente il file "A", poi il "C"... e via discorrendo.
WHICHDISK invece serve se i files da salvare su nastro sono contenuti in più dischi. In questo caso, indicando in corrispondenza di ciascun file il numero del disco di appartenenza, verrà chiesto un cambio disco durante la fase di save.
STARTUP è l'indirizzo di start del nostro LOADER.
Una volta compilato, occorre preparare i files da "masterizzare" su nasto con i nomi corretti che abbiamo scelto per loro.
Dopodichè si prepara un bel disco contenente il saver, il loader e tutti i files, lo si mette nel drive, si esegue il saver e si seguono le istruzioni a video.
Se tutto va bene, avremo il nostro programma masterizzato su nastro, con la pic, la musica, lo scrolltext e le "barre colorate".
Penso che per ora... possa bastare.
Fammi sapere come procede.
-
Grande!
Ho fatto una prima prova (fallimentare) ma almeno ho cominciato a capire come muovermi....
Per cominciare con una cosa semplice ho impostato nel loader un solo elemento in "FILE_TRIGGERS" che dovrebbe essere il mio demo:
FILE_TRIGGERS
dc.b 05 ;overload (A)
Se ho capito bene il valore 05 dovrebbe appunto corrispondere a: "Carica ed esegui"
Nel saver invece due righe:
HOWMANY EQU 2
FILEDATA dc.w $0800,$0C0E ;A Freeloader control software
dc.w $0801,$E379 ;A Overload of control software
Le locazioni le ho recuperate in fase di compilazione.
Qui la prima domanda:
E' lecito definire in FILEDATA locazioni sovrapposte?
Posso ricompilare eventualmente il loader e spostarlo un po più su oppure devo riorganizzare il mio codice per liberare da $0800 a $0C0E?
Dopo aver generato il TAP (con vice) parte il caricamento con righe colorate e testo "RAINBOW" (non l'ho modificato nel saver) ma, dopo 8 giri di nastro,appare lo scroller (vuoto) e l'emulatore lancia un errore: "Main CPU: JAM at $0849"
-
Per cominciare con una cosa semplice ho impostato nel loader un solo elemento in "FILE_TRIGGERS" che dovrebbe essere il mio demo:
FILE_TRIGGERS
dc.b 05 ;overload (A)
Se ho capito bene il valore 05 dovrebbe appunto corrispondere a: "Carica ed esegui"
Durante i miei test ha sempre funzionato usando uno $00 per A come primo valore... quindi:
FILE_TRIGGERS
dc.b 00 ; dummy (A)
dc.b 05 ; tuodemo (B)
Come intuisci, il filename del loader è A e quello del tuo demo è B.
Ma POTREBBE ESSERE che funzioni solo specificando B... ma serve un test per saperlo. Dai sorgenti pare che si debba specificare anche il dummy per il loader.
E' lecito definire in FILEDATA locazioni sovrapposte?
No... il file da caricare NON si deve sovrapporre al loader.
Riprova che dovremmo esserci...
-
Ciao F,
anche su lemon64 (dove avevo postato una richiesta d'aiuto tempo fa) mi hanno suggerito di utilizzare solo il saver impostando un solo file (il programma da eseguire)
Mi hanno anche fornito un d64 con saver e programma che, una volta eseguito, genera il tap funzionante, quindi ti confermo che può funzionare anche cosi!
Purtroppo credo che il mio problema sia proprio nella definizione degli indirizzi (start-end) del mio prg e della locazione di start:
FILEDATA dc.w $0801,$16E2 ;A Overload of control software
FLNAM dc.b "A" ;Ordine inverso
WHICHDISK dc.b 0
STARTUP EQU $080D
Mi hanno suggerito di caricare il mio prg con una cartuccia tipo action replay per verificare start ed end address ma non ci sono riuscito....
Questa è la parte iniziale del mio codice (comando basic con il sys e locazione di partenza):
org $0801
include "lib\_basicline.asm" ;sys command
org $080D ;Inizio del programma
L'indirizzo "end" lo recupero in fase di compilazione con il dasm ma probabilmente è qui che sbaglio...
-
A me sta cosa del loader che NON va specificato NON torna. Per niente.
Compila il loader, diciamo a $C000.
Segnati l'indirizzo finale.
Chiamalo "A" e il tuo file chiamalo "B".
Configura il SAVER di conseguenza.
NOTA BENE:
Dovrai mettere l'indirizzo di esecuzione del LOADER nel saver e l'indirizzo di esecuzione del tuo programma nel LOADER.
PS: da quel che vedo, gli indirizzi li prendi correttamente... quindi non è quello il problema.
Questa è una configurazione funzionante che ho ritrovato fra i miei files di lavoro:
;---------------------------------------
; Freeload file data
; WHICHDISK & FLNAM are read backwards !
;-------------------
HOWMANY = $02
FILEDATA
.WORD $C000,$C117 ; A Freeloader control software
.WORD $0801,$4890 ; B Game
FLNAM
.TEXT "BA" ; BACKWARDS !!!
WHICHDISK
.BYTE $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
STARTUP = $C000 ; Freeload control software start address
dalla quale si evince anche che l'indirizzo di caricamento e di esecuzione del loader sono uguali...
-
Devo sicuramente riprovare ad utilizzare il loader per beneficiare delle utili funzionalità esposte (musica,bitmap,ecc...).
Ieri sera intanto ho fatto un po di test semplificando al massimo tutto per capire dove il flusso si interrompe.
- Caricando direttamente con il saver un piccolo prg liscio tutto funziona.
- Utilizzando un prg exomized (sfx $080d), il file viene caricato ma al momento dell'esecuzione comincia a fare il decrunch ma dopo meno di un secondo il nastro riparte e va in crash....
- Utilizzando il prg exomized (non so con che parametri) che mi hanno passato su lemon64 tutto funziona correttamente compreso il decrunch (il nastro si ferma)
A questo punto mi viene logico pensare che il problema sia, o nei parametri da passare ad exomizer , oppure nella configurazione di FILEDATA/STARTUP nel saver...
Che ne pensi?
-
Penso che invece di parlare per niente e andare per presupposti, era ora che mi "sporcassi le mani" per vedere un po' quali problemi ci sono nell'usare il codice DASM rilasciato.
Ti premetto che io uso il 64tass, quindi ho dovuto convertire il sorgente in -qualcosa- di compilabile per il mio compilatore.
Ho notato una cosa, che può essere solo un mio problema con il 64tass, perchè NON so come si comporta il DASM.
La seguente porzione di codice del SAVER:
FILEDATA
.WORD $C000, $C118 ; A Freeloader control software
.WORD $0801, $19CF ; B Game
viene compilata dal 64tass come:
$C0, $00, $C1, $18, $08, $01, $19, $CF
ma il codice del SAVER si aspetta l'ordine basso/alto dei bytes, cioè:
$00, $C0, $18, $C1, $01, $08, $CF, $19
quindi verifica l'esattezza di questa cosa, prima di tutto.
Poi, nei miei precedenti esperimenti, avevo usato la versione MULTILOAD che non implementa alcuna automazione per la visualizzazione delle Pictures, per la musica o per lo scrolltext, ma si limita a caricare un file da nastro dato "un numero" che l'identifica.
Anche qui la questione non è chiara: il "numero che identifica" dovrebbe essere il numero del file da caricare partendo da quello attuale.
Esempio veloce: carichiamo il primo file su nastro, lo eseguima e al termine dell'esecuzione dobbiamo caricare il secondo file: specifichiamo sempre 1 come numero del file da caricare... cioè "non saltare" alcun file, ma carica subito.
Ma questo è un altro discorso... che ho fatto per dire che con il "multiloader" riesco a creare TAP funzionanti, mentre con il SINGLE loader (che è quello con lo scrolltext, gli effetti etc... etc... ho qualche problema anch'io).
Un esempio di TAP funzionante è questo (http://dl.dropboxusercontent.com/u/93655104/ready_test_tap.tap).
Altro dettaglio è la "lunghezza" dei files da salvare su nastro: il valore corretto da usare è quello riportato dalla cartuccia Action Replay (per esempio) e non quello riportato dal compilatore.
Esempio: il mio loader occupa la ram da $C000 a $C117.
Se lo carico con l'ActionReplay, la cart riporta $C000-$C118, mentre il compilatore riporta la prima coppia di indirizzi.
Il saver funziona correttamente solo se gli si "passa" la versione con "un byte in più" della ram realmente occupata dal codice.
Per tornare al LOADER... il codice della versione "mono" è altamente customizzata per qualche tipo di software che l'autore stava sviluppando...
Infatti nel bel mezzo del codice c'è:
;---------------------------------------
; RELOCATE - Relocates code from
; $4000 to $D000
;-------------------
RELOCATE
SEI
LDA #$30
STA $01 ; relocate code
LDY #$00
LDX #$10
TLOP
LDA $4000,Y
TO
STA $D000,Y
INY
BNE TLOP
INC TLOP+$0002
INC TO+$0002
DEX
BNE TLOP
LDA #$35
STA $01
CLI
LDA #$60 ; self modifying CLI to RTS
STA $02D4
JMP $02A7 ; re-initialise the loader
richiamato in questo punto
LOAD_D000
JSR CHECKSTOP
LDX LOAD_FLAG ; $4000 relocating up to $D000
BEQ LOAD_D000
INX
STX LOAD_FLAG
JSR RELOCATE ; relocate code to $D000
ma non è di alcuna utilità in un programma generico...
Poi c'è la parte per rilevare le "expert cartridge" che è pressochè inutile oggi.
Nei miei tests riesco ad eseguire lo scrolltext, caricare le pic, suonare la musica... ma NON ad eseguire correttamente un programma...
L'ultima porzione del caricamento viene gestita da un loader nello stack pointer, cioè quando il loader incontra il "trigger" per il FIRE_UP_STACK, butta nello stack il codice e lo esegue. Questo codice carica ancora almeno un file e poi, dopo alcune operazioni, salta all'indirizzo di partenza specificato in fase di compilazione...
Non riesco a capire se sia più utile studiare la versione "single load" per "rimetterla in funzione" o crearne una nuova usando il "multiloader"...
Confesso che il passaggio DASM -> 64Tass ha creato qualche difficoltà...
Tu sei riuscito ad ottenere risultati migliori?
-
Ciao F,
ieri ho avuto poco tempo ed ho solo fatto qualche test utilizzando solamente il metodo "saver+mio prg".
Sono riuscito a far caricare con successo un semplice programma ed anche un gioco (exomized) che mi hanno passato su lemon64.
Tuttavia testando il tutto con il mio demo completo ho incontrato diversi problemi:
- Il decrunch termina, il codice sembra correttamente caricato ma al momento dell'esecuzione non va...
- Gran parte dei dati caricati tra $2187 e $4ce9 sono corrotti (in pratica tutto il charset)
- Anche la musica messa su $A000 suona storpiata
- Altre locazioni non le ho controllate....
A questo punto credo che, per far funzionare questo metodo,sia necessario rispettare un particolare setup della memoria.
Io ho adottato questo:
;$DD00 = %xxxxxx10 -> bank1: $4000-$7fff
;$D018 = %0000xxxx -> screenmem is at $0000
;$D018 = %xxxx001x -> charmem is at $0800
musica: $A000
dati extra $D000 <-> $FFFF (switching $01)
ps:
Non riesco a trovare un'immagine di action replay funzionante su VICE che mi mostri "start,end address" in fase di caricamento....
Me ne indicheresti una?
-
Piccolo aggiornamento:
Dopo una serie di test sono sicuro al 99% che il freesaver +prg non riesce a caricare prg che vanno sulla memoria IO e Kernel (dopo la fase di decrunching ovviamente).
Ho compilato diversi prg e, se provo a mettere qualsiasi cosa in quello spazio di ram, non funziona più nulla...
Voglio sicuramente approfondire il metodo freesaver + freeloader +prg che probabilmente non soffrirà di tale limitazione!
Nel mentre ho provato questo fantastico script in pyton: http://csdb.dk/release/?id=108580 (http://csdb.dk/release/?id=108580) che funziona senza alcun problema!
-
Innanzi tutto, l'immagine CRT della AR6 la puoi scaricare da qui. (https://dl.dropboxusercontent.com/u/93655104/Action_Replay_V6.0_6.0_1989_PAL.crt)
Poi ti confermo tutti i miei sospetti: il codice DASM originale del loader contenente le subroutine per la gestione dello scrolltext, grafica e musica, contiene una MONTAGNA DI FUFFA.
Sono partito dal mio "multiloader" e ho ricostruito un loader concettualmente identico, ma con codice nuovo.
Ne trovi un esempio con musica e scrolltext scaricabile da qui (https://dl.dropboxusercontent.com/u/93655104/freeload_test.tap).
Da notare che il mio codice non compie nessuna "raffinatezza" nel codice d'uscita: setta $01, "spegne" il SID e salta brutalmente all'indirizzo di partenza del programma linkato.
Ho semplificato molto le cose: un trigger per ogni file che viene attivato DOPO il load del file stesso (eh...si... prima si carica la musica e poi la si esegue... oppure prima si carica un file e poi si fa partire lo scrolltext...).
Non riesco a capire perchè l'autore originario l'abbia pensata diversamente, ma io mi limito a lanciare l'esecuzione dopo il caricamento delll'ultimo file.
A quel punto si presuppone che tutto sia in memoria e che si possa andar tranquilli...
Cose da sistemare: resettare ai valori di default i registri CIA e Vettori IRQ prima di lanciare il programma caricato. Il codice originale DASM, fra i vari macelli che fa, non si preoccupa minimamente di ripristinare le cose e, molto probabilmente, i problemi che hai "post loading" sono dati dai vettori IRQ che puntano lanciati verso il nulla cosmico.
(Quando sarò soddisftatto di come funziona posto anche una versione completa... ma per ora:)
-Nucleo principale del mio loader-
;-------------------
JSR INIT_TURBO
LDY #FILES_TO_LOAD
STY FILE_N_BUFFER
JSR TURBO_LOAD
;-------------------
LDA #PROGRAM_01
STA $01
JSR $E544
JMP PROGRAM_START
Cioè: "quanti files devo caricare?", "Ok, li carico", "...bene... ho finito di caricare, setto $01 e lancio il programma".
"Main" part che gestisce il caricamento dei files, -interfacciandosi- col codice che gira in IRQ:
;---------------------------------------
; TURBO_LOAD
; Entered with "Y" equals number of files
; to load
;-------------------
TURBO_LOAD
BIT $D011
BPL TURBO_LOAD
TURBO_WAIT
BIT $D011
BMI TURBO_WAIT
;-------------------
MUSIC_FLAG = *+$0001
LDA #$00
BEQ MUSIC_DISABLED
JSR MUSIC_PLAY
MUSIC_DISABLED
;-------------------
SCROLL_FLAG = *+$0001
LDA #$00
BEQ SCROLL_DISABLED
JSR SMOOTH_SCROLL
LDA $D016 ; do the hardware x scroll
AND #%11111000
SMOOTH_X = *+$0001
ORA #$00
STA $D016
;-------------------
SCROLL_DISABLED
LDX LOAD_FLAG ; wait for nonzero ($FF) loadflag value
BEQ TURBO_LOAD
INX ; reset loadflag
STX LOAD_FLAG
;-------------------
ACTUAL_FILE = *+$0001
LDX #$00
LDA FILE_TRIGGERS,X ; see if anything is required to happen
BEQ NO_TRIGGER
ASL
TAX
LDA ROUT_LOOKUP,X ; do any routines required
STA JUMPVEC_1+$0001
LDA ROUT_LOOKUP+$0001,X
STA JUMPVEC_1+$0002
JUMPVEC_1
JSR $DEAD ; self modified
;-------------------
NO_TRIGGER
INC ACTUAL_FILE
FILE_N_BUFFER = *+$0001
LDY #$00
DEY
STY FILE_N_BUFFER
BNE TURBO_LOAD
Come vedi, niente di trascendentale:
Soliti BIT $D011 per sincronizzarsi al VB (al posto di quel macello di CMP e OVERLAY che usa l'originale), semplici FLAGS per lanciare musica, scrolltext e quant'altro, e lo stesso codice di TRIGGERING.
Ovviamente oltre a questo, c'è il codice di INIT dell'IRQ e il codice IRQ vero e proprio, che è lo stesso dell'originale.
Quindi il "SAVER" funziona correttamente... i problemi li crea tutti il LOADER.
-
Ecco qui il loader con il nuovo codice che implementa tutte le subroutine, musica, scrolltext e grafica:
Freeload Test Tape (https://dl.dropboxusercontent.com/u/93655104/ready_test_tap-2.tap)
-
Che dire... La tua competenza è davvero degna di nota!
Per quanto riguarda l'AR ho provato a caricare un prg ma non vedo sti' benedetti address!
Con il vice:
- Inserisco la cartuccia
- F7 per installare fastload
- LOAD "A",8,1
- niente indirizzi....(allego foto)
Per il freeload, mentre attendo con pazienza un eventuale rilascio del tuo sorgente modificato, approfitto per chiederti un chiarimento:
Considerando che ho un demo che parte da $0801 ed occupa un bel po di ram, che limitazioni ci sono nella rilocazione del loader? Posso compilarlo anche in un'area che poi verrà sovrascritta dal gioco vero e proprio, oppure devo riservare uno spazio "sicuro per il loader"?
-
Per l'action replay devi abilitare la True Drive Emulation (emulazione hardware dei drives), poi vedrai che ti funziona.
Per la seconda domanda: niente deve sovrascrivere il loader che, comunque, carica anche sotto le rom e forse anche a $Dxxx... ma di questo non sono sicuro al 100% perchè ricordo che il codice modifica $01 durante il load, ma non ho presente bene per cosa al momento...
Il mio codice lo rilascio appena ho finito di controllare una cosa: nonostante io resetti tutto quello che riguarda gli irq, succede di ritrovarsi in esecuzione del codice nello stack... ma non ho capito bene ancora da cosa dipende... se è dovuto proprio alla gestione degli indirizzi nello stack stesso oppure se resta qualche irq/nmi spurio che sopravvive anche dopo l'uscita dal loader...
-
Ok! intanto grazie ancora per i numerosi spunti!
-
Eccolo qua.
Versione 64Tass...
Probabilmente migliorabile ma... almeno funziona come dovrebbe.
Nel caso ci siano errori od omissioni... mi corriggerete.
:)
;-------------------------------------------------------------------------------
; FREELOAD FlavioWeb custom version 1.0
;-------------------------------------------------------------------------------
; Based ond Freeload Version 5.0
; (c) Paul Hughes 01.01.1989
; Custom version by Flavioweb 2016
;-------------------------------------------------------------------------------
; To use
;
; Set contants:
; PROGRAM_START = Start address of loaded program
; MUSIC_INIT = Sid tune initialization address (if used)
; MUSIC_PLAY = Sid tune play address (if used)
; ------------------
; Set FILE_TRIGGERS with one trigger per file to load.
; If a file don't need a trigger, leave it at $00.
; Edit your scrolltext ad well...
;
; Picture details:
; Color RAM data: $C400
; Screen RAM data: $C800
; Bitmap data: $E000
;---------------------------------------
; Constants
;-------------------
HEADER_BYTE = $40 ; Header byte value
HEADER_END = $5A ; Header end byte value
LOADER_START = $C000 ; This loader start address
PROGRAM_START = $080D ; Loaded program start address
MUSIC_INIT = $A600 ; Sid tune Init address
MUSIC_PLAY = $A603 ; Sid tune Play address
CLEAR_BITMAP_FLAG = $01 ; Clear Bitmap area $E000-$FF40 at start.
BITMAP_ADDRESS = $E000 ; Picture Bitmap data address
COLOR_ADDRESS = $C400 ; Picture Color RAM data address
SCREEN_ADDRESS = $C800 ; Picture Screen RAM data address
;---------------------------------------
; VARIABLES
; Variables used by cassette loader,
; MUST follow contiguously
;-------------------
ZP = $10
LOAD_ADDR = ZP ; loader data start
LOAD_END = ZP+$02 ; loader data end
VERIFY = ZP+$03 ; saved checksum
CHECKSUM = ZP+$04 ; checksum value
BIT_COUNT = ZP+$05 ; bit store
LOAD_FLAG = ZP+$06 ; loader monitor flag
;---------------------------------------
; Loader starts here...
;-------------------
*= LOADER_START
START
LDX #$37
STX $01
JSR $E544
LDX #$FF ; reset the stack
TXS
INX
STX $D020 ; screen & borders black
STX $D021
TXA
BLANK_ATTR
STA $D800,X ; blank the attributes
STA $D900,X
STA $DA00,X
STA $DB00,X
INX
BNE BLANK_ATTR
LDX #$27
SET_LINES
LDA #$01
STA $D800+$17*$28,X ; set attributes for scrolling
LDA #$07
STA $D800+$16*$28,X ; set attributes for dividers
STA $D800+$18*$28,X
LDA #$40 ; print dividers
STA $0400+$16*$28,X
STA $0400+$18*$28,X
LDA #$20
STA $0400+$17*$28,X
DEX
BPL SET_LINES
;-------------------
LDA CLEAR_BITMAP_FLAG ; If this flag is selected, then before
BEQ DO_NOT_CLEAR ; loader starts, ram between $E000 and $FF40 is
JSR CLEAR_BITMAP ; cleared to avoid loader -slow down-
DO_NOT_CLEAR
;-------------------
JSR INIT_TURBO
LDY #FILES_TO_LOAD
STY FILE_N_BUFFER
JSR TURBO_LOAD
;-------------------
SEI
LDX #$FF
TXS
LDA #$37
STA $01
;-------------------
JSR TUNE_OFF
LDA #$00
STA $0286
STA $D020
STA $D021
JSR $E544
LDX #$1F
JSR $E5AA
LDX #$05
IRQ_VEC_LOOP
LDA $FD30,X
STA $0314,X
DEX
BPL IRQ_VEC_LOOP
;-------------------
LDA #$81
STA $DC0D ; Re-enable IRQs
LDA $DD0D ; Re-enable NMIs
LDA #$11
STA $DC0E ; Setup IRQ
LDA #$97
STA $DD00 ; Default VICII-Bank
LDX #$1B
STX $D011
;-------------------
CLI
JMP PROGRAM_START
;---------------------------------------
; INIT_TURBO - Initialises Freeload
;-------------------
INIT_TURBO
SEI
LDA #$00
STA LOAD_FLAG ; Reset load flag
STA BIT_COUNT ; Reset bit count
STA $D01A ; Halt rasters
LDA #$7F ; Latch interrupts
STA $DC0D
STA $DD0D
LDA $DC0D ; Unlatch interrupts
LDA $DD0D
ASL $D019
LDA #$05 ; ROMS's out cassette motor on
STA $01
LDA #$68
STA $DC04 ; Set CIA #$01 Timer A countdown time
LDA #$03
STA $DC05
LDA #$90
STA $DC0D
LDA #<LOADER_IRQ
STA $FFFE ; Point the interrupt vector to loader
LDA #>LOADER_IRQ
STA $FFFF
CLI
RTS
;---------------------------------------
; TURBO_LOAD
; Entered with "Y" equals number of files
; to load
;-------------------
TURBO_LOAD
BIT $D011 ; Vertical Blank Sync
BPL TURBO_LOAD
TURBO_WAIT
BIT $D011
BMI TURBO_WAIT
;-------------------
MUSIC_FLAG = *+$0001
LDA #$00 ; Should i play some noise?
BEQ MUSIC_DISABLED
JSR MUSIC_PLAY
MUSIC_DISABLED
;-------------------
SCROLL_FLAG = *+$0001
LDA #$00 ; Should i display some text?
BEQ SCROLL_DISABLED
JSR SMOOTH_SCROLL
LDA $D016 ; Do the hardware x scroll
AND #%11111000
SMOOTH_X = *+$0001
ORA #$00
STA $D016
;-------------------
SCROLL_DISABLED
LDX LOAD_FLAG ; Wait for nonzero ($FF) loadflag value
BEQ TURBO_LOAD
INX ; Reset loadflag
STX LOAD_FLAG
;-------------------
ACTUAL_FILE = *+$0001
LDX #$00
LDA FILE_TRIGGERS,X ; See if anything is required to happen
BEQ NO_TRIGGER
ASL
TAX
LDA ROUT_LOOKUP,X ; Do any routines required
STA JUMPVEC_1+$0001
LDA ROUT_LOOKUP+$0001,X
STA JUMPVEC_1+$0002
JUMPVEC_1
JSR $DEAD ; Self modified
;-------------------
NO_TRIGGER
INC ACTUAL_FILE
FILE_N_BUFFER = *+$0001
LDY #$00
DEY
STY FILE_N_BUFFER
BNE TURBO_LOAD
;-------------------
SEI
JSR TUNE_OFF ; Silence, please.
LDA #$35 ; Motor off, ROMS out
STA $01
LDA #$7F ; Unlatch interrupts
STA $DC0D
STA $DD0D
LDA $DC0D
LDA $DD0D
LDA #$00 ; Reset border colour
STA $D020
LDA #$1B
STA $D011 ; Screen on
RTS
;---------------------------------------
; LOADER_IRQ
; All data is recieved through here
;-------------------
LOADER_IRQ
PHA
TYA
PHA
LDA $D020 ; Flash the border
EOR #$05
STA $D020
LDA $DC05
LDY #$19 ; Trigger the counters
STY $DC0E
EOR #$02
LSR
LSR ; Shift in a BIT
ROL BIT_COUNT ; Until dummy bit 7 gets shifted out
LDA BIT_COUNT
BRANCH_MOD_1
BCC WAIT_HEADER ; Self modified branch
REFERENCE
BCS EXIT
WAIT_HEADER
CMP #HEADER_BYTE ; Is it a Header ?
BNE EXIT
LDA #HEADER_CHECK-REFERENCE
STA BRANCH_MOD_1+$0001
SET_AND_EXIT
LDA #%11111110 ; Init bit counter for the next 8
STA BIT_COUNT
EXIT
LDA $DC0D ; Acknowledge NMI
PLA
TAY
PLA
RTI ; Return
;-------------------
HEADER_CHECK
CMP #HEADER_BYTE
BEQ SET_AND_EXIT ; Confirmed Header Byte
CMP #HEADER_END ; Is it a Header END marker ?
BEQ CLEAR_CHECKSUM ; Yes it is
BNE SET_HEADER
; -------------------
CLEAR_CHECKSUM
LDA #SET_LOAD_ADDR-REFERENCE
STA BRANCH_MOD_1+$0001
LDA #$00 ; Clear the checksum
STA CHECKSUM
BEQ SET_AND_EXIT ; Branch always !
;-------------------
SET_LOAD_ADDR
STA LOAD_ADDR ; Store start Address
INC SET_LOAD_ADDR+$0001 ; And end address
LDA SET_LOAD_ADDR+$0001
CMP #LOAD_ADDR+$0004
BNE SET_AND_EXIT
LDA #STORE_BYTE-REFERENCE
STA BRANCH_MOD_1+$0001
BNE SET_AND_EXIT ; Branch always !
;-------------------
STORE_BYTE
LDY #$00
DEC $01 ; Page $D0 enabled
STA (LOAD_ADDR),Y ; Store recieved BYTE
INC $01 ; Page $D0 disabled
EOR CHECKSUM
STA CHECKSUM ; Store Checksum
INC LOAD_ADDR ; Bump the LOAD ADDRESS COUNTER
BNE NO_CARRY
INC LOAD_ADDR+$0001
INC $D020
NO_CARRY
LDA LOAD_ADDR ; Have we finished yet ?
CMP LOAD_END
LDA LOAD_ADDR+$0001
SBC LOAD_END+$0001
BCC SET_AND_EXIT ; No
LDA #LOAD_COMPLETE-REFERENCE
STA BRANCH_MOD_1+$0001
BNE SET_AND_EXIT ; Branch always !
;-------------------
LOAD_COMPLETE
STA VERIFY ; Store the verify BYTE
LDA #$FF ; Signal to FREELOAD that a load
STA LOAD_FLAG ; Has completed
LDA #LOAD_ADDR
STA SET_LOAD_ADDR+$0001 ; Reset low byte of load address
SET_HEADER
LDA #WAIT_HEADER-REFERENCE
STA BRANCH_MOD_1+$0001 ; Reset ready for the next file
BNE SET_AND_EXIT ; Branch always !
;---------------------------------------
; Smooth scroll subroutines
;-------------------
SMOOTH_SCROLL
LDA SMOOTH_X ; Alter the smooth X
SEC
SBC #$02
AND #$07
STA SMOOTH_X
BCC DO_BLOCK
RTS
;-------------------
DO_BLOCK
LDX #$00 ; Shunt line 23 across
SHIFT_LINE
LDA $0401+$17*$28,X
STA $0400+$17*$28,X
INX
CPX #$27
BNE SHIFT_LINE
PRINT_CHAR
LDA SCROLL_TEXT ; Print the new message byte
BEQ WRAP_MESS
AND #$3F
STA $0427+$17*$28
INC PRINT_CHAR+$0001
BNE PRINT_CHAR_01
INC PRINT_CHAR+$0002
PRINT_CHAR_01
RTS
;-------------------
WRAP_MESS
LDA #<SCROLL_TEXT ; Reset the message
STA PRINT_CHAR+$0001
LDA #>SCROLL_TEXT
STA PRINT_CHAR+$0002
JMP PRINT_CHAR
;-------------------
CLEAR_BITMAP
LDA #$00
CLEAR_ADDR = *+$0001
STA BITMAP_ADDRESS
INC CLEAR_ADDR
BNE NO_CARRY_02
INC CLEAR_ADDR+$0001
NO_CARRY_02
LDA CLEAR_ADDR
CMP #$40
BNE CLEAR_BITMAP
LDA CLEAR_ADDR+$0001
CMP #$FF
BNE CLEAR_BITMAP
;-------------------
LDA #$06 ; Setup the Bitmap colours
STA $D021
LDA #$00
STA $D020
RTS
;---------------------------------------
; Files triggers Routines
;-------------------
BITMAP_ON
LDA #$C0 ; Switch bitmap on
STA $DD00
LDA #$3F
STA $DD02
LDA #$28 ; Colour @ $C800, bitmap @ $E000
STA $D018
LDA #$3B ; Bitmap on
STA $D011
LDA #$D8 ; Multi colour on
STA $D016
;-------------------
LDX #$00 ; Copy up to colour ram
FILL_COL
LDA COLOR_ADDRESS+$0000,X ; From COLOR_ADDRESS to $D800
STA $D800,X
LDA COLOR_ADDRESS+$0100,X
STA $D900,X
LDA COLOR_ADDRESS+$0200,X
STA $DA00,X
LDA COLOR_ADDRESS+$0300,X
STA $DB00,X
INX
BNE FILL_COL
STX SCROLL_FLAG ; Switch the scroll off
RTS
;-------------------
BITMAP_OFF
LDA #$97 ; Switch the Bitmap off
STA $DD00
LDA #$1B ; Bitmap off
STA $D011
LDA #$C8 ; Multi colour off
STA $D016
LDA #$D2 ; Reset char and screen memory
STA $D018
;-------------------
LDX #$00
TXA
BLACK_OUT
STA $D800,X ; Blank the attributes
STA $D900,X
STA $DA00,X
STA $DB00,X
STA $D021
INX
BNE BLACK_OUT
RTS
;-------------------
TUNE_ON
LDX #$01
STX MUSIC_FLAG
DEX
TXA
TAY
JMP MUSIC_INIT
;-------------------
TUNE_OFF
LDA #$00
STA MUSIC_FLAG
LDX #$18 ; Clear SID chip
CLR_SID
STA $D400,X
DEX
BPL CLR_SID
RTS
;-------------------
SCROLL_ON
LDA $D016
AND #%11110111
STA $D016
INC SCROLL_FLAG
RTS
;-------------------
SCROLL_OFF
DEC SCROLL_FLAG
RTS
;---------------------------------------
; Files triggers table
;-------------------
FILES_TO_LOAD = FILE_TRIGGERS_END-FILE_TRIGGERS
;-------------------
FILE_TRIGGERS
.BYTE $05 ; Trigger for file 1 (B) Music
.BYTE $02 ; Trigger for file 2 (C) Color
.BYTE $01 ; Trigger for file 3 (D) Screen
.BYTE $00 ; Trigger for file 4 (E) Bitmap
.BYTE $00 ; Trigger for file 2 (F) Intro
FILE_TRIGGERS_END
;---------------------------------------
; Lookup table for files triggers
;-------------------
ROUT_LOOKUP
.ADDR $0000 ; Dummy
.ADDR BITMAP_ON ; 01 (this also turns the scroll off)
.ADDR TUNE_ON ; 02
.ADDR BITMAP_OFF ; 03
.ADDR TUNE_OFF ; 04
.ADDR SCROLL_ON ; 05
.ADDR SCROLL_OFF ; 06
;---------------------------------------
; Scroll text
;-------------------
SCROLL_TEXT
.TEXT "FREELOAD TEST BY FLAVIOWEB 2016 - "
.TEXT "ANTONIO MAURO - READY 64 !!! "
.BYTE $00
;-------------------------------------------------------------------------------
-
Piccola nota (quasi) a margine:
il SAVER forza il caricamento dei "segmenti" di programma da salvare su nastro, a $1000.
Ovviamente poi cambia lo start address e ricalcola l'indirizzo finale per il salvataggio, ma il fatto che debba avere i files in memoria da $1000, e che di default il SAVER sia compilato a $C000, significa che un file da salvare deve necessariamente stare fra $1000 e $BFFF indipendentemente dal suo indirizzo di caricamento originario...
Spostare il saver a $0801 ci lascia la ram da $1000 a $CFFF facendoci guadagnare 4k per i nostri dati...
-
Grande! Lo provo subito!!
Ma per rilocare il saver a $0801 mi basta modificare la direttiva "org $C000" oppure bisogna ritoccare qualche altra istruzione/costante?
-
Basta modificare l'ORG...
Se metti $0801 come infdirizzo di partenza, poi eseguirai il SAVER con SYS 2049.
Tieni presente che se il tuo programma può essere "diviso" in più file, puoi caricaricarli uno alla volta in memoria, al posto di avere un "bloccone" tutto exomizato.
Certo è che un "blocco" exomizato da $1000 a $CFFF dovrebbe essere più che sufficiente...
-
Attualmente ho un solo "bloccone" exomizzato sfx, cosa che risulta molto comoda per un demo/gioco single load. Per utilizzare questo metodo dovrò sicuramente riorganizzare il tutto dividendo in più parti rinunciando però alla comodità dell'auto decrunch!....
Per quanto riguarda invece i loader da disco cosa mi consigli?
-
Quanto "occupa" il bloccone?
Da $0801 a dove?
Per il disco, io ti consiglio il CovertBitOps Loader (http://cadaver.homeftp.net/tools/loader226.zip), discretamente semplice da usare, supporta direttamente i file exomizati (e pucrunch) e li decruncha al volo (level packed).
Oppure il loader di Krill (http://csdb.dk/release/?id=118713)
Per il disco ce ne sono millemila... dipende da cosa devi fare.
Specifico per i demo, potrebbe essere questo:
BitFire (http://csdb.dk/release/?id=146211) o il relativo repo GitHub (https://github.com/bboxy/bitfire).
-
Il bloccone exomizzato attualmente arriva a $3873 ma dovrebbe crescere ancora un bel po'!
Se ho ben capito i loader da disco non hanno un "saver" ma implementano solo il caricamento di dati via IRQ.
Bisogna quindi importare tali funzioni nel proprio codice e creare le logiche di caricamento (immagini, musica, codice,ecc...)
Corretto?
-
Si, corretto.
Generalmente i loader disco sono divisibili in 2 parti: init e loader.
Se non serve interagire col disco se non per caricare i files, allora una volta inizializzato il loader, il codice di init può essere cancellato/sovrascritto, mentre la parte del loader vera e propria deve essere residente in memoria.
Di solito i loader disco, oltre ad alcune locazioni in zp, servono aree buffer per allocare i dati durante la lettura ed eventualmente altre aree dati/zp per le routines di decrunch usate durante il loading (se richiesto).
Comunque il freeload non ha particolari problemi a gestire file exomizati auto scompattanti...
-
Comincio a fare qualche test con il "CovertBitOps Loader" giusto perchè compilabile in dasm senza modifiche....
Quindi per un uso "tradizionale" tutta la parte che segue a :"INITFASTLOAD" riga 1303 può essere eseguita e poi sovrascritta con altri dati?
Come si può specificare in quale locazione verrano caricati i dati utilizzando le funzioni "loadfile_*"?
Perdona le tante (forse banali)domande!!
-
Per risponderti con precisione, dovrei controllare bene i sorgenti, comunque in linea generale, il codice non residente è quello che verifica su quale periferica sia in esecuzione il loader e che carica o meno il drivecode.
Bisogna prestare attenzione ad eventuali bytes usati cone "variabili" dal loader...
Se sono compilate nella zona del codice di init, allora è meglio allocarle altrove, in modo che possano restare attive col loader.
Per gli indirizzi di caricamento, vengono specificati nel normale formato disco, cioè i primi 2 bytes letti dalla periferica rappresentano il load address nel formato basso/alto.
Il discorso varia con i files exomizati perchè, se non specificato diversamente in fase di compressione, i loro primi 2 bytes rappresentano l'indirizzo finale... ma questo è un discorso che per ora possiamo evitare, anche perchè è tutto gestito automagicamente dal loader.
Per iniziare, evita modifiche al codice. Fai una versione che lavori "out of the box" e poi pensa a come migliorare secondo le tue esigenze.
-
Considerando che lavorerò principalmente con files exomizzati immagino che debbano essere compressi con la direttiva "mem" (io utilizzavo sfx per avere un prg pronto all'uso)
Corretto?
Qual'è il parametro per specificare il "load address" su exomizer?
-
Se usi dei programm eseguibili autoscompattanti (exomizzati con SFX e simili, per intenderci) non devi fare niente.
Basta che li carichi normalmente col loader.
Se invece hai dei "blocchi di dati", li devi comprimere con l'opzione "LEVEL".
Quest'ultima opzione la si applica a grafica, musica, dati e, in generale, quasi mai al codice... anche se nulla vieta di farlo.
Il loader di CoverBitOps fornisce SOLO le subroutine per il caricamento dei dati. Compressione e salvataggio sono "a carico tuo".
Anche l'esecuzione del flusso delle operazioni deve essere gestita dal tuo "main code".
Il loader -carica- e basta. Punto.
-
Grazie ancora per le utilissime spiegazioni!
-
Avevo visto quei loader ma li avevo scartati perchè non ho ben capito come compilarli (Jam?)
Preferire utilizzare qualcosa compilabile con dasm (tipo ocean freeload) ma se riesco a far andare questi va bene lo stesso!
-
Io tempo fa realizzai il TAP di Imperoid con un programma direttamente da 64. Serviva una immagine Koala, un SID, ed un pò di pazienza nel trovare gli indirizzi di esecuzione.
(https://image.ibb.co/iqH2Hc/01.png)
(https://image.ibb.co/hq6wcc/02.png)
(https://image.ibb.co/kw3L3H/03.png)
(https://image.ibb.co/b4QBAx/04.png)
(https://image.ibb.co/c7vBAx/05.png)
(https://image.ibb.co/f1J9xc/06.png)
Se lo trovo lo condivido qui.
-
ottimo aspettiamo...