Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to index page
Thread view  Board view
KarlG

28.05.2022, 21:59
 

Game sometimes crashes upon exit (Developers)

As I mentioned in a previous post, I am making a new game with CGA graphics, targeting the early PCs. I'm still early in the process; just drawing a few things to the screen. My issue is that about 1 out of every 10 times I run the game, it crashes after I exit. The crash takes various forms, usually locking up and not accepting input.

I think the crash is somehow related to my custom keyboard handler in some way. The keyboard handler itself seems to work fine, but the crash upon exit only seems to happen when it is enabled. Relevant code is below, and I'm also posting a link to a zip of the code and the binary (compiled with Watcom C compiler). Any thoughts or suggestions would be welcome!

Here is my custom keyboard routine:


// Use our own keyboard interrupt routine to track
// multiple keypresses and save CPU time.
void __interrupt __far NewKbdRoutine() {
    _asm {
        sti             // Enable higher-priority interrupts (timer)
        in al, 0x60     // Read raw keycode from keyboard buffer port
        xor ah,ah       // blank out high byte
        mov raw_key, ax // copy low byte to raw_key global variable
        in al, 0x61     // Read value from keyboard control port
        or al, 0x80     // set bit 7 in value
        out 0x61,al     // write value to keyboard control port
        and al,0x7F     // mask out bit 7
        out 0x61,al     // write value to keyboard control port
    }
    switch( raw_key )
        case KEY_UP_DOWN: {
            key_state |= UP_PRESSED;
            break;
       
        case KEY_DOWN_DOWN:
            key_state |= DOWN_PRESSED;
            break;
       
        case KEY_LEFT_DOWN:
            key_state |= LEFT_PRESSED;
            break;
       
        case KEY_RIGHT_DOWN:
            key_state |= RIGHT_PRESSED;
            break;
       
        case KEY_SPACE_DOWN:
            key_state |= SPACE_PRESSED;
            break;
       
        case KEY_ESCAPE_DOWN:
            key_state |= ESC_PRESSED;
       
        case KEY_X_DOWN:
            key_state |= ESC_PRESSED;
       
        case KEY_Q_DOWN:
            key_state |= ESC_PRESSED;
            break;
       
        case KEY_UP_UP:
            key_state &= ~UP_PRESSED;
            break;
       
        case KEY_DOWN_UP:
            key_state &= ~DOWN_PRESSED;
            break;
       
        case KEY_LEFT_UP:
            key_state &= ~LEFT_PRESSED;
            break;
       
        case KEY_RIGHT_UP:
            key_state &= ~RIGHT_PRESSED;
            break;
       
        case KEY_SPACE_UP:
            key_state &= ~SPACE_PRESSED;
            break;
                   
        default: break;
    }
    _disable(); // Interrups are re-disabled right before the EOI signal.
    outp( 0x20, 0x20 ); // EOI for interrupt
}


The custom keyboard handler is installed with this code:


    // Install new keyboard routine for speed
    // and multiple keypress detection
    OldKbdRoutine = _dos_getvect(KEYBOARD_INT);
    _dos_setvect(KEYBOARD_INT, NewKbdRoutine);


The old routine is restored in my program's exit function with the following code:


    _dos_setvect(KEYBOARD_INT, OldKbdRoutine);



A link to a zip of the source and binary may be found here:

CGAINV.ZIP

Thanks in advance for any advice! :-)

Japheth

Homepage

Germany (South),
29.05.2022, 06:21

@ KarlG
 

Game sometimes crashes upon exit

> Watcom C compiler). Any thoughts or suggestions would be welcome!

Since the crash occurs after the "old" interrupt vector has been restored, this saved vector most likely has been inadvertently modified.

Looking into the .map file to see the location of the saved vector:


074d:035d+     _FireHeld
074d:0af4+     _star_background
074d:2a34*     _ship_background_new
074d:2a4c*     _ship_sprite
074d:2a7c*     _ship_background_old
074d:2a94+     _OldKbdRoutine
074d:2a98+     _Sprites


As you can see, OldKbdRoutine is located behind star_background ( the symbols marked with "*" may be ignored since they are "unused" ).

star_background is defined as:


unsigned char star_background[8000];


and accessed:


        Offset = TempRand&0x1FFF;
        memset(star_background+Offset, Star, 1);


The problem is that 0x2000 is 8192, not 8000.

---
MS-DOS forever!

tkchia

Homepage

29.05.2022, 09:53

@ Japheth
 

Game sometimes crashes upon exit

Hello KarlG, hello Japheth,

> > Watcom C compiler). Any thoughts or suggestions would be welcome!
> Since the crash occurs after the "old" interrupt vector has been restored,
> this saved vector most likely has been inadvertently modified.

A few other thoughts that I have, regarding the sound handling:

(1) Why does KillSound() want to write to port 0x40? This port controls PIT 0, the timer that controls IRQ 0 — and has nothing to do with sound, which is controlled by PIT 2. The program should not need to reprogram PIT 0.

(2) At the same time, the program probably does need to temporarily disable interrupts while starting or stopping sound, so that an IRQ does not mess up the ongoing port I/O.

So this is what I would propose for the relevant portions:


void ProcessSound() {
    ...
    _disable();
    outp( 0x43, 0xB6 );
    outp( 0x42, Freq&0xFF );
    outp( 0x42, ( Freq>>8 ) );
    outp( 0x61, ( inp( 0x61 ) | 3 ) );
    _enable();
}

void KillSound() {
    _disable();
    outp( 0x61, ( inp( 0x61 ) & 0xFC ) );
    _enable();
}

Thank you!

---
https://gitlab.com/tkchia · https://codeberg.org/tkchia · 😴 "MOV AX,0D500H+CMOS_REG_D+NMI"

KarlG

29.05.2022, 15:26

@ tkchia
 

Game sometimes crashes upon exit

> Hello KarlG, hello Japheth,

> (1) Why does KillSound() want to write to port
> 0x40? This port controls PIT 0, the timer that controls IRQ 0
> — and has nothing to do with sound, which is controlled by PIT 2.
> The program should not need to reprogram PIT 0.

Good question. That comes from me copying from an example that I didn't fully understand. :-)

> (2) At the same time, the program probably does need to temporarily
> disable interrupts while starting or stopping sound, so that an IRQ does
> not mess up the ongoing port I/O.

Good point. I will follow both of your suggestions here. Thank you for your advice!

KarlG

29.05.2022, 15:24

@ Japheth
 

Game sometimes crashes upon exit

> Since the crash occurs after the "old" interrupt vector has been restored,
> this saved vector most likely has been inadvertently modified.
> star_background is defined as:

...

>
> unsigned char star_background[8000];
>

>
> and accessed:
>
>
> Offset = TempRand&0x1FFF;
> memset(star_background+Offset, Star, 1);
>

>
> The problem is that 0x2000 is 8192, not 8000.

D'oh! Thank you. That explains what I am seeing neatly. It also explains why the issues did not happen every time, since presumably sometimes my random star background routine didn't generate any values > 8000. Thanks again.

Back to index page
Thread view  Board view
22049 Postings in 2034 Threads, 396 registered users, 82 users online (1 registered, 81 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum