Jump to content

TheMole

Members
  • Content Count

    855
  • Joined

  • Last visited

Posts posted by TheMole


  1. TI Scramble is not loading data from disk but it's unpacking data and uploading to vdp.

     

    Yeah, sorry, I know it's not exactly as in Scramble, I was just referring to the little 'hick-up' you see in Scramble when loading levels (which I think in Scramble is perfectly fine, but I'm not sure it would work for Alex Kidd, especially given the fact that it will need to load longer since it's loading from disk).


  2. Thanks for asking! Unfortunately I haven't had the time to spend anything more than half an hour here or there on coding projects, and I'm at a bit of a difficult point with Alex Kidd where I'm running up against memory (and speed) limitations that require a more concentrated effort. I have been thinking about possible ways forward though, so when I do find some time, I have a bunch of things to try.

     

    One of the avenues I'm considering is making the game cartridge-based while still requiring the 32k memory expansion and disk system, with part of the code running off the cartridge and part running from the memory expansion. That should give me the additional 8k of memory that I need but would require a physical cart release for anyone to be able to play it on real iron (or a supercart, I guess). Another alternative is to simply do some mid-level loading of data from disk (kinda like in TI Scramble), but Alex Kidd doesn't have forced scrolling, so I don't know how well that would work.


  3.  

    I only got around to viewing this on the hardware today, and it looks great, but why does it take up 10k VDP RAM when it's not bigger than that? A full screen bitmap takes 12k according to my calculations.

     

    Do you have any palette colors left for displaying anything around the fire?

     

    You're right, I miscalculated, It needs roughly 5k. The BML is initialized at 80x80 pixels, but I should've used 40x80 for my calculations since I'm using fat pixels. So, the effect requires an offscreen buffer of 40x80 bytes (not nibbles), so 3200 bytes. And the BML layer itself needs half of that (nibbles instead of bytes), so another 1600 bytes adding up to 4800 bytes. The program itself is around 300 bytes, so we need 5100 bytes in total for the fire effect and not 9900 like I originally calculated using an 80x80 buffer.

     

    So yes, it should be possible to fit in a bitmap image.

    Plenty of colors still available, since I'm only using one of 4 available 16-color palettes. Just need to assign a different palette to the BML.

     

    Do you have the original for the picture somewhere?


  4. Yes, the two RNGs were removed to make room for more desirable features. I can provide a C function that performs the same algorithm if you want? As for the PIX instruction, it won't work with the new fat-pixel enhancement (as you discovered.) PIX is too hard wired for the BML pixel format and would have required too much ripping up to add the fat-pixel support. However, you should be able to write one fat-pixel using two PIX instructions, incrementing the X coordinate between each instruction. That might be faster than a read-mask-write for each nibble of the fat-pixel feature.

     

    Very nice fire effect!

     

    No worries, I just plugged in a C function that I'd used somewhere else before. Is it correct that the timers you added in favor of the RNG are not available to the GPU?


  5.  

    Damn, that's awesome! :thumbsup: :thumbsup: :thumbsup: :thumbsup: :thumbsup:

     

    I'm curious, would it be possible to take a photo of a brick fireplace, convert it into TI format with Tursi's program and integrate your program to display with the static photo? That would probably be the best screen saver ever made for the TI.

     

    I'd love to collect a whole series of screen savers for the TI, each one different showing off the power of the F18A.

     

    Thanks :). It should be possible to put some graphics around the fire, but not something that was output by Tursi's convert9918a (the fire effect runs completely in VRAM, and requires almost 10k of memory; a bitmap image requires 12k, so you can't have both at the same time in the F18A's 18k). Something photorealistic is probably out of the question, but character mode graphics should be doable though, perhaps even in ECM3 mode... if you want to design something in Magellan, I'd be happy to include it for you.

    • Like 1

  6. Where in the original source can I see the assembly code for the GPU routines?

     

    You can't, it's all C code that gets compiled by GCC. The GPU routines are in gpucode.c, get compiled to binary format (to gpucode.o, which gets transformed to gpucode.bin) and then turned into a header file via bin2h to end up as an array of bytes in gpucode.h. This header gets included in main.c and uploaded to VRAM (starting at memory locations 0x1900) by the host program.

     

    If you want to see the assembled code, the simplest thing you can do is use js99er's debugger to look at VRAM from 0x1900 and onwards (roughly 300 bytes, I think). As I said, both versions upload the code to 0x1900 in VRAM, but in the broken version the entrypoint of the 'main' function is at 0x1948 (so GPU execution starts there instead of at 0x1900), with the first 0x48 bytes occupied by code that gets jumped to later (functions in C). The working version just starts at 0x1900, since there the functions are inlined.

    • Like 1

  7. Yeah, it's not going to run on Classic99, that's normal. But indeed, I just tested on my real hardware and it crashes there as well. The strange thing is that it runs fine in js99er.net and it is damn hard to debug on RI :?

     

    *edit* The version attached to this post does run on the real deal (and it runs quite a bit faster, making the effect more convincing). I only inlined some functions in the GPU program, which probably means that my tools to compile C code for the GPU don't always work when using regular function calls. (I left the original up as well, if Rasmus wants to verify why js99er gave different results to the real HW)

     

    Video proof:

    https://www.youtube.com/watch?v=RY_8i_ouXc8

     

    fire.dsk

    • Like 6

  8.  

    I don't think the fat pixel BML works with PIX, you have to write directly to VDP memory.

     

    Ok, cool, thanks.

     

    Well, inspired by sometimes99er's fire demo, I did one for the f18a. The cool thing about the f18a is that it makes all those old DOS effects new again, so I dug out an old fire demo I did and ported it to the F18A. The result is attached, and here's a video for the f18a impaired (or lazy people):

     

    https://www.youtube.com/watch?v=k2Qg-QqnJVM

     

    This isn't optimized, and there is some "black snow" because I'm not double buffering, but I think it looks nice enough... Not tested on real iron yet, and NOT reset button safe :P

    fire-src.tar.gz

    fire.dsk

    • Like 9

  9. Sorry for spamming the thread with all my questions, but is the 16-color fat pixel BML mode documented somewhere? My assumption is that the destination operand's lower nibble will define the color of a fat pixel, and that e.g. the following command would plot a pixel with color 14 at location (32,32) in the BML:

    LI    r0,>2020
    LI    r1,>000e
    PIX   r0,r1
    

    That's not what I'm seeing however, but I might be doing something wrong...


  10. Great news, thanks!

     

    Regarding libgcc: I just tried rebuilding the entire thing from scratch, and libgcc did build as expected this time. I must have been playing around with a dirty build before. My apologies for sending you on a wild goose chase...

     

    Regarding new features, it would be great if the compiler could 'natively' support paged/banked memory configurations (like an AMS or 512k cart type setup). Not sure if this is a compiler feature though, it might be something that is best achieved with a separate set of tools?


  11. Turn out, I also have the latest version of the compiler on my laptop, and hotels are boring at night :).

     

    Anyway, this is the minimum code needed to trigger the error:

    /*************************/
    /* TI-99/4A Ray caster   */
    /* 2013 - Danny Lousberg */
    /*************************/
    
    // Includes
    #include "lookup.h"					// Needed to calculate movement
    
    // Defines
    #define		MAX_INT 			32767
    #define 	MAP_WIDTH 			24
    #define 	MAP_HEIGHT 			24
    #define 	CELL_SIZE 			32		// Size of each wall "cube" on the map: width, depth and height
    #define		SCREEN_WIDTH		64		// Number of rays to cast, or number of columns, or slices
    #define		SCREEN_HEIGHT		64		// Height of the rendering surface, in pseudo-pixels; not including bottom area
    #define		FOV					64		// Field Of View, aka how wide the arc of rays needs to be
    #define 	SCREEN_DISTANCE 	3200	// Distance to screen projection plane
    										// Formula for this is (SCREEN_WIDTH / 2) / tan(FOV / 2)
    #define		ANGLE_STEP			1		// Should be FOV / SCREEN_WIDTH, so FOV needs 
    										// to be a multiple of SCREEN_WIDTH, effectively 
    										// giving a max resolution of 64 for 
    										// realistic looking rendering
    #define     SLICEPARAMBUFFER	0x2000	// Where in VRAM do we put our slice parameters? 4 bytes in a row at 0x2000 (8k)
    #define		ABS(a)				(((a) < 0) ? -(a) : (a))
    
    // World map
    char worldmap[MAP_WIDTH][MAP_HEIGHT] =
    {
    	{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
    	{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
    	{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
    	{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
    	{1,2,2,0,2,2,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
    	{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
    	{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1},
    	{1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
    	{1,0,0,0,0,1,2,2,0,2,2,1,0,0,0,3,0,3,0,3,0,0,0,1},
    	{1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1},
    	{1,1,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1},
    	{1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1},
    	{1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,2,2,2,2,2,2,2,2,2},
    	{1,0,0,0,0,1,0,0,0,0,0,1,2,2,2,2,0,0,0,0,0,0,0,2},
    	{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
    	{1,0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,0,0,0,0,0,0,0,2},
    	{1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,2,0,0,0,0,0,0,0,2},
    	{1,2,2,2,0,0,0,0,2,0,0,0,0,0,0,2,2,2,2,0,2,2,2,2},
    	{1,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1},
    	{1,2,0,2,0,0,0,0,2,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1},
    	{1,2,0,2,2,2,2,2,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1},
    	{1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
    	{1,2,2,2,2,2,2,2,2,0,0,0,0,0,0,1,0,0,1,1,1,0,0,1},
    	{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
    };
    
    //*********************
    // VDP access ports
    //*********************
    // Write Address/Register
    #define VDPWA	*((volatile unsigned char*)0x8C02)
    // Write Data
    #define VDPWD	*((volatile unsigned char*)0x8C00)
    
    //*********************
    // Inline VDP helpers
    //*********************
    
    // Set VDP address for write (adds 0x4000 bit)
    inline void VDP_SET_ADDRESS_WRITE(unsigned int x)					{	VDPWA=((x)&0xff); VDPWA=(((x)>>|0x40);	}
    
    // Set VDP write-only register 'r' to value 'v'
    inline void VDP_SET_REGISTER(unsigned char r, unsigned char v)		{	VDPWA=(v); VDPWA=(0x80|(r));				}
    
    void draw_slice(unsigned char column, int slicestart, int sliceend, unsigned char color)
    {
    	// Write parameters to VRAM
    	VDP_SET_ADDRESS_WRITE(SLICEPARAMBUFFER);
    	VDPWD = (unsigned char)column;
    	VDPWD = (unsigned char)slicestart;
    	VDPWD = (unsigned char)sliceend;
    	VDPWD = (unsigned char)color;
    
    	// Kick of slice rendering program
    	VDP_SET_REGISTER(54, 0x20);
    	VDP_SET_REGISTER(55, 0x04);
    }
    
    // The actual ray casting algorithm, called once per frame
    // Basically, we iterate over each screen column and calculate the angle of view
    // that is associated with that column. Then we "cast a ray" from the player's position
    // along that angle until we hit a wall in our map.
    // We use the distance to that wall to calculate the height of the slice to be 
    // rendered for the current column (the further away, the smaller the slice)
    void cast_rays(int playerx, int playery, int playerangle)
    {
    	int	column;								// column iterator, range: 0-SCREEN_WIDTH
    	int rayangle;	
    	unsigned int hordist, verdist;			// distance to the closest wall in horizontal _and_ vertical direction
    	int mapx, mapy;							// temp values for checking a hit on the map, will be copied into hitx,hit
    	int hitx, hity;							// coords in map space of the _closest_ hit (either vert or hort)
    	unsigned int distance;					// distance of the _closest_ hit (either vert or hort)
    	int xstep, ystep;						// How many units to step from one wall-boundary to the next
    	int checkx, checky;						// coords of the first intersection, before we start "stepping"
    	int side = 0;
    
    	// First ray, left-most column starts at half the FOV counterclockwise from the player's angle
    	rayangle = playerangle - FOV / 2;
    	hitx = hity = 0;
    
        for(column = 0; column < SCREEN_WIDTH; column++)
        {
    		// Normalize angle to 0-359 range
    		if (rayangle < 0)
    			rayangle += 360;
    		if (rayangle >= 360)
    			rayangle -= 360;
    
    		// Initialize distance, will be used in comparison later on
    		// and there is a code path that could leave this undefined
    		distance = MAX_INT;
    
    
    		// Check for horizontal intersections
    		if ((rayangle != 0) && (rayangle != 180))
    		{
    			int hit;						// Boolean to stop checking for walls
    	    
    			// initialize to longest distance as we will be picking the shortest distance
    			// to a hit between the two axis
    			hordist = MAX_INT;
    
    			// Calculate first intersection point on next cell along ray
    			// First we calculate the Y coord (easiest)
    			if (rayangle > 180)
    			{
    				// ray is facing up in the map; so we put the checkpoint RIGHT ABOVE (hence the - 1)
    				// the boundary of the cell we are in on the Y-axis
    				checky = ((playery / CELL_SIZE) * CELL_SIZE) - 1;
    				xstep = -STEPX[rayangle]; // = (256 * -CELL_SIZE) / TAN255[rayangle];
    				ystep = -CELL_SIZE;
    			}
    			else
    			{
    				// ray is facing down in the map; so we put the checkpoint right AT
    				// the boundary of the cell BELOW the one we are in on the Y-axis
    				checky = ((playery / CELL_SIZE) * CELL_SIZE) + CELL_SIZE;
    				xstep = STEPX[rayangle]; // = (256 * CELL_SIZE) / TAN255[rayangle];
    				ystep = CELL_SIZE;
    			}
    			checkx = playerx - ( (256 * (playery - checky)) / TAN255[rayangle] );
    
    			hit = 0;
    			mapx = checkx / CELL_SIZE;
    			mapy = checky / CELL_SIZE;
    			while (!hit)
    			{
    				// Ray has left the map; need to break out of the loop
    				if ( (mapx < 0) || (mapy < 0) || (mapx >= MAP_WIDTH) || (mapy >= MAP_HEIGHT) )
    				{
    					hordist = MAX_INT;
    					break;
    				}
    			
    				// if we hit a non-zero field in the map, we're on the edge of a wall
    				if (worldmap[mapx][mapy])
    				{
    					hit = 1;
    					hordist = 1;
    				}
    				else
    				{
    					// No wall? Then we take steps to the next boundary and
    					// reset the map coords to be checked
    					checkx += xstep;
    					checky += ystep;
    					mapx = checkx / CELL_SIZE;
    					mapy = checky / CELL_SIZE;
    				}
    			}
    			
    			// Only checked horizontal hits yet, so these are by definition our best guess for
    			// the closest hit. We'll check these values against the vertical results later on
    			// so we store in the variables for the final result for now...
    			hitx = mapx;
    			hity = mapy;
    			distance = hordist;
    		}
    		else
    		{
    			// Angles 0 and 180 have a cos of zero
    			// or in other words, we will never see a horizontal intersection
    			hordist = MAX_INT;
    		}
    
    		// Check for vertical intersections
    		if ((rayangle != 90) && (rayangle != 270))
    		{
    			int hit;						// Boolean to stop checking for walls
    	    
    			// initialize to longest distance as we will be picking the shortest distance
    			// to a hit between the two axis
    			verdist = MAX_INT;
    
    			// Calculate first intersection point on next cell along ray
    			// First we calculate the X coord (easiest)
    			if ( (rayangle < 270) && (rayangle >= 90) )
    			{
    				// Going left, check against left boundary of current cell
    				checkx = ((playerx / CELL_SIZE) * CELL_SIZE) - 1;
    				ystep = -STEPY[rayangle]; // = (-CELL_SIZE * TAN255[rayangle]) / 256;
    				xstep = -CELL_SIZE;
    			}
    			else
    			{
    				// facing right, check against LEFT boundary of NEXT cell
    				checkx = ((playerx / CELL_SIZE) * CELL_SIZE) + CELL_SIZE;
    				ystep = STEPY[rayangle]; // = (CELL_SIZE * TAN255[rayangle]) / 256;
    				xstep = CELL_SIZE;
    			}
    			// The below should simply be "checky = playery - ( ((playerx - checkx) * TAN255[rayangle]) >> 8 );"
    			// But this result overflows when angles approach 90 or 270, likelyhood increase the bigger 
    			// the distance between test point and player gets
    			// So, for high result values of TAN255, we just pre-scale the numbers before the multiplication
    			// For the lower numbers, we don't do prescale since we'de lose too much precision
    			if ( ABS(TAN255[rayangle]) > 1000 )
    				checky = playery - ( ((playerx - checkx) * (TAN255[rayangle] >> 4)) >> 4 );
    			else
    				checky = playery - ( ((playerx - checkx) * TAN255[rayangle]) >> 8 );
    
    			hit = 0;
    			mapx = checkx / CELL_SIZE;
    			mapy = checky / CELL_SIZE;
    			while (!hit)
    			{
    				// Ray has left the map; need to break out of the loop
    				if ( (mapx < 0) || (mapy <0) || (mapx >= MAP_WIDTH) || (mapy >= MAP_HEIGHT) )
    				{
    					verdist = MAX_INT;
    					break;
    				} 
    
    				// if we hit a non-zero field in the map, we're on the edge of a wall
    				if (worldmap[mapx][mapy])
    				{
    					hit = 1;
    					verdist = 1;
    				}
    				else
    				{
    					// No wall? Then we take steps to the next boundary and
    					// reset the map coords to be checked
    					checkx += xstep;
    					checky += ystep;
    					mapx = checkx / CELL_SIZE;
    					mapy = checky / CELL_SIZE;
    				}
    			}
    		}
    		else
    		{
    			// cos of 90 and 270 is zero, so there is never an intersection with a vertical wall
    			verdist = MAX_INT;
    		}
      	
    		// See which of our hits we should take into account
    		// Default was horizontal, but we take vertical if that distance is shorter
    		side = 0;
    		if (verdist <= hordist)
    		{
    			hitx = mapx;
    			hity = mapy;
    			distance = verdist;
    			side = 1;
    		}
    
    		// calculate slice height based on distance
    		int sliceheight, slicestart, sliceend;
    		if (distance) 
    			sliceheight = SCREEN_DISTANCE / distance;
    		else
    			sliceheight = SCREEN_HEIGHT;
    
    		slicestart = (SCREEN_HEIGHT - sliceheight) / 2;
    		sliceend = slicestart + sliceheight;
    
    		// Start of rendering this slice
    		// Color of wall slice
    		char color;
    		if (side != 1)
    		{
    			// Front view, light colors
    			switch(worldmap[hitx][hity])
    			{
    				case 1:  color = 15;  break;   // white
    				case 2:  color = 2;   break;   // green
    				case 3:  color = 5;   break;   // blue
    				default: color = 11;  break;   // yellow
    			}
    		}
    		else
    		{
    			// Side view, dark colors
    			switch(worldmap[hitx][hity])
    			{
    				case 1:  color = 14;  break;   // gray
    				case 2:  color = 12;  break;   // dark green
    				case 3:  color = 4;   break;   // dark blue
    				default: color = 10;  break;   // dark yellow
    			}
    		}
    
    		// draw the pixels of the stripe as a vertical line
    		draw_slice(column, slicestart, sliceend, color);
    				
    		// Prepare for next column
    		rayangle += ANGLE_STEP;
    	}
    }
    
    int main(int argc, char *argv[])
    {
    	while(1)
    	{
    	}
    
        return 0;
    }
    
    

    Note that this code doesn't perform anything useful anymore, and I took some of the calculations out, so the algorithm itself won't work either.

     

    Don't know how significant this is, but I found it strange that although the error during compilation is reported in line 278, commenting out line 312 will actually make it go away...

     

    Attached is a folder containing all that's needed to build this (and trigger the bug). Again, for others that would be tempted to download this: it does not contain a working program...

    wolfie-error.tar.gz


  12. I'm currently traveling for work, but I'll prepare a file for you ASAP, probably second half of the week. I'm more than happy to help debug this. Just let me know where to look, and what you want me to do.

     

    I think the reason libgcc won't build could be the same reason why my own code won't build. I'll dig up the exact error when I'm near my main computer later this week, but given libgcc implements a number of math functions it wouldn't surprise me the error is the same here.


  13. I know the difference between an emulator and MIST :) I just talk about the feeling in the use of both them, they are equal.

    I get why you would say that, but to me there's a world of difference between emulators and FPGA implementations. Different strokes for different folks, right... I'm not a purist by any means, but there's surely gradations for me:

     

    "Classic" Real Iron > Mixed setup with newer components (e.g. F18A, Lotharek, NanoPeb) > Full-on FPGA implementation ala MIST > Emulation

    • Like 1

  14. Thanks Insomnia. Actually, I get another error when trying your test:

    Dannys-MacBook-Pro:wolfie-f18a lousbergd$ echo "int test() { return 1; }" > test.c
    Dannys-MacBook-Pro:wolfie-f18a lousbergd$ /Users/lousbergd/tms9900/bin/tms9900-gcc -da test.c
    /Users/lousbergd/tms9900/bin/../lib/gcc/tms9900/4.4.0/../../../../tms9900/bin/ld: cannot find -lgcc
    Dannys-MacBook-Pro:wolfie-f18a lousbergd$ ls *_subreg
    test.c.171r.tms9900_subreg
    

    So, it does look like I'm using the latest version, but it seems that something else is going wrong.

     

    I'm not on my home PC now, so I can't give you the install script I modified, but it was extremely simple (basically a find and replace of "wget" with "curl -O"). I'll make a patch for my changes to toplev.c and toplev.h and include the application of that patch in the script if it detects it's running on a Mac.


  15.  

    Important information is 32k RAM expansion.

    I know the jumper settings are documented on the board but documenting there meaning would be great.

     

    BTW: Do you offer a schematic, too?

     

    ti99user

     

    Keep in mind that not all 512k carts will ship software that requires the 32k expansion, most (if not all) of the collections currently available do, but that's a function of the software installed on the carts, not the hardware itself.

    • Like 1

  16. Thanks for the update Insomnia!

     

    However, I'm not sure I'm using the last version. I used (and modified) the install script from the first post, the patch file says 1.11 (and 1.7 for binutils), but I get the same problems as with the last version:

    • Build of libgcc crashes (removed that from build script)
    • Errors during compilation when converting bytes-ints
    • Errors with certain divisions.

    I'm wondering if there's a way to verify the patch level from a compiled binary? It's not part of the version number, which just reports 4.4.0 :).

     

    These are the error messages I get:

    wolfie3.c: In function ‘cast_rays’:
    wolfie3.c:403: internal compiler error: in subreg_highpart_offset, at emit-rtl.c:1304
     

    for this code (SCREEN_DISTANCE is a '#define 3200', distance is an unsigned int)

    // calculate slice height based on distance
    int sliceheight, slicestart, sliceend;
    if (distance) 
    	sliceheight = SCREEN_DISTANCE / distance;
    else
    	sliceheight = SCREEN_HEIGHT;
    
    

    And:

    /Users/lousbergd/tms9900/bin/tms9900-ld crt0_ea5.o  utils.o tistdio.o wolfie3.o --section-start .text=0xa000 --section-start .data=0x2080 -M  -L./libti99 -lti99 -o wolf18a.ea5.elf > ea5.map
    wolfie3.o: In function `L55':
    (.text+0x1ce): undefined reference to `__divsi3'
    
    

    For the expression in this code:

    verdist = (int)( (long)(256 * ABS(checkx - playerx)) / (long)(ABS(COS255[rayangle])) );
    
    

    I think the __divsi3 stuff might be related to libgcc not being built, and the first error is probably a type conversion error, but if I understand it correctly both of these should be fixed, right?

     

    Not related, but for people trying to compile this on a Mac - and as a reminder for myself next time I want to compile this: note that you need to do a couple of things to make everything compile correctly:

    1. Modify the install script by replacing every instance of 'wget' with 'curl -O', since there's no wget on OS X anymore
    2. You will need to modify toplev.c and toplev.h to fix a host compiler version check that fails with clang (the floor_log2 and exact_log2 functions will redefine an inline function, which isn't allowed in c99, but gcc will allow this). Just remove the inline version in toplev.h and the test around the implementation in toplev.c.
    3. (for now, I think...) remove libgcc from the targets in the gcc config line in install.sh

    Either way, a big thank you for all your efforts, I wouldn't be coding for the TI again if it wasn't for this!


  17. The SGCPU board is a great example of what would be possible if we did this again today. The problem with it for me is that it's a PEB-only solution, I would love a new motherboard for the console that has extra memory on board (SAMS compatible preferably) but still maintains all of the TI's interfaces (side port, cartridge slot, casette port, joysticks, ...). Just something than can be populated with existing components where possible, and modern replacements where original chips are becoming hard/impossible to find (e.g. GROM chips), or for those looking for upgraded functionality (e.g. F18A).

     

    In terms of nostalgia, I generally tend to think of things "that were possible" back in the day as meeting that criterion. I wouldn't care of we used a single-chip SRAM approach instead of 24 separate chips in a new version of the SAMS, and I don't mind the F18A using an FPGA since it really doesn't do anything that was technically impossible back in the 80's.


  18. I figured as much. I'm already counting on the ability to reduce the stride between bitplanes to make the sprite pattern table fit in 3k instead of the normal 6k. 64 patterns per player are enough to display the on-screen sprites, but I also need to find room to put a backbuffer somewhere in memory for the next animation frame while it's being uploaded from the host system. Unless there's a way to optimize VRAM usage that I haven't figured out yet, I think a streetfighter game would need to be restricted to one plane only.

    • Like 1
×
×
  • Create New...