Tag Archives: old-computers

Micro Adlib player in Assembly

Plays RAW adlib songs in 100 lines of code … kindda

Using information from here:

And using fasm to compile I can play captured raw songs.

But something is still off ?!?

It sounds a little different, and I need to implement a better timer routine. (Below my version and opencubicplayer)

This is a test for my bootloader, playing music from my bootblock!


org 0x100


	; set speed (Byte 8,9 from the raw file)
	mov ax,[tune+8]
	mov [clockspeed],ax
	; call player
	call rawreg
	; wait 0.5 sec for exit
	mov bx,6
	call waitmore
	jmp exit

	mov bx,tune+0ah		; start of song at offset ah

; order registerdata, register!
; Are there more control codes? ???

	mov cx,[bx]
; reg = 2 - check data
	cmp ch,2
	je checkreg2
; reg = 0 - cyclewait
	cmp ch,0
	je cyclewait
; data = FFFF - end song - end play routine
	cmp cx,0ffffh
	jne skipr

cyclewait:		; waits cl times waitroutine
	call waitlong
	dec cl
	jnz cylloop
	inc bx
	inc bx
	jmp lraw

; check low opl
	cmp cl,1
	jne checkh
	mov ch,0
	mov [highlow],ch
	jmp incandret
; check high opl
	cmp cl,2
	jne check00
	mov ch,1
	mov [highlow],ch
	jmp incandret
; set new speed
	cmp cl,0
	jne incandret
	inc bx
	inc bx
	mov ax,[bx]
	mov [clockspeed],ax
; next double byte in the song please
	inc bx     
	inc bx     
	jmp lraw

; sends data to the control and data registers
	mov dx,ctrlreg
	mov al,[highlow]
	cmp al,0
	je regokay
	inc dx
	inc dx
	mov al,ch
	out dx,al
;	call waitshort ; not needed for newer adlib cards
	mov dx,datareg
	mov al,[highlow]
	cmp al,0
	je regokay2
	inc dx
	inc dx
	mov al,cl
	out dx,al
	call waitlong
	inc bx
	inc bx
	jmp lraw

	push ax
	push cx
	push dx
	mov cx, 0      ;HIGH WORD.
	mov dx, 010h ;LOW WORD.
	mov ah, 86h    ;WAIT.
	int 15h
	pop dx
	pop cx
	pop ax

	push bx
	push ax
	push cx
	push dx
	mov cx, 0      ;HIGH WORD.
	mov dx, [clockspeed]
	shr dx,1
	mov ah, 86h    ;WAIT.
	int 15h
	pop dx
	pop cx
	pop ax
	pop bx

; in bx == 12h is 1 sec
; destroys ax,bx,cx,dx
	push ax
	push bx
	push cx
	push dx
	mov ax,0h
	int 1ah
	add dx, bx
	mov bx,dx
	mov ax,0h
	int 1ah
	cmp bx,dx
	jnz waitloop
	pop dx
	pop cx
	pop bx
	pop ax

	mov dx,0388h
	mov al,0b0h
	out dx,al
	inc dx
	xor al,al
	out dx,al
	mov ax,04c00h
	int 21h

clockspeed: dw 0

highlow:	db 0


Rewrote 8086 bootblock trackloader

Loading a 320×200 image from 14 cilinders. There is no msdos on the floppy!

9 sectors, 14 cilinders, 1 head * sector size (512 bytes) = 64512 bytes

Mode 13h (320×200 265 colors)

Cuting the raw part from a BMP (see previous post)

root@battlestation:/mnt/# ls -la MAD.bmp
-rw-rw-r-- 1 fash fash 65078 Sep 14 15:57 MAD.bmp

I need 64000 bytes (320x200)
65078-64000 = 1078

root@battlestation:/mnt/# dd if=MAD.bmp of=mad.raw skip=1078 bs=1
64000+0 records in
64000+0 records out
64000 bytes (64 kB, 62 KiB) copied, 0.441618 s, 145 kB/s

I use debug to write to the sectors

debug mad.raw
-w100 0 9 7f
(write from address 100 drive=0 startsector=9 (cylinder 1) and 7f sectors long

Wrote a little sector viewer to debug/view data written.

  • r – read sector again
  • s – next sector (shift previous)
  • c – next cylinder (shift previous)
  • h – toggle head 0 – 1
  • p – load palette from current 2 sectors
  • l – clear screen
  • 1 – goto graphic mode
  • 2 – goto text mode and show sector,head and cylinder info
  • q – quit
  • -/+ tweak palette offset ( was needed for debugging

I will post the code after some code cleaning and adding some comments

Boot loader with image 320×200 256 colors.

This is a work in progress, below are my Lab notes.

I want to rewrite pieces we made for a demo, loading images and effects from a floppydisk bootloader.

Without looking at old code (which was written using Masm), I wanted to learn the steps using Fasm.

I started with a boot sector program, It should do the following.

  • Set graphic mode, and start a trackloader
  • Load sector 2 and 3 which contains the color palette for the image.
  • Next sectors, cylinders and heads contain the raw image

I got it working, half that is.
In the past I used real disks, and now a virtual disk, maybe thats the difference?

First Code

org 0x7c00

mov ah,0x0
mov al,0x13
int 10h

mov ax, 0a000h
mov es, ax
xor di, di
mov ax, 50
mov cx, 64000
rep stosb

	jmp loophere

times 510 - ($-$$) db 0

dw 0xaa55

Compiling and starting:

fasm mybootblock.asm
qemu-system-x86_64 --drive format=raw,file=mybootblock.bin

This works, it sets the graphical mode and clears the screen.

Second Code
Skipping the int 25h version

## Track read part
    xor ax, ax    ; DS = 0
    mov ds, ax
    mov ah, 2h    ; int13h function 2 track read
    mov al, 2     ; number of tracks ( should be 2 for reading only palette)
    mov ch, 0     ; from cylinder number 0
    mov cl, 2     ; the sector number 2 - second sector (starts from 1, not 0)
    mov dh, 0     ; head number 0
    xor bx, bx    ; BX = 0
    mov es, bx    ; ES = 0
    mov bx, 7e00h ; Offset from above
    int 13h

    call setpal

## End part with setpalette routine
## appending palette.colors
## and a raw image

    mov dx,3c8h
    xor al,al
    mov di, ax
    out dx,al
    inc dx
    mov cx,256*3
    mov si,07e00h
    rep outsb
times 510 - ($-$$) db 0

dw 0xaa55
include 'palette.colors'

times 2048 - ($-$$) db 0
file 'image.raw'

Seems there is still a header on the RAW file, lets look at how I made this.

NOTE! .. Below converts an image with a STANDARD VGA palette, not a custom one as used above

Looking with ghex at the file I saw that there was a header 0x415 bytes large.
(Probably still palette colors in there)

dd if=shoes.bmp of=cutshoe.bmp bs=1 skip=1078 (0x415h + 3?)
worked for me

Loading the extra tracks didn’t work for me?!?!
But how could I define tracks/sectors and heads on a virtual floppy?

I tried to write sectors using debug.com

start dosbox
imgmount a: /tmp/floppy.img -t floppy
debug.com bootsector.bin
-r bx 01 

-r cx 512
; set bx:cx for size
-w 100 0 0 1
; write from address 100, drive 0 (a), sector 0, number of sectors

; testing
-l 100 0 0 1
;load sector to addr 100 drive 0 sector 0 number of sectors 

This used to work with real disks on a real machine, not in dosbox ?!?!

my way to create a disk in linux

dd if=bootblock.bin of=disk1.img bs=512 count=1 seek=0
dd if=palette.col of=disk1.img bs=512 count=1 seek=1 # or 2?
dd if=shoes.raw of=disk1.img bs=512 count=10000 seek=17

It looks like I can’t read futher than 18 sectors on a virtual floppy.
What next? Head=1? Cylinder=1?
Below the info from a floppy image before altering.

DOS/MBR boot sector, code offset 0x3c+2, OEM-ID “MSDOS5.0”, root entries 224, sectors 2880 (volumes <=32 MB), sectors/FAT 9, sectors/track 18, serial number 0x1c2a0d0f, unlabeled, FAT (12 bit), followed by FAT

Appending the RAW to a executable gave me problems to.
(Without making a bootdisk)

Above and below weird data. Appending the data to the executable needs some work also.

At least for today let me display this image correctly πŸ™‚

org 0x100

; set mode 320x200 256 colors palette
	mov ah,0x0
	mov al,13h
	int 10h

; clear screen routine, not really needed
	push ax
	mov ax, 0a000h
	mov es, ax
	pop ax
	xor di, di
	inc ax
	mov cx, 64000 ; 320x200
	rep stosb

; call file loader 
	call Loadfile

; after displaying the image or displaying an error, wait for keypress to exit
	INT 16h
	JZ waitforkeyloop
	INT 16h
	MOV AX,3	; default text mode 3
	INT 10h
	MOV AX,4C00h	; exit to dos (terminate process)
	INT 21h

	MOV DX,filename
	MOV AX,3D00h	; open filehandle
	INT 21h
	JC Err1
	MOV BX,AX   	; filehandle
	MOV CX,0FFFFh 	; size
	mov dx,0a000h 	; destination 0000:a000h - Screen memory
	mov ds,dx

	MOV AH,3Fh	; read from file
	INT 21h
	JC  Err1
	MOV AH,3Eh	; close filehandle
	INT 21h

; print error
	push cs		; make ds same as cs
	pop ds
	MOV DX,TxtErr1	; error
	MOV AH,09h
	INT 21h

filename DB "shoes.bmp",0
TxtErr1 DB "shoes.bmp not found!",7,10,13,"$"

Tomorrow .. back to the track loader

Mikrotik Wifi, 80386 and Lilygo streaming

Quiet days, I working on some art.

But here are the last ‘prutsen’

My current Wifi setup

I’ve got a Wifi outside of my network for guest and emergency. ( 2 SSIDs)

Then a main Wifi router in my livingroom, one in my workshop/studio and one in the Attic (Electronics Lab)

So three main Wifi AccessPoints. These all have the same SSID’s but on different frequencies. That way i’ve got roaming in and outside my house.
Also some virtual accesspoints are configured.
I’ve got a main, folkband, IOT, guest-inside all on 2.4Ghz and 5Ghz.

I watched a lot of YT presentations about Mikrotik Wifi.

So I ended up with DFS safe channels 20Mhz for 2.4 and 20/40Mhz Ce for 5Ghz. (subchannels for each after some frequency scanning)
(2.4 does a failback to 20Mhz whenever there is even one client detected which connects only on this band. Such as some old IOT stuff)
2.4 in only 1,6 and 11 no overlap, each on another device.
300Mbps is sufficient for my wifi πŸ™‚

I’ve got accesslists in place and i’m going to read into kicking a client when the signal strenght is below -50dB

80386 (DX) Computer

Besides my 8088 and 8086 machines I needed a machine which could run our old demo’s. So I bought a new toy.

It has 8Mb Ram and runs at 40Mhz.

I’ve noticed that many of my VGA register manipulation code, can’t be run on a modern VGA monitor, I need to use a CRT for that .. Another thing to buy

Lilygo T-Display S3 Streaming

Not my code: https://github.com/Steve5451/esp32-stream-desktop
A very cool project!

Needed to fix arduino code, due to the TFT_eSPI library issues.
And I’ve got a S3 with another resolution, but that was an easy fix.
Then needed to reinstall nodejs with another version.
Had to modify the code because the tcp server would not start.
Weird errors logging, but in the end fixed … very cool

I probably end up designing a 3D printed case that looks like a monitor or tv.

My dosbox assembly directory

Below you can find the files in a zip for writing assemby machine code in dosbox.

I’ve got mine extracted in ~/projects/dos

To automount this i’ve edited

;-------- bottom part
# Lines in this section will be run at startup.
# You can put your MOUNT lines here.

mount c: /home/myusername/projects/dos

The files

  • A.BAT – Runs editor, masm,linker (start with a<space>progname
  • DEBUG.COM – msdos debugger
  • EXE2BIN.EXE – exe to com (if segments allow)
  • GFX.ASM – example template (see below)
  • LINK.EXE – masm linker
  • MASM.EXE – masm compiler
  • Q* – editor stuff
  • Q.EXE – editor
  • SR.EXE – sourcer
  • TASM.EXE – turbo assembler
  • TD.EXE – turbo debugger
  • TLINK.EXE – turbo linker


; everything in 64k CS, DS, and SS are the same
.model small
; start pointer
.stack 100h
	; set mode 13 (320x200 * 265 colors palette)
    mov ah,0	
    mov al,13h
    int 10h

    ; set pixel in the middle color 2 (cyan)
    mov ah,0ch
    mov al,2
    mov cx,160
    mov dx,100
    int 10h

	; wait key input
    mov ah,0
    int 16h

	; set mode back to text
    mov ah,0
    mov al,3
    int 10h

	; exit to dos
    mov ax,4c00h
    int 21h
end start


start dosbox
a gfx (edit gfx.asm example)
esc, q, e
gfx (run program)


Perviously i’ve posted about PCem

But I wanted to have a emulator which could load extension biosses also.
This for my own tinkering.

I was told to look at MartyPC and PCE/ibmpc

I donΒ΄t like it being written in Rust, but it does the job.

Running the Basic Extension Rom
Running one of my own roms. I knew it didn’t work, now i can use the buildin debug to see why!
Another of my test roms, which is working!

ROM config part i’ve got in martypc.toml

rom_override = [
    { path = "./roms/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", address = 0xF0000, offset=0, org="Normal" },
    { path = "./roms/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", address = 0xF8000, offset=0, org="Normal" },
    { path = "./roms/myromextension.bin", address = 0xF6000, offset=0, org="Normal" }

GLABios for Laser XT/3

In previous post :

I mentioned a 2 ROM setup because the 8086 is 16bits instead of 8.
So I was wondering that maybe a recompile was needed, or the data being split over two roms (odd/even)

The guy from GLABios was so kind to build me two interleaved roms.

So while working on a padded bench, I tested the ROMs.

Working outside .. on the padded bench

Back to the roms, it didn’t work!

But I missed a detail in the technical manual (the bold text)

In Turbo XT /2 and Turbo XT /3, there are two 28-pin sockets for ROM,
both of them are occupied by 2764 which stored the BIOS. The contents
of the two 2764 are identical.
One of them contribute the ODD Byte to the system and the other EVEN Byte. Together they support 16 Bit BIOS

I don’t know why this is how it works, but when I flashed two the same 28C64’s it worked!
(I also tought that is was strange that both original roms had the same markings.

It workes!

Only remarks/observations:

  • There was a longer wait time before the CF Card was detected/accessed
  • GLABios mentions 8088 in the splashscreen, but the machine is a 8086


GLABios was not updated for displaying 8086 yet.
Error 1701 was the (old spinning) harddisk not being connected.

Nice .. harddisk infomation like size, rom address and CHS

8086 sideway scroller ‘n stuff

Today I was working on my own brew ISA card (wirewrapping).
Did some mini modeling stuff.
Sorted some pipetunes.
And played around with my 8086.

Got it on a desk now, and replaced the harddisk with the CF card.
Also got an old SoundBlaster working, so i wanted to see what of my old code could still run.
Apparanty most code was compiled for 386/486 πŸ™
So i recompiled some stuff.
Below a horizontal scroller example.

Meanwhile i got my new fans in for my NUC (Kodi player, it was making a hell of a noise due to bad ball bearings.


Adding a picture:
Most used is loading a koala picture.
Never done it like this before, luckily loads of retro lovers are posting code examples.
There are a lot of tools now available on PC. (Windows and Linux)

Acme : compiler i’ve used for this example
Retropixels : converting jpg into koala
Exomizer : packing/compressing the C64 prg (16k to 5.4k)
Sidreloc : relocator for SID files.

Exomizer command with effect:
(NOTE on linux you have to use single qoutes!)

retropixels -r 64 --format prg bottom.jpg ; for a prg (not used)
retropixels bottom.jpg ; for a koala picture

exomizer sfx 0x080d bottom.prg -x 'lda $fb eor #$01 sta $fb beq skip dec $d020 inc $d020 skip:'
# 0x080d is the starting address


!to "bottomsm.prg",cbm
; start prg
* = $0801
; header for sys auto start
!byte $0b, $08, $00, $00, $9e, $32, $30, $36, $31, $00, $00, $00

PICTURE = $2000

* = $080d

	lda #<irq
	ldx #>irq
	sta $314
	stx $315
	lda #$1b
	ldx #$00
	ldy #$7f 
	sta $d011
	stx $d012
	sty $dc0d
	lda #$01
	sta $d01a
	sta $d019 ; ACK any raster IRQs
	lda #$00
	jsr $1000 ; Call music

	lda #$00
	sta $d020 ; Border Color
	sta $d021 ; Screen Color

	; Transfer Video and Color
	ldx #$00
	; Transfers video data
	lda VIDEO,x
	sta $0400,x
	lda VIDEO+$100,x
	sta $0500,x
	lda VIDEO+$200,x
	sta $0600,x
	lda VIDEO+$2e8,x
	sta $06e8,x
	; Transfers color data
	lda COLOR,x
	sta $d800,x
	lda COLOR+$100,x
	sta $d900,x
	lda COLOR+$200,x
	sta $da00,x
	lda COLOR+$2e8,x
	sta $dae8,x
	bne .LOOP

	; Bitmap Mode On
	lda #$3b
	sta $d011

	; MultiColor On
	lda #$d8
	sta $d016
	; When bitmap adress is $2000 ; Screen at $0400 ; Value of $d018 is $18
	lda #$18
	sta $d018
	jmp .MYLOOP

	lda #$01
	sta $d019 ; ACK any raster IRQs
	jsr $1003 ;Play the music
	jmp $ea31
; Data parts with headers cut
	* = $1000
	!binary "bottom1000.sid" ,, $7c+2

	!binary "bottom.kla",,2

Laser XT/3 Bios

As posted before

I really like GlaBios for my 8088, so today I got my Laser XT/3 8086 machine from the attic.

Mmm TWO ROM’s thats interesting

Looking futher in the schematics I found this. Apparantly there is a 8K ROM configured in a D0-D7 + D8-D15 setup. (16 bits)

Found a technical manual, this is a excerpt.

In Turbo XT, there are two 28-pin sockets for ROM, one of them is
occupied by a 2764 which stored the BIOS (Basic Input Output System).
The other empty socket is used to house a 32K ROM, such as the BASIC

And about the XT/3 version which I have.

In Turbo XT /2 and Turbo XT /3, there are two 28-pin sockets for ROM,
both of them are occupied by 2764 which stored the BIOS. The contents
of the two 2764 are identical. One of them contribute the ODD Byte to the system and the other EVEN Byte. Together they support 16 Bit BIOS

This could be an interesting chat with Greg ..

Meanwhile i’m going to look how to split a rom into odd/even.
Maybe i have to write a little python program for this.

Well, thats enough for today.

Lets fix my Cat S60 Flir phone, so i can track the hedgehog in our garden. (Battery replacement and powerbutton fix)

I fixed several phones before, (broken screen. touch not working). But I hate how some manufacturers build them.