Jump to content
IGNORED

Animation playback on the TI-99/4A


Tursi

Recommended Posts

After that, build, load and run videoblaster.a99 from the distribution package (EA#3, program name MAIN), and your video should play.

 

attachicon.gifclassic99BigFileHack.zip

 

Output from assembling the pics and sound:

C:\Users\Jon\Desktop\tursi\5-sao_tipics>videopack.exe OUT converted_ti_sao_sound
 OUTPUT2TEST

OUT03034.tiap
3034 frames, Audio ended with 276 bytes left 

276 is pretty good! Lots less than 1500.

 

Tried to assemble the videoblaster.a99 with WinASM99 and keep getting some errors... Mostly an undefined SOUND label, as well as VDPWA/VDPWD labels (don't see them defined anywhere). Any ideas what I'm doing wrong?

 

Edit: Defined VDPWA and VDPWD in ASM99 settings... wasn't too sure what to define for SOUND equate though.

VDPWD  EQU  >8C00             * VDP write data
VDPWA  EQU  >8C02             * VDP set read/write address 

post-22866-0-47838800-1423417990_thumb.png

 

It's loading the output. Just need to get the video player going :) I tried equating SOUND to >8400 and some of the other equates and I get some really funky stuff when I try to run the modded Classic99 with the output file.

Link to comment
Share on other sites

Is there any discussion on how to do the audio encoding? On my list of conversions to do is Berzerk and I would like to include the speech with the option to do so without the Speech Synthesizer. I have attached samples for which I think our console-based playback is well-suited.

berzerk.zip

  • Like 3
Link to comment
Share on other sites

Tried to assemble the videoblaster.a99 with WinASM99 and keep getting some errors... Mostly an undefined SOUND label, as well as VDPWA/VDPWD labels (don't see them defined anywhere). Any ideas what I'm doing wrong?

Ah... see, that's what happens when I start using convenience tools, nobody else can use my code. ;) I am using the 'fav equ/defs' function in Asm994A.

 

That said, you defined them correctly, I'm not sure why it isn't playing for you. I'll check if the source file is messed up after work, in the meantime, here's a working obj file. I played your video - it corrupts after the boss is defeated - I'm not sure how many frames you originally had (it should loop in theory), but that suggests a byte (or more) is missing somewhere.

 

video.zip

Link to comment
Share on other sites

Is there any discussion on how to do the audio encoding? On my list of conversions to do is Berzerk and I would like to include the speech with the option to do so without the Speech Synthesizer. I have attached samples for which I think our console-based playback is well-suited.

I thought I talked about it, but I can't locate it. For game speech though, you'll either need a clever main loop or you'll have to pause the game to talk (Berzerk should allow for the former, though, and that would be bloody amazing).

 

You can look at the source for 'audioconvert' in my package, but the discussion that I thought I'd written up somewhere was pretty simple.

 

Basically, the straight-forward way to do it, is just to divide the audio down to 4-bit resolution. This actually works and sounds okay as long as the audio has reasonable volume. For soft things like the intro to Let It Go, I was getting very staticy or outright silent areas.

 

The second approach I tried, what I use in my MOD converter, was to map each audio level to the sound chip's logarithmic output (just using a simple search, there are only 16 values). This is technically more accurate reproduction, but loud audio loses a lot of resolution and quiet audio still suffered from the problem of ending up muted a lot. The main reason this is an issue is that audio goes positive and negative around a center point, but TI audio is (essentially) positive only, with all the resolution down near 0.

 

I /did/ attempt to map all audio positive - I tried two approaches. One was to swing negative transitions positive. This worked, but was crazy noisy. The other was to /discard/ negative transitions. Surprisingly, this /also/ worked and was less noisy. But playing the whole waveform centered in the TI space still sounded better. The problem was once you're in the center of the logarithmic scale, you've already lost a lot of the resolution available at the low end - that's now at the bottom of the curve.

 

So for this converter, I threw accuracy out the window, and hand-wrote a volume mapping table that emphasized softer sounds. That seems to work pretty well - although very loud sounds are now a little more staticy, at least EVERYTHING can be heard. ;) Each sample is just matched to the value in the table that it comes closest to.

 

It's just a sample mapper, your basic trick will be to determine the sample rate that your code outputs at. This video player is around 13khz. Since Berzerk used a speech chip, it was around 8khz, and you could probably easily get away with 4khz. That should give you room to play. :) The sample conversion doesn't care about the rate, you do that externally.

  • Like 1
Link to comment
Share on other sites

I /did/ attempt to map all audio positive - I tried two approaches. One was to swing negative transitions positive. This worked, but was crazy noisy. The other was to /discard/ negative transitions. Surprisingly, this /also/ worked and was less noisy. But playing the whole waveform centered in the TI space still sounded better. The problem was once you're in the center of the logarithmic scale, you've already lost a lot of the resolution available at the low end - that's now at the bottom of the curve.

 

Try this one. In GoldWave lower the volume (Effect, Volume, Change) to about half the power, then lift the sample into the positive (Effect, Offset). In both cases 50% should get you going. Or maybe that was about what you already did ?

Edited by sometimes99er
Link to comment
Share on other sites

Incredible! I guess cartoons work well because they are very colourful (i.e. not natural). Try this:

 

 

The above has an interesting mix of cartoon and "real life" footage. Be interesting to see how that comes out.

 

What about black and white stuff? If I might suggest any particular scene from one of the best films ever made:

 

 

:-D

Link to comment
Share on other sites

Sorry, Willsy, I can't download videos here, it's too unreliable. Greyscale should look good, though, I got good results when I added greyscale conversion to Convert9918.

 

I am just posting to confirm I looked at the assembler issues and yes, videoblaster.a99 is broken. This is where I admit that I screwed up and lost the source code, and had to re-create it from the cartridge version, then didn't test it. ;)

 

Here's the fixed source, and it is tested. I'll update the archive on my website in a couple of days, I want to update the docs to use ffmpeg and see whether using sox for audio would make the process scriptable.

 

 

 

* Final Version:

* Interleaved 8-bit code:

* 8-bit - 336578 cycles per frame

* Each frame has 6144 bytes of video, and 1544 bytes of audio.

* approximate output is:

* 8.9132 fps and 13762.04 Hz (but audio is best calculated

* as (frames * 6144) = samples / duration = rate)
SOUND EQU >8400

VDPWA EQU >8C02

VDPWD EQU >8C00
 DEF MAIN
source equ >7FFF * fake hardware for the moment

*     * should reset when >6000 is read

MAIN

 LIMI 0

 LWPI >8300

 

* * set up sound chip

 LI R0,>9FBF  * mute all channels

 MOVB R0,@SOUND

 SWPB R0

 MOVB R0,@SOUND

 LI R0,>DFFF

 MOVB R0,@SOUND

 SWPB R0

 MOVB R0,@SOUND

 LI R0,>8100  * highest frequency

 MOVB R0,@SOUND

 SWPB R0

 MOVB R0,@SOUND

 

* * set up bitmap

 BL @BITMAP

 

* * set up copy
* We /could/ get away with 3 blocks, and I did that originally.

* The idea of using four is to interleave the painting more so

* pattern updates are more closely followed by color udpates.

* it causes more obvious paints, but this looks better than the flicker.

 li r2,>0040  * start address table 1 >0000

 li r3,>0048  * start address table 2 >0800

 li r4,>004B  * start address table 5 >0B00

 li r5,>0050  * start address table 6 >1000

 li r6,>0060  * start address table 3 >2000

 li r7,>0068  * start address table 4 >2800

 li r8,>006B  * start address table 7 >2B00

 li r9,>0070  * start address table 8 >3000

 li r10,192  * size of one table divided by 4 (24*4*8/4)

 li r12,VDPWA

 LI r13,VDPWD

 li r14,source

 li r15,SOUND

 

*

* try to keep the cycles between sound writes about even

* the setup blocks need to be 2 cycles longer than the copy blocks

* to make up for the JNE fallthrough being 2 cycles shorter.

*

* Although the smaller code needs fewer bytes to VDP, to keep the

* code reasonably tight, we now need SIX copy loops.

*

* The data pattern needs to be (P=PATTERN, C=COLOR, S=Sound):

* 1  S

* 192 PPPPS first 1/3rd, chars 0-95

* 1  S

* 192 CCCCS

* 1  S

* 192 PPPPS second 1/3rd, chars 0-95

* 1  S

* 192 CCCCS

* 1  S

* 192 PPPPS second 1/3rd, chars 96-191

* 1  S

* 192 CCCCS

* 1  S

* 192 PPPPS third 1/3rd, chars 0-95

* 1  S

* 192 CCCCS

*

* Repeat - above sequence is first pattern data, then color data (color at >2000)

* We are interleaving the pattern and color through each table

*

*                                                  8Bit 16bit

OUTLOOP
* Pattern 1

 MOVB R2,*R12         30 26

 SWPB R2           14 10

 MOVB R2,*R12 * VDP address set    30 26

 SWPB R2           14 10

 SRL R0,8  * waste time     32 28

 SRL R0,7          30 26

 MOV R10,R0  * bytes to write divided by 4 18 14

 MOVB *R14,*R15 * write sound     38 34

*               220 192

LOOP1

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R15 * write sound     38 34

 DEC R0           14 10

 JNE LOOP1          14 10

*               218 190
* Color 1

 MOVB R6,*R12         30 26

 SWPB R6           14 10

 MOVB R6,*R12 * VDP address set    30 26

 SWPB R6           14 10

 NOP            14 10

 SRL R0,8  * waste time     32 28

 SRL R0,7          30 26

 MOV R10,R0  * bytes to write divided by 4 18 14

 MOVB *R14,*R15 * write sound     38 34

*               220 192
LOOP1c

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R15 * write sound     38 34

 DEC R0           14 10

 JNE LOOP1c          14 10

*               218 190
* Pattern 2

 MOVB R3,*R12         30 26

 SWPB R3           14 10

 MOVB R3,*R12 * VDP address set    30 26

 SWPB R3           14 10

 NOP            14 10

 SRL R0,8  * waste time     32 28

 SRL R0,7          30 26

 MOV R10,R0  * bytes to write divided by 4 18 14

 MOVB *R14,*R15 * write sound     38 34

*               220 192

 

LOOP2

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R15 * write sound     38 34

 DEC R0           14 10

 JNE LOOP2          14 10

*               218 190
* Color 2

 MOVB R7,*R12         30 26

 SWPB R7           14 10

 MOVB R7,*R12 * VDP address set    30 26

 SWPB R7           14 10

 NOP            14 10

 SRL R0,8  * waste time     32 28

 SRL R0,7          30 26

 MOV R10,R0  * bytes to write divided by 4 18 14

 MOVB *R14,*R15 * write sound     38 34

*               220 192
LOOP2c

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R15 * write sound     38 34

 DEC R0           14 10

 JNE LOOP2c          14 10

*               218 190
* Pattern 2b

 MOVB R4,*R12         30 26

 SWPB R4           14 10

 MOVB R4,*R12 * VDP address set    30 26

 SWPB R4           14 10

 NOP            14 10

 SRL R0,8  * waste time     32 28

 SRL R0,7          30 26

 MOV R10,R0  * bytes to write divided by 4 18 14

 MOVB *R14,*R15 * write sound     38 34

*               220 192

 

LOOP2b

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R15 * write sound     38 34

 DEC R0           14 10

 JNE LOOP2b          14 10

*               218 190
* Color 2b

 MOVB R8,*R12         30 26

 SWPB R8           14 10

 MOVB R8,*R12 * VDP address set    30 26

 SWPB R8           14 10

 NOP            14 10

 SRL R0,8  * waste time     32 28

 SRL R0,7          30 26

 MOV R10,R0  * bytes to write divided by 4 18 14

 MOVB *R14,*R15 * write sound     38 34

*               220 192
LOOP2bc

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R15 * write sound     38 34

 DEC R0           14 10

 JNE LOOP2bc          14 10

*               218 190
* Pattern 3

 MOVB R5,*R12         30 26

 SWPB R5           14 10

 MOVB R5,*R12 * VDP address set    30 26

 SWPB R5           14 10

 NOP            14 10

 SRL R0,8  * waste time     32 28

 SRL R0,7          30 26

 MOV R10,R0  * bytes to write divided by 4 18 14

 MOVB *R14,*R15 * write sound     38 34

*               220 192

 

LOOP3

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R15 * write sound     38 34

 DEC R0           14 10

 JNE LOOP3          14 10

*               218 190
* Color 3

 MOVB R9,*R12         30 26

 SWPB R9           14 10

 MOVB R9,*R12 * VDP address set    30 26

 SWPB R9           14 10

 NOP            14 10

 SRL R0,8  * waste time     32 28

 SRL R0,7          30 26

 MOV R10,R0  * bytes to write divided by 4 18 14

 MOVB *R14,*R15 * write sound     38 34

*               220 192
LOOP3c

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R13 * data       38 34

 MOVB *R14,*R15 * write sound     38 34

 DEC R0           14 10

 JNE LOOP3c          14 10

*               218 190
 JMP OUTLOOP          14 10
FINAL

 

 

* Setup for normal bitmap mode

* returns with video off - set VDP R1 to E2 to enable (>81E2)

SAVE BSS 2

BITMAP

 MOV R11,@SAVE
* set display and disable sprites

 LI R1,BMREGS

 BL @LOADRG

 

* set up SIT - We first fill with 255 bytes

 LI R0,>5800

 BL @VDPWTA

 LI R0,768

 LI R1,>FF00

LP#

 MOVB R1,@>8C00

 DEC R0

 JNE LP#

 

* Now special setup for each table - we have 16 rows

* of 24 chars each.

* First table is 4 rows and so starts at row 4

* Indent is 4 chars on each side, so start at 4

 LI R0,>5884 * address

 CLR R1  * char to write

 LI R2,4  * rows left

 BL @WRITEBK

 

* Second table is 8 rows and starts at row 8

 LI R0,>5904 * address

 CLR R1  * char to write

 LI R2,8  * rows left

 BL @WRITEBK

 

* third table is 4 rows and starts at row 16

 LI R0,>5A04 * address

 CLR R1  * char to write

 LI R2,4  * rows left

 BL @WRITEBK

 

 MOV @SAVE,R11

 B *R11
SAVE2 BSS 2
WRITEBK

 MOV R11,@SAVE2

LPA1 

 BL @VDPWTA * set address

 LI R3,24 * chars left

LPA2

 MOVB R1,@>8C00

 AI R1,>0100 * next char

 DEC R3

 JNE LPA2 * column loop

 

 AI R0,32 * next row

 DEC R2

 JNE LPA1 * row loop

 

 MOV @SAVE2,R11

 B *R11
* registers for bitmap (and 5B00 is the address of the sprite table)

* background is transparent (the only color never redefined)

* PDT - >0000

* SIT - >1800

* SDT - >1800

* CT  - >2000

* SAL - >1B00

BMREGS DATA >81E0,>8002,>8206,>83ff,>8403,>8536,>8603,>8700,>5B00,>0000
* load regs list to VDP address, end on >0000 and write >D0 (for sprites)

* address of table in R1 (destroyed)

LOADRG

LOADLP

 MOV *R1+,R0

 JEQ LDRDN

 SWPB R0

 MOVB R0,@>8C02

 SWPB R0

 MOVB R0,@>8C02

 JMP LOADLP

LDRDN

 LI R1,>D000

 MOVB R1,@>8C00

 B *R11
* Write address or register

VDPWTA

 SWPB R0

 MOVB R0,@>8C02

 SWPB R0

 MOVB R0,@>8C02

 B *R11 


 END

 

 

 

Link to comment
Share on other sites

And here it is!

 

You'll have to forgive a Windows app instead of a script, but since all my other stuff is, what's one more? ;)

 

I haven't published this package yet, so it's just in my temp folder, but, unpack this, and it comes with all the tools needed. /IF/ I did it right, you don't need any extra packages or DLLs installed.

 

What's it do? Run "tividconvert myVideoFile.mpg", and in a little while you'll have both a raw and cartridge version of your video file.

 

The one gotcha that I noticed that isn't in the readme file is if your aspect ratio is taller than 4:3, you'll get a white edge on your video - it can only crop horizontally. The one gotcha that IS in the readme file, is that it will fail after all the hard work if there's no audio stream - so make sure your video file has an audio track, or a lot of time will be wasted. ;) So use a converter to size appropriately and add an audio track if needed.

 

Since it uses ffmpeg, it can manage any video file ffmpeg can. ;) The maximum raw output file is unlimited (but if you want to play it in Classic99, it will be fully loaded into RAM), and the maximum cartridge image is 32MB (it will write larger, but won't bother to pad it.)

 

I also updated Classic99 - the current version crashes if you load a 378 type file larger than 2MB. I rolled the command-line hack for 'big file hack' mode into the release as well.

 

Anyway... current location: http://www.harmlesslion.com/temp/TIVidConvert.zip

 

  • Like 4
Link to comment
Share on other sites

It's just the money for nothing video (see further up in this thread). I'm not expecting very good results. I think it's too demanding too many colours. An old fashioned cartoon like Tom and Jerry might give excellent results. Still, it'll be great to get Dire Straits blasting out of a TI :-)

  • Like 1
Link to comment
Share on other sites

Classic99 will only load 2MB carts. To play longer videos don't use the cart version, use the command line hack to pass in the packed output file (not the 8.BIN, the other one). Then EA#3 load videoblaster.obj (should be included), program name MAIN.

 

I use Open Broadcaster Software to do my captures of Classic99, Willsy. It's worked for everything I've got and is my current fav. It has the additional benefit of being able to stream, but it records just fine.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...