Using a task list for multi-game or simultaneus game use

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
slobu
Posts: 275
Joined: Tue Jul 12, 2011 10:58 am

Using a task list for multi-game or simultaneus game use

Post by slobu »

What if you designed a game such that each routine was given a label 0-255. A single game would consist of a static array of 8-bit values that would prompt the game engine to jump to the coinciding routine.

I'm not sure what terminology this would fall into. Perhaps single-threading? A jump table?

Are there any advantages to this technique? I'm hoping that such a method would allow multiple games of the same cart. Also, two separate threads could be used for split screen games wherein each player could be running a different game.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Using a task list for multi-game or simultaneus game use

Post by tokumaru »

slobu wrote:What if you designed a game such that each routine was given a label 0-255. A single game would consist of a static array of 8-bit values that would prompt the game engine to jump to the coinciding routine.
This is already done in a lot of games to control the current game state, but I guess you could generalize it further to individual tasks within the game state.
I'm not sure what terminology this would fall into. Perhaps single-threading? A jump table?
Not sure either... A NES game would be single-threaded even without this technique, and a jump table table is just the mechanism to call the functions, but it doesn't describe the general idea at all.
Are there any advantages to this technique?
Not sure. Most games already are basically a chain of different systems running one after the other, only they're executed in a hardwired order. The only advantages of shuffling the order of the tasks I can think of is completely skipping unnecessary tasks in certain parts of the game or reusing individual systems in different engines, but we can kinda do that already.
I'm hoping that such a method would allow multiple games of the same cart.
I don't get it... You want to code some generic functions and chain them together in different ways in order to create different games?
Also, two separate threads could be used for split screen games wherein each player could be running a different game.
I guess so, as long as you have the RAM to keep track of both games (and they were programmed to make use of relocatable variables).
User avatar
Movax12
Posts: 529
Joined: Sun Jan 02, 2011 11:50 am

Re: Using a task list for multi-game or simultaneus game use

Post by Movax12 »

It's easier to store and work with an address than to store a gamestate variable. You can have substates that are also addresses, and just emulate a jsr indirect in place of say a jump table. This allows for saving of an address anywhere as well for a yield kind of functionality.
LocalH
Posts: 180
Joined: Thu Mar 02, 2006 12:30 pm

Re: Using a task list for multi-game or simultaneus game use

Post by LocalH »

slobu wrote:Also, two separate threads could be used for split screen games wherein each player could be running a different game.
This would be interesting, to see something like the Mixed Match from SNES Tetris & Dr. Mario.
slobu
Posts: 275
Joined: Tue Jul 12, 2011 10:58 am

Re: Using a task list for multi-game or simultaneus game use

Post by slobu »

Thanks for the replies, guys. The idea is half-baked. I'm thankful it got your attention.

The main reason I was thinking about a list of sub-routines to jump to is not only for mini-games but RPG Maker use. I could see storing the list in battery backed RAM.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Using a task list for multi-game or simultaneus game use

Post by tepples »

This "list of subroutines" has been used in real life as threaded code and return-oriented programming and bytecode.
JRoatch
Formerly 43110
Posts: 394
Joined: Wed Feb 05, 2014 7:01 am
Location: us-east
Contact:

Re: Using a task list for multi-game or simultaneus game use

Post by JRoatch »

Movax12 wrote:It's easier to store and work with an address than to store a gamestate variable. You can have substates that are also addresses, and just emulate a jsr indirect in place of say a jump table. This allows for saving of an address anywhere as well for a yield kind of functionality.
So I had a problem of handling multiple background tasks that wouldn't hog the main routine that executes every frame. First I tried a linked list of nmi interrupts in the stack. that was conceptually unwieldy. Next I tried a fixed task list only to realize that it was equivalent to lists of subroutines like tepples said. Recently I figured out that what I really wanted was coroutines and event loops, so I tried a routine that pushed an address at the bottom of the stack instead of the top like a jsr. That was closer to what I wanted, but that approach ended up with lots of house keeping code. After some tweaks I think I've got a fairly efficient pair of routines that implement the thread safe multitasking I wanted.

This could be written to that only the addresses are saved, but I'm anticipating I'm going to want saved pointers. I could also write this so that cpu registers are saved, but I'm experimenting with a particular calling convention which reserves X and expects Y to be 0.

EDIT: The code has been edited to only save addresses, and to be robust against overflowing the queue. Also the examples has been removed for space.

Code: Select all

.segment "ZEROPAGE"
sub_queue_head:             .res 1
sub_queue_tail:             .res 1

.segment "CODE"

sub_queue       = $0300 ; uses the low end of the page

;;
; queues the top of the return stack to the event loop,
;   and forces the caller to rts.
; This will cause the rest of the caller to execute
;   after the whole return stack unwinds.
.proc yield
  ; clc = pre increment
  ; sec = post increment
  sec
  lda #$00
  ; increment ptr and load into A atomically
  ; this way nmi can safely call yield even if normal
  ;   processes are executing yield as well.
  ; isc zp is an unofficial opcode that compiles to $E7
  isc sub_queue_head
  eor #$ff

  ; if queue is full, execute one item before pushing this.
  cmp sub_queue_tail
  bmi @queue_not_full
    pha
    jsr __execute_queued_routine
    pla
  @queue_not_full:

  and #%00011111    ; A = (sub_queue_head++)%32
  tay
  pla
  sta sub_queue+192+32*0, y
  pla
  sta sub_queue+192+32*1, y
  rts
.endproc

.proc event_loop_start
  lda #0
  sta sub_queue_head
  lda #32
  sta sub_queue_tail
    ;!; jmp event_loop
.endproc

.proc event_loop
  lda #>(event_loop-1)
  pha
  lda #<(event_loop-1)
  pha

  sec
  lda sub_queue_tail
  sbc #32
  ; busy loop until queue is not empty
  @wait_loop:
    cmp sub_queue_head
  beq @wait_loop
    ;!; jmp __execute_queued_routine
.endproc

.proc __execute_queued_routine
  ; atomic increment and load needs to happen here as well
  ; because this can be called by yield as well.
  sec
  lda #$00
  isc sub_queue_tail
  eor #$ff
  
  and #%00011111
  tay
  lda sub_queue+192+32*1, y
  pha
  lda sub_queue+192+32*0, y
  pha
  rts
.endproc
Last edited by JRoatch on Mon Oct 20, 2014 4:53 pm, edited 1 time in total.
User avatar
Dwedit
Posts: 4470
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Using a task list for multi-game or simultaneus game use

Post by Dwedit »

NES Games become multithreaded the instant you add interrupts.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
JRoatch
Formerly 43110
Posts: 394
Joined: Wed Feb 05, 2014 7:01 am
Location: us-east
Contact:

Re: Using a task list for multi-game or simultaneus game use

Post by JRoatch »

Right, but I'm making a distinction between a multi-threading and multi-tasking. Since I'm going to have some IO bound tasks (such as map decompression, and tile uploading), I want those tasks to yield their time to other tasks during the spare time before the next NMI.
User avatar
Movax12
Posts: 529
Joined: Sun Jan 02, 2011 11:50 am

Re: Using a task list for multi-game or simultaneus game use

Post by Movax12 »

Sounds like you want this idea: viewtopic.php?t=11075&p=126450
You can do a simplistic two thread setup by splitting the stack into two, and saving all the registers for a thread when you switch. (No recursion of course.)
So you could yield while waiting for NMI, and then force a yield when NMI hits.
JRoatch
Formerly 43110
Posts: 394
Joined: Wed Feb 05, 2014 7:01 am
Location: us-east
Contact:

Re: Using a task list for multi-game or simultaneus game use

Post by JRoatch »

Yes the async idea but not a multi stack implementation. I know this isn't a new idea, I think the only novel thing I did was the use of an unofficial opcode for thread safety.

For the multi-stack setup, why would you not be able to recurse if the entire stack is preserved on the context switch?

EDIT: clarifying which context switch I'm talking about.
Last edited by JRoatch on Mon Oct 20, 2014 6:19 pm, edited 1 time in total.
User avatar
Movax12
Posts: 529
Joined: Sun Jan 02, 2011 11:50 am

Re: Using a task list for multi-game or simultaneus game use

Post by Movax12 »

Actually, I guess that is not a limitation in this case.
Post Reply