Pari réussi, vais pouvoir continuer le code, enfin plutôt le kit de dev ST et le code
Donc je me suis bricolé un Lynxer.ttp comme ci-dessus : fichiers déclarés et ceux non déclarés commençant par @ (accolage brutal après le dernier fichier) ou # (accolage intelligent, après le dernier fichier, si c'est à cheval entre deux blocs de 1024 octets, alors j'aligne au multiple de 1024).
Pour le fichier .MAK
insert.o
tst_spr2.o
#ALIGN
sprites\brun1.spr ; fichier déclaré, on accèdera aux autres avec LoadCartDir(2)
#sprites\brun2.spr
#sprites\brun3.spr
#sprites\btongue1.spr
#sprites\btongue2.spr
#sprites\btongue3.spr
#sprites\bwalk1.spr
#sprites\bwalk2.spr
#sprites\bwalk3.spr
#sprites\bwalk4.spr
#sprites\bback1.spr
#sprites\bback2.spr
#sprites\bfront1.spr
#sprites\bfront2.spr
#sprites\bnod1.spr
#sprites\bnod2.spr
#sprites\bmock1.spr
#sprites\bmock2.spr
#sprites\bdrink1.spr
#sprites\bdrink2.spr
#sprites\bjump1.spr
#sprites\bburnin1.spr
#sprites\bburnin2.spr
#sprites\bburnin3.spr
;--8<----------------------------
#sprites\van22.spr
#sprites\van31.spr
#sprites\van32.spr
Le lynxer avec la commande "[-l [log_file]]" me fournit un fichier texte en C qui me décrit les localisations des fichiers :
struct file {
uchar fileEntry; // with LoadCardDir(F)
uchar blockOffset; // + N blocks of 1024
int byteOffset; // + O bytes
};
struct filePosition fpos[127] = {
{0, 0, 0}, // 2346 bytes for insert.o
{1, 0, 0}, // 3620 bytes for tst_spr2.o
{2, 0, 0}, // 270 bytes for sprites\brun1.spr
{2, 0, 270}, // 264 bytes for #sprites\brun2.spr
{2, 0, 534}, // 278 bytes for #sprites\brun3.spr
{2, 1, 0}, // 274 bytes for #sprites\btongue1.spr
{2, 1, 274}, // 266 bytes for #sprites\btongue2.spr
{2, 1, 540}, // 278 bytes for #sprites\btongue3.spr
{2, 2, 0}, // 258 bytes for #sprites\bwalk1.spr
{2, 2, 258}, // 266 bytes for #sprites\bwalk2.spr
{2, 2, 524}, // 264 bytes for #sprites\bwalk3.spr
{2, 3, 0}, // 260 bytes for #sprites\bwalk4.spr
{2, 3, 260}, // 252 bytes for #sprites\bback1.spr
{2, 3, 512}, // 254 bytes for #sprites\bback2.spr
{2, 4, 0}, // 262 bytes for #sprites\bfront1.spr
{2, 4, 262}, // 264 bytes for #sprites\bfront2.spr
{2, 4, 526}, // 252 bytes for #sprites\bnod1.spr
{2, 5, 0}, // 252 bytes for #sprites\bnod2.spr
{2, 31, 400}, // 100 bytes for #sprites\n0900.spr
{2, 31, 500}, // 102 bytes for #sprites\n1000.spr
//--8<----------------------
{2, 32, 0}, // 592 bytes for #sprites\van01.spr
{2, 33, 0}, // 602 bytes for #sprites\van02.spr
{2, 34, 0}, // 546 bytes for #sprites\van11.spr
{2, 35, 0}, // 556 bytes for #sprites\van12.spr
{2, 36, 0}, // 514 bytes for #sprites\van21.spr
{2, 37, 0}, // 534 bytes for #sprites\van22.spr
{2, 38, 0}, // 518 bytes for #sprites\van31.spr
{2, 39, 0} // 532 bytes for #sprites\van32.spr
};
Ce fichier va être intégré dans le source C, en enlevant les 2 premiers fichiers de la table...
#include <lynx.h>
#include <lynxlib.h>
#include <stdlib.h>
// Bug in cc65? Needs real code before C++ comments occur?
extern char FileEntry[ 8];
struct fileCache {
uchar entry;
uchar block;
int offset;
char *address;
char buffer[ 1024];
};
struct fileCache cache;
struct fileLocation {
uchar fileEntry; // with LoadCardDir(F)
uchar blockOffset; // + N blocks of 1024
int byteOffset; // + O bytes
};
struct fileLocation fpos[ 125] = {
{2, 0, 0}, // 270 bytes for sprites\brun1.spr
{2, 0, 270}, // 264 bytes for #sprites\brun2.spr
{2, 0, 534}, // 278 bytes for #sprites\brun3.spr
{2, 1, 0}, // 274 bytes for #sprites\btongue1.spr
{2, 1, 274}, // 266 bytes for #sprites\btongue2.spr
{2, 1, 540}, // 278 bytes for #sprites\btongue3.spr
{2, 2, 0}, // 258 bytes for #sprites\bwalk1.spr
{2, 2, 258}, // 266 bytes for #sprites\bwalk2.spr
{2, 2, 524}, // 264 bytes for #sprites\bwalk3.spr
{2, 3, 0}, // 260 bytes for #sprites\bwalk4.spr
{2, 3, 260}, // 252 bytes for #sprites\bback1.spr
{2, 3, 512}, // 254 bytes for #sprites\bback2.spr
{2, 4, 0}, // 262 bytes for #sprites\bfront1.spr
{2, 4, 262}, // 264 bytes for #sprites\bfront2.spr
{2, 4, 526}, // 252 bytes for #sprites\bnod1.spr
{2, 5, 0}, // 252 bytes for #sprites\bnod2.spr
{2, 5, 252}, // 254 bytes for #sprites\bmock1.spr
{2, 5, 506}, // 254 bytes for #sprites\bmock2.spr
{2, 6, 0}, // 304 bytes for #sprites\bdrink1.spr
{2, 6, 304}, // 316 bytes for #sprites\bdrink2.spr
{2, 6, 620}, // 336 bytes for #sprites\bjump1.spr
{2, 7, 0}, // 272 bytes for #sprites\bburnin1.spr
{2, 7, 272}, // 288 bytes for #sprites\bburnin2.spr
{2, 7, 560}, // 286 bytes for #sprites\bburnin3.spr
{2, 8, 0}, // 262 bytes for #sprites\bburnin4.spr
{2, 8, 262}, // 254 bytes for #sprites\bburnin5.spr
{2, 8, 516}, // 234 bytes for #sprites\bburnin6.spr
{2, 8, 750}, // 236 bytes for #sprites\bburnin7.spr
{2, 9, 0}, // 238 bytes for #sprites\bburnin8.spr
{2, 9, 238}, // 228 bytes for #sprites\bburnin9.spr
{2, 9, 466}, // 274 bytes for #sprites\bhit1.spr
{2, 10, 0}, // 294 bytes for #sprites\bhit2.spr
{2, 10, 294}, // 284 bytes for #sprites\bhit3.spr
{2, 10, 578}, // 240 bytes for #sprites\bcaught1.spr
{2, 11, 0}, // 244 bytes for #sprites\crun1.spr
{2, 11, 244}, // 232 bytes for #sprites\crun2.spr
{2, 11, 476}, // 238 bytes for #sprites\crun3.spr
{2, 11, 714}, // 224 bytes for #sprites\crun4.spr
{2, 12, 0}, // 232 bytes for #sprites\crun5.spr
{2, 12, 232}, // 232 bytes for #sprites\crun6.spr
{2, 12, 464}, // 224 bytes for #sprites\crun7.spr
{2, 12, 688}, // 234 bytes for #sprites\cbreak1.spr
{2, 13, 0}, // 234 bytes for #sprites\cbreak2.spr
{2, 13, 234}, // 242 bytes for #sprites\cdrink1.spr
{2, 13, 476}, // 242 bytes for #sprites\cdrink2.spr
//--8<------------------------------
{2, 35, 0}, // 556 bytes for #sprites\van12.spr
{2, 36, 0}, // 514 bytes for #sprites\van21.spr
{2, 37, 0}, // 534 bytes for #sprites\van22.spr
{2, 38, 0}, // 518 bytes for #sprites\van31.spr
{2, 39, 0} // 532 bytes for #sprites\van32.spr
};
extern char SCB_test[];
#asm
_SCB_test dc.b $c4,$10,$20
dc.w 0
dc.w 0
dc.w 64,64
dc.w $100,$100
dc.b $01,$23,$45,$67,$89,$ab,$cd,$ef
#endasm
#include "ingame.pal"
extern uchar VBLflag;
#asm
_VBLflag = $a0
#endasm
#define VSYNC { ++VBLflag; while(VBLflag) {} }
VBL() interrupt { VBLflag = 0; }
register uchar joy;
void WaitTicks(waitticks) uchar waitticks {
uchar tick;
tick = 0;
while (tick < waitticks) {
VSYNC;
++tick;
}
}
uchar WaitButton() {
uchar key;
while (!(key = joystick)) {}
while (joystick) {}
return key;
}
void getFile(fp, fc) struct fileLocation *fp; struct fileCache *fc; {
if (fc->entry != fp->fileEntry) {
fc->entry = fp->fileEntry;
fc->block = fp->blockOffset;
fc->offset = fp->byteOffset;
fc->address = fc->buffer + fc->offset;
LoadCartDir(fc->entry);
LoadCartBlock(FileEntry[ 0] + fc->block, fc->buffer);
}
else if (fc->block != fp->blockOffset) {
fc->block = fp->blockOffset;
fc->offset = fp->byteOffset;
fc->address = fc->buffer + fc->offset;
LoadCartBlock(FileEntry[ 0] + fc->block, fc->buffer);
}
else if (fc->offset != fp->byteOffset) {
fc->offset = fp->byteOffset;
fc->address = fc->buffer + fc->offset;
}
}
uchar sprite_id;
char *sprite_adr;
void main() {
joy = 0;
InitIRQ();
InstallIRQ(2, VBL);
EnableIRQ(2);
CLI;
_SetRGB(pal);
SetBuffers(0xa000, 0xc000, 0);
cache.entry = 0;
cache.block = 0;
cache.offset = 0;
sprite_id = 0;
while(1) {
getFile(&fpos[sprite_id], &cache);
SCBDATA(SCB_test) = cache.address;
DrawFBox(0, 0, 160, 102, 5);
DrawSprite(SCB_test);
WaitTicks(4);
SwapBuffers();
//WaitButton();
++sprite_id;
if (sprite_id == 125) { sprite_id = 0; }
}
}
J'ai mis un temps d'attente de 4 VBLs pour cette démo sinon on ne verrait rien. C'est trop rapide. Pour expliquer ce source : on considère que les sprites ne dépassent jamais 1024 octets, et qu'on les charge dans un buffer/cache de cette taille. Si le sprite est contenu dans ce cache, on l'affiche, sinon on va le chercher dans la ROM/cartouche. On pourrait faire un cache de N*1024, il suffirait de multiplier les LoadCartBlock et pour stocker plus de fichiers, les accoler avec un @ dans le .MAK et en calculant bien.
Le résultat se trouve là ->
http://rajah.atari.org/files/ -> tst_spr2.lnx (attention, c'est un fichier de travail, donc je l'effacerai au bout de 2 semaines).