Shop OBEX P1 Docs P2 Docs Learn Events
Sega SC-3000 emulated on a PropC3 equipped with a C3Synapse — Parallax Forums

Sega SC-3000 emulated on a PropC3 equipped with a C3Synapse

digimorfdigimorf Posts: 74
edited 2012-10-21 14:45 in Propeller 1
Hi to everybody!

Here it is the first video of the early working version of the Sega SC-3000 emulator for the PropC3+C3Synapse.

This video shows the Parallax PropC3 unit, equipped with a C3Synapse memory expansion, that run the Sega SC-3000 emulator for Propeller. As I have said, this is an early version of the emulator and still needs to be bug fixed but, it can run already many games such as: Exerion, Champion boxing, Ninja princess, Pacar, Star force and many others.
( Sorry for the quality of the video, my camera really as to be changed! :) )

The Sega SC-3000 system is emulated by the Propeller present in the PropC3 unit and uses the memory space on the expansion memory C3Synapse for the Z80 emulation. In addiction I have built a simple parallel Joystick interface that uses the free IO pins left on the PropC3 unit.


The emulator is configured as follows:

Z80:
This is the customized version of the zq80 program by Pulmoll http://forums.parallax.com/showthread.php?121579-qZ80-the-third-shot&highlight=qz80
The Z80 uses the SRAM memory space of the C3Synapse as fast as possible. In order to do that I had to make a customized version of the qz80 by Pullmoll.

VDP:
This is the TMS9928 driver that I'm developing. The actual version is completely in ASM and has the IO interface embedded. It uses 16Kb of shared memory as fast VRAM.

PSG:
This is the SN76489 driver used by my VGM music player. It has been updated and the length of the code reduced to save memory for the emulator. Actually there is the stable version of the SN76489 available in the OBEX section of the Parallax site: http://obex.parallax.com/objects/891/

The memory mapper program actually is really simple and has is embedded in each emulated chip. It has to be improved.

In the future I will embed a boot loader in the emulator, something like that shown in this video that I made some time ago:
http://www.youtube.com/watch?v=0q_NxV6mi0I&feature=g-upl

And as soon as I will have a stable alpha version I will start publishing the source code within the Parallax forum.
Enjoy for now!

Comments

  • Bill HenningBill Henning Posts: 6,445
    edited 2012-10-18 05:58
    Very cool!

    Well done Francesco, more emulation for the prop is a good thing...
    digimorf wrote: »
    Hi to everybody!

    Here it is the first video of the early working version of the Sega SC-3000 emulator for the PropC3+C3Synapse.

    This video shows the Parallax PropC3 unit, equipped with a C3Synapse memory expansion, that run the Sega SC-3000 emulator for Propeller. As I have said, this is an early version of the emulator and still needs to be bug fixed but, it can run already many games such as: Exerion, Champion boxing, Ninja princess, Pacar, Star force and many others.
    ( Sorry for the quality of the video, my camera really as to be changed! :) )

    The Sega SC-3000 system is emulated by the Propeller present in the PropC3 unit and uses the memory space on the expansion memory C3Synapse for the Z80 emulation. In addiction I have built a simple parallel Joystick interface that uses the free IO pins left on the PropC3 unit.


    The emulator is configured as follows:

    Z80:
    This is the customized version of the zq80 program by Pulmoll http://forums.parallax.com/showthread.php?121579-qZ80-the-third-shot&highlight=qz80
    The Z80 uses the SRAM memory space of the C3Synapse as fast as possible. In order to do that I had to make a customized version of the qz80 by Pullmoll.

    VDP:
    This is the TMS9928 driver that I'm developing. The actual version is completely in ASM and has the IO interface embedded. It uses 16Kb of shared memory as fast VRAM.

    PSG:
    This is the SN76489 driver used by my VGM music player. It has been updated and the length of the code reduced to save memory for the emulator. Actually there is the stable version of the SN76489 available in the OBEX section of the Parallax site: http://obex.parallax.com/objects/891/

    The memory mapper program actually is really simple and has is embedded in each emulated chip. It has to be improved.

    In the future I will embed a boot loader in the emulator, something like that shown in this video that I made some time ago:
    http://www.youtube.com/watch?v=0q_NxV6mi0I&feature=g-upl

    And as soon as I will have a stable alpha version I will start publishing the source code within the Parallax forum.
    Enjoy for now!
  • Ahle2Ahle2 Posts: 1,179
    edited 2012-10-18 13:11
    This is an achievement, well done!

    /Johannes
  • Heater.Heater. Posts: 21,230
    edited 2012-10-18 13:30
    Incredible, fantastic, brilliant. Well done.
    Looks like I need to get hold of a C3:)
  • digimorfdigimorf Posts: 74
    edited 2012-10-19 09:02
    Thank you guys,
    I must admit that I'm going very slow in this project but little by little things seem to work out.

    There is still the boot loaded to be done for loading roms into the C3Synapse. Actually the rom loader is run from the ram of the PropC3, then it reboots the C3 that loads the emulator from the eeprom. There is no more space for a boot loader within the emulator since half of the ram is taken by the TMS9928 VRAM ( 16 KB ), and 9,8KB are taken by the qz80.
    I had to fit the TMS9928 vdp main driver, the renderer with lookup tables, the tv driver and the SN76489 in almost 6KB, and leave some space for the line buffer and memory maspped registers for the VDP.
    Not easy.

    I think that If I split the emulator in 2 Propellers, one on the PropC3 and an external one placed on some board on top of the C3Synapse, maybe I can have more chances to complete this emulator, and maybe to have more resources to go beyond with a Sega Master System emulation.
    But this is not in my plans right now.
  • JT CookJT Cook Posts: 487
    edited 2012-10-20 23:23
    Very nice! How does the speed compare with the actual console?
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-10-21 02:17
    Wow, this looks fun.

    What sort of speed are you getting the Z80 to run. I never got it much over 2Mhz, and the Sega is 3.57Mhz. Are you using a cache for the ram?

    I wonder if it would run on a touchscreen? I'm working at the moment on a hybrid propeller and a real Z80 chip as I think there are some clever things we can do.

    Are you reusing space in hub ram after a cog is loaded?
  • digimorfdigimorf Posts: 74
    edited 2012-10-21 14:11
    JT Cook wrote: »
    Very nice! How does the speed compare with the actual console?
    Dr_Acula wrote: »
    Wow, this looks fun.

    What sort of speed are you getting the Z80 to run. I never got it much over 2Mhz, and the Sega is 3.57Mhz. Are you using a cache for the ram?

    Hi guys, thank you very much.
    I haven't implemented any cache yet, nor measured speed, nor implemented any "frame skip" method to increase emulation speed like I did for my Flash Action Script emulators. The first goal was to make all games work.

    Almost the 75% of the games now work, but I had to reduce the code of the qz80 in some places to save some machine cycles. The actual memory access routines for the C3Synapse are the following:
    '***************************************************************************************************************
    '       Memory access functions (C3Synapse)
    '***************************************************************************************************************
    
    
    ' Pin definitions for accessing the HC138
     CMD_DATA_OUT_DIR      long    000000_00000111_00000000_11111111
     DATA_Reset            long    111111_11111111_11111111_00000000
     CMD_DATA_Reset        long    111111_11111000_11111111_00000000
     CMD_Reset             long    111111_11111000_11111111_11111111
    
    
    ' Command for accessing the HC138  
      WrCmd                 long    01_00000000_00000000
      RdCmd                 long    10_00000000_00000000
      SetMd                 long    00_00000000_00000000
      SetHi                 long    01_00000000_00000000
      SetLo                 long    10_00000000_00000000
    
    
    '***************************************************************************************************************
    {┌─────────────────────────────────────────────────────────────┐
     │ _rd_byte , input: Address, Byte, Num output: void           │
     └─────────────────────────────────────────────────────────────┘
     - Write at arg0 Address, arg2 Num bytes arg1 byte into Synapse -
    
    
     DATA_Reset         111111_11111111_11111111_00000000
     CMD_Reset          111111_11111000_11111111_11111111
    
    
     RdCmd              10_00000000_00000000    Activates line 2 of multiplexer 74HC138
    
    
     This routine reads a single byte by first setting up the memory address. It performs a "RANDOM ACCESS MEMORY" on Synapse
     }
     
    rd_byte
    rd_rom
    rd_ram
                    call  #ram_address            ' sets up the latches with the correct ram address
    
    
                    and   dira, DATA_Reset        ' setup the input direction for data
                    or    outa, RdCmd             ' setup the read command
                    mov   alu, ina                ' get value from the data bus
                    and   outa, CMD_Reset         ' reset command bits to finalize command
                    or    dira, CMD_DATA_OUT_DIR  ' set data bus direction back to output
                    and   alu, #$ff               ' extract 8 bits
    rd_byte_ret
    rd_opcode_ret
    rd_byte_hl_ret
                    ret
    
    
    '***************************************************************************************************************
    {┌─────────────────────────────────────────────────────────────┐
     │ _wr_byte, input: address word, data byte, output: void      │
     └─────────────────────────────────────────────────────────────┘
     - Write at arg0 Address, a byte arg1 into Synapse -
    
    
     CMD_Reset          111111_11111000_11111111_11111111
    
    
     WrCmd              01_00000000_00000000     Activates line 1 of multiplexer 74HC138
    
    
     This routine writes a single byte by first setting up the memory address. It performs a "RANDOM ACCESS MEMORY" on Synapse
    
    
     }
    wr_byte
    wr_ram
                    cmp   ea, #romlimit wz,wc
               if_b jmp   #wr_byte_ret
    
    
                    call  #ram_address      ' sets up the latches with the correct ram address
    
    
                    mov   outx, alu         ' get the byte to output
                    or    outa, outx        ' prepare data on the bus
                    or    outa, WrCmd       ' set command bits to value 1
                    and   outa, CMD_Reset   ' reset command bits
    wr_byte_ret
                    ret
    
    
    romlimit        long  $C000
    '***************************************************************************************************************
    {┌─────────────────────────────────────────────────────────────┐
     │ _setAddress , input: address word, output: void             │
     └─────────────────────────────────────────────────────────────┘
     - Sets the address to write/read on Synapse -
    
    
     CMD_DATA_Reset    111111_11111000_11111111_00000000
    
    
     SetMd             00_00000000_00000000  Activates line 4 of multiplexer 74HC138
     SetLo             10_00000000_00000000  Activates line 6 of multiplexer 74HC138
    
    
     The address is set by updating two nibbles of the address ( 64KB of memory space ).
     Each nibble is updated when its value is sent to Synapse by outputting
     to the C3 pins 16..18 the proper value, and reset the command with a null value
     }
    
    
    ram_address     mov   outx, ea                  ' get the address into a temp variable
                    and   outx, #$FF
                    mov   outa, outx                ' prepare the value on port
                    or    outa, SetLo               ' send the command to multiplexer to drive the first latch
                    and   outa, CMD_Reset           ' reset the data bus
    
    
                    mov   outx, ea                  ' get the address into a temp variable
                    shr   outx, #8                  ' shift right by 8 places
                    mov   outa, outx                ' prepare the value on port
                    or    outa, SetMd               ' send the command to multiplexer to drive the second latch
                    and   outa, CMD_Reset           ' reset the data bus
    
    
                    mov   outa, #0                  ' prepare the value on port, 0 because the address range is up to 64k
    ram_address_ret
                    ret
    
    
    '***************************************************************************************************************
    

    As you can see the access to the C3Synapse is very simple, and here the access to the memory space is from 0 to $FFFF, so I handle only two nibbles of the address. This saves a lot of time. The memory mapper of the SEGA SC-3000 is pretty simple, so I removed all memory access tables and put only one control on the write routine. The SEGA SC-3000 has only 2KB of DRAM mapped from $C000. Considering that the Z80 can handle 64KB a time, and the SEGA SC-3000 only use that memory space, it's useless to update everytime the third nibble of the address.

    Some games run almost at the same speed of a real machine, others are really slow, mostly the sprites move very slow, not the background music. That means to me that there's something that can still be done to improve the speed.

    Exerion for example, one of the games in the video, is really fast, more than I expected. I still have to see that but I haven't so mush time now. I'm studying something else. But right now I'm really happy and proud of what's coming out from this emulator :)
    Dr_Acula wrote: »
    I wonder if it would run on a touchscreen? I'm working at the moment on a hybrid propeller and a real Z80 chip as I think there are some clever things we can do.

    Uhm, I'm not sure about that. Now I have only one cog free, so that should drive the touch screen. But, the controls for the SC-3000, I mean in the real machine, it's provided by a Intel8255, so the Z80, when accesses the PPI port expect to read data from the keyboard matrix. This means that the z80 writes one byte to enable one column of the matrix, then it reads 2 bytes from the rows. In the emulated machine I only control the joystick, so I can reduce the code and embed it in the qz80 code:
    '***************************************************************************************************************
    ' Write a byte from the alu to an I/O port
    '
    wr_port         mov     io_port, ea
    
    
                    cmp     io_port, #$7F   wz  ' the PSG port
               if_z jmp     #wr_port_set
                    cmp     io_port, #$BF   wz  ' the VDP Register port 
               if_z jmp     #wr_port_set
                    cmp     io_port, #$BE   wz  ' the VDP Data port
               if_z jmp     #wr_port_set
    
    
                    jmp     #wr_port_ret
    
    
    wr_port_set     mov     t1, #1
                    shl     t1, #16
                    or      t1, ea
                    shl     t1, #8
                    or      t1, alu
                    wrlong  t1, io_command
    :wait           rdlong  t1, io_command                  '...and wait for it to be completed.
                    shr     t1, #24         WZ, NR
            if_nz   jmp     #:wait
    wr_port_ret
                    ret
    
    
    '***************************************************************************************************************
    ' Read a byte from an I/O port into the alu
    '
    rd_port         mov     io_port, ea
                    and     io_port, #$FF
    
    
                    cmp     io_port, #$DC   wz    '  the first PPI port 
               if_z jmp     #read_A
                    cmp     io_port, #$DD   wz    '  the second PPI port ( actually not used )
               if_z jmp     #read_B
    
    
                    cmp     io_port, #$BF   wz  ' the VDP Register port 
               if_z jmp     #rd_port_set
                    cmp     io_port, #$BE   wz  ' the VDP Data port 
               if_z jmp     #rd_port_set
    
    
                    jmp     #rd_port_ret
    
    
    rd_port_set     mov     t1, #2
                    shl     t1, #16
                    or      t1, ea
                    shl     t1, #8
    rd_port_cmd
                    wrlong  t1, io_command
    :wait           rdlong  t1, io_command                
                    shr     t1, #24         WZ, NR
            if_nz   jmp     #:wait
                    mov     alu, t1
                    and     alu, #$ff
    rd_port_cmd_ret
    rd_port_ret
                    ret
    '*******************************************
    ' Pins checked are from P19 to P22 ( direction buttons ), and P26,P27 ( triggers )  of the PropC3 Bus, the ones you can see from the video
    
    
    read_A          andn    dira, dirmask
                    mov     alu, ina
                    mov     movements, alu
                    shr     movements, #19
                    and     movements, #%1111
                    mov     triggers, alu
                    shr     triggers, #26
                    and     triggers, #%11
                    shl     triggers, #4
                    or      movements, triggers
                    or      movements, #%11000000
                    mov     alu, movements
    
    
                    jmp     #rd_port_ret
    
    
    read_B          mov     alu, #$FF
                    jmp     #rd_port_ret
    
    
                    io_port   long 0
                    dirback   long 0
                    dirmask   long %00001100_01111000_00000000_00000000
                    movements long 0
                    triggers  long 0
    '***************************************************************************************************************
    
    
    
    Dr_Acula wrote: »
    Are you reusing space in hub ram after a cog is loaded?

    No. The hub ram is full. 16KB used by the TMS9928 as VRAM, and 9,8KB are used by the qz80. The other memory is used by the VDP program code ( driver, renderers and TV driver )
  • Toby SeckshundToby Seckshund Posts: 2,027
    edited 2012-10-21 14:45
    With my tin hat and asbestos knickers on -

    Have you seen the AX81, AX81b and AX82 stuff.
Sign In or Register to comment.