I'm still working on my game project (a text-based dungeon crawl in the tradition of several DOS-based BBS door games), although it's coming along further. I ran into a design problem, though, and I'd like some input on my stop-gap solution.
With my current approach the stack will eventually overflow if the user dies and either starts a new game or loads from a previous save several times in a single program execution. My tentative fix is to save SP right before the main loop that calls all other branching functions, and in the event the player restarts I restore that SP value and jump back to the beginning of that main loop. Here are some code snippets, TASM syntax:
[code] public SP_STATE, GAME_RESET
SP_STATE dw 0 ;Stack Pointer state stored for game resetting
; to keep stack from overflowing.
GAME_RESET dw DrawMenu ;Offset of DrawMenu for resetting game.
.
.
.
public TextDungeon
extrn ReadByte:proc, ClearScreen:proc, WriteString:proc
extrn SendCRLF:proc, GotoXY:proc, WriteChar:proc
extrn RandomMonster:proc, ResetChar:proc
TextDungeon proc
push ax
push bx
push dx
mov [SP_STATE],sp ;Save SP to SP_STATE for later reset
DrawMenu:
call ClearScreen
xor dx,dx
call GotoXY ;Put cursor at 0,0 (top left)
mov dx,[CurrentMenu]
call WriteString ;Draw menu and prompt
lea dx,[MenuPrompt]
call WriteString
.
.
.
[/code]
And here is the current SP resetting procedure:
[code]
public RenewGame
extrn ClearScreen:proc, ChangeName:proc, TextDungeon:proc
extrn ResetChar:proc
.data
extrn SP_STATE:word, GAME_RESET:word
.code
RenewGame proc
call ClearScreen
call ResetChar
call ChangeName
mov ax,[GAME_RESET]
mov sp,[SP_STATE]
jmp ax ;Jump to TextDungeon DrawMenu label.
mov ax,4C99h ;Should never be reached but gives error
int 21h ; and exits if it happens...
RenewGame endp[/code]
I've read repeatedly that SP should never be modified directly unless you know exactly what you're doing, given that a system interrupt can occur in the middle of the process and bring the whole thing to an ugly, grinding halt. I've done my best to ensure that the IP change happens immediately after the SP change, which seems to me like it should minimize the chance of a problem down to the smallest it can get.
Is this a good way to do things or should I suck it up and fix my short-sighted design?
With my current approach the stack will eventually overflow if the user dies and either starts a new game or loads from a previous save several times in a single program execution. My tentative fix is to save SP right before the main loop that calls all other branching functions, and in the event the player restarts I restore that SP value and jump back to the beginning of that main loop. Here are some code snippets, TASM syntax:
[code] public SP_STATE, GAME_RESET
SP_STATE dw 0 ;Stack Pointer state stored for game resetting
; to keep stack from overflowing.
GAME_RESET dw DrawMenu ;Offset of DrawMenu for resetting game.
.
.
.
public TextDungeon
extrn ReadByte:proc, ClearScreen:proc, WriteString:proc
extrn SendCRLF:proc, GotoXY:proc, WriteChar:proc
extrn RandomMonster:proc, ResetChar:proc
TextDungeon proc
push ax
push bx
push dx
mov [SP_STATE],sp ;Save SP to SP_STATE for later reset
DrawMenu:
call ClearScreen
xor dx,dx
call GotoXY ;Put cursor at 0,0 (top left)
mov dx,[CurrentMenu]
call WriteString ;Draw menu and prompt
lea dx,[MenuPrompt]
call WriteString
.
.
.
[/code]
And here is the current SP resetting procedure:
[code]
public RenewGame
extrn ClearScreen:proc, ChangeName:proc, TextDungeon:proc
extrn ResetChar:proc
.data
extrn SP_STATE:word, GAME_RESET:word
.code
RenewGame proc
call ClearScreen
call ResetChar
call ChangeName
mov ax,[GAME_RESET]
mov sp,[SP_STATE]
jmp ax ;Jump to TextDungeon DrawMenu label.
mov ax,4C99h ;Should never be reached but gives error
int 21h ; and exits if it happens...
RenewGame endp[/code]
I've read repeatedly that SP should never be modified directly unless you know exactly what you're doing, given that a system interrupt can occur in the middle of the process and bring the whole thing to an ugly, grinding halt. I've done my best to ensure that the IP change happens immediately after the SP change, which seems to me like it should minimize the chance of a problem down to the smallest it can get.
Is this a good way to do things or should I suck it up and fix my short-sighted design?