Community
SCI Programming => SCI Development Tools => Topic started by: Kawa on April 12, 2017, 05:48:34 PM
-
I just managed to compile my own copy of sierra.exe. It doesn't actually run anything yet, but at least I got the right compiler! Lemme just rename it so it can coexist with the one that came with the archive...
(http://i.imgur.com/pTk7ux2.png)
Yeah okay, I'll accept that.
Edit: got a new development environment set up in a DOSbox. Two minor changes to startasm.s and info.c later, I have an SCI.EXE (debug) that manages to run the template game, albeit without the ability to initialize my sound hardware, and a SIERRA.EXE that actively refuses because it's not been stamped.
-
What compiler?
-
VC++ v1.52 I guess? :)
-
Yeah.
Who wantsHere's a ZIP with all you need to compile this?: http://helmet.kafuka.org/sci/scibuild.zip run it in DOSBox, with SCIBUILD as C:, invoke GO to set up the env. Run it at least INSTALL once for initial setup to remove stamping and such.
Things I feel like doing:
1. Fix the issues cl warns about
2. Add a novel subcommand, palette inversion most likely.
Changelog: EXISTS is shit, split up the setup batch files instead. Added -nologo and @ to clean up compiler invocations.
-
I've been going through the code, fixing warnings and mildly updating formatting style -- it's full of old-style function definitions with the types listed separately -- and I'm wondering what kind of features could feasibly be added.
So far I've got that palette inversion thing, (RemapColors rcZAWARUDO [range]), which needs more testing, and an optional fourth arg for DisplayPic to control transition speeds, confirmed to work on dsOPEN_CHECKBOARD and dsOPEN_FADEPALETTE (names from memory because lolphone).
Phil has suggested:
* Savegame thumbnails, though I've no idea where to even start, plus there's the whole palette thing.
* Masked sprites.
* Coroutines, so very likely.
-
Port to Win32 ;)
-
Masked sprites seem like the easiest (and biggest bang for the buck). In Cascade Quest, I use them for: having a waterfall "dry up", making the ego partially submerged in water (at different levels), making the ego partially transparent, and fading from one tv screen to another.
Savegame thumbnails and coroutines would be a ton of work.
-
If the cel drawing routine is ASM, I'm not going there.
Edit: phucking fone
-
New kernel call, so as to not foul up what's already there:
(Kawa 0 {...}) wraps DoAlert(), basically.
(Kawa 1 [from] [to]) inverts the specified range in the palette. Here's (Kawa 1 0 63). (https://i.imgur.com/frilbIs.png)
(Kawa 2 [back] [text]) sets the title bar color of the uncustomized system window. To wit. (https://i.imgur.com/P3FZtKk.png)
(Kawa 3) returns 1 if we're running a debug terp. Might extend this to &2 if we have menu bar support, I dunno.
-
Haha...
When I still cared about running (or was able to run) on Sierra SCI, I was overloading DoAvoider for my kernel extensibility, since it does nothing (on SCI0 anyway).
-
Why overload when you can extend, right?
-
(Kawa 1 [from] [to]) inverts the specified range in the palette.
Ilira on shrooms?
-
From what I recall, you can only modify the intensity of a palette right? How about adding color channel multipliers, or saturation adjustment, or hue shifting? Should be pretty straightforward (although I guess there's already a function to transition gradually between 2 palettes, so maybe that's not needed).
-
Well, having the ability to adjust a palette by hue, saturation, etc would negate the need to have extra palette resources....though that's not really a huge issue. Maybe just easier to deal with commands than remembering which palettes are which?
-
Palette adjustments like that, without using floats? Should be fun. And you could always use some defines in your PalVary call to identify the targets.
Anyway, here's a control renderer that listens to the back and color properties. Normally it only cares about text and font.
(http://i.imgur.com/Vymasda.png)
Shown here on a one-pixel bevel window. Where and how these colors are set is up to you.
-
Idea for easy add: ability to vertically flip views.
-
Easy perhaps, but still ASM. Tch, we'll see.
-
Easy perhaps, but still ASM. Tch, we'll see.
It's "tsk" not "tch", you barbarian you.
-
So with a little help from IDA and a few liters of diet coke, I found out that startasm.s was being assembled wrong. This broke restore/restart, which works by longjmp, and saving if it were to fail. And woah boy how it broke.
Turns out that MASM was generating extra code around the setjmp and longjmp procedures, because they have parameters. The originally released code did not specify any, but MASM wouldn't take it because the proto definitions did have parameters. To quote the MASM 6.11 manual:
When you use the PROC directive with its extended syntax and argument list, the assembler automatically generates the prologue and epilogue code in your procedure.
If a procedure does not have any parameters or local variables, the prologue and epilogue code that sets up and restores a stack pointer is omitted, unless FORCEFRAME is included in the prologuearg list.
We want to do the opposite here, though...
If you want to revert to the standard prologue or epilogue code, use PROLOGUEDEF or EPILOGUEDEF as the macroname in the OPTION statement.
OPTION EPILOGUE:EPILOGUEDEFYou can completely suppress prologue or epilogue generation with OPTION PROLOGUE:None
OPTION EPILOGUE:None
(http://i.imgur.com/2tJJpmk.gif)
This has of course been tested and confirmed. The scibuild.zip file in my stash has been updated accordingly.
-
If you're still working on this, other than the x/y axis flipping (which is useful for having mirror or floor reflections), you can:
- have a flag that says ignore the priority comparison when drawing a view (so it always draws)
- have a flag that tells a view not to write to the visual screen (combined with the above, useful for cutting out holes of lower priority in a scene... like for a window)
- have a flag that tells a view not to write to the priority screen (lets you apply a "decal" onto a surface of varying priority)
- have a flag that inverts the priority compare (why would you do this? I have a crazy reason to do this)
-
I'm gonna need another field for those flags.
-
Yes, you will.
-
Y'know, I haven't done anything with this for a bit now, but the fact you can build versions that have menu bar support like the terp that came with LSL6 did remind me of something. I did mention menu bars on page one about (Kawa 3).
SIERRA.EXE has no debugger and no menu bar, basically the one intended for public use. SIERRAM.EXE adds SCI0-style menu bar support to that, and is basically what LSL6 came with. SCI.EXE includes the debugger, and SCITESTR.EXE has both.
Given a SIERRAM terp (custom built or LSL6's), what's stopping you from being cheeky and removing the icon bar?
Edit: and yes, I did add that "& 2 to check if menus are available" thing:case 3: //KAWA_ISDEBUG
//(Kawa 3) ;Returns 1 if debug version, 2 if menu bars are enabled, 3 if both.
acc = isDebugVersion;
#if TESTER
acc |= 2;
#endif
break;
-
Given no resource.cfg, the original interpreter will say it can't find the configuration file and to run the install program.
Given a config file with a missing video driver -- literally no videoDrv = ____ line at all -- it'll say it couldn't install the video driver but not how to fix it.
So I edited mine to detect the fact that there's no driver specified and simply say, "please run the install program." No script #, no IP #, just a simple request so next time you run it there will be a video driver to try and load.
Now I should update my install program to secretly reset to defaults if these things are missing too cos I just loaded a no-driver config and it was full of blanks :D (update: done and uploaded.)
-
Oh, and another thing that I did. Ending text screens. B800 screens, ENDOOM screens, whatever you wanna call 'em. If the data's not there, it reverts to the regular quit message.
-
ASCII ending screens are the best.
-
It's about time I added a new feature.
(https://pbs.twimg.com/media/DkZ4el-XsAA_2h9.png)
(Display {This text is outlined automagically!} dsCOORD 8 8 dsALIGN 2 dsCOLOR 31)
Alignment can be 0 for left, 1 for center, or -1 for right. Seems a waste of a whole 16-bit word, why not make 2 left-outlined and 3 center-outlined?
In any case I can now draw outlined text in any font I damn well want.
In KERNEL.C:
RGrafPort savePort;
RPoint newPenLoc;
word penColor = 0, outline = 0; //add these two
width = colorIt = -1;
mode = TEJUSTLEFT;
case p_color:
penColor = *args++; //instead of calling PenColor directly
break;//get size of text rectangle
RTextSize(&r, text, -1, width);
if (mode & 2) RInsetRect(&r, -1, -1); //not sure if needed but eeeeeh
//move the rectangle to current pen position
MoveRect(&r, rThePort->pnLoc.h, rThePort->pnLoc.v);//opaque background
if (colorIt != -1) RFillRect(&r, VMAP, colorIt);
//add this whole thing.
if (mode & 2) {
mode &= ~2;
ROffsetRect(&r, 1, 0); RTextBox(text, FALSE, &r, mode, -1); //right...
ROffsetRect(&r, 0, 1); RTextBox(text, FALSE, &r, mode, -1); //bottom right...
ROffsetRect(&r,-1, 0); RTextBox(text, FALSE, &r, mode, -1); //bottom...
ROffsetRect(&r,-1, 0); RTextBox(text, FALSE, &r, mode, -1); //bottom left...
ROffsetRect(&r, 0,-1); RTextBox(text, FALSE, &r, mode, -1); //left...
ROffsetRect(&r, 0,-1); RTextBox(text, FALSE, &r, mode, -1); //top left...
ROffsetRect(&r, 1, 0); RTextBox(text, FALSE, &r, mode, -1); //top...
ROffsetRect(&r, 1, 0); RTextBox(text, FALSE, &r, mode, -1); //top right...
ROffsetRect(&r,-1, 1); //and back to the center.
}
PenColor(penColor); //NOW we set our pen color!
//now draw the text and show the rectangle it is in
RTextBox(text, FALSE, &r, mode, -1);Outlines are always in black because it calls PenColor(0) before parsing the arguments.
-
Add another bitmask/flag for controlling which of the 8 "outline texts" are drawn. Then you can do things like dropshadows, or fake a blur on the text if the outline color is partway between your text color and your screen (this is how I do the hover effect on the verbs in Snowspirit).
-
I was thinking of having the 4 bit do dropshadows... by the way, I mentioned this on Twitter but there's an extra value in Display that's not in your header file, 121 "noshow".
-
Okay, I moved the thing into its own pseud, dsSTROKE 122, and made it a bitfield. You'll notice there was an unused outline variable in that code I posted...
case p_noshow:
showIt = 0;
break;
case p_stroke:
stroke = *args++; //this was that variable.
break;
if (stroke)
{
ROffsetRect(&r, 1, 0); if (stroke & 1) RTextBox(text, FALSE, &r, mode, -1); //right...
ROffsetRect(&r, 0, 1); if (stroke & 2) RTextBox(text, FALSE, &r, mode, -1); //bottom right...
ROffsetRect(&r,-1, 0); if (stroke & 4) RTextBox(text, FALSE, &r, mode, -1); //bottom...
ROffsetRect(&r,-1, 0); if (stroke & 8) RTextBox(text, FALSE, &r, mode, -1); //bottom left...
ROffsetRect(&r, 0,-1); if (stroke & 16) RTextBox(text, FALSE, &r, mode, -1); //left...
ROffsetRect(&r, 0,-1); if (stroke & 32) RTextBox(text, FALSE, &r, mode, -1); //top left...
ROffsetRect(&r, 1, 0); if (stroke & 64) RTextBox(text, FALSE, &r, mode, -1); //top...
ROffsetRect(&r, 1, 0); if (stroke & 128) RTextBox(text, FALSE, &r, mode, -1); //top right...
ROffsetRect(&r,-1, 1); //and center.
}Useless offset calls, but this does ensure you end up in the right spot.
(https://i.imgur.com/eGyCn2n.png)
-
Really cool to watch this develop.
-
Y'think? Here's the ENDOOM thing:
START.C
void exit(char code)
{
int i;
Handle hB800;
volatile char far* vidya = (volatile char far*)0xB8000000;
char far* b800;
for (i = exitIndex - 1; i >= 0; i--)
exitProcs[i]();
if (panicStr)
WriteString(panicStr);
else
{
if (ResCheck(RES_VOCAB, 0xB8))
{
hB800 = ResLoad(RES_VOCAB, 0xB8);
b800 = (char far*)*hB800;
for (i = 0; i < 80*25*2; i++)
*vidya++ = *b800++;
gotoxy(23, 0);
//Consideration: add four bytes to the end of the picture
//data with the quitStr and prompt coordinates.
}
else if (quitStr)
WriteString(quitStr);
}
ExitFromC(code);
}
STARTASM.S
gotoxy proc row: byte, col: byte
mov ah, 2
xor bh, bh
mov dh, row
xor dl, col
int 10h
ret
gotoxy endp
START.H
void gotoxy(char, char);
And then you just drop your standard textmode screen dump, 4000 bytes plus an 86 00 resource cookie in the front, in your game as 184.VOC and quit the game. And then you realize DOSBox is set up to quit afterwards and you slap yourself on the forehead.
-
You are pulling our collective legs, right?
STARTASM.S
gotoxy proc row: byte, col: byte
mov ah, 2
xor bh, bh
mov dh, row
*** xor dl, col ***
int 10h
ret
gotoxy endp
This makes DL undefined unless it happened to be zero to begin with (which may well be true but unreliable) in which case DL = 0 ^ col = col.
-
I never said I was any good at x86 ASM. But you did just solve an odd problem.
Edit: yeah, I now have quitString appearing wherever the vocab specifies it should.
if (ResCheck(RES_VOCAB, 0xB8))
{
hB800 = ResLoad(RES_VOCAB, 0xB8);
b800 = (char far*)*hB800;
for (i = 0; i < 80*25*2; i++)
*vidya++ = *b800++;
x = *b800++; y = *b800++;
if (quitStr)
{
gotoxy(x, y);
WriteString(quitStr);
}
x = *b800++; y = *b800++;
gotoxy(x, y); //note: prompt appears at the *next* line.
}
else if (quitStr)
WriteString(quitStr);
-
In cels.s, invoked in the line builders after setting al to the current view pixel color:
DoColorKawaHax proc near
.if (al == ss:skip) || (al >= REMAPCOLORSTART)
ret
.elseif (ss:kawaHax == 1)
xor al, al
.elseif (ss:kawaHax == 2)
;naive shitty but fast
;dec al
;proper
push bx
xor bh, bh
mov bl, al
mov al, ss:remapTable[bx]
pop bx
.elseif (ss:kawaHax == 3)
mov al, 253
.endif
ret
DoColorKawaHax endpwith kawaHax defined up top aspublic kawaHax
kawaHax byte 0
In animate.c, add an extern char kawaHax; and add this: //this handle will be valid for a while */
theViewNum = IndexedProp(him, actView);
view = ResLoad(RES_VIEW, theViewNum);
kawaHax = GetProperty(him,s_vm_signal) >> 8;
//all stopped actors have already been drawn
//a HIDE actor is not drawn
//a VIEWADDED is not drawn
if (!(signal & (VIEWADDED | NOUPDATE | HIDE)))
{
//......
}
kawaHax = 0;
}
//do we show the screen hereNow you can do stuff like this in an actor's doit: (if (== (self onControl: TRUE) ctlGREY)
(self scaleSignal: (| (self scaleSignal?) $200))
else
(self scaleSignal: (& (self scaleSignal?) (~ $200)))
)Try it on Ego. Given an earlier (RemapColors rcPERCENT 253 64), every dark gray control area now causes that actor to darken in shadow.
(https://i.imgur.com/FAMTeub.gif)
It's like Roger Wilco in SQ3, as seen in that video I made, but better.
-
Nice effect. Now if the shadow is being cast at an angle the shade would sweep up and down the character when walking through it.
-
(https://i.imgur.com/MuErgR1.png)
This is not something I added! It turns out that DrawCel has two more optional parameters that aren't listed in Phil's documentation: scaleX scaleY. I don't know if this also applies to SCI11, but that's easy enough to test.
I found that out while trying to simulate PQ4's translucent windows.
-
Using SCI Companion's version detector as a guide because the ScummVM wiki page on the topic is too confusingly worded, I've added a thing where the interpreter'll try to ensure you're trying to run an SCI11 game (https://bitbucket.org/Kawa/sci16/commits/14b56a956a6c2882b5d0584a5a3b9175267135f2), so instead of getting zero hunk allocation requests, errors on explode, or missing 0.fon, all in bigass font, you get a friendly and informative message.
-
So this is version detection of the resources, not the interpreter?
-
The interpreter detects the format of resource.map so as to not try and fail to run non-SCI11 data.
-
Nice. This must be what the ScummVM does to guess the versions of the interpreters with the "x.yyy.yyy" version strings.
-
Near I can tell it always does this. After all, you only need the resource files to run the games in ScummVM.
I've been working on a flip bit but I'm having trouble with the Y-offsets.
-
When ScummVM decided to take on SCI they started with the then available documentation like the FreeSCI specs, etc. Among those were the HWM documents. His SCI version list is based on the interpreter itself, I assume from the version string. The Wiki still has this list with the "x.yyy.yyy" strings.
It would make sense that SVM would have to go by resource versions to handle a game since the original interpreter is not used.
Near I can tell it always does this. After all, you only need the resource files to run the games in ScummVM.
I've been working on a flip bit but I'm having trouble with the Y-offsets.
For cast shadows and reflections of views?
-
For cast shadows and reflections of views?
Exactly that.
-
Yes, ScummVM does other things (the full algorithm can't work without having loaded the selector table and instantiated some scripts). We used version numbers in the FreeSCI days, but it became untenable with both SCI1.1 and SCI32.. No version numbers, and lots of little annoying quirks in each interpreter. (Try issuing the 'version' command from a ScummVM console one day and see. Its output is... voluminous).