-
Posts
545 -
Joined
-
Last visited
-
Days Won
1
Content Type
Profiles
Forums
Blogs
Gallery
Events
Store
Posts posted by PeteE
-
-
The speech synth doesn't pass through 5v power, so that's probably why it doesn't work. If the backbit 32k has an external power connector, you'll need to power it that way.
Edit: From photos, it appears to not have ext power. So it cannot be used with the speech synth between it and the side port.
- 2
-
4 hours ago, Willsy said:
Compiled fine on my Mint system (once I installed SDL lib!) - it's asking for the rom files -
Failed to load ROM/GROM files: 994arom.bin 994agrom.bin
Any pointers? Thanks
Mark
They can be gotten from here https://ftp.whtech.com/System ROMs/MAME/pre_0.174/ti99_complete.zip nested inside the ti99_4a.zip
- 2
-
2 hours ago, gferluga said:
How do I map a DSK floppy disk drive image?
Thanks!
Disk IO hasn't been done yet, sorry 😓
- 1
-
1 hour ago, OLD CS1 said:
That is fine. As customer service becomes a lost art, as a free market entrepreneur I see the opportunity for a new experience to arise from the ashes: a place where you can shop which has courteous and helpful employees. The kind of employees who give way when you come down the aisle; the kind who will reach up to shelves for you; the kind who do not have their cell phones in their hands when they see you; the kind who do not have personal conversations with each other while you stand there waiting to "butt in" for assistance; the kind who do no wear their pants below their ass cracks. Oh, what a glorious future we have before us!
Tell me more, Mr. Harry Gordon Selfridge!
- 4
-
Okay, this is what I see on the FinalGrom menu:
Before I didn't notice the blank A item above the B parent directory item. Seems like the custom font messes up the directory sorting, and since there are no character patterns defined for the custom font, it appears blank. Selecting A does load the Ghostbusters game properly! But resetting console doesn't run the custom load routine; in fact, nothing appears in the menu at all, only "1 FOR TI BASIC".
@HOME AUTOMATION has a fix for the reset and menu. I tested it and it works.
- 3
- 1
-
3 hours ago, TheMole said:
Oh, no, you absolutely can enjoy this on the finalgrom! Just put gbustg.bin and gbust8.bin on your SD card, and I think it should appear in the FG99 menu. I haven't been able to test if it works on real hardware yet, so if you've tried that and it doesn't work, I need to figure out why .
I tried it on my FinalGrom and it doesn't appear in the menu. I tried putting it in its own folder, and also tried renaming to "gbust8.bin" to "gbustc.bin" because I think that's what the FG99 requires. I suspect it might not like something in the GROM header?
- 2
-
4 minutes ago, OLD CS1 said:
How difficult would it be to use the GPU as a blitter to do that?
That depends on how much GPU RAM is left over after both TL1 and TL2 name and attribute tables, ECM3 patterns and ECM3 sprites. The level data needs to be stored somewhere.
Edit: oh... blitter as a block transfer, to move the data in the name+attr tables up/down/left right. Yeah, that would work. Good idea!
-
7 minutes ago, matthew180 said:
That is the native functionality if you just start changing the scroll registers without any masking (from TL2, etc.) or setting up the additional name tables.
I meant with future 34x26 border scroll functionality. I would rather have the scroll wrap instead of needing to rewrite the whole name table every 8 pixels scroll.
-
3 hours ago, matthew180 said:
This does mean after scrolling 8 pixels in any direction you will have to reset the scroll and tile-shift the whole name table, but you eventually have to do this anyway. With this technique the name table only needs to grow by 116 bytes, i.e. 768 to 884 (1088 in ROW30), which is way less memory than doubling or quadrupling the name table space for each layer.
Would it be possible to allow the scroll to wrap at the edges? On the right side: 33 to 0, and at the bottom: 25 to 0 (or 31 to 0 w/ ROW30).
I also can think of a situation where I would want BM layer on top of both TL1 and TL2.
-
Hi Lily and Robyn!
Great work on your first assembly language game! You have a great career ahead of you in retrocoding, haha.
My only tip for you is to use the DORG (Dummy ORiGin) to generate your variable labels without having to calculate the offsets all by hand. It does not generate any object code, so you can use BYTE, DATA or BSS directives to specify how much size should be allocated to each variable. The DORG needs to outside of your AORG section. You should also generate a listing file so and check your variable offsets to make sure you haven't exceeded the fast RAM memory space.
IDT 'SNAKE' DORG >8320 HDCOL BYTE 0 HDROW BYTE 0 TLCOL BYTE 0 TLROW BYTE 0 SNDIR BYTE 0 WAITHI BYTE 0 WAITLO BYTE 0 SNDIR2 BYTE 0 SCR1 BYTE 0 SCR2 BYTE 0 SCR3 BYTE 0 NM1 BYTE 0 NM2 BYTE 0 NM3 BYTE 0 HSCR1 BYTE 0 HSCR2 BYTE 0 HSCR3 BYTE 0 CSCR1 BYTE 0 CSCR2 BYTE 0 CSCR3 BYTE 0 PSET BYTE 0 DORG >837D VDPCHR BYTE 0 VDPROW BYTE 0 VDPCOL BYTE 0 * The BYTE values don't matter, no data is being written AORG >6000 ...
You could also combine WAITHI and WAITLO into a single word "WAIT DATA 0", but make sure it is on an even address by putting an "EVEN" directive on the previous line. Then instead of this:
LI R0,>0001 MOVB @R0LB,@WAITHI LI R0,>00A0 MOVB @R0LB,@WAITLO
You could do this:
LI R0,>01A0 MOV R0,@WAIT
Hope that is helpful. Looking forward to seeing what else you can make.
- 5
-
1 hour ago, khanivore said:
Looks like the parity bit - Yeah I never bothered implementing that one
FYI the tester uses an AB instruction to set the flags to a known value before testing each instruction twice:
LI R2,>A000 AB R2,R2 ; set status LGT AGT C OV P and CLR R2 AB R2,R2 ; set status EQ
After each instruction, the status flags are compared to the expected flags. By using two sets of flags, we can determine if the instruction only modifies the flags that are intended.
Hopefully, once you get the parity check added to the byte-variant instructions, most tests should start passing.
- 4
-
47 minutes ago, wavemotion said:
To save me some reading... what is the right order? I guess it's the order I'm not doing it...
This is the right order: https://forums.atariage.com/topic/162941-assembly-on-the-994a/?do=findComment&comment=5415033
- 2
-
Here's my torture test, updated yesterday to catch the post-increment cases recently discussed in the assembly thread:
- 7
-
Nice work on patch 1.29. Binary size is much improved over previous patches!
Patch 1.18: 8048 bytes
Patch 1.29: 7860 bytes (188 less)
I'm using CFLAGS+= -O1 -fno-function-cse
When I tried -O2, I get the same ICE that Tursi reported.
- 5
-
That FORTH cover illustration is STACKED!
-
TI99/4A Discord user Distortions is working on a power supply board in the Hardware channel, and found this switch fits perfectly: https://www.lcsc.com/product-detail/Slide-Switches_G-Switch-SS-22G88-G090_C2848925.html
- 5
-
On 1/23/2024 at 2:51 PM, retrodroid said:
However, I may be able to source some of the desired sounds from existing non-TI hardware, in which case option 1 might make things easier.
Does anyone have any comments or suggestions on how to proceed, given my (and my project's) limitations?
I can tell you what I did for my no-expansion bare-console projects:
For Bounce'n'Pounce, I made a dual sound list player, one dedicated to playing music on the first two tone generators, and the other to playing sound effects on the 3rd tone and noise generator. Each music or sound effect sound list is crafted to only play on the correct channel. The workspace RAM usage is slight: one byte counter and a word pointer for each sound list, so 6 bytes total. An additional feature for sound effect priority was to sort the sound effects in ROM in order of priority, and when a new sound effect is to be played, its address can be compared to the currently playing sound list address to determine if it can be played or not. Game thread here.
For Tilda, I made my own advanced music and sound effect player. For this I wanted the music to be played using all four generators, but also allow sound effects to play on any generator and allow music to resume after the sound effect ends. Also, the music turned out to be quite large so I also needed a method of compression so that it will fit in a single ROM bank. The memory usage for this scheme was 4 words for music, and 4 words for sound effect, so 16 bytes total workspace usage, plus a little extra in the VDP memory for pattern-return-addresses. Each word contains a 3-bit counter, and 13-bit address (the player code and sound+music data reside in the same ROM bank so this is sufficient.) The compression works by making codes for volume changes a single byte and volume+note 2 bytes. Also if the music contains repeated patterns, these can be split out into a subroutine-like gosub and return. If the music needs to loop, it can use the gosub without the return. The notes and sub-pattern addresses are stored in a 256-entry table. More info here. I haven't released any of the tools for this, but I could maybe polish them up if it sounds useful.
- 2
- 1
-
22 minutes ago, retrodroid said:
This is somewhat insightful, though most of the opcodes seem to use similar amounts of cycles in the end. One interesting thing I've learned just now is that SLA/SRA is apparently extremely expensive in terms of cycle-counts. I've been using these all over the place in lieu of using MPY and esp. DIV. For example, I often do a before/after comparison of a value if I need to know if it's divisible by some factor of 2 using code like this:
MOV R0, R1 ; Copy original value SRA R0, 3 ; Div by 8 SLA R0, 3 ; Mpy by 8 C R0, R1 JEQ NOREM ; R0 is divisible evenly by 8, with no remainder
vs
LI R2, 8 DIV R2, R0 ; Div by 8 JNO NOREM ; No remainder
...but it seems It would be waaay more efficient to use the second version instead.
And even more efficient, if you are sticking to powers of 2, is to use a bitmask to test (with the bitmask equal to 1 less than the power-of-2 value you are testing) like this:
MOV R0, R1 ; Copy original value ANDI R1,7 ; Mask bits to check modulo 8 JEQ NOREM ; R0 is divisible evenly by 8, with no remainder
Using the ANDI (and bits immediate) will set the equal flag if the result of the AND operation was zero, which it will be for multiples of that number. For visualization, the binary powers of two are:
decimal hex binary binary mask hex mask 2 0002 0000000000000010 0000000000000001 0001 4 0004 0000000000000100 0000000000000011 0003 8 0008 0000000000001000 0000000000000111 0007 16 0010 0000000000010000 0000000000001111 000F 32 0020 0000000000100000 0000000000011111 001F 64 0040 0000000001000000 0000000000111111 003F 128 0080 0000000010000000 0000000001111111 007F 256 0100 0000000100000000 0000000011111111 00FF 512 0200 0000001000000000 0000000111111111 01FF 1024 0400 0000010000000000 0000001111111111 03FF 2048 0800 0000100000000000 0000011111111111 07FF 4096 1000 0001000000000000 0000111111111111 0FFF 8192 2000 0010000000000000 0001111111111111 1FFF 16384 4000 0100000000000000 0011111111111111 3FFF 32768 8000 1000000000000000 0111111111111111 7FFF
- 2
- 1
-
1 hour ago, TheBF said:
You might have a typo there (+254 -256)
9900 native jump instructions are limited to so +127 .. -128.
Or is there even more magic inside GCC?
+254 -256 bytes is +127 -128 words
- 2
-
This is great! The feel is very authentic.
- 1
-
Regarding the size of the generated code, here are some instruction comparisons I made from my C program compiled with GCC patch 1.19 (on the left) versus 1.27 (on the right.)
-
12 hours ago, khanivore said:
You need to tweak the FIXED_REGISTERS define in tms9900.h as well. It's a bit fussy about how you define the registers. Probably easiest if I just go back to using r10 as above
Actually, I think it relates to the CALL_USED_REGISTERS define. With the current patch, only R14 doesn't produce the warning. With the old 1.18 patch, R9, R13-15 don't produce the warning. If you do go back to SP in R10, I would suggest this for CALL_USED_REGISTERS:
#define CALL_USED_REGISTERS \ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0} /* SC 1 2 3 4 5 6 7 8 9 SP LR CB LW LP LS*/
That would allow me to use R14 and R15 for my global register variables.
EDIT: Nevermind the above, please go ahead and let GCC use all of the registers. I discovered the -ffixed-REG option to gcc that allows you to update the fixed_regs table to avoid the warning. So for global register variables in "r14" and "r15", I would add "-ffixed-r14 -ffixed-r15" to my CFLAGS.
- 5
-
13 hours ago, Tursi said:
But I don't know if anyone else has written code that assumes the register allocations. Anyone?
I did: Turmoil
The idea was to keep the address of the VDP address and write data port in registers R14 and R15:
// keep address and data addresses in global registers for fast access register volatile u8 *vdp_address_reg_addr asm("r14"); register volatile u8 *vdp_write_data_reg_addr asm("r15"); ... // initialize global register variables vdp_address_reg_addr = (u8*)0x8C02; vdp_write_data_reg_addr = (u8*)0x8C00;
It's easy enough to change the register numbers for the new gcc patch, but I'm now getting warnings like this:
main.c:130: warning: call-clobbered register used for global register variable
I'll dig into this more later.
- 2
-
Wow, Jason, that is a beast of an .ino file. That's a lot of useful code in there. Thanks for sharing!
- 5
Alex Kidd on Miracle Island - Playable Demo
in TI-99/4A Development
Posted
The background layer water effect looks really great. Are you using the GPU to adjust the background horizontal scroll on every scanline?