diff --git a/bochs/iodev/display/voodoo_data.h b/bochs/iodev/display/voodoo_data.h index 3bde87c41..5f5a29cb1 100644 --- a/bochs/iodev/display/voodoo_data.h +++ b/bochs/iodev/display/voodoo_data.h @@ -1509,7 +1509,9 @@ struct _cmdfifo_info Bit32u depth; /* current depth */ Bit32u depth_needed; /* depth needed for command */ Bit32u holes; /* number of holes */ + Bit32u retAddr; bool cmd_ready; + bool jsr; }; diff --git a/bochs/iodev/display/voodoo_func.h b/bochs/iodev/display/voodoo_func.h index c8ce83c5b..42050fb25 100644 --- a/bochs/iodev/display/voodoo_func.h +++ b/bochs/iodev/display/voodoo_func.h @@ -2936,11 +2936,13 @@ Bit32u cmdfifo_r(cmdfifo_info *f) data = *(Bit32u*)(&v->fbi.ram[f->rdptr & v->fbi.mask]); f->rdptr += 4; - if (f->rdptr >= f->end) { - BX_INFO(("CMDFIFO RdPtr rollover")); - f->rdptr = f->base; + if (!f->jsr) { + if (f->rdptr >= f->end) { + BX_INFO(("CMDFIFO RdPtr rollover")); + f->rdptr = f->base; + } + f->depth--; } - f->depth--; return data; } @@ -2961,6 +2963,24 @@ void cmdfifo_process(cmdfifo_info *f) switch (code) { case 0: // NOP break; + case 1: // JSR + if (f->jsr) { + BX_ERROR(("cmdfifo_process(): JSR: already inside of subroutine")); + } else { + f->jsr = true; + f->retAddr = f->rdptr; + f->rdptr = (command >> 4) & 0xfffffc; + } + break; + case 2: // RET + if (!f->jsr) { + BX_ERROR(("cmdfifo_process(): RET: not inside of subroutine")); + } else { + f->rdptr = f->retAddr; + f->retAddr = 0; + f->jsr = false; + } + break; case 3: // JMP f->rdptr = (command >> 4) & 0xfffffc; if (f->count_holes) { @@ -3209,7 +3229,7 @@ void cmdfifo_process(cmdfifo_info *f) BX_ERROR(("CMDFIFO: unsupported packet type %d", type)); } f->depth_needed = cmdfifo_calc_depth_needed(f); - if (f->depth < f->depth_needed) { + if (!f->jsr && f->depth < f->depth_needed) { f->cmd_ready = 0; } }