//
// ID Engine
// ID_US.h - Header file for the User Manager
// v1.0d1
// By Jason Blochowiak
//
#ifndef __ID_US__
#define __ID_US__
#ifdef __DEBUG__
#define __DEBUG_UserMgr__
#endif
//#define HELPTEXTLINKED
#define MaxX 320
#define MaxY 200
#define MaxHelpLines 500
#define MaxHighName 57
#define MaxScores 7
typedef struct
{
char name[MaxHighName + 1];
long score;
word completed,episode;
} HighScore;
#define MaxGameName 32
#define MaxSaveGames 6
typedef struct
{
char signature[4];
word *oldtest;
boolean present;
char name[MaxGameName + 1];
} SaveGame;
#define MaxString 128 // Maximum input string size
typedef struct
{
int x,y,
w,h,
px,py;
} WindowRec; // Record used to save & restore screen windows
typedef enum
{
gd_Continue,
gd_Easy,
gd_Normal,
gd_Hard
} GameDiff;
// Hack import for TED launch support
extern boolean tedlevel;
extern int tedlevelnum;
extern void TEDDeath(void);
extern boolean ingame, // Set by game code if a game is in progress
abortgame, // Set if a game load failed
loadedgame, // Set if the current game was loaded
NoWait,
HighScoresDirty;
extern char *abortprogram; // Set to error msg if program is dying
extern GameDiff restartgame; // Normally gd_Continue, else starts game
extern word PrintX,PrintY; // Current printing location in the window
extern word WindowX,WindowY,// Current location of window
WindowW,WindowH;// Current size of window
extern boolean Button0,Button1,
CursorBad;
extern int CursorX,CursorY;
extern void (*USL_MeasureString)(char far *,word *,word *),
(*USL_DrawString)(char far *);
extern boolean (*USL_SaveGame)(int),(*USL_LoadGame)(int);
extern void (*USL_ResetGame)(void);
extern SaveGame Games[MaxSaveGames];
extern HighScore Scores[];
#define US_HomeWindow() {PrintX = WindowX; PrintY = WindowY;}
extern void US_Startup(void),
US_Setup(void),
US_Shutdown(void),
US_InitRndT(boolean randomize),
US_SetLoadSaveHooks(boolean (*load)(int),
boolean (*save)(int),
void (*reset)(void)),
US_TextScreen(void),
US_UpdateTextScreen(void),
US_FinishTextScreen(void),
US_DrawWindow(word x,word y,word w,word h),
US_CenterWindow(word,word),
US_SaveWindow(WindowRec *win),
US_RestoreWindow(WindowRec *win),
US_ClearWindow(void),
US_SetPrintRoutines(void (*measure)(char far *,word *,word *),
void (*print)(char far *)),
US_PrintCentered(char far *s),
US_CPrint(char far *s),
US_CPrintLine(char far *s),
US_Print(char far *s),
US_PrintUnsigned(longword n),
US_PrintSigned(long n),
US_StartCursor(void),
US_ShutCursor(void),
US_CheckHighScore(long score,word other),
US_DisplayHighScores(int which);
extern boolean US_UpdateCursor(void),
US_LineInput(int x,int y,char *buf,char *def,boolean escok,
int maxchars,int maxwidth);
extern int US_CheckParm(char *parm,char **strings),
US_RndT(void);
void USL_PrintInCenter(char far *s,Rect r);
char *USL_GiveSaveName(word game);
#endif
;
; ID_SD_A.ASM
; Id Sound Manager assembly stuff
.286C
IDEAL
MODEL MEDIUM,C
JUMPS
INCLUDE 'ID_SD.EQU'
DEBUG = 0
EXTRN SDL_DigitizedDone:FAR
EXTRN alOut:FAR
;============================================================================
DATASEG
EXTRN sqActive:WORD
EXTRN ssSample:DWORD
EXTRN ssLengthLeft:WORD
EXTRN ssControl:WORD
EXTRN ssStatus:WORD
EXTRN ssData:WORD
EXTRN ssOn:BYTE
EXTRN ssOff:BYTE
EXTRN pcSound:DWORD
EXTRN pcLengthLeft:WORD
EXTRN pcLastSample:BYTE
EXTRN pcSoundLookup:WORD
EXTRN alSound:DWORD
EXTRN alBlock:WORD
EXTRN alLengthLeft:WORD
EXTRN alTimeCount:DWORD
EXTRN sqHack:DWORD
EXTRN sqHackPtr:DWORD
EXTRN sqHackLen:WORD
EXTRN sqHackSeqLen:WORD
EXTRN sqHackTime:DWORD
EXTRN HackCount:WORD
EXTRN TimeCount:WORD
EXTRN LocalTime:WORD
EXTRN TimerCount:WORD
EXTRN TimerDivisor:WORD
EXTRN t0OldService:DWORD
EXTRN SoundMode:WORD
EXTRN DigiMode:WORD
EXTRN SoundNumber:WORD
EXTRN SoundPriority:WORD
count_time dw ?
count_fx dw ?
pcdtab db 00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b
db 00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b
db 00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b
db 00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b
db 00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b
db 00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b
db 00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b
db 00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b,00b
db 10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b
db 10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b
db 10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b
db 10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b
db 10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b
db 10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b
db 10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b
db 10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b,10b
;============================================================================
CODESEG
MyDS dw ?
pcindicate dw ?
extreme dw ?
PROC SDL_SetDS
PUBLIC SDL_SetDS
mov ax,ds
mov [cs:MyDS],ds
ret
ENDP
;
; COMMONSTART
; Macro used for common prefix code
;
MACRO COMMONSTART
IF DEBUG
push dx
push ax
mov dx,STATUS_REGISTER_1
in al,dx
mov dx,ATR_INDEX
mov al,ATR_OVERSCAN
out dx,al
mov al,4 ; red
out dx,al
ENDIF
push ds
push ax
mov ds,[cs:MyDS]
inc [HackCount]
ENDM
;
; DOFX
; Macro used to do the sound effects code
;
MACRO DOFX
les di,[pcSound] ; PC sound effects
mov ax,es
or ax,di
jz @@nopc ; nil pointer - no PC sound effect going
mov bl,[es:di] ; Get the byte
inc [WORD PTR pcSound] ; Increment pointer
cmp [pcLastSample],bl ; Is this sample the same as last?
jz @@pcsame ; Yep - don't do anything
mov [pcLastSample],bl ; No, save it for next time
or bl,bl
jz @@pcoff ; If 0, turn sounds off
xor bh,bh
shl bx,1
mov bx,[pcSoundLookup+bx] ; Use byte as index into frequency table
mov al,0b6h ; Write to channel 2 (speaker) timer
out pcTAccess,al
mov al,bl
out pcTimer,al ; Low byte
mov al,bh
out pcTimer,al ; High byte
in al,pcSpeaker ; Turn the speaker & gate on
or al,3
out pcSpeaker,al
jmp @@pcsame
@@pcoff:
in al,pcSpeaker ; Turn the speaker & gate off
and al,0fch ; ~3
out pcSpeaker,al
@@pcsame:
dec [pcLengthLeft] ; Decrement length
jnz @@nopc ; If not 0, we're not done with the sound
mov ax,0
mov [WORD PTR pcSound],ax ; Zero the pointer
mov [WORD PTR pcSound + 2],ax
mov [SoundNumber],ax ; Indicate no sound
mov [SoundPriority],ax ; with no priority
in al,pcSpeaker ; Turn the speaker off
and al,0fdh ; ~2
out pcSpeaker,al
@@nopc:
les di,[alSound] ; AdLib sound effects
mov ax,es
or ax,di
jz @@noal ; nil pointer - no AdLib effect going
xor ah,ah
mov al,[es:di]
or al,al
jz @@aldone
CALL alOut C,alFreqL,ax
mov ax,[alBlock]
@@aldone:
CALL alOut C,alFreqH,ax
inc [WORD PTR alSound]
dec [alLengthLeft]
jnz @@noal
mov ax,0
mov [WORD PTR alSound],ax ; Zero the pointer
mov [WORD PTR alSound + 2],ax
mov [SoundNumber],ax ; Indicate no sound
mov [SoundPriority],ax ; with no priority
CALL alOut C,alFreqH,ax ; Turn off the sound
@@noal:
ENDM
;
;
;
MACRO TIME
cmp [count_time],2
jb @@notime
add [LocalTime],1
adc [LocalTime+2],0
add [TimeCount],1
adc [TimeCount+2],0
mov [count_time],0
@@notime:
ENDM
;
; COMMONEND
; Macro used for common suffix code
;
MACRO COMMONEND
@@fullexit:
pop es
popa
@@nosave:
mov ax,[TimerDivisor]
add [TimerCount],ax
jnc @@myack
pushf
call [t0OldService]
jmp @@out
@@myack:
mov al,20h
out 20h,al
@@out:
pop ax
pop ds
IF DEBUG
mov dx,STATUS_REGISTER_1
in al,dx
mov dx,ATR_INDEX
mov al,ATR_OVERSCAN
out dx,al
mov al,3 ; blue
out dx,al
mov al,20h ; normal
out dx,al
pop ax
pop dx
ENDIF
iret
ENDM
;
; SDL_IndicatePC
;
PROC SDL_IndicatePC on:WORD
PUBLIC SDL_IndicatePC
mov ax,[on]
mov [cs:pcindicate],ax
ret
ENDP
;
; SDL_t0ExtremeAsmService
; Timer 0 ISR 7000Hz interrupts
;
PROC SDL_t0ExtremeAsmService
PUBLIC SDL_t0ExtremeAsmService
push ax
mov al,[BYTE PTR cs:pcindicate]
or al,al
jz @@done
push ds
push es
pusha
mov ds,[cs:MyDS]
les di,[pcSound]
mov ax,es
or ax,di
jz @@donereg ; nil pointer
mov bl,[es:di] ; Get the byte
inc [WORD PTR pcSound] ; Increment pointer
and bl,11100000b ; Nuke some of the precision (DEBUG - do this in the table)
xor bh,bh
mov ah,[pcdtab+bx] ; Translate the byte
in al,pcSpeaker
and al,11111100b
or al,ah
out pcSpeaker,al
dec [pcLengthLeft]
jnz @@donereg
mov [WORD PTR pcSound],0 ; We're done with this sample
mov [WORD PTR pcSound+2],0
in al,pcSpeaker
and al,11111100b
out pcSpeaker,al
call SDL_DigitizedDone
@@donereg:
popa
pop es
pop ds
@@done:
inc [cs:extreme]
cmp [cs:extreme],10
jae @@tofast
mov al,20h
out 20h,al
pop ax
iret
@@tofast:
mov [cs:extreme],0
pop ax
; jmp SDL_t0FastAsmService ; Drops through to SDL_t0FastAsmService
ENDP
;
; SDL_t0FastAsmService
; Timer 0 ISR for 700Hz interrupts
;
PROC SDL_t0FastAsmService
PUBLIC SDL_t0FastAsmService
COMMONSTART
inc [count_fx] ; Time to do PC/AdLib effects & time?
cmp [count_fx],5
jae @@dofull
mov ax,[sqActive] ; Is the sequencer active?
or ax,ax
jnz @@dofull
mov ax,[WORD PTR ssSample] ; Is there a sample for the Sound Src?
or ax,[WORD PTR ssSample+2]
jz @@nosave
@@dofull:
pusha
push es
cmp [count_fx],5
jb @@nofx
mov [count_fx],0
DOFX
inc [count_time]
TIME
@@nofx:
mov ax,[sqActive]
or ax,ax
jz @@nosq
mov ax,[sqHackLen]
or ax,ax
jz @@sqdone
les di,[sqHackPtr]
@@sqloop:
mov ax,[WORD PTR sqHackTime+2]
cmp ax,[WORD PTR alTimeCount+2]
ja @@sqdone
mov ax,[WORD PTR sqHackTime]
cmp ax,[WORD PTR alTimeCount]
ja @@sqdone
mov ax,[es:di+2] ; Get time to next event
add ax,[WORD PTR alTimeCount]
mov [WORD PTR sqHackTime],ax
mov ax,[WORD PTR alTimeCount+2]
adc ax,0
mov [WORD PTR sqHackTime+2],ax
mov ax,[es:di] ; Get register/value pair
xor bh,bh
mov bl,ah
xor ah,ah
CALL alOut C,ax,bx
add di,4
mov [WORD PTR sqHackPtr],di
sub [sqHackLen],4
jnz @@sqloop
@@sqdone:
add [WORD PTR alTimeCount],1
adc [WORD PTR alTimeCount+2],0
mov ax,[sqHackLen]
or ax,ax
jnz @@nosq
mov ax,[WORD PTR sqHack] ; Copy pointer
mov [WORD PTR sqHackPtr],ax
mov ax,[WORD PTR sqHack+2]
mov [WORD PTR sqHackPtr+2],ax
mov ax,[sqHackSeqLen] ; Copy length
mov [sqHackLen],ax
mov ax,0
mov [WORD PTR alTimeCount],ax ; Reset time counts
mov [WORD PTR alTimeCount+2],ax
mov [WORD PTR sqHackTime],ax
mov [WORD PTR sqHackTime+2],ax
@@nosq:
les di,[ssSample] ; Get pointer to Sound Source sample
mov ax,es
or ax,di
jz @@ssdone ; If nil, skip this
@@ssloop:
mov dx,[ssStatus] ; Check to see if FIFO has any empty slots
in al,dx
test al,40h
jnz @@ssdone ; Nope - don't push any more data out
mov dx,[ssData]
mov al,[es:di] ; al = *ssSample
out dx,al ; Pump the value out
mov dx,[ssControl] ; Pulse printer select
mov al,[ssOff]
out dx,al
push ax
pop ax
mov al,[ssOn]
out dx,al
push ax ; Delay a short while
pop ax
inc di
mov [WORD PTR ssSample],di ; ssSample++
dec [ssLengthLeft]
jnz @@ssloop
mov [WORD PTR ssSample],0 ; We're done with this sample
mov [WORD PTR ssSample+2],0
call SDL_DigitizedDone
@@ssdone:
COMMONEND
ENDP
;
; SDL_t0SlowAsmService
; Timer 0 ISR for 140Hz interrupts
;
PROC SDL_t0SlowAsmService
PUBLIC SDL_t0SlowAsmService
IF DEBUG
push dx
push ax
mov dx,STATUS_REGISTER_1
in al,dx
mov dx,ATR_INDEX
mov al,ATR_OVERSCAN
out dx,al
mov al,4 ; red
out dx,al
ENDIF
push ds
push ax
mov ds,[cs:MyDS]
inc [count_time]
TIME
mov ax,[WORD PTR pcSound] ; Is there a PC sound effect going?
or ax,[WORD PTR pcSound+2]
jnz @@dofull
mov ax,[WORD PTR alSound] ; Is there an AdLib sound effect going?
or ax,[WORD PTR alSound+2]
jz @@nosave
@@dofull:
pusha
push es
DOFX
COMMONEND
ENDP
END